From 3c57a6ac3641d8d558d42d21f590e0679dbb9482 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 20 Jul 2021 21:03:52 +0800 Subject: [PATCH] driver/i2s: refactor ll and hal --- components/driver/i2s.c | 1170 +++++++++-------- components/driver/include/driver/i2s.h | 43 +- components/driver/test/test_i2s.c | 170 +-- components/hal/esp32/include/hal/i2s_ll.h | 343 ++--- components/hal/esp32c3/include/hal/i2s_ll.h | 288 ++-- components/hal/esp32h2/include/hal/i2s_ll.h | 281 ++-- components/hal/esp32s2/include/hal/i2s_ll.h | 191 ++- components/hal/esp32s3/include/hal/i2s_ll.h | 278 ++-- components/hal/i2s_hal.c | 330 ++--- components/hal/include/hal/i2s_hal.h | 123 +- components/hal/include/hal/i2s_types.h | 42 +- components/soc/esp32c3/include/soc/soc_caps.h | 6 +- components/soc/esp32h2/include/soc/soc_caps.h | 6 +- .../soc/esp32s3/include/soc/i2s_struct.h | 2 +- components/soc/esp32s3/include/soc/soc_caps.h | 1 + docs/en/api-reference/peripherals/i2s.rst | 4 +- 16 files changed, 1871 insertions(+), 1407 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 5857e67bd6..36c4618d5b 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -43,10 +43,10 @@ static const char *TAG = "I2S"; -#define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) +#define I2S_ENTER_CRITICAL_ISR(i2s_num) portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL_ISR(i2s_num) portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) #define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) @@ -119,6 +119,12 @@ static int _i2s_adc_channel = -1; static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma); +/************************************************************** + * I2S GPIO operation * + * - gpio_matrix_out_check_and_set * + * - gpio_matrix_in_check_and_set * + * - i2s_set_pin * + **************************************************************/ static void gpio_matrix_out_check_and_set(int gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { //if pin = -1, do not need to configure @@ -139,443 +145,68 @@ static void gpio_matrix_in_check_and_set(int gpio, uint32_t signal_idx, bool inv } } -float i2s_get_clk(i2s_port_t i2s_num) +esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - return (float)p_i2s[i2s_num]->sample_rate; -} - -static void i2s_tx_reset(i2s_port_t i2s_num) -{ - p_i2s[i2s_num]->tx->curr_ptr = NULL; - p_i2s[i2s_num]->tx->rw_pos = 0; -#if SOC_GDMA_SUPPORTED - gdma_reset(p_i2s[i2s_num]->tx_dma_chan); -#else - //attach DMA - i2s_hal_attach_tx_dma(&(p_i2s[i2s_num]->hal)); - // Reset I2S TX module first, and then, reset DMA and FIFO. - i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_txdma(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); -#endif -} - -static void i2s_rx_reset(i2s_port_t i2s_num) -{ - p_i2s[i2s_num]->rx->curr_ptr = NULL; - p_i2s[i2s_num]->rx->rw_pos = 0; -#if SOC_GDMA_SUPPORTED - gdma_reset(p_i2s[i2s_num]->rx_dma_chan); -#else - //attach DMA - i2s_hal_attach_rx_dma(&(p_i2s[i2s_num]->hal)); - // Reset I2S RX module first, and then, reset DMA and FIFO. - i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_rxdma(&(p_i2s[i2s_num]->hal)); - i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); -#endif -} - -static void i2s_tx_start(i2s_port_t i2s_num) -{ -#if SOC_GDMA_SUPPORTED - gdma_start(p_i2s[i2s_num]->tx_dma_chan, (uint32_t) p_i2s[i2s_num]->tx->desc[0]); -#else - i2s_hal_enable_tx_intr(&(p_i2s[i2s_num]->hal)); - i2s_hal_start_tx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->tx->desc[0]); -#endif - i2s_hal_start_tx(&(p_i2s[i2s_num]->hal)); -} - -static void i2s_rx_start(i2s_port_t i2s_num) -{ -#if SOC_GDMA_SUPPORTED - gdma_start(p_i2s[i2s_num]->rx_dma_chan, (uint32_t) p_i2s[i2s_num]->rx->desc[0]); -#else - i2s_hal_enable_rx_intr(&(p_i2s[i2s_num]->hal)); - i2s_hal_start_rx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->rx->desc[0]); -#endif - i2s_hal_start_rx(&(p_i2s[i2s_num]->hal)); -} - -static void i2s_tx_stop(i2s_port_t i2s_num) -{ -#if SOC_GDMA_SUPPORTED - gdma_stop(p_i2s[i2s_num]->tx_dma_chan); -#else - i2s_hal_stop_tx_link(&(p_i2s[i2s_num]->hal)); - i2s_hal_stop_tx(&(p_i2s[i2s_num]->hal)); - i2s_hal_disable_tx_intr(&(p_i2s[i2s_num]->hal)); -#endif -} - -static void i2s_rx_stop(i2s_port_t i2s_num) -{ -#if SOC_GDMA_SUPPORTED - gdma_stop(p_i2s[i2s_num]->rx_dma_chan); -#else - i2s_hal_stop_rx_link(&(p_i2s[i2s_num]->hal)); - i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); - i2s_hal_disable_rx_intr(&(p_i2s[i2s_num]->hal)); -#endif -} - -#if SOC_I2S_SUPPORTS_APLL -static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) -{ - int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; - -#if CONFIG_IDF_TARGET_ESP32 - /* ESP32 rev0 silicon issue for APLL range/accuracy, please see ESP32 ECO document for more information on this */ - if (esp_efuse_get_chip_ver() == 0) { - sdm0 = 0; - sdm1 = 0; - } -#endif - float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4); - if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) { - return SOC_I2S_APLL_MAX_FREQ; - } - float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1) - return fpll / 2; -} - -/** - * @brief APLL calculate function, was described by following: - * APLL Output frequency is given by the formula: - * - * apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) - * apll_freq = fout / ((o_div + 2) * 2) - * - * The dividend in this expression should be in the range of 240 - 600 MHz. - * In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0. - * * sdm0 frequency adjustment parameter, 0..255 - * * sdm1 frequency adjustment parameter, 0..255 - * * sdm2 frequency adjustment parameter, 0..63 - * * o_div frequency divider, 0..31 - * - * The most accurate way to find the sdm0..2 and odir parameters is to loop through them all, - * then apply the above formula, finding the closest frequency to the desired one. - * But 256*256*64*32 = 134.217.728 loops are too slow with ESP32 - * 1. We will choose the parameters with the highest level of change, - * With 350MHzchannel_num != ch) { - p_i2s[i2s_num]->channel_num = (ch == 2) ? 2 : 1; - } - - i2s_dma_t *save_tx = NULL, *save_rx = NULL; - - if (data_bits != p_i2s[i2s_num]->bits_per_sample) { - p_i2s[i2s_num]->bits_per_sample = data_bits; - - // Round bytes_per_sample up to next multiple of 16 bits - int halfwords_per_sample = (data_bits + 15) / 16; - p_i2s[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; - - // Because limited of DMA buffer is 4092 bytes - if (p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->bytes_per_sample * p_i2s[i2s_num]->channel_num > 4092) { - p_i2s[i2s_num]->dma_buf_len = 4092 / p_i2s[i2s_num]->bytes_per_sample / p_i2s[i2s_num]->channel_num; - } - - // Re-create TX DMA buffer - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - save_tx = p_i2s[i2s_num]->tx; - //destroy old tx dma if exist - if (save_tx) { - i2s_destroy_dma_queue(i2s_num, save_tx); - } - p_i2s[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); - if (p_i2s[i2s_num]->tx == NULL) { - ESP_LOGE(TAG, "Failed to create tx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - } - // Re-create RX DMA buffer - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - save_rx = p_i2s[i2s_num]->rx; - //destroy old rx dma if exist - if (save_rx) { - i2s_destroy_dma_queue(i2s_num, save_rx); - } - p_i2s[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); - if (p_i2s[i2s_num]->rx == NULL) { - ESP_LOGE(TAG, "Failed to create rx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->channel_num * p_i2s[i2s_num]->bytes_per_sample); - } - } - return ESP_OK; -} - -static esp_err_t i2s_fbclk_cal(int i2s_num, uint32_t rate, int channel, int channel_bit, uint32_t *sclk, uint32_t *fbck, uint32_t *bck_div) -{ - //Default select I2S_D2CLK (160M) - uint32_t _sclk = I2S_LL_BASE_CLK; - uint32_t _fbck = rate * channel * channel_bit; - uint32_t _bck_div = (256 % channel_bit) ? 12 : 8; - i2s_clock_src_t clk_src = I2S_CLK_D2CLK; - -//ADC mode only support on ESP32, + if (pin == NULL) { #if SOC_I2S_SUPPORTS_ADC_DAC - if ( p_i2s[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - _fbck = rate * I2S_LL_AD_BCK_FACTOR * 2; - _bck_div = I2S_LL_AD_BCK_FACTOR; - } -#endif // SOC_I2S_SUPPORTS_ADC_DAC - - if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) { -#if SOC_I2S_SUPPORTS_PDM_TX - if ( p_i2s[i2s_num]->mode & I2S_MODE_TX) { - int fp = 1; - int fs = 1; - i2s_hal_get_tx_pdm_fpfs(&(p_i2s[i2s_num]->hal), &fp, &fs); - _fbck = rate * I2S_LL_PDM_BCK_FACTOR * fp / fs; - } -#endif //SOC_I2S_SUPPORTS_PDM_TX -#if SOC_I2S_SUPPORTS_PDM_RX - if ( p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_pdm_dsr_t dsr; - i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr); - _fbck = rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1); - } -#endif // SOC_I2S_SUPPORTS_PDM_RX - _bck_div = 8; - } - -#if SOC_I2S_SUPPORTS_APLL - int sdm0 = 0; - int sdm1 = 0; - int sdm2 = 0; - int odir = 0; - //If APLL is specified, try to calculate in APLL - if (p_i2s[i2s_num]->use_apll && i2s_apll_calculate_fi2s(p_i2s[i2s_num]->fixed_mclk, channel_bit, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { - _sclk = p_i2s[i2s_num]->fixed_mclk; - clk_src = I2S_CLK_APLL; - ESP_LOGD(TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); - rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir); - } -#endif // SOC_I2S_SUPPORTS_APLL - if ((_fbck * _bck_div) > _sclk) { - ESP_LOGE(TAG, "sample rate is too large\r\n"); - return ESP_ERR_INVALID_ARG; - } - i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), clk_src); - *sclk = _sclk; - *fbck = _fbck; - *bck_div = _bck_div; - return ESP_OK; -} - -static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg) -{ - switch (hal_cfg->chan_fmt) { - case I2S_CHANNEL_FMT_RIGHT_LEFT: //fall through - case I2S_CHANNEL_FMT_ALL_RIGHT: //fall through - case I2S_CHANNEL_FMT_ALL_LEFT: - return 2; - case I2S_CHANNEL_FMT_ONLY_RIGHT: //fall through - case I2S_CHANNEL_FMT_ONLY_LEFT: - return 1; -#if SOC_I2S_SUPPORTS_TDM - case I2S_CHANNEL_FMT_TDM: { - uint32_t num = 0; - uint32_t max_chan = 0; - uint32_t chan_mask = hal_cfg->chan_mask; - - for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) { - if ((chan_mask & 0x01) == 1) { - num++; - max_chan = i + 1; - } - } - if (max_chan > hal_cfg->total_chan) { - hal_cfg->total_chan = max_chan; - } - return num; - } -#endif - default: - return 0; - } -} - -esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch) -{ - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_ARG, TAG, "Not initialized yet"); - - i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; - int data_bits = 0; - int chan_bits = 0; - int active_chan_num = 0; - int chan_num = 0; - - cfg->ch = ch; - cfg->sample_rate = rate; - cfg->bits_cfg.val = bits_cfg; - - cfg->bits_cfg.chan_bits = cfg->bits_cfg.chan_bits < cfg->bits_cfg.sample_bits ? - cfg->bits_cfg.sample_bits : cfg->bits_cfg.chan_bits; - chan_bits = cfg->bits_cfg.chan_bits; - data_bits = cfg->bits_cfg.sample_bits; - -#if SOC_I2S_SUPPORTS_TDM - cfg->chan_mask = ch & 0xFFFF; - active_chan_num = i2s_get_active_chan_num(cfg); - chan_num = cfg->total_chan; + return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); #else - active_chan_num = i2s_get_active_chan_num(cfg); - chan_num = ch == I2S_CHANNEL_MONO ? 2 : active_chan_num; + return ESP_ERR_INVALID_ARG; #endif - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - - if ((data_bits % 8 != 0) || (data_bits > I2S_BITS_PER_SAMPLE_32BIT)) { - ESP_LOGE(TAG, "Invalid bits per sample"); + } + if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) { + ESP_LOGE(TAG, "bck_io_num error"); return ESP_ERR_INVALID_ARG; } - //Stop I2S - i2s_stop(i2s_num); - // wait all on-going writing finish - if ((p_i2s[i2s_num]->mode & I2S_MODE_TX) && p_i2s[i2s_num]->tx) { - xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) { + ESP_LOGE(TAG, "ws_io_num error"); + return ESP_ERR_INVALID_ARG; } - if ((p_i2s[i2s_num]->mode & I2S_MODE_RX) && p_i2s[i2s_num]->rx) { - xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) { + ESP_LOGE(TAG, "data_out_num error"); + return ESP_ERR_INVALID_ARG; } - //malloc DMA buffer - if (i2s_alloc_dma_buffer(i2s_num, data_bits, active_chan_num) != ESP_OK ) { - return ESP_ERR_NO_MEM; + if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) { + ESP_LOGE(TAG, "data_in_num error"); + return ESP_ERR_INVALID_ARG; } - - uint32_t i2s_clk = 0; // I2S source clock - uint32_t i2s_bck = 0; // I2S back clock - uint32_t bck_div = 0; // I2S bck div - //calculate bck_div, f_bck and select source clock - if (i2s_fbclk_cal(i2s_num, rate, chan_num, chan_bits, &i2s_clk, &i2s_bck, &bck_div) != ESP_OK) { - return ESP_FAIL; - } - //configure i2s clock - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); - i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); - // wait all writing on-going finish - if (p_i2s[i2s_num]->tx) { - xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + if (p_i2s[i2s_num]->mode & I2S_MODE_SLAVE) { + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0); + } else { + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0); + } + } else { + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0, 0); + } else { + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0, 0); } } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); - i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); - // wait all writing on-going finish - if (p_i2s[i2s_num]->rx) { - xSemaphoreGive(p_i2s[i2s_num]->rx->mux); - } - } - i2s_hal_samples_config(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); - // Reset message queue to avoid receiving unavailable values because the old dma queque has been destroyed - if (p_i2s[i2s_num]->tx) { - xQueueReset(p_i2s[i2s_num]->tx->queue); - } - if (p_i2s[i2s_num]->rx) { - xQueueReset(p_i2s[i2s_num]->rx->queue); - } - - //I2S start - i2s_start(i2s_num); - p_i2s[i2s_num]->sample_rate = rate; + gpio_matrix_out_check_and_set(pin->data_out_num, i2s_periph_signal[i2s_num].data_out_sig, 0, 0); + gpio_matrix_in_check_and_set(pin->data_in_num, i2s_periph_signal[i2s_num].data_in_sig, 0); return ESP_OK; } + +/************************************************************** + * I2S DMA operation * + * - i2s_dma_rx_callback * + * - i2s_dma_tx_callback * + * - i2s_intr_handler_default * + * - i2s_tx_reset * + * - i2s_rx_reset * + * - i2s_tx_start * + * - i2s_rx_start * + * - i2s_tx_stop * + * - i2s_rx_stop * + **************************************************************/ + #if SOC_GDMA_SUPPORTED static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { @@ -635,8 +266,7 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e static void IRAM_ATTR i2s_intr_handler_default(void *arg) { i2s_obj_t *p_i2s = (i2s_obj_t *) arg; - uint32_t status; - i2s_hal_get_intr_status(&(p_i2s->hal), &status); + uint32_t status = i2s_hal_get_intr_status(&(p_i2s->hal)); if (status == 0) { //Avoid spurious interrupt return; @@ -702,6 +332,148 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } #endif +static void i2s_tx_reset(i2s_port_t i2s_num) +{ + p_i2s[i2s_num]->tx->curr_ptr = NULL; + p_i2s[i2s_num]->tx->rw_pos = 0; +#if SOC_GDMA_SUPPORTED + // gdma_stop(p_i2s[i2s_num]->tx_dma_chan); + i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); + gdma_reset(p_i2s[i2s_num]->tx_dma_chan); + i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); +#else + // Reset I2S TX module first, and then, reset DMA and FIFO. + i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); + i2s_hal_reset_txdma(&(p_i2s[i2s_num]->hal)); + i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); +#endif +} + +static void i2s_rx_reset(i2s_port_t i2s_num) +{ + p_i2s[i2s_num]->rx->curr_ptr = NULL; + p_i2s[i2s_num]->rx->rw_pos = 0; +#if SOC_GDMA_SUPPORTED + i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); + gdma_reset(p_i2s[i2s_num]->rx_dma_chan); + i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); +#else + + // Reset I2S RX module first, and then, reset DMA and FIFO. + i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); + i2s_hal_reset_rxdma(&(p_i2s[i2s_num]->hal)); + i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); +#endif +} + +static void i2s_tx_start(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_start(p_i2s[i2s_num]->tx_dma_chan, (uint32_t) p_i2s[i2s_num]->tx->desc[0]); +#else + i2s_hal_enable_tx_dma(&(p_i2s[i2s_num]->hal)); + i2s_hal_enable_tx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_start_tx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->tx->desc[0]); +#endif + i2s_hal_start_tx(&(p_i2s[i2s_num]->hal)); +} + +static void i2s_rx_start(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_start(p_i2s[i2s_num]->rx_dma_chan, (uint32_t) p_i2s[i2s_num]->rx->desc[0]); +#else + i2s_hal_enable_rx_dma(&(p_i2s[i2s_num]->hal)); + i2s_hal_enable_rx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_start_rx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->rx->desc[0]); +#endif + i2s_hal_start_rx(&(p_i2s[i2s_num]->hal)); +} + +static void i2s_tx_stop(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_stop(p_i2s[i2s_num]->tx_dma_chan); +#else + i2s_hal_stop_tx_link(&(p_i2s[i2s_num]->hal)); + i2s_hal_stop_tx(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_tx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_tx_dma(&(p_i2s[i2s_num]->hal)); +#endif +} + +static void i2s_rx_stop(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_stop(p_i2s[i2s_num]->rx_dma_chan); +#else + i2s_hal_stop_rx_link(&(p_i2s[i2s_num]->hal)); + i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_rx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_rx_dma(&(p_i2s[i2s_num]->hal)); +#endif +} + +/************************************************************** + * I2S buffer operation * + * - i2s_alloc_dma_buffer * + * - i2s_destroy_dma_queue * + * - i2s_create_dma_queue * + * - i2s_zero_dma_buffer * + **************************************************************/ +static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, int data_bits, int ch) +{ + if (p_i2s[i2s_num]->channel_num != ch) { + p_i2s[i2s_num]->channel_num = (ch == 2) ? 2 : 1; + } + + i2s_dma_t *save_tx = NULL, *save_rx = NULL; + + if (data_bits != p_i2s[i2s_num]->bits_per_sample) { + p_i2s[i2s_num]->bits_per_sample = data_bits; + + // Round bytes_per_sample up to next multiple of 16 bits + int halfwords_per_sample = (data_bits + 15) / 16; + p_i2s[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; + + // Because limited of DMA buffer is 4092 bytes + if (p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->bytes_per_sample * p_i2s[i2s_num]->channel_num > 4092) { + p_i2s[i2s_num]->dma_buf_len = 4092 / p_i2s[i2s_num]->bytes_per_sample / p_i2s[i2s_num]->channel_num; + } + + // Re-create TX DMA buffer + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + save_tx = p_i2s[i2s_num]->tx; + //destroy old tx dma if exist + if (save_tx) { + i2s_destroy_dma_queue(i2s_num, save_tx); + } + p_i2s[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); + if (p_i2s[i2s_num]->tx == NULL) { + ESP_LOGE(TAG, "Failed to create tx dma buffer"); + i2s_driver_uninstall(i2s_num); + return ESP_ERR_NO_MEM; + } + } + // Re-create RX DMA buffer + if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + save_rx = p_i2s[i2s_num]->rx; + //destroy old rx dma if exist + if (save_rx) { + i2s_destroy_dma_queue(i2s_num, save_rx); + } + p_i2s[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s[i2s_num]->dma_buf_count, p_i2s[i2s_num]->dma_buf_len); + if (p_i2s[i2s_num]->rx == NULL) { + ESP_LOGE(TAG, "Failed to create rx dma buffer"); + i2s_driver_uninstall(i2s_num); + return ESP_ERR_NO_MEM; + } + i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->dma_buf_len * p_i2s[i2s_num]->channel_num * p_i2s[i2s_num]->bytes_per_sample); + } + } + return ESP_OK; +} + static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) { int bux_idx; @@ -794,50 +566,273 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in return dma; } -esp_err_t i2s_start(i2s_port_t i2s_num) +esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - //start DMA link - I2S_ENTER_CRITICAL(); - -#if !SOC_GDMA_SUPPORTED - esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); - i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX); -#endif - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_tx_reset(i2s_num); - i2s_tx_start(i2s_num); + if (p_i2s[i2s_num]->rx && p_i2s[i2s_num]->rx->buf != NULL && p_i2s[i2s_num]->rx->buf_size != 0) { + for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { + memset(p_i2s[i2s_num]->rx->buf[i], 0, p_i2s[i2s_num]->rx->buf_size); + } } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_rx_reset(i2s_num); - i2s_rx_start(i2s_num); + if (p_i2s[i2s_num]->tx && p_i2s[i2s_num]->tx->buf != NULL && p_i2s[i2s_num]->tx->buf_size != 0) { + int bytes_left = 0; + bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4; + if (bytes_left) { + size_t zero_bytes = 0, bytes_written; + i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); + } + for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { + memset(p_i2s[i2s_num]->tx->buf[i], 0, p_i2s[i2s_num]->tx->buf_size); + } } -#if !SOC_GDMA_SUPPORTED - esp_intr_enable(p_i2s[i2s_num]->i2s_isr_handle); -#endif - I2S_EXIT_CRITICAL(); return ESP_OK; } -esp_err_t i2s_stop(i2s_port_t i2s_num) +/************************************************************** + * I2S clock operation * + * - i2s_get_clk * + * - i2s_apll_get_fi2s * + * - i2s_apll_calculate_fi2s * + * - i2s_fbclk_cal * + **************************************************************/ + +float i2s_get_clk(i2s_port_t i2s_num) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - I2S_ENTER_CRITICAL(); -#if !SOC_GDMA_SUPPORTED - esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); -#endif - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_tx_stop(i2s_num); + return (float)p_i2s[i2s_num]->sample_rate; +} + + +#if SOC_I2S_SUPPORTS_APLL +static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) +{ + int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; + +#if CONFIG_IDF_TARGET_ESP32 + /* ESP32 rev0 silicon issue for APLL range/accuracy, please see ESP32 ECO document for more information on this */ + if (esp_efuse_get_chip_ver() == 0) { + sdm0 = 0; + sdm1 = 0; } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_rx_stop(i2s_num); - } -#if !SOC_GDMA_SUPPORTED - i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX); #endif - I2S_EXIT_CRITICAL(); + float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4); + if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) { + return SOC_I2S_APLL_MAX_FREQ; + } + float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1) + return fpll / 2; +} + +/** + * @brief APLL calculate function, was described by following: + * APLL Output frequency is given by the formula: + * + * apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) + * apll_freq = fout / ((o_div + 2) * 2) + * + * The dividend in this expression should be in the range of 240 - 600 MHz. + * In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0. + * * sdm0 frequency adjustment parameter, 0..255 + * * sdm1 frequency adjustment parameter, 0..255 + * * sdm2 frequency adjustment parameter, 0..63 + * * o_div frequency divider, 0..31 + * + * The most accurate way to find the sdm0..2 and odir parameters is to loop through them all, + * then apply the above formula, finding the closest frequency to the desired one. + * But 256*256*64*32 = 134.217.728 loops are too slow with ESP32 + * 1. We will choose the parameters with the highest level of change, + * With 350MHzmode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + _fbck = rate * I2S_LL_AD_BCK_FACTOR * 2; + _bck_div = I2S_LL_AD_BCK_FACTOR; + } +#endif // SOC_I2S_SUPPORTS_ADC_DAC + + if ( p_i2s[i2s_num]->mode & I2S_MODE_PDM) { +#if SOC_I2S_SUPPORTS_PDM_TX + if ( p_i2s[i2s_num]->mode & I2S_MODE_TX) { + int fp = i2s_hal_get_tx_pdm_fp(&(p_i2s[i2s_num]->hal)); + int fs = i2s_hal_get_tx_pdm_fs(&(p_i2s[i2s_num]->hal)); + _fbck = rate * I2S_LL_PDM_BCK_FACTOR * fp / fs; + } +#endif //SOC_I2S_SUPPORTS_PDM_TX +#if SOC_I2S_SUPPORTS_PDM_RX + if ( p_i2s[i2s_num]->mode & I2S_MODE_RX) { + i2s_pdm_dsr_t dsr; + i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr); + _fbck = rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1); + } +#endif // SOC_I2S_SUPPORTS_PDM_RX + _bck_div = 8; + } + +#if SOC_I2S_SUPPORTS_APLL + int sdm0 = 0; + int sdm1 = 0; + int sdm2 = 0; + int odir = 0; + //If APLL is specified, try to calculate in APLL + if (p_i2s[i2s_num]->use_apll && i2s_apll_calculate_fi2s(p_i2s[i2s_num]->fixed_mclk, channel_bit, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { + _sclk = p_i2s[i2s_num]->fixed_mclk; + clk_src = I2S_CLK_APLL; + ESP_LOGD(TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); + rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir); + } +#endif // SOC_I2S_SUPPORTS_APLL + if ((_fbck * _bck_div) > _sclk) { + ESP_LOGE(TAG, "sample rate is too large\r\n"); + return ESP_ERR_INVALID_ARG; + } + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), clk_src); + *sclk = _sclk; + *fbck = _fbck; + *bck_div = _bck_div; + return ESP_OK; +} + +/************************************************************** + * I2S configuration * + * - i2s_get_active_chan_num * + * - i2s_set_dac_mode * + * - _i2s_adc_mode_recover * + * - i2s_set_adc_mode * + * - i2s_adc_enable * + * - i2s_adc_disable * + * - i2s_set_sample_rates * + * - i2s_pcm_config * + * - i2s_set_pdm_rx_down_sample * + * - i2s_set_pdm_tx_up_sample * + * - i2s_check_cfg_static * + * - i2s_param_config * + * - i2s_set_clk * + * - i2s_set_mode * + **************************************************************/ + +static uint32_t i2s_get_active_chan_num(i2s_hal_config_t *hal_cfg) +{ + switch (hal_cfg->chan_fmt) { + case I2S_CHANNEL_FMT_RIGHT_LEFT: //fall through + case I2S_CHANNEL_FMT_ALL_RIGHT: //fall through + case I2S_CHANNEL_FMT_ALL_LEFT: + return 2; + case I2S_CHANNEL_FMT_ONLY_RIGHT: //fall through + case I2S_CHANNEL_FMT_ONLY_LEFT: + return 1; +#if SOC_I2S_SUPPORTS_TDM + case I2S_CHANNEL_FMT_MULTIPLE: { + uint32_t num = 0; + uint32_t max_chan = 0; + uint32_t chan_mask = hal_cfg->chan_mask; + + for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) { + if ((chan_mask & 0x01) == 1) { + num++; + max_chan = i + 1; + } + } + if (max_chan > hal_cfg->total_chan) { + hal_cfg->total_chan = max_chan; + } + return num; + } +#endif + default: + return 0; + } +} #if SOC_I2S_SUPPORTS_ADC_DAC esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) @@ -901,53 +896,6 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) } #endif -esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) -{ - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - if (pin == NULL) { -#if SOC_I2S_SUPPORTS_ADC_DAC - return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); -#else - return ESP_ERR_INVALID_ARG; -#endif - } - if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) { - ESP_LOGE(TAG, "bck_io_num error"); - return ESP_FAIL; - } - if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) { - ESP_LOGE(TAG, "ws_io_num error"); - return ESP_FAIL; - } - if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) { - ESP_LOGE(TAG, "data_out_num error"); - return ESP_FAIL; - } - if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) { - ESP_LOGE(TAG, "data_in_num error"); - return ESP_FAIL; - } - if (p_i2s[i2s_num]->mode & I2S_MODE_SLAVE) { - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0); - gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0); - } else { - gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0); - gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0); - } - } else { - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].tx_ws_sig, 0, 0); - gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].tx_bck_sig, 0, 0); - } else { - gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].rx_ws_sig, 0, 0); - gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].rx_bck_sig, 0, 0); - } - } - gpio_matrix_out_check_and_set(pin->data_out_num, i2s_periph_signal[i2s_num].data_out_sig, 0, 0); - gpio_matrix_in_check_and_set(pin->data_in_num, i2s_periph_signal[i2s_num].data_in_sig, 0); - return ESP_OK; -} esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) { @@ -956,11 +904,31 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) return i2s_set_clk(i2s_num, rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); } +#if SOC_I2S_SUPPORTS_PCM +esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg) +{ + ESP_RETURN_ON_FALSE(!p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->communication_format & I2S_COMM_FORMAT_STAND_PCM_SHORT), + ESP_ERR_INVALID_ARG, TAG, "i2s communication mode is not PCM mode"); + i2s_stop(i2s_num); + if (pcm_cfg->mode & I2S_MODE_TX) { + i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); + } else if(pcm_cfg->mode & I2S_MODE_RX) { + i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); + } + i2s_start(i2s_num); + return ESP_OK; +} +#endif + #if SOC_I2S_SUPPORTS_PDM_RX esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr) { - ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE(!p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + i2s_stop(i2s_num); i2s_hal_set_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), dsr); + // i2s will start in 'i2s_set_clk' return i2s_set_clk(i2s_num, p_i2s[i2s_num]->sample_rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); } #endif @@ -968,9 +936,11 @@ 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 esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, int sample_rate, int fp, int fs) { - I2S_ENTER_CRITICAL(); + ESP_RETURN_ON_FALSE(!p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + i2s_stop(i2s_num); i2s_hal_set_tx_pdm_fpfs(&(p_i2s[i2s_num]->hal), fp, fs); - I2S_EXIT_CRITICAL(); + // i2s will start in 'i2s_set_clk' return i2s_set_clk(i2s_num, sample_rate, p_i2s[i2s_num]->bits_per_sample, p_i2s[i2s_num]->channel_num); } #endif @@ -1022,25 +992,148 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num) return ESP_OK; } -esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) +esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch) { ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); - if (p_i2s[i2s_num]->rx && p_i2s[i2s_num]->rx->buf != NULL && p_i2s[i2s_num]->rx->buf_size != 0) { - for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { - memset(p_i2s[i2s_num]->rx->buf[i], 0, p_i2s[i2s_num]->rx->buf_size); - } + ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_ARG, TAG, "Not initialized yet"); + + i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; + int data_bits = 0; + int chan_bits = 0; + int active_chan_num = 0; + int chan_num = 0; + + cfg->ch = ch; + cfg->sample_rate = rate; + cfg->bits_cfg.val = bits_cfg; + + cfg->bits_cfg.chan_bits = cfg->bits_cfg.chan_bits < cfg->bits_cfg.sample_bits ? + cfg->bits_cfg.sample_bits : cfg->bits_cfg.chan_bits; + chan_bits = cfg->bits_cfg.chan_bits; + data_bits = cfg->bits_cfg.sample_bits; + +#if SOC_I2S_SUPPORTS_TDM + cfg->chan_mask = ch & 0xFFFF; + active_chan_num = i2s_get_active_chan_num(cfg); + chan_num = cfg->total_chan; +#else + active_chan_num = i2s_get_active_chan_num(cfg); + chan_num = ch == I2S_CHANNEL_MONO ? 2 : active_chan_num; +#endif + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + + if ((data_bits % 8 != 0) || (data_bits > I2S_BITS_PER_SAMPLE_32BIT)) { + ESP_LOGE(TAG, "Invalid bits per sample"); + return ESP_ERR_INVALID_ARG; } - if (p_i2s[i2s_num]->tx && p_i2s[i2s_num]->tx->buf != NULL && p_i2s[i2s_num]->tx->buf_size != 0) { - int bytes_left = 0; - bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4; - if (bytes_left) { - size_t zero_bytes = 0, bytes_written; - i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); - } - for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { - memset(p_i2s[i2s_num]->tx->buf[i], 0, p_i2s[i2s_num]->tx->buf_size); - } + //Stop I2S + i2s_stop(i2s_num); + // wait all on-going writing finish + if ((p_i2s[i2s_num]->mode & I2S_MODE_TX) && p_i2s[i2s_num]->tx) { + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); } + if ((p_i2s[i2s_num]->mode & I2S_MODE_RX) && p_i2s[i2s_num]->rx) { + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + } + //malloc DMA buffer + if (i2s_alloc_dma_buffer(i2s_num, data_bits, active_chan_num) != ESP_OK ) { + return ESP_ERR_NO_MEM; + } + + uint32_t i2s_clk = 0; // I2S source clock + uint32_t i2s_bck = 0; // I2S back clock + uint32_t bck_div = 0; // I2S bck div + //calculate bck_div, f_bck and select source clock + if (i2s_fbclk_cal(i2s_num, rate, chan_num, chan_bits, &i2s_clk, &i2s_bck, &bck_div) != ESP_OK) { + return ESP_FAIL; + } + //configure i2s clock + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); + i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); + // wait all writing on-going finish + if (p_i2s[i2s_num]->tx) { + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + } + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } + if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), i2s_clk, i2s_bck, bck_div); + i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), chan_bits, data_bits); + // wait all writing on-going finish + if (p_i2s[i2s_num]->rx) { + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + } + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } + // Reset message queue to avoid receiving unavailable values because the old dma queque has been destroyed + if (p_i2s[i2s_num]->tx) { + xQueueReset(p_i2s[i2s_num]->tx->queue); + } + if (p_i2s[i2s_num]->rx) { + xQueueReset(p_i2s[i2s_num]->rx->queue); + } + + //I2S start + i2s_start(i2s_num); + p_i2s[i2s_num]->sample_rate = rate; + return ESP_OK; +} + + + +/************************************************************** + * I2S driver operation * + * - i2s_start * + * - i2s_stop * + * - i2s_driver_install * + * - i2s_write * + * - i2s_write_expand * + * - i2s_read * + **************************************************************/ + +esp_err_t i2s_start(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + //start DMA link + I2S_ENTER_CRITICAL(i2s_num); + +#if !SOC_GDMA_SUPPORTED + esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); + i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX); +#endif + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + i2s_tx_reset(i2s_num); + i2s_tx_start(i2s_num); + } + if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + i2s_rx_reset(i2s_num); + i2s_rx_start(i2s_num); + } +#if !SOC_GDMA_SUPPORTED + esp_intr_enable(p_i2s[i2s_num]->i2s_isr_handle); +#endif + I2S_EXIT_CRITICAL(i2s_num); + return ESP_OK; +} + +esp_err_t i2s_stop(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + I2S_ENTER_CRITICAL(i2s_num); +#if !SOC_GDMA_SUPPORTED + esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); +#endif + if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { + i2s_tx_stop(i2s_num); + } + if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { + i2s_rx_stop(i2s_num); + } +#if !SOC_GDMA_SUPPORTED + i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX); +#endif + I2S_EXIT_CRITICAL(i2s_num); return ESP_OK; } @@ -1088,16 +1181,16 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, active_chan = 2; break; case I2S_CHANNEL_FMT_ONLY_RIGHT: - p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0; + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align_en ? I2S_TDM_ACTIVE_CH1 : I2S_TDM_ACTIVE_CH0; p_i2s[i2s_num]->hal_cfg.total_chan = 1; active_chan = 1; break; case I2S_CHANNEL_FMT_ONLY_LEFT: - p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->tdm_flags.left_align_en ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1; + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->left_align_en ? I2S_TDM_ACTIVE_CH0 : I2S_TDM_ACTIVE_CH1; p_i2s[i2s_num]->hal_cfg.total_chan = 1; active_chan = 1; break; - case I2S_CHANNEL_FMT_TDM: + case I2S_CHANNEL_FMT_MULTIPLE: ESP_RETURN_ON_FALSE((i2s_config->chan_mask != 0), ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled"); p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask; i2s_get_active_chan_num(&p_i2s[i2s_num]->hal_cfg); @@ -1106,7 +1199,10 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, ESP_LOGE(TAG, "wrong i2s channel format, uninstalled i2s."); goto err; } - p_i2s[i2s_num]->hal_cfg.flags.val = i2s_config->tdm_flags.val; + p_i2s[i2s_num]->hal_cfg.left_align_en = i2s_config->left_align_en; + p_i2s[i2s_num]->hal_cfg.big_edin_en = i2s_config->big_edin_en; + p_i2s[i2s_num]->hal_cfg.bit_order_msb_en = i2s_config->bit_order_msb_en; + p_i2s[i2s_num]->hal_cfg.skip_msk_en = i2s_config->skip_msk_en; #endif // Set I2S driver configurations @@ -1119,18 +1215,6 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, p_i2s[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; -#if SOC_I2S_SUPPORTS_PCM - // Set PCM compress type for PCM communication mode - if (p_i2s[i2s_num]->communication_format & I2S_COMM_FORMAT_STAND_PCM_SHORT) { - if (p_i2s[i2s_num]->mode & I2S_MODE_TX) { - i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), i2s_config->pcm_compress_type); - } - if (p_i2s[i2s_num]->mode & I2S_MODE_RX) { - i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), i2s_config->pcm_compress_type); - } - } -#endif // SOC_I2S_SUPPORTS_PCM - #ifdef CONFIG_PM_ENABLE if (i2s_config->use_apll) { ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock); @@ -1180,7 +1264,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, ESP_GOTO_ON_ERROR(ret, err, TAG, "I2S param configure error"); if (i2s_queue) { p_i2s[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); - ESP_GOTO_ON_ERROR(ret, err, TAG, "I2S queue create failed"); + ESP_GOTO_ON_ERROR(p_i2s[i2s_num]->i2s_queue, err, TAG, "I2S queue create failed"); *((QueueHandle_t *) i2s_queue) = p_i2s[i2s_num]->i2s_queue; ESP_LOGI(TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_i2s[i2s_num]->i2s_queue)); } else { @@ -1375,6 +1459,7 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr, *dest_byte; int bytes_can_read; *bytes_read = 0; @@ -1389,6 +1474,7 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re while (size > 0) { if (p_i2s[i2s_num]->rx->rw_pos == p_i2s[i2s_num]->rx->buf_size || p_i2s[i2s_num]->rx->curr_ptr == NULL) { if (xQueueReceive(p_i2s[i2s_num]->rx->queue, &p_i2s[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } p_i2s[i2s_num]->rx->rw_pos = 0; @@ -1409,5 +1495,5 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re esp_pm_lock_release(p_i2s[i2s_num]->pm_lock); #endif xSemaphoreGive(p_i2s[i2s_num]->rx->mux); - return ESP_OK; + return ret; } diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 5ec6f2841a..c7185bf52a 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -54,9 +54,9 @@ typedef struct { * */ typedef struct { - i2s_pcm_compress_t pcm_mode; /*!< I2S PCM a/u-law decompress or compress mode */ + i2s_mode_t mode; /*!< I2S mode. Usually only need to choose I2S_MODE_TX or I2S_MODE_RX */ + i2s_pcm_compress_t pcm_type; /*!< I2S PCM a/u-law decompress or compress type */ } i2s_pcm_cfg_t; - #endif /** @@ -76,24 +76,15 @@ typedef struct { 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_chan_t bits_per_chan; /*!< 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_PCM - i2s_pcm_compress_t pcm_compress_type; /*!< I2S PCM a/u-law decompress or compress mode. Set this field if `communication_format` is set to `I2S_COMM_FORMAT_STAND_PCM_SHORT` or `I2S_COMM_FORMAT_STAND_PCM_LONG` */ -#endif // SOC_I2S_SUPPORTS_PCM + i2s_bits_per_chan_t bits_per_chan; /*!< I2S total bits in one channel, only take effect when larger than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */ #if SOC_I2S_SUPPORTS_TDM i2s_channel_t chan_mask; /*!< I2S active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1< 1 - case I2S_TEST_MODE_SLAVE_TO_MAXTER: { - esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); + case I2S_TEST_MODE_SLAVE_TO_MAXTER: { + esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); - 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(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, I2S1_DATA_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0); - } - break; + 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; - case I2S_TEST_MODE_MASTER_TO_SLAVE: { - esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); + case I2S_TEST_MODE_MASTER_TO_SLAVE: { + esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); - 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(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, I2S0_DATA_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S1_DATA_IN_IDX, 0); - } - break; + 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, I2S0_DATA_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0); - } - break; + case I2S_TEST_MODE_LOOPBACK: { + 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; - default: { - TEST_FAIL_MESSAGE("error: mode not supported"); - } - break; + default: { + TEST_FAIL_MESSAGE("error: mode not supported"); + } + break; } } @@ -144,7 +144,7 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 60, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; // normal i2s @@ -180,7 +180,7 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -193,29 +193,28 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") i2s_test_io_config(I2S_TEST_MODE_LOOPBACK); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); - uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); + uint8_t *data_wr = (uint8_t *)malloc(sizeof(uint8_t) * 400); size_t i2s_bytes_write = 0; size_t bytes_read = 0; int length = 0; - uint8_t *i2s_read_buff = (uint8_t*)malloc(sizeof(uint8_t)*10000); + uint8_t *i2s_read_buff = (uint8_t *)malloc(sizeof(uint8_t) * 10000); - for(int i=0; i<100; i++) { - data_wr[i] = i+1; + for (int i = 0; i < 100; i++) { + data_wr[i] = i + 1; } - int flag=0; // break loop flag + int flag = 0; // break loop flag 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); - while(!flag){ + i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t) * 400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); + while (!flag) { if (length >= 10000 - 500) { break; } - i2s_read(I2S_NUM_0, i2s_read_buff + length, sizeof(uint8_t)*500, &bytes_read, 1000/portMAX_DELAY); - if(bytes_read>0) { - printf("read data size: %d\n", bytes_read); - for(int i=length; i 0) { + for (int i = length; i < length + bytes_read; i++) { + if (i2s_read_buff[i] == 100) { + flag = 1; end_position = i; break; } @@ -224,8 +223,8 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") length = length + bytes_read; } // test the read data right or not - for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); + for (int i = end_position - 99; i <= end_position; i++) { + TEST_ASSERT_EQUAL_UINT8((i - end_position + 100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -246,7 +245,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -268,7 +267,7 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; i2s_pin_config_t slave_pin_config = { .bck_io_num = SLAVE_BCK_IO, @@ -282,27 +281,27 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") i2s_test_io_config(I2S_TEST_MODE_MASTER_TO_SLAVE); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); - uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); + uint8_t *data_wr = (uint8_t *)malloc(sizeof(uint8_t) * 400); size_t i2s_bytes_write = 0; size_t bytes_read = 0; int length = 0; - uint8_t *i2s_read_buff = (uint8_t*)malloc(sizeof(uint8_t)*10000); + uint8_t *i2s_read_buff = (uint8_t *)malloc(sizeof(uint8_t) * 10000); - for(int i=0; i<100; i++) { - data_wr[i] = i+1; + for (int i = 0; i < 100; i++) { + data_wr[i] = i + 1; } - int flag=0; // break loop flag + int flag = 0; // break loop flag 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); + 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) { + while (!flag) { + i2s_read(I2S_NUM_1, i2s_read_buff + length, sizeof(uint8_t) * 500, &bytes_read, 1000 / portTICK_PERIOD_MS); + if (bytes_read > 0) { printf("read data size: %d\n", bytes_read); - for(int i=length; i 0) { - for(int i=length; i 0) { + for (int i = length; i < length + bytes_read; i++) { + if (i2s_read_buff[i] == 100) { + flag = 1; end_position = i; break; } @@ -396,8 +396,8 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]") length = length + bytes_read; } // test the readed data right or not - for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); + for (int i = end_position - 99; i <= end_position; i++) { + TEST_ASSERT_EQUAL_UINT8((i - end_position + 100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -417,7 +417,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -431,7 +431,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]") i2s_driver_uninstall(I2S_NUM_0); int initial_size = esp_get_free_heap_size(); - for(int i=0; i<100; i++) { + for (int i = 0; i < 100; i++) { TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); i2s_driver_uninstall(I2S_NUM_0); @@ -475,14 +475,14 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") uint32_t sample_rate_arr[8] = { 10675, 11025, 16000, 22050, 32000, 44100, 48000, 96000 }; int bits_per_sample_arr[3] = { 16, 24, 32 }; - 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++) { + 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.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)); - TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i]))/(sample_rate_arr[i]))*100 < PERCENT_DIFF); + TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i])) / (sample_rate_arr[i])) * 100 < PERCENT_DIFF); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); TEST_ASSERT(initial_size == esp_get_free_heap_size()); } @@ -506,7 +506,7 @@ TEST_CASE("I2S adc test", "[i2s]") .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 @@ -514,7 +514,7 @@ TEST_CASE("I2S adc test", "[i2s]") // 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)); + uint16_t *i2sReadBuffer = (uint16_t *)calloc(1024, sizeof(uint16_t)); size_t bytesRead; for (int loop = 0; loop < 10; loop++) { @@ -526,7 +526,7 @@ TEST_CASE("I2S adc test", "[i2s]") } 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); + i2s_read(I2S_NUM_0, (void *)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY); // calc average int64_t adcSumValue = 0; @@ -571,7 +571,7 @@ TEST_CASE("I2S dac test", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 60, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, }; //install and start i2s driver diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index eaa74bec20..6b928721ec 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -67,7 +67,7 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param enable Set true to enable tx msb right */ -static inline void i2s_ll_tx_msb_right_en(i2s_dev_t *hw, bool enable) +static inline void i2s_ll_tx_enable_msb_right(i2s_dev_t *hw, bool enable) { hw->conf.tx_msb_right = enable; } @@ -78,7 +78,7 @@ static inline void i2s_ll_tx_msb_right_en(i2s_dev_t *hw, bool enable) * @param hw Peripheral I2S hardware instance address. * @param enable Set true to enable rx msb right */ -static inline void i2s_ll_rx_msb_right_en(i2s_dev_t *hw, bool enable) +static inline void i2s_ll_rx_enable_msb_right(i2s_dev_t *hw, bool enable) { hw->conf.rx_msb_right = enable; } @@ -89,7 +89,7 @@ static inline void i2s_ll_rx_msb_right_en(i2s_dev_t *hw, bool enable) * @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) +static inline void i2s_ll_tx_enable_right_first(i2s_dev_t *hw, bool enable) { hw->conf.tx_right_first = enable; } @@ -100,7 +100,7 @@ static inline void i2s_ll_tx_right_first_en(i2s_dev_t *hw, bool enable) * @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) +static inline void i2s_ll_rx_enable_right_first(i2s_dev_t *hw, bool enable) { hw->conf.rx_right_first = enable; } @@ -111,7 +111,7 @@ static inline void i2s_ll_rx_right_first_en(i2s_dev_t *hw, bool 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) +static inline void i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) { hw->fifo_conf.tx_fifo_mod_force_en = enable; } @@ -122,7 +122,7 @@ static inline void i2s_ll_tx_fifo_mod_force_en(i2s_dev_t *hw, bool 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) +static inline void i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) { hw->fifo_conf.rx_fifo_mod_force_en = enable; } @@ -132,7 +132,7 @@ static inline void i2s_ll_rx_fifo_mod_force_en(i2s_dev_t *hw, bool enable) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->conf.tx_slave_mod = slave_en; } @@ -143,7 +143,7 @@ static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->conf.rx_slave_mod = slave_en; } @@ -153,7 +153,7 @@ static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { hw->conf.tx_reset = 1; hw->conf.tx_reset = 0; @@ -164,7 +164,7 @@ static inline void i2s_ll_reset_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { hw->conf.rx_reset = 1; hw->conf.rx_reset = 0; @@ -175,7 +175,7 @@ static inline void i2s_ll_reset_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->conf.tx_fifo_reset = 1; hw->conf.tx_fifo_reset = 0; @@ -186,7 +186,7 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { hw->conf.rx_fifo_reset = 1; hw->conf.rx_fifo_reset = 0; @@ -198,7 +198,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 */ -static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock //1: Enable APLL clock, I2S module will using APLL as source clock @@ -211,7 +211,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 */ -static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock //1: Enable APLL clock, I2S module will using APLL as source clock @@ -224,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_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_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; @@ -238,7 +238,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_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_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_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; @@ -251,7 +251,7 @@ static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 1; hw->int_ena.out_dscr_err = 1; @@ -262,7 +262,7 @@ static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 0; hw->int_ena.out_dscr_err = 0; @@ -273,7 +273,7 @@ static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw) { hw->int_ena.in_suc_eof = 1; hw->int_ena.in_dscr_err = 1; @@ -284,7 +284,7 @@ static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw) { hw->int_ena.in_suc_eof = 0; hw->int_ena.in_dscr_err = 0; @@ -294,11 +294,12 @@ static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) * @brief Get I2S interrupt status * * @param hw Peripheral I2S hardware instance address. - * @param int_stat Pointer to module interrupt status + * @return + * - module interrupt status */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *int_stat) +static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw) { - *int_stat = hw->int_st.val; + return hw->int_st.val; } /** @@ -317,7 +318,7 @@ static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.out_rst = 1; hw->lc_conf.out_rst = 0; @@ -328,7 +329,7 @@ static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.in_rst = 1; hw->lc_conf.in_rst = 0; @@ -339,7 +340,7 @@ static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { hw->conf.tx_start = 1; } @@ -349,7 +350,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { hw->conf.rx_start = 1; } @@ -360,7 +361,7 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_start_tx_link(i2s_dev_t *hw, uint32_t link_addr) +static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr) { hw->out_link.addr = link_addr; hw->out_link.start = 1; @@ -372,7 +373,7 @@ static inline void i2s_ll_start_tx_link(i2s_dev_t *hw, uint32_t link_addr) * @param hw Peripheral I2S hardware instance address. * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_start_rx_link(i2s_dev_t *hw, uint32_t link_addr) +static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr) { hw->in_link.addr = link_addr; hw->in_link.start = 1; @@ -383,7 +384,7 @@ static inline void i2s_ll_start_rx_link(i2s_dev_t *hw, uint32_t link_addr) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { hw->conf.tx_start = 0; } @@ -393,7 +394,7 @@ static inline void i2s_ll_stop_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { hw->conf.rx_start = 0; } @@ -403,7 +404,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw) { hw->out_link.stop = 1; } @@ -413,7 +414,7 @@ static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw) { hw->in_link.stop = 1; } @@ -424,7 +425,7 @@ static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param eof_addr Pointer to accept out eof des address */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { *eof_addr = hw->out_eof_des_addr; } @@ -435,7 +436,7 @@ static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr * @param hw Peripheral I2S hardware instance address. * @param eof_addr Pointer to accept in eof des address */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { *eof_addr = hw->in_eof_des_addr; } @@ -446,7 +447,7 @@ static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) * @param hw Peripheral I2S hardware instance address. * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { // On ESP32, the eof_num count in words. hw->rx_eof_num = eof_num / 4; @@ -456,12 +457,12 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) * @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->fifo_conf.tx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); hw->sample_rate_conf.tx_bits_mod = data_bit; } @@ -469,12 +470,12 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->fifo_conf.rx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); hw->sample_rate_conf.rx_bits_mod = data_bit; } @@ -484,97 +485,53 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable DMA */ -static inline void i2s_ll_dma_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena) { hw->fifo_conf.dscr_en = ena; } /** - * @brief Set I2S TX to philip standard + * @brief Configure TX WS signal width * * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 1; + hw->conf.tx_short_sync = width == 1 ? 1 : 0; } /** - * @brief Set I2S RX to philip standard + * @brief Configure RX WS signal width * * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 1; + hw->conf.rx_short_sync = width == 1 ? 1 : 0; } /** - * @brief Set I2S TX to MSB Alignment Standard + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_tx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 0; + hw->conf.tx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S RX to MSB Alignment Standard + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 0; -} - -/** - * @brief Set I2S TX to PCM short standard - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) -{ - hw->conf.tx_short_sync = 1; - hw->conf.tx_msb_shift = 0; -} - -/** - * @brief Set I2S RX to PCM short standard - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) -{ - hw->conf.rx_short_sync = 1; - hw->conf.rx_msb_shift = 0; -} - -/** - * @brief Set I2S TX to PCM long standard - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) -{ - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 0; -} - -/** - * @brief Set I2S RX to PCM long standard - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) -{ - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 0; + hw->conf.rx_msb_shift = msb_shift_enable; } /** @@ -583,14 +540,10 @@ static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_tx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { int data_bit = hw->sample_rate_conf.tx_bits_mod; - if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) { - hw->fifo_conf.tx_fifo_mod = 0 + mono_ena; - } else { - hw->fifo_conf.tx_fifo_mod = 2 + mono_ena; - } + hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; hw->conf_chan.tx_chan_mod = mono_ena; } @@ -600,14 +553,10 @@ static inline void i2s_ll_tx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_rx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { int data_bit = hw->sample_rate_conf.rx_bits_mod; - if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) { - hw->fifo_conf.rx_fifo_mod = 0 + mono_ena; - } else { - hw->fifo_conf.rx_fifo_mod = 2 + mono_ena; - } + hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; hw->conf_chan.rx_chan_mod = mono_ena; } @@ -617,30 +566,21 @@ static inline void i2s_ll_rx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) * @param hw Peripheral I2S hardware instance address. * @param loopback_en Set true to enable loopback mode. */ -static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool loopback_en) +static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool loopback_en) { hw->conf.sig_loopback = loopback_en; } -/** - * @brief Set default RX PDM mode - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw) -{ - hw->pdm_conf.rx_sinc_dsr_16_en = 0; - hw->pdm_conf.pdm2pcm_conv_en = 1; - hw->pdm_conf.rx_pdm_en = 1; -} + +/******************************I2S PDM Configurations*************************************/ /** * @brief Configure RX PDM downsample * * @param hw Peripheral I2S hardware instance address. * @param dsr PDM downsample configuration paramater */ -static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) +static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) { hw->pdm_conf.rx_sinc_dsr_16_en = dsr; } @@ -651,44 +591,88 @@ static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) * @param hw Peripheral I2S hardware instance address. * @param dsr Pointer to accept PDM downsample configuration */ -static inline void i2s_ll_get_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) +static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) { *dsr = hw->pdm_conf.rx_sinc_dsr_16_en; } +/** + * @brief Enable I2S TX PDM mode + * + * @param hw Peripheral I2S hardware instance address. + * @param pdm_ena Set true to enable TX PDM mode + */ +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_ena) +{ + hw->pdm_conf.tx_pdm_en = pdm_ena; + hw->pdm_conf.pcm2pdm_conv_en = pdm_ena; +} + /** * @brief Enable I2S RX PDM mode * * @param hw Peripheral I2S hardware instance address. * @param pdm_ena Set true to enable RX PDM mode */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_ena) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_ena) { hw->pdm_conf.rx_pdm_en = pdm_ena; + hw->pdm_conf.pdm2pcm_conv_en = pdm_ena; } /** - * @brief Configure I2S TX pdm + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param sample_rate The sample rate to be set. + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - 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_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.pcm2pdm_conv_en = 1; - pdm_conf_reg.tx_pdm_en = 1; - hw->pdm_conf.val = pdm_conf_reg.val; - hw->pdm_freq_conf.tx_pdm_fp = fp; - hw->pdm_freq_conf.tx_pdm_fs = fs; + hw->pdm_conf.tx_prescale = prescale; +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->pdm_conf.tx_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->pdm_conf.tx_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->pdm_conf.tx_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->pdm_conf.tx_sigmadelta_in_shift = sig_scale; } /** @@ -699,7 +683,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) * @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) +static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs) { hw->pdm_freq_conf.tx_pdm_fp = fp; hw->pdm_freq_conf.tx_pdm_fs = fs; @@ -707,56 +691,85 @@ static inline void i2s_ll_set_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM configuration + * @brief Get I2S TX PDM fp configuration paramater * * @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 + * @return + * - fp configuration paramater */ -static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { - *fp = hw->pdm_freq_conf.tx_pdm_fp; - *fs = hw->pdm_freq_conf.tx_pdm_fs; + return hw->pdm_freq_conf.tx_pdm_fp; } /** - * @brief Enable I2S TX PDM mode + * @brief Get I2S TX PDM fs configuration paramater * * @param hw Peripheral I2S hardware instance address. - * @param pdm_ena Set true to enable TX PDM mode + * @return + * - fs configuration paramater */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_ena) +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { - hw->pdm_conf.tx_pdm_en = pdm_ena; + return hw->pdm_freq_conf.tx_pdm_fs; +} + + + + +/****************************I2S ADC/DAC Configurations***********************************/ +/** + * @brief Enable I2S LCD mode + * @note Have to enable LCD mode to use build in ADC/DAC + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable LCD mode. + */ +static inline void i2s_ll_enable_lcd(i2s_dev_t *hw, bool enable) +{ + hw->conf2.lcd_en = enable; +} + +/** + * @brief Enable I2S camera mode + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable camera mode. + */ +static inline void i2s_ll_enable_camera(i2s_dev_t *hw, bool enable) +{ + hw->conf2.camera_en = enable; } /** * @brief Enable I2S build in ADC mode * * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable build in ADC */ -static inline void i2s_ll_build_in_adc_ena(i2s_dev_t *hw) +static inline void i2s_ll_enable_builtin_adc(i2s_dev_t *hw, bool enable) { - hw->conf2.lcd_en = 1; + hw->conf2.lcd_en = enable; hw->conf2.camera_en = 0; hw->conf.rx_right_first = 0; hw->conf.rx_msb_shift = 0; hw->conf.rx_mono = 0; hw->conf.rx_short_sync = 0; - hw->fifo_conf.rx_fifo_mod = 1; - hw->conf_chan.rx_chan_mod = 1; + hw->fifo_conf.rx_fifo_mod = enable; + hw->conf_chan.rx_chan_mod = enable; } /** * @brief Enable I2S build in DAC mode * * @param hw Peripheral I2S hardware instance address. + * * @param enable Set true to enable build in DAC */ -static inline void i2s_ll_build_in_dac_ena(i2s_dev_t *hw) +static inline void i2s_ll_enable_builtin_dac(i2s_dev_t *hw, bool enable) { - hw->conf2.lcd_en = 1; + hw->conf2.lcd_en = enable; hw->conf2.camera_en = 0; - hw->conf.tx_right_first = 1; + hw->conf.tx_right_first = enable; hw->conf.tx_msb_shift = 0; hw->conf.tx_short_sync = 0; } diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 94eb7d9077..41a8c36d50 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -60,7 +60,7 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { hw->tx_clkm_conf.tx_clk_active = 1; } @@ -70,7 +70,7 @@ static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_clock(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { hw->rx_clkm_conf.rx_clk_active = 1; } @@ -101,7 +101,7 @@ static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->tx_conf.tx_slave_mod = slave_en; } @@ -112,7 +112,7 @@ static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->rx_conf.rx_slave_mod = slave_en; } @@ -122,7 +122,7 @@ static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { hw->tx_conf.tx_reset = 1; hw->tx_conf.tx_reset = 0; @@ -133,7 +133,7 @@ static inline void i2s_ll_reset_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { hw->rx_conf.rx_reset = 1; hw->rx_conf.rx_reset = 0; @@ -144,7 +144,7 @@ static inline void i2s_ll_reset_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->tx_conf.tx_fifo_reset = 1; hw->tx_conf.tx_fifo_reset = 0; @@ -155,7 +155,7 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { hw->rx_conf.rx_fifo_reset = 1; hw->rx_conf.rx_fifo_reset = 0; @@ -167,7 +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. */ -static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->tx_clkm_conf.tx_clk_sel = 2; } @@ -178,7 +178,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` */ -static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->rx_clkm_conf.rx_clk_sel = 2; } @@ -189,7 +189,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_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_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; @@ -218,7 +218,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_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_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_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; @@ -246,7 +246,7 @@ static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { hw->tx_conf.tx_update = 0; hw->tx_conf.tx_update = 1; @@ -258,7 +258,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { hw->rx_conf.rx_update = 0; hw->rx_conf.rx_update = 1; @@ -270,7 +270,7 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { hw->tx_conf.tx_start = 0; } @@ -280,7 +280,7 @@ static inline void i2s_ll_stop_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { hw->rx_conf.rx_start = 0; } @@ -291,7 +291,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { hw->tx_conf1.tx_tdm_ws_width = width - 1; } @@ -302,7 +302,7 @@ static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { hw->rx_conf1.rx_tdm_ws_width = width - 1; } @@ -313,7 +313,7 @@ static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { hw->rx_eof_num.rx_eof_num = eof_num; } @@ -322,26 +322,26 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) * @brief Congfigure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** * @brief Congfigure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** @@ -350,7 +350,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_tx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1; } @@ -361,7 +361,7 @@ static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_rx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1; } @@ -372,7 +372,7 @@ static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->tx_conf1.tx_msb_shift = msb_shift_enable; } @@ -383,7 +383,7 @@ static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->rx_conf1.rx_msb_shift = msb_shift_enable; } @@ -394,7 +394,7 @@ 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 chan number */ -static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_tx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1; } @@ -405,7 +405,7 @@ static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param total_num Total chan number */ -static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; } @@ -416,7 +416,7 @@ static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of tx active chan */ -static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -430,7 +430,7 @@ static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of rx active chan */ -static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -444,7 +444,7 @@ static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_tx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->tx_conf.tx_ws_idle_pol = ws_pol_level; } @@ -455,7 +455,7 @@ static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->rx_conf.rx_ws_idle_pol = ws_pol_level; } @@ -466,47 +466,133 @@ static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @param pdm_enable Set true to TX enable PDM mode */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_tx_enable_pdm(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; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; } /** - * @brief Configure I2S TX pdm + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param sample_rate The sample rate to be set. + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - 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_pdm_prescale = 0; - pdm_conf_reg.tx_pdm_hp_in_shift = 1; - 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_dac_mode_en = 1; - pdm_conf_reg.tx_pdm_sigmadelta_dither = 0; - pdm_conf_reg.tx_pdm_sigmadelta_dither2 = 0; - pdm_conf_reg.tx_pdm_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_pdm_hp_bypass = 0; - hw->tx_pcm2pdm_conf = pdm_conf_reg; - hw->tx_pcm2pdm_conf1 = pdm_conf1_reg; + hw->tx_pcm2pdm_conf.tx_pdm_prescale = prescale; +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S TX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S TX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_bypass = !enable; +} + +/** + * @brief Enable I2S TX PDM sigma-delta codec + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = enable; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither = dither; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither2 I2S TX PDM sigmadelta dither2 value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither2 = dither2; } /** @@ -517,7 +603,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) * @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) +static inline void i2s_ll_tx_set_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; @@ -525,28 +611,40 @@ static inline void i2s_ll_set_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM configuration + * @brief Get I2S TX PDM fp configuration paramater * * @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 + * @return + * - fp configuration paramater */ -static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { - *fp = hw->tx_pcm2pdm_conf1.tx_pdm_fp; - *fs = hw->tx_pcm2pdm_conf1.tx_pdm_fs; + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; +} + +/** + * @brief Get I2S TX PDM fs configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater + */ +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; } /** * @brief Enable RX PDM mode. + * @note ESP32-C3 doesn't support pdm in rx mode, disable anyway * * @param hw Peripheral I2S hardware instance address. - * @param pdm_enable Set true to RX enable PDM mode + * @param pdm_enable Set true to RX enable PDM mode (ignored) */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { - hw->rx_conf.rx_pdm_en = pdm_enable; - hw->rx_conf.rx_tdm_en = !pdm_enable; + hw->rx_conf.rx_pdm_en = 0; + hw->rx_conf.rx_tdm_en = 1; } /** @@ -555,14 +653,10 @@ 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_compress_t pcm_cfg) +static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->tx_conf.tx_pcm_bypass = 1; - } else { - hw->tx_conf.tx_pcm_conf = pcm_cfg; - hw->tx_conf.tx_pcm_bypass = 0; - } + hw->tx_conf.tx_pcm_conf = pcm_cfg; + hw->tx_conf.tx_pcm_bypass = !pcm_cfg; } /** @@ -571,14 +665,10 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_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_compress_t pcm_cfg) +static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->rx_conf.rx_pcm_bypass = 1; - } else { - hw->rx_conf.rx_pcm_conf = pcm_cfg; - hw->rx_conf.rx_pcm_bypass = 0; - } + hw->rx_conf.rx_pcm_conf = pcm_cfg; + hw->rx_conf.rx_pcm_bypass = !pcm_cfg; } /** @@ -587,7 +677,7 @@ static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_left_align = ena; } @@ -598,7 +688,7 @@ static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_left_align = ena; } @@ -609,7 +699,7 @@ static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_big_endian = ena; } @@ -620,7 +710,7 @@ static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_tx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_big_endian = ena; } @@ -665,7 +755,7 @@ static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena) * @param hw Peripheral I2S hardware instance address. * @param data Single data to be set */ -static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) +static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) { hw->conf_single_data = data; } @@ -676,7 +766,7 @@ static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable loopback mode. */ -static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 056cb5ce55..4f933c78bd 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -61,7 +61,7 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { hw->tx_clkm_conf.tx_clk_active = 1; } @@ -71,7 +71,7 @@ static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_clock(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { hw->rx_clkm_conf.rx_clk_active = 1; } @@ -102,7 +102,7 @@ static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->tx_conf.tx_slave_mod = slave_en; } @@ -113,7 +113,7 @@ static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->rx_conf.rx_slave_mod = slave_en; } @@ -123,7 +123,7 @@ static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { hw->tx_conf.tx_reset = 1; hw->tx_conf.tx_reset = 0; @@ -134,7 +134,7 @@ static inline void i2s_ll_reset_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { hw->rx_conf.rx_reset = 1; hw->rx_conf.rx_reset = 0; @@ -145,7 +145,7 @@ static inline void i2s_ll_reset_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->tx_conf.tx_fifo_reset = 1; hw->tx_conf.tx_fifo_reset = 0; @@ -156,7 +156,7 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { hw->rx_conf.rx_fifo_reset = 1; hw->rx_conf.rx_fifo_reset = 0; @@ -168,7 +168,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. */ -static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->tx_clkm_conf.tx_clk_sel = 2; } @@ -179,7 +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` */ -static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->rx_clkm_conf.rx_clk_sel = 2; } @@ -190,7 +190,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_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_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; @@ -219,7 +219,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_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_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_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; @@ -247,7 +247,7 @@ static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { hw->tx_conf.tx_update = 0; hw->tx_conf.tx_update = 1; @@ -259,7 +259,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { hw->rx_conf.rx_update = 0; hw->rx_conf.rx_update = 1; @@ -271,7 +271,7 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { hw->tx_conf.tx_start = 0; } @@ -281,7 +281,7 @@ static inline void i2s_ll_stop_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { hw->rx_conf.rx_start = 0; } @@ -292,7 +292,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { hw->tx_conf1.tx_tdm_ws_width = width - 1; } @@ -303,7 +303,7 @@ static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { hw->rx_conf1.rx_tdm_ws_width = width - 1; } @@ -314,7 +314,7 @@ static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { hw->rx_eof_num.rx_eof_num = eof_num; } @@ -323,26 +323,26 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) * @brief Congfigure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** * @brief Congfigure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** @@ -351,7 +351,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_tx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1; } @@ -362,7 +362,7 @@ static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_rx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1; } @@ -373,7 +373,7 @@ static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->tx_conf1.tx_msb_shift = msb_shift_enable; } @@ -384,7 +384,7 @@ static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->rx_conf1.rx_msb_shift = msb_shift_enable; } @@ -395,7 +395,7 @@ 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 chan number */ -static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_tx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1; } @@ -406,7 +406,7 @@ static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param total_num Total chan number */ -static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; } @@ -417,7 +417,7 @@ static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of tx active chan */ -static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -431,7 +431,7 @@ static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of rx active chan */ -static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -445,7 +445,7 @@ static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_tx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->tx_conf.tx_ws_idle_pol = ws_pol_level; } @@ -456,7 +456,7 @@ static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->rx_conf.rx_ws_idle_pol = ws_pol_level; } @@ -467,47 +467,133 @@ static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @param pdm_enable Set true to TX enable PDM mode */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_tx_enable_pdm(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; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; } /** - * @brief Configure I2S TX pdm + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param sample_rate The sample rate to be set. + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - 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_pdm_prescale = 0; - pdm_conf_reg.tx_pdm_hp_in_shift = 1; - 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_dac_mode_en = 1; - pdm_conf_reg.tx_pdm_sigmadelta_dither = 0; - pdm_conf_reg.tx_pdm_sigmadelta_dither2 = 0; - pdm_conf_reg.tx_pdm_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_pdm_hp_bypass = 0; - hw->tx_pcm2pdm_conf = pdm_conf_reg; - hw->tx_pcm2pdm_conf1 = pdm_conf1_reg; + hw->tx_pcm2pdm_conf.tx_pdm_prescale = prescale; +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S TX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S TX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_hp_bypass = !enable; +} + +/** + * @brief Enable I2S TX PDM sigma-delta codec + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = enable; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither = dither; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither2 I2S TX PDM sigmadelta dither2 value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) +{ + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither2 = dither2; } /** @@ -518,7 +604,7 @@ static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) * @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) +static inline void i2s_ll_tx_set_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; @@ -526,16 +612,27 @@ static inline void i2s_ll_set_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM configuration + * @brief Get I2S TX PDM fp configuration paramater * * @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 + * @return + * - fp configuration paramater */ -static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { - *fp = hw->tx_pcm2pdm_conf1.tx_pdm_fp; - *fs = hw->tx_pcm2pdm_conf1.tx_pdm_fs; + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; +} + +/** + * @brief Get I2S TX PDM fs configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater + */ +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) +{ + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; } /** @@ -544,7 +641,7 @@ static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t * @param hw Peripheral I2S hardware instance address. * @param pdm_enable Set true to RX enable PDM mode */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { hw->rx_conf.rx_pdm_en = pdm_enable; hw->rx_conf.rx_tdm_en = !pdm_enable; @@ -556,14 +653,10 @@ 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_compress_t pcm_cfg) +static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->tx_conf.tx_pcm_bypass = 1; - } else { - hw->tx_conf.tx_pcm_conf = pcm_cfg; - hw->tx_conf.tx_pcm_bypass = 0; - } + hw->tx_conf.tx_pcm_conf = pcm_cfg; + hw->tx_conf.tx_pcm_bypass = !pcm_cfg; } /** @@ -572,14 +665,10 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_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_compress_t pcm_cfg) +static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->rx_conf.rx_pcm_bypass = 1; - } else { - hw->rx_conf.rx_pcm_conf = pcm_cfg; - hw->rx_conf.rx_pcm_bypass = 0; - } + hw->rx_conf.rx_pcm_conf = pcm_cfg; + hw->rx_conf.rx_pcm_bypass = !pcm_cfg; } /** @@ -588,7 +677,7 @@ static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_left_align = ena; } @@ -599,7 +688,7 @@ static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_left_align = ena; } @@ -610,7 +699,7 @@ static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_big_endian = ena; } @@ -621,7 +710,7 @@ static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_tx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_big_endian = ena; } @@ -666,7 +755,7 @@ static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena) * @param hw Peripheral I2S hardware instance address. * @param data Single data to be set */ -static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) +static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) { hw->conf_single_data = data; } @@ -677,7 +766,7 @@ static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable loopback mode. */ -static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 5ca3262018..91ba45e3f3 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -66,7 +66,7 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param enable Set true to enable tx msb right */ -static inline void i2s_ll_tx_msb_right_en(i2s_dev_t *hw, bool enable) +static inline void i2s_ll_tx_enable_msb_right(i2s_dev_t *hw, bool enable) { hw->conf.tx_msb_right = enable; } @@ -77,7 +77,7 @@ static inline void i2s_ll_tx_msb_right_en(i2s_dev_t *hw, bool enable) * @param hw Peripheral I2S hardware instance address. * @param enable Set true to enable rx msb right */ -static inline void i2s_ll_rx_msb_right_en(i2s_dev_t *hw, bool enable) +static inline void i2s_ll_rx_enable_msb_right(i2s_dev_t *hw, bool enable) { hw->conf.rx_msb_right = enable; } @@ -88,7 +88,7 @@ static inline void i2s_ll_rx_msb_right_en(i2s_dev_t *hw, bool enable) * @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) +static inline void i2s_ll_tx_enable_right_first(i2s_dev_t *hw, bool enable) { hw->conf.tx_right_first = enable; } @@ -99,7 +99,7 @@ static inline void i2s_ll_tx_right_first_en(i2s_dev_t *hw, bool enable) * @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) +static inline void i2s_ll_rx_enable_right_first(i2s_dev_t *hw, bool enable) { hw->conf.rx_right_first = enable; } @@ -110,7 +110,7 @@ static inline void i2s_ll_rx_right_first_en(i2s_dev_t *hw, bool 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) +static inline void i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) { hw->fifo_conf.tx_fifo_mod_force_en = enable; } @@ -121,7 +121,7 @@ static inline void i2s_ll_tx_fifo_mod_force_en(i2s_dev_t *hw, bool 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) +static inline void i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) { hw->fifo_conf.rx_fifo_mod_force_en = enable; } @@ -132,7 +132,7 @@ static inline void i2s_ll_rx_fifo_mod_force_en(i2s_dev_t *hw, bool enable) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->conf.tx_slave_mod = slave_en; } @@ -143,7 +143,7 @@ static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->conf.rx_slave_mod = slave_en; } @@ -153,7 +153,7 @@ static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { hw->conf.tx_reset = 1; hw->conf.tx_reset = 0; @@ -164,7 +164,7 @@ static inline void i2s_ll_reset_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { hw->conf.rx_reset = 1; hw->conf.rx_reset = 0; @@ -175,7 +175,7 @@ static inline void i2s_ll_reset_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->conf.tx_fifo_reset = 1; hw->conf.tx_fifo_reset = 0; @@ -186,7 +186,7 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { hw->conf.rx_fifo_reset = 1; hw->conf.rx_fifo_reset = 0; @@ -198,7 +198,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 */ -static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->clkm_conf.clk_sel = (src == 1) ? 1 : 2; } @@ -209,7 +209,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 */ -static inline void i2s_ll_set_rx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->clkm_conf.clk_sel = (src == 1) ? 1 : 2; } @@ -220,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_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_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; @@ -234,7 +234,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_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_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_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 +247,7 @@ static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 1; hw->int_ena.out_dscr_err = 1; @@ -258,7 +258,7 @@ static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 0; hw->int_ena.out_dscr_err = 0; @@ -269,7 +269,7 @@ static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw) { hw->int_ena.in_suc_eof = 1; hw->int_ena.in_dscr_err = 1; @@ -280,7 +280,7 @@ static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw) { hw->int_ena.in_suc_eof = 0; hw->int_ena.in_dscr_err = 0; @@ -290,11 +290,12 @@ static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) * @brief Get I2S interrupt status * * @param hw Peripheral I2S hardware instance address. - * @param intr_mask Pointer to accept interrupt status + * @return + * - module interrupt status */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *intr_mask) +static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw) { - *intr_mask = hw->int_st.val; + return hw->int_st.val; } /** @@ -313,7 +314,7 @@ static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.out_rst = 1; hw->lc_conf.out_rst = 0; @@ -324,18 +325,44 @@ static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.in_rst = 1; hw->lc_conf.in_rst = 0; } +/** + * @brief Enable TX PDM mode. + * @note ESP32-S2 doesn't support pdm + * This function is used to be compatible with those support pdm + * + * @param hw Peripheral I2S hardware instance address (ignored) + * @param pdm_enable Set true to TX enable PDM mode (ignored) + */ +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + // Remain empty +} + +/** + * @brief Enable RX PDM mode. + * @note ESP32-S2 doesn't support pdm + * This function is used to be compatible with those support pdm + * + * @param hw Peripheral I2S hardware instance address (ignored) + * @param pdm_enable Set true to RX enable PDM mode (ignored) + */ +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + // Remain empty +} + /** * @brief Start TX module * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { hw->conf.tx_start = 1; } @@ -345,7 +372,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { hw->conf.rx_start = 1; } @@ -356,7 +383,7 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_start_tx_link(i2s_dev_t *hw, uint32_t link_addr) +static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr) { hw->out_link.addr = link_addr; hw->out_link.start = 1; @@ -368,7 +395,7 @@ static inline void i2s_ll_start_tx_link(i2s_dev_t *hw, uint32_t link_addr) * @param hw Peripheral I2S hardware instance address. * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_start_rx_link(i2s_dev_t *hw, uint32_t link_addr) +static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr) { hw->in_link.addr = link_addr; hw->in_link.start = 1; @@ -379,7 +406,7 @@ static inline void i2s_ll_start_rx_link(i2s_dev_t *hw, uint32_t link_addr) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { hw->conf.tx_start = 0; } @@ -389,7 +416,7 @@ static inline void i2s_ll_stop_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { hw->conf.rx_start = 0; } @@ -399,7 +426,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw) { hw->out_link.stop = 1; } @@ -409,7 +436,7 @@ static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw) { hw->in_link.stop = 1; } @@ -420,7 +447,7 @@ static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param eof_addr Pointer to accept out eof des address */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { *eof_addr = hw->out_eof_des_addr; } @@ -431,7 +458,7 @@ static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr * @param hw Peripheral I2S hardware instance address. * @param eof_addr Pointer to accept in eof des address */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { *eof_addr = hw->in_eof_des_addr; } @@ -442,7 +469,7 @@ static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) * @param hw Peripheral I2S hardware instance address. * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t eof_num) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, uint32_t eof_num) { hw->rx_eof_num = eof_num; } @@ -451,12 +478,12 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t eof_num) * @brief Congfigure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->fifo_conf.tx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); hw->sample_rate_conf.tx_bits_mod = data_bit; } @@ -464,12 +491,12 @@ static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @brief Congfigure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->fifo_conf.rx_fifo_mod = (sample_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); hw->sample_rate_conf.rx_bits_mod = data_bit; } @@ -479,7 +506,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable DMA */ -static inline void i2s_ll_dma_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena) { hw->fifo_conf.dscr_en = ena; } @@ -489,7 +516,7 @@ static inline void i2s_ll_dma_enable(i2s_dev_t *hw, bool ena) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_format_philip(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 1; @@ -500,7 +527,7 @@ static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_format_philip(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 1; @@ -511,7 +538,7 @@ static inline void i2s_ll_set_rx_format_philip(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_format_msb_align(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 0; @@ -522,7 +549,7 @@ static inline void i2s_ll_set_tx_format_msb_align(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_format_msb_align(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 0; @@ -533,7 +560,7 @@ static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pcm_short(i2s_dev_t *hw) { hw->conf.tx_short_sync = 1; hw->conf.tx_msb_shift = 0; @@ -544,7 +571,7 @@ static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_pcm_short(i2s_dev_t *hw) { hw->conf.rx_short_sync = 1; hw->conf.rx_msb_shift = 0; @@ -555,7 +582,7 @@ static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pcm_long(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 0; @@ -566,26 +593,66 @@ static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_pcm_long(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 0; } +/** + * @brief Configure TX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->conf.tx_short_sync = width == 1 ? 1 : 0; +} + +/** + * @brief Configure RX WS signal width + * + * @param hw Peripheral I2S hardware instance address. + * @param width WS width in BCK cycle + */ +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) +{ + hw->conf.rx_short_sync = width == 1 ? 1 : 0; +} + +/** + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->conf.tx_msb_shift = msb_shift_enable; +} + +/** + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock + * + * @param hw Peripheral I2S hardware instance address. + * @param msb_shift_enable Set true to enable MSB shift + */ +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) +{ + hw->conf.rx_msb_shift = msb_shift_enable; +} + /** * @brief Enable TX mono mode * * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_tx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { int data_bit = hw->sample_rate_conf.tx_bits_mod; - if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) { - hw->fifo_conf.tx_fifo_mod = 0 + mono_ena; - } else { - hw->fifo_conf.tx_fifo_mod = 2 + mono_ena; - } + hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; hw->conf.tx_dma_equal = mono_ena; hw->conf_chan.tx_chan_mod = mono_ena; } @@ -596,14 +663,10 @@ static inline void i2s_ll_tx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) * @param hw Peripheral I2S hardware instance address. * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_rx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { int data_bit = hw->sample_rate_conf.rx_bits_mod; - if (data_bit <= I2S_BITS_PER_SAMPLE_16BIT) { - hw->fifo_conf.rx_fifo_mod = 0 + mono_ena; - } else { - hw->fifo_conf.rx_fifo_mod = 2 + mono_ena; - } + hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; hw->conf.rx_dma_equal = mono_ena; hw->conf_chan.rx_chan_mod = mono_ena; } @@ -614,7 +677,7 @@ static inline void i2s_ll_rx_mono_mode_ena(i2s_dev_t *hw, bool mono_ena) * @param hw Peripheral I2S hardware instance address. * @param loopback_en Set true to enable loopback mode. */ -static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool loopback_en) +static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool loopback_en) { hw->conf.sig_loopback = loopback_en; } diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 3b2766fe5c..76ef727b88 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -61,7 +61,7 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { hw->tx_clkm_conf.tx_clk_active = 1; } @@ -71,7 +71,7 @@ static inline void i2s_ll_enable_tx_clock(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_clock(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { hw->rx_clkm_conf.rx_clk_active = 1; } @@ -102,7 +102,7 @@ static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->tx_conf.tx_slave_mod = slave_en; } @@ -113,7 +113,7 @@ static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, bool slave_en) * @param hw Peripheral I2S hardware instance address. * @param slave_en Set true to enable slave mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { hw->rx_conf.rx_slave_mod = slave_en; } @@ -123,7 +123,7 @@ static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, bool slave_en) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { hw->tx_conf.tx_reset = 1; hw->tx_conf.tx_reset = 0; @@ -134,7 +134,7 @@ static inline void i2s_ll_reset_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { hw->rx_conf.rx_reset = 1; hw->rx_conf.rx_reset = 0; @@ -145,7 +145,7 @@ static inline void i2s_ll_reset_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->tx_conf.tx_fifo_reset = 1; hw->tx_conf.tx_fifo_reset = 0; @@ -156,7 +156,7 @@ static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { hw->rx_conf.rx_fifo_reset = 1; hw->rx_conf.rx_fifo_reset = 0; @@ -169,7 +169,7 @@ static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) * @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) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->tx_clkm_conf.tx_clk_sel = 2; } @@ -181,7 +181,7 @@ static inline void i2s_ll_set_tx_clk_src(i2s_dev_t *hw, i2s_clock_src_t src) * @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) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { hw->rx_clkm_conf.rx_clk_sel = 2; } @@ -192,7 +192,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_ll_clk_cal_t *set) +static inline void i2s_ll_tx_set_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; @@ -221,7 +221,7 @@ static inline void i2s_ll_set_tx_clk(i2s_dev_t *hw, i2s_ll_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_ll_clk_cal_t *set) +static inline void i2s_ll_rx_set_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; @@ -249,7 +249,7 @@ static inline void i2s_ll_set_rx_clk(i2s_dev_t *hw, i2s_ll_clk_cal_t *set) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { hw->tx_conf.tx_update = 0; hw->tx_conf.tx_update = 1; @@ -261,7 +261,7 @@ static inline void i2s_ll_start_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { hw->rx_conf.rx_update = 0; hw->rx_conf.rx_update = 1; @@ -273,7 +273,7 @@ static inline void i2s_ll_start_rx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { hw->tx_conf.tx_start = 0; } @@ -283,7 +283,7 @@ static inline void i2s_ll_stop_tx(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { hw->rx_conf.rx_start = 0; } @@ -294,7 +294,7 @@ static inline void i2s_ll_stop_rx(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { hw->tx_conf1.tx_tdm_ws_width = width - 1; } @@ -305,7 +305,7 @@ static inline void i2s_ll_set_tx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { hw->rx_conf1.rx_tdm_ws_width = width - 1; } @@ -316,7 +316,7 @@ static inline void i2s_ll_set_rx_tdm_ws_width(i2s_dev_t *hw, int width) * @param hw Peripheral I2S hardware instance address. * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { hw->rx_eof_num.rx_eof_num = eof_num; } @@ -325,26 +325,26 @@ static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, int eof_num) * @brief Congfigure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_tx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** * @brief Congfigure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param sample_bit The chan bit width + * @param chan_bit The chan bit width * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, int data_bit) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_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 = chan_bit - 1; } /** @@ -353,7 +353,7 @@ static inline void i2s_ll_set_rx_sample_bit(i2s_dev_t *hw, uint8_t sample_bit, i * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_tx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->tx_conf1.tx_half_sample_bits = half_sample_bits - 1; } @@ -364,7 +364,7 @@ static inline void i2s_ll_set_tx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) +static inline void i2s_ll_rx_set_half_sample_bit(i2s_dev_t *hw, int half_sample_bits) { hw->rx_conf1.rx_half_sample_bits = half_sample_bits - 1; } @@ -375,7 +375,7 @@ static inline void i2s_ll_set_rx_half_sample_bit(i2s_dev_t *hw, int half_sample_ * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->tx_conf1.tx_msb_shift = msb_shift_enable; } @@ -386,7 +386,7 @@ static inline void i2s_ll_tx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enab * @param hw Peripheral I2S hardware instance address. * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_rx_msb_shift_enable(i2s_dev_t *hw, bool msb_shift_enable) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { hw->rx_conf1.rx_msb_shift = msb_shift_enable; } @@ -397,7 +397,7 @@ 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 chan number */ -static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_tx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->tx_tdm_ctrl.tx_tdm_tot_chan_num = total_num - 1; } @@ -408,7 +408,7 @@ static inline void i2s_ll_set_tx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param total_num Total chan number */ -static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) { hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; } @@ -419,7 +419,7 @@ static inline void i2s_ll_set_rx_chan_num(i2s_dev_t *hw, int total_num) * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of tx active chan */ -static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -433,7 +433,7 @@ static inline void i2s_ll_set_tx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @param chan_mask mask of rx active chan */ -static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; @@ -447,7 +447,7 @@ static inline void i2s_ll_set_rx_active_chan_mask(i2s_dev_t *hw, uint32_t chan_m * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_tx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->tx_conf.tx_ws_idle_pol = ws_pol_level; } @@ -458,7 +458,7 @@ static inline void i2s_set_tx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @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) +static inline void i2s_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { hw->rx_conf.rx_ws_idle_pol = ws_pol_level; } @@ -469,10 +469,11 @@ static inline void i2s_set_rx_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) * @param hw Peripheral I2S hardware instance address. * @param pdm_enable Set true to TX enable PDM mode */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { hw->tx_conf.tx_pdm_en = pdm_enable; hw->tx_conf.tx_tdm_en = !pdm_enable; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; } /** @@ -481,10 +482,11 @@ static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_enable) * @param hw Peripheral I2S hardware instance address. * @param pdm_enable Set true to RX enable PDM mode */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { hw->rx_conf.rx_pdm_en = pdm_enable; hw->rx_conf.rx_tdm_en = !pdm_enable; + hw->rx_conf.rx_pdm2pcm_en = pdm_enable; } /** @@ -495,7 +497,7 @@ static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_enable) * @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) +static inline void i2s_ll_tx_set_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; @@ -503,61 +505,149 @@ static inline void i2s_ll_set_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM configuration + * @brief Get I2S TX PDM fp configuration paramater * * @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 + * @return + * - fp configuration paramater */ -static inline void i2s_ll_get_tx_pdm_fpfs(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { - *fp = hw->tx_pcm2pdm_conf1.tx_pdm_fp; - *fs = hw->tx_pcm2pdm_conf1.tx_pdm_fs; + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; } /** - * @brief Configure I2S TX pdm + * @brief Get I2S TX PDM fs configuration paramater * * @param hw Peripheral I2S hardware instance address. - * @param sample_rate The sample rate to be set. + * @return + * - fs configuration paramater */ -static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { - 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; + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; } /** - * @brief Set default RX PDM mode + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->rx_conf.rx_tdm_en = 0; - hw->rx_conf.rx_pdm2pcm_en = 1; - hw->rx_conf.rx_pdm_sinc_dsr_16_en = 0; - hw->rx_conf.rx_pdm_en = 1; + hw->tx_pcm2pdm_conf.tx_prescale = prescale; +} + +/** + * @brief Set I2S TX PDM high pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_hp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM low pass filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_lp_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sinc filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_sinc_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM sigma-delta filter scaling + * + * @param hw Peripheral I2S hardware instance address. + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter + */ +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) +{ + hw->tx_pcm2pdm_conf.tx_sigmadelta_in_shift = sig_scale; +} + +/** + * @brief Set I2S TX PDM high pass filter param0 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; +} + +/** + * @brief Set I2S TX PDM high pass filter param5 + * + * @param hw Peripheral I2S hardware instance address. + * @param param The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + */ +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) +{ + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; +} + +/** + * @brief Enable I2S TX PDM high pass filter + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it + */ +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_hp_bypass = !enable; +} + +/** + * @brief Enable I2S TX PDM sigma-delta codec + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_dac_mode_en = enable; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) +{ + hw->tx_pcm2pdm_conf.tx_sigmadelta_dither = dither; +} + +/** + * @brief Set I2S TX PDM sigma-delta codec dither + * + * @param hw Peripheral I2S hardware instance address. + * @param dither2 I2S TX PDM sigmadelta dither2 value + */ +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) +{ + hw->tx_pcm2pdm_conf.tx_sigmadelta_dither2 = dither2; } /** @@ -566,7 +656,7 @@ static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw) * @param hw Peripheral I2S hardware instance address. * @param dsr PDM downsample configuration paramater */ -static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) +static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) { hw->rx_conf.rx_pdm_sinc_dsr_16_en = dsr; } @@ -577,7 +667,7 @@ static inline void i2s_ll_set_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) * @param hw Peripheral I2S hardware instance address. * @param dsr Pointer to accept PDM downsample configuration */ -static inline void i2s_ll_get_pdm_rx_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) +static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) { *dsr = hw->rx_conf.rx_pdm_sinc_dsr_16_en; } @@ -588,14 +678,10 @@ 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_compress_t pcm_cfg) +static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->tx_conf.tx_pcm_bypass = 1; - } else { - hw->tx_conf.tx_pcm_conf = pcm_cfg; - hw->tx_conf.tx_pcm_bypass = 0; - } + hw->tx_conf.tx_pcm_conf = pcm_cfg; + hw->tx_conf.tx_pcm_bypass = !pcm_cfg; } /** @@ -604,14 +690,10 @@ static inline void i2s_ll_tx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_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_compress_t pcm_cfg) +static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { - if (pcm_cfg == I2S_PCM_DISABLE) { - hw->rx_conf.rx_pcm_bypass = 1; - } else { - hw->rx_conf.rx_pcm_conf = pcm_cfg; - hw->rx_conf.rx_pcm_bypass = 0; - } + hw->rx_conf.rx_pcm_conf = pcm_cfg; + hw->rx_conf.rx_pcm_bypass = !pcm_cfg; } /** @@ -620,7 +702,7 @@ static inline void i2s_ll_rx_pcm_cfg(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_left_align = ena; } @@ -631,7 +713,7 @@ static inline void i2s_ll_tx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable left alignment */ -static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_left_align(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_left_align = ena; } @@ -642,7 +724,7 @@ static inline void i2s_ll_rx_left_align_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_rx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->rx_conf.rx_big_endian = ena; } @@ -653,7 +735,7 @@ static inline void i2s_ll_rx_big_endian_enable(i2s_dev_t *hw, bool ena) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable big endian mode */ -static inline void i2s_ll_tx_big_endian_enable(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_tx_enable_big_endian(i2s_dev_t *hw, bool ena) { hw->tx_conf.tx_big_endian = ena; } @@ -698,9 +780,9 @@ static inline void i2s_ll_tx_set_skip_mask(i2s_dev_t *hw, bool skip_mask_ena) * @param hw Peripheral I2S hardware instance address. * @param data Single data to be set */ -static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) +static inline void i2s_ll_set_single_data(i2s_dev_t *hw, uint32_t data) { - hw->conf_signal_data = data; + hw->conf_single_data = data; } /** @@ -709,7 +791,7 @@ static inline void i2s_ll_single_data_config(i2s_dev_t *hw, uint32_t data) * @param hw Peripheral I2S hardware instance address. * @param ena Set true to enable loopback mode. */ -static inline void i2s_ll_loop_back_ena(i2s_dev_t *hw, bool ena) +static inline void i2s_ll_enable_loop_back(i2s_dev_t *hw, bool ena) { hw->tx_conf.sig_loopback = ena; } diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index bbabba6ba7..b7cbe45994 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -65,34 +65,34 @@ static void i2s_hal_clk_cal(uint32_t fsclk, uint32_t fbck, int bck_div, i2s_ll_c void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel) { - i2s_ll_set_tx_clk_src(hal->dev, sel); - i2s_ll_set_rx_clk_src(hal->dev, sel); + i2s_ll_tx_clk_set_src(hal->dev, sel); + i2s_ll_rx_clk_set_src(hal->dev, sel); } void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbck, int factor) { 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); + i2s_ll_tx_set_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_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); + i2s_ll_rx_set_clk(hal->dev, &clk_set); } void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal) { - i2s_ll_set_tx_slave_mod(hal->dev, 0); //TX master - i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_tx_set_slave_mod(hal->dev, 0); //TX master + i2s_ll_rx_set_slave_mod(hal->dev, 1); //RX Slave } void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal) { - i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave - i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_tx_set_slave_mod(hal->dev, 1); //TX Slave + i2s_ll_rx_set_slave_mod(hal->dev, 1); //RX Slave } void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) @@ -102,193 +102,195 @@ void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) i2s_ll_enable_clock(hal->dev); } -static void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +static void i2s_hal_tx_set_pdm_mode(i2s_hal_context_t *hal, uint32_t sample_rate) { -#if !SOC_I2S_SUPPORTS_TDM - 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 (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); - } - } +#if SOC_I2S_SUPPORTS_PDM_TX + /* enable pdm tx mode */ + i2s_ll_tx_enable_pdm(hal->dev, true); + /* set pdm tx default presacle */ + i2s_ll_tx_set_pdm_prescale(hal->dev, 0); + /* set pdm tx default sacle of high pass filter */ + i2s_ll_tx_set_pdm_hp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of low pass filter */ + i2s_ll_tx_set_pdm_lp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of sinc filter */ + i2s_ll_tx_set_pdm_sinc_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of sigma-delta filter */ + i2s_ll_tx_set_pdm_sd_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx sample rate */ + i2s_ll_tx_set_pdm_fpfs(hal->dev, 960, sample_rate / 100); + +#if SOC_I2S_SUPPORTS_PDM_CODEC + /* enable pdm high pass filter */ + i2s_ll_tx_enable_pdm_hp_filter(hal->dev, true); + /* set pdm tx high pass filter parameters */ + i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, 6); + i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, 7); + /* enable pdm sigma-delta codec */ + i2s_ll_tx_enable_pdm_sd_codec(hal->dev, true); + /* set pdm tx sigma-delta codec dither */ + i2s_ll_tx_set_pdm_sd_dither(hal->dev, 0); + i2s_ll_tx_set_pdm_sd_dither2(hal->dev, 0); + +#endif // SOC_I2S_SUPPORTS_PDM_CODEC +#endif // SOC_I2S_SUPPORTS_PDM_TX +} + +static void i2s_hal_rx_set_pdm_mode(i2s_hal_context_t *hal) +{ +#if SOC_I2S_SUPPORTS_PDM_RX + /* enable pdm rx mode */ + i2s_ll_rx_enable_pdm(hal->dev, true); + /* set pdm rx downsample number */ + i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S); +#endif // SOC_I2S_SUPPORTS_PDM_RX +} + + +static void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + /* disable pdm tx mode */ + i2s_ll_tx_enable_pdm(hal->dev, false); + +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_tx_enable_clock(hal->dev); + i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default + i2s_ll_mclk_use_tx_clk(hal->dev); + + i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask); + i2s_ll_tx_enable_left_align(hal->dev, hal_cfg->left_align_en); + i2s_ll_tx_enable_big_endian(hal->dev, hal_cfg->big_edin_en); + i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->bit_order_msb_en); + i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->skip_msk_en); #else - int chan_bits = hal_cfg->bits_cfg.chan_bits; - int chan_num = hal_cfg->total_chan; - bool msb_shift_en = false; - int tdm_ws_width = 0; - switch (hal_cfg->comm_fmt) { - case I2S_COMM_FORMAT_STAND_MSB: - msb_shift_en = false; - tdm_ws_width = chan_num * chan_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 = chan_bits; - break; - default: //I2S_COMM_FORMAT_STAND_I2S - msb_shift_en = true; - tdm_ws_width = chan_num * chan_bits / 2; - break; - } - 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, chan_num * chan_bits / 2); - } - 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, chan_num * chan_bits / 2); - } + i2s_ll_tx_enable_msb_right(hal->dev, false); + i2s_ll_tx_enable_right_first(hal->dev, false); + i2s_ll_tx_force_enable_fifo_mod(hal->dev, true); #endif } -void i2s_hal_samples_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +static void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { - int data_bits = hal_cfg->bits_cfg.sample_bits; - int chan_bits = hal_cfg->bits_cfg.chan_bits; + /* disable pdm rx mode */ + i2s_ll_rx_enable_pdm(hal->dev, false); + #if SOC_I2S_SUPPORTS_TDM - int chan_num = hal_cfg->total_chan; - if (hal_cfg->mode & I2S_MODE_TX) { - i2s_ll_set_tx_chan_num(hal->dev, chan_num); - i2s_ll_set_tx_sample_bit(hal->dev, chan_bits, data_bits); - } - if (hal_cfg->mode & I2S_MODE_RX) { - i2s_ll_set_rx_chan_num(hal->dev, chan_num); - i2s_ll_set_rx_sample_bit(hal->dev, chan_bits, data_bits); - } + i2s_ll_rx_enable_clock(hal->dev); + i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default + i2s_ll_mclk_use_rx_clk(hal->dev); + + i2s_ll_rx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask); + i2s_ll_rx_enable_left_align(hal->dev, hal_cfg->left_align_en); + i2s_ll_rx_enable_big_endian(hal->dev, hal_cfg->big_edin_en); + i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->bit_order_msb_en); #else - if (hal_cfg->mode & I2S_MODE_TX) { - i2s_ll_set_tx_sample_bit(hal->dev, chan_bits, data_bits); - } - if (hal_cfg->mode & I2S_MODE_RX) { - i2s_ll_set_rx_sample_bit(hal->dev, chan_bits, data_bits); - } + i2s_ll_rx_enable_msb_right(hal->dev, false); + i2s_ll_rx_enable_right_first(hal->dev, false); + i2s_ll_rx_force_enable_fifo_mod(hal->dev, true); #endif - //I2S standards config: Philip, MSB or PCM, Only I2S mode should do this configuration. - if ((hal_cfg->mode & (~(I2S_MODE_I2S))) == 0) { - i2s_hal_format_config(hal, hal_cfg); +} + +static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uint32_t chan_bits) +{ + switch (fmt) { + case I2S_COMM_FORMAT_STAND_MSB: + return chan_num * chan_bits / 2; + case I2S_COMM_FORMAT_STAND_PCM_SHORT: + return 1; + case I2S_COMM_FORMAT_STAND_PCM_LONG: + return chan_bits; + default: //I2S_COMM_FORMAT_STAND_I2S + return chan_num * chan_bits / 2; } } +void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + uint32_t chan_num = 2; + uint32_t chan_bits = hal_cfg->bits_cfg.chan_bits; + uint32_t data_bits = hal_cfg->bits_cfg.sample_bits; + + /* Set channel number and valid data bits */ +#if SOC_I2S_SUPPORTS_TDM + chan_num = hal_cfg->total_chan; + i2s_ll_tx_set_chan_num(hal->dev, chan_num); +#endif + i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits); + + /* Set communication format */ + bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; + uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits); + i2s_ll_tx_enable_msb_shift(hal->dev, shift_en); + i2s_ll_tx_set_ws_width(hal->dev, ws_width); +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_tx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2); +#endif +} + +void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + uint32_t chan_num = 2; + uint32_t chan_bits = hal_cfg->bits_cfg.chan_bits; + uint32_t data_bits = hal_cfg->bits_cfg.sample_bits; + +#if SOC_I2S_SUPPORTS_TDM + chan_num = hal_cfg->total_chan; + i2s_ll_rx_set_chan_num(hal->dev, chan_num); +#endif + i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits); + + /* Set communication format */ + bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; + uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits); + i2s_ll_rx_enable_msb_shift(hal->dev, shift_en); + i2s_ll_rx_set_ws_width(hal->dev, ws_width); +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_rx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2); +#endif +} + void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) { - 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_chan_mask(hal->dev, hal_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 (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_chan_mask(hal->dev, hal_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 (hal_cfg->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + if ((hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) || (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN)) { if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) { - i2s_ll_build_in_dac_ena(hal->dev); + i2s_ll_enable_builtin_dac(hal->dev, true); } if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) { - i2s_ll_build_in_adc_ena(hal->dev); + i2s_ll_enable_builtin_adc(hal->dev, true); } - // Buildin ADC and DAC have nothing to do with communication format configuration. + /* Use builtin ADC/DAC, return directly. */ return; + } else { + i2s_ll_enable_builtin_dac(hal->dev, false); + i2s_ll_enable_builtin_adc(hal->dev, false); } #endif -#if SOC_I2S_SUPPORTS_PDM_TX if (hal_cfg->mode & I2S_MODE_TX) { + i2s_ll_tx_stop(hal->dev); + i2s_ll_tx_reset(hal->dev); + i2s_ll_tx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //TX Slave if (hal_cfg->mode & I2S_MODE_PDM) { - i2s_ll_tx_pdm_cfg(hal->dev, hal_cfg->sample_rate); + /* Set tx pdm mode */ + i2s_hal_tx_set_pdm_mode(hal, hal_cfg->sample_rate); } else { - i2s_ll_set_tx_pdm_en(hal->dev, false); + /* Set tx common mode */ + i2s_hal_tx_set_common_mode(hal, hal_cfg); + i2s_hal_tx_set_channel_style(hal, hal_cfg); } } -#endif // SOC_I2S_SUPPORTS_PDM_TX -#if SOC_I2S_SUPPORTS_PDM_RX if (hal_cfg->mode & I2S_MODE_RX) { + i2s_ll_rx_stop(hal->dev); + i2s_ll_rx_reset(hal->dev); + i2s_ll_rx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //RX Slave if (hal_cfg->mode & I2S_MODE_PDM) { - i2s_ll_rx_pdm_cfg(hal->dev); + /* Set rx pdm mode */ + i2s_hal_rx_set_pdm_mode(hal); } else { - i2s_ll_set_rx_pdm_en(hal->dev, false); + /* Set rx common mode */ + i2s_hal_rx_set_common_mode(hal, hal_cfg); + i2s_hal_rx_set_channel_style(hal, hal_cfg); } } -#endif // SOC_I2S_SUPPORTS_PDM_RX - //Configure I2S chan number,sample bit. - i2s_hal_samples_config(hal, hal_cfg); } diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index be07a92e41..ee5c32abc3 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -57,15 +57,10 @@ typedef struct { #if SOC_I2S_SUPPORTS_TDM uint32_t total_chan; /*!< Total number of I2S channels */ uint32_t chan_mask; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<dev) +#define i2s_hal_reset_tx(hal) i2s_ll_tx_reset((hal)->dev) /** * @brief Reset I2S TX fifo * * @param hal Context of the HAL layer */ -#define i2s_hal_reset_tx_fifo(hal) i2s_ll_reset_tx_fifo((hal)->dev) +#define i2s_hal_reset_tx_fifo(hal) i2s_ll_tx_reset_fifo((hal)->dev) /** * @brief Reset I2S RX channel * * @param hal Context of the HAL layer */ -#define i2s_hal_reset_rx(hal) i2s_ll_reset_rx((hal)->dev) +#define i2s_hal_reset_rx(hal) i2s_ll_rx_reset((hal)->dev) /** * @brief Reset I2S RX fifo * * @param hal Context of the HAL layer */ -#define i2s_hal_reset_rx_fifo(hal) i2s_ll_reset_rx_fifo((hal)->dev) +#define i2s_hal_reset_rx_fifo(hal) i2s_ll_rx_reset_fifo((hal)->dev) /** * @brief Init the I2S hal. This function should be called first before other hal layer function is called @@ -122,12 +117,20 @@ void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel); /** - * @brief Configure communication format + * @brief Set Tx channel style * * @param hal Context of the HAL layer * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_samples_config(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); +void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); + +/** + * @brief Set Rx channel style + * + * @param hal Context of the HAL layer + * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` + */ +void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** * @brief Config I2S param @@ -156,28 +159,28 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); * * @param hal Context of the HAL layer */ -#define i2s_hal_start_tx(hal) i2s_ll_start_tx((hal)->dev) +#define i2s_hal_start_tx(hal) i2s_ll_tx_start((hal)->dev) /** * @brief Start I2S rx * * @param hal Context of the HAL layer */ -#define i2s_hal_start_rx(hal) i2s_ll_start_rx((hal)->dev) +#define i2s_hal_start_rx(hal) i2s_ll_rx_start((hal)->dev) /** * @brief Stop I2S tx * * @param hal Context of the HAL layer */ -#define i2s_hal_stop_tx(hal) i2s_ll_stop_tx((hal)->dev) +#define i2s_hal_stop_tx(hal) i2s_ll_tx_stop((hal)->dev) /** * @brief Stop I2S rx * * @param hal Context of the HAL layer */ -#define i2s_hal_stop_rx(hal) i2s_ll_stop_rx((hal)->dev) +#define i2s_hal_stop_rx(hal) i2s_ll_rx_stop((hal)->dev) /** * @brief Set the received data length to trigger `in_suc_eof` interrupt. @@ -185,7 +188,7 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); * @param hal Context of the HAL layer * @param eof_byte The byte length that trigger in_suc_eof interrupt. */ -#define i2s_hal_set_rx_eof_num(hal, eof_byte) i2s_ll_set_rx_eof_num((hal)->dev, eof_byte) +#define i2s_hal_set_rx_eof_num(hal, eof_byte) i2s_ll_rx_set_eof_num((hal)->dev, eof_byte) /** * @brief Set I2S TX sample bit @@ -194,7 +197,7 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); * @param chan_bit I2S TX chan bit * @param data_bit The sample data bit length. */ -#define i2s_hal_set_tx_sample_bit(hal, chan_bit, data_bit) i2s_ll_set_tx_sample_bit((hal)->dev, chan_bit, data_bit) +#define i2s_hal_set_tx_sample_bit(hal, chan_bit, data_bit) i2s_ll_tx_set_sample_bit((hal)->dev, chan_bit, data_bit) /** * @brief Set I2S RX sample bit @@ -203,7 +206,7 @@ void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); * @param chan_bit I2S RX chan bit * @param data_bit The sample data bit length. */ -#define i2s_hal_set_rx_sample_bit(hal, chan_bit, data_bit) i2s_ll_set_rx_sample_bit((hal)->dev, chan_bit, data_bit) +#define i2s_hal_set_rx_sample_bit(hal, chan_bit, data_bit) i2s_ll_rx_set_sample_bit((hal)->dev, chan_bit, data_bit) /** * @brief Configure I2S TX module clock devider @@ -232,7 +235,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` */ -#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_pcm_cfg((hal)->dev, cfg) +#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_set_pcm_type((hal)->dev, cfg) /** * @brief Configure I2S RX PCM encoder or decoder. @@ -240,7 +243,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` */ -#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_pcm_cfg((hal)->dev, cfg) +#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_set_pcm_type((hal)->dev, cfg) #endif /** @@ -248,7 +251,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_sig_loopback(hal) i2s_ll_loop_back_ena((hal)->dev, true) +#define i2s_hal_enable_sig_loopback(hal) i2s_ll_enable_loop_back((hal)->dev, true) #if SOC_I2S_SUPPORTS_PDM_TX /** @@ -259,16 +262,25 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param fp TX PDM fp paramater configuration * @param fs TX PDM fs paramater configuration */ -#define i2s_hal_set_tx_pdm_fpfs(hal, fp, fs) i2s_ll_set_tx_pdm_fpfs((hal)->dev, fp, fs) +#define i2s_hal_set_tx_pdm_fpfs(hal, fp, fs) i2s_ll_tx_set_pdm_fpfs((hal)->dev, fp, fs) /** - * @brief Get I2S TX PDM configuration + * @brief Get I2S TX PDM fp * * @param hal Context of the HAL layer - * @param fp Pointer to accept TX PDM fp paramater configuration - * @param fs Pointer to accept TX PDM fs paramater configuration + * @return + * - fp configuration paramater */ -#define i2s_hal_get_tx_pdm_fpfs(hal, fp, fs) i2s_ll_get_tx_pdm_fpfs((hal)->dev, (uint32_t *)fp, (uint32_t *)fs) +#define i2s_hal_get_tx_pdm_fp(hal) i2s_ll_tx_get_pdm_fp((hal)->dev) + +/** + * @brief Get I2S TX PDM fs + * + * @param hal Context of the HAL layer + * @return + * - fs configuration paramater + */ +#define i2s_hal_get_tx_pdm_fs(hal) i2s_ll_tx_get_pdm_fs((hal)->dev) #endif #if SOC_I2S_SUPPORTS_PDM_RX @@ -279,7 +291,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param dsr PDM downsample configuration paramater */ -#define i2s_hal_set_rx_pdm_dsr(hal, dsr) i2s_ll_set_pdm_rx_dsr((hal)->dev, dsr) +#define i2s_hal_set_rx_pdm_dsr(hal, dsr) i2s_ll_rx_set_pdm_dsr((hal)->dev, dsr) /** * @brief Get RX PDM downsample configuration @@ -287,7 +299,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param dsr Pointer to accept PDM downsample configuration */ -#define i2s_hal_get_rx_pdm_dsr(hal, dsr) i2s_ll_get_pdm_rx_dsr((hal)->dev, dsr) +#define i2s_hal_get_rx_pdm_dsr(hal, dsr) i2s_ll_rx_get_pdm_dsr((hal)->dev, dsr) #endif #if !SOC_GDMA_SUPPORTED @@ -296,22 +308,37 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * * @param hal Context of the HAL layer */ -#define i2s_hal_attach_tx_dma(hal) i2s_ll_dma_enable((hal)->dev,true) +#define i2s_hal_enable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,true) /** * @brief Enable I2S RX DMA * * @param hal Context of the HAL layer */ -#define i2s_hal_attach_rx_dma(hal) i2s_ll_dma_enable((hal)->dev,true) +#define i2s_hal_enable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,true) + +/** + * @brief Disable I2S TX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,false) + +/** + * @brief Disable I2S RX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,false) /** * @brief Get I2S interrupt status * * @param hal Context of the HAL layer - * @param status Pointer to accept I2S interrupt status + * @return + * - module interrupt status */ -#define i2s_hal_get_intr_status(hal, status) i2s_ll_get_intr_status((hal)->dev, status) +#define i2s_hal_get_intr_status(hal) i2s_ll_get_intr_status((hal)->dev) /** * @brief Get I2S interrupt status @@ -326,28 +353,28 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_rx_intr(hal) i2s_ll_enable_rx_intr((hal)->dev) +#define i2s_hal_enable_rx_intr(hal) i2s_ll_rx_enable_intr((hal)->dev) /** * @brief Disable I2S RX interrupt * * @param hal Context of the HAL layer */ -#define i2s_hal_disable_rx_intr(hal) i2s_ll_disable_rx_intr((hal)->dev) +#define i2s_hal_disable_rx_intr(hal) i2s_ll_rx_disable_intr((hal)->dev) /** * @brief Disable I2S TX interrupt * * @param hal Context of the HAL layer */ -#define i2s_hal_disable_tx_intr(hal) i2s_ll_disable_tx_intr((hal)->dev) +#define i2s_hal_disable_tx_intr(hal) i2s_ll_tx_disable_intr((hal)->dev) /** * @brief Enable I2S TX interrupt * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_tx_intr(hal) i2s_ll_enable_tx_intr((hal)->dev) +#define i2s_hal_enable_tx_intr(hal) i2s_ll_tx_enable_intr((hal)->dev) /** * @brief Configure TX DMA descriptor address and start TX DMA @@ -355,7 +382,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param link_addr DMA descriptor link address. */ -#define i2s_hal_start_tx_link(hal, link_addr) i2s_ll_start_tx_link((hal)->dev, link_addr) +#define i2s_hal_start_tx_link(hal, link_addr) i2s_ll_tx_start_link((hal)->dev, link_addr) /** * @brief Configure RX DMA descriptor address and start RX DMA @@ -363,35 +390,35 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param link_addr DMA descriptor link address. */ -#define i2s_hal_start_rx_link(hal, link_addr) i2s_ll_start_rx_link((hal)->dev, link_addr) +#define i2s_hal_start_rx_link(hal, link_addr) i2s_ll_rx_start_link((hal)->dev, link_addr) /** * @brief Stop TX DMA link * * @param hal Context of the HAL layer */ -#define i2s_hal_stop_tx_link(hal) i2s_ll_stop_out_link((hal)->dev) +#define i2s_hal_stop_tx_link(hal) i2s_ll_tx_stop_link((hal)->dev) /** * @brief Stop RX DMA link * * @param hal Context of the HAL layer */ -#define i2s_hal_stop_rx_link(hal) i2s_ll_stop_in_link((hal)->dev) +#define i2s_hal_stop_rx_link(hal) i2s_ll_rx_stop_link((hal)->dev) /** * @brief Reset RX DMA * * @param hal Context of the HAL layer */ -#define i2s_hal_reset_rxdma(hal) i2s_ll_reset_dma_in((hal)->dev) +#define i2s_hal_reset_rxdma(hal) i2s_ll_rx_reset_dma((hal)->dev) /** * @brief Reset TX DMA * * @param hal Context of the HAL layer */ -#define i2s_hal_reset_txdma(hal) i2s_ll_reset_dma_out((hal)->dev) +#define i2s_hal_reset_txdma(hal) i2s_ll_tx_reset_dma((hal)->dev) /** * @brief Get I2S out eof descriptor address @@ -399,7 +426,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param addr Pointer to accept out eof des address */ -#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_get_out_eof_des_addr((hal)->dev, addr) +#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_tx_get_eof_des_addr((hal)->dev, addr) /** * @brief Get I2S in suc eof descriptor address @@ -407,7 +434,7 @@ void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, uint32_t sclk, uint32_t fbc * @param hal Context of the HAL layer * @param addr Pointer to accept in suc eof des address */ -#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_get_in_eof_des_addr((hal)->dev, addr) +#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_rx_get_eof_des_addr((hal)->dev, addr) #endif #ifdef __cplusplus diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index 6b12b4812d..a42ad40d05 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -29,10 +29,10 @@ extern "C" { * */ typedef enum { - I2S_BITS_PER_SAMPLE_8BIT = 8, - I2S_BITS_PER_SAMPLE_16BIT = 16, - I2S_BITS_PER_SAMPLE_24BIT = 24, - I2S_BITS_PER_SAMPLE_32BIT = 32, + I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< data bit-width: 8 */ + I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< data bit-width: 16 */ + I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< data bit-width: 24 */ + I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< data bit-width: 32 */ } i2s_bits_per_sample_t; /** @@ -40,11 +40,11 @@ typedef enum { * */ typedef enum { - I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< chan bit equals to data bit*/ - I2S_BITS_PER_CHAN_8BIT = (8), /*!< chan bit 8*/ - I2S_BITS_PER_CHAN_16BIT = (16), /*!< chan bit 16*/ - I2S_BITS_PER_CHAN_24BIT = (24), /*!< chan bit 24*/ - I2S_BITS_PER_CHAN_32BIT = (32), /*!< chan bit 32*/ + I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< channel bit-width equals to data bit-width */ + I2S_BITS_PER_CHAN_8BIT = (8), /*!< channel bit-width: 8 */ + I2S_BITS_PER_CHAN_16BIT = (16), /*!< channel bit-width: 16 */ + I2S_BITS_PER_CHAN_24BIT = (24), /*!< channel bit-width: 24 */ + I2S_BITS_PER_CHAN_32BIT = (32), /*!< channel bit-width: 32 */ } i2s_bits_per_chan_t; /** @@ -93,7 +93,7 @@ typedef enum { 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*/ + 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`*/ @@ -108,13 +108,14 @@ typedef enum { * @brief I2S channel format type */ typedef enum { - I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00, - I2S_CHANNEL_FMT_ALL_RIGHT, - I2S_CHANNEL_FMT_ALL_LEFT, - I2S_CHANNEL_FMT_ONLY_RIGHT, - I2S_CHANNEL_FMT_ONLY_LEFT, + I2S_CHANNEL_FMT_RIGHT_LEFT, /*!< Separated left and right channel */ + I2S_CHANNEL_FMT_ALL_RIGHT, /*!< Load right channel data in both two channels */ + I2S_CHANNEL_FMT_ALL_LEFT, /*!< Load left channel data in both two channels */ + I2S_CHANNEL_FMT_ONLY_RIGHT, /*!< Only load data in right channel */ + I2S_CHANNEL_FMT_ONLY_LEFT, /*!< Only load data in left channel */ #if SOC_I2S_SUPPORTS_TDM - I2S_CHANNEL_FMT_TDM, // Up to 16 channels + // Multiple channels are available with TDM feature + I2S_CHANNEL_FMT_MULTIPLE, /*!< More than two channels are used */ #endif } i2s_channel_fmt_t; @@ -183,6 +184,15 @@ typedef enum { } i2s_pdm_dsr_t; #endif +#if SOC_I2S_SUPPORTS_PDM_TX +typedef enum { + I2S_PDM_SIG_SCALING_DIV_2 = 0, /*!< I2S TX PDM sigmadelta signal scaling: /2 */ + I2S_PDM_SIG_SCALING_MUL_1 = 1, /*!< I2S TX PDM sigmadelta signal scaling: x1 */ + I2S_PDM_SIG_SCALING_MUL_2 = 2, /*!< I2S TX PDM sigmadelta signal scaling: x2 */ + I2S_PDM_SIG_SCALING_MUL_4 = 3, /*!< I2S TX PDM sigmadelta signal scaling: x4 */ +} i2s_pdm_sig_scale_t; +#endif + /** * @brief PDM PCM convter enable/disable. * diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 1557305eef..cb25945ed5 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -111,12 +111,8 @@ #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_CODEC (1) #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 -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 40a4ecb249..9b7f87eebc 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -108,12 +108,8 @@ #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_CODEC (1) #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 -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) diff --git a/components/soc/esp32s3/include/soc/i2s_struct.h b/components/soc/esp32s3/include/soc/i2s_struct.h index 1699ab9128..fc02adc0b8 100644 --- a/components/soc/esp32s3/include/soc/i2s_struct.h +++ b/components/soc/esp32s3/include/soc/i2s_struct.h @@ -319,7 +319,7 @@ typedef volatile struct { }; uint32_t val; } rx_eof_num; - uint32_t conf_signal_data; /*I2S signal data register*/ + uint32_t conf_single_data; /*the right channel or left channel put out constant value stored in this register according to tx_chan_mod and reg_tx_msb_right*/ union { struct { uint32_t tx_idle : 1; /*1: i2s_tx is idle state. 0: i2s_tx is working.*/ diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index f2fda6ab00..b3680c6bd8 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -67,6 +67,7 @@ #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM_TX (1) #define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_SUPPORTS_PDM_CODEC (1) #define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index 55b9c883b3..73498c6d59 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -257,7 +257,7 @@ Example for general usage. i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver - I2S on {IDF_TARGET_NAME} support TDM mode, up to 16 channels are available in TDM mode. If you want to use TDM mode, set field ``channel_format`` of :cpp:type:`i2s_config_t` to ``I2S_CHANNEL_FMT_TDM``. Then enable the channels by setting ``tdm_chan_cfg.chan_mask`` using masks in :cpp:type:`i2s_channel_t`, the number of active channels and total channels will be calculate automatically. Also you can set a particular total channel number for it, but it shouldn't be smaller than the largest channel you use. + I2S on {IDF_TARGET_NAME} support TDM mode, up to 16 channels are available in TDM mode. If you want to use TDM mode, set field ``channel_format`` of :cpp:type:`i2s_config_t` to ``I2S_CHANNEL_FMT_MULTIPLE``. Then enable the channels by setting ``tdm_chan_cfg.chan_mask`` using masks in :cpp:type:`i2s_channel_t`, the number of active channels and total channels will be calculate automatically. Also you can set a particular total channel number for it, but it shouldn't be smaller than the largest channel you use. .. code-block:: c @@ -269,7 +269,7 @@ Example for general usage. .mode = I2S_MODE_MASTER | I2S_MODE_TX, .sample_rate = 44100, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, - .channel_format = I2S_CHANNEL_FMT_TDM, + .channel_format = I2S_CHANNEL_FMT_MULTIPLE, .communication_format = I2S_COMM_FORMAT_STAND_I2S .tx_desc_auto_clear = false, .dma_buf_count = 8,