EmbeddedRelated.com
Forums

Problem with fir filtering algorithm

Started by Unknown November 20, 2012
Hello!

Hope you guys can help me:

I just get my fir filter working fine!

I'm sampling sound with sample frequency of 10 KHz and using a 128 tap low
pass fir filter ( pass from 0 to 500 Hz).

The algorithm i'm using is this one:

void filtering(void)
{
DAC12_0DAT = (signed int)out+ 2048;
//1) previous result to output

sample[0] = ADC12MEM0 - 2048;
//2) stores sample

out = 0;
counter = 128 - 1;

do
{
out += sample[counter]*filter_taps[counter];
sample[counter] = sample[counter-1];
}
while (--counter);

out += sample[counter]*filter_taps[counter];
out = out >>16 ;
DMAIV = 0;
}
My problem: When listening the output, i hear just noise....

Thanks

Fero Santos


Beginning Microcontrollers with the MSP430

This depends to some extent on the particular MSP430 you are using, but
I don't believe that even the faster ones are capable of a 128 tap FIR
filter at 10kHz.

each sample occurs 2500clocks apart, there are 128 taps, so if every
single cycle were available to the filter algorithm you'd have slightly
over 19 cycles available to calculate each tap. Some instructions can
execute in a single cycle, but most will execute in 5 or 6, so even with
an average of 4 cycles per instruction, and using hand optimised
assembler you don't have enough time to do this.

Al

Did you try and calculate any of this before designing or trying this?

On 20/11/2012 9:40 PM, Fero Santos wrote:
> Hello!
>
> Hope you guys can help me:
>
> I just get my fir filter working fine!
>
> I'm sampling sound with sample frequency of 10 KHz and using a 128 tap low
> pass fir filter ( pass from 0 to 500 Hz).
>
> The algorithm i'm using is this one:
>
> void filtering(void)
> {
> DAC12_0DAT = (signed int)out+ 2048;
> //1) previous result to output
>
> sample[0] = ADC12MEM0 - 2048;
> //2) stores sample
>
> out = 0;
> counter = 128 - 1;
>
> do
> {
> out += sample[counter]*filter_taps[counter];
> sample[counter] = sample[counter-1];
> }
> while (--counter);
>
> out += sample[counter]*filter_taps[counter];
> out = out >>16 ;
> DMAIV = 0;
> }
> My problem: When listening the output, i hear just noise....
>
> Thanks
>
> Fero Santos
>
>
>
Actually, i've worked with a Cortex M3 and this worked just fine (yeah, the
clock was 32M Hz with 256 taps)...

My clock is at 8M Hz. Could it be possible to make a 64 taps or 32 taps
filter working fine?

(Just couldn't understand how you found those 2500 clock cycles per
sampling).

Cheers!

Fero

On Tue, Nov 20, 2012 at 11:09 AM, Onestone wrote:

> **
> This depends to some extent on the particular MSP430 you are using, but
> I don't believe that even the faster ones are capable of a 128 tap FIR
> filter at 10kHz.
>
> each sample occurs 2500clocks apart, there are 128 taps, so if every
> single cycle were available to the filter algorithm you'd have slightly
> over 19 cycles available to calculate each tap. Some instructions can
> execute in a single cycle, but most will execute in 5 or 6, so even with
> an average of 4 cycles per instruction, and using hand optimised
> assembler you don't have enough time to do this.
>
> Al
>
> Did you try and calculate any of this before designing or trying this?
> On 20/11/2012 9:40 PM, Fero Santos wrote:
> > Hello!
> >
> > Hope you guys can help me:
> >
> > I just get my fir filter working fine!
> >
> > I'm sampling sound with sample frequency of 10 KHz and using a 128 tap
> low
> > pass fir filter ( pass from 0 to 500 Hz).
> >
> > The algorithm i'm using is this one:
> >
> > void filtering(void)
> > {
> > DAC12_0DAT = (signed int)out+ 2048;
> > //1) previous result to output
> >
> > sample[0] = ADC12MEM0 - 2048;
> > //2) stores sample
> >
> > out = 0;
> > counter = 128 - 1;
> >
> > do
> > {
> > out += sample[counter]*filter_taps[counter];
> > sample[counter] = sample[counter-1];
> > }
> > while (--counter);
> >
> > out += sample[counter]*filter_taps[counter];
> > out = out >>16 ;
> > DMAIV = 0;
> > }
> >
> >
> > My problem: When listening the output, i hear just noise....
> >
> > Thanks
> >
> > Fero Santos
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
Clock rates per sample is simply a case of dividing Fosc/SRATE, so
25,000,000 (the fastest MSP430 clock) /10,000 (sample rate) is 2500. so
for your 8MHz at 10kHz you get just 800 clocks per sample, and remember
this is absolute maximum, you still need to collect and store the
samples etc, so 800 clocks /32 is still only 25 clocks per tap ideal.

