/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * Copyright 2016-2020 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_debug_console.h" #include "fsl_sai.h" #include "music.h" #include "fsl_codec_common.h" #include "fsl_wm8960.h" #include "fsl_gpio.h" #include "fsl_iomuxc.h" #include "fsl_codec_adapter.h" /******************************************************************************* * Definitions ******************************************************************************/ #define DEMO_SAI (I2S7) #define DEMO_SAI_CHANNEL (0) #define DEMO_SAI_CLK_FREQ \ (CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootSai7)) / \ (CLOCK_GetRootPostDivider(kCLOCK_RootSai7))) #define I2C_RELEASE_SDA_GPIO GPIO5 #define I2C_RELEASE_SDA_PIN 19U #define I2C_RELEASE_SCL_GPIO GPIO5 #define I2C_RELEASE_SCL_PIN 18U #define I2C_RELEASE_BUS_COUNT 100U /*set Bclk source to Mclk clock*/ #define DEMO_SAI_CLOCK_SOURCE (1U) #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 #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 DEMO_SAI_CLK_FREQ #define BOARD_SAI_RXCONFIG(config, mode) /******************************************************************************* * Prototypes ******************************************************************************/ void BOARD_I2C_ReleaseBus(void); void BOARD_MASTER_CLOCK_CONFIG(void); extern void BOARD_SAI_RXConfig(sai_transceiver_t *config, sai_sync_mode_t sync); /******************************************************************************* * Variables ******************************************************************************/ wm8960_config_t wm8960Config = { .i2cConfig = {.codecI2CInstance = BOARD_CODEC_I2C_INSTANCE, .codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ}, .route = kWM8960_RoutePlaybackandRecord, .rightInputSource = kWM8960_InputDifferentialMicInput2, .playSource = kWM8960_PlaySourceDAC, .slaveAddress = WM8960_I2C_ADDR, .bus = kWM8960_BusI2S, .format = {.mclk_HZ = 24576000U, .sampleRate = kWM8960_AudioSampleRate16KHz, .bitWidth = kWM8960_AudioBitWidth16bit}, .master_slave = false, }; codec_config_t boardCodecConfig = {.codecDevType = kCODEC_WM8960, .codecDevConfig = &wm8960Config}; sai_master_clock_t mclkConfig; sai_handle_t txHandle = {0}; static volatile bool isFinished = false; extern codec_config_t boardCodecConfig; codec_handle_t codecHandle; /******************************************************************************* * Code ******************************************************************************/ static void i2c_release_bus_delay(void) { uint32_t i = 0; for (i = 0; i < I2C_RELEASE_BUS_COUNT; i++) { __NOP(); } } void BOARD_I2C_ReleaseBus(void) { uint8_t i = 0; gpio_pin_config_t pin_config = {kGPIO_DigitalOutput, 1, kGPIO_NoIntmode}; IOMUXC_SetPinMux(IOMUXC_I2C3_SCL_GPIO5_IO18, 0U); IOMUXC_SetPinConfig(IOMUXC_I2C3_SCL_GPIO5_IO18, IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); IOMUXC_SetPinMux(IOMUXC_I2C3_SDA_GPIO5_IO19, 0U); IOMUXC_SetPinConfig(IOMUXC_I2C3_SDA_GPIO5_IO19, IOMUXC_SW_PAD_CTL_PAD_DSE(3U) | IOMUXC_SW_PAD_CTL_PAD_FSEL_MASK | IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); GPIO_PinInit(I2C_RELEASE_SCL_GPIO, I2C_RELEASE_SCL_PIN, &pin_config); GPIO_PinInit(I2C_RELEASE_SDA_GPIO, I2C_RELEASE_SDA_PIN, &pin_config); /* Drive SDA low first to simulate a start */ GPIO_PinWrite(I2C_RELEASE_SDA_GPIO, I2C_RELEASE_SDA_PIN, 0U); i2c_release_bus_delay(); /* Send 9 pulses on SCL and keep SDA high */ for (i = 0; i < 9; i++) { GPIO_PinWrite(I2C_RELEASE_SCL_GPIO, I2C_RELEASE_SCL_PIN, 0U); i2c_release_bus_delay(); GPIO_PinWrite(I2C_RELEASE_SDA_GPIO, I2C_RELEASE_SDA_PIN, 1U); i2c_release_bus_delay(); GPIO_PinWrite(I2C_RELEASE_SCL_GPIO, I2C_RELEASE_SCL_PIN, 1U); i2c_release_bus_delay(); i2c_release_bus_delay(); } /* Send stop */ GPIO_PinWrite(I2C_RELEASE_SCL_GPIO, I2C_RELEASE_SCL_PIN, 0U); i2c_release_bus_delay(); GPIO_PinWrite(I2C_RELEASE_SDA_GPIO, I2C_RELEASE_SDA_PIN, 0U); i2c_release_bus_delay(); GPIO_PinWrite(I2C_RELEASE_SCL_GPIO, I2C_RELEASE_SCL_PIN, 1U); i2c_release_bus_delay(); GPIO_PinWrite(I2C_RELEASE_SDA_GPIO, I2C_RELEASE_SDA_PIN, 1U); i2c_release_bus_delay(); } void BOARD_MASTER_CLOCK_CONFIG(void) { mclkConfig.mclkOutputEnable = true; mclkConfig.mclkHz = DEMO_AUDIO_MASTER_CLOCK; mclkConfig.mclkSourceClkHz = DEMO_SAI_CLK_FREQ; SAI_SetMasterClockConfig(DEMO_SAI, &mclkConfig); } static void callback(I2S_Type *base, sai_handle_t *handle, status_t status, void *userData) { isFinished = true; } /*! * @brief Main function */ int main(void) { sai_transfer_t xfer; uint32_t temp = 0; sai_transceiver_t config; /* M7 has its local cache and enabled by default, * need to set smart subsystems (0x28000000 ~ 0x3FFFFFFF) * non-cacheable before accessing this address region */ BOARD_InitMemory(); /* Board specific RDC settings */ BOARD_RdcInit(); BOARD_InitPins(); BOARD_BootClockRUN(); // BOARD_I2C_ReleaseBus(); BOARD_I2C_ConfigurePins(); BOARD_InitDebugConsole(); //update to sai7 // CLOCK_SetRootMux(kCLOCK_RootSai3, kCLOCK_SaiRootmuxAudioPll1); /* Set SAI source to AUDIO PLL1 393216000HZ*/ // CLOCK_SetRootDivider(kCLOCK_RootSai3, 1U, 16U); /* Set root clock to 393216000HZ / 16 = 24.576MHz */ CLOCK_SetRootMux(kCLOCK_RootSai7, kCLOCK_SaiRootmuxAudioPll1); /* Set SAI source to AUDIO PLL1 393216000HZ*/ CLOCK_SetRootDivider(kCLOCK_RootSai7, 1U, 16U); /* Set root clock to 393216000HZ / 16 = 24.576MHz */ CLOCK_SetRootMux(kCLOCK_RootI2c3, kCLOCK_I2cRootmuxSysPll1Div5); /* Set I2C source to SysPLL1 Div5 160MHZ */ CLOCK_SetRootDivider(kCLOCK_RootI2c3, 1U, 10U); /* Set root clock to 160MHZ / 10 = 16MHZ */ /* SAI bit clock source */ // AUDIOMIX_AttachClk(AUDIOMIX, kAUDIOMIX_Attach_SAI3_MCLK1_To_SAI3_ROOT); AUDIOMIX_AttachClk(AUDIOMIX, kAUDIOMIX_Attach_SAI7_MCLK1_To_SAI7_ROOT); PRINTF("SAI example started!\n\r"); /* SAI init */ SAI_Init(DEMO_SAI); SAI_TransferTxCreateHandle(DEMO_SAI, &txHandle, callback, NULL); /* I2S mode configurations */ SAI_GetClassicI2SConfig(&config, DEMO_AUDIO_BIT_WIDTH, kSAI_Stereo, 1U << DEMO_SAI_CHANNEL); config.syncMode = DEMO_SAI_TX_SYNC_MODE; config.masterSlave = DEMO_SAI_MASTER_SLAVE; SAI_TransferTxSetConfig(DEMO_SAI, &txHandle, &config); /* 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 rx configurations */ BOARD_SAI_RXCONFIG(&config, DEMO_SAI_RX_SYNC_MODE); /* master clock configurations */ BOARD_MASTER_CLOCK_CONFIG(); /* Use default setting to init codec */ // if (CODEC_Init(&codecHandle, &boardCodecConfig) != kStatus_Success) // { // assert(false); // } /* xfer structure */ for(int i = 0; i<1; i++) { temp = (uint32_t)music; xfer.data = (uint8_t *)temp; xfer.dataSize = MUSIC_LEN; isFinished = false; SAI_TransferSendNonBlocking(DEMO_SAI, &txHandle, &xfer); /* Wait until finished */ while (isFinished != true) { } SDK_DelayAtLeastUs(100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); PRINTF("\n\r SAI example finished! i =%d round\n\r ", i); } while (1) { } }