/* * Copyright 2021 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ /* Board includes */ #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "main.h" #include "cmd.h" #include "audio_speaker.h" #include "fsl_debug_console.h" #include "usb_phy.h" #include "fsl_gpio.h" #include "fsl_iomuxc.h" #include "fsl_dmamux.h" #include "fsl_codec_common.h" #include "fsl_wm8960.h" #include "app_definitions.h" /******************************************************************************* * Definitions ******************************************************************************/ #define APP_TASK_STACK_SIZE (8 * 1024) /******************************************************************************* * Prototypes ******************************************************************************/ int BOARD_CODEC_Init(void); /******************************************************************************* * Variables ******************************************************************************/ codec_handle_t codecHandle = {0}; wm8960_config_t wm8960Config = { .i2cConfig = {.codecI2CInstance = BOARD_CODEC_I2C_INSTANCE, .codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ}, .route = kWM8960_RoutePlaybackandRecord, .leftInputSource = kWM8960_InputDifferentialMicInput3, .rightInputSource = kWM8960_InputDifferentialMicInput2, .playSource = kWM8960_PlaySourceDAC, .slaveAddress = WM8960_I2C_ADDR, .bus = kWM8960_BusI2S, .format = {.mclk_HZ = 12288000U, .sampleRate = kWM8960_AudioSampleRate48KHz, .bitWidth = kWM8960_AudioBitWidth16bit}, .master_slave = false, }; codec_config_t boardCodecConfig = {.codecDevType = kCODEC_WM8960, .codecDevConfig = &wm8960Config}; static app_handle_t app; /******************************************************************************* * Code ******************************************************************************/ /* * AUDIO PLL setting: Frequency = Fref * (DIV_SELECT + NUM / DENOM) * = 24 * (30 + 66/625) * = 722.5344 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 = 66, /* 30 bit numerator of fractional loop divider. */ .denominator = 625, /* 30 bit denominator of fractional loop divider */ }; void BOARD_EnableSaiMclkOutput(bool enable) { if (enable) { IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK; } else { IOMUXC_GPR->GPR1 &= (~IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK); } } int BOARD_CODEC_Init(void) { CODEC_Init(&codecHandle, &boardCodecConfig); /* Initial volume kept low for hearing safety. */ CODEC_SetVolume(&codecHandle, kCODEC_PlayChannelHeadphoneLeft | kCODEC_PlayChannelHeadphoneRight, 50); return 0; } void USB_DeviceClockInit(void) { usb_phy_config_struct_t phyConfig = { BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, }; if (CONTROLLER_ID == kUSB_ControllerEhci0) { CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U); } else { CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U); CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U); } USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig); } void handleShellMessage(void *arg) { /* Wait for response message to be processed before returning to shell. */ ulTaskNotifyTake(pdTRUE, portMAX_DELAY); } void APP_Shell_Task(void *param) { PRINTF("[APP_Shell_Task] start\r\n"); /* Handle shell commands. Return when 'exit' command entered. */ shellCmd(handleShellMessage, param); vTaskSuspend(NULL); while (1) ; } int main(void) { int ret; BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_BootClockRUN(); /* 1. Init SAI clock .*/ CLOCK_InitAudioPll(&audioPllConfig); BOARD_InitDebugConsole(); /*Clock setting for LPI2C*/ CLOCK_SetMux(kCLOCK_Lpi2cMux, BOARD_CODEC_I2C_CLOCK_SOURCE_SELECT); CLOCK_SetDiv(kCLOCK_Lpi2cDiv, BOARD_CODEC_I2C_CLOCK_SOURCE_DIVIDER); CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT); CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER); CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER); /*Enable MCLK clock*/ BOARD_EnableSaiMclkOutput(true); DMAMUX_Init(DEMO_DMAMUX); DMAMUX_SetSource(DEMO_DMAMUX, DEMO_TX_CHANNEL, (uint8_t)DEMO_SAI_TX_SOURCE); DMAMUX_EnableChannel(DEMO_DMAMUX, DEMO_TX_CHANNEL); /*Clock setting for USB*/ USB_DeviceClockInit(); PRINTF("\r\n"); PRINTF("**********************************************\r\n"); PRINTF("Maestro audio USB speaker solutions demo start\r\n"); PRINTF("**********************************************\r\n"); PRINTF("\r\n"); /* Initialize OSA*/ OSA_Init(); ret = BOARD_CODEC_Init(); if (ret) { PRINTF("CODEC_Init failed\r\n"); return -1; } /* USB speaker initialization */ USB_DeviceApplicationInit(); /* Set shell command task priority = 4 */ if (xTaskCreate(APP_Shell_Task, "Shell Task", APP_TASK_STACK_SIZE, &app, configMAX_PRIORITIES - 3, &app.shell_task_handle) != pdPASS) { PRINTF("\r\nFailed to create application task\r\n"); while (1) ; } /* Run RTOS */ vTaskStartScheduler(); /* Should not reach this statement */ return 0; }