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.

IQMATH V160 issue

Genius 5910 points

Please see the following code:

volatile _iq15 DEBUG;
volatile long DEBUG1;

DEBUG= _IQ15 (DEBUG1) ;

When DEBUG1 is changed in the debug window. The variable DEBUG doesn't change it is always 0.

See: IQMathlib.h

#define   _IQ15(A)      (long) ((A) * 32768.0L)

the Significant field of float is 23 bits. So any value greater then (23 - 15) will give an overflow in the conversion. 

 When I change it  to:

#define   _IQ15(A)      (long) ((A) * 32768L)

It works fine.

  • Hi,

    evs said:
    DEBUG= _IQ15 (DEBUG1) ;

    Can you post the disassembly associated with this line for both the failing and working cases. If im not mistake A should be promoted to double (32-bit single precision on the C28x), multiplied by 32768.0 and then cast to long.

  • If I remember correctly  somewhere in the documentation. There is no double, a double is redefined as float.

    The code:

    DEBUG=((DEBUG1) * 32768L);

            MOVL      ACC,@_DEBUG1          ; [CPU_] |118|
            LSL       ACC,15                ; [CPU_] |118|
            MOVL      @_DEBUG,ACC           ; [CPU_] |118|

    DEBUG=((DEBUG1) * 32768.0L);

    ;*** 118    -----------------------    DEBUG = (long)((long double)DEBUG1*32768.0L);

        .dwpsn    file "../main.c",line 118,column 2,is_stmt,isa 0
            SUBB      XAR4,#12              ; [CPU_U] |118|
        .dwpsn    file "../main.c",line 117,column 2,is_stmt,isa 0
            MOVL      @_encoder_timebase,ACC ; [CPU_] |117|
        .dwpsn    file "../main.c",line 118,column 2,is_stmt,isa 0
            MOVZ      AR6,AR4               ; [CPU_] |118|
            MOVW      DP,#_DEBUG1           ; [CPU_U]
            MOVL      ACC,@_DEBUG1          ; [CPU_] |118|
    $C$DW$201    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$201, DW_AT_low_pc(0x00)
        .dwattr $C$DW$201, DW_AT_name("L$$TOFD")
        .dwattr $C$DW$201, DW_AT_TI_call
            LCR       #L$$TOFD              ; [CPU_] |118|
            ; call occurs [#L$$TOFD] ; [] |118|
            MOVZ      AR5,SP                ; [CPU_] |118|
            MOVZ      AR4,SP                ; [CPU_] |118|
            SUBB      XAR5,#8               ; [CPU_U] |118|
            SUBB      XAR4,#12              ; [CPU_U] |118|
            MOVZ      AR6,AR5               ; [CPU_] |118|
            MOVZ      AR4,AR4               ; [CPU_] |118|
            MOVL      XAR5,#$C$FL1          ; [CPU_U] |118|
    $C$DW$202    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$202, DW_AT_low_pc(0x00)
        .dwattr $C$DW$202, DW_AT_name("FD$$MPY")
        .dwattr $C$DW$202, DW_AT_TI_call
            LCR       #FD$$MPY              ; [CPU_] |118|
            ; call occurs [#FD$$MPY] ; [] |118|
            MOVZ      AR4,SP                ; [CPU_] |118|
            SUBB      XAR4,#8               ; [CPU_U] |118|
            MOVZ      AR4,AR4               ; [CPU_] |118|
    $C$DW$203    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$203, DW_AT_low_pc(0x00)
        .dwattr $C$DW$203, DW_AT_name("FD$$TOL")
        .dwattr $C$DW$203, DW_AT_TI_call
            LCR       #FD$$TOL              ; [CPU_] |118|
            ; call occurs [#FD$$TOL] ; [] |118|
            MOVW      DP,#_DEBUG            ; [CPU_U]
            MOVL      @_DEBUG,ACC           ; [CPU_] |118|

    28035 and TI 6.4.11

  • The disassembly looks correct.  Its promoting the argument DEBUG1 to long double (actually double precision on the C28x) and then doing a double multiply with 32768.0 and then converting the result to long. This is correct.

    What value of DEBUG1 results in DEBUG=0 for the non working case?

  •  sizeof (float) = 2

    sizeof (double) = 2 

    There is your issue.

    TypeSignExponentSignificand fieldTotal bitsExponent biasBits precisionNumber of decimal digits
    Half (IEEE 754-2008) 1 5 10 16 15 11 ~3.3
    Single 1 8 23 32 127 24 ~7.2
    Double 1 11 52 64 1023 53 ~15.9
    x86 extended precision 1 15 64 80 16383 64 ~19.2
    Quad 1 15 112 128 16383 113 ~34.0

     en.wikipedia.org/.../Floating_point

  • On the C28x, float and double are the same size i.e. 32-bits - this was done intentionally, and is documented in the compiler guide as well: SPRU514, Table 6-1. 

    long double is 64-bit precision - they have added a section describing that as well, section 6.4.3

    I do not know the rationale for the decision behind keeping double and float the same size (i can inquire with our compiler team), but it was intentional. So, the IQ15 macro is doing the correct operation based on the C language implementation.