So I would first work out the absolute optimised FIR code that you can,
use registers if possible, and use assembler, then work that backwards.
At 16MHz you can probably handle a 32 tap filter at 10MHz.

I haven't done anything with FIR on the MSP430 for some time, but there
are a couple of good app notes/papers from Ti, they are SLAA357, which
describes a FIR code generator for the MSWP430 16x parts, and suggests
that they can do a 21 tap low pass FIR sampling at 4kHz executing in 662
clocks. so this is possibly just off your 10kHz sample rate. Then it's
easy to switch to a faster MSP if this is not a case of the cart before
the horse. The other App note is SLAA 228.

At the very least between these they will show you how best to optimise
your code for different family members

Al.
On 20/11/2012 11:54 PM, Fero Santos wrote:
> Actually, i've worked with a Cortex M3 and this worked just fine (yeah, the
> clock was 32M Hz with 256 taps)...
>
> My clock is at 8M Hz. Could it be possible to make a 64 taps or 32 taps
> filter working fine?
>
> (Just couldn't understand how you found those 2500 clock cycles per
> sampling).
>
> Cheers!
>
> Fero
> On Tue, Nov 20, 2012 at 11:09 AM, Onestone wrote:
>
>> **
>> This depends to some extent on the particular MSP430 you are using, but
>> I don't believe that even the faster ones are capable of a 128 tap FIR
>> filter at 10kHz.
>>
>> each sample occurs 2500clocks apart, there are 128 taps, so if every
>> single cycle were available to the filter algorithm you'd have slightly
>> over 19 cycles available to calculate each tap. Some instructions can
>> execute in a single cycle, but most will execute in 5 or 6, so even with
>> an average of 4 cycles per instruction, and using hand optimised
>> assembler you don't have enough time to do this.
>>
>> Al
>>
>> Did you try and calculate any of this before designing or trying this?
>> On 20/11/2012 9:40 PM, Fero Santos wrote:
>>> Hello!
>>>
>>> Hope you guys can help me:
>>>
>>> I just get my fir filter working fine!
>>>
>>> I'm sampling sound with sample frequency of 10 KHz and using a 128 tap
>> low
>>> pass fir filter ( pass from 0 to 500 Hz).
>>>
>>> The algorithm i'm using is this one:
>>>
>>> void filtering(void)
>>> {
>>> DAC12_0DAT = (signed int)out+ 2048;
>>> //1) previous result to output
>>>
>>> sample[0] = ADC12MEM0 - 2048;
>>> //2) stores sample
>>>
>>> out = 0;
>>> counter = 128 - 1;
>>>
>>> do
>>> {
>>> out += sample[counter]*filter_taps[counter];
>>> sample[counter] = sample[counter-1];
>>> }
>>> while (--counter);
>>>
>>> out += sample[counter]*filter_taps[counter];
>>> out = out >>16 ;
>>> DMAIV = 0;
>>> }
>>>
>>>
>>> My problem: When listening the output, i hear just noise....
>>>
>>> Thanks
>>>
>>> Fero Santos
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
My guess is that the "2500 clock cycles per sampling" is based on a top
speed of 25 MHz on the fastest msp430. For an 8 MHz clock, you have 800
cycles per sample. That is not a lot for a 128 tap filter!

For comparison, the Cortex M3 will do much more per clock cycle -
probably at least 10 times as much for this sort of work. I'm guessing
you are using 32-bit integers for your intermediate results?

There a few things you can do to improve your code to shave off a good
number of clocks per tap. Three obvious points are:

1. Use a local variable for out, so that it goes in a register pair
rather than memory.

2. Don't move your whole sample window - use an index to track the
current "zero" sample.

3. If your FIR filter is symmetric (as many are), use that fact to half
the number of multiplies.

4. Look /very/ carefully at the way the multiply is handled, examining
the generated assembly. Some msp430 toolchains will disable interrupts
around the multiply (so that multiplication can safely be used in
interrupts) - this can usually be disabled. Also make sure you are
using the appropriate size of multiplication - you probably want a
16x16->32 bit multiply here, but depending on the types of your arrays,
you might be getting 32x32->32 bit (wasting a lot of time) or 16x16->16
(leading to incorrect results).
However, I do not expect you will ever get it to work. As Al says, 32
taps x 10 KHz at 16 MHz clock is a much more realistic goal. You are an
order of magnitude too ambitious for this processor - you would be much
better with a Cortex M4 (not M3) for this sort of application.

On 20/11/2012 14:24, Fero Santos wrote:
> Actually, i've worked with a Cortex M3 and this worked just fine (yeah, the
> clock was 32M Hz with 256 taps)...
>
> My clock is at 8M Hz. Could it be possible to make a 64 taps or 32 taps
> filter working fine?
>
> (Just couldn't understand how you found those 2500 clock cycles per
> sampling).
>
> Cheers!
>
> Fero
>