• Not Answered

Compiler/TMS320F28069M: IQmath problem

Part Number: TMS320F28069M

Tool/software: TI C/C++ Compiler

Hi all!

I have a problem with the #include <IQmathLib.h> library. Currently I'm using a Launchpad F28069M, and the idea is that I need to calculate the sine and cosine for some variables in radians. But the IQmath lybrary is not that easy to understand.

My angles values are expressed as a 2*pi*w, and i have to update w several times during  a period of time (w will be between 10 and 10000). (This is in order to apply a FFT in my code)

I hope someone has an example of how  to apply the sine and cosine applying the IQmath lib so I can adapt it to my code.

Thanks in advance for the help!

Maria 

9 Replies

  • Hi Maria,

    For examples of the basic IQmath functions I can do no better than point to the code examples in the quickstart guide (attached). The sine and cosine functions expect inputs in radians, and you have to keep within the numeric range of your chosen IQ format.  For example, with w = 10000 you'll be passing in a value of 62832, so your IQ format will need at least 16 bits of range (2^16 = 65536).  This will restrict you to IQ15 or less.

    Is your input data (w) already in IQ format?

    Regards,

    Richard

    6136.IQmath_Quickstart.pdf

  • In reply to Richard Poley:

    Dear Richard

    Thanks for your repply, there is an easier way to do it? i tried with math.h and it does not matter what value I put i have the same answer, also tried some IQmath examples and they also give me some numbers at the output value that are really big and make no sense to me (even changing them from IQ to float) then I tried also CLAmath without success.

    The main idea is only to generate a sine and cosine function in terms of a variable wp with amplitude 1. Then I want to have this value:

    sin(2*pi*w) and cos(2*pi*w)

    The variables I have are not in IQ format yet, but I would really appreciate if you could tell me an easier way to do it (without getting that into details with IQmath that is a bit complicated)

    Thanks in advance for your help

    Best regards

    Maria
  • In reply to MerSago:

    Hi Maria,

    It should be fairly straightforward to do this.  Once you have added the IQmath library to your project, here's what you might try in your program:

    // variables
    _iq twopi = _IQ(6.283185307f);
    _iq sval = _IQ(0.0f);
    _iq cval = _IQ(0.0f);
    _iq ref = _IQ(0.0f);
    _iq inc = _IQ(0.01f);
    _iq angle = _IQ(0.0f);
    long i;

    main()

    {

    for (i=0; i<9999; i++)
    {
    angle = _IQmpy(twopi, ref);
    sval = _IQsin(angle);
    cval = _IQcos(angle);
    ref += inc;
    }

    ...etc.

    If I set a break-point on the last line ("ref += inc;") it's stepping through the angles nicely.  You would change "inc" to change the frequency of the sine/cosine outputs, which would obviously be in global _IQ format (I was using IQ24).  The attachment is what I see in the watch window.

    An alternative approach which does not involve IQmath is to use the FastRTS library which you can find in controlSUITE.  The sine and cosine functions have approximately the same cycle counts as their IQmath counterparts, and you will be able to keep everything in floating-point if that's what you want.

    I hope this helps, but do post back if you have further questions.

    Regards,

    Richard

  • In reply to Richard Poley:

    Dear Richard

    Thanks for the repply, I dont understand what happened but now I have 33 errors related to the #include <IQmathCPP.h> library. The error looks like this

    And I cant try the code you sent me. This error appears the moment I call the include function.

    Thanks in advance for the help.

    best

    Maria 

  • In reply to MerSago:

    Hi Maria,

    Regret I can't really see what's going wrong from the errors.  Those warnings are from the C++ version of the library header file.

    If I'm right, your project is the ADC SOC example in controlSUITE, which is likely at this location on your hard drive:

    C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5\adc_soc

    I've attached a slightly modified main source file for this example.  The only changes I've made are to add the IQ math header file at the top, and copy in the lines of code from my last post.  It's working correctly on my machine.  

    Can you change your own source file to look like this and let me know if it builds please?

    (Note: you may get a couple of warnings when you build the project but these can be ignored).

    Thanks.

    Regards,

    Richard

    3515.Example_2806xAdcSoc.c

  • In reply to Richard Poley:

    dear Richard

    First of all thanks for your time and help. I manage to fix the problem with the library by following your answer. Now i have a problem, I need to use the sine and cosine signal to compare with some float values in real time. I would like to know how to convert the values expressed below (Q format) to float directly(not only for visualization)


    I hope you can help me to fix this problem too. Maybe i need to do some conversion? 

    And still i have some doubts about the results i have, as you can see in the next image, the values are not correctly at all for sine and cosine of the given angle. I would like to know if there is another thing i should add to the code? I'm here just using the code you sent to me. and I even add the #define   GLOBAL_Q       24

    Thanks in advance for your help

    Regards

    Maria 

  • In reply to MerSago:

    Dear Richard,

    The problem with the 33 errors is generated when I try to include the library #include “IQmathCPP.h” that is used in the examples. I also tried to use the FastRTS but nothing seems to give me values that are useful for me for now. I imported the libraries:

    #include "math.h"
    #include "C28x_FPU_FastRTS.h"

    And not even with 0 or 2*pi or 180 i have some value that is close to reality. Hope you can help me

    best regards

    Maria

  • In reply to MerSago:

    If you are on F28069 you do not need IQmath library at all because you are already on floating point. 

    Use #include <math.h>

    Please note the C28x_FPU_FastRTS.h does not need to be included, it's only a link time replacement.. 

    read the user guide for fastRTS here

    C:\ti\controlSUITE\libs\math\FPUfastRTS\V100\doc

    Note:

    The fastRTS also relies on CMD file for the math look up tables

    the uG points to the below but this may not be correct for the device you have selected

    MEMORY
    {
    PAGE 0 :

    FPUTABLES : origin = 0x3FEBDC, length = 0x0006A0

    }
    SECTIONS
    {

    FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD

    }

    I think it should be the below...  can you confirm you are using F28069M ?? 

    MEMORY
    {
    PAGE 0 :

    FPUTABLES   : origin = 0x3FD590, length = 0x0006A0 /* FPU Tables in Boot ROM */


    }
    SECTIONS
    {

    FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD

    }

  • In reply to Manish Bhardwaj:

    Hi Manish
    Thanks for your reply, I already tried with the math.h library, using the following code with the adc_soc example in the F28069m

    //###########################################################################
    // Description:
    //! \addtogroup f2806x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC - ADCINT1.
    //! Two channels are converted, ADCINA4 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10] - Last 10 ADCRESULT0 values
    //! - Voltage2[10] - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount - Idle loop counter
    //
    //
    //###########################################################################
    // $TI Release: F2806x C/C++ Header Files and Peripheral Examples V151 $
    // $Release Date: February 2, 2016 $
    // $Copyright: Copyright (C) 2011-2016 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

    #include "DSP28x_Project.h" // Device Headerfile and Examples Include File
    #include "math.h"

    // Prototype statements for functions found within this file.
    __interrupt void adc_isr(void);
    void Adc_Config(void);


    // Global variables used in this example:
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];

    double sinRT = 0;
    double cosRT = 0;
    double angle = 0;
    double wp = 2.65;
    double pi = 3.141592654;

    // variables

    long i;


    main()
    {
    // IQ math test
    angle = 2*pi*wp;
    sinRT = sin(angle);
    cosRT = cos(angle);

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2806x_SysCtrl.c file.
    InitSysCtrl();


    // Step 2. Initialize GPIO:
    // This example function is found in the F2806x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio(); // Skipped for this example

    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2806x_PieCtrl.c file.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example. This is useful for debug purposes.
    // The shell ISR routines are found in F2806x_DefaultIsr.c.
    // This function is found in F2806x_PieVect.c.
    InitPieVectTable();

    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    EALLOW; // This is needed to write to EALLOW protected register
    PieVectTable.ADCINT1 = &adc_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize all the Device Peripherals:
    // This function is found in F2806x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
    InitAdc(); // For this example, init the ADC
    AdcOffsetSelfCal();

    // Step 5. User specific code, enable interrupts:

    // Enable ADCINT1 in PIE
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
    IER |= M_INT1; // Enable CPU Interrupt 1
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM

    LoopCount = 0;
    ConversionCount = 0;

    // Configure ADC
    EALLOW;
    AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1; // Enable non-overlap mode
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // ADCINT1 trips after AdcResults latch
    AdcRegs.INTSEL1N2.bit.INT1E = 1; // Enabled ADCINT1
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // Disable ADCINT1 Continuous mode
    AdcRegs.INTSEL1N2.bit.INT1SEL = 1; // setup EOC1 to trigger ADCINT1 to fire
    AdcRegs.ADCSOC0CTL.bit.CHSEL = 4; // set SOC0 channel select to ADCINA4
    AdcRegs.ADCSOC1CTL.bit.CHSEL = 2; // set SOC1 channel select to ADCINA2
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; // set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    EDIS;

    // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from CMPA on upcount
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
    EPwm1Regs.CMPA.half.CMPA = 0x0080; // Set compare A value
    EPwm1Regs.TBPRD = 0xFFFF; // Set period for ePWM1
    EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start

    // Wait for ADC interrupt
    for(;;)
    {
    LoopCount++;
    }

    }


    __interrupt void adc_isr(void)
    {

    Voltage1[ConversionCount] = AdcResult.ADCRESULT0;
    Voltage2[ConversionCount] = AdcResult.ADCRESULT1;

    // If 20 conversions have been logged, start over
    if(ConversionCount == 9)
    {
    ConversionCount = 0;
    }
    else ConversionCount++;

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

    return;
    }


    and the replies i have are not the correct values, I don't know if I should change then some other configuration ?
    wp = 0;
    angle = 0;
    sinRT = -0.9569404
    cosRT = -0.2902847

    or in a second try
    wp = 2.65;
    angle = 16.65044;
    sinRT = 1.054673
    cosRT = 0.008753741

    Please I hope you can help me to understand where is the mistake

    Thanks in advance

    Best

    MAria