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 configuration

Hi,

I just started working with the C6748 processor and I encounter problems in what should be simple tryouts.

I want to implement a filter for both left and right channel of the stereo input.

For this purpuse I configured the McAsp for burst mode, 32 bit frame- one slot. My purpose is to receive the right channel on the first 16 bits and the left channel on the last 16 bits.

I am working with HWI, I configured the interrupts for input/output and enabled only "receive" interrupts.

My code is very simple at the moment- only seperates the right and left channel, seperate them and saves them to two buffers.

I think the interrupts are not synconized properly with the actions of the A/D, because the buffers are full of junk... (my input is a sine wave)

Here are my configurations for the McASP- I hope it helps.. Thanks in advance!

Ariel

MCASP->RMASK = 0xFFFFFFFF; // all 32-bits NOT masked

MCASP->RFMT = 0x000080F8; // Read form periphereal configuration port (not DMA) MSB first, slot=32bits,

MCASP->AFSRCTL = 0x00000012; // int'l gen'd, FS/word, Burst Mode

MCASP->ACLKRCTL = 0x000000AF; // rising edge, clkrm internal, /16 CLKRDIV

MCASP->AHCLKRCTL = 0x00000000; // HCLKRDIV = 1

MCASP->RTDM = 0x00000001; // SLOT 0 active

MCASP->RINTCTL = 0x00000020; // interrupt enables

MCASP->RCLKCHK = 0x00FF0008; // RMAX = FF, RPS = /256

The configurations for the transmit register are parralel (excpet for the interrupt)

 

 

 

 

 

 

 

  • Ariel,

     

    Using the McASP can be a bit tricky. If you're used to a McBSP, getting to know the McASP takes a bit of time and trial/error - mostly error at the beginning. ;-)

    If you think in terms of 32-bits ALWAYS, that will help. If you have a 16-bit slot size, msb first, then a 16-bit short coming from the AIC lands in the upper half of the XBUF register (MS-uh-short!). When you read the XBUF register, your "data" will be in the upper 16 bits. You can also turn on ROR to automatically rotate right those upper 16 bits to the lower half (makes your C code easier to read, but requires a comment - or stick with the job security that only YOU know ROR is turned on. ;-) ).

    Oh - did you actually ENABLE the interrupt in the HWI Manager in the config tool? To get ints to work, you must enable them in the McASP routine (as you did - 0x20) AND have interrupt 5 (in this case HWI_INT5) enabled in the bios configuration. You can see both shown in my init routine below (done during _Start) and in main(). However, I think the burst mode (non-I2S mode) is what is causing your problem.

    Anyway, here is a dump of my McASP init code from the BIOS workshop, main, and the isr code that works well. You can also download ALL of these files from the BIOS workshop wiki (download the sols.zip file and look at lab4 - just an HWI reading/writing from the McASP - audio pass through).

     

    BIOS Workshop wiki site:

    http://processors.wiki.ti.com/index.php/TMS320C64x%2B_DSP_System_Integration_Workshop_using_DSP/BIOS

     

    I opted to turn on interrupts in the _Start routine vs. the initial configuration. Also, the I2S configuration works when NOT using the DMA. It requires a 1-bit delay as shown in the code below. Burst mode might be what is causing your problem - use I2S instead. Let me know if this helps...

     

    Here is my McASP_Init code:

    **************************************************************************************************************************************

    //-----------------------------------------------------------------------------

    // Title:   Technical Training Organization (TTO) BIOS Workshop 5.50

    // File: mcasp_TTO.c 

    // Rev: 1.0

    // Date: 08-31-2010

    // Author: Eric Wilbur (ericw@ti.com)

    // Ref: C6748 BSL, Experimenter Test Example (audio, mcasp)

    //

    // Brief: Init McASP clocks/control & interrupts, dummy writes to XDATA

    //

    // Notes: 1. Refer to main.h for key definitions

    // 2. Underrun is a SERIOUS condition on the McASP. Notice that

    //             dummy writes occur at selected points to keep XDATA filled

    // 3. For symbol definitions, refer to evmc6748_mcasp.h

    //

    //-----------------------------------------------------------------------------

     

    //-----------------------------------------------------------------------------

    // Includes

    //-----------------------------------------------------------------------------

    #include "main.h"

     

    //-----------------------------------------------------------------------------

    // DEFINES (enable XDATA/RDATA interrupts in McASP)

    //-----------------------------------------------------------------------------

    #define RDATA 0x20 // R/XDATA interrupt mask

    #define XDATA 0x20

     

    //-----------------------------------------------------------------------------

    // Private Defines and Macros

    //-----------------------------------------------------------------------------

    // pinmux defines.

    #define PINMUX_MCASP_REG_0       (0)

    #define PINMUX_MCASP_MASK_0      (0x00FFFFFF)

    #define PINMUX_MCASP_VAL_0       (0x00111111)

    #define PINMUX_MCASP_REG_1       (1)

    #define PINMUX_MCASP_MASK_1      (0x000FF000)

    #define PINMUX_MCASP_VAL_1       (0x00011000)

     

     

    //-----------------------------------------------------------------------------

    // McASP_Init_TTO()

    //-----------------------------------------------------------------------------

     

    void McASP_Init_TTO(void)

    {

       // enable the psc and config pinmux for mcasp.

       EVMC6748_lpscTransition(PSC1, DOMAIN0, LPSC_MCASP0, PSC_ENABLE);

       EVMC6748_pinmuxConfig(PINMUX_MCASP_REG_0, PINMUX_MCASP_MASK_0, PINMUX_MCASP_VAL_0);

       EVMC6748_pinmuxConfig(PINMUX_MCASP_REG_1, PINMUX_MCASP_MASK_1, PINMUX_MCASP_VAL_1);

     

       // reset mcasp.

       MCASP->GBLCTL  = 0;

     

       // NOTE: ROR 16-bits enabled for both XMT/RCV. SLOT SIZE = 16 bits, 1-bit delay

       //       MCLK = 2.456MHz, CLKRDIV = 16, SO, bitclk = MCLK/CLKRDIV = 1.536MHz

       //       SAMPLE RATE = 1.536MHz/32bits = 48KHz

     

       // configure receive registers for I2S

       MCASP->RMASK      = 0xFFFFFFFF; // all 32-bits NOT masked

       MCASP->RFMT       = 0x0001807C; // MSB first, align left, slot=16bits, 1-bit delay, ROR 16-bits

       MCASP->AFSRCTL    = 0x00000112; // int'l gen'd, FS/word, 2 SLOT TDM = I2S

       MCASP->ACLKRCTL   = 0x000000AF; // rising edge, clkrm internal, /16 CLKRDIV

       MCASP->AHCLKRCTL  = 0x00000000; // HCLKRDIV = 1

       MCASP->RTDM       = 0x00000003; // SLOT 0 & 1 active I2S

       MCASP->RINTCTL    = 0x00000000; // ints disabled (enabled later though)

       MCASP->RCLKCHK    = 0x00FF0008; // RMAX = FF, RPS = /256

     

       // configure transmit registers for I2S - all same as above

       MCASP->XMASK      = 0xFFFFFFFF;

       MCASP->XFMT       = 0x0001807C;  

       MCASP->AFSXCTL    = 0x00000112;

       MCASP->ACLKXCTL   = 0x000000AF;

       MCASP->AHCLKXCTL  = 0x00000000;

       MCASP->XTDM       = 0x00000003;

       MCASP->XINTCTL    = 0x00000000;

       MCASP->XCLKCHK    = 0x00FF0008;

     

       // config serializers (11 = xmit, 12 = rcv)

       MCASP->SRCTL11    = 0x000D; // XMT

       MCASP->SRCTL12    = 0x000E; // RCV

     

       // config pin function and direction.

       MCASP->PFUNC      = 0;

       MCASP->PDIR       = 0x14000800;

     

       MCASP->DITCTL     = 0x00000000;

       MCASP->DLBCTL     = 0x00000000;

       MCASP->AMUTE      = 0x00000000;

     

    }

     

    //-----------------------------------------------------------------------------

    // McASP_Start_TTO()

    //-----------------------------------------------------------------------------

     

    void McASP_Start_TTO(void)

    {

     

       // enable the audio clocks, verifying each bit is properly set.

    SETBIT(MCASP->XGBLCTL, XHCLKRST);

        while (!CHKBIT(MCASP->XGBLCTL, XHCLKRST)) {}

        SETBIT(MCASP->RGBLCTL, RHCLKRST);

        while (!CHKBIT(MCASP->RGBLCTL, RHCLKRST)) {}

     

        SETBIT(MCASP->XGBLCTL, XCLKRST);

        while (!CHKBIT(MCASP->XGBLCTL, XCLKRST)) {}

        SETBIT(MCASP->RGBLCTL, RCLKRST);

        while (!CHKBIT(MCASP->RGBLCTL, RCLKRST)) {}

     

       SETBIT(MCASP->RINTCTL, RDATA); // enable McASP XMT/RCV interrupts

       while (!CHKBIT(MCASP->RINTCTL, RDATA)) {} // see #defines at top of file

       SETBIT(MCASP->XINTCTL, XDATA);

       while (!CHKBIT(MCASP->XINTCTL, XDATA)) {}

     

        MCASP->XSTAT = 0x0000FFFF;        // Clear all (see procedure in UG)

        MCASP->RSTAT = 0x0000FFFF;        // Clear all

     

     

       SETBIT(MCASP->XGBLCTL, XSRCLR);

       while (!CHKBIT(MCASP->XGBLCTL, XSRCLR)) {}

       SETBIT(MCASP->RGBLCTL, RSRCLR);

       while (!CHKBIT(MCASP->RGBLCTL, RSRCLR)) {}

     

       /* Write a 0, so that no underrun occurs after releasing the state machine */

       MCASP->XBUF11 = 0;

     

       SETBIT(MCASP->XGBLCTL, XSMRST);

       while (!CHKBIT(MCASP->XGBLCTL, XSMRST)) {}

       SETBIT(MCASP->RGBLCTL, RSMRST);

       while (!CHKBIT(MCASP->RGBLCTL, RSMRST)) {}

     

       SETBIT(MCASP->XGBLCTL, XFRST);

       while (!CHKBIT(MCASP->XGBLCTL, XFRST)) {}

       SETBIT(MCASP->RGBLCTL, RFRST);

       while (!CHKBIT(MCASP->RGBLCTL, RFRST)) {}

     

       // wait for transmit ready and send a dummy byte.

       //while(!CHKBIT(MCASP->SRCTL11, XRDY)) {}

       //MCASP->XBUF11 = 0;

     

    }

     

     

    Here is my main code calling the McASP Init routines:

    **************************************************************************************************************************************

    void main(void)

    {

     

    #if NO_GEL // if NO GEL file, init board/RAM

       EVMC6748_init();

       EVMC6748_initRAM();

    #endif

     

     

        init_buffers(); // zero buffers

     

       I2C_init(I2C0, I2C_CLK_400K); // init I2C channel

     

    LED_init(); // init LED and DIP BSL

    DIP_init();

     

       McASP_Init_TTO(); // init McASP (modified from original BSL)

       AIC3106_Init_TTO(); // init AIC3106 (modified from original BSL)

     

       ICR  = (1 << 5); // clear INT5 (precaution)

    IER |= (1 << 5); // enable INT5 as CPU interrupt 

     

    McASP_Start_TTO(); // start McASP clocks

     

    return;   // return to BIOS scheduler

    }  

     

    Here is my ISR.c code that reads/writes in/out data from/to the McASP/buffers.

    **************************************************************************************************************************************

    //-----------------------------------------------------------------------------

    // isrAudio()

    //-----------------------------------------------------------------------------

    void isrAudio(void)

    {

       static int32_t dataIn32, dataOut32; //store McASP audio data

    static int16_t blkCnt = 0; //blk counter

    static int16_t *pInBuf_local, *pOutBuf_local; //local pointers to global buffers

     

     

    //Init local pointers for ping/pong buffering

     

    if (blkCnt == 0){ //If new buffer, swap ping/pong

       if (pingPong == PING){ //PING Buffers

    pInBuf_local = rcvPing;  

    pOutBuf_local  = xmtPing;

       }

    else { //PONG Buffers

    pInBuf_local = rcvPong;  

    pOutBuf_local  = xmtPong;

    }

    }

     

    // McASP set to 16-bit slot size - always read 32, data in upper half, ROR 16-bit ENABLED

    // ROR 16 shifts the upper half to the lower half of dataIn32

     

    //read 32 bits from McASP (ROR 16, so lower 16 bits valid) and store in InBuf

    dataIn32 = MCASP->XBUF12;

    pInBuf_local[blkCnt] = (int16_t)(dataIn32);

     

    //read 16 bits from XMT buffer and send to McASP XMT 

    dataOut32 = pOutBuf_local[blkCnt];

    MCASP->XBUF11 = dataOut32;

     

       blkCnt += 1;

     

    //IF end of buffer, copy rcv-to-xmt, zero blkCnt, swap PING-PONG boolean

    if (blkCnt >= BUFFSIZE){

    SWI_post(&SWI_firProcess);

    // FIR_process(pInBuf_local, pOutBuf_local, BUFFSIZE);

    blkCnt = 0;

    pingPong ^=1;

    }

    }

    Again, the best way to copy all this code is to simply download the "solution" files for the BIOS workshop and look at lab4 - HWI.

     

    Let me know if this helps...

     

    Cheers,

    Eric

  • One other thing - make sure you have IER (bit 5) enabled in main (as I show above). For interrupts to work, you need the flag bit set (IFR, bit 5 for HWI_INT5), IER (bit 5) enabled, GIE/NMIE set/enabled (in the CSR register) - this is done automatically in BIOS - but in non-BIOS apps, you have to turn on GIE/NMIE manually or NO interrupts occur - EVER. And then, in the config of HWI_INTx, you must have the EVT# for the McASP interrupt defined in the GUI, your ISR routine and the HWI Dispatcher turned on. That's kind of the interrupt story in a nutshell. 

    Looking at chapter 4 (interrupts) and lab4 will also help.

    Cheers,

    Eric

  • Hi Eric,

    Thank you so much for your help!

    However, my problems are not over yet,

    It seems to me that with your configuration, the ISR runs seperately for the left and right channels.

    I also chacked the sampling frequncy with a scope. the output is 96Khz, which is twice the stated frequency, which leads me to the (wrong??) assumption

    that the ISR 'toggles' between the left and right channel. I aslo ran the 6th TI example which seperates the left and right channels to two different buffers.

    However, when I try to manipulate one of the channles (even the most simple action as masking one of the channel outputs with  0x0) it does not work.

    It seems that either both of the outputs are masked, and no signal is coming out, or none are masked.

    How can I make sure that I process the right input? Is there a way to differ between the channels?

    Thanks again,

    Ariel 

  • URIKA!!

    It is possible to check the RSLOT register- this way you know which channel is now sampled, and can transffer it

    to the right buffer.

    So everything is good at the moment, I might need some help in the future though,

    Bye

    Ariel

  • That's a good catch. And, as you can see, you've taught ME something (not difficult to do and MUCH appreciated). I had not thought of using RSLOT to differentiate right from left in code. I made the assumption in the code that the first sample was L, then R. Your idea is WAY better. I'll have to update my own code to reflect that. Anyway, I'm glad I could help get you over a hurdle and, in the process, I too learned something. Thanks for writing back and sharing. Others on the forums, some day, will appreciate this dialogue.

    Cheers,

    Eric

  • I noticed that when you write e.g. reset signals, you are reading back XGBLCTL or RGBLCTL...

    but the user's guide (spruh77a) explicitly says in section  25.2.4.1.4  that:

    "Finally, please note that while RGBLCTL and XGBLCTL allow separate changing of the receive and transmit halves of GBLCTL, they also immediately reflect the updated value (useful for debug purposes). Only GBLCTL can be used for the read back step. "

    so I'm confused.....

  • Hi, I have one question: I have downloaded the lab4 - HWI example and started to work with that. I separated the left and right channel as I need (by the way, it seems that the board swap them, but anyway...). Now I have to do some computation on the received frame to transmit back an elaborated buffer, but I can't figure out how I can do that. I already tried to put the elaboration in the FIR_process() function but it doesn't work. The system can't receive and transmit any longer in this way (out of sync?). So i thought to use a flag that notify when receive buffers are full, check it in an infinity loop in the main and elaborate the buffers in the main itself. This doesn't work too, because interrupts are not taken into account in the infinite loop in the main (of course I inserted the loop just before the "return", so after interrupt enable). Can someone tell me how and where the computation should be done? Thank you.

     

    Cheers,

    Francesco