|
|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
|
|
+ * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
|
|
*
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
*/
|
|
|
@@ -8,356 +8,282 @@
|
|
|
// The HAL layer for I2S (common part)
|
|
|
|
|
|
#include "soc/soc.h"
|
|
|
-#include "soc/soc_caps.h"
|
|
|
#include "hal/i2s_hal.h"
|
|
|
|
|
|
-/**
|
|
|
- * @brief Calculate the closest sample rate clock configuration.
|
|
|
- * clock relationship:
|
|
|
- * Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a)
|
|
|
- *
|
|
|
- * @param clk_cfg I2S clock configuration(input)
|
|
|
- * @param cal Point to `i2s_ll_mclk_div_t` structure(output).
|
|
|
- */
|
|
|
-static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal)
|
|
|
-{
|
|
|
- int ma = 0;
|
|
|
- int mb = 0;
|
|
|
- cal->mclk_div = clk_cfg->mclk_div;
|
|
|
- cal->a = 1;
|
|
|
- cal->b = 0;
|
|
|
-
|
|
|
- uint32_t freq_diff = abs((int)clk_cfg->sclk - (int)(clk_cfg->mclk * cal->mclk_div));
|
|
|
- if (!freq_diff) {
|
|
|
- return;
|
|
|
- }
|
|
|
- float decimal = freq_diff / (float)clk_cfg->mclk;
|
|
|
- // Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
|
|
|
- if (decimal > 125.0 / 126.0) {
|
|
|
- cal->mclk_div++;
|
|
|
- return;
|
|
|
- }
|
|
|
- uint32_t min = ~0;
|
|
|
- for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
|
|
|
- // Calculate the closest 'b' in this loop, no need to loop 'b' to seek the closest value
|
|
|
- int b = (int)(a * (freq_diff / (double)clk_cfg->mclk) + 0.5);
|
|
|
- ma = freq_diff * a;
|
|
|
- mb = clk_cfg->mclk * b;
|
|
|
- if (ma == mb) {
|
|
|
- cal->a = a;
|
|
|
- cal->b = b;
|
|
|
- return;
|
|
|
- }
|
|
|
- if (abs((mb - ma)) < min) {
|
|
|
- cal->a = a;
|
|
|
- cal->b = b;
|
|
|
- min = abs(mb - ma);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel)
|
|
|
-{
|
|
|
- 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, i2s_hal_clock_cfg_t *clk_cfg)
|
|
|
-{
|
|
|
- i2s_ll_mclk_div_t mclk_set;
|
|
|
- i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
|
|
|
- i2s_ll_tx_set_clk(hal->dev, &mclk_set);
|
|
|
- i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
|
|
|
-}
|
|
|
-
|
|
|
-void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg)
|
|
|
-{
|
|
|
- i2s_ll_mclk_div_t mclk_set;
|
|
|
- i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set);
|
|
|
- i2s_ll_rx_set_clk(hal->dev, &mclk_set);
|
|
|
- i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div);
|
|
|
-}
|
|
|
-
|
|
|
-void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal)
|
|
|
-{
|
|
|
- i2s_ll_tx_set_slave_mod(hal->dev, false); //TX master
|
|
|
- i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
|
|
|
-}
|
|
|
-
|
|
|
-void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal)
|
|
|
-{
|
|
|
- i2s_ll_tx_set_slave_mod(hal->dev, true); //TX Slave
|
|
|
- i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave
|
|
|
-}
|
|
|
+#include "hal/i2s_std.h"
|
|
|
+#include "hal/i2s_pdm.h"
|
|
|
+#include "hal/i2s_tdm.h"
|
|
|
+
|
|
|
+#if SOC_I2S_HW_VERSION_2 && SOC_I2S_SUPPORTS_PDM_TX
|
|
|
+/* PDM tx high pass filter cut-off frequency and coeffecients list
|
|
|
+ * [0]: cut-off frequency; [1]: param0; [2]: param5 */
|
|
|
+static const float cut_off_coef[21][3] = {
|
|
|
+ {185, 0, 0}, {172, 0, 1}, {160, 1, 1},
|
|
|
+ {150, 1, 2}, {137, 2, 2}, {126, 2, 3},
|
|
|
+ {120, 0, 3}, {115, 3, 3}, {106, 1, 7},
|
|
|
+ {104, 2, 4}, {92, 4, 4}, {91.5, 2, 7},
|
|
|
+ {81, 4, 5}, {77.2, 3, 7}, {69, 5, 5},
|
|
|
+ {63, 4, 7}, {58, 5, 6}, {49, 5, 7},
|
|
|
+ {46, 6, 6}, {35.5, 6, 7}, {23.3, 7, 7}};
|
|
|
+#endif
|
|
|
|
|
|
-void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
|
|
|
+void i2s_hal_init(i2s_hal_context_t *hal, int port_id)
|
|
|
{
|
|
|
/* Get hardware instance */
|
|
|
- hal->dev = I2S_LL_GET_HW(i2s_num);
|
|
|
+ hal->dev = I2S_LL_GET_HW(port_id);
|
|
|
}
|
|
|
|
|
|
-#if SOC_I2S_SUPPORTS_PDM_TX
|
|
|
-void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate)
|
|
|
+void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src)
|
|
|
{
|
|
|
- /* enable pdm tx mode */
|
|
|
- i2s_ll_tx_enable_pdm(hal->dev, true);
|
|
|
-#if SOC_I2S_SUPPORTS_TDM
|
|
|
+#if SOC_I2S_HW_VERSION_2
|
|
|
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);
|
|
|
- /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
|
|
- i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
|
|
|
-#else
|
|
|
- i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+ i2s_ll_mclk_bind_to_tx_clk(hal->dev);
|
|
|
#endif
|
|
|
- /* 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
|
|
|
+ i2s_ll_tx_clk_set_src(hal->dev, clk_src);
|
|
|
+ i2s_ll_tx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
|
|
|
+ i2s_ll_tx_set_bck_div_num(hal->dev, clk_info->bclk_div);
|
|
|
}
|
|
|
-#endif // SOC_I2S_SUPPORTS_PDM_TX
|
|
|
|
|
|
-#if SOC_I2S_SUPPORTS_PDM_RX
|
|
|
-void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal)
|
|
|
+void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_clock_info_t *clk_info, i2s_clock_src_t clk_src)
|
|
|
{
|
|
|
- /* 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);
|
|
|
-#if SOC_I2S_SUPPORTS_TDM
|
|
|
+#if SOC_I2S_HW_VERSION_2
|
|
|
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);
|
|
|
- /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
|
|
- i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1);
|
|
|
-#else
|
|
|
- i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+ i2s_ll_mclk_bind_to_rx_clk(hal->dev);
|
|
|
#endif
|
|
|
+ i2s_ll_rx_clk_set_src(hal->dev, clk_src);
|
|
|
+ i2s_ll_rx_set_mclk(hal->dev, clk_info->sclk, clk_info->mclk, clk_info->mclk_div);
|
|
|
+ i2s_ll_rx_set_bck_div_num(hal->dev, clk_info->bclk_div);
|
|
|
}
|
|
|
-#endif // SOC_I2S_SUPPORTS_PDM_RX
|
|
|
|
|
|
-
|
|
|
-void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
|
|
+/*-------------------------------------------------------------------------
|
|
|
+ | STD Specific Slot Configurations |
|
|
|
+ -------------------------------------------------------------------------*/
|
|
|
+void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
{
|
|
|
- /* Disable PDM tx mode and enable TDM mode (if support) */
|
|
|
- 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);
|
|
|
-
|
|
|
- // In TDM mode(more than 2 channels), the ws polarity should be high first.
|
|
|
- if (hal_cfg->total_chan > 2) {
|
|
|
- i2s_ll_tx_set_ws_idle_pol(hal->dev, true);
|
|
|
- }
|
|
|
- i2s_ll_tx_enable_left_align(hal->dev, hal_cfg->left_align);
|
|
|
- i2s_ll_tx_enable_big_endian(hal->dev, hal_cfg->big_edin);
|
|
|
- i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
|
|
|
- i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->skip_msk);
|
|
|
-#else
|
|
|
- i2s_ll_tx_enable_msb_right(hal->dev, false);
|
|
|
- i2s_ll_tx_enable_right_first(hal->dev, false);
|
|
|
+ i2s_std_slot_config_t *slot_cfg = (i2s_std_slot_config_t*)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ i2s_ll_tx_reset(hal->dev);
|
|
|
+ i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
|
|
|
+ i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+ i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
|
|
|
+ i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width);
|
|
|
+#if SOC_I2S_HW_VERSION_1
|
|
|
+ i2s_ll_tx_enable_msb_right(hal->dev, slot_cfg->msb_right);
|
|
|
+ i2s_ll_tx_enable_right_first(hal->dev, slot_cfg->ws_pol);
|
|
|
+ /* Should always enable fifo */
|
|
|
i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+#elif SOC_I2S_HW_VERSION_2
|
|
|
+ /* There are always 2 slots in std mode */
|
|
|
+ i2s_ll_tx_set_chan_num(hal->dev, 2);
|
|
|
+ /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot
|
|
|
+ * Otherwise always enable the first two slots */
|
|
|
+ i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03);
|
|
|
+ i2s_ll_tx_set_half_sample_bit(hal->dev, slot_bit_width);
|
|
|
+ i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
|
|
|
+ i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
|
|
|
+ i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->left_align);
|
|
|
+ i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->big_endian);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
|
|
+void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
{
|
|
|
- /* Disable PDM rx mode and enable TDM rx mode (if support)*/
|
|
|
- i2s_ll_rx_enable_pdm(hal->dev, false);
|
|
|
-
|
|
|
-#if SOC_I2S_SUPPORTS_TDM
|
|
|
- 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);
|
|
|
-
|
|
|
- // In TDM mode(more than 2 channels), the ws polarity should be high first.
|
|
|
- if (hal_cfg->total_chan > 2) {
|
|
|
- i2s_ll_rx_set_ws_idle_pol(hal->dev, true);
|
|
|
- }
|
|
|
- i2s_ll_rx_enable_left_align(hal->dev, hal_cfg->left_align);
|
|
|
- i2s_ll_rx_enable_big_endian(hal->dev, hal_cfg->big_edin);
|
|
|
- i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->bit_order_msb);
|
|
|
-#else
|
|
|
- i2s_ll_rx_enable_msb_right(hal->dev, false);
|
|
|
- i2s_ll_rx_enable_right_first(hal->dev, false);
|
|
|
+ i2s_std_slot_config_t *slot_cfg = (i2s_std_slot_config_t*)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ i2s_ll_rx_reset(hal->dev);
|
|
|
+ i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
|
|
|
+ i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+ i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
|
|
|
+ i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->ws_width);
|
|
|
+#if SOC_I2S_HW_VERSION_1
|
|
|
+ i2s_ll_rx_enable_msb_right(hal->dev, slot_cfg->msb_right);
|
|
|
+ i2s_ll_rx_enable_right_first(hal->dev, slot_cfg->ws_pol);
|
|
|
+ /* Should always enable fifo */
|
|
|
i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+#elif SOC_I2S_HW_VERSION_2
|
|
|
+ /* There are always 2 slots in std mode */
|
|
|
+ i2s_ll_rx_set_chan_num(hal->dev, 2);
|
|
|
+ /* In mono mode, there only should be one slot enabled, another inactive slot will transmit same data as enabled slot
|
|
|
+ * Otherwise always enable the first two slots */
|
|
|
+ i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 0x01 : 0x03);
|
|
|
+ i2s_ll_rx_set_half_sample_bit(hal->dev, slot_bit_width);
|
|
|
+ i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
|
|
|
+ i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
|
|
|
+ i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->left_align);
|
|
|
+ i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->big_endian);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uint32_t chan_bits)
|
|
|
+void i2s_hal_std_enable_tx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
- 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;
|
|
|
- }
|
|
|
+ i2s_ll_tx_enable_std(hal->dev);
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
|
|
+void i2s_hal_std_enable_rx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
- uint32_t chan_num = 2;
|
|
|
- uint32_t chan_bits = hal_cfg->chan_bits;
|
|
|
- uint32_t data_bits = hal_cfg->sample_bits;
|
|
|
- bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
|
|
|
- (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
|
|
|
-
|
|
|
- /* Set channel number and valid data bits */
|
|
|
-#if SOC_I2S_SUPPORTS_TDM
|
|
|
- chan_num = hal_cfg->total_chan;
|
|
|
- i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
|
|
|
- i2s_ll_tx_set_chan_num(hal->dev, chan_num);
|
|
|
-#endif
|
|
|
- i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits);
|
|
|
- i2s_ll_tx_enable_mono_mode(hal->dev, is_mono);
|
|
|
+ i2s_ll_rx_enable_std(hal->dev);
|
|
|
+}
|
|
|
|
|
|
- /* 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);
|
|
|
+/*-------------------------------------------------------------------------
|
|
|
+ | PDM Specific Slot Configurations |
|
|
|
+ -------------------------------------------------------------------------*/
|
|
|
+#if SOC_I2S_SUPPORTS_PDM_TX
|
|
|
+void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
+{
|
|
|
+ i2s_pdm_tx_slot_config_t *slot_cfg = (i2s_pdm_tx_slot_config_t *)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ i2s_ll_tx_reset(hal->dev);
|
|
|
+ i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
|
|
|
+ i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+
|
|
|
+ i2s_ll_tx_set_pdm_prescale(hal->dev, slot_cfg->sd_prescale);
|
|
|
+ i2s_ll_tx_set_pdm_hp_scale(hal->dev, slot_cfg->hp_scale);
|
|
|
+ i2s_ll_tx_set_pdm_lp_scale(hal->dev, slot_cfg->lp_scale);
|
|
|
+ i2s_ll_tx_set_pdm_sinc_scale(hal->dev, slot_cfg->sinc_scale);
|
|
|
+ i2s_ll_tx_set_pdm_sd_scale(hal->dev, slot_cfg->sd_scale);
|
|
|
+
|
|
|
+#if SOC_I2S_HW_VERSION_1
|
|
|
+ i2s_ll_tx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+#elif SOC_I2S_HW_VERSION_2
|
|
|
+ /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
|
|
+ i2s_ll_tx_set_active_chan_mask(hal->dev, I2S_TDM_SLOT0 | I2S_TDM_SLOT1);
|
|
|
+ i2s_ll_tx_enable_pdm_hp_filter(hal->dev, slot_cfg->hp_en);
|
|
|
+ uint8_t cnt = 0;
|
|
|
+ float min = 1000;
|
|
|
+ float expt_cut_off = slot_cfg->hp_cut_off_freq_hz;
|
|
|
+ /* Find the closest cut-off frequency and its coefficients */
|
|
|
+ for (int i = 0; i < 21; i++) {
|
|
|
+ float tmp = cut_off_coef[i][0] < expt_cut_off ? expt_cut_off - cut_off_coef[i][0] : cut_off_coef[i][0] - expt_cut_off;
|
|
|
+ if (tmp < min) {
|
|
|
+ min = tmp;
|
|
|
+ cnt = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, cut_off_coef[cnt][1]);
|
|
|
+ i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, cut_off_coef[cnt][2]);
|
|
|
+ i2s_ll_tx_enable_pdm_sd_codec(hal->dev, slot_cfg->sd_en);
|
|
|
+ i2s_ll_tx_set_pdm_sd_dither(hal->dev, slot_cfg->sd_dither);
|
|
|
+ i2s_ll_tx_set_pdm_sd_dither2(hal->dev, slot_cfg->sd_dither2);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
|
|
+void i2s_hal_pdm_enable_tx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
- uint32_t chan_num = 2;
|
|
|
- uint32_t chan_bits = hal_cfg->chan_bits;
|
|
|
- uint32_t data_bits = hal_cfg->sample_bits;
|
|
|
- bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) ||
|
|
|
- (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT);
|
|
|
-
|
|
|
-#if SOC_I2S_SUPPORTS_TDM
|
|
|
- chan_num = hal_cfg->total_chan;
|
|
|
- i2s_ll_rx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask >> 16);
|
|
|
- i2s_ll_rx_set_chan_num(hal->dev, chan_num);
|
|
|
+ i2s_ll_tx_enable_pdm(hal->dev);
|
|
|
+}
|
|
|
#endif
|
|
|
- i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits);
|
|
|
- i2s_ll_rx_enable_mono_mode(hal->dev, is_mono);
|
|
|
|
|
|
- /* 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);
|
|
|
+#if SOC_I2S_SUPPORTS_PDM_RX
|
|
|
+void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
+{
|
|
|
+ i2s_pdm_rx_slot_config_t *slot_cfg = (i2s_pdm_rx_slot_config_t *)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ i2s_ll_rx_reset(hal->dev);
|
|
|
+ i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
|
|
|
+ i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+#if SOC_I2S_HW_VERSION_1
|
|
|
+ i2s_ll_rx_force_enable_fifo_mod(hal->dev, true);
|
|
|
+#elif SOC_I2S_HW_VERSION_2
|
|
|
+ /* Still need to enable the first 2 TDM channel mask to get the correct number of frame */
|
|
|
+ i2s_ll_rx_set_active_chan_mask(hal->dev, I2S_TDM_SLOT0 | I2S_TDM_SLOT1);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg)
|
|
|
+void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
-#if SOC_I2S_SUPPORTS_ADC
|
|
|
- if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) {
|
|
|
- /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel.
|
|
|
- * In the current stage, we only support ADC1 and single channel mode.
|
|
|
- * In default data mode, the ADC data is in 12-bit resolution mode.
|
|
|
- */
|
|
|
- i2s_ll_enable_builtin_adc(hal->dev, true);
|
|
|
- return;
|
|
|
- }
|
|
|
- i2s_ll_enable_builtin_adc(hal->dev, false);
|
|
|
-#endif
|
|
|
-#if SOC_I2S_SUPPORTS_DAC
|
|
|
- if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) {
|
|
|
- i2s_ll_enable_builtin_dac(hal->dev, true);
|
|
|
- return;
|
|
|
- }
|
|
|
- i2s_ll_enable_builtin_dac(hal->dev, false);
|
|
|
-#endif
|
|
|
- /* Set configurations for TX mode */
|
|
|
- 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 SOC_I2S_SUPPORTS_PDM_TX
|
|
|
- if (hal_cfg->mode & I2S_MODE_PDM) {
|
|
|
- /* Set tx pdm mode */
|
|
|
- i2s_hal_tx_set_pdm_mode_default(hal, hal_cfg->sample_rate);
|
|
|
- } else
|
|
|
+ i2s_ll_rx_enable_pdm(hal->dev);
|
|
|
+}
|
|
|
#endif
|
|
|
- {
|
|
|
- /* Set tx common mode */
|
|
|
- i2s_hal_tx_set_common_mode(hal, hal_cfg);
|
|
|
- }
|
|
|
- i2s_hal_tx_set_channel_style(hal, hal_cfg);
|
|
|
- }
|
|
|
|
|
|
- /* Set configurations for RX mode */
|
|
|
- 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 SOC_I2S_SUPPORTS_PDM_RX
|
|
|
- if (hal_cfg->mode & I2S_MODE_PDM) {
|
|
|
- /* Set rx pdm mode */
|
|
|
- i2s_hal_rx_set_pdm_mode_default(hal);
|
|
|
- } else
|
|
|
-#endif
|
|
|
- {
|
|
|
- /* Set rx common mode */
|
|
|
- i2s_hal_rx_set_common_mode(hal, hal_cfg);
|
|
|
- }
|
|
|
- i2s_hal_rx_set_channel_style(hal, hal_cfg);
|
|
|
+/*-------------------------------------------------------------------------
|
|
|
+ | TDM Specific Slot Configurations |
|
|
|
+ -------------------------------------------------------------------------*/
|
|
|
+#if SOC_I2S_SUPPORTS_TDM
|
|
|
+void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
+{
|
|
|
+ i2s_tdm_slot_config_t *slot_cfg = (i2s_tdm_slot_config_t*)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ uint32_t cnt;
|
|
|
+ uint32_t msk = slot_cfg->slot_mask;
|
|
|
+ /* Get the maximum slot number */
|
|
|
+ cnt = 32 - __builtin_clz(msk);
|
|
|
+ /* There should be at least 2 slots in total even for mono mode */
|
|
|
+ cnt = cnt < 2 ? 2 : cnt;
|
|
|
+ uint32_t total_slot = slot_cfg->total_slot > cnt ? slot_cfg->total_slot : cnt;
|
|
|
+ i2s_ll_tx_reset(hal->dev);
|
|
|
+ i2s_ll_tx_set_slave_mod(hal->dev, is_slave); //TX Slave
|
|
|
+ i2s_ll_tx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_tx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+ i2s_ll_tx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
|
|
|
+ if (slot_cfg->ws_width == I2S_TDM_AUTO_WS_WIDTH) {
|
|
|
+ i2s_ll_tx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
|
|
|
+ } else {
|
|
|
+ i2s_ll_tx_set_ws_width(hal->dev, slot_cfg->ws_width);
|
|
|
}
|
|
|
|
|
|
- /* Set configurations for full-duplex mode */
|
|
|
- if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) {
|
|
|
- i2s_ll_share_bck_ws(hal->dev, true);
|
|
|
- if (hal_cfg->mode & I2S_MODE_MASTER) {
|
|
|
- i2s_hal_enable_master_fd_mode(hal);
|
|
|
- } else {
|
|
|
- i2s_hal_enable_slave_fd_mode(hal);
|
|
|
- }
|
|
|
- }
|
|
|
+ i2s_ll_tx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
|
|
|
+ i2s_ll_tx_set_chan_num(hal->dev, total_slot);
|
|
|
+ /* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
|
|
|
+ i2s_ll_tx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
|
|
|
+ I2S_TDM_SLOT0 : (uint32_t)slot_cfg->slot_mask);
|
|
|
+ i2s_ll_tx_set_skip_mask(hal->dev, slot_cfg->skip_mask);
|
|
|
+ i2s_ll_tx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2);
|
|
|
+ i2s_ll_tx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
|
|
|
+ i2s_ll_tx_enable_left_align(hal->dev, slot_cfg->left_align);
|
|
|
+ i2s_ll_tx_enable_big_endian(hal->dev, slot_cfg->big_endian);
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_start_tx(i2s_hal_context_t *hal)
|
|
|
+void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_slot_config_t *slot_config)
|
|
|
{
|
|
|
- i2s_ll_tx_start(hal->dev);
|
|
|
-}
|
|
|
+ i2s_tdm_slot_config_t *slot_cfg = (i2s_tdm_slot_config_t*)slot_config;
|
|
|
+ uint32_t slot_bit_width = (int)slot_cfg->slot_bit_width < (int)slot_cfg->data_bit_width ?
|
|
|
+ slot_cfg->data_bit_width : slot_cfg->slot_bit_width;
|
|
|
+ uint32_t cnt;
|
|
|
+ uint32_t msk = slot_cfg->slot_mask;
|
|
|
+ for (cnt = 0; msk; cnt++, msk >>= 1);
|
|
|
+ /* Get the maximum slot number */
|
|
|
+ cnt = 32 - __builtin_clz(msk);
|
|
|
+ /* There should be at least 2 slots in total even for mono mode */
|
|
|
+ cnt = cnt < 2 ? 2 : cnt;
|
|
|
+ uint32_t total_slot = slot_cfg->total_slot > cnt ? slot_cfg->total_slot : cnt;
|
|
|
+ i2s_ll_rx_reset(hal->dev);
|
|
|
+ i2s_ll_rx_set_slave_mod(hal->dev, is_slave); //RX Slave
|
|
|
+ i2s_ll_rx_set_sample_bit(hal->dev, slot_bit_width, slot_cfg->data_bit_width);
|
|
|
+ i2s_ll_rx_enable_mono_mode(hal->dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
|
|
|
+ i2s_ll_rx_enable_msb_shift(hal->dev, slot_cfg->bit_shift);
|
|
|
+ if (slot_cfg->ws_width == I2S_TDM_AUTO_WS_WIDTH) {
|
|
|
+ i2s_ll_rx_set_ws_width(hal->dev, (total_slot * slot_bit_width) / 2);
|
|
|
+ } else {
|
|
|
+ i2s_ll_rx_set_ws_width(hal->dev, slot_cfg->ws_width);
|
|
|
+ }
|
|
|
|
|
|
-void i2s_hal_start_rx(i2s_hal_context_t *hal)
|
|
|
-{
|
|
|
- i2s_ll_rx_start(hal->dev);
|
|
|
+ i2s_ll_rx_set_ws_idle_pol(hal->dev, slot_cfg->ws_pol);
|
|
|
+ i2s_ll_rx_set_chan_num(hal->dev, total_slot);
|
|
|
+ /* In mono mode, there only should be one slot enabled, other inactive slots will transmit same data as enabled slot */
|
|
|
+ i2s_ll_rx_set_active_chan_mask(hal->dev, (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ?
|
|
|
+ I2S_TDM_SLOT0 : (uint32_t)slot_cfg->slot_mask);
|
|
|
+ i2s_ll_rx_set_half_sample_bit(hal->dev, total_slot * slot_bit_width / 2);
|
|
|
+ i2s_ll_rx_set_bit_order(hal->dev, slot_cfg->bit_order_lsb);
|
|
|
+ i2s_ll_rx_enable_left_align(hal->dev, slot_cfg->left_align);
|
|
|
+ i2s_ll_rx_enable_big_endian(hal->dev, slot_cfg->big_endian);
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_stop_tx(i2s_hal_context_t *hal)
|
|
|
+void i2s_hal_tdm_enable_tx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
- i2s_ll_tx_stop(hal->dev);
|
|
|
+ i2s_ll_tx_enable_tdm(hal->dev);
|
|
|
}
|
|
|
|
|
|
-void i2s_hal_stop_rx(i2s_hal_context_t *hal)
|
|
|
+void i2s_hal_tdm_enable_rx_channel(i2s_hal_context_t *hal)
|
|
|
{
|
|
|
- i2s_ll_rx_stop(hal->dev);
|
|
|
+ i2s_ll_rx_enable_tdm(hal->dev);
|
|
|
}
|
|
|
+#endif
|