12,550,593 members (46,017 online)
alternative version

19.7K views
13 bookmarked
Posted

# Filtering a Sampled Signal Using FIR Filters in a Morsecode Translator

, 19 Dec 2010 CPOL
 Rate this:
Using FIR filtering (finite impulse response) coefficients to create filters

## Introduction

FIR stands for Finite Impulse Response.

In the analogue world, if you wished to filter a signal, you would use capacitors, resistors and inductors wired together to create the filter of your choice. In the digital world, you can still apply a filter to a sampled signal being received by a method of multiplying the samples by as series of coefficients and summing to create a new (filtered) sample stream.

Imagine a train of samples being received at 200msec intervals. Each sample is modified by adding or subtracting, depending on the power of the coefficient, corrected amounts of the other samples. A new filtered stream of samples is created.

## Background

I’ve written a program to decode Morse code by using the PC sound card hooked up to a radio transmitter / receiver. The issue is that these radios use a lot automatic gain control (AGC). While there is no received morse tone, the noise threshold comes up and can be miss decoded.

Noise threshold raised

To counter the effects of the AGC, I needed to filter both the morse tone (700Hz) and the out of band noise and use the latter to boost the gain of the former (i.e. lots of noise reduce gain, low noise boost the gain). The result is very good separation for the given frequency.

ScopeFir is an excellent program to use to design the filters. A 30 day trial can be downloaded from here.

Considerations to follow:

• Reducing the sample rate reduces the bandwidth of the filter. Nyquist theorem says the sample rate must be more than twice the highest frequency. I was only filtering 700Hz so my sample rate was set to 2000 samples / sec (1khz BW)
• I needed the minimum processing delay through the filter. Morse tone is measured in tens of milliseconds. The more coefficients you use, the sharper the filter but the longer the processing delay. I optimised at nine coefficients with a processing delay of 3.2msecs.

The resultant filter shapes look like this. The first passes 700hz with about 10db of noise suppression. The second filter notches out the 700Hz so passes the noise element.

The derived coefficients and time delays for the two filters are as shown.

## Using the Code

Two arrays are filled with the coefficients for the bandpass and bandstop filters. Each sample is cascaded through the algorithm being multiplied by each coefficient and summed to create five new samples.

The stop filter will return the out of band noise while the band pass filter returns the desired signal, in this case 700hz. Summing the results of the filters creates effectively an inverse AGC.

//
//    ' FIR filter coefficients
Dim CBP(9) As Double
CBP(0) = 0.1020135767780434
CBP(1) = -0.35600582739652703
CBP(2) = 0.41498447051618764
CBP(3) = -0.35600582739652703
CBP(4) = 0.1020135767780434
CBP(5) = 0.1020135767780434
CBP(6) = -0.35600582739652703
CBP(7) = 0.41498447051618764
CBP(8) = -0.35600582739652703

Dim CBS(9) As Double
CBS(0) = 0.1020135767780434
CBS(1) = -0.35600582739652703
CBS(2) = 0.41498447051618764
CBS(3) = -0.35600582739652703
CBS(4) = 0.1020135767780434
CBS(5) = 0.1020135767780434
CBS(6) = -0.35600582739652703
CBS(7) = 0.41498447051618764
CBS(8) = -0.35600582739652703

Dim samples__1 As Array = buffer.Read_
(0, GetType(Int16), LockFlag.FromWriteCursor, SAMPLE_FORMAT_ARRAY)

//
For J As Integer = 0 To 4 ' Filter five samples five times

For H As Integer = 0 To SAMPLES - 6 ' Apply FIR filter coefficients
'to five samples at a time and add together
templeftGoal(J) = templeftGoal(J) + _
(CType(samples__1.GetValue(H + J, 0, 0), Int16) * CBP(H))
templeftrange(J) = templeftrange(J) + _
(CType(samples__1.GetValue(H + J, 0, 0), Int16) * CBS(H))
temprightGoal(J) = temprightGoal(J) + _
(CType(samples__1.GetValue(H + J, 1, 0), Int16) * CBP(H))
temprightrange(J) = temprightrange(J) + _
(CType(samples__1.GetValue(H + J, 1, 0), Int16) * CBS(H))
Next

// normalise all samples

If templeftGoal(J) < 0 Then templeftGoal(J) = 0 - templeftGoal(J)
leftGoal += templeftGoal(J)
If templeftrange(J) < 0 Then templeftrange(J) = 0 - templeftrange(J)
leftrange += templeftrange(J)

If temprightGoal(J) < 0 Then temprightGoal(J) = 0 - temprightGoal(J)
rightGoal += temprightGoal(J)
If temprightrange(J) < 0 Then temprightrange(J) = 0 - temprightrange(J)
rightrange += temprightrange(J)

Next

leftGoal = CInt(Math.Abs(leftGoal \ (SAMPLES - 5)))
leftrange = CInt(Math.Abs(leftrange \ (SAMPLES - 5)))
rightGoal = CInt(Math.Abs(rightGoal \ (SAMPLES - 5)))
rightrange = CInt(Math.Abs(rightrange \ (SAMPLES - 5)))

//

## Points of Interest

If you are interested in the Morse Code program, you will find it here. The program uses both the FIR filters and my PPM meters.

• Version 1.0

## Share

 Engineer BBC News United Kingdom
I do a little programming in VB2010 and for PIC controllers. I wouldn't call myself an expert as it always takes me a long time and I'm constantly learning. I enjoy what I do.

I've completed a few projects.

Tide calculator for the UK
Sony LANC camera remote control - serial and Pic controllers
PIC Pulse Induction Metal Detector
Morse Code through the sound card
Home Maintenance Log

I also do a little web design and maintain my diving club's web site at http://www.esac.org.uk/.

## You may also be interested in...

 Pro Pro

 First Prev Next
 My vote of 5 Ben_126-Dec-12 14:34 Ben_1 26-Dec-12 14:34
 Ooops Peter Hawke29-Dec-11 11:45 Peter Hawke 29-Dec-11 11:45
 Is their source code? Peter Hawke27-Dec-11 13:48 Peter Hawke 27-Dec-11 13:48
 FIR? Vaclav_Sal2-Jul-11 16:10 Vaclav_Sal 2-Jul-11 16:10
 Re: FIR? Nigel Ealand2-Jul-11 22:13 Nigel Ealand 2-Jul-11 22:13