mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
driver/i2s: support i2s on c3 and s3
1. Support i2s on esp32c3 and esp32s3 2. Refactor i2s_config_t to avoid breaking change 2. Fix a bug that receiving unavailable values from message queue when dma queue has been re-allocted 4. Support i2s unit test on esp32c3 and esp32s3
This commit is contained in:
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
|
||||
|
Reference in New Issue
Block a user