티스토리 뷰

TI(텍사스 인스루먼트)TMS320 계열의 DSP 칩은 IEEE 754 와 달리 지수 비트가 최상위 비트에 위치해 있지 않다. float 형의 경우 RAW Data 를 그대로 받아왔을때 IEEE754 로 변환 해주어야 한다.

기본적인  IEEE 754 규약을 간단하게 말하면

float 형의 경우 부호(sign)비트 1비트 지수(exponent) 비트 8비트 가수(mantissa) 나머지 24비트의 순서로 총 4Bytes 사이즈로 구성이 된다.

double 형의 경우 총 64비트 중 부호(sign)비트 1비트 지수(exponent) 비트 11비트 가수(mantissa) 나머지 52비트의 순서로 총 8Bytes 사이즈로 구성이 된다.

TI의 DSP 30 타입의 float형은 지수 비트와 가수 비트 사이에 부호비트를 넣고 있으며, IEEE754 타입과 비트사이즈가 동일하다. 이에 대해선 TMS320C30 의 레퍼런스를 참고 하기 바란다.

 

다음은 C30->IEEE754 컨버팅 코드소스이다.

float DasBuffer::convertToIeee ( int ControllerNum, int locate, char *value )
{
    struct  c30float
    {
        signed        int     mantissa    : 23;
        unsigned    int     sign        : 1;
        signed        int     exponent    : 8;
    };

    struct  ieeefloat
    {
        unsigned    int     mantissa    : 23;
        unsigned    int     exponent    : 8;
        unsigned    int     sign        : 1;

    };

    union   ieee_union {
            unsigned int            hex;
            char                    val[4];
            float                    in;
            struct      ieeefloat   str;
    } ieee;

    union   c30_union {
            unsigned int            hex;
            char                    val[4];           
            float                   flt;
            struct      c30float    str;
    } c30;

    memcpy ( c30.val, value, 4 );
    //아마 필요 없을듯 하나 데이터가 역순으로 비트를 전송 받으면 그에 대한 처릴 해줘야 함.
    c30.hex = ntohl ( c30.hex );
    /*for ( int = 3; i >= 0 ; i--)
    {
        memcpy(c30[i], value+3-i, 1)
    }
    */
    /*Debug out routine
    *gDebug.setPrintLevel (Debug::LOG);  
    *gDebug.setPrintDirection ( "IEEELog.txt", Debug::DEBUG_APPEND);
    *gDebug.hprintln (Debug::LOG, " IEEE.flt value -------------- %f", c30.flt);
    */

/*Bnf Source*/   
    if (c30.hex == 0x80000000) {
        ieee.in = 0;
        return ieee.in;
    } else if (c30.str.exponent == 0x7F)
    {   
        ieee.str.exponent = 255;
        ieee.str.mantissa = 0;
        ieee.str.sign = c30.str.sign;
        return ieee.in;
      }
    if (c30.str.sign) ieee.str.mantissa = ~(c30.str.mantissa-1);
    else ieee.str.mantissa = c30.str.mantissa;
    ieee.str.sign = c30.str.sign;
    ieee.str.exponent = (c30.str.exponent == -128) ? 0 : c30.str.exponent+127;
    /*Bnf Source end*/   

#if 0
    /* Refer to page 5-15 in the TMS320C3x User's Guide for the */
    /* following case numbers of C3X-->IEEE conversion. */
    if (c30.hex == 0x80000000)
    {
        /* Case 6 -- Zero */
        return(0.0);
    } else if (c30.str.exponent == 0x7F)
    {
        /* Case 1 and 2 -- Max Pos/Neg Infinity */
        ieee.str.exponent = 255;
        ieee.str.mantissa = 0;  /* don't care */
        ieee.str.sign = c30.str.sign; /* signs are same for +/- infinity */
        return(ieee.in);
    } else {
        ieee.str.sign = c30.str.sign;  /* signs will be same from here on */
        if (c30.str.sign == 0)
        {
            /* Case 3 */   
            ieee.str.mantissa = c30.str.mantissa;       
            ieee.str.exponent = c30.str.exponent + 0x7F;
            return(ieee.in);
        } else {
            if (c30.str.mantissa == 0)
            {
            /* Case 5 */
            ieee.str.mantissa = 0;
            ieee.str.exponent = c30.str.exponent + 0x80;
            return(ieee.in);
            } else {
            /* Case 4 */
            //Wrong
            //ieee.str.mantissa = ~(c30.str.mantissa + 1);
            ieee.str.mantissa = ((~c30.str.mantissa) + 1);
            ieee.str.exponent = c30.str.exponent + 0x7F;   
            return(ieee.in);
            }
        }
    }
#endif

    gDebug.hprintln (Debug::LOG, "[convertToIeee] C:%d, locate:%d, c30(f:%08x,m:%d,s:%d,e:%d), ieee(i:%08x, m:%d,s:%d,e:%d)",
        ControllerNum, locate,
        c30.flt, c30.str.mantissa, c30.str.sign, c30.str.exponent,
        ieee.in, ieee.str.mantissa, ieee.str.sign, ieee.str.exponent);

    return ( ieee.in );
}

