This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

McASP I2S problem

Other Parts Discussed in Thread: OMAP-L138, OMAP-L137, DM385

I need to use 32 bit audio signal using I2S slave mode  in OMAP-L137 and OMAP-L138. 

input Audio Spec :   32 bit  , I2S 

receive clock :  Bit clock, Word clock from other board

I want to get I2S signal and some signal processing and send to other board using I2S signal.

I just copy input buffer to output buffer, but I cannot get I2S signal on the EVM board.

Is there any other setting for pin configuration?

I guess I did not set about PINMUX, I don't know how can I do for PIN configuration.

If my initial file is ok, I can check I2S signal using oscillopscope, but at this time no signal comes out.

Here is my initial file (L137)

-------

void McASP_Init_L137(void)
{
        /* Initialize MCASP1 */
         mcasp = &MCASP_MODULE_1;
         /* ---------------------------------------------------------------- *
          *                                                                  *
          *  McASP1 is in Slave mode.                                       *
          *      BCLK & WCLK come from McASP1                                *
          *      DIN is used by write16/write32                              *
          *      DOUT is usec by read16/read32                               *
          *                                                                  *
          * ---------------------------------------------------------------- */
         mcasp->regs->GBLCTL  = 0;       // Reset
         mcasp->regs->RGBLCTL = 0;       // Reset RX
         mcasp->regs->XGBLCTL = 0;       // Reset TX
         mcasp->regs->PWRDEMU = 1;       // Free-running

           /* RX */
         mcasp->regs->RMASK      = 0xffffffff; // No padding used
         mcasp->regs->RFMT       = 0x0001807C; // MSB 16bit, 1-delay, no pad, CFGBus
         mcasp->regs->AFSRCTL    = 0x00000112; // 2TDM, 1bit Rising, INTERNAL FS, word
         mcasp->regs->ACLKRCTL   = 0x000000AF; // Rising INTERNAL CLK,(from tx side)
         mcasp->regs->AHCLKRCTL  = 0x00000000; // INT CLK (from tx side)
         mcasp->regs->RTDM       = 0x00000003; // Slots 0,1
         mcasp->regs->RINTCTL    = 0x00000000; // Not used
         mcasp->regs->RCLKCHK    = 0x00FF0008; // 255-MAX 0-MIN, div-by-256

         /* TX */
         mcasp->regs->XMASK      = 0xffffffff; // No padding used
         mcasp->regs->XFMT       = 0x0001807C; // MSB 16bit, 1-delay, no pad, CFGBus
         mcasp->regs->AFSXCTL    = 0x00000112; // 2TDM, 1bit Rising edge INTERNAL FS, word
         mcasp->regs->ACLKXCTL   = 0x000000AF; // ASYNC, Rising INTERNAL CLK, div-by-16
         mcasp->regs->AHCLKXCTL  = 0x00000000; // EXT CLK
         mcasp->regs->XTDM       = 0x00000003; // Slots 0,1
         mcasp->regs->XINTCTL    = 0x00000000; // Not used
         mcasp->regs->XCLKCHK    = 0x00FF0008; // 255-MAX 0-MIN, div-by-256

         mcasp->regs->SRCTL5     = 0x000D;     // MCASP1.AXR1[5] --> DIN
         mcasp->regs->SRCTL0     = 0x000E;     // MCASP1.AXR1[0] <-- DOUT
         mcasp->regs->PFUNC      = 0;          // All MCASPs
         mcasp->regs->PDIR       = 0x14000020; // All inputs except AXR0[5], ACLKX1, AFSX1

         mcasp->regs->DITCTL     = 0x00000000; // Not used
         mcasp->regs->DLBCTL     = 0x00000000; // Not used
         mcasp->regs->AMUTE      = 0x00000000; // Not used
}
 
