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.

Changing the sampling rate.

Other Parts Discussed in Thread: OMAPL138, REG102, REG101, OMAP-L138

Urgent.

Dear friends,

I am presently  test running the McASP program of Starterware 1.x.x.3 on my OMAPL138 EVM. I need to change the sampling frequency to 8192 Hz from 8000Hz. 

Can I get Fs= 8192 Hz instead of 8000Hz using the formula given below

  fs = (PLL_IN * [pllJval.pllDval] * pllRval) /(2048 * pllPval).
 Where  PLL_IN = 24576 kHz ..

If possible, how to calculate the values of pllJval, pllDval, pllRval, pllPval to obtain 8192Hz.

Thanks in advance.

Regards,

Mahesh



  • Mahesh,

    Try this combination:

        unsigned char fs = 0x44u;
        unsigned char ref = 0x0Au;
        unsigned char pllPval = 4u;
        unsigned char pllRval = 1u;
        unsigned char pllJval = 8u;
        unsigned short pllDval = 1920u;

    Regards,

    Sujith.

  • Dear Sujit,

    Thanks for the fast response. Need some more help in this. There is no audio output this time with the above settings.

    //  file : mcaspPlayBk.c

    AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, (8192u));  // passing 8192 Hz as argument.

    // file : aic31.c

    void AIC31SampleRateConfig(unsigned int baseAddr, unsigned int mode,
                               unsigned int sampleRate)
    {
       /*    Original combination by Starterware
        *
         unsigned char fs;
        unsigned char ref = 0x0Au;
        unsigned char temp;
        unsigned char pllPval = 4u;
        unsigned char pllRval = 1u;
        unsigned char pllJval = 16u;
        unsigned short pllDval = 0u;
        */

        /* Modified lines for 8192 Hz  on 19 April*/



            //unsigned char fs = 0x44u;
            unsigned char fs;
            unsigned char ref = 0x0Au;
            unsigned char pllPval = 4u;
            unsigned char pllRval = 1u;
            unsigned char pllJval = 8u;
            unsigned short pllDval = 1920u;
            unsigned char temp;




        /* Select the configuration for the given sampling rate */
        switch(sampleRate)
        {
            case 8000:
                fs = 0xAAu;
            break;

            case 8192:   // lines added extra to get 8192 Hz sampling frequency
                fs = 0x44u;
                break;
            case 11025:
                fs = 0x66u;
                ref = 0x8Au;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 16000:
                fs = 0x44u;
            break;

            case 22050:
                fs = 0x22u;
                ref = 0x8Au;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 24000:
                fs = 0x22u;
            break;
        
            case 32000:
                fs = 0x11u;
            break;

            case 44100:
                ref = 0x8Au;
                fs = 0x00u;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 48000:
                fs = 0x00u;
            break;

            case 96000:
                ref = 0x6Au;
                fs = 0x00u;
            break;

            default:
                fs = 0x00u;
            break;
        }
        
        temp = (mode & fs);
       
        /* Set the sample Rate */
        CodecRegWrite(baseAddr, AIC31_P0_REG2, temp);
     
        CodecRegWrite(baseAddr, AIC31_P0_REG3, 0x80 | pllPval);

        /* use PLL_CLK_IN as MCLK */
        CodecRegWrite(baseAddr, AIC31_P0_REG102, 0x08);

        /* Use PLL DIV OUT as codec CLK IN */
        CodecRegBitClr(baseAddr, AIC31_P0_REG101, 0x01);

        /* Select GPIO to output the divided PLL IN */
        CodecRegWrite(baseAddr, AIC31_P0_REG98, 0x20);

        temp = (pllJval << 2);
        CodecRegWrite(baseAddr, AIC31_P0_REG4, temp);

        /* Configure the PLL divide registers */
        CodecRegWrite(baseAddr, AIC31_P0_REG5, (pllDval >> 6) & 0xFF);
        CodecRegWrite(baseAddr, AIC31_P0_REG6, (pllDval & 0x3F) << 2);

        temp = pllRval;
        CodecRegWrite(baseAddr, AIC31_P0_REG11, temp);

        /* Enable the codec to be master for fs and bclk */
        CodecRegWrite(baseAddr, AIC31_P0_REG8, 0xD0);

        CodecRegWrite(baseAddr, AIC31_P0_REG7, ref);
    }

    There is no audio audio output at all.  Could you pls find where exactly I am making mistake guide me to correct them.

    regards,

    Mahesh

  • Hi Mahesh,

    When I refered to AIC31 data sheet, I could find fsref which can be selected as 48000 or 44100 (register 7). And these values can be divided by some values described for register 2. But 8192 seems cannot be achieved exactly as per the doc.

    Anyway, could you please try the below combination so that we can achieve a frequency closer to 8192 and then we may tune the J/D values to make it proper ? You can probe the clock line and see what frequency it comes exactly.

            unsigned char fs = 0x99u;         //  44100/5.5
            unsigned char ref = 0x8Au;
            unsigned char pllPval = 4u;
            unsigned char pllRval = 1u;
            unsigned char pllJval = 8u;
            unsigned short pllDval = 1920u;

    Regards,

    sujith.

  • Dear Sujitji,

    I tried some other few things and got it working for 8192Hz.

    //file: mcaspPlayBk.c

    #define SAMPLING_RATE                         (48000u)
    #define MODIFIED_SAMPLING_RATE                (8192u)

       AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, MODIFIED_SAMPLING_RATE);

    // file :aic31.c

    void AIC31SampleRateConfig(unsigned int baseAddr, unsigned int mode,
                               unsigned int sampleRate)
    {
        unsigned char fs;
        unsigned char ref = 0x0Au;
        unsigned char temp;
        unsigned char pllPval = 4u;
        unsigned char pllRval = 1u;
        unsigned char pllJval = 16u;
        unsigned short pllDval = 0u;


        /* Select the configuration for the given sampling rate */
        switch(sampleRate)
        {
            case 8000:
                fs = 0xAAu;
            break;

            case 8192 :
                fs = 0x44u;
                pllJval = 8u;
                pllDval = 1920u;
                break;

            case 11025:
                fs = 0x66u;
                ref = 0x8Au;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 16000:
                fs = 0x44u;
            break;

            case 22050:
                fs = 0x22u;
                ref = 0x8Au;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 24000:
                fs = 0x22u;
            break;
        
            case 32000:
                fs = 0x11u;
            break;

            case 44100:
                ref = 0x8Au;
                fs = 0x00u;
                pllJval = 14u;
                pllDval = 7000u;
            break;

            case 48000:
                fs = 0x00u;
            break;

            case 96000:
                ref = 0x6Au;
                fs = 0x00u;
            break;

            default:
                fs = 0x00u;
            break;
        }
        
        temp = (mode & fs);
       
        /* Set the sample Rate */
        CodecRegWrite(baseAddr, AIC31_P0_REG2, temp);
     
        CodecRegWrite(baseAddr, AIC31_P0_REG3, 0x80 | pllPval);

        /* use PLL_CLK_IN as MCLK */
        CodecRegWrite(baseAddr, AIC31_P0_REG102, 0x08);

        /* Use PLL DIV OUT as codec CLK IN */
        CodecRegBitClr(baseAddr, AIC31_P0_REG101, 0x01);

        /* Select GPIO to output the divided PLL IN */
        CodecRegWrite(baseAddr, AIC31_P0_REG98, 0x20);

        temp = (pllJval << 2);
        CodecRegWrite(baseAddr, AIC31_P0_REG4, temp);

        /* Configure the PLL divide registers */
        CodecRegWrite(baseAddr, AIC31_P0_REG5, (pllDval >> 6) & 0xFF);
        CodecRegWrite(baseAddr, AIC31_P0_REG6, (pllDval & 0x3F) << 2);

        temp = pllRval;
        CodecRegWrite(baseAddr, AIC31_P0_REG11, temp);

        /* Enable the codec to be master for fs and bclk */
        CodecRegWrite(baseAddr, AIC31_P0_REG8, 0xD0);

        CodecRegWrite(baseAddr, AIC31_P0_REG7, ref);
    }

    Few more questions at last.

    1. Can't I use a variable unsigned integer instead of #define macro to change sampling frequency? I need this because the sampling frequency will be coming as result of some data processing algorithm.

    2.  After getting the sound for  8192Hz, how to verify that it is correctly set to 8192Hz or the nearest possible value.? Is there any chance to see on oscilloscope?

    3.  Could you please give me exact steps in calculating ref,pllPval, pllRval,pllJval,pllDval  value for desired sampling rate?

    Regards,

    Mahesh

  • Hi Mahesh,

    1. Can't I use a variable unsigned integer instead of #define macro to change sampling frequency? I need this because the sampling frequency will be coming as result of some data processing algorithm.

      >>>> Yes you can. Only that, you need to know which all values will come, to put a case in the switch. Otherwise, J, D, P, R values have to be calculated dynamically (hmm.. might be difficult).

    2.  After getting the sound for  8192Hz, how to verify that it is correctly set to 8192Hz or the nearest possible value.? Is there any chance to see on oscilloscope?

    >>>>> Yes. The output of the codec fs line can be probed.

    3.  Could you please give me exact steps in calculating ref,pllPval, pllRval,pllJval,pllDval  value for desired sampling rate?

    >>>>>The calculation is according to the equation given. Say, PLL_IN is 12000, and the output you need is 48000,

               you have to tune the values pllPval, pllRval,pllJval,pllDval. May be you can fix P and R values, then find J.D to get the desired output.

    Regards,

    Sujith

  • Dear Sujit,

    The aic31 doc give formula for Fsref and the starterware program gives formula for Fs.

    aic31.doc:

    When the PLL is enabled,
    FSref = (PLLCLK_IN × K × R) / (2048 × P), where
    P = 1, 2, 3,…, 8
    R = 1, 2, …, 16
    K = J.D
    J = 1, 2, 3, …, 63
    D = 0000, 0001, 0002, 0003, …, 9998, 9999
    PLLCLK_IN can be MCLK or BCLK, selected by register 102, bits D5-D4

    aic31.c:

      fs = (PLL_IN * [pllJval.pllDval] * pllRval) /(2048 * pllPval).

     Where  PLL_IN = 24576 kHz

    I use the later one , with

    PLL_IN=24576000; R=1, P=4.

    I get K=[J.D]=2.7306.

    I am confused a little bit, could pls tell me the significance of setting values for fs and ref in the aic31.c file and relate them to doc.

    regards,

    Mahesh

  • Dear Sujit,

    Sorry, I do not find any pin with name Fs to observe the sampling frequency but there are some ones with names: MCLK, BCLK, WCLK. Which is to be observed?

    Regards,

    Mahesh

  • Hi Mahesh, 

    You can observe WCLK. I hope that is word clock. Anyway, observe BCLK too. 

    Regards,

    Sujith

  • Dear Sujit,

    Today it is not possible to observe the signal since the probes are here right now. Mean while could you please help in interpreting the     fs = 0x44u; and ref = 0x0Au; in aic31.c . (0x44u = 16*4+4=68, 0x0a=10).

    Regards,

    Mahesh

  • Dear Sujit,

    I  have a related question. After changing the sampling rate I wanted to see the samples on the Graphs (amplitude vs. sample number, and amplitude vs seconds/microseconds). This may give an idea of sampling frequency.

    The following code in the original program copies received buffers in to transmit buffers.


                /* Copy the buffer */

               memcpy( (void *)txBufPtr[lastSentTxBuf],   (void *)rxBufPtr[lastFullRxBuf],  AUDIO_BUF_SIZE);

    But I want to access the audio data available in rxBufPtr[NUM_BUF] on sample-by-sample basis, from all the received buffers, convert each sample to preferably float/double, copy each float/double sample into  an array using for loop. When I get data for 0.25 seconds, I process them to find Ts and display waveform on the time and frequency graphs.

    // my declerations

    float iSample;

    float *psample;

    unsigned char pbyte[2];

    float arrSample[NUM_SAMPLES_PER_AUDIO_BUF];

    //The following code seems not working

                 for (j=0;  j < AUDIO_BUF_SIZE/2; j++){


                   pbyte[0]= rxBuf0[2*j];

                   pbyte[1]= rxBuf0[2*j+1];

                   psample = (float *) pbyte;  // convert pointer to  unsigned char array (two byte wide) to pointer to float

                   iSample = *psample; // get float value

                   printf("%f",iSample);

    // todo:  store these iSample values in arrSample;

                    }

    In the above code, I assumed that Starterware is taking 16-bit word length.

    I get only 0.000 in the iSample when printed onto the console using printf("%f") or printf("%g");

    How to get individual samples in to iSample?

    Regards,

    Mahesh

  • Can any body please respond to the above please.

  • Hi Mahesh, 

    There is no option for probing ?

    Anyway, it is possible to read the stored values from the buffer (I couldnt understand the piece of code :(), but how are you going to calculate the sampling frequency from the stored samples ?

    Regards

    Sujith

  • Dear Sujit,

    I defer the probe option until I get proper probes back from other lab. This is week end here. Please have re-look at the code. I am not sure this is correct way.

    Mean while , I try with code. My idea is to generate a single frequency sine wave in MATLAB and play it with desired sampling frequency using wavplay() function. Connect the Line-out port of my host PC to line-in port of OMAP-L138 evm kit. Acquire the audio using McASP.c project of StarterWare. I know how many samples are going to be there in a single cycle. For this I need to read the stored samples in float/double type array and plot. Optionally, find FFT and  store the FFT amplitude and frequency indexes into harddisk using fprintf() for further plotting in MATLAB to verify the spectrum.

    I have already written FFT  program to do the optioanl part in off-lie using some DSPLIB functions. What I need is to read the audio values stored in rxBuf0, rxBuf1, and rxBuf2.

    Please reply soon,.

    Regards,

    Mahesh

  • Is there anybody attending this forum today. Could you please suggest me how to get audio samples into my own float array for manipulation or display.

    Regards,

    Mahesh

  • Dear Sujit,

    Are you there . I am still looking for the solution.

    Regards,

    Mahesh

  • Hi Mahesh,

    I was busy with some issues, so couldnt respond to this. 

    I suggest to configure McASP only for Receive, may be only receive EDMA paRAM set you configure, then capture the sine wave in the three RX buffers. 

    You can define three paramsets and statically link them. 

    configuration for rxBuf0:

    static struct EDMA3CCPaRAMEntry const rx0Par =
    {
    (unsigned int)(OPT_FIFO_WIDTH), /* Opt field */
    (unsigned int)SOC_MCASP_1_DATA_REGS, /* source address */
    (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
    (unsigned short)(1), /* bCnt */
    (unsigned int)rxBuf0, /* dest address */    ----> for the next paramset (rx1Par), give rxBuf1, and for rx2Par, give rxBuf2.
    (short) (0), /* source bIdx */
    (short)(BYTES_PER_SAMPLE), /* dest bIdx */
    (unsigned short)(***), /* link address */ ----> here give link to the paramset of rxBuf1. for rx1Par, give link to the paramset of rx2Par. For rx2Par, give 0xFFFF;
    (unsigned short)(0), /* bCnt reload value */
    (short)(0), /* source cIdx */
    (short)(0), /* dest cIdx */
    (unsigned short)1 /* cCnt */
    };

    If you configure properly, the sine wave will be captured in the three buffers.

    BTW, if you already know the sine wave frequency, I hope you can calculate how many samples are there in the sine wave directly from the sample values.

    regards

    sujith.

  • Dear Sujit,

    I have incorporated the changes that you suggested.

    Also I add one extra line here in soc_omapl138.h

    #define SOC_MCASP_0_DATA_REGS               (0x01D02000)
    #define SOC_MCASP_1_DATA_REGS               (0x46400000) // extra line

    But I get error in the following regarding link aadress.

    //    configuration for rxBuf0

    static struct EDMA3CCPaRAMEntry const rx0Par =
        {
                (unsigned int)(OPT_FIFO_WIDTH), /* Opt field */
                (unsigned int)SOC_MCASP_1_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)(rx1Par), /* link address */ // mere use of rx1Par gives error: expression must have arithmetic type
                (unsigned short)(0), /* bCnt reload value */
                        (short)(0), /* source cIdx */
                        (short)(0), /* dest cIdx */
                        (unsigned short)1 /* cCnt */
        };


    Can you tell me why such errors are coming and what to pass as link address.

    Regards,

    Mahesh

  • Hi Mahesh,

    The link address is NOT the address of the structure. It is the address of the param set to which the current paramset has to be linked to. Kindly refer to the function BufferRxDMAActivate() function in the McASP example application, to see how we can give link address. Here it is done run-time. But in your case, you can statically give as I had explained.

    Cheers,

    Sujith.

  • Dear Sujit,

    I have been trying to capture the samples as per your suggestions.

    1.  I am  resetting the transmitter ,disabling all the transmit interrupts , and enabling the interrupts as follows,

         McASPTxIntDisable(SOC_MCASP_0_CTRL_REGS, MCASP_TX_DMAERROR
                                                    | MCASP_TX_CLKFAIL
                                                    | MCASP_TX_SYNCERROR
                                                    | MCASP_TX_UNDERRUN);
        /* Enable error interrupts for McASP - Receive */
        McASPRxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_RX_DMAERROR
                                                | MCASP_RX_CLKFAIL
                                                | MCASP_RX_SYNCERROR
                                                | MCASP_RX_OVERRUN);

       /* Reset Transmit section */
        McASPTxReset(SOC_MCASP_0_CTRL_REGS);

    2.  I am declaring my own array of pointers to copy from rxBufPtr

    static unsigned int const ch0BufPtr[NUM_BUF] =
           {
               (unsigned int) ch0Buf0,
               (unsigned int) ch0Buf1,
               (unsigned int) ch0Buf2
           };

    static unsigned char ch0Buf0[AUDIO_BUF_SIZE];
    static unsigned char ch0Buf1[AUDIO_BUF_SIZE];
    static unsigned char ch0Buf2[AUDIO_BUF_SIZE];

    3. I declare the paRAM set as below

    /* The paRAM for rxBuf0 of Receive section. */
    static struct EDMA3CCPaRAMEntry const rx0Par =
           {
               (unsigned int)(OPT_FIFO_WIDTH), /* Opt field */
               (unsigned int)SOC_MCASP_1_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)(40* SIZE_PARAMSET), /* link address */
               (unsigned short)(0), /* bCnt reload value */
               (short)(0), /* source cIdx */
               (short)(0), /* dest cIdx */
               (unsigned short)1 /* cCnt */
           };

    /* The paRAM for rxBuf1 of Receive section. */
    static struct EDMA3CCPaRAMEntry const rx1Par =
           {
               (unsigned int)(OPT_FIFO_WIDTH), /* Opt field */
               (unsigned int)SOC_MCASP_1_DATA_REGS, /* source address */
               (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
               (unsigned short)(1), /* bCnt */
               (unsigned int)rxBuf1, /* dest address */
               (short) (0), /* source bIdx */
               (short)(BYTES_PER_SAMPLE), /* dest bIdx */
               (unsigned short)(41* SIZE_PARAMSET), /* link address */
               (unsigned short)(0), /* bCnt reload value */
               (short)(0), /* source cIdx */
               (short)(0), /* dest cIdx */
               (unsigned short)1 /* cCnt */
           };

    /* The paRAM for rxBuf2 of Receive section. */
    static struct EDMA3CCPaRAMEntry const rx2Par =
           {
               (unsigned int)(OPT_FIFO_WIDTH), /* Opt field */
               (unsigned int)SOC_MCASP_1_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)(0xFFFF), /* link address */
               (unsigned short)(0), /* bCnt reload value */
               (short)(0), /* source cIdx */
               (short)(0), /* dest cIdx */
               (unsigned short)1 /* cCnt */
           };


    I can see that audio transmission is off. I want to see that audio samples recieved in rxBuf0, rxBuf1, and rxBuf2 are displayed in graph. The single time Graph reports an error that it cannot compute the starting address of rxBuf0. The capture size and display sizes are 8000 samples, with 32-bit integer data type.

    The graph is empty always. The Expressions window in the Debug perspective shows- initially when program is loaded- correct size of the rxBuf0 but when the program is running, it shows Type: unknown and Error: Unknown identifier rxBuf0.

    Please see the file modified . I am waiting for your suggestions.

    0118.modified_asp.c

    Regards,

    Mahesh



  • Dear Sujit,

    Are you there?

    Regards,

    Mahesh

  • Hi Mahesh,

    I think you are facing problem because aCnt, bCnt are not properly programmed. The way you are linking seems to be proper. Please refer to EDMA of TRM for details on how EDMA transfers will happen.

    Regards,

    Sujith.

  • Dear Sujit,

    I incorporated the changes for aCnt, bCnt as per TRM but still the problem persists.

    1145.modified_mcasp.c

    Regards,

    Mahesh

  • Hi Mahesh,

                   Since this need more closer look at the code. I suggest you to contact your local FAE.

    Regards

    Baskaran