Hello everyone,
I'm trying to implement a SAI with TDM protocol for audio data transfer.
Starting from sai_edma_tdm_record_playback without CS42448, I've changed few configurations in order to implement a loopback between SAI1_RX/TX.
Links are:
TX_BCLK -> RX_BCLK
TX_SYNC -> RX_SYNC
TX_DA0 -> RX_DA0
On an oscilloscope connected to TX_DA0, it is possible to see data sent but they are uncorrect.
someone can explain to me how to correctly configure a TDM communication and what is wrong in the code below?
Thanks a lot,
-F
AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t Buffer[BUFFER_NUMBER * BUFFER_SIZE], 4);
#if defined(DEMO_QUICKACCESS_SECTION_CACHEABLE) && DEMO_QUICKACCESS_SECTION_CACHEABLE
AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle);
AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t rxHandle);
#else
AT_QUICKACCESS_SECTION_DATA(sai_edma_handle_t txHandle);
AT_QUICKACCESS_SECTION_DATA(sai_edma_handle_t rxHandle);
#endif
static uint32_t tx_index = 0U, rx_index = 0U;
volatile uint32_t emptyBlock = BUFFER_NUMBER;
edma_handle_t dmaTxHandle = {0}, dmaRxHandle = {0};
extern codec_config_t boardCodecConfig;
codec_handle_t codecHandle;
/*******************************************************************************
* Code
******************************************************************************/
static void rx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
if (kStatus_SAI_RxError == status)
{
/* Handle the error. */
}
else
{
emptyBlock--;
}
}
static void tx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
if (kStatus_SAI_TxError == status)
{
/* Handle the error. */
}
else
{
emptyBlock++;
}
}
/*!
* @brief Main function
*/
int main(void)
{
sai_transfer_t xfer;
edma_config_t dmaConfig = {0};
sai_transceiver_t saiConfig;
BOARD_InitHardware();
PRINTF("SAI TDM record playback example started!\n\r");
/* Init DMA and create handle for DMA */
EDMA_GetDefaultConfig(&dmaConfig);
#if defined(BOARD_GetEDMAConfig)
BOARD_GetEDMAConfig(dmaConfig);
#endif
EDMA_Init(EXAMPLE_DMA, &dmaConfig);
EDMA_CreateHandle(&dmaTxHandle, EXAMPLE_DMA, EXAMPLE_TX_CHANNEL);
EDMA_CreateHandle(&dmaRxHandle, EXAMPLE_DMA, EXAMPLE_RX_CHANNEL);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(EXAMPLE_DMA, EXAMPLE_TX_CHANNEL, EXAMPLE_SAI_TX_SOURCE);
EDMA_SetChannelMux(EXAMPLE_DMA, EXAMPLE_RX_CHANNEL, EXAMPLE_SAI_RX_SOURCE);
#endif
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#if defined(EXAMPLE_DMAMUX_TX_CHANNEL) && defined(EXAMPLE_DMAMUX_RX_CHANNEL)
/* Init DMAMUX */
DMAMUX_Init(EXAMPLE_DMAMUX_TX);
DMAMUX_Init(EXAMPLE_DMAMUX_RX);
DMAMUX_SetSource(EXAMPLE_DMAMUX_TX, EXAMPLE_DMAMUX_TX_CHANNEL, (uint8_t)EXAMPLE_SAI_TX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX_TX, EXAMPLE_DMAMUX_TX_CHANNEL);
DMAMUX_SetSource(EXAMPLE_DMAMUX_RX, EXAMPLE_DMAMUX_RX_CHANNEL, (uint8_t)EXAMPLE_SAI_RX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX_RX, EXAMPLE_DMAMUX_RX_CHANNEL);
#else
/* Init DMAMUX */
DMAMUX_Init(EXAMPLE_DMAMUX);
DMAMUX_SetSource(EXAMPLE_DMAMUX, EXAMPLE_TX_CHANNEL, (uint8_t)EXAMPLE_SAI_TX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX, EXAMPLE_TX_CHANNEL);
DMAMUX_SetSource(EXAMPLE_DMAMUX, EXAMPLE_RX_CHANNEL, (uint8_t)EXAMPLE_SAI_RX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX, EXAMPLE_RX_CHANNEL);
#endif
#endif
/* SAI init */
SAI_Init(DEMO_SAI);
SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, tx_callback, NULL, &dmaTxHandle);
SAI_TransferRxCreateHandleEDMA(DEMO_SAI, &rxHandle, rx_callback, NULL, &dmaRxHandle);
/* TDM mode configurations */
SAI_GetTDMConfig(&saiConfig, kSAI_FrameSyncLenOneBitClk, DEMO_AUDIO_BIT_WIDTH, DEMO_AUDIO_DATA_CHANNEL,
kSAI_Channel0Mask);
saiConfig.frameSync.frameSyncEarly = true;
saiConfig.masterSlave = kSAI_Master;
SAI_TransferTxSetConfigEDMA(DEMO_SAI, &txHandle, &saiConfig);
saiConfig.masterSlave = kSAI_Slave;
SAI_TransferRxSetConfigEDMA(DEMO_SAI, &rxHandle, &saiConfig);
/* set bit clock divider */
SAI_TxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
DEMO_AUDIO_DATA_CHANNEL);
SAI_RxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
DEMO_AUDIO_DATA_CHANNEL);
/* master clock configurations */
BOARD_MASTER_CLOCK_CONFIG();
/* CS42888 initialization */
//DEMO_InitCodec();
memset((uint8_t *)&Buffer,'5', sizeof(uint8_t) * 4096);
while (1)
{
if (emptyBlock > 0)
{
xfer.data = Buffer + rx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
if (kStatus_Success == SAI_TransferReceiveEDMA(DEMO_SAI, &rxHandle, &xfer))
{
rx_index++;
}
if (rx_index == BUFFER_NUMBER)
{
rx_index = 0U;
}
}
if (emptyBlock < BUFFER_NUMBER)
{
xfer.data = Buffer + tx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
if (kStatus_Success == SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer))
{
tx_index++;
}
if (tx_index == BUFFER_NUMBER)
{
tx_index = 0U;
}
}
}
}