테스트 용으로 IEEE->C30 컨버트 소스

struct  c30float
{
    signed        int     mantissa    : 23;
    unsigned    int     sign        : 1;
    signed        int     exponent    : 8;
};

struct  ieeefloat
{
    unsigned    int     mantissa    : 23;
    signed        int     exponent    : 8;
    unsigned   int     sign        : 1;

};

union   ieee_union {
        char                    val[4];
        float            in;
        struct      ieeefloat   str;
} ieee;

union   c30_union {
        char                    val[4];
        float                   flt;
        struct      c30float    str;
} c30;

 

int IeeeToTi(float i , float *pFloat)
{
    ieee.in = i;
    c30.str.mantissa = ieee.str.mantissa;
    c30.str.exponent = (ieee.str.exponent == 0) ? -128 : ieee.str.exponent - 127;
    c30.str.sign = 0;
    if(ieee.str.sign) c30.flt = -c30.flt;
    *pFloat = (float) c30.flt;

    printf(" ieee sign %d exponenet %d mentissa %d\n",ieee.str.sign, ieee.str.exponent, ieee.str.mantissa);
    printf(" ieee [0:%x] [1:%x] [2:%x] [3:%x]\n",ieee.val[0],ieee.val[1],ieee.val[2],ieee.val[3]);
    //showbit_c30(ieee.val);
    printf("\n");

    printf(" c30 sign %d exponenet %d mentissa %d\n",c30.str.sign, c30.str.exponent, c30.str.mantissa);
    printf(" c30 [0:%x] [1:%x] [2:%x] [3:%x]\n",c30.val[0],c30.val[1],c30.val[2],c30.val[3]);
    //showbit_c30(c30.val);
    printf("\n");

    /*c30.str.sign = 1;
    c30.str.exponent = 3;
    c30.str.mantissa = 6396314;

    printf(" c30 sign %d exponenet %d mentissa %d\n",c30.str.sign, c30.str.exponent, c30.str.mantissa);
    printf(" c30 [0:%x] [1:%x] [2:%x] [3:%x]\n",c30.val[0],c30.val[1],c30.val[2],c30.val[3]);
    showbit_c30(c30.val);
    printf("\n");*/
    printf("test %f\n",c30.flt);

    *pFloat = (float) c30.flt;

    return (1);
}

//비트 검증 코드

void showbit(float value)
{
    unsigned int bit;
    float f_sen;
    memcpy( &bit, &value ,4);
    unsigned int t = ( 1<<31);
    for (int i = 0 ; i <32 ;i++ )
    {
        if ( ( t& bit) == t ) printf("1") ; else printf("0");
        if (i%8 == 0)printf(" ");
        t>>=1;
    }
    printf("\n");

}