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.

IQ math problem

Other Parts Discussed in Thread: TMS320F2812, CONTROLSUITE

Hi

I am using a fixed point DSP (TMS320F2812) for my application. I am using a sine look-up table and so I have to use IQ math. I am using the following equations.

s1 = _IQ30mpy(m4,_IQ30(0.8));

EvaRegs.CMPR1 = T1-_IQsat(_IQ30mpy(_IQ30mpy(sine_table[i],s1),T1/2),T1,0);

m4 is also in IQ30 format and T1 is my period register value.

I am getting s1 in 32 bit format but registers are 16 bit only. 

How can I make IQ30 in int format instead of long int?

  • Murali,

    The _IQtoQN() function in the IQ math library will help you.  In your case, I think _IQtoQ15 will yield a 16-bit number in the right format.  You may have to convert into global IQ format first if GLOBAL_Q is not set to 30 in your project.

    Regards,

    Richard

  • Hi Richard
    Thanks for your reply. I still can't get it to work. My GLOBAL_Q is 24 and I'm using the equation s1 = _IQmpy(m4,_IQ(0.8));. But it doesn't give me any output. But when I'm using s1 = _IQ(m4*_IQ(0.8)); I get a better result. But what I understand from the literature is that according to IQ math in C I can't use this second equation. Am I wrong? My other doubt is if I use IQ15 as my GLOBAL_Q ,cause I don't need very high resolution, can I reduce data loss on truncation when I convert it to Q format?
    Regards,
    Murali
  • Murali,

    The following is working for me:

    _iq s1;
    _iq s2;
    _iq m4 = _IQ(0.2);

    main()
    {
    s1 = _IQ(m4*_IQ(0.8));
    s2 = _IQmpy(m4, _IQ(0.8));

    I get s2 as 0.16 in IQ24 format, as expected.  s1 is something meaningless (-128) because we are doing an integer multiplication without taking account of numeric format.

    When you say it "doesn't give any output", what is the value of s1 in your code after the instruction completes?

    Regards,

    Richard

  • Hi Richard,
    Thanks for your reply.My sine_table is in _iq format and has 1011 points. And I've changed my equation to
    _iq p = _IQ(0.4);
    s1 = _IQmpy(sine_table[i],p);.
    The value of i changes by an index of 10 up to 1000. But the value of s1 is always zero. I don't understand why it's so. My sine table entries are all positive(ie starting from 1,maximum value 2 and minimum value 0) and one entry has 5 decimal points only. I still don't get why the multiplication result is always zero.
    Regards,
    Murali
  • Sorry Murali, I have not been able to reproduce this.

    There is an example of IQ math use for F2812 in controlSUITE at: C:\ti\controlSUITE\libs\math\IQmath\v160\examples_ccsv4\C\281x

    Can you try to run that project on your machine and check the results, especially the two logged waveforms in lines 121 & 122?

    If the results are correct, look for differences between that project and your own.

    Regards,

    Richard

  • Hi Richard,
    I found out that there was no section specified for IQ math in my linker file(EzDSP2812_ram_lnk.cmd). I edited the file and included the sections. But the multiplication doesn't work. Should I add the IQmath.lib file in the project? I am currently using the rts2800_ml.lib file. Can I use 2 library files in the same project?
    Waiting for your reply,
    Thank you.
    Murali
  • Hi Murali,

    Yes, please go ahead and add the IQmath library.  There is no problem having both these libraries in the same project.

    Regards,

    Richard

  • Hi Richard,
    The problem seems to be that the program doesn't fetch any value from the sine table even though the index is varying. Is it because I haven't added anything that is necessary? I am attaching a copy of my Ram_lnk.cmd. Can you check it?
    Thanks,
    Murali

    MEMORY
    {
    PAGE 0 :
    /* For this example, H0 is split between PAGE 0 and PAGE 1 */
    /* BEGIN is used for the "boot to HO" bootloader mode */
    /* RESET is loaded with the reset vector only if */
    /* the boot is from XINTF Zone 7. Otherwise reset vector */
    /* is fetched from boot ROM. See .reset section below */

    IQTABLES : origin = 0x3FF000, length = 0x000B50
    RAMM0 : origin = 0x000000, length = 0x000400
    BEGIN : origin = 0x3F8000, length = 0x000002
    PRAMH0 : origin = 0x3F8002, length = 0x000FFE
    RESET : origin = 0x3FFFC0, length = 0x000002


    PAGE 1 :

    /* For this example, H0 is split between PAGE 0 and PAGE 1 */

    RAMM1 : origin = 0x000400, length = 0x000400
    DRAMH0 : origin = 0x3F9000, length = 0x001000
    }


    SECTIONS
    {
    /* Setup for "boot to H0" mode:
    The codestart section (found in DSP28_CodeStartBranch.asm)
    re-directs execution to the start of user code.
    Place this section at the start of H0 */

    codestart : > BEGIN, PAGE = 0
    ramfuncs : > PRAMH0 PAGE = 0
    .text : > PRAMH0, PAGE = 0
    .cinit : > PRAMH0, PAGE = 0
    .pinit : > PRAMH0, PAGE = 0
    .switch : > RAMM0, PAGE = 0
    .reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */

    .stack : > RAMM1, PAGE = 1
    .ebss : > DRAMH0, PAGE = 1
    .econst : > DRAMH0, PAGE = 1
    .esysmem : > DRAMH0, PAGE = 1

    IQmath : > DRAMH0, PAGE = 1
    IQmathTables : > IQTABLES, PAGE = 0, type = NOLOAD

    }

  • Hi Murali,

    Your linker command file looks fine. 

    How is your sine table defined and initialized, and where in memory does it reside?

    Regards,

    Richard

  • What kind of sine table is that?!

    Maximum value is 2, but sine values are from -1 to 1.

    It is a fixed point processor and the variables (_iq) are long type. Are you sure you have a sine table with long numbers?

    What is your IQbase? If IQ30,  values in the table should be _IQ(-1.0) to _IQ(1.0), means -1 x 2^30 to 1 x 2^30

    Or in your convention,  _IQ(0) to _IQ(2.0), no floats with 5 decimal

    Copy the float in to execl, multiply with 2^30, use the int part of it, something like int(A1*2^30)

    Hope it makes sense

  • Hi
    Since the timer values are all positive I've added a 1 to every sine values and thus made the sine table. I've input float values in the table. May be that is the problem.
    _iq sine_table[1011] = {1.0000, 1.0062, 1.0125, 1.0188, 1.0251, 1.0314,...};
    My IQbase is 24. So is it just (sine value)*2^24? And one more doubt. I am using the below equations to vary the values of the compare register.

    EvaRegs.CMPR1 = PRD-_IQ30mpy(_IQ30mpy(sine_table[i],s1),T1/2);

    Where PRD is 15000(decimal value). And s1 is 0.8. When I watch the register CMPR1 it's value is more than 15000 most of the time and so the output PWM is not correct. How can I resolve this?

    Thank you for your replies.
    Murali.

  • See the macro, copied from a controlsuite example.

    Here m.MfuncC1 is the variable varies from -1 to 1 (sinusoid), IQ format.

    Keep the sinusoidal table as bipolar (-1 to 1), use the result to load the pwm regs.



    #define PWM_MACRO(ch1,ch2,ch3,m) \
    \
    /* Mfuncx range is (-1,1) */ \
    /* The code below changes PeriodMax*Mfuncx range .... */ \
    /* from (-PeriodMax,PeriodMax) to (0,PeriodMax) where HalfPerMax=PeriodMax/2 */ \
    \
    (*ePWM[ch1]).CMPA.half.CMPA = _IQmpy(m.HalfPerMax,m.MfuncC1)+ m.HalfPerMax; \
    (*ePWM[ch2]).CMPA.half.CMPA = _IQmpy(m.HalfPerMax,m.MfuncC2)+ m.HalfPerMax; \
    (*ePWM[ch3]).CMPA.half.CMPA = _IQmpy(m.HalfPerMax,m.MfuncC3)+ m.HalfPerMax; \
  • Hi Joy,
    What about the second question?
    Regards
    Murali