Advertisement
honey_the_codewitch

MIMXRT1170-EVK i2s (doesn't work)

Jan 14th, 2025 (edited)
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.95 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3.  * Copyright 2016-2019 NXP
  4.  * All rights reserved.
  5.  *
  6.  * SPDX-License-Identifier: BSD-3-Clause
  7.  */
  8. #include <math.h>
  9. #include <stdint.h>
  10. #include <stddef.h>
  11. #include "pin_mux.h"
  12. #include "clock_config.h"
  13. #include "board.h"
  14. #include "fsl_dmamux.h"
  15. #include "fsl_flexio_i2s_edma.h"
  16. #include "fsl_debug_console.h"
  17. #include "fsl_codec_common.h"
  18. #include "fsl_wm8960.h"
  19. #include "fsl_sai.h"
  20. #include "fsl_codec_adapter.h"
  21. /*******************************************************************************
  22.  * Definitions
  23.  ******************************************************************************/
  24. /* SAI and I2C instance and clock */
  25. #define DEMO_CODEC_WM8960
  26. #define DEMO_I2C         LPI2C5
  27. #define DEMO_FLEXIO_BASE FLEXIO2
  28. #define DEMO_SAI         SAI1
  29.  
  30. /* Get frequency of sai1 clock */
  31. #define DEMO_SAI_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_PLL_AUDIO_OUT))
  32.  
  33. /* Get frequency of lpi2c clock */
  34. #define DEMO_I2C_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_LPI2C5_CLK_ROOT))
  35.  
  36. #define DEMO_FLEXIO_CLK_FREQ (CLOCK_GetFreqFromObs(CCM_OBS_FLEXIO2_CLK_ROOT))
  37.  
  38. #define BCLK_PIN                (13U)
  39. #define FRAME_SYNC_PIN          (12U)
  40. #define TX_DATA_PIN             (11U)
  41. #define FLEXIO_TX_SHIFTER_INDEX 0
  42.  
  43. #define EXAMPLE_DMAMUX        DMAMUX0
  44. #define EXAMPLE_DMA           DMA0
  45. #define EXAMPLE_TX_CHANNEL    0
  46. #define EXAMPLE_TX_DMA_SOURCE kDmaRequestMuxFlexIO2Request0Request1
  47. //#define EXAMPLE_RX_DMA_SOURCE kDmaRequestMuxFlexIO2Request2Request3
  48. //#define OVER_SAMPLE_RATE (384)
  49. #define BUFFER_SIZE      (128)
  50. #define BUFFER_NUM       (4)
  51. #define PLAY_COUNT       (5000 * 2U)
  52.  
  53. /* demo audio sample rate */
  54. #define DEMO_AUDIO_SAMPLE_RATE (kFLEXIO_I2S_SampleRate44100Hz)
  55. /* demo audio master clock */
  56. #if (defined FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER && FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) || \
  57.     (defined FSL_FEATURE_PCC_HAS_SAI_DIVIDER && FSL_FEATURE_PCC_HAS_SAI_DIVIDER)
  58. //#define DEMO_AUDIO_MASTER_CLOCK OVER_SAMPLE_RATE *DEMO_AUDIO_SAMPLE_RATE
  59. #else
  60. #define DEMO_AUDIO_MASTER_CLOCK DEMO_SAI_CLK_FREQ
  61. #endif
  62. /* demo audio data channel */
  63. #define DEMO_AUDIO_DATA_CHANNEL (2U)
  64. /* demo audio bit width */
  65. #define DEMO_AUDIO_BIT_WIDTH (kFLEXIO_I2S_WordWidth16bits)
  66. /*******************************************************************************
  67.  * Prototypes
  68.  ******************************************************************************/
  69.  
  70. /*******************************************************************************
  71.  * Variables
  72.  ******************************************************************************/
  73. wm8960_config_t wm8960Config = {
  74.     .i2cConfig = {.codecI2CInstance = BOARD_CODEC_I2C_INSTANCE, .codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ},
  75.     .route     = kWM8960_RoutePlayback,
  76.     .enableSpeaker = true,
  77.     .leftInputSource  = kWM8960_InputClosed,//kWM8960_InputDifferentialMicInput3,
  78.     .rightInputSource = kWM8960_InputClosed,//kWM8960_InputDifferentialMicInput2,
  79.     .playSource       = kWM8960_ModuleLineOut,//kWM8960_ModuleHP
  80.     .slaveAddress     = WM8960_I2C_ADDR,
  81.     .bus              = kWM8960_BusI2S,
  82.     .format = {.mclk_HZ = /*24576000*/16934400, .sampleRate = kWM8960_AudioSampleRate44100Hz, .bitWidth = kWM8960_AudioBitWidth16bit},
  83.     .master_slave = false,
  84. };
  85. codec_config_t boardCodecConfig = {.codecDevType = kCODEC_WM8960, .codecDevConfig = &wm8960Config};
  86. /* USB1 PLL configuration for RUN mode */
  87. const clock_audio_pll_config_t audioPllConfig = {
  88.     .loopDivider = 32U, /*!< PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
  89.     .postDivider = 1U,  /*!< Divider after the PLL, should only be 1, 2, 4, 8, 16. */
  90.     .numerator   = 77,  /*!< 30 bit numerator of fractional loop divider.*/
  91.     .denominator = 100, /*!< 30 bit denominator of fractional loop divider */
  92. };
  93. AT_NONCACHEABLE_SECTION_INIT(flexio_i2s_edma_handle_t txHandle)                           = {0};
  94. edma_handle_t txDmaHandle                                                                 = {0};
  95. AT_NONCACHEABLE_SECTION_ALIGN_INIT(static uint8_t audioBuff[BUFFER_SIZE * BUFFER_NUM], 4) = {0};
  96.  
  97. extern codec_config_t boardCodecConfig;
  98. FLEXIO_I2S_Type s_base;
  99. static volatile uint8_t emptyBlock    = 0;
  100.  
  101. #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_DA7212) || defined(DEMO_CODEC_WM8962)
  102. // none of these preprocessor expressions evaluates to true on this board:
  103. #if (defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)) || \
  104.     (defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER))
  105. sai_master_clock_t mclkConfig = {
  106. #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
  107.     .mclkOutputEnable = true,
  108. #if !(defined(FSL_FEATURE_SAI_HAS_NO_MCR_MICS) && (FSL_FEATURE_SAI_HAS_NO_MCR_MICS))
  109.     .mclkSource = kSAI_MclkSourceSysclk,
  110. #endif
  111. #endif
  112. };
  113. #endif
  114. #endif
  115. codec_handle_t codecHandle;
  116.  
  117. #ifndef PI
  118. #define PI (3.141592654f)
  119. #endif
  120. #ifndef TWO_PI
  121. #define TWO_PI (PI*2)
  122. #endif
  123. 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) {
  124.     const float delta = TWO_PI*frequency/sample_rate;
  125.     float f;
  126.     uint16_t* out = samples;
  127.     for(int i = 0;i<sample_count;++i) {
  128.         switch(shape) {
  129.             case 0: // sin
  130.                 f=sinf(*phase);
  131.                 break;
  132.             case 1: // square
  133.                 f=(*phase>PI)*2-1.0;;
  134.                 break;
  135.             case 2: // triangle
  136.                 f=(*phase-PI)/PI;
  137.                 break;
  138.             case 3: // sawtooth
  139.                 f=(*phase-PI)/PI;
  140.                 break;
  141.         }
  142.         f*=amplitude;
  143.         if(f<-1) f=-1;
  144.         if(f>1) f=1;
  145.         int16_t smp;
  146.         if(f<0) {
  147.             smp=f*32768.f;
  148.         } else {
  149.             smp=f*32767.f;
  150.         }
  151.         uint16_t smpt = (smp+(32768));
  152.         for(int i = 0;i<channels;++i) {
  153.             *(out++) = smpt;
  154.         }
  155.         *phase+=delta;
  156.         if(*phase>TWO_PI) {
  157.             *phase-=TWO_PI;
  158.         }
  159.     }
  160.  
  161.  
  162.     return sample_count;
  163. }
  164. /*******************************************************************************
  165.  * Code
  166.  ******************************************************************************/
  167. void BOARD_EnableSaiMclkOutput(bool enable)
  168. {
  169.     if (enable)
  170.     {
  171.         IOMUXC_GPR->GPR0 |= IOMUXC_GPR_GPR0_SAI1_MCLK_DIR_MASK;
  172.     }
  173.     else
  174.     {
  175.         IOMUXC_GPR->GPR0 &= (~IOMUXC_GPR_GPR0_SAI1_MCLK_DIR_MASK);
  176.     }
  177. }
  178.  
  179. static void txCallback(FLEXIO_I2S_Type *i2sBase, flexio_i2s_edma_handle_t *handle, status_t status, void *userData)
  180. {
  181.     if ((emptyBlock < BUFFER_NUM))
  182.     {
  183.         emptyBlock++;
  184.     }
  185.  
  186. }
  187. /*!
  188.  * @brief Main function
  189.  */
  190. int main(void)
  191. {
  192.     DMAMUX_Type *dmamuxBase = NULL;
  193.     flexio_i2s_config_t config;
  194.     flexio_i2s_format_t format;
  195.     flexio_i2s_transfer_t txXfer;
  196.     uint8_t txIndex = 0;
  197.     edma_config_t dmaConfig = {0};
  198.  
  199.     BOARD_ConfigMPU();
  200.     BOARD_InitPins();
  201.     BOARD_I2C_ConfigurePins();
  202.     BOARD_FLEXIO_ConfigurePins();
  203.     BOARD_BootClockRUN();
  204.     BOARD_InitDebugConsole();
  205.     BOARD_SAI_ConfigurePins();
  206.     CLOCK_InitAudioPll(&audioPllConfig);
  207.  
  208.     /*Clock setting for LPI2C*/
  209.     CLOCK_SetRootClockMux(kCLOCK_Root_Lpi2c5, 1);
  210.  
  211.     /*Clock setting for SAI1*/
  212.     CLOCK_SetRootClockMux(kCLOCK_Root_Sai1, 4);
  213.     CLOCK_SetRootClockDiv(kCLOCK_Root_Sai1, 16);
  214.  
  215.     /* Enable SAI1 MCLK output */
  216.     BOARD_EnableSaiMclkOutput(true);
  217.     BOARD_Codec_I2C_Init();
  218.     PRINTF("FLEXIO I2S EDMA example started!\n\r");
  219.  
  220.     /* Set flexio i2s pin, shifter and timer */
  221.     s_base.bclkPinIndex = BCLK_PIN;
  222.     s_base.fsPinIndex   = FRAME_SYNC_PIN;
  223.     s_base.txPinIndex   = TX_DATA_PIN;
  224.     //s_base.rxPinIndex   = RX_DATA_PIN;
  225.  
  226. #if defined FLEXIO_TX_SHIFTER_INDEX
  227.     s_base.txShifterIndex = FLEXIO_TX_SHIFTER_INDEX;
  228. #else
  229.     s_base.txShifterIndex = 0;
  230. #endif
  231. #if defined FLEXIO_RX_SHIFTER_INDEX
  232.     s_base.rxShifterIndex = FLEXIO_RX_SHIFTER_INDEX;
  233. #else
  234.     s_base.rxShifterIndex = 1;
  235. #endif
  236.     s_base.bclkTimerIndex = 0;
  237.     s_base.fsTimerIndex   = 1;
  238.     s_base.flexioBase     = DEMO_FLEXIO_BASE;
  239.  
  240. #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_DA7212) || defined(DEMO_CODEC_WM8962)
  241.     /* SAI init */
  242.     SAI_Init(DEMO_SAI);
  243.     PRINTF("SAI init!\n\r");
  244.     /* I2S mode configurations */
  245.     sai_transceiver_t saiConfig;
  246.     SAI_GetClassicI2SConfig(&saiConfig, (sai_word_width_t)DEMO_AUDIO_BIT_WIDTH, kSAI_Stereo, kSAI_Channel0Mask);
  247.  
  248.     SAI_TxSetConfig(DEMO_SAI, &saiConfig);
  249.     PRINTF("SAI TX config!\n\r");
  250.     /* set bit clock divider */
  251.     SAI_TxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
  252.                           DEMO_AUDIO_DATA_CHANNEL);
  253.     PRINTF("SAI audio init!\n\r");
  254.  
  255.     /* master clock configurations */
  256. #if (defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)) || \
  257.     (defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER))
  258. #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
  259.     mclkConfig.mclkHz          = DEMO_AUDIO_MASTER_CLOCK;
  260.     mclkConfig.mclkSourceClkHz = DEMO_SAI_CLK_FREQ;
  261.     #endif
  262.     SAI_SetMasterClockConfig(DEMO_SAI, &mclkConfig);
  263. #endif
  264.  
  265.  
  266.     SAI_TxEnable(DEMO_SAI, true);
  267. #endif
  268.     PRINTF("SAI configured!\n\r");
  269.     /* Create EDMA handle */
  270.     /*
  271.      * dmaConfig.enableRoundRobinArbitration = false;
  272.      * dmaConfig.enableHaltOnError = true;
  273.      * dmaConfig.enableContinuousLinkMode = false;
  274.      * dmaConfig.enableDebugMode = false;
  275.      */
  276.     EDMA_GetDefaultConfig(&dmaConfig);
  277.     EDMA_Init(EXAMPLE_DMA, &dmaConfig);
  278.     EDMA_CreateHandle(&txDmaHandle, EXAMPLE_DMA, EXAMPLE_TX_CHANNEL);
  279.     PRINTF("DMA handle created!\n\r");
  280. #if defined EXAMPLE_DMAMUX
  281.     dmamuxBase = EXAMPLE_DMAMUX;
  282. #else
  283.     dmamuxBase          = DMAMUX0;
  284. #endif
  285.     DMAMUX_Init(dmamuxBase);
  286.     DMAMUX_SetSource(dmamuxBase, EXAMPLE_TX_CHANNEL, EXAMPLE_TX_DMA_SOURCE);
  287.     DMAMUX_EnableChannel(dmamuxBase, EXAMPLE_TX_CHANNEL);
  288.  
  289.     /* Init SAI module */
  290.     /*
  291.      * config.enableI2S = true;
  292.      */
  293.     FLEXIO_I2S_GetDefaultConfig(&config);
  294. #if defined(DEMO_CODEC_WM8960) || defined(DEMO_CODEC_WM8962)
  295.     config.bclkPinPolarity = kFLEXIO_PinActiveLow;
  296. #endif
  297.     FLEXIO_I2S_Init(&s_base, &config);
  298.  
  299.     /* Configure the audio format */
  300.     format.bitWidth      = DEMO_AUDIO_BIT_WIDTH;
  301.     format.sampleRate_Hz = DEMO_AUDIO_SAMPLE_RATE;
  302.  
  303.     /* Use default setting to init codec */
  304.     if (CODEC_Init(&codecHandle, &boardCodecConfig) != kStatus_Success)
  305.     {
  306.         assert(false);
  307.     }
  308.  
  309.     FLEXIO_I2S_TransferTxCreateHandleEDMA(&s_base, &txHandle, txCallback, NULL, &txDmaHandle);
  310.  
  311.     FLEXIO_I2S_TransferSetFormatEDMA(&s_base, &txHandle, &format, DEMO_FLEXIO_CLK_FREQ);
  312.     PRINTF("FLEXIO I2S EDMA initialized!\n\r");
  313.     emptyBlock = BUFFER_NUM;
  314.  
  315.     float phase = 0;
  316.     int shape = 0;
  317.     float freq = 1000;
  318.     float ampl = .5f;
  319.     static const size_t sample_count = BUFFER_SIZE/sizeof(uint16_t)/2;
  320.     PRINTF("First waveform\r\n");
  321.     waveform((uint16_t*)audioBuff,sample_count , &phase, shape, freq, ampl, 44100, 2);
  322.     emptyBlock=4;
  323.     while (1)
  324.     {
  325.         PRINTF("Block transfer\n\r");
  326.         if (emptyBlock >0)
  327.         {
  328.             uint8_t* p = audioBuff + txIndex * BUFFER_SIZE;
  329.             txXfer.dataSize = BUFFER_SIZE;
  330.             txXfer.data     = p;
  331.             PRINTF("Start waveform\n\r");
  332.             waveform((uint16_t*)p,sample_count , &phase, shape, freq, ampl, 44100, 2);
  333.             PRINTF("Start dma\n\r");
  334.             if (FLEXIO_I2S_TransferSendEDMA(&s_base, &txHandle, &txXfer) == kStatus_Success)
  335.             {
  336.                 --emptyBlock;
  337.                 txIndex = (txIndex + 1) % BUFFER_NUM;
  338.                 PRINTF("Transfer\n\r");
  339.  
  340.             } else {
  341.                 PRINTF("Transfer failed\n\r");
  342.             }
  343.  
  344.  
  345.  
  346.         } else {
  347.             PRINTF("HALT: emptyBlock: %d\n\r",(int)emptyBlock);
  348.             while(1);
  349.         }
  350.     }
  351. }
  352.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement