7
\$\begingroup\$

Background

Is there anybody here who is an EE with programming experience who has worked with the Texas Instruments TMS320 C3X-series DSP? I am currently doing some work with the C3X for a project. My goal here is to convert C3X-formatted floating point hexadecimal values into IEEE 754 format. The code that I have works properly for:

enter image description here

Where x is the input single floating-point C3X hex number (represented as a UInt32).

The issue, is when I attempt to use a number such as 0.123. It seems that I always get a NaN value as a result. I am currently using this code snippet from the University of Florida that I have ported over to C#.

Procedure

  1. Swap the sign and exponent fields to go from C3X to IEEE. I will not show this code (unless asked) as I believe it is very straightforward for anyone who has worked with this DSP.
  2. Perform the University of Florida algorithm (linked above), that I believe I do not fully understand.
  3. Combine the sign, exponent, and mantissa into single-precision IEEE 754 floating point.

C# Implementation

Here is the code used to implement the algorithm for when the C3X float-number happens to be between 0 and 1 (where the issue is happening). The c30 object, represents the C3X floating point number. The ieee object represents the IEEE 754 floating point number.

EDIT: Upon popular request, here is a code sample that isn't awful. This sample is the properly working version where we dump in 15,913.35... (as C3X hexadecimal).

C30Float c30 = null;
UInt32 bias = 127;
Int32 mantissa = 0;
Int32 digit = 0;
double fraction = 0;
double exponent = 0;
double fpValue = 0;
double sign = 0;

// 1. Declare the new C3X floating point value.
c30 = new C30Float(0x0D78A56B);

// 2. Get the sign bit value.
sign = c30.GetSign();

// 3. Decide whether or not to do the flip.
if (sign == 1)
{
    // flip
    mantissa = c30.GetMantissa();
    mantissa = mantissa + 1;
    mantissa = (~mantissa) & 0x007FFFFF; // the first 9 bits have nothing to do with the mantissa
}
else
{
    mantissa = c30.GetMantissa();
}

// 4. Obtain part of the fraction (do the swim!).
for (int i = -1; i > -24; i--)
{
    // mantissa index
    int currentDigit = i + 23; // n = -23 + 23 => n = 0

    // shift forward (get the digit)
    digit = mantissa;
    digit = digit & (1 << currentDigit);

    // shift back (get the digit into the lowest place)
    digit = digit >> currentDigit;

    // apply the digit to the fraction
    fraction += digit * Math.Pow(2, i);
}

// 5. Obtain the exponential part of the number.
exponent = c30.GetExponent() + 0x7F;

// 6. Get the floating point number.
fpValue = Math.Pow(-1, sign);
fpValue *= (1 + fraction) * Math.Pow(2, exponent - bias);

I know that I have not provided the implementation details for the following:

GetMantissa()
GetExponent()
GetSign()

or...

SetMantissa()
SetExponent()
SetSign()

The reason for this is that all these are doing is entering/pulling the numbers to/from their respective fields as specified in the TMS320 C3X User's Guide. Who knows, maybe that is where I'm going wrong, but for now I'd like to start at where I think the scope of the problem begins. If any of you believe that the issue is not here then feel free to ask about this implementation and I will provide more detail as warranted.

Question

My issue is apparently with numbers between 0 and 1. So if anyone has known C3X hex values and their known counter-part floats/reals that I can plug-and-chug that would be great so I can troubleshoot this algorithm.

Note: We don't have the DSP in front of us for what we're doing and can't just get the numbers out.

\$\endgroup\$
  • \$\begingroup\$ Are you remembering to convert the exponent between 8-bit signed (presumably 2's complement, I can't see it stated in the TI doc) and 8-bit unsigned with bias=127 (IEEE)? Last time I used the TMS320 it was still 16-bit integer only... (TMS32010) \$\endgroup\$ – Brian Drummond Mar 21 '16 at 14:11
  • \$\begingroup\$ @BrianDrummond that is called the "flip" and yes I am doing it. \$\endgroup\$ – Snoop Mar 21 '16 at 14:11
  • \$\begingroup\$ @BrianDrummond have you worked with this DSP? \$\endgroup\$ – Snoop Mar 21 '16 at 14:12
  • \$\begingroup\$ @BrianDrummond it seems like the numbers coming out of this thing that "should be" (and i'll say that because we're only here to discuss the DSP and NOT the nature of the application) small fractional numbers i.e. 0.234 seem to be having big Exponent values. Is this normal? Or impossible? \$\endgroup\$ – Snoop Mar 21 '16 at 14:16
  • \$\begingroup\$ That is certainly where I would focus my intention. I think exponent(0.234) should be 124 (IEEE) or -3 =252 (TMS320). \$\endgroup\$ – Brian Drummond Mar 21 '16 at 14:21
1
\$\begingroup\$

The TMS320C3x User’s Guide lists a few test values:

  • Hex value of C3X floating value interpreted as uint32 ~~ Corresponding floating point value
  • 0x02400000 ~~ +6.0 (see p. 5-10)
  • 0x01C00000 ~~ -3.0 (see p. 5-11)
  • 0xFB400000 ~~ (+3/64) (see p. 5-11)

I'm guessing you want code something more like:

/*
Convert from single-precision TMS C3x floating point
to single-precision IEEE floating point.
2016-07-11: minor tweaks by David Cary
2016-03-21: StevieV

(see
http://electronics.stackexchange.com/questions/223832/tms320-floating-point-texas-instruments-dsp-from-98
http://etd.fcla.edu/UF/UFE0005060/tmsieeeconv.c
http://etd.fcla.edu/UF/UFE0005060/tmsieeeconv.h
)
*/

C30Float c30 = null;
Int32 mantissa = 0;
double exponent = 0;
double sign = 0;
double fpValue = 0;

// 1. Declare the new single precision C3X floating point value.
c30 = new C30Float(0x0D78A56B);

/*
We could have followed page 5-21 in the TMS320C3x User's Guide
http://www.ti.com/lit/ug/spru031f/spru031f.pdf
for C3X-->IEEE conversion.

But it seemed simpler to follow page 5-9
in the TMS320C3x User's Guide
"5.3.5 Determining the Decimal Equivalent of a TMS320C3x Floating-Point Format"
http://www.ti.com/lit/ug/spru031f/spru031f.pdf
*/

// 2. Break up the C3X floating value into its components
// (Assume that these 3 functions deal with endianness).
sign = c30.GetSign(); // either 0 (positive) or 1 (negative)
exponent = c30.GetExponent(); // a signed 8-bit integer, -128 to +127.
mantissa = c30.GetMantissa(); // a 23-bit unsigned integer

// insert implied most significant bit to the left of MSB of the mantissa.
mantissa = ((1 + sign) << 23) + mantissa;

// 6. Get the floating point number.
// Move the binary point left 22 places,
// then adjust further based on exponent.
// (Possibly something like ldexp() or BitConverter.ToSingle()
// would be more efficient).
fpValue = (-sign) * mantissa * Math.Pow(2, exponent - 22);
return fpValue;
\$\endgroup\$
  • \$\begingroup\$ I see your answer, I just haven't gotten back to this project yet. I will take a look at this when I get back around to it. \$\endgroup\$ – Snoop Aug 8 '16 at 11:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.