Saturday, August 17, 2024

Overview of FIR Filter Blocks & Usage in GNURadio

GNURadio provides several wrapper functions to take the pain out of Finite Impulse Response (FIR) Filter design, but some background information is required to fully understand what is going on behind the scenes and to use the wrapper functions to their full potential.

In this brief review, we will talk about Low Pass Filters, but the discussion is applicable to all the supported filter types: Low Pass, High Pass, Band Pass, Band Reject.

 

Filter Design Parameters

To design a filter, you first need the design parameters or goals. Figure 1 shows a basic filter response and the usual goals.

Figure 1 - To design a filter, you first need a set of design goals, then you can fit the minimum complexity filter to the goals. Above are the GNURadio Standard Definitions for a FIR Filter.

Sometimes the filter terms are different, such as a “Shape Factor” will be specified instead of a “Transition Band” but these terms may be expressed as any other term to fit the above GNURadio standard definitions.

 

GNURadio FIR Filter Design Methodology

There are a multitude of ways to design FIR Filters, GNURadio uses the Window Function methodology which bases the filter response on a supplied Window function. The Window functions are the same ones used in windowing data before a FFT, because they are well known and understood [1][2]. 

 

GNURadio's Convenience Filter Blocks

If you look at the Blocks -> Core -> Filters in GNURadio Companion you will see these basic filter types listed,

Low Pass Filter

High Pass Filter

Band Pass Filter

Band Reject Filter

These are the simplest and easiest filters to get going quickly in a flowgraph. They implement a wrapper function around the low level “Decimating FIR Filter” block. These simplified filters are decimating as that is the most commonly used functionality with GNURadio. If a Decimation is specified, first your signal is filtered by your specified filter parameters, then the signal is decimated. Be sure your filter adequately filters the input signal to a bandwidth that is less than the resulting decimated sample rate to eliminate spurious out-of-band signals. If decimation is not required, just set it to 1 and no decimation will be done on the output stream.

The convenience filter blocks have all the parameters needed to design a decent filter included in the block definition (Figure 2).

Figure 2 - The Low Pass Filter Block Parameter. The Frequencies are in Hz, the Window type and Beta is described later. For general defaults they are fine lest as is.

However, you might notice one filter parameter that is shown in figure 1 that appears to be missing, namely the: “Stop Band Attenuation”. The Stop Band Attenuation is not missing, but it has been “wrapped away” for simplicity. The trouble is that the implicit Stop Band Attenuation that is used for any given window is hidden deep in the GNURadio API documentation. Figure 3 shows what the Documentation has to say about this.


 

Figure 3 - The upper figure is the API documentation for the max_attenuation() function. The bottom figure contains specific detail on the GNURadio windows.

In the code when these wrapper functions are used, a function named max_attenuation() is called and given the specified window type (figure 3 upper).

This function then looks at an enumeration called win_type to retrieve the default stop band attenuation values (figure 3 lower).

The specific window data is the missing piece of the puzzle. Out of the window types shown in figure 3 lower, for these wrapped filter functions you can choose four standard windows (figure 4), with the given stop band attenuation.

  • Hamming - Stopband Attenuation is: 53 dB
  • Hann - Stopband Attenuation is: 44 dB
  • Blackman - Stopband Attenuation is: 74 dB
  • Rectangular - Stopband Attenuation is: 21 dB
  • Kaiser -  
If Beta = 4.55, Stopband Attenuation is: 50 dB
If Beta = 6.76, Stopband Attenuation is: 70 dB
 
For other stopband attenuations greater than 50 dB, you can calculate a Beta based on the following formula,
Beta = 0.1102 * ( stopband_attenuation_dB - 8.7 )

Figure 4 - The basic filter block provides 4 widow types. The Kaiser window is adjustable using the Beta factor as described later.

The default Hamming Window is a good choice for most over the air demodulation tasks and RTL based receiver USB sticks.. Rarely will you ever have a signal-to-noise ratio that is so large that 53 dB attenuation is insufficient. If you want some more optimization, then the Kaiser window offers it. A 90 dB attenuation filter can be specified by using a Kaiser Window with a Beta equal to 8.96.

 

Frequency Translation Filter

The Frequency Translation Filter (FTF) or, Channelizing filter is a very common filter in SDR design (figure 5, and reference 3). It allows a portion of the sampled RF bandwidth to be selected and brought down to baseband for further processing.


 

Figure 5 - Frequency Translating Filter, or Channelizer. This block does not have filter parameter specifications directly, but rather has a field called 'Taps' that expects a list of FIR filter taps.

As shown in Figure 5, the FTF filter lacks any sort of filter definitions but instead has a field called ‘Taps’. In this field, there needs to be a list of filter taps that define the FIR filter. Don’t fret, GNURadio provides another set of wrapper blocks that provide the required list for you (figure 6). 


Figure 6 - GNURadio provides various 'Taps' blocks. These blocks are a wrapper around an even lower level call to a C++ function that is described below. The 'Filter Taps Loader' is a special block that can read filter Taps from a text file.

Typically, the FTF filter consists of two types: a Complex Bandpass filter for Complex IO, and a Real Low Pass Filter for Real IO. Figure 7 shows the familiar filter specification fields as the other filters. 

Figure 7 - The parameters for a given Taps block. Since this block is a bandpass filter the specifications are slightly different than for a low pass filter because you can specify the low and high cutoff frequencies independently.

All that needs to be done to use the Taps Filter Block is, give the Filter Taps Block some ID name (or use the default), then paste this same name in the ‘Taps’ field of the FTF block as shown in figure 8.

 Figure 8 - To use any of the Filter Taps Blocks, be sure to give it a name and paste that same name in the Filter Block 'Taps' field as shown above.

 

Base Filter Functions

Below these Taps wrapper blocks are a series of functions called firdes.xxxx() as shown in figure 9.

firdes.band_pass(), firdes.band_pass_2()

firdes.band_reject(), firdes.band_reject2()

firdes.complex_band_pass(), firdes.complex_band_pass_2()

firdes.complex_band_reject(), firdes.complex_band_reject_2()

firdes.gaussian() 

firdes.high_pass()

firdes.high_pass()

firdes.hilbert()

firdes.low_pass(), firdes.low_pass2()

firdes.root_raised_cosine()

Figure 9 - firdes() functions available. These functions take various parameters and produce a list of taps. These functions may be directly inserted in the "Taps" field of any block.

You can use the appropriate firdes functions in any Taps field and the proper taps will be generated at runtime. The firdes functions take various parameters which describe the filter just like the filter blocks as described above. You can access the current documentation by clicking on the reference 4 links below.

To use a firdes function you can fill in the proper fields [4] the paste the function call directly in the 'Taps' field. A definition that has the same functionality as the Taps Block in figure 8 is shown below,

firdes.complex_band_pass(1, samp_rate, -5000, 5000, 500, window.win_type.WIN_HAMMING, 6.76)

Using Raw Taps Lists

You can also use a raw Python list of Taps in any Taps field. These taps may be generated by any suitable FIR filter design program, such as the GNU Radio Supplied Filter Design Tool.

Note: As of GNURadio version 3.10.10, the Filter Design Tool is not properly working for Kaiser Window based filters. Specifically, it is incorrectly calculating the attenuation based on the GUI input value.

To use the Filter Design Tool, simply enter your desired parameters, press the "Design” button and inspect the results.

The Filter Designer GUI has a “Filter Coefficients” tab, there you can cut and directly paste the list into the “Taps” field of the GNU Radio Block.

taps=0.015155321023725285,0.027219656578798622,

0.029870991728012164,0.01184698593945574,-0.021991794902241332,

-0.05036266878604228,-0.05031691165541314,-0.018823427291265682,

0.018756485040462168,0.026013593755063666

The above text shows the Example Filter Coefficients cut directly from the Filter Designer GUI “Filter Coefficients” tab.

[0.015155321023725285,0.027219656578798622,0.029870991728012164,

0.01184698593945574,-0.021991794902241332,-0.05036266878604228,

-0.05031691165541314,-0.018823427291265682,0.018756485040462168,

0.026013593755063666]

Before Pasting the raw filter coefficients in any ‘Taps’ field, first remove the leading "taps = " text, then surround the entire list with the Python notation for a list, namely square brackets: [] as shown in the lower text example above. This modified text can then be inserted into the Taps field of any filter type that offers it.

Note: FIR Filter Taps usually consist of fifty to sometimes hundreds of coefficients, not the few shown above for simplicity.

 

Bonus

If you want to visualize your filter in GNURadio, you can use the 'Cookbook Idea' presented here,

https://gnuradio-cookbook.blogspot.com/2024/08/using-gnuradio-companion-to-visualize.html


References

[1] Window Reference Information: https://en.wikipedia.org/wiki/Window_function

[2] List of GNU Radio Windows: https://www.gnuradio.org/doc/doxygen/classgr_1_1fft_1_1window.html

[3] Frequency Translating Filter GNURadio documentation: https://wiki.gnuradio.org/index.php/Frequency_Xlating_FIR_Filter/

[4] firdes API Documentation: https://www.gnuradio.org/doc/doxygen/classgr_1_1filter_1_1firdes.html

firdes Github Code Repository: https://github.com/gnuradio/gnuradio/blob/main/gr-filter/lib/firdes.cc


No comments:

Post a Comment