How do I convert a floating point C code to fixed point?

心已入冬 提交于 2019-11-28 19:41:22

TI provides a fixed-point library called "IQmath":

http://focus.ti.com/lit/sw/sprc990/sprc990.pdf

Converting involves analyzing your current code - for each variable you need to know what range it can hold, and what precision it needs. Then you can decide which type to store it in. IQMath provides types from q30 with a range of +/-2 and a precision of 0.0000000001 to q1 with a range of ~+/- 1 million and a precision of 0.5.

For operations which can possibly overflow the range of the variables, you need to add checks for overflow, and decide how to handle it - pin it at max, store with a different scale, raise an error, etc.

There is really no way to convert to fixed point without really gaining a deep understanding of the dataflow of your process.

The following code defines a type Fixed, using integers as its internal representation. Additions and subtractions are performed simply with the + and - operators. Multiplication is performed using the defined MULT macro.

#include <stdio.h>
typedef int Fixed;

#define FRACT_BITS 16
#define FRACT_BITS_D2 8
#define FIXED_ONE (1 << FRACT_BITS)
#define INT2FIXED(x) ((x) << FRACT_BITS)
#define FLOAT2FIXED(x) ((int)((x) * (1 << FRACT_BITS))) 
#define FIXED2INT(x) ((x) >> FRACT_BITS)
#define FIXED2DOUBLE(x) (((double)(x)) / (1 << FRACT_BITS))
#define MULT(x, y) ( ((x) >> FRACT_BITS_D2) * ((y)>> FRACT_BITS_D2) )

I was using the above code to represent fractions in my image processing algorithm. It was faster than the version which was using doubles and the results were almost exactly the same.

Most DSP toolchains include libraries for floating-point emulation in software. This will be slow, but you should initially build your code with floating-point support, then profile to see if there are just a few places that you need to convert to fixed-point to get sufficient performance. You will also need to have the floating-point stuff running to provide a comparison as you port to fixed-point, to make sure you haven't lost anything in the process.

If the C code uses doubles very seldom/sparsely, then you might be able to use a floating point emulation library without causing your C code to run 10X to 100X slower. If don't want that performance hit and there are a lot of floating point operations, and you know the scale and precision required at every arithmetic and store operation for every realistic input, then you might be able convert each arithmetic operation, manually, to used scaled integer data types and operations. But analyzing precision requirements is, in general, non-trivial for DSP type code. There are many DSP and Numerical Methods textbook chapters on the subject.

There are a few libraries out there that may do this for you. More likely, though, the PSP for your device should include some sort of math library. It should be documented. You will likely have to re-write some your code, because the control constructs you use when doing primitive-based floating-point arithmetic may not make sense when you use the API provided by your PSP.

For example - you might convert this

double arraysum = 0.0;
for (int i = 0; i < arraylen; i++) 
{
    arraysum += array[i];
}

to this

psp_decimal_t arraysum;
if (0 != psp_sum_elements(&array, arraylen, &arraysum))
{
    printf("error!");
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!