1
$\begingroup$

I will be using the filter coefficients generated by MATLAB in my code that will run on a microcontroller. The poor microcontroller is very bad in floating point Arithmetic. So What do I do? Shall I directly truncate all float values to nearest int? shall I do ceil? or floor? Is there any function that can automatically do this conversion for me?

Update All my filter coefficeints are coming like: 0.465, 0.76, 0.23 etc, so If I use ciel then all will become zero. What should I do now?

Actual Filter Coefficients are:

> -0.00385638
>  0.004944457
>  0.01505063
>  0.018768283
>  0.009635631
> -0.01192891
> -0.035809426
> -0.045043857
> -0.023993426
>  0.032106934
>  0.111777547
>  0.18997355
>  0.238374966
>  0.238374966
>  0.18997355
>  0.111777547
>  0.032106934
> -0.023993426
> -0.045043857
> -0.035809426
> -0.01192891
> 0.009635631
> 0.018768283
> 0.01505063
> 0.004944457
> -0.00385638
$\endgroup$
  • $\begingroup$ Are you implementing the filter on your microcontroller or just using it to calculate coefficients? "very bad in floating point Arithmetic" How bad? Have you tried floating point math on it, and it takes too much memory or time? $\endgroup$ – endolith Feb 28 '13 at 18:22
  • $\begingroup$ I am doing output calculations on microcontroller using filter coeficients that I got from Matlab.. the out is coming very slowly $\endgroup$ – gpuguy Mar 1 '13 at 5:44
  • $\begingroup$ I got most of the confusion clear, thanks to people here. My last question is when I take filter coefficients as 16 bit int, do I also take the signal values also 16 bit int, and then multiply and accumulate ? $\endgroup$ – gpuguy Apr 3 '13 at 8:49
7
$\begingroup$

Normally you would use fixed-point arithmetic for performing DSP on a a floating-point-challenged CPU.

So for, say, 16 bit fixed-point coefficients with a range of -1.0 to +1.0 your coeffs would translate to e.g.:

0.465    =>    0.465 * 0x7fff = 0x3b5

If your microcontroller does not have direct support for fixed point arithemtic (most DSPs do, general purpose microcontrollers typically do not) then you'll need to take care of scaling when you multiply or divide. (Addition and subtraction work as normal of course, provided you are not mixing different fixed point types.)

$\endgroup$
  • $\begingroup$ Why you used 0x7fff (= 32767 in decimal)? My filter coefficients are signed (having both positive and negative values). So do you think I should use 32655 instead of 32767? $\endgroup$ – gpuguy Apr 3 '13 at 6:40
  • 1
    $\begingroup$ For 16 bit signed fixed point 0x7fff = 32767 represents +1.0. Think of it as a 16 bit signed (2s complement) value scaled by 2^-15. $\endgroup$ – Paul R Apr 3 '13 at 7:00
  • $\begingroup$ Thanks for your quick reply. Can you tell me what will be 0.99 in 16 bit? $\endgroup$ – gpuguy Apr 3 '13 at 7:22
  • $\begingroup$ 0.99 * 32767 = 32439 = 0x7eb7 $\endgroup$ – Paul R Apr 3 '13 at 7:24
  • $\begingroup$ I got most of the confusion clear now. When I take filter coefficients as 16 bit int, do I also need to take the signal values also 16 bit int, and then multiply and accumulate (two 16 bit int) ? $\endgroup$ – gpuguy Apr 3 '13 at 8:52
2
$\begingroup$

If your coefficients are contained in a vector "h," multiply them by 2^15, and use the int16() function.

For example:

coeffs = int16(h*2^15);

This will put them in an integer format filling the span of a 16 bit signed integer and from there you can export the coefficients to a header or delimited data file. The processor does not care whether they're integer or fractional. As far as it is concerned, it's just a binary pattern. It's up to the programmer to decide what those patterns mean.

$\endgroup$
  • $\begingroup$ Thanks for your reply. By multiplying by 2^15 , am I not increasing the amplitude of each point ? for example my +1.0 is now a new number 32767. Is it not bad? $\endgroup$ – gpuguy Apr 3 '13 at 7:49
  • $\begingroup$ Not at all. As I said, the processor will just see the values as binary patterns, for example 0x0CCC represents .1 and 3276. With fixed point processing, you have to be mindful of data formats. If you multiply that 16.0 integer value by a 1.15 fractional value, the result is 17.15. You have to know if the processor did any automatic shifting to the result, which 16 bits are actually your result, and how to extract them. $\endgroup$ – Matt Young Apr 3 '13 at 14:59
0
$\begingroup$

Fixed point signal processing is a lot more complicated than floating point. The fixed point related problems include: quantization noise, coefficient quantization, overflow, underflow, saturation, limit cycles, etc.

For example, writing an IIR filter in fixed point, requires fairly thorough analysis of the filter topology, input & output signal statistics, state variable behavior and the filter transfer function as well.

Unless you have a very simple task, say a low order FIR filter with well known coefficients, I recommend some text book study.

$\endgroup$
0
$\begingroup$

You should use 2^^(number of fractional bits) For signed 16 bit with 15 fractional bits - you would multiply by 32768. The range is +32767 to -32768. 1/32768 is your lsb value. To convert a floating point to fixed - multiply as shown above and then round. Watch out for +1 since that is actually above 15 fractional and would require an integer bit. In your case you would saturate positive numbers to be no larger than 32767.

$\endgroup$

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.