2021-08-18 07:45:51 -04:00
/*
2022-12-22 02:28:28 -05:00
* SPDX - FileCopyrightText : 2022 - 2023 Espressif Systems ( Shanghai ) CO LTD
2021-08-18 07:45:51 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
# include <string.h>
2022-04-07 03:32:46 -04:00
2021-08-18 07:45:51 -04:00
# include "freertos/FreeRTOS.h"
# include "freertos/semphr.h"
2022-04-07 03:32:46 -04:00
# include "sdkconfig.h"
# if CONFIG_I2S_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
# define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
# endif
2021-08-18 07:45:51 -04:00
# include "hal/i2s_hal.h"
# include "driver/gpio.h"
# include "driver/i2s_tdm.h"
# include "i2s_private.h"
# include "clk_ctrl_os.h"
# include "esp_intr_alloc.h"
# include "esp_check.h"
2022-04-07 03:32:46 -04:00
const static char * TAG = " i2s_tdm " ;
2021-08-18 07:45:51 -04:00
// Same with standard mode except total slot number
static esp_err_t i2s_tdm_calculate_clock ( i2s_chan_handle_t handle , const i2s_tdm_clk_config_t * clk_cfg , i2s_hal_clock_info_t * clk_info )
{
uint32_t rate = clk_cfg - > sample_rate_hz ;
i2s_tdm_slot_config_t * slot_cfg = & ( ( i2s_tdm_config_t * ) ( handle - > mode_info ) ) - > slot_cfg ;
uint32_t slot_bits = ( slot_cfg - > slot_bit_width = = I2S_SLOT_BIT_WIDTH_AUTO ) | |
( ( int ) slot_cfg - > slot_bit_width < ( int ) slot_cfg - > data_bit_width ) ?
slot_cfg - > data_bit_width : slot_cfg - > slot_bit_width ;
/* Calculate multiple
* Fmclk = bck_div * fbck = fsclk / ( mclk_div + b / a ) */
if ( handle - > role = = I2S_ROLE_MASTER ) {
clk_info - > bclk = rate * handle - > total_slot * slot_bits ;
clk_info - > mclk = rate * clk_cfg - > mclk_multiple ;
clk_info - > bclk_div = clk_info - > mclk / clk_info - > bclk ;
2022-11-17 21:40:03 -05:00
/* While RECEIVING multiple slots, the data will go wrong if the bclk_div is equal or smaller than 2 */
if ( clk_info - > bclk_div < = 2 ) {
clk_info - > bclk_div = 3 ;
clk_info - > mclk = clk_info - > bclk * clk_info - > bclk_div ;
ESP_LOGW ( TAG , " the current mclk multiple is too small, adjust the mclk multiple to % " PRIu32 , clk_info - > mclk / rate ) ;
}
2021-08-18 07:45:51 -04:00
} else {
/* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */
clk_info - > bclk_div = 8 ;
clk_info - > bclk = rate * handle - > total_slot * slot_bits ;
clk_info - > mclk = clk_info - > bclk * clk_info - > bclk_div ;
}
2022-07-04 23:22:27 -04:00
2021-08-18 07:45:51 -04:00
# if SOC_I2S_SUPPORTS_APLL
2022-04-07 03:32:46 -04:00
clk_info - > sclk = clk_cfg - > clk_src = = I2S_CLK_SRC_APLL ? i2s_set_get_apll_freq ( clk_info - > mclk ) : I2S_LL_BASE_CLK ;
2021-08-18 07:45:51 -04:00
# else
clk_info - > sclk = I2S_LL_BASE_CLK ;
# endif
clk_info - > mclk_div = clk_info - > sclk / clk_info - > mclk ;
/* Check if the configuration is correct */
ESP_RETURN_ON_FALSE ( clk_info - > mclk_div , ESP_ERR_INVALID_ARG , TAG , " sample rate is too large " ) ;
return ESP_OK ;
}
static esp_err_t i2s_tdm_set_clock ( i2s_chan_handle_t handle , const i2s_tdm_clk_config_t * clk_cfg )
{
esp_err_t ret = ESP_OK ;
i2s_tdm_config_t * tdm_cfg = ( i2s_tdm_config_t * ) ( handle - > mode_info ) ;
i2s_hal_clock_info_t clk_info ;
/* Calculate clock parameters */
ESP_RETURN_ON_ERROR ( i2s_tdm_calculate_clock ( handle , clk_cfg , & clk_info ) , TAG , " clock calculate failed " ) ;
2022-08-04 01:08:48 -04:00
ESP_LOGD ( TAG , " Clock division info: [sclk] % " PRIu32 " Hz [mdiv] %d [mclk] % " PRIu32 " Hz [bdiv] %d [bclk] % " PRIu32 " Hz " ,
2022-04-07 03:32:46 -04:00
clk_info . sclk , clk_info . mclk_div , clk_info . mclk , clk_info . bclk_div , clk_info . bclk ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
portENTER_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
/* Set clock configurations in HAL*/
if ( handle - > dir = = I2S_DIR_TX ) {
2022-04-07 03:32:46 -04:00
i2s_hal_set_tx_clock ( & handle - > controller - > hal , & clk_info , clk_cfg - > clk_src ) ;
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_hal_set_rx_clock ( & handle - > controller - > hal , & clk_info , clk_cfg - > clk_src ) ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portEXIT_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
/* Update the mode info: clock configuration */
memcpy ( & ( tdm_cfg - > clk_cfg ) , clk_cfg , sizeof ( i2s_tdm_clk_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ret ;
}
static esp_err_t i2s_tdm_set_slot ( i2s_chan_handle_t handle , const i2s_tdm_slot_config_t * slot_cfg )
{
2023-04-26 10:39:43 -04:00
ESP_RETURN_ON_FALSE ( slot_cfg - > slot_mask , ESP_ERR_INVALID_ARG , TAG , " At least one channel should be enabled " ) ;
2022-04-02 09:31:35 -04:00
/* Update the total slot num and active slot num */
handle - > active_slot = slot_cfg - > slot_mode = = I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount ( slot_cfg - > slot_mask ) ;
uint32_t max_slot_num = 32 - __builtin_clz ( slot_cfg - > slot_mask ) ;
handle - > total_slot = slot_cfg - > total_slot < max_slot_num ? max_slot_num : slot_cfg - > total_slot ;
handle - > total_slot = handle - > total_slot < 2 ? 2 : handle - > total_slot ; // At least two slots in a frame
2021-08-18 07:45:51 -04:00
uint32_t buf_size = i2s_get_buf_size ( handle , slot_cfg - > data_bit_width , handle - > dma . frame_num ) ;
/* The DMA buffer need to re-allocate if the buffer size changed */
if ( handle - > dma . buf_size ! = buf_size ) {
handle - > dma . buf_size = buf_size ;
ESP_RETURN_ON_ERROR ( i2s_free_dma_desc ( handle ) , TAG , " failed to free the old dma descriptor " ) ;
ESP_RETURN_ON_ERROR ( i2s_alloc_dma_desc ( handle , handle - > dma . desc_num , buf_size ) ,
TAG , " allocate memory for dma descriptor failed " ) ;
}
bool is_slave = handle - > role = = I2S_ROLE_SLAVE ;
/* Share bck and ws signal in full-duplex mode */
2022-04-07 03:32:46 -04:00
if ( handle - > controller - > full_duplex ) {
i2s_ll_share_bck_ws ( handle - > controller - > hal . dev , true ) ;
2021-08-18 07:45:51 -04:00
/* Since bck and ws are shared, only tx or rx can be master
Force to set rx as slave to avoid conflict of clock signal */
if ( handle - > dir = = I2S_DIR_RX ) {
is_slave = true ;
}
} else {
2022-04-07 03:32:46 -04:00
i2s_ll_share_bck_ws ( handle - > controller - > hal . dev , false ) ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portENTER_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
/* Configure the hardware to apply TDM format */
if ( handle - > dir = = I2S_DIR_TX ) {
2022-04-07 03:32:46 -04:00
i2s_hal_tdm_set_tx_slot ( & ( handle - > controller - > hal ) , is_slave , ( i2s_hal_slot_config_t * ) slot_cfg ) ;
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_hal_tdm_set_rx_slot ( & ( handle - > controller - > hal ) , is_slave , ( i2s_hal_slot_config_t * ) slot_cfg ) ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portEXIT_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
/* Update the mode info: slot configuration */
2022-04-07 03:32:46 -04:00
i2s_tdm_config_t * tdm_cfg = ( i2s_tdm_config_t * ) ( handle - > mode_info ) ;
2022-04-02 09:31:35 -04:00
memcpy ( & ( tdm_cfg - > slot_cfg ) , slot_cfg , sizeof ( i2s_tdm_slot_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ESP_OK ;
}
static esp_err_t i2s_tdm_set_gpio ( i2s_chan_handle_t handle , const i2s_tdm_gpio_config_t * gpio_cfg )
{
2022-04-07 03:32:46 -04:00
int id = handle - > controller - > id ;
2021-08-18 07:45:51 -04:00
/* Check validity of selected pins */
ESP_RETURN_ON_FALSE ( ( gpio_cfg - > bclk = = - 1 | | GPIO_IS_VALID_GPIO ( gpio_cfg - > bclk ) ) ,
ESP_ERR_INVALID_ARG , TAG , " bclk invalid " ) ;
ESP_RETURN_ON_FALSE ( ( gpio_cfg - > ws = = - 1 | | GPIO_IS_VALID_GPIO ( gpio_cfg - > ws ) ) ,
ESP_ERR_INVALID_ARG , TAG , " ws invalid " ) ;
2022-04-02 09:31:35 -04:00
/* Loopback if dout = din */
if ( gpio_cfg - > dout ! = - 1 & &
gpio_cfg - > dout = = gpio_cfg - > din ) {
2022-04-07 03:32:46 -04:00
i2s_gpio_loopback_set ( gpio_cfg - > dout , i2s_periph_signal [ id ] . data_out_sig , i2s_periph_signal [ id ] . data_in_sig ) ;
} else if ( handle - > dir = = I2S_DIR_TX ) {
/* Set data output GPIO */
i2s_gpio_check_and_set ( gpio_cfg - > dout , i2s_periph_signal [ id ] . data_out_sig , false , false ) ;
} else {
/* Set data input GPIO */
i2s_gpio_check_and_set ( gpio_cfg - > din , i2s_periph_signal [ id ] . data_in_sig , true , false ) ;
2022-04-02 09:31:35 -04:00
}
2021-08-18 07:45:51 -04:00
if ( handle - > role = = I2S_ROLE_SLAVE ) {
/* For "tx + slave" mode, select TX signal index for ws and bck */
2022-04-07 03:32:46 -04:00
if ( handle - > dir = = I2S_DIR_TX & & ! handle - > controller - > full_duplex ) {
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
2022-04-07 03:32:46 -04:00
i2s_ll_mclk_bind_to_tx_clk ( handle - > controller - > hal . dev ) ;
2021-08-18 07:45:51 -04:00
# endif
2022-04-07 03:32:46 -04:00
i2s_gpio_check_and_set ( gpio_cfg - > ws , i2s_periph_signal [ id ] . s_tx_ws_sig , true , gpio_cfg - > invert_flags . ws_inv ) ;
i2s_gpio_check_and_set ( gpio_cfg - > bclk , i2s_periph_signal [ id ] . s_tx_bck_sig , true , gpio_cfg - > invert_flags . bclk_inv ) ;
/* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_gpio_check_and_set ( gpio_cfg - > ws , i2s_periph_signal [ id ] . s_rx_ws_sig , true , gpio_cfg - > invert_flags . ws_inv ) ;
i2s_gpio_check_and_set ( gpio_cfg - > bclk , i2s_periph_signal [ id ] . s_rx_bck_sig , true , gpio_cfg - > invert_flags . bclk_inv ) ;
2021-08-18 07:45:51 -04:00
}
} else {
/* mclk only available in master mode */
2022-04-07 03:32:46 -04:00
ESP_RETURN_ON_ERROR ( i2s_check_set_mclk ( id , gpio_cfg - > mclk , false , gpio_cfg - > invert_flags . mclk_inv ) , TAG , " mclk config failed " ) ;
2021-08-18 07:45:51 -04:00
/* For "rx + master" mode, select RX signal index for ws and bck */
2022-04-07 03:32:46 -04:00
if ( handle - > dir = = I2S_DIR_RX & & ! handle - > controller - > full_duplex ) {
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
2022-04-07 03:32:46 -04:00
i2s_ll_mclk_bind_to_rx_clk ( handle - > controller - > hal . dev ) ;
2021-08-18 07:45:51 -04:00
# endif
2022-04-07 03:32:46 -04:00
i2s_gpio_check_and_set ( gpio_cfg - > ws , i2s_periph_signal [ id ] . m_rx_ws_sig , false , gpio_cfg - > invert_flags . ws_inv ) ;
i2s_gpio_check_and_set ( gpio_cfg - > bclk , i2s_periph_signal [ id ] . m_rx_bck_sig , false , gpio_cfg - > invert_flags . bclk_inv ) ;
/* For "tx + rx + master" or "tx + master" mode, select TX signal index for ws and bck */
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_gpio_check_and_set ( gpio_cfg - > ws , i2s_periph_signal [ id ] . m_tx_ws_sig , false , gpio_cfg - > invert_flags . ws_inv ) ;
i2s_gpio_check_and_set ( gpio_cfg - > bclk , i2s_periph_signal [ id ] . m_tx_bck_sig , false , gpio_cfg - > invert_flags . bclk_inv ) ;
2021-08-18 07:45:51 -04:00
}
}
2022-04-02 09:31:35 -04:00
/* Update the mode info: gpio configuration */
2022-04-07 03:32:46 -04:00
i2s_tdm_config_t * tdm_cfg = ( i2s_tdm_config_t * ) ( handle - > mode_info ) ;
2022-04-02 09:31:35 -04:00
memcpy ( & ( tdm_cfg - > gpio_cfg ) , gpio_cfg , sizeof ( i2s_tdm_gpio_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ESP_OK ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_init_tdm_mode ( i2s_chan_handle_t handle , const i2s_tdm_config_t * tdm_cfg )
2021-08-18 07:45:51 -04:00
{
2022-04-07 03:32:46 -04:00
# if CONFIG_I2S_ENABLE_DEBUG_LOG
esp_log_level_set ( TAG , ESP_LOG_DEBUG ) ;
# endif
2021-08-18 07:45:51 -04:00
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
ESP_GOTO_ON_FALSE ( handle - > state = = I2S_CHAN_STATE_REGISTER , ESP_ERR_INVALID_STATE , err , TAG , " the channel has initialized already " ) ;
2022-04-02 09:31:35 -04:00
handle - > mode = I2S_COMM_MODE_TDM ;
/* Allocate memory for storing the configurations of TDM mode */
if ( handle - > mode_info ) {
free ( handle - > mode_info ) ;
}
handle - > mode_info = calloc ( 1 , sizeof ( i2s_tdm_config_t ) ) ;
ESP_GOTO_ON_FALSE ( handle - > mode_info , ESP_ERR_NO_MEM , err , TAG , " no memory for storing the configurations " ) ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_tdm_set_gpio ( handle , & tdm_cfg - > gpio_cfg ) , err , TAG , " initialize channel failed while setting gpio pins " ) ;
2022-04-07 03:32:46 -04:00
/* i2s_set_tdm_slot should be called before i2s_set_tdm_clock while initializing, because clock is relay on the slot */
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_tdm_set_slot ( handle , & tdm_cfg - > slot_cfg ) , err , TAG , " initialize channel failed while setting slot " ) ;
2022-04-02 09:31:35 -04:00
# if SOC_I2S_SUPPORTS_APLL
/* Enable APLL and acquire its lock when the clock source is APLL */
2022-04-07 03:32:46 -04:00
if ( tdm_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_acquire ( ) ;
handle - > apll_en = true ;
}
2022-04-07 03:32:46 -04:00
# endif
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_tdm_set_clock ( handle , & tdm_cfg - > clk_cfg ) , err , TAG , " initialize channel failed while setting clock " ) ;
2023-03-20 08:15:12 -04:00
ESP_GOTO_ON_ERROR ( i2s_init_dma_intr ( handle , I2S_INTR_ALLOC_FLAGS ) , err , TAG , " initialize dma interrupt failed " ) ;
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
if ( handle - > dir = = I2S_DIR_TX ) {
2022-04-07 03:32:46 -04:00
i2s_ll_tx_enable_tdm ( handle - > controller - > hal . dev ) ;
i2s_ll_tx_enable_clock ( handle - > controller - > hal . dev ) ;
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_ll_rx_enable_tdm ( handle - > controller - > hal . dev ) ;
i2s_ll_rx_enable_clock ( handle - > controller - > hal . dev ) ;
}
# endif
# ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX ;
# if SOC_I2S_SUPPORTS_APLL
if ( tdm_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
pm_type = ESP_PM_NO_LIGHT_SLEEP ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
# endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR ( esp_pm_lock_create ( pm_type , 0 , " i2s_driver " , & handle - > pm_lock ) , TAG , " I2S pm lock create failed " ) ;
2021-08-18 07:45:51 -04:00
# endif
/* Initialization finished, mark state as ready */
handle - > state = I2S_CHAN_STATE_READY ;
xSemaphoreGive ( handle - > mutex ) ;
2022-06-20 08:30:31 -04:00
ESP_LOGD ( TAG , " The %s channel on I2S%d has been initialized to TDM mode successfully " ,
handle - > dir = = I2S_DIR_TX ? " tx " : " rx " , handle - > controller - > id ) ;
2021-08-18 07:45:51 -04:00
return ret ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_tdm_clock ( i2s_chan_handle_t handle , const i2s_tdm_clk_config_t * clk_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , clk_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_TDM , ESP_ERR_INVALID_ARG , err , TAG , " this handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
ESP_GOTO_ON_FALSE ( handle - > state = = I2S_CHAN_STATE_READY , ESP_ERR_INVALID_STATE , err , TAG , " invalid state, I2S should be disabled before reconfiguring the clock " ) ;
i2s_tdm_config_t * tdm_cfg = ( i2s_tdm_config_t * ) handle - > mode_info ;
ESP_GOTO_ON_FALSE ( tdm_cfg , ESP_ERR_INVALID_STATE , err , TAG , " initialization not complete " ) ;
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
# if SOC_I2S_SUPPORTS_APLL
/* Enable APLL and acquire its lock when the clock source is changed to APLL */
2022-04-07 03:32:46 -04:00
if ( clk_cfg - > clk_src = = I2S_CLK_SRC_APLL & & clk_cfg - > clk_cfg . clk_src ! = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_acquire ( ) ;
handle - > apll_en = true ;
}
/* Disable APLL and release its lock when clock source is changed to 160M_PLL */
2022-04-07 03:32:46 -04:00
if ( clk_cfg - > clk_src ! = I2S_CLK_SRC_APLL & & clk_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_release ( ) ;
handle - > apll_en = false ;
}
# endif
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
ESP_GOTO_ON_ERROR ( i2s_tdm_set_clock ( handle , clk_cfg ) , err , TAG , " update clock failed " ) ;
2022-04-07 03:32:46 -04:00
# ifdef CONFIG_PM_ENABLE
// Create/Re-create power management lock
if ( tdm_cfg - > clk_cfg . clk_src ! = clk_cfg - > clk_src ) {
ESP_GOTO_ON_ERROR ( esp_pm_lock_delete ( handle - > pm_lock ) , err , TAG , " I2S delete old pm lock failed " ) ;
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX ;
# if SOC_I2S_SUPPORTS_APLL
if ( clk_cfg - > clk_src = = I2S_CLK_SRC_APLL ) {
pm_type = ESP_PM_NO_LIGHT_SLEEP ;
}
# endif // SOC_I2S_SUPPORTS_APLL
ESP_GOTO_ON_ERROR ( esp_pm_lock_create ( pm_type , 0 , " i2s_driver " , & handle - > pm_lock ) , err , TAG , " I2S pm lock create failed " ) ;
}
# endif //CONFIG_PM_ENABLE
2021-08-18 07:45:51 -04:00
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_tdm_slot ( i2s_chan_handle_t handle , const i2s_tdm_slot_config_t * slot_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , slot_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_TDM , ESP_ERR_INVALID_ARG , err , TAG , " this handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
ESP_GOTO_ON_FALSE ( handle - > state = = I2S_CHAN_STATE_READY , ESP_ERR_INVALID_STATE , err , TAG , " invalid state, I2S should be disabled before reconfiguring the slot " ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
i2s_tdm_config_t * tdm_cfg = ( i2s_tdm_config_t * ) handle - > mode_info ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_FALSE ( tdm_cfg , ESP_ERR_INVALID_STATE , err , TAG , " initialization not complete " ) ;
ESP_GOTO_ON_ERROR ( i2s_tdm_set_slot ( handle , slot_cfg ) , err , TAG , " set i2s standard slot failed " ) ;
/* If the slot bit width changed, then need to update the clock */
uint32_t slot_bits = slot_cfg - > slot_bit_width = = I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg - > data_bit_width : slot_cfg - > slot_bit_width ;
if ( tdm_cfg - > slot_cfg . slot_bit_width = = slot_bits ) {
ESP_GOTO_ON_ERROR ( i2s_tdm_set_clock ( handle , & tdm_cfg - > clk_cfg ) , err , TAG , " update clock failed " ) ;
}
2022-04-07 03:32:46 -04:00
/* Reset queue */
xQueueReset ( handle - > msg_queue ) ;
2021-08-18 07:45:51 -04:00
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_tdm_gpio ( i2s_chan_handle_t handle , const i2s_tdm_gpio_config_t * gpio_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , gpio_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_TDM , ESP_ERR_INVALID_ARG , err , TAG , " This handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
ESP_GOTO_ON_FALSE ( handle - > state = = I2S_CHAN_STATE_READY , ESP_ERR_INVALID_STATE , err , TAG , " Invalid state, I2S should be disabled before reconfiguring the gpio " ) ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_tdm_set_gpio ( handle , gpio_cfg ) , err , TAG , " set i2s standard slot failed " ) ;
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}