void McASP_Start_L137(void)
{
    /* Starting sections of the McASP*/
    mcasp->regs->XGBLCTL |= GBLCTL_XHCLKRST_ON;                                    // HS Clk
    while ( ( mcasp->regs->XGBLCTL & GBLCTL_XHCLKRST_ON ) != GBLCTL_XHCLKRST_ON );
    mcasp->regs->RGBLCTL |= GBLCTL_RHCLKRST_ON;                                    // HS Clk
    while ( ( mcasp->regs->RGBLCTL & GBLCTL_RHCLKRST_ON ) != GBLCTL_RHCLKRST_ON );

    mcasp->regs->XGBLCTL |= GBLCTL_XCLKRST_ON;                                     // Clk
    while ( ( mcasp->regs->XGBLCTL & GBLCTL_XCLKRST_ON ) != GBLCTL_XCLKRST_ON );
    mcasp->regs->RGBLCTL |= GBLCTL_RCLKRST_ON;                                     // Clk
    while ( ( mcasp->regs->RGBLCTL & GBLCTL_RCLKRST_ON ) != GBLCTL_RCLKRST_ON );

    mcasp->regs->RINTCTL |= RDATA;                              // enable McASP XMT/RCV interrupts
    while ( ( mcasp->regs->RINTCTL & RDATA ) != RDATA );
    mcasp->regs->XINTCTL |= XDATA;
    while ( ( mcasp->regs->XINTCTL & XDATA ) != XDATA );

    mcasp->regs->XSTAT = 0x0000ffff;        // Clear all
    mcasp->regs->RSTAT = 0x0000ffff;        // Clear all

    mcasp->regs->XGBLCTL |= GBLCTL_XSRCLR_ON;                                      // Serialize
    while ( ( mcasp->regs->XGBLCTL & GBLCTL_XSRCLR_ON ) != GBLCTL_XSRCLR_ON );
    mcasp->regs->RGBLCTL |= GBLCTL_RSRCLR_ON;                                      // Serialize
    while ( ( mcasp->regs->RGBLCTL & GBLCTL_RSRCLR_ON ) != GBLCTL_RSRCLR_ON );

    /* Write a 0, so that no underrun occurs after releasing the state machine */
    mcasp->regs->XBUF5 = 0;
    mcasp->regs->RBUF0 = 0;

    mcasp->regs->XGBLCTL |= GBLCTL_XSMRST_ON;                                       // State Machine
    while ( ( mcasp->regs->XGBLCTL & GBLCTL_XSMRST_ON ) != GBLCTL_XSMRST_ON );
    mcasp->regs->RGBLCTL |= GBLCTL_RSMRST_ON;                                       // State Machine
    while ( ( mcasp->regs->RGBLCTL & GBLCTL_RSMRST_ON ) != GBLCTL_RSMRST_ON );

    mcasp->regs->XGBLCTL |= GBLCTL_XFRST_ON;                                        // Frame Sync
    while ( ( mcasp->regs->XGBLCTL & GBLCTL_XFRST_ON ) != GBLCTL_XFRST_ON );
    mcasp->regs->RGBLCTL |= GBLCTL_RFRST_ON;                                        // Frame Sync
    while ( ( mcasp->regs->RGBLCTL & GBLCTL_RFRST_ON ) != GBLCTL_RFRST_ON );


    /* Start by sending a dummy write */
    while( ! ( mcasp->regs->SRCTL5 & 0x10 ) );  // Check for Tx ready
    mcasp->regs->XBUF5 = 0;
}
 
