Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2019 NXP
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <math.h>
- #include <stdint.h>
- #include <stddef.h>
- #include "pin_mux.h"
- #include "clock_config.h"
- #include "board.h"
- #include "fsl_dmamux.h"
- #include "fsl_flexio_i2s_edma.h"
- #include "fsl_debug_console.h"
- #include "fsl_codec_common.h"
- #include "fsl_wm8960.h"
- #include "fsl_sai.h"
- #include "fsl_codec_adapter.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* SAI and I2C instance and clock */
- #define DEMO_CODEC_WM8960
- #define DEMO_I2C LPI2C5
- #define DEMO_FLEXIO_BASE FLEXIO2
- #define DEMO_SAI SAI1
- /* Get frequency of sai1 clock */
- #define DEMO_SAI_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_PLL_AUDIO_OUT))
- /* Get frequency of lpi2c clock */
- #define DEMO_I2C_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_LPI2C5_CLK_ROOT))
- #define DEMO_FLEXIO_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_FLEXIO2_CLK_ROOT))
- #define BCLK_PIN (13U)
- #define FRAME_SYNC_PIN (12U)
- #define TX_DATA_PIN (11U)
- #define FLEXIO_TX_SHIFTER_INDEX 0
- #define EXAMPLE_DMAMUX DMAMUX0
- #define EXAMPLE_DMA DMA0
- #define EXAMPLE_TX_CHANNEL 0
- #define EXAMPLE_TX_DMA_SOURCE kDmaRequestMuxFlexIO2Request0Request1
- //#define EXAMPLE_RX_DMA_SOURCE kDmaRequestMuxFlexIO2Request2Request3
- //#define OVER_SAMPLE_RATE (384)
- #define BUFFER_SIZE (128)
- #define BUFFER_NUM (4)
- #define PLAY_COUNT (5000 * 2U)
- /* demo audio sample rate */
- #define DEMO_AUDIO_SAMPLE_RATE (kFLEXIO_I2S_SampleRate44100Hz)
- /* demo audio master clock */
- #if (defined FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER && FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) || \
- (defined FSL_FEATURE_PCC_HAS_SAI_DIVIDER && FSL_FEATURE_PCC_HAS_SAI_DIVIDER)
- //#define DEMO_AUDIO_MASTER_CLOCK OVER_SAMPLE_RATE *DEMO_AUDIO_SAMPLE_RATE
- #else
- #define DEMO_AUDIO_MASTER_CLOCK DEMO_SAI_CLK_FREQ
- #endif
- /* demo audio data channel */
- #define DEMO_AUDIO_DATA_CHANNEL (2U)
- /* demo audio bit width */
- #define DEMO_AUDIO_BIT_WIDTH (kFLEXIO_I2S_WordWidth16bits)
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- wm8960_config_t wm8960Config = {
- .i2cConfig = {.codecI2CInstance = BOARD_CODEC_I2C_INSTANCE, .codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ},
- .route = kWM8960_RoutePlayback,
- .enableSpeaker = true,
- .leftInputSource = kWM8960_InputClosed,//kWM8960_InputDifferentialMicInput3,
- .rightInputSource = kWM8960_InputClosed,//kWM8960_InputDifferentialMicInput2,
- .playSource = kWM8960_ModuleLineOut,//kWM8960_ModuleHP
- .slaveAddress = WM8960_I2C_ADDR,
- .bus = kWM8960_BusI2S,
- .format = {.mclk_HZ = /*24576000*/16934400, .sampleRate = kWM8960_AudioSampleRate44100Hz, .bitWidth = kWM8960_AudioBitWidth16bit},
- .master_slave = false,
- };
- codec_config_t boardCodecConfig = {.codecDevType = kCODEC_WM8960, .codecDevConfig = &wm8960Config};
- /* USB1 PLL configuration for RUN mode */
- const clock_audio_pll_config_t audioPllConfig = {
- .loopDivider = 32U, /*!< PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
- .postDivider = 1U, /*!< Divider after the PLL, should only be 1, 2, 4, 8, 16. */
- .numerator = 77, /*!< 30 bit numerator of fractional loop divider.*/
- .denominator = 100, /*!< 30 bit denominator of fractional loop divider */
- };
- AT_NONCACHEABLE_SECTION_INIT(flexio_i2s_edma_handle_t txHandle) = {0};
- edma_handle_t txDmaHandle = {0};
- AT_NONCACHEABLE_SECTION_ALIGN_INIT(static uint8_t audioBuff[BUFFER_SIZE * BUFFER_NUM], 4) = {0};
- extern codec_config_t boardCodecConfig;
- FLEXIO_I2S_Type s_base;
- static volatile uint8_t emptyBlock = 0;
- #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_DA7212) || defined(DEMO_CODEC_WM8962)
- // none of these preprocessor expressions evaluates to true on this board:
- #if (defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)) || \
- (defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER))
- sai_master_clock_t mclkConfig = {
- #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
- .mclkOutputEnable = true,
- #if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
- .mclkSource = kSAI_MclkSourceSysclk,
- #endif
- #endif
- };
- #endif
- #endif
- codec_handle_t codecHandle;
- #ifndef PI
- #define PI (3.141592654f)
- #endif
- #ifndef TWO_PI
- #define TWO_PI (PI*2)
- #endif
- static size_t waveform(uint16_t* samples, size_t sample_count, float* phase, int shape, size_t frequency, float amplitude, size_t sample_rate, size_t channels) {
- const float delta = TWO_PI*frequency/sample_rate;
- float f;
- uint16_t* out = samples;
- for(int i = 0;i<sample_count;++i) {
- switch(shape) {
- case 0: // sin
- f=sinf(*phase);
- break;
- case 1: // square
- f=(*phase>PI)*2-1.0;;
- break;
- case 2: // triangle
- f=(*phase-PI)/PI;
- break;
- case 3: // sawtooth
- f=(*phase-PI)/PI;
- break;
- }
- f*=amplitude;
- if(f<-1) f=-1;
- if(f>1) f=1;
- int16_t smp;
- if(f<0) {
- smp=f*32768.f;
- } else {
- smp=f*32767.f;
- }
- uint16_t smpt = (smp+(32768));
- for(int i = 0;i<channels;++i) {
- *(out++) = smpt;
- }
- *phase+=delta;
- if(*phase>TWO_PI) {
- *phase-=TWO_PI;
- }
- }
- return sample_count;
- }
- /*******************************************************************************
- * Code
- ******************************************************************************/
- void BOARD_EnableSaiMclkOutput(bool enable)
- {
- if (enable)
- {
- IOMUXC_GPR->GPR0 |= IOMUXC_GPR_GPR0_SAI1_MCLK_DIR_MASK;
- }
- else
- {
- IOMUXC_GPR->GPR0 &= (~IOMUXC_GPR_GPR0_SAI1_MCLK_DIR_MASK);
- }
- }
- static void txCallback(FLEXIO_I2S_Type *i2sBase, flexio_i2s_edma_handle_t *handle, status_t status, void *userData)
- {
- if ((emptyBlock < BUFFER_NUM))
- {
- emptyBlock++;
- }
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- DMAMUX_Type *dmamuxBase = NULL;
- flexio_i2s_config_t config;
- flexio_i2s_format_t format;
- flexio_i2s_transfer_t txXfer;
- uint8_t txIndex = 0;
- edma_config_t dmaConfig = {0};
- BOARD_ConfigMPU();
- BOARD_InitPins();
- BOARD_I2C_ConfigurePins();
- BOARD_FLEXIO_ConfigurePins();
- BOARD_BootClockRUN();
- BOARD_InitDebugConsole();
- BOARD_SAI_ConfigurePins();
- CLOCK_InitAudioPll(&audioPllConfig);
- /*Clock setting for LPI2C*/
- CLOCK_SetRootClockMux(kCLOCK_Root_Lpi2c5, 1);
- /*Clock setting for SAI1*/
- CLOCK_SetRootClockMux(kCLOCK_Root_Sai1, 4);
- CLOCK_SetRootClockDiv(kCLOCK_Root_Sai1, 16);
- /* Enable SAI1 MCLK output */
- BOARD_EnableSaiMclkOutput(true);
- BOARD_Codec_I2C_Init();
- PRINTF("FLEXIO I2S EDMA example started!\n\r");
- /* Set flexio i2s pin, shifter and timer */
- s_base.bclkPinIndex = BCLK_PIN;
- s_base.fsPinIndex = FRAME_SYNC_PIN;
- s_base.txPinIndex = TX_DATA_PIN;
- //s_base.rxPinIndex = RX_DATA_PIN;
- #if defined FLEXIO_TX_SHIFTER_INDEX
- s_base.txShifterIndex = FLEXIO_TX_SHIFTER_INDEX;
- #else
- s_base.txShifterIndex = 0;
- #endif
- #if defined FLEXIO_RX_SHIFTER_INDEX
- s_base.rxShifterIndex = FLEXIO_RX_SHIFTER_INDEX;
- #else
- s_base.rxShifterIndex = 1;
- #endif
- s_base.bclkTimerIndex = 0;
- s_base.fsTimerIndex = 1;
- s_base.flexioBase = DEMO_FLEXIO_BASE;
- #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_DA7212) || defined(DEMO_CODEC_WM8962)
- /* SAI init */
- SAI_Init(DEMO_SAI);
- PRINTF("SAI init!\n\r");
- /* I2S mode configurations */
- sai_transceiver_t saiConfig;
- SAI_GetClassicI2SConfig(&saiConfig, (sai_word_width_t)DEMO_AUDIO_BIT_WIDTH, kSAI_Stereo, kSAI_Channel0Mask);
- SAI_TxSetConfig(DEMO_SAI, &saiConfig);
- PRINTF("SAI TX config!\n\r");
- /* set bit clock divider */
- SAI_TxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
- DEMO_AUDIO_DATA_CHANNEL);
- PRINTF("SAI audio init!\n\r");
- /* master clock configurations */
- #if (defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)) || \
- (defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER))
- #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
- mclkConfig.mclkHz = DEMO_AUDIO_MASTER_CLOCK;
- mclkConfig.mclkSourceClkHz = DEMO_SAI_CLK_FREQ;
- #endif
- SAI_SetMasterClockConfig(DEMO_SAI, &mclkConfig);
- #endif
- SAI_TxEnable(DEMO_SAI, true);
- #endif
- PRINTF("SAI configured!\n\r");
- /* Create EDMA handle */
- /*
- * dmaConfig.enableRoundRobinArbitration = false;
- * dmaConfig.enableHaltOnError = true;
- * dmaConfig.enableContinuousLinkMode = false;
- * dmaConfig.enableDebugMode = false;
- */
- EDMA_GetDefaultConfig(&dmaConfig);
- EDMA_Init(EXAMPLE_DMA, &dmaConfig);
- EDMA_CreateHandle(&txDmaHandle, EXAMPLE_DMA, EXAMPLE_TX_CHANNEL);
- PRINTF("DMA handle created!\n\r");
- #if defined EXAMPLE_DMAMUX
- dmamuxBase = EXAMPLE_DMAMUX;
- #else
- dmamuxBase = DMAMUX0;
- #endif
- DMAMUX_Init(dmamuxBase);
- DMAMUX_SetSource(dmamuxBase, EXAMPLE_TX_CHANNEL, EXAMPLE_TX_DMA_SOURCE);
- DMAMUX_EnableChannel(dmamuxBase, EXAMPLE_TX_CHANNEL);
- /* Init SAI module */
- /*
- * config.enableI2S = true;
- */
- FLEXIO_I2S_GetDefaultConfig(&config);
- #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_WM8962)
- config.bclkPinPolarity = kFLEXIO_PinActiveLow;
- #endif
- FLEXIO_I2S_Init(&s_base, &config);
- /* Configure the audio format */
- format.bitWidth = DEMO_AUDIO_BIT_WIDTH;
- format.sampleRate_Hz = DEMO_AUDIO_SAMPLE_RATE;
- /* Use default setting to init codec */
- if (CODEC_Init(&codecHandle, &boardCodecConfig) != kStatus_Success)
- {
- assert(false);
- }
- FLEXIO_I2S_TransferTxCreateHandleEDMA(&s_base, &txHandle, txCallback, NULL, &txDmaHandle);
- FLEXIO_I2S_TransferSetFormatEDMA(&s_base, &txHandle, &format, DEMO_FLEXIO_CLK_FREQ);
- PRINTF("FLEXIO I2S EDMA initialized!\n\r");
- emptyBlock = BUFFER_NUM;
- float phase = 0;
- int shape = 0;
- float freq = 1000;
- float ampl = .5f;
- static const size_t sample_count = BUFFER_SIZE/sizeof(uint16_t)/2;
- PRINTF("First waveform\r\n");
- waveform((uint16_t*)audioBuff,sample_count , &phase, shape, freq, ampl, 44100, 2);
- emptyBlock=4;
- while (1)
- {
- PRINTF("Block transfer\n\r");
- if (emptyBlock >0)
- {
- uint8_t* p = audioBuff + txIndex * BUFFER_SIZE;
- txXfer.dataSize = BUFFER_SIZE;
- txXfer.data = p;
- PRINTF("Start waveform\n\r");
- waveform((uint16_t*)p,sample_count , &phase, shape, freq, ampl, 44100, 2);
- PRINTF("Start dma\n\r");
- if (FLEXIO_I2S_TransferSendEDMA(&s_base, &txHandle, &txXfer) == kStatus_Success)
- {
- --emptyBlock;
- txIndex = (txIndex + 1) % BUFFER_NUM;
- PRINTF("Transfer\n\r");
- } else {
- PRINTF("Transfer failed\n\r");
- }
- } else {
- PRINTF("HALT: emptyBlock: %d\n\r",(int)emptyBlock);
- while(1);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement