#include "board.h" #include "music.h" #include "pin_mux.h" #include "clock_config.h" #include "fsl_dmamux.h" #include "fsl_sai_edma.h" #include "fsl_iomuxc.h" #include "fsl_debug_console.h" /******************************************************************************* * Definitions ******************************************************************************/ #define DEMO_SAI SAI3 #define DEMO_SAI_CHANNEL (0) #define DEMO_SAI_TX_SYNC_MODE kSAI_ModeAsync #define DEMO_SAI_RX_SYNC_MODE kSAI_ModeSync #define DEMO_SAI_MCLK_OUTPUT true #define DEMO_SAI_MASTER_SLAVE kSAI_Master//kSAI_Slave - orig #define DEMO_AUDIO_DATA_CHANNEL (2U) #define DEMO_AUDIO_BIT_WIDTH kSAI_WordWidth16bits #define DEMO_AUDIO_SAMPLE_RATE (kSAI_SampleRate16KHz) #define DEMO_AUDIO_MASTER_CLOCK 12288000 /* SAI instance and clock */ #define DEMO_SAI SAI3 /* Select Audio/Video PLL (786.48 MHz) as sai3 clock source */ #define DEMO_SAI3_CLOCK_SOURCE_SELECT (2U) /* Clock pre divider for sai3 clock source */ #define DEMO_SAI3_CLOCK_SOURCE_PRE_DIVIDER (0U) /* Clock divider for sai3 clock source */ #define DEMO_SAI3_CLOCK_SOURCE_DIVIDER (63U) /* Get frequency of sai clock: SAI3_Clock = 786.432MHz /(3+1)/(4+1) = 39.321MHz */ #define DEMO_SAI_CLK_FREQ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI3_CLOCK_SOURCE_DIVIDER + 1U) / (DEMO_SAI3_CLOCK_SOURCE_PRE_DIVIDER + 1U)) /* DMA */ #define DMAMUX0 DMAMUX #define DEMO_DMA DMA0 #define DEMO_EDMA_CHANNEL (0U) #define DEMO_SAI_TX_SOURCE kDmaRequestMuxSai3Tx #define EXAMPLE_SAI_TX_SOURCE kDmaRequestMuxSai3Tx /******************************************************************************* * Prototypes ******************************************************************************/ static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData); /******************************************************************************* * Variables ******************************************************************************/ AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle) = { 0 }; edma_handle_t dmaHandle = { 0 }; static volatile bool isFinished = false; /******************************************************************************* * Code ******************************************************************************/ /* * AUDIO PLL setting: Frequency = Fref * (DIV_SELECT + NUM / DENOM) * = 24 * (32 + 768/1000) * = 786.432 MHz */ const clock_audio_pll_config_t audioPllConfig = { .loopDivider = 30, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */ .postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */ .numerator = 200, /* 30 bit numerator of fractional loop divider. */ .denominator = 100, /* 30 bit denominator of fractional loop divider */ }; static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData) { isFinished = true; } static void callback_blocking(I2S_Type *base, sai_handle_t *handle, status_t status, void *userData) { isFinished = true; } void configMQS(void) { CCM->CCGR0 = CCM->CCGR0 & (~CCM_CCGR0_CG2_MASK) | CCM_CCGR0_CG2(3); /* Enable MQS hmclk. */ IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, true); /* Reset MQS. */ IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, false); /* Release reset MQS. */ IOMUXC_MQSEnable(IOMUXC_GPR, true); /* Enable MQS. */ IOMUXC_MQSConfig(IOMUXC_GPR, kIOMUXC_MqsPwmOverSampleRate64, 0u); /* 78.6432MHz/64/(0+1) = 1.2288MHz,Higher frequency PWM involves less low frequency harmonic.*/ } void BOARD_EnableSaiMclkOutput(bool enable) { if (enable) { IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI3_MCLK_DIR_MASK; } else { IOMUXC_GPR->GPR1 &= (~IOMUXC_GPR_GPR1_SAI3_MCLK_DIR_MASK); } } int mqs_test(void) { sai_config_t config; sai_transceiver_t saiConfig; sai_transfer_format_t format; sai_transfer_t xfer; edma_config_t dmaConfig = { 0 }; sai_handle_t thandle; BOARD_ConfigMPU(); BOARD_InitPins(); BOARD_BootClockRUN(); CLOCK_InitAudioPll(&audioPllConfig); BOARD_InitDebugConsole(); /*Enable MCLK clock*/ BOARD_EnableSaiMclkOutput(true); /* Init DMAMUX */ DMAMUX_Init(DMAMUX0); DMAMUX_SetSource(DMAMUX0, DEMO_EDMA_CHANNEL, DEMO_SAI_TX_SOURCE); DMAMUX_EnableChannel(DMAMUX0, DEMO_EDMA_CHANNEL); PRINTF("SAI example started!\n\r"); /* Create EDMA handle */ /* * dmaConfig.enableRoundRobinArbitration = false; * dmaConfig.enableHaltOnError = true; * dmaConfig.enableContinuousLinkMode = false; * dmaConfig.enableDebugMode = false; */ EDMA_GetDefaultConfig(&dmaConfig); EDMA_Init(DEMO_DMA, &dmaConfig); EDMA_CreateHandle(&dmaHandle, DEMO_DMA, DEMO_EDMA_CHANNEL); /* Init SAI module */ SAI_TxGetDefaultConfig(&config); SAI_TxInit(DEMO_SAI, &config); // /* I2S mode configurations */ SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, callback, NULL, &dmaHandle); SAI_GetClassicI2SConfig(&saiConfig, DEMO_AUDIO_BIT_WIDTH, kSAI_Stereo, 1U << DEMO_SAI_CHANNEL); saiConfig.syncMode = DEMO_SAI_TX_SYNC_MODE; saiConfig.masterSlave = DEMO_SAI_MASTER_SLAVE; SAI_TransferTxSetConfigEDMA(DEMO_SAI, &txHandle, &saiConfig); // /* set bit clock divider */ SAI_TxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH, 1);//DEMO_AUDIO_DATA_CHANNEL /* Configure the audio format */ format.bitWidth = kSAI_WordWidth16bits; format.channel = 0U; format.sampleRate_Hz = kSAI_SampleRate16KHz; //format.masterClockHz = DEMO_SAI_CLK_FREQ; format.protocol = config.protocol; format.stereo = kSAI_Stereo; format.isFrameSyncCompact = true; format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U; SAI_TransferTxSetFormatEDMA(DEMO_SAI, &txHandle, &format, DEMO_AUDIO_MASTER_CLOCK, DEMO_SAI_CLK_FREQ); configMQS(); for (int i = 0; i < 64; i++) { music[i] = 0; } xfer.data = (uint8_t*) (uint32_t) music; xfer.dataSize = MUSIC_LEN; while (1) { isFinished = false; SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer); /* Wait until finished */ while (isFinished != true) { __NOP(); } } }