Thanks in advance
Doug
  • Hi Doug,

    Thanks for your post.

    There are some tips in using McASP in I2S mode as follows:

    1. I2S mode shall be used only in 2-slot frame as part of TDM transmission format, otherwise, if more slots/frame through I2S interface shall be possible only by external DIR (digital interface receiver) device

    2. For I2S format, (R/X)DATDLY should be set to a 1-bit delay, whereas for left-justified format, it should be set to a 0-bit delay (refer section 26.2.3.2 in the TRM)

    3. To transmit in I2S format, use MSB first, left aligned, and also select XDATDLY = 01,  RDATDLY = 01 ((1 bit delay) (refer Table 26-4 & Table 26-5 in the TRM)

    In addition to the above tips, there are some considerations to use the system with McASP module (clocks, datapins, data format, data transfers) and also there are some steps to properly configure the McASP module for the transmit/receive section initialization. Please ensure the steps referred in Section 26.2.4.1 in the TRM are followed correctly in your configuration.

    Please refer the OMAPL137 TRM as below:

    http://www.ti.com/lit/ug/spruh92b/spruh92b.pdf

    For your easy reference, i have attached you the sample code snippet to configure McASP Transmit section in I2S mode. Please refer the function McASPI2SConfigure() in the attached code snippet.

    /**
     * \file  mcaspPlayBk.c
     *
     * \brief Sample application for McASP. This application loops back the input
     *        at LINE_IN of the EVM to the LINE_OUT of the EVM. 
     */
    
    /*
    * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 
    *
    *  Redistribution and use in source and binary forms, with or without 
    *  modification, are permitted provided that the following conditions 
    *  are met:
    *
    *    Redistributions of source code must retain the above copyright 
    *    notice, this list of conditions and the following disclaimer.
    *
    *    Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the 
    *    documentation and/or other materials provided with the   
    *    distribution.
    *
    *    Neither the name of Texas Instruments Incorporated nor the names of
    *    its contributors may be used to endorse or promote products derived
    *    from this software without specific prior written permission.
    *
    *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
    
    #include "edma_event.h" 
    #include "interrupt.h"
    #include "soc_C6748.h"
    #include "hw_syscfg0_C6748.h"
    #include "evmC6748.h"
    #include "codecif.h"
    #include "mcasp.h"
    #include "aic31.h"
    #include "edma.h"
    #include "psc.h"
    
    #include <string.h>
    
    /******************************************************************************
    **                      INTERNAL MACRO DEFINITIONS
    ******************************************************************************/
    /*
    ** Values which are configurable
    */
    /* Slot size to send/receive data */
    #define SLOT_SIZE                             (16u)
    
    /* Word size to send/receive data. Word size <= Slot size */
    #define WORD_SIZE                             (16u)
    
    /* Sampling Rate which will be used by both transmit and receive sections */
    #define SAMPLING_RATE                         (48000u)
    
    /* Number of channels, L & R */
    #define NUM_I2S_CHANNELS                      (2u) 
    
    /* Number of samples to be used per audio buffer */
    #define NUM_SAMPLES_PER_AUDIO_BUF             (2000u)
    
    /* Number of buffers used per tx/rx */
    #define NUM_BUF                               (3u)
    
    /* Number of linked parameter set used per tx/rx */
    #define NUM_PAR                               (2u)
    
    /* Specify where the parameter set starting is */
    #define PAR_ID_START                          (40u)
    
    /* Number of samples in loop buffer */
    #define NUM_SAMPLES_LOOP_BUF                  (10u)
    
    /* AIC3106 codec address */
    #define I2C_SLAVE_CODEC_AIC31                 (0x18u) 
    
    /* Interrupt channels to map in AINTC */
    #define INT_CHANNEL_I2C                       (2u)
    #define INT_CHANNEL_MCASP                     (2u)
    #define INT_CHANNEL_EDMACC                    (2u)
    
    /* McASP Serializer for Receive */
    #define MCASP_XSER_RX                         (12u)
    
    /* McASP Serializer for Transmit */
    #define MCASP_XSER_TX                         (11u)
    
    /*
    ** Below Macros are calculated based on the above inputs
    */
    #define NUM_TX_SERIALIZERS                    ((NUM_I2S_CHANNELS >> 1) \
                                                   + (NUM_I2S_CHANNELS & 0x01))
    #define NUM_RX_SERIALIZERS                    ((NUM_I2S_CHANNELS >> 1) \
                                                   + (NUM_I2S_CHANNELS & 0x01))
    #define I2S_SLOTS                             ((1 << NUM_I2S_CHANNELS) - 1)
    
    #define BYTES_PER_SAMPLE                      ((WORD_SIZE >> 3) \
                                                   * NUM_I2S_CHANNELS)
    
    #define AUDIO_BUF_SIZE                        (NUM_SAMPLES_PER_AUDIO_BUF \
                                                   * BYTES_PER_SAMPLE)
    
    #define TX_DMA_INT_ENABLE                     (EDMA3CC_OPT_TCC_SET(1) | (1 \
                                                   << EDMA3CC_OPT_TCINTEN_SHIFT))
    #define RX_DMA_INT_ENABLE                     (EDMA3CC_OPT_TCC_SET(0) | (1 \
                                                   << EDMA3CC_OPT_TCINTEN_SHIFT))
    
    #define PAR_RX_START                          (PAR_ID_START)
    #define PAR_TX_START                          (PAR_RX_START + NUM_PAR)
    
    /*
    ** Definitions which are not configurable 
    */
    #define SIZE_PARAMSET                         (32u)
    #define OPT_FIFO_WIDTH                        (0x02 << 8u)
    
    /******************************************************************************
    **                      INTERNAL FUNCTION PROTOTYPES
    ******************************************************************************/
    static void McASPErrorIsr(void);
    static void McASPErrorIntSetup(void);
    static void AIC31I2SConfigure(void);
    static void McASPI2SConfigure(void);
    static void McASPTxDMAComplHandler(void);
    static void McASPRxDMAComplHandler(void);
    static void EDMA3CCComplIsr(void);
    static void I2SDataTxRxActivate(void);
    static void I2SDMAParamInit(void);
    static void ParamTxLoopJobSet(unsigned short parId);
    static void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
                                    unsigned short parToUpdate, 
                                    unsigned short linkAddr);
    static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
                                    unsigned short parLink);
    
    /******************************************************************************
    **                      INTERNAL VARIABLE DEFINITIONS
    ******************************************************************************/
    static unsigned char loopBuf[NUM_SAMPLES_LOOP_BUF * BYTES_PER_SAMPLE] = {0};
    
    /*
    ** Transmit buffers. If any new buffer is to be added, define it here and 
    ** update the NUM_BUF.
    */
    static unsigned char txBuf0[AUDIO_BUF_SIZE];
    static unsigned char txBuf1[AUDIO_BUF_SIZE];
    static unsigned char txBuf2[AUDIO_BUF_SIZE];
    
    /*
    ** Receive buffers. If any new buffer is to be added, define it here and 
    ** update the NUM_BUF.
    */
    static unsigned char rxBuf0[AUDIO_BUF_SIZE];
    static unsigned char rxBuf1[AUDIO_BUF_SIZE];
    static unsigned char rxBuf2[AUDIO_BUF_SIZE];
    
    /*
    ** Next buffer to receive data. The data will be received in this buffer.
    */
    static volatile unsigned int nxtBufToRcv = 0;
    
    /*
    ** The RX buffer which filled latest.
    */
    static volatile unsigned int lastFullRxBuf = 0;
    
    /*
    ** The offset of the paRAM ID, from the starting of the paRAM set.
    */
    static volatile unsigned short parOffRcvd = 0;
    
    /*
    ** The offset of the paRAM ID sent, from starting of the paRAM set.
    */
    static volatile unsigned short parOffSent = 0;
    
    /*
    ** The offset of the paRAM ID to be sent next, from starting of the paRAM set. 
    */
    static volatile unsigned short parOffTxToSend = 0;
    
    /*
    ** The transmit buffer which was sent last.
    */
    static volatile unsigned int lastSentTxBuf = NUM_BUF - 1;
    
    /******************************************************************************
    **                      INTERNAL CONSTATNT DEFINITIONS
    ******************************************************************************/
    /* Array of receive buffer pointers */
    static unsigned int const rxBufPtr[NUM_BUF] =
           { 
               (unsigned int) rxBuf0,
               (unsigned int) rxBuf1,
               (unsigned int) rxBuf2
           };
    
    /* Array of transmit buffer pointers */
    static unsigned int const txBufPtr[NUM_BUF] =
           { 
               (unsigned int) txBuf0,
               (unsigned int) txBuf1,
               (unsigned int) txBuf2
           };
    
    /*
    ** Default paRAM for Transmit section. This will be transmitting from 
    ** a loop buffer.
    */
    static struct EDMA3CCPaRAMEntry const txDefaultPar = 
           {
               (unsigned int)(EDMA3CC_OPT_DAM  | (0x02 << 8u)), /* Opt field */
               (unsigned int)loopBuf, /* source address */
               (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
               (unsigned short)(NUM_SAMPLES_LOOP_BUF), /* bCnt */ 
               (unsigned int) SOC_MCASP_0_DATA_REGS, /* dest address */
               (short) (BYTES_PER_SAMPLE), /* source bIdx */
               (short)(0), /* dest bIdx */
               (unsigned short)(PAR_TX_START * SIZE_PARAMSET), /* link address */
               (unsigned short)(0), /* bCnt reload value */
               (short)(0), /* source cIdx */
               (short)(0), /* dest cIdx */
               (unsigned short)1 /* cCnt */
           };
    
    /*
    ** Default paRAM for Receive section.  
    */
    static struct EDMA3CCPaRAMEntry const rxDefaultPar =
           {
               (unsigned int)(EDMA3CC_OPT_SAM  | (0x02 << 8u)), /* Opt field */
               (unsigned int)SOC_MCASP_0_DATA_REGS, /* source address */
               (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
               (unsigned short)(1), /* bCnt */
               (unsigned int)rxBuf0, /* dest address */
               (short) (0), /* source bIdx */
               (short)(BYTES_PER_SAMPLE), /* dest bIdx */
               (unsigned short)(PAR_RX_START * SIZE_PARAMSET), /* link address */
               (unsigned short)(0), /* bCnt reload value */
               (short)(0), /* source cIdx */
               (short)(0), /* dest cIdx */
               (unsigned short)1 /* cCnt */
           };
    
    /******************************************************************************
    **                          FUNCTION DEFINITIONS
    ******************************************************************************/
    /*
    ** Assigns loop job for a parameter set
    */
    static void ParamTxLoopJobSet(unsigned short parId)
    {
        EDMA3CCPaRAMEntry paramSet;
        
        memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2);
      
        /* link the paRAM to itself */
        paramSet.linkAddr = parId * SIZE_PARAMSET;
    
        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet);
    }
    
    /*
    ** Initializes the DMA parameters.
    ** The RX basic paRAM set(channel) is 0 and TX basic paRAM set (channel) is 1.
    **
    ** The RX paRAM set 0 will be initialized to receive data in the rx buffer 0.
    ** The transfer completion interrupt will not be enabled for paRAM set 0;
    ** paRAM set 0 will be linked to linked paRAM set starting (PAR_RX_START) of RX.
    ** and further reception only happens via linked paRAM set. 
    ** For example, if the PAR_RX_START value is 40, and the number of paRAMS is 2, 
    ** reception paRAM set linking will be initialized as 0-->40-->41-->40
    **
    ** The TX paRAM sets will be initialized to transmit from the loop buffer.
    ** The size of the loop buffer can be configured.   
    ** The transfer completion interrupt will not be enabled for paRAM set 1;
    ** paRAM set 1 will be linked to linked paRAM set starting (PAR_TX_START) of TX.
    ** All other paRAM sets will be linked to itself.
    ** and further transmission only happens via linked paRAM set.
    ** For example, if the PAR_RX_START value is 42, and the number of paRAMS is 2, 
    ** So transmission paRAM set linking will be initialized as 1-->42-->42, 43->43. 
    */
    static void I2SDMAParamInit(void)
    {
        EDMA3CCPaRAMEntry paramSet;
        int idx; 
     
        /* Initialize the 0th paRAM set for receive */ 
        memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2);
    
        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, &paramSet);
    
        /* further paramsets, enable interrupt */
        paramSet.opt |= RX_DMA_INT_ENABLE; 
     
        for(idx = 0 ; idx < NUM_PAR; idx++)
        {
            paramSet.destAddr = rxBufPtr[idx];
    
            paramSet.linkAddr = (PAR_RX_START + ((idx + 1) % NUM_PAR)) 
                                 * (SIZE_PARAMSET);        
    
            paramSet.bCnt =  NUM_SAMPLES_PER_AUDIO_BUF;
    
            /* 
            ** for the first linked paRAM set, start receiving the second
            ** sample only since the first sample is already received in
            ** rx buffer 0 itself.
            */
            if( 0 == idx)
            {
                paramSet.destAddr += BYTES_PER_SAMPLE;
                paramSet.bCnt -= BYTES_PER_SAMPLE;
            }
    
            EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, (PAR_RX_START + idx), &paramSet);
        } 
    
        /* Initialize the required variables for reception */
        nxtBufToRcv = idx % NUM_BUF;
        lastFullRxBuf = NUM_BUF - 1;
        parOffRcvd = 0;
    
        /* Initialize the 1st paRAM set for transmit */ 
        memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET);
    
        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX, &paramSet);
    
        /* rest of the params, enable loop job */
        for(idx = 0 ; idx < NUM_PAR; idx++)
        {
            ParamTxLoopJobSet(PAR_TX_START + idx);
        }
     
        /* Initialize the variables for transmit */
        parOffSent = 0;
        lastSentTxBuf = NUM_BUF - 1; 
    }
    
    /*
    ** Function to configure the codec for I2S mode
    */
    static void AIC31I2SConfigure(void)
    {
        volatile unsigned int delay = 0xFFF;
    
        AIC31Reset(SOC_I2C_0_REGS);
        while(delay--);
    
        /* Configure the data format and sampling rate */
        AIC31DataConfig(SOC_I2C_0_REGS, AIC31_DATATYPE_I2S, SLOT_SIZE, 0);
        AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, SAMPLING_RATE);
    
        /* Initialize both ADC and DAC */
        AIC31ADCInit(SOC_I2C_0_REGS);
        AIC31DACInit(SOC_I2C_0_REGS);
    }
    
    /*
    ** Configures the McASP Transmit Section in I2S mode.
    */
    static void McASPI2SConfigure(void)
    {
        McASPRxReset(SOC_MCASP_0_CTRL_REGS);
        McASPTxReset(SOC_MCASP_0_CTRL_REGS);
    
        /* Enable the FIFOs for DMA transfer */
        McASPReadFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1);
        McASPWriteFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1);
    
        /* Set I2S format in the transmitter/receiver format units */
        McASPRxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE,
                         MCASP_RX_MODE_DMA);
        McASPTxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE,
                         MCASP_TX_MODE_DMA);
    
        /* Configure the frame sync. I2S shall work in TDM format with 2 slots */
        McASPRxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_RX_FS_WIDTH_WORD, 
                            MCASP_RX_FS_EXT_BEGIN_ON_RIS_EDGE);
        McASPTxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_TX_FS_WIDTH_WORD, 
                            MCASP_TX_FS_EXT_BEGIN_ON_RIS_EDGE);
    
        /* configure the clock for receiver */
        McASPRxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL, 0, 0);
        McASPRxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_POL_RIS_EDGE); 
        McASPRxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLKCHCK_DIV32,
                              0x00, 0xFF);
    
        /* configure the clock for transmitter */
        McASPTxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL, 0, 0);
        McASPTxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_POL_FALL_EDGE); 
        McASPTxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLKCHCK_DIV32,
                              0x00, 0xFF);
     
        /* Enable synchronization of RX and TX sections  */  
        McASPTxRxClkSyncEnable(SOC_MCASP_0_CTRL_REGS);
    
        /* Enable the transmitter/receiver slots. I2S uses 2 slots */
        McASPRxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS);
        McASPTxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS);
    
        /*
        ** Set the serializers, Currently only one serializer is set as
        ** transmitter and one serializer as receiver.
        */
        McASPSerializerRxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_RX);
        McASPSerializerTxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_TX);
    
        /*
        ** Configure the McASP pins 
        ** Input - Frame Sync, Clock and Serializer Rx
        ** Output - Serializer Tx is connected to the input of the codec 
        */
        McASPPinMcASPSet(SOC_MCASP_0_CTRL_REGS, 0xFFFFFFFF);
        McASPPinDirOutputSet(SOC_MCASP_0_CTRL_REGS, MCASP_PIN_AXR(MCASP_XSER_TX));
        McASPPinDirInputSet(SOC_MCASP_0_CTRL_REGS, MCASP_PIN_AFSX 
                                                   | MCASP_PIN_ACLKX
                                                   | MCASP_PIN_AFSR
                                                   | MCASP_PIN_ACLKR
                                                   | MCASP_PIN_AXR(MCASP_XSER_RX));
    
        /* Enable error interrupts for McASP */
        McASPTxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_TX_DMAERROR 
                                                | MCASP_TX_CLKFAIL 
                                                | MCASP_TX_SYNCERROR
                                                | MCASP_TX_UNDERRUN);
    
        McASPRxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_RX_DMAERROR 
                                                | MCASP_RX_CLKFAIL
                                                | MCASP_RX_SYNCERROR 
                                                | MCASP_RX_OVERRUN);
    }
    
    /*
    ** Sets up the interrupts for EDMA in AINTC
    */
    static void EDMA3IntSetup(void)
    {
    #ifdef _TMS320C6X
    	IntRegister(C674X_MASK_INT5, EDMA3CCComplIsr);
    	IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_0_CC0_INT1);
    	IntEnable(C674X_MASK_INT5);
    #else
        IntRegister(SYS_INT_CCINT0, EDMA3CCComplIsr);
        IntChannelSet(SYS_INT_CCINT0, INT_CHANNEL_EDMACC); 
        IntSystemEnable(SYS_INT_CCINT0);
    #endif
    }
    
    /*
    ** Sets up the error interrupts for McASP in AINTC
    */
    static void McASPErrorIntSetup(void)
    {
    #ifdef _TMS320C6X
    	IntRegister(C674X_MASK_INT6, McASPErrorIsr);
    	IntEventMap(C674X_MASK_INT6, SYS_INT_MCASP0_INT);
    	IntEnable(C674X_MASK_INT6);
    #else
        /* Register the error ISR for McASP */
        IntRegister(SYS_INT_MCASPINT, McASPErrorIsr);
    
        IntChannelSet(SYS_INT_MCASPINT, INT_CHANNEL_MCASP);
        IntSystemEnable(SYS_INT_MCASPINT);
    #endif
    }
    
    /*
    ** Activates the data transmission/reception
    ** The DMA parameters shall be ready before calling this function.
    */
    static void I2SDataTxRxActivate(void)
    {
        /* Start the clocks */
        McASPRxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL);
        McASPTxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL);
    
        /* Enable EDMA for the transfer */
        EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX,
                            EDMA3_TRIG_MODE_EVENT);
        EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, 
                            EDMA3_CHA_MCASP0_TX, EDMA3_TRIG_MODE_EVENT);
    
        /* Activate the  serializers */
        McASPRxSerActivate(SOC_MCASP_0_CTRL_REGS);
        McASPTxSerActivate(SOC_MCASP_0_CTRL_REGS);
    
        /* make sure that the XDATA bit is cleared to zero */
        while(McASPTxStatusGet(SOC_MCASP_0_CTRL_REGS) & MCASP_TX_STAT_DATAREADY);
    
        /* Activate the state machines */
        McASPRxEnable(SOC_MCASP_0_CTRL_REGS);
        McASPTxEnable(SOC_MCASP_0_CTRL_REGS);
    }
    
    /*
    ** Activates the DMA transfer for a parameterset from the given buffer.
    */
    void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
                             unsigned short parId, unsigned short linkPar)
    {
        EDMA3CCPaRAMEntry paramSet;
    
        /* Copy the default paramset */
        memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2);
        
        /* Enable completion interrupt */
        paramSet.opt |= TX_DMA_INT_ENABLE;
        paramSet.srcAddr =  txBufPtr[txBuf];
        paramSet.linkAddr = linkPar * SIZE_PARAMSET;  
        paramSet.bCnt = numSamples;
    
        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet);
    }
    
    /*
    ** The main function. Application starts here.
    */
    int main(void)
    {
        unsigned short parToSend;
        unsigned short parToLink;
    
        /* Set up pin mux for I2C module 0 */
        I2CPinMuxSetup(0);
        McASPPinMuxSetup();
    
        /* Power up the McASP module */
        PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_MCASP0, PSC_POWERDOMAIN_ALWAYS_ON,
    		     PSC_MDCTL_NEXT_ENABLE);
    
        /* Power up EDMA3CC_0 and EDMA3TC_0 */
        PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON,
    		     PSC_MDCTL_NEXT_ENABLE);
        PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON,
    		     PSC_MDCTL_NEXT_ENABLE);
    
    #ifdef _TMS320C6X
        // Initialize the DSP interrupt controller
        IntDSPINTCInit();
    #else
        /* Initialize the ARM Interrupt Controller.*/
        IntAINTCInit();
    #endif
    
        /* Initialize the I2C 0 interface for the codec AIC31 */
        I2CCodecIfInit(SOC_I2C_0_REGS, INT_CHANNEL_I2C, I2C_SLAVE_CODEC_AIC31);
    
        EDMA3Init(SOC_EDMA30CC_0_REGS, 0);
        EDMA3IntSetup(); 
    
        McASPErrorIntSetup();
      
    #ifdef _TMS320C6X
        IntGlobalEnable();
    #else
        /* Enable the interrupts generation at global level */ 
        IntMasterIRQEnable();
        IntGlobalEnable();
        IntIRQEnable();
    #endif
    
        /*
        ** Request EDMA channels. Channel 0 is used for reception and
        ** Channel 1 is used for transmission
        */
        EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
                            EDMA3_CHA_MCASP0_TX, EDMA3_CHA_MCASP0_TX, 0);
        EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
                            EDMA3_CHA_MCASP0_RX, EDMA3_CHA_MCASP0_RX, 0);
    
        /* Initialize the DMA parameters */
        I2SDMAParamInit();
    
        /* Configure the Codec for I2S mode */
        AIC31I2SConfigure();
    
        /* Configure the McASP for I2S */
        McASPI2SConfigure();
      
        /* Activate the audio transmission and reception */ 
        I2SDataTxRxActivate();
       
        /*
        ** Looop forever. if a new buffer is received, the lastFullRxBuf will be 
        ** updated in the rx completion ISR. if it is not the lastSentTxBuf, 
        ** buffer is to be sent. This has to be mapped to proper paRAM set.
        */
        while(1)
        {
            if(lastFullRxBuf != lastSentTxBuf)
            {  
                /*
                ** Start the transmission from the link paramset. The param set 
                ** 1 will be linked to param set at PAR_TX_START. So do not 
                ** update paRAM set1.
                */ 
                parToSend =  PAR_TX_START + (parOffTxToSend % NUM_PAR);
                parOffTxToSend = (parOffTxToSend + 1) % NUM_PAR;
                parToLink  = PAR_TX_START + parOffTxToSend; 
     
                lastSentTxBuf = (lastSentTxBuf + 1) % NUM_BUF;
    
                /* Copy the buffer */
                memcpy((void *)txBufPtr[lastSentTxBuf],
                       (void *)rxBufPtr[lastFullRxBuf],
                       AUDIO_BUF_SIZE);
    
                /*
                ** Send the buffer by setting the DMA params accordingly.
                ** Here the buffer to send and number of samples are passed as
                ** parameters. This is important, if only transmit section 
                ** is to be used.
                */
                BufferTxDMAActivate(lastSentTxBuf, NUM_SAMPLES_PER_AUDIO_BUF,
                                    (unsigned short)parToSend,
                                    (unsigned short)parToLink);
            }
        }
    }  
    
    /*
    ** Activates the DMA transfer for a parameter set from the given buffer.
    */
    static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
                                    unsigned short parLink)
    {
        EDMA3CCPaRAMEntry paramSet;
    
        /* Copy the default paramset */
        memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2);
    
        /* Enable completion interrupt */
        paramSet.opt |= RX_DMA_INT_ENABLE;
        paramSet.destAddr =  rxBufPtr[rxBuf];
        paramSet.bCnt =  NUM_SAMPLES_PER_AUDIO_BUF;
        paramSet.linkAddr = parLink * SIZE_PARAMSET ;
    
        EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet);
    }
    
    /*
    ** This function will be called once receive DMA is completed
    */
    static void McASPRxDMAComplHandler(void)
    {
        unsigned short nxtParToUpdate;
    
        /*
        ** Update lastFullRxBuf to indicate a new buffer reception
        ** is completed.
        */
        lastFullRxBuf = (lastFullRxBuf + 1) % NUM_BUF;
        nxtParToUpdate =  PAR_RX_START + parOffRcvd;  
        parOffRcvd = (parOffRcvd + 1) % NUM_PAR;
     
        /*
        ** Update the DMA parameters for the received buffer to receive
        ** further data in proper buffer
        */
        BufferRxDMAActivate(nxtBufToRcv, nxtParToUpdate,
                            PAR_RX_START + parOffRcvd);
        
        /* update the next buffer to receive data */ 
        nxtBufToRcv = (nxtBufToRcv + 1) % NUM_BUF;
    }
    
    /*
    ** This function will be called once transmit DMA is completed
    */
    static void McASPTxDMAComplHandler(void)
    {
        ParamTxLoopJobSet((unsigned short)(PAR_TX_START + parOffSent));
    
        parOffSent = (parOffSent + 1) % NUM_PAR;
    }
    
    /*
    ** EDMA transfer completion ISR
    */
    static void EDMA3CCComplIsr(void) 
    { 
    #ifdef _TMS320C6X
    	IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
    #else
        IntSystemStatusClear(SYS_INT_CCINT0);
    #endif
    
        /* Check if receive DMA completed */
        if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_RX)) 
        { 
            /* Clear the interrupt status for the 0th channel */
            EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX); 
            McASPRxDMAComplHandler();
        }
        
        /* Check if transmit DMA completed */
        if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_TX)) 
        { 
            /* Clear the interrupt status for the first channel */
            EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX); 
            McASPTxDMAComplHandler();
        }
    }
    
    /*
    ** Error ISR for McASP
    */
    static void McASPErrorIsr(void)
    {
    #ifdef _TMS320C6X
    	IntEventClear(SYS_INT_MCASP0_INT);
    #else
        IntSystemStatusClear(SYS_INT_MCASPINT);
    #endif
    
        ; /* Perform any error handling here.*/
    }
    
    /***************************** End Of File ***********************************/
    

    Hope it helps!

    Thanks & regards,

    Sivaraj K

    ---------------------------------------------------------------------------------
    Please click the
    Verify Answer button on this post if it answers your question.
    ---------------------------------------------------------------------------------

  • Thank you for your information,

    I got your example code very well, but I cannot understand that code because that file has predefined constant and function.

    Could you send me other file (header,etc..) for me?  

    I would like to compile and run on my L138 borad, if it is possible, it would very helpful for me.

    Thanks in advance.

    Doug

  • Hi Dong,

    Thanks for your update.

    You shall install C6748 starter ware package and there, you have McASP examples included in the installation path as below: ( all files are included in the path)

    ~\Texas Instruments\pdk_C6748_2_0_0_0\C6748_StarterWare_1_20_03_03\examples\evmC6748\mcasp

    Thanks & regards,

    Sivaraj K

    ---------------------------------------------------------------------------------
    Please click the
    Verify Answer button on this post if it answers your question.
    ---------------------------------------------------------------------------------
  • Hi Shivraj K,


    We are using DM385 with IPNC RDK,

    As per description McAsp is capturing   audio in I2S format from Audio Chip on EVM.

    Now, In our custom board we need to capture Audio from MEMS INMP441  in I2S format.

    INMP441 chip doesn't require any type of configuration. It directly provides I2S output after getting clock from master.

    http://www.invensense.com/mems/microphone/inmp441.html

    Can  you please suggest us what changes need to do in kernel source ?


    Thanks in advance,

    Regards Kalpesh