mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04: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:
parent
2f1247e1c4
commit
f7f8c9c11f
File diff suppressed because it is too large
Load Diff
@ -28,42 +28,70 @@ extern "C" {
|
||||
|
||||
#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */
|
||||
|
||||
/**
|
||||
* @brief I2S port number, the max port number is (I2S_NUM_MAX -1).
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_NUM_0 = 0, /*!< I2S port 0 */
|
||||
#if SOC_I2S_NUM > 1
|
||||
I2S_NUM_1 = 1, /*!< I2S port 1 */
|
||||
#endif
|
||||
I2S_NUM_MAX, /*!< I2S port max */
|
||||
} i2s_port_t;
|
||||
|
||||
/**
|
||||
* @brief I2S pin number for i2s_set_pin
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int bck_io_num; /*!< BCK in out pin*/
|
||||
int ws_io_num; /*!< WS in out pin*/
|
||||
int data_out_num; /*!< DATA out pin*/
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
typedef i2s_hal_chan_cfg_t tdm_chan_cfg_t;
|
||||
typedef i2s_hal_tdm_flags_t tdm_flags_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S driver configuration parameters
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
// Compatible with previous versions. For ESP32-S3, ESP32-C3 and the later chip, you should use `param_cfg` fields to initialize I2S.
|
||||
struct {
|
||||
i2s_mode_t mode; /*!< I2S work mode*/
|
||||
uint32_t sample_rate; /*!< I2S sample rate*/
|
||||
uint32_t bits_per_sample; /*!< I2S bits per sample*/
|
||||
i2s_channel_fmt_t channel_format; /*!< I2S channel format */
|
||||
i2s_comm_format_t communication_format; /*!< I2S communication format */
|
||||
};
|
||||
i2s_config_param_t param_cfg; /*!< I2S config paramater */
|
||||
};
|
||||
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_mode_t mode; /*!< I2S work mode */
|
||||
uint32_t sample_rate; /*!< I2S sample rate */
|
||||
i2s_bits_per_sample_t bits_per_sample; /*!< I2S sample bits in one channel */
|
||||
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_bits_per_slot_t bits_per_slot; /*!< I2S total bits in one channel, Should not be smaller than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
tdm_chan_cfg_t tdm_chan_cfg; /*!< I2S TDM channel configurations*/
|
||||
tdm_flags_t tdm_flags; /*!< I2S TDM flags*/
|
||||
#endif
|
||||
} i2s_driver_config_t;
|
||||
|
||||
typedef i2s_driver_config_t i2s_config_t;
|
||||
typedef intr_handle_t i2s_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief I2S event types
|
||||
* @brief I2S event queue 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_TX_Q_OVF, /*!< I2S DMA sent queue overflow*/
|
||||
I2S_EVENT_RX_Q_OVF, /*!< I2S DMA receive queue overflow*/
|
||||
I2S_EVENT_MAX, /*!< I2S event max index*/
|
||||
} i2s_event_type_t;
|
||||
/**
|
||||
@ -123,7 +151,7 @@ esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr);
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
/**
|
||||
* @brief Set TX PDM mode up-sample rate
|
||||
* TX PDM have two type upsampling rate configurations:
|
||||
* TX PDM can only be set to the following two upsampling rate configurations:
|
||||
* 1: fp = 960, fs = sample_rate / 100, in this case, Fpdm = 128*48000
|
||||
* 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate
|
||||
* If the pdm receiver do not care the pdm serial clock, it's recommended set Fpdm = 128*48000
|
||||
@ -162,7 +190,7 @@ esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, int sample_rate, int fp,
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue);
|
||||
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue);
|
||||
|
||||
/**
|
||||
* @brief Uninstall I2S driver.
|
||||
@ -326,7 +354,7 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, int mode, i2s_pcm_cfg_t pcm_cfg);
|
||||
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, i2s_mode_t mode, i2s_pcm_mode_t pcm_cfg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -334,20 +362,27 @@ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, int mode, i2s_pcm_cfg_t pcm_cfg);
|
||||
*
|
||||
* Similar to i2s_set_sample_rates(), but also sets bit width.
|
||||
*
|
||||
* 1. stop i2s;
|
||||
* 2. calculate mclk, bck, bck_factor
|
||||
* 3. malloc dma buffer;
|
||||
* 4. start i2s
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param rate I2S sample rate (ex: 8000, 44100...)
|
||||
*
|
||||
* @param slot_bits i2s slot bit configuration
|
||||
* @param bits_cfg I2S bits configuation
|
||||
* the low 16 bits is for data bits per sample in one channel (see 'i2s_bits_per_sample_t')
|
||||
* the high 16 bits is for total bits in one channel (see 'i2s_bits_per_slot_t')
|
||||
*
|
||||
* @param sloct_ch I2S slot number configuration
|
||||
* @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_slot_bits_cfg_t slot_bits, i2s_slot_channel_cfg_t sloct_ch);
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch);
|
||||
|
||||
/**
|
||||
* @brief get clock set on particular port number.
|
||||
@ -357,7 +392,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_slot_bits_cfg_t slo
|
||||
* @return
|
||||
* - actual clock set by i2s driver
|
||||
*/
|
||||
uint32_t i2s_get_clk(i2s_port_t i2s_num);
|
||||
float i2s_get_clk(i2s_port_t i2s_num);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
/**
|
||||
|
@ -54,12 +54,10 @@ static void example_i2s_init(void)
|
||||
{
|
||||
int i2s_num = EXAMPLE_I2S_NUM;
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.slot_bits_cfg = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024,
|
||||
|
@ -56,12 +56,10 @@ static void example_i2s_init(void)
|
||||
{
|
||||
int i2s_num = EXAMPLE_I2S_NUM;
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.slot_bits_cfg = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024,
|
||||
|
@ -21,22 +21,51 @@
|
||||
#include "math.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3)
|
||||
|
||||
#define SAMPLE_RATE (36000)
|
||||
#define SAMPLE_BITS (16)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define MASTER_BCK_IO 15
|
||||
#define MASTER_WS_IO 25
|
||||
#define SLAVE_BCK_IO 19
|
||||
#define SLAVE_WS_IO 26
|
||||
#define DATA_IN_IO 21
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define MASTER_WS_IO 25
|
||||
#define DATA_OUT_IO 22
|
||||
#define ADC1_CHANNEL_4_IO 32
|
||||
#define I2S0_DATA_OUT_IDX I2S0O_DATA_OUT23_IDX
|
||||
#define I2S0_DATA_IN_IDX I2S0I_DATA_IN15_IDX
|
||||
#define I2S1_DATA_OUT_IDX I2S1O_DATA_OUT23_IDX
|
||||
#define I2S1_DATA_IN_IDX I2S1I_DATA_IN15_IDX
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define MASTER_BCK_IO 15
|
||||
#define MASTER_WS_IO 28
|
||||
#define SLAVE_BCK_IO 19
|
||||
#define SLAVE_WS_IO 26
|
||||
#define DATA_IN_IO 21
|
||||
#define DATA_OUT_IO 20
|
||||
#define I2S0_DATA_OUT_IDX I2S0O_DATA_OUT23_IDX
|
||||
#define I2S0_DATA_IN_IDX I2S0I_DATA_IN15_IDX
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
// TODO: change pins
|
||||
#define MASTER_BCK_IO 4
|
||||
#define MASTER_WS_IO 5
|
||||
#define SLAVE_BCK_IO 14
|
||||
#define SLAVE_WS_IO 15
|
||||
#define DATA_IN_IO 19
|
||||
#define DATA_OUT_IO 18
|
||||
#define I2S0_DATA_OUT_IDX I2SO_SD_OUT_IDX
|
||||
#define I2S0_DATA_IN_IDX I2SI_SD_IN_IDX
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define MASTER_BCK_IO 4
|
||||
#define MASTER_WS_IO 5
|
||||
#define SLAVE_BCK_IO 14
|
||||
#define SLAVE_WS_IO 15
|
||||
#define DATA_IN_IO 19
|
||||
#define DATA_OUT_IO 18
|
||||
#define I2S0_DATA_OUT_IDX I2S0O_SD_OUT_IDX
|
||||
#define I2S0_DATA_IN_IDX I2S0I_SD_IN_IDX
|
||||
#define I2S1_DATA_OUT_IDX I2S1O_SD_OUT_IDX
|
||||
#define I2S1_DATA_IN_IDX I2S1I_SD_IN_IDX
|
||||
#endif
|
||||
|
||||
#define PERCENT_DIFF 0.0001
|
||||
@ -67,8 +96,8 @@ static void i2s_test_io_config(int mode)
|
||||
esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0I_WS_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1O_WS_IN_IDX, 0);
|
||||
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S1O_DATA_OUT23_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0);
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S1_DATA_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -79,14 +108,14 @@ static void i2s_test_io_config(int mode)
|
||||
esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0O_WS_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1I_WS_IN_IDX, 0);
|
||||
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S1I_DATA_IN15_IDX, 0);
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0_DATA_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S1_DATA_IN_IDX, 0);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case I2S_TEST_MODE_LOOPBACK: {
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0);
|
||||
esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0_DATA_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -107,35 +136,17 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]")
|
||||
{
|
||||
// dac, adc i2s
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.use_apll = 0,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 ,
|
||||
};
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//install and start i2s driver
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
//for internal DAC, this will enable both of the internal channels
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL));
|
||||
//stop & destroy i2s driver
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
#endif
|
||||
|
||||
// normal i2s
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
@ -161,20 +172,11 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
|
||||
{
|
||||
// master driver installed and send data
|
||||
i2s_config_t master_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 0,
|
||||
@ -230,89 +232,17 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP32S2)
|
||||
/* ESP32S2 has only single I2S port and hence following test cases are not applicable */
|
||||
TEST_CASE("I2S adc test", "[i2s]")
|
||||
{
|
||||
// init I2S ADC
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024,
|
||||
.use_apll = 0,
|
||||
};
|
||||
// install and start I2S driver
|
||||
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
|
||||
// init ADC pad
|
||||
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4);
|
||||
// enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init
|
||||
i2s_adc_enable(I2S_NUM_0);
|
||||
// init read buffer
|
||||
uint16_t* i2sReadBuffer = (uint16_t*)calloc(1024, sizeof(uint16_t));
|
||||
size_t bytesRead;
|
||||
|
||||
for (int loop = 0; loop < 10; loop++) {
|
||||
for (int level = 0; level <= 1; level++) {
|
||||
if (level == 0) {
|
||||
gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY);
|
||||
} else {
|
||||
gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY);
|
||||
}
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
// read data from adc, will block until buffer is full
|
||||
i2s_read(I2S_NUM_0, (void*)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY);
|
||||
|
||||
// calc average
|
||||
int64_t adcSumValue = 0;
|
||||
for (size_t i = 0; i < 1024; i++) {
|
||||
adcSumValue += i2sReadBuffer[i] & 0xfff;
|
||||
}
|
||||
int adcAvgValue = adcSumValue / 1024;
|
||||
printf("adc average val: %d\n", adcAvgValue);
|
||||
|
||||
if (level == 0) {
|
||||
TEST_ASSERT_LESS_THAN(100, adcAvgValue);
|
||||
} else {
|
||||
TEST_ASSERT_GREATER_THAN(4000, adcAvgValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
i2s_adc_disable(I2S_NUM_0);
|
||||
free(i2sReadBuffer);
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
|
||||
/* ESP32S2 and ESP32C3 has only single I2S port and hence following test cases are not applicable */
|
||||
TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
{
|
||||
// master driver installed and send data
|
||||
i2s_config_t master_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 0,
|
||||
@ -330,20 +260,11 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
printf("\r\nheap size: %d\n", esp_get_free_heap_size());
|
||||
|
||||
i2s_config_t slave_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_SLAVE | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_SLAVE | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 0,
|
||||
@ -374,6 +295,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
|
||||
int end_position = 0;
|
||||
// write data to slave
|
||||
i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t)*400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS);
|
||||
printf("write data size: %d\n", i2s_bytes_write);
|
||||
while(!flag){
|
||||
i2s_read(I2S_NUM_1, i2s_read_buff + length, sizeof(uint8_t)*500, &bytes_read, 1000/portMAX_DELAY);
|
||||
if(bytes_read>0) {
|
||||
@ -402,20 +324,11 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
{
|
||||
// master driver installed and send data
|
||||
i2s_config_t master_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 1,
|
||||
@ -433,20 +346,11 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
printf("\r\nheap size: %d\n", esp_get_free_heap_size());
|
||||
|
||||
i2s_config_t slave_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_SLAVE | I2S_MODE_TX, // Only RX
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_SLAVE | I2S_MODE_TX, // Only RX
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 1,
|
||||
@ -474,7 +378,7 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
}
|
||||
// slave write data to master
|
||||
i2s_write(I2S_NUM_1, data_wr, sizeof(uint8_t)*400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS);
|
||||
|
||||
printf("write data size: %d\n", i2s_bytes_write);
|
||||
int flag=0; // break loop flag
|
||||
int end_position = 0;
|
||||
// write data to slave
|
||||
@ -505,20 +409,11 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
|
||||
TEST_CASE("I2S memory leaking test", "[i2s]")
|
||||
{
|
||||
i2s_config_t master_i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 100,
|
||||
.use_apll = 0,
|
||||
@ -561,20 +456,11 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
};
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.use_apll = true,
|
||||
@ -591,8 +477,8 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
|
||||
for (int i = 0; i < (sizeof(sample_rate_arr)/sizeof(sample_rate_arr[0])); i++) {
|
||||
for (int j = 0; j < (sizeof(bits_per_sample_arr)/sizeof(bits_per_sample_arr[0])); j++) {
|
||||
i2s_config.param_cfg.sample_rate = sample_rate_arr[i];
|
||||
i2s_config.param_cfg.slot_bits_cfg = bits_per_sample_arr[j];
|
||||
i2s_config.sample_rate = sample_rate_arr[i];
|
||||
i2s_config.bits_per_sample = bits_per_sample_arr[j];
|
||||
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config));
|
||||
@ -606,4 +492,93 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
#if DISABLED_FOR_TARGETS(ESP32)
|
||||
/* Only ESP32 need I2S adc/dac test */
|
||||
TEST_CASE("I2S adc test", "[i2s]")
|
||||
{
|
||||
// init I2S ADC
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024,
|
||||
.use_apll = 0,
|
||||
};
|
||||
// install and start I2S driver
|
||||
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
|
||||
// init ADC pad
|
||||
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4);
|
||||
// enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init
|
||||
i2s_adc_enable(I2S_NUM_0);
|
||||
// init read buffer
|
||||
uint16_t* i2sReadBuffer = (uint16_t*)calloc(1024, sizeof(uint16_t));
|
||||
size_t bytesRead;
|
||||
|
||||
for (int loop = 0; loop < 10; loop++) {
|
||||
for (int level = 0; level <= 1; level++) {
|
||||
if (level == 0) {
|
||||
gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY);
|
||||
} else {
|
||||
gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY);
|
||||
}
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
// read data from adc, will block until buffer is full
|
||||
i2s_read(I2S_NUM_0, (void*)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY);
|
||||
|
||||
// calc average
|
||||
int64_t adcSumValue = 0;
|
||||
for (size_t i = 0; i < 1024; i++) {
|
||||
adcSumValue += i2sReadBuffer[i] & 0xfff;
|
||||
}
|
||||
int adcAvgValue = adcSumValue / 1024;
|
||||
printf("adc average val: %d\n", adcAvgValue);
|
||||
|
||||
if (level == 0) {
|
||||
if (adcAvgValue > 100) {
|
||||
i2s_adc_disable(I2S_NUM_0);
|
||||
free(i2sReadBuffer);
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
TEST_ASSERT_LESS_THAN(100, adcAvgValue);
|
||||
}
|
||||
} else {
|
||||
if (adcAvgValue < 4000) {
|
||||
i2s_adc_disable(I2S_NUM_0);
|
||||
free(i2sReadBuffer);
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
TEST_ASSERT_GREATER_THAN(4000, adcAvgValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i2s_adc_disable(I2S_NUM_0);
|
||||
free(i2sReadBuffer);
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
}
|
||||
|
||||
TEST_CASE("I2S dac test", "[i2s]")
|
||||
{
|
||||
// dac, adc i2s
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.use_apll = 0,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 ,
|
||||
};
|
||||
|
||||
//install and start i2s driver
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
//for internal DAC, this will enable both of the internal channels
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL));
|
||||
//stop & destroy i2s driver
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
}
|
||||
#endif
|
||||
|
@ -16,16 +16,6 @@ extern "C" {
|
||||
|
||||
#define ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(scheme, max_num_bit)
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
#define SOC_I2S_NUM (1)
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (0)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) //(SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_GDMA_I2S0_DMA_CHANNEL (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2021 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,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for I2C register operations
|
||||
// The LL layer for I2S register operations
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
@ -29,14 +29,14 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define I2S_LL_GET_HW(num) (&I2S0)
|
||||
#define I2S_INTR_OUT_DSCR_ERR (0x1 << 6)
|
||||
#define I2S_INTR_OUT_EOF (0x1 << 4)
|
||||
#define I2S_INTR_IN_DSCR_ERR (0x1 << 5)
|
||||
#define I2S_INTR_IN_SUC_EOF (0x1 << 1)
|
||||
#define I2S_INTR_MAX (~0)
|
||||
#define I2S_LL_GET_HW(num) (&I2S0)
|
||||
|
||||
#define I2S_TDM_CH_MASK (0xffff)
|
||||
#define I2S_LL_TDM_CH_MASK (0xffff)
|
||||
#define I2S_LL_PDM_BCK_FACTOR (64)
|
||||
#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ)
|
||||
|
||||
#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9)
|
||||
#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
|
||||
|
||||
/* I2S clock configuration structure */
|
||||
typedef struct {
|
||||
@ -44,95 +44,58 @@ 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 = freq_diff * 512;
|
||||
if (freq_diff == 0) {
|
||||
return;
|
||||
}
|
||||
for (int a = 2; a <= 512; 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)
|
||||
{
|
||||
hw->tx_clkm_conf.clk_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2S TX module, enable default source clock and set to TDM mode.
|
||||
* @brief Enable I2S tx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_tx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw)
|
||||
{
|
||||
hw->tx_conf.tx_start = 0;
|
||||
hw->tx_conf.tx_reset = 1;
|
||||
hw->tx_conf.tx_reset = 0;
|
||||
hw->tx_conf.tx_slave_mod = 0;
|
||||
hw->tx_conf.tx_tdm_en = 1;
|
||||
hw->tx_conf.tx_pdm_en = 0;
|
||||
hw->tx_clkm_conf.tx_clk_active = 1;
|
||||
hw->tx_clkm_conf.tx_clk_sel = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2S RX module, enable default source clock and set to TDM mode.
|
||||
* @brief Enable I2S rx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_rx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_enable_rx_clock(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_conf.rx_start = 0;
|
||||
hw->rx_conf.rx_reset = 1;
|
||||
hw->rx_conf.rx_reset = 0;
|
||||
hw->rx_conf.rx_slave_mod = 0;
|
||||
hw->rx_conf.rx_tdm_en = 1;
|
||||
hw->rx_conf.rx_pdm_en = 0;
|
||||
hw->rx_clkm_conf.rx_clk_active = 1;
|
||||
hw->rx_clkm_conf.rx_clk_sel = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S mclk use tx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_clkm_conf.mclk_sel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S mclk use rx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_clkm_conf.mclk_sel = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX slave mode
|
||||
*
|
||||
@ -203,7 +166,7 @@ static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw)
|
||||
* @brief Set TX source clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param src I2S source clock, ESP32-S3 only support `I2S_CLK_D2CLK`
|
||||
* @param src I2S source clock.
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
{
|
||||
@ -227,27 +190,27 @@ 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)
|
||||
{
|
||||
if (set->a == 0 || set->b == 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 (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;
|
||||
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_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_yn1 = 0;
|
||||
}
|
||||
}
|
||||
hw->tx_clkm_conf.tx_clkm_div_num = set->mclk_div;
|
||||
hw->tx_conf1.tx_bck_div_num = set->bck_div-1;
|
||||
hw->tx_conf1.tx_bck_div_num = set->bck_div - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,27 +219,27 @@ 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)
|
||||
{
|
||||
if (set->a == 0 || set->b == 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 (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;
|
||||
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_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_yn1 = 0;
|
||||
}
|
||||
}
|
||||
hw->rx_clkm_conf.rx_clkm_div_num = set->mclk_div;
|
||||
hw->rx_conf1.rx_bck_div_num = set->bck_div-1;
|
||||
hw->rx_conf1.rx_bck_div_num = set->bck_div - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +294,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw)
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
{
|
||||
hw->tx_conf1.tx_tdm_ws_width = width-1;
|
||||
hw->tx_conf1.tx_tdm_ws_width = width - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -342,7 +305,7 @@ static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
{
|
||||
hw->rx_conf1.rx_tdm_ws_width = width-1;
|
||||
hw->rx_conf1.rx_tdm_ws_width = width - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,7 +329,7 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num)
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
hw->tx_conf1.tx_bits_mod = data_bit - 1;
|
||||
hw->tx_conf1.tx_tdm_chan_bits = sample_bit-1;
|
||||
hw->tx_conf1.tx_tdm_chan_bits = sample_bit - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,7 +342,7 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
hw->rx_conf1.rx_bits_mod = data_bit - 1;
|
||||
hw->rx_conf1.rx_tdm_chan_bits = sample_bit-1;
|
||||
hw->rx_conf1.rx_tdm_chan_bits = sample_bit - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,7 +353,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits)
|
||||
{
|
||||
hw->tx_conf1.tx_half_sample_bits = half_sample_bits-1;
|
||||
hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,7 +364,7 @@ static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits)
|
||||
{
|
||||
hw->rx_conf1.rx_half_sample_bits = half_sample_bits-1;
|
||||
hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,9 +395,9 @@ static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_tx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num-1;
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -443,22 +406,22 @@ static inline void i2s_ll_set_tx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_rx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num-1;
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active TX slot, only the active slot can launch audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param slot_mask mask of tx active slot
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
{
|
||||
typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask&I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@ -466,13 +429,13 @@ static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_m
|
||||
* @brief Set the bimap of the active RX slot, only the active slot can receive audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param slot_mask mask of rx active slot
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
{
|
||||
typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask&I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@ -480,7 +443,7 @@ static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_m
|
||||
* @brief Set TX WS signal pol level
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param ws_pol_level pin level of WS(output) when receiving left channel data
|
||||
*/
|
||||
static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
{
|
||||
@ -491,7 +454,7 @@ static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
* @brief Set RX WS signal pol level
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param ws_pol_level pin level of WS(input) when receiving left channel data
|
||||
*/
|
||||
static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
{
|
||||
@ -533,7 +496,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate)
|
||||
pdm_conf_reg.tx_pdm_lp_in_shift = 1;
|
||||
pdm_conf_reg.tx_pdm_sinc_in_shift = 1;
|
||||
pdm_conf_reg.tx_pdm_sigmadelta_in_shift = 1;
|
||||
pdm_conf_reg.tx_pdm_sinc_osr2 = fp/fs;
|
||||
pdm_conf_reg.tx_pdm_sinc_osr2 = fp / fs;
|
||||
pdm_conf_reg.tx_pdm_dac_mode_en = 1;
|
||||
pdm_conf_reg.tx_pdm_sigmadelta_dither = 0;
|
||||
pdm_conf_reg.tx_pdm_sigmadelta_dither2 = 0;
|
||||
@ -541,7 +504,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate)
|
||||
pdm_conf1_reg.tx_pdm_fp = fp;
|
||||
pdm_conf1_reg.tx_pdm_fs = fs;
|
||||
pdm_conf1_reg.tx_iir_hp_mult12_5 = 7;
|
||||
pdm_conf1_reg.tx_iir_hp_mult12_0 =6;
|
||||
pdm_conf1_reg.tx_iir_hp_mult12_0 = 6;
|
||||
pdm_conf_reg.tx_pdm_hp_bypass = 0;
|
||||
hw->tx_pcm2pdm_conf = pdm_conf_reg;
|
||||
hw->tx_pcm2pdm_conf1 = pdm_conf1_reg;
|
||||
@ -583,13 +546,8 @@ static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
{
|
||||
if (pdm_enable) {
|
||||
hw->rx_conf.rx_tdm_en = 0;
|
||||
hw->rx_conf.rx_pdm_en = 1;
|
||||
} else {
|
||||
hw->rx_conf.rx_pdm_en = 0;
|
||||
hw->rx_conf.rx_tdm_en = 1;
|
||||
}
|
||||
hw->rx_conf.rx_pdm_en = pdm_enable;
|
||||
hw->rx_conf.rx_tdm_en = !pdm_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -598,7 +556,7 @@ static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->tx_conf.tx_pcm_bypass = 1;
|
||||
@ -614,7 +572,7 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->rx_conf.rx_pcm_bypass = 1;
|
||||
@ -690,6 +648,18 @@ static inline void i2s_ll_rx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena)
|
||||
hw->rx_conf.rx_bit_order = lsb_order_ena;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX skip mask enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param skip_mask_ena Set true to skip inactive channels.
|
||||
*/
|
||||
static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_skip_msk_en = skip_mask_ena;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure single data
|
||||
*
|
||||
|
@ -31,13 +31,12 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Get I2S hardware instance with giving i2s num
|
||||
#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL)
|
||||
#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : 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_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 {
|
||||
@ -45,56 +44,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_sel = 2;
|
||||
@ -104,35 +61,69 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +220,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;
|
||||
@ -243,7 +234,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;
|
||||
@ -490,11 +481,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2021 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,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for I2C register operations
|
||||
// The LL layer for I2S register operations
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
@ -30,13 +30,13 @@ extern "C" {
|
||||
|
||||
|
||||
#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : &I2S1)
|
||||
#define I2S_INTR_OUT_DSCR_ERR (0x1 << 6)
|
||||
#define I2S_INTR_OUT_EOF (0x1 << 4)
|
||||
#define I2S_INTR_IN_DSCR_ERR (0x1 << 5)
|
||||
#define I2S_INTR_IN_SUC_EOF (0x1 << 1)
|
||||
#define I2S_INTR_MAX (~0)
|
||||
|
||||
#define I2S_TDM_CH_MASK (0xffff)
|
||||
#define I2S_LL_TDM_CH_MASK (0xffff)
|
||||
#define I2S_LL_PDM_BCK_FACTOR (64)
|
||||
#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ)
|
||||
|
||||
#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9)
|
||||
#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
|
||||
|
||||
/* I2S clock configuration structure */
|
||||
typedef struct {
|
||||
@ -44,95 +44,58 @@ 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 = freq_diff * 512;
|
||||
if (freq_diff == 0) {
|
||||
return;
|
||||
}
|
||||
for (int a = 2; a <= 512; 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)
|
||||
{
|
||||
hw->tx_clkm_conf.clk_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2S TX module, enable default source clock and set to TDM mode.
|
||||
* @brief Enable I2S tx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_tx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw)
|
||||
{
|
||||
hw->tx_conf.tx_start = 0;
|
||||
hw->tx_conf.tx_reset = 1;
|
||||
hw->tx_conf.tx_reset = 0;
|
||||
hw->tx_conf.tx_slave_mod = 0;
|
||||
hw->tx_conf.tx_tdm_en = 1;
|
||||
hw->tx_conf.tx_pdm_en = 0;
|
||||
hw->tx_clkm_conf.tx_clk_active = 1;
|
||||
hw->tx_clkm_conf.tx_clk_sel = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2S RX module, enable default source clock and set to TDM mode.
|
||||
* @brief Enable I2S rx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_rx_gen_init(i2s_dev_t *hw)
|
||||
static inline void i2s_ll_enable_rx_clock(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_conf.rx_start = 0;
|
||||
hw->rx_conf.rx_reset = 1;
|
||||
hw->rx_conf.rx_reset = 0;
|
||||
hw->rx_conf.rx_slave_mod = 0;
|
||||
hw->rx_conf.rx_tdm_en = 1;
|
||||
hw->rx_conf.rx_pdm_en = 0;
|
||||
hw->rx_clkm_conf.rx_clk_active = 1;
|
||||
hw->rx_clkm_conf.rx_clk_sel = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S mclk use tx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_clkm_conf.mclk_sel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S mclk use rx module clock
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
*/
|
||||
static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_clkm_conf.mclk_sel = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX slave mode
|
||||
*
|
||||
@ -204,6 +167,7 @@ static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw)
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param src I2S source clock, ESP32-S3 only support `I2S_CLK_D2CLK`
|
||||
* TX and RX share the same clock setting
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
{
|
||||
@ -215,6 +179,7 @@ static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param src I2S source clock, ESP32-S3 only support `I2S_CLK_D2CLK`
|
||||
* TX and RX share the same clock setting
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src)
|
||||
{
|
||||
@ -227,27 +192,27 @@ 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)
|
||||
{
|
||||
if (set->a == 0 || set->b == 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 (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;
|
||||
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_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_yn1 = 0;
|
||||
}
|
||||
}
|
||||
hw->tx_clkm_conf.tx_clkm_div_num = set->mclk_div;
|
||||
hw->tx_conf1.tx_bck_div_num = set->bck_div-1;
|
||||
hw->tx_conf1.tx_bck_div_num = set->bck_div - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,27 +221,27 @@ 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)
|
||||
{
|
||||
if (set->a == 0 || set->b == 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 (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;
|
||||
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_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_yn1 = 0;
|
||||
}
|
||||
}
|
||||
hw->rx_clkm_conf.rx_clkm_div_num = set->mclk_div;
|
||||
hw->rx_conf1.rx_bck_div_num = set->bck_div-1;
|
||||
hw->rx_conf1.rx_bck_div_num = set->bck_div - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +296,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw)
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
{
|
||||
hw->tx_conf1.tx_tdm_ws_width = width-1;
|
||||
hw->tx_conf1.tx_tdm_ws_width = width - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -342,7 +307,7 @@ static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width)
|
||||
{
|
||||
hw->rx_conf1.rx_tdm_ws_width = width-1;
|
||||
hw->rx_conf1.rx_tdm_ws_width = width - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,7 +331,7 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num)
|
||||
static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
hw->tx_conf1.tx_bits_mod = data_bit - 1;
|
||||
hw->tx_conf1.tx_tdm_chan_bits = sample_bit-1;
|
||||
hw->tx_conf1.tx_tdm_chan_bits = sample_bit - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,7 +344,7 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit)
|
||||
{
|
||||
hw->rx_conf1.rx_bits_mod = data_bit - 1;
|
||||
hw->rx_conf1.rx_tdm_chan_bits = sample_bit-1;
|
||||
hw->rx_conf1.rx_tdm_chan_bits = sample_bit - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,7 +355,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits)
|
||||
{
|
||||
hw->tx_conf1.tx_half_sample_bits = half_sample_bits-1;
|
||||
hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,7 +366,7 @@ static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits)
|
||||
{
|
||||
hw->rx_conf1.rx_half_sample_bits = half_sample_bits-1;
|
||||
hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,9 +397,9 @@ static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_tx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num-1;
|
||||
hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -443,22 +408,22 @@ static inline void i2s_ll_set_tx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param total_num Total slot number
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_slot_mun(i2s_dev_t *hw, int total_num)
|
||||
static inline void i2s_ll_set_rx_slot_num(i2s_dev_t *hw, int total_num)
|
||||
{
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num-1;
|
||||
hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the bimap of the active TX slot, only the active slot can launch audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param slot_mask mask of tx active slot
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
{
|
||||
typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask&I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@ -466,13 +431,13 @@ static inline void i2s_ll_set_tx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_m
|
||||
* @brief Set the bimap of the active RX slot, only the active slot can receive audio data.
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param slot_mask mask of rx active slot
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_mask)
|
||||
{
|
||||
typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl;
|
||||
tdm_ctrl_reg.val &= ~I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask&I2S_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK;
|
||||
tdm_ctrl_reg.val |= slot_mask & I2S_LL_TDM_CH_MASK;
|
||||
hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val;
|
||||
}
|
||||
|
||||
@ -480,7 +445,7 @@ static inline void i2s_ll_set_rx_active_slot_mask(i2s_dev_t *hw, uint32_t slot_m
|
||||
* @brief Set TX WS signal pol level
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param ws_pol_level pin level of WS(output) when receiving left channel data
|
||||
*/
|
||||
static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
{
|
||||
@ -491,7 +456,7 @@ static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
* @brief Set RX WS signal pol level
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param
|
||||
* @param ws_pol_level pin level of WS(input) when receiving left channel data
|
||||
*/
|
||||
static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
{
|
||||
@ -506,13 +471,8 @@ static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level)
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
{
|
||||
if (pdm_enable) {
|
||||
hw->tx_conf.tx_tdm_en = 0;
|
||||
hw->tx_conf.tx_pdm_en = 1;
|
||||
} else {
|
||||
hw->tx_conf.tx_pdm_en = 0;
|
||||
hw->tx_conf.tx_tdm_en = 1;
|
||||
}
|
||||
hw->tx_conf.tx_pdm_en = pdm_enable;
|
||||
hw->tx_conf.tx_tdm_en = !pdm_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -523,13 +483,68 @@ static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
*/
|
||||
static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable)
|
||||
{
|
||||
if (pdm_enable) {
|
||||
hw->rx_conf.rx_tdm_en = 0;
|
||||
hw->rx_conf.rx_pdm_en = 1;
|
||||
} else {
|
||||
hw->rx_conf.rx_pdm_en = 0;
|
||||
hw->rx_conf.rx_tdm_en = 1;
|
||||
}
|
||||
hw->rx_conf.rx_pdm_en = pdm_enable;
|
||||
hw->rx_conf.rx_tdm_en = !pdm_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2S TX PDM sample rate
|
||||
* Fpdm = 64*Fpcm*fp/fs
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param fp The fp value of TX PDM filter module group0.
|
||||
* @param fs The fs value of TX PDM filter module group0.
|
||||
*/
|
||||
static inline void i2s_ll_set_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs)
|
||||
{
|
||||
hw->tx_pcm2pdm_conf1.tx_pdm_fp = fp;
|
||||
hw->tx_pcm2pdm_conf1.tx_pdm_fs = fs;
|
||||
hw->tx_pcm2pdm_conf.tx_sinc_osr2 = fp / fs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S TX PDM configuration
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param fp Pointer to accept TX PDM fp configuration paramater
|
||||
* @param fs Pointer to accept TX PDM fs configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs)
|
||||
{
|
||||
*fp = hw->tx_pcm2pdm_conf1.tx_pdm_fp;
|
||||
*fs = hw->tx_pcm2pdm_conf1.tx_pdm_fs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2S TX pdm
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param sample_rate The sample rate to be set.
|
||||
*/
|
||||
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->tx_pcm2pdm_conf) pdm_conf_reg = hw->tx_pcm2pdm_conf;
|
||||
typeof(hw->tx_pcm2pdm_conf1) pdm_conf1_reg = hw->tx_pcm2pdm_conf1;
|
||||
pdm_conf_reg.pcm2pdm_conv_en = 1;
|
||||
pdm_conf_reg.tx_prescale = 0;
|
||||
pdm_conf_reg.tx_hp_in_shift = 1;
|
||||
pdm_conf_reg.tx_lp_in_shift = 1;
|
||||
pdm_conf_reg.tx_sinc_in_shift = 1;
|
||||
pdm_conf_reg.tx_sigmadelta_in_shift = 1;
|
||||
pdm_conf_reg.tx_sinc_osr2 = fp / fs;
|
||||
pdm_conf_reg.tx_dac_mode_en = 1;
|
||||
pdm_conf_reg.tx_sigmadelta_dither = 0;
|
||||
pdm_conf_reg.tx_sigmadelta_dither2 = 0;
|
||||
pdm_conf_reg.tx_dac_2out_en = 1;
|
||||
pdm_conf1_reg.tx_pdm_fp = fp;
|
||||
pdm_conf1_reg.tx_pdm_fs = fs;
|
||||
pdm_conf1_reg.tx_iir_hp_mult12_5 = 7;
|
||||
pdm_conf1_reg.tx_iir_hp_mult12_0 = 6;
|
||||
pdm_conf_reg.tx_hp_bypass = 0;
|
||||
hw->tx_pcm2pdm_conf = pdm_conf_reg;
|
||||
hw->tx_pcm2pdm_conf1 = pdm_conf1_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -541,7 +556,7 @@ static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw)
|
||||
{
|
||||
hw->rx_conf.rx_tdm_en = 0;
|
||||
hw->rx_conf.rx_pdm2pcm_en = 1;
|
||||
hw->rx_conf.rx_sinc_dsr_16_en = 0;
|
||||
hw->rx_conf.rx_pdm_sinc_dsr_16_en = 0;
|
||||
hw->rx_conf.rx_pdm_en = 1;
|
||||
}
|
||||
|
||||
@ -553,7 +568,7 @@ static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw)
|
||||
*/
|
||||
static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr)
|
||||
{
|
||||
hw->rx_conf.rx_sinc_dsr_16_en = dsr;
|
||||
hw->rx_conf.rx_pdm_sinc_dsr_16_en = dsr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -564,7 +579,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->rx_conf.rx_sinc_dsr_16_en;
|
||||
*dsr = hw->rx_conf.rx_pdm_sinc_dsr_16_en;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -573,7 +588,7 @@ static inline void i2s_ll_get_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->tx_conf.tx_pcm_bypass = 1;
|
||||
@ -589,7 +604,7 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param pcm_cfg PCM configuration paramater
|
||||
*/
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_cfg_t pcm_cfg)
|
||||
static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_mode_t pcm_cfg)
|
||||
{
|
||||
if (pcm_cfg == I2S_PCM_DISABLE) {
|
||||
hw->rx_conf.rx_pcm_bypass = 1;
|
||||
@ -665,6 +680,18 @@ static inline void i2s_ll_rx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena)
|
||||
hw->rx_conf.rx_bit_order = lsb_order_ena;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX skip mask enable
|
||||
*
|
||||
* @param hw Peripheral I2S hardware instance address.
|
||||
* @param skip_mask_ena Set true to skip inactive channels.
|
||||
*/
|
||||
static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena)
|
||||
{
|
||||
hw->tx_tdm_ctrl.tx_tdm_skip_msk_en = skip_mask_ena;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure single data
|
||||
*
|
||||
@ -673,7 +700,7 @@ static inline void i2s_ll_rx_set_bit_order(i2s_dev_t *hw, bool lsb_order_ena)
|
||||
*/
|
||||
static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data)
|
||||
{
|
||||
hw->conf_single_data = data;
|
||||
hw->conf_signal_data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,59 +17,50 @@
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/gdma_channel.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
|
||||
#define I2S_MODE_I2S (I2S_MODE_MASTER|I2S_MODE_SLAVE|I2S_MODE_TX|I2S_MODE_RX) /*!< I2S normal mode*/
|
||||
|
||||
void i2s_hal_reset_tx(i2s_hal_context_t *hal)
|
||||
/**
|
||||
* @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_ll_clk_cal_t` structure.
|
||||
*/
|
||||
static void i2s_hal_clk_cal(uint32_t fsclk, uint32_t fbck, int bck_div, i2s_ll_clk_cal_t *cal)
|
||||
{
|
||||
i2s_ll_reset_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_reset_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_reset_rx(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_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_start_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_start_rx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_stop_tx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
|
||||
{
|
||||
i2s_ll_stop_rx(hal->dev);
|
||||
}
|
||||
|
||||
void i2s_hal_set_tx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit)
|
||||
{
|
||||
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);
|
||||
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 <= I2S_LL_MCLK_DIVIDER_MAX; 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel)
|
||||
@ -80,23 +71,18 @@ void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t 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_clk_cal_t clk_set = {0};
|
||||
i2s_hal_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_clk_cal_t clk_set = {0};
|
||||
i2s_hal_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
|
||||
@ -109,200 +95,175 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal)
|
||||
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);
|
||||
i2s_ll_enable_clock(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)
|
||||
static void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
||||
{
|
||||
int active_slot_num = slot_ch_cfg & 0xffff;
|
||||
#if !SOC_I2S_SUPPORTS_TDM
|
||||
switch (format) {
|
||||
case I2S_COMM_FORMAT_STAND_MSB:
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_msb_align(hal->dev);
|
||||
}
|
||||
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_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_short(hal->dev);
|
||||
}
|
||||
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_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_philip(hal->dev);
|
||||
}
|
||||
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);
|
||||
switch (hal_cfg->comm_fmt) {
|
||||
case I2S_COMM_FORMAT_STAND_MSB:
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_msb_align(hal->dev);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_mono_mode_ena(hal->dev, active_slot_num == I2S_CHANNEL_MONO);
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_format_msb_align(hal->dev);
|
||||
}
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_short(hal->dev);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pcm_short(hal->dev);
|
||||
}
|
||||
break;
|
||||
case I2S_COMM_FORMAT_STAND_PCM_LONG:
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_pcm_long(hal->dev);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_pcm_long(hal->dev);
|
||||
}
|
||||
break;
|
||||
default: //I2S_COMM_FORMAT_STAND_I2S
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_format_philip(hal->dev);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_format_philip(hal->dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (hal_cfg->ch == I2S_CHANNEL_MONO) {
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_tx_mono_mode_ena(hal->dev, true);
|
||||
}
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_rx_mono_mode_ena(hal->dev, true);
|
||||
}
|
||||
}
|
||||
#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);
|
||||
int slot_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
int slot_num = hal_cfg->chan_cfg.total_chan;
|
||||
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;
|
||||
switch (hal_cfg->comm_fmt) {
|
||||
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) {
|
||||
if (hal_cfg->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);
|
||||
i2s_ll_set_tx_half_sample_bit(hal->dev, slot_num * slot_bits / 2);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
if (hal_cfg->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);
|
||||
i2s_ll_set_rx_half_sample_bit(hal->dev, slot_num * slot_bits / 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
void i2s_hal_samples_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
||||
{
|
||||
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);
|
||||
int data_bits = hal_cfg->bits_cfg.sample_bits;
|
||||
int slot_bits = hal_cfg->bits_cfg.chan_bits;
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_slot_mun(hal->dev, slot_num);
|
||||
int slot_num = hal_cfg->chan_cfg.total_chan;
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_slot_num(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);
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_set_rx_slot_num(hal->dev, slot_num);
|
||||
i2s_ll_set_rx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
#else
|
||||
if (i2s_mode & I2S_MODE_TX) {
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_set_tx_sample_bit(hal->dev, slot_bits, data_bits);
|
||||
}
|
||||
if (i2s_mode & I2S_MODE_RX) {
|
||||
if (hal_cfg->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);
|
||||
if ((hal_cfg->mode & (~(I2S_MODE_I2S))) == 0) {
|
||||
i2s_hal_format_config(hal, hal_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_param_t *i2s_config)
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
||||
{
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
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
|
||||
}
|
||||
bool is_slave = ((hal_cfg->mode & I2S_MODE_SLAVE) > 0);
|
||||
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
i2s_ll_stop_tx(hal->dev);
|
||||
i2s_ll_reset_tx(hal->dev);
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_ll_set_tx_pdm_en(hal->dev, false);
|
||||
i2s_ll_enable_tx_clock(hal->dev);
|
||||
i2s_ll_set_tx_clk_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||
i2s_ll_mclk_use_tx_clk(hal->dev);
|
||||
|
||||
i2s_ll_set_tx_active_slot_mask(hal->dev, hal_cfg->chan_cfg.chan_mask);
|
||||
i2s_ll_tx_left_align_enable(hal->dev, hal_cfg->flags.left_align_en);
|
||||
i2s_ll_tx_big_endian_enable(hal->dev, hal_cfg->flags.big_edin_en);
|
||||
i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->flags.bit_order_msb_en);
|
||||
i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->flags.skip_msk_en);
|
||||
#else
|
||||
i2s_ll_tx_msb_right_en(hal->dev, false);
|
||||
i2s_ll_tx_right_first_en(hal->dev, false);
|
||||
i2s_ll_tx_fifo_mod_force_en(hal->dev, true);
|
||||
#endif
|
||||
i2s_ll_set_tx_slave_mod(hal->dev, is_slave); //TX Slave
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_RX) {
|
||||
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 (hal_cfg->mode & I2S_MODE_RX) {
|
||||
i2s_ll_stop_rx(hal->dev);
|
||||
i2s_ll_reset_rx(hal->dev);
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
||||
i2s_ll_enable_rx_clock(hal->dev);
|
||||
i2s_ll_set_rx_clk_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default
|
||||
i2s_ll_mclk_use_rx_clk(hal->dev);
|
||||
|
||||
i2s_ll_set_rx_active_slot_mask(hal->dev, hal_cfg->chan_cfg.chan_mask);
|
||||
i2s_ll_rx_left_align_enable(hal->dev, hal_cfg->flags.left_align_en);
|
||||
i2s_ll_rx_big_endian_enable(hal->dev, hal_cfg->flags.big_edin_en);
|
||||
i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->flags.bit_order_msb_en);
|
||||
#else
|
||||
i2s_ll_rx_msb_right_en(hal->dev, false);
|
||||
i2s_ll_rx_right_first_en(hal->dev, false);
|
||||
i2s_ll_rx_fifo_mod_force_en(hal->dev, true);
|
||||
#endif
|
||||
i2s_ll_set_rx_slave_mod(hal->dev, is_slave); //RX Slave
|
||||
}
|
||||
#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) {
|
||||
if (hal_cfg->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
|
||||
if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) {
|
||||
i2s_ll_build_in_dac_ena(hal->dev);
|
||||
}
|
||||
if (i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
|
||||
if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) {
|
||||
i2s_ll_build_in_adc_ena(hal->dev);
|
||||
}
|
||||
// Buildin ADC and DAC have nothing to do with communication format configuration.
|
||||
@ -311,47 +272,27 @@ void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_param_t *i2s_
|
||||
#endif
|
||||
|
||||
#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
|
||||
bool is_pdm = ((hal_cfg->mode & I2S_MODE_PDM) > 0);
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
if (i2s_config->mode & I2S_MODE_TX) {
|
||||
if (hal_cfg->mode & I2S_MODE_TX) {
|
||||
if (is_pdm) {
|
||||
i2s_ll_tx_pdm_cfg(hal->dev, hal_cfg->sample_rate);
|
||||
} else {
|
||||
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
|
||||
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_PDM_TX
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
if(i2s_config->mode & I2S_MODE_RX) {
|
||||
if (hal_cfg->mode & I2S_MODE_RX) {
|
||||
if (is_pdm) {
|
||||
i2s_ll_rx_pdm_cfg(hal->dev);
|
||||
} else {
|
||||
i2s_ll_set_rx_pdm_en(hal->dev, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#endif // SOC_I2S_SUPPORTS_PDM_RX
|
||||
#endif // SOC_I2S_SUPPORTS_PDM
|
||||
//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);
|
||||
i2s_hal_samples_config(hal, hal_cfg);
|
||||
|
||||
}
|
||||
|
@ -27,55 +27,103 @@
|
||||
#include "soc/soc_caps.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" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S channel bits configurations
|
||||
*
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t sample_bits : 16; /*!< I2S sample bits in one channel */
|
||||
uint32_t chan_bits : 16; /*!< I2S total bits in one channel. Should not be smaller than 'sample_bits', default '0' means equal to 'sample_bits' */
|
||||
};
|
||||
uint32_t val; /*!< I2S cannel bits configiration value */
|
||||
} i2s_hal_bits_cfg_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
/**
|
||||
* @brief I2S channel configurations
|
||||
*
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t total_chan : 8; /*!< Total number of I2S channels */
|
||||
uint32_t active_chan : 8; /*!< Active channel number, it will be set automatically if chan_mask is set */
|
||||
uint32_t chan_mask : 16; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<<total_slot_num). */
|
||||
};
|
||||
uint32_t val; /*!< Slot data bits value*/
|
||||
} i2s_hal_chan_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief I2S TDM flags
|
||||
*
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t left_align_en : 1; /*!< Set to enable left aligment */
|
||||
uint32_t big_edin_en : 1; /*!< Set to enable big edin */
|
||||
uint32_t bit_order_msb_en : 1; /*!< Set to enable msb order */
|
||||
uint32_t skip_msk_en : 1; /*!< Set to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
|
||||
};
|
||||
uint32_t val;
|
||||
} i2s_hal_tdm_flags_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S HAL configurations
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_mode_t mode; /*!< I2S work mode, using ored mask of `i2s_mode_t`*/
|
||||
uint32_t sample_rate; /*!< I2S sample rate*/
|
||||
i2s_channel_t ch; /*!< I2S channels*/
|
||||
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.*/
|
||||
i2s_hal_bits_cfg_t bits_cfg; /*!< Channel bits configuration*/
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_hal_chan_cfg_t chan_cfg; /*!< active slot bit mask, using the ored mask of `i2s_channel_t`*/
|
||||
i2s_hal_tdm_flags_t flags; /*!< Set TDM flags*/
|
||||
#endif
|
||||
} i2s_hal_config_t;
|
||||
|
||||
/**
|
||||
* Context that should be maintained by both the driver and the HAL
|
||||
*/
|
||||
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 Reset I2S TX channel
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_reset_tx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_reset_tx(hal) i2s_ll_reset_tx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Reset I2S TX fifo
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_reset_tx_fifo(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_reset_tx_fifo(hal) i2s_ll_reset_tx_fifo((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Reset I2S RX channel
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_reset_rx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_reset_rx(hal) i2s_ll_reset_rx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Reset I2S RX fifo
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_reset_rx_fifo(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_reset_rx_fifo(hal) i2s_ll_reset_rx_fifo((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Init the I2S hal. This function should be called first before other hal layer function is called
|
||||
@ -97,20 +145,17 @@ void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel);
|
||||
* @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
|
||||
* @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t`
|
||||
*/
|
||||
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);
|
||||
void i2s_hal_samples_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
|
||||
|
||||
/**
|
||||
* @brief Config I2S param
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2s_config I2S paramater configuration structer, refer to `i2s_config_param_t`
|
||||
* @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_config_param_t *i2s_config);
|
||||
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg);
|
||||
|
||||
/**
|
||||
* @brief Enable I2S master full-duplex mode
|
||||
@ -131,28 +176,28 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal);
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_start_tx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_start_tx(hal) i2s_ll_start_tx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Start I2S rx
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_start_rx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_start_rx(hal) i2s_ll_start_rx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Stop I2S tx
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_stop_tx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_stop_tx(hal) i2s_ll_stop_tx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Stop I2S rx
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_stop_rx(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_stop_rx(hal) i2s_ll_stop_rx((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Set the received data length to trigger `in_suc_eof` interrupt.
|
||||
@ -160,25 +205,25 @@ void i2s_hal_stop_rx(i2s_hal_context_t *hal);
|
||||
* @param hal Context of the HAL layer
|
||||
* @param eof_byte The byte length that trigger in_suc_eof interrupt.
|
||||
*/
|
||||
void i2s_hal_set_rx_eof_num(i2s_hal_context_t *hal, uint32_t eof_byte);
|
||||
#define i2s_hal_set_rx_eof_num(hal, eof_byte) i2s_ll_set_rx_eof_num((hal)->dev, eof_byte)
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @param data_bit The sample data bit length.
|
||||
*/
|
||||
void i2s_hal_set_tx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit);
|
||||
#define i2s_hal_set_tx_sample_bit(hal, slot_bit, data_bit) i2s_ll_set_tx_sample_bit((hal)->dev, slot_bit, data_bit)
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @param data_bit The sample data bit length.
|
||||
*/
|
||||
void i2s_hal_set_rx_sample_bit(i2s_hal_context_t *hal, int slot_bit, int data_bit);
|
||||
#define i2s_hal_set_rx_sample_bit(hal, slot_bit, data_bit) i2s_ll_set_rx_sample_bit((hal)->dev, slot_bit, data_bit)
|
||||
|
||||
/**
|
||||
* @brief Configure I2S TX module clock devider
|
||||
@ -205,17 +250,17 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc
|
||||
* @brief Configure I2S TX PCM encoder or decoder.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_cfg_t`
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_mode_t`
|
||||
*/
|
||||
void i2s_hal_tx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg);
|
||||
#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_pcm_cfg((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_cfg_t`
|
||||
* @param cfg PCM configure paramater, refer to `i2s_pcm_mode_t`
|
||||
*/
|
||||
void i2s_hal_rx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg);
|
||||
#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_pcm_cfg((hal)->dev, cfg)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -223,7 +268,7 @@ void i2s_hal_rx_pcm_cfg(i2s_hal_context_t *hal, i2s_pcm_cfg_t cfg);
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*/
|
||||
void i2s_hal_enable_sig_loopback(i2s_hal_context_t *hal);
|
||||
#define i2s_hal_enable_sig_loopback(hal) i2s_ll_loop_back_ena((hal)->dev, true)
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
/**
|
||||
@ -234,7 +279,7 @@ void i2s_hal_enable_sig_loopback(i2s_hal_context_t *hal);
|
||||
* @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);
|
||||
#define i2s_hal_set_tx_pdm_fpfs(hal, fp, fs) i2s_ll_set_tx_pdm_fpfs((hal)->dev, fp, fs)
|
||||
|
||||
/**
|
||||
* @brief Get I2S TX PDM configuration
|
||||
@ -243,7 +288,7 @@ void i2s_hal_set_tx_pdm_fpfs(i2s_hal_context_t *hal, int fp, int fs);
|
||||
* @param fp Pointer to accept TX PDM fp paramater configuration
|
||||
* @param fs Pointer to accept TX PDM fs paramater configuration
|
||||
*/
|
||||
void i2s_hal_get_tx_pdm_fpfs(i2s_hal_context_t *hal, int *fp, int *fs);
|
||||
#define i2s_hal_get_tx_pdm_fpfs(hal, fp, fs) i2s_ll_get_tx_pdm_fpfs((hal)->dev, (uint32_t *)fp, (uint32_t *)fs)
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
@ -254,7 +299,7 @@ void i2s_hal_get_tx_pdm_fpfs(i2s_hal_context_t *hal, int *fp, int *fs);
|
||||
* @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);
|
||||
#define i2s_hal_set_rx_pdm_dsr(hal, dsr) i2s_ll_set_pdm_rx_dsr((hal)->dev, dsr)
|
||||
|
||||
/**
|
||||
* @brief Get RX PDM downsample configuration
|
||||
@ -262,7 +307,7 @@ void i2s_hal_set_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t dsr);
|
||||
* @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);
|
||||
#define i2s_hal_get_rx_pdm_dsr(hal, dsr) i2s_ll_get_pdm_rx_dsr((hal)->dev, dsr)
|
||||
#endif
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
@ -383,28 +428,6 @@ void i2s_hal_get_rx_pdm_dsr(i2s_hal_context_t *hal, i2s_pdm_dsr_t *dsr);
|
||||
* @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
|
||||
|
@ -24,17 +24,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S port number, the max port number is (I2S_NUM_MAX -1).
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_NUM_0 = 0, /*!< I2S port 0 */
|
||||
#if SOC_I2S_NUM > 1
|
||||
I2S_NUM_1 = 1, /*!< I2S port 1 */
|
||||
#endif
|
||||
I2S_NUM_MAX, /*!< I2S port max */
|
||||
} i2s_port_t;
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per sample.
|
||||
*
|
||||
@ -55,81 +44,67 @@ typedef enum {
|
||||
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_EQU_SAMPLE = (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.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CHANNEL_MONO = 1, /*!< I2S 1 channel (mono)*/
|
||||
I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/
|
||||
// I2S_CHANNEL_MONO and I2S_CHANNEL_STEREO values are changed to be compatible with TDM mode
|
||||
// The lower 16 bits is for enabling specific channels
|
||||
// The highest bit in I2S_CHANNEL_MONO is for differentiating I2S_CHANNEL_MONO and I2S_CHANNEL_STEREO because they both use two channels
|
||||
// Two channels will transmit same data in I2S_CHANNEL_MONO mode, and different data in I2S_CHANNEL_STEREO mode
|
||||
I2S_CHANNEL_MONO = (0x01 << 31) | 0x03, /*!< I2S channel (mono), two channel enabled */
|
||||
I2S_CHANNEL_STEREO = 0x03, /*!< I2S channel (stereo), two channel enabled */
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
// Bit map of active chan.
|
||||
// There are 16 channels in TDM mode.
|
||||
// For TX module, only the active channel send the audio data, the inactive channel send a constant(configurable) or will be skiped if 'skip_msk_en' in 'i2s_hal_tdm_flags_t' is set.
|
||||
// For RX module, only receive the audio data in active channels, the data in inactive channels will be ignored.
|
||||
// the bit map of active channel can not exceed (0x1<<total_chan_num).
|
||||
// e.g: active_chan_mask = (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH3), here the active_chan_number is 2 and total_chan_num is not supposed to be smaller than 4.
|
||||
I2S_TDM_ACTIVE_CH0 = (0x1 << 0), /*!< I2S channel 0 enabled */
|
||||
I2S_TDM_ACTIVE_CH1 = (0x1 << 1), /*!< I2S channel 1 enabled */
|
||||
I2S_TDM_ACTIVE_CH2 = (0x1 << 2), /*!< I2S channel 2 enabled */
|
||||
I2S_TDM_ACTIVE_CH3 = (0x1 << 3), /*!< I2S channel 3 enabled */
|
||||
I2S_TDM_ACTIVE_CH4 = (0x1 << 4), /*!< I2S channel 4 enabled */
|
||||
I2S_TDM_ACTIVE_CH5 = (0x1 << 5), /*!< I2S channel 5 enabled */
|
||||
I2S_TDM_ACTIVE_CH6 = (0x1 << 6), /*!< I2S channel 6 enabled */
|
||||
I2S_TDM_ACTIVE_CH7 = (0x1 << 7), /*!< I2S channel 7 enabled */
|
||||
I2S_TDM_ACTIVE_CH8 = (0x1 << 8), /*!< I2S channel 8 enabled */
|
||||
I2S_TDM_ACTIVE_CH9 = (0x1 << 9), /*!< I2S channel 9 enabled */
|
||||
I2S_TDM_ACTIVE_CH10 = (0x1 << 10), /*!< I2S channel 10 enabled */
|
||||
I2S_TDM_ACTIVE_CH11 = (0x1 << 11), /*!< I2S channel 11 enabled */
|
||||
I2S_TDM_ACTIVE_CH12 = (0x1 << 12), /*!< I2S channel 12 enabled */
|
||||
I2S_TDM_ACTIVE_CH13 = (0x1 << 13), /*!< I2S channel 13 enabled */
|
||||
I2S_TDM_ACTIVE_CH14 = (0x1 << 14), /*!< I2S channel 14 enabled */
|
||||
I2S_TDM_ACTIVE_CH15 = (0x1 << 15), /*!< I2S channel 15 enabled */
|
||||
#endif
|
||||
} 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 {
|
||||
I2S_COMM_FORMAT_STAND_I2S = 0X01, /*!< I2S communication I2S Philips standard, data launch at second BCK*/
|
||||
I2S_COMM_FORMAT_STAND_MSB = 0X02, /*!< I2S communication MSB alignment standard, data launch at first BCK*/
|
||||
I2S_COMM_FORMAT_STAND_I2S = 0X01, /*!< I2S communication I2S Philips standard, data launch at second 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;
|
||||
|
||||
/**
|
||||
@ -141,24 +116,27 @@ typedef enum {
|
||||
I2S_CHANNEL_FMT_ALL_LEFT,
|
||||
I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
} i2s_channel_fmt_t;
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
I2S_CHANNEL_FMT_TDM, // Up to 16 channels
|
||||
#endif
|
||||
} i2s_channel_fmt_t;
|
||||
|
||||
/**
|
||||
* @brief I2S Mode
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODE_MASTER = 1, /*!< Master mode*/
|
||||
I2S_MODE_SLAVE = 2, /*!< Slave mode*/
|
||||
I2S_MODE_TX = 4, /*!< TX mode*/
|
||||
I2S_MODE_RX = 8, /*!< RX mode*/
|
||||
I2S_MODE_MASTER = (0x1 << 0), /*!< Master mode*/
|
||||
I2S_MODE_SLAVE = (0x1 << 1), /*!< Slave mode*/
|
||||
I2S_MODE_TX = (0x1 << 2), /*!< TX mode*/
|
||||
I2S_MODE_RX = (0x1 << 3), /*!< 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*/
|
||||
I2S_MODE_DAC_BUILT_IN = (0x1 << 4), /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
I2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTS_PDM
|
||||
//PDM functions are only supported on I2S0.
|
||||
I2S_MODE_PDM = 64, /*!< I2S PDM mode*/
|
||||
// PDM functions are only supported on I2S0 (all chips).
|
||||
I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
|
||||
#endif
|
||||
} i2s_mode_t;
|
||||
|
||||
@ -170,27 +148,6 @@ typedef enum {
|
||||
I2S_CLK_APLL, /*!< Clock from APLL*/
|
||||
} i2s_clock_src_t;
|
||||
|
||||
/**
|
||||
* @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, 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 */
|
||||
#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.
|
||||
@ -206,17 +163,6 @@ typedef enum {
|
||||
} i2s_dac_mode_t;
|
||||
#endif //SOC_I2S_SUPPORTS_ADC_DAC
|
||||
|
||||
/**
|
||||
* @brief I2S pin number for i2s_set_pin
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int bck_io_num; /*!< BCK in out pin*/
|
||||
int ws_io_num; /*!< WS in out pin*/
|
||||
int data_out_num; /*!< DATA out pin*/
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief A/U-law decompress or compress configuration.
|
||||
@ -228,7 +174,7 @@ typedef enum {
|
||||
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;
|
||||
} i2s_pcm_mode_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
|
@ -26,7 +26,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2SI_WS_IN_IDX,
|
||||
.data_out_sig = I2SO_SD_OUT_IDX,
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
.irq = ETS_DMA_CH0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -109,7 +109,11 @@
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
#define SOC_I2S_NUM (1)
|
||||
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (0)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) //(SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_TDM (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
|
||||
|
@ -26,7 +26,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2S0I_WS_IN_IDX,
|
||||
.data_out_sig = I2S0O_SD_OUT_IDX,
|
||||
.data_in_sig = I2S0I_SD_IN_IDX,
|
||||
.irq = ETS_DMA_CH0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
},
|
||||
{
|
||||
@ -36,7 +35,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.rx_ws_sig = I2S1I_WS_IN_IDX,
|
||||
.data_out_sig = I2S1O_SD_OUT_IDX,
|
||||
.data_in_sig = I2S1I_SD_IN_IDX,
|
||||
.irq = ETS_DMA_CH3_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -318,8 +318,8 @@ typedef volatile struct {
|
||||
uint32_t reserved12 : 20; /* Reserved*/
|
||||
};
|
||||
uint32_t val;
|
||||
} rxeof_num;
|
||||
uint32_t conf_sigle_data;
|
||||
} rx_eof_num;
|
||||
uint32_t conf_signal_data; /*I2S signal data register*/
|
||||
union {
|
||||
struct {
|
||||
uint32_t tx_idle : 1; /*1: i2s_tx is idle state. 0: i2s_tx is working.*/
|
||||
|
@ -65,7 +65,7 @@
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
#define SOC_I2S_NUM (2)
|
||||
#define SOC_I2S_SUPPORTS_PCM (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (0)
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM (1) //(SOC_I2S_SUPPORTS_PDM_RX | SOC_I2S_SUPPORTS_PDM_TX)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
|
@ -75,13 +75,11 @@ Configuration example:
|
||||
static const int i2s_num = 0; // i2s port number
|
||||
|
||||
static const i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
|
@ -53,25 +53,15 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
#else
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
#endif
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
|
@ -684,24 +684,15 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
#else
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
#endif
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.sample_rate = 44100,
|
||||
.slot_bits_cfg = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.sample_rate = 44100,
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.intr_alloc_flags = 0, //Default interrupt priority
|
||||
|
@ -63,13 +63,11 @@ void example_i2s_init(void)
|
||||
{
|
||||
int i2s_num = EXAMPLE_I2S_NUM;
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.slot_bits_cfg = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN,
|
||||
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
|
||||
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.channel_format = EXAMPLE_I2S_FORMAT,
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
@ -22,13 +23,15 @@
|
||||
#define I2S_NUM (0)
|
||||
#define WAVE_FREQ_HZ (100)
|
||||
#define PI (3.14159265)
|
||||
#define I2S_BCK_IO (GPIO_NUM_13)
|
||||
#define I2S_WS_IO (GPIO_NUM_15)
|
||||
#define I2S_DO_IO (GPIO_NUM_21)
|
||||
#define I2S_BCK_IO (GPIO_NUM_4)
|
||||
#define I2S_WS_IO (GPIO_NUM_5)
|
||||
#define I2S_DO_IO (GPIO_NUM_18)
|
||||
#define I2S_DI_IO (-1)
|
||||
|
||||
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
|
||||
|
||||
static const char* TAG = "i2s_example";
|
||||
|
||||
static void setup_triangle_sine_waves(int bits)
|
||||
{
|
||||
int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4);
|
||||
@ -64,7 +67,7 @@ static void setup_triangle_sine_waves(int bits)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "set clock");
|
||||
i2s_set_clk(I2S_NUM, SAMPLE_RATE, bits, 2);
|
||||
//Using push
|
||||
// for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
|
||||
@ -74,6 +77,7 @@ static void setup_triangle_sine_waves(int bits)
|
||||
// i2s_push_sample(0, &samples_data[i*2], 100);
|
||||
// }
|
||||
// or write
|
||||
ESP_LOGI(TAG, "write data");
|
||||
i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
|
||||
|
||||
free(samples_data);
|
||||
@ -87,20 +91,11 @@ void app_main(void)
|
||||
//if 2-channels, 16-bit each channel, total buffer is 360*4 = 1440 bytes
|
||||
//if 2-channels, 24/32-bit each channel, total buffer is 360*8 = 2880 bytes
|
||||
i2s_config_t i2s_config = {
|
||||
.param_cfg = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.slot_bits_cfg = (I2S_BITS_PER_SLOT_16BIT << SLOT_BIT_SHIFT) | I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
.slot_channel_cfg = (2 << SLOT_CH_SHIFT) | 2,
|
||||
.active_slot_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
|
||||
.left_align_en = false,
|
||||
.big_edin_en = false,
|
||||
.bit_order_msb_en = false,
|
||||
#endif
|
||||
},
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.use_apll = false,
|
||||
|
Loading…
Reference in New Issue
Block a user