Click here to Skip to main content
Click here to Skip to main content

Filtering a Sampled Signal Using FIR Filters in a Morsecode Translator

, 19 Dec 2010
Rate this:
Please Sign up or sign in to vote.
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.

FIR_block.jpg

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.

Morse_Rx.jpg

Morse Received

Morse_noise.jpg

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.

BP_wave.jpg BS_wave.jpg

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

BP_Imp.jpg BS_Imp.jpg

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.

Further detail of using Directx to communicate with the sound card can be found in my PPM meters project.

//
//    ' 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
         
// Read the audio buffer
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.

History

  • Version 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nigel Ealand
Engineer BBC News
United Kingdom 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/.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberBen_126-Dec-12 14:34 
QuestionOoops PinmemberPeter Hawke29-Dec-11 11:45 
QuestionIs their source code? PinmemberPeter Hawke27-Dec-11 13:48 
QuestionFIR? PinmemberVaclav_Sal2-Jul-11 16:10 
AnswerRe: FIR? PinmemberNigel Ealand2-Jul-11 22:13 
Generalsaladin Pinmembersaladin19848-Jan-11 22:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140718.1 | Last Updated 20 Dec 2010
Article Copyright 2010 by Nigel Ealand
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid