cembeddedprintfcortex-mfixed-point

How to correctly print a 2.30 fixed point variable


I'm obtaining a DFT using a cortex-M3. I'm calculating the magnitude using the CMSIS DSP function arm_cmplx_mag_q31. The documentation says that it returns the result in the format 2.30 (which I assume is 2 bits for the integer and 30 for the fractional part; without sign bit since the magnitude can't be negative).

I'm trying to output the result to the user, but I'm finding hard to print out the correct value.

I've tried using typedef to define a new union where I can store the integer and fractional part like this

/* 2.30 union*/
typedef union {
  uint32_t full;
  struct {
    uint32_t fpart:30;
    uint8_t  ipart:2;
  } parts;
} fixed2_30_t;

then I store the 2.30 magnitude result into a fixed2_30_t variable and try to print its parts

fixed2_30_t   result;
result = magnitude;

sprintf(msg, "final results %0d.%010u", 
        result.parts.ipart, result.parts.fpart / 1073741824);

I'm dividing the fractional part by 2^30 to scale it back to a decimal, but I'm not obtaining sensible results, and I'm not entirely sure my zero padding is correct.

What would be the correct way to print it? And how do you determine the zero-padding to use?

Thanks!


Solution

  • How to correctly print a 2.30 fixed point variable

    To print to 10 decimal places after the . with a rounded value, scale the fraction by 1010 and then divide by 232.

    Use unsigned long long math to insure probability. Note that the product below, with a maximal .fpart is a 64-bit positive value.

    sprintf(msg, "final results %0d.%010llu", 
        result.parts.ipart, 
        //                                    add half the divisor
        (result.parts.fpart * 10000000000LLu + 0x40000000u/2) / 0x40000000u);
    

    Note: with less than 10 fractional digits, rounding may change the integer portion.