Search code examples
gnuradiosoftware-defined-radio

GFSK demodulation with Xlating filter in GNU Radio


I have been trying to demodulate a GFSK signal for months now using GNU Radio with USRP B210. Unfortunately, I haven't found even a single decent book on GNU Radio and hence most of my references are based on some random websites including the official GNU Radio page.

The GFSK signal comes from a cubesat in the lab. At the moment, it is transmitting a '10101010 ...... ' test signal. The GFSK modulation index used is 0.6667 and the data rate is 9600 bps. My flowgraph, as shown in the diagram below, uses the GFSK demod block, which apparently doesnt have any documentation except its source code. Sensitivity is set at pi * modulation_index/samples_per_symbol. I have recorded a number of files sampled as 10x 20x 40x 80x and 160x the baud rate (9600). In both of these files, I was able to receive repeated groups of 0x55 and 0xAA as expected.Unfortunately, these groups were accompanied by some random bytes which I have no idea as to where they are coming from[my first guess is noise].

Serendipitously I was able to get a very decent output when I shifted the received signal from the USPR by 1000hz using frequence xlating fir filter for the signal that was sampled at 40x. Here is where some funny behaviors of gnuradio comes along. I use the slider to control the center frequence of the xlating filter so as to be able to change it from its default value (1000hz) to whatever value I want during runtime. When I change the value, the signal becomes less decent i.e. bit swapping, random bytes addition etc. I was expecting the signal to go back to normal when I slide back to 1000hz, which is quite weird.

Could anyone tell me why this happens? My flowgraph is given below. Feel free to point out errors that I have overlooked so far.

xlating fir filter taps : firdes.low_pass_2(1,samp_rate,cut_off, xlating_bw, xlating_attn)

[enter image description here]


Solution

  • First off: No, I can't explain the strange behaviour when sliding. However, changing the frequency offset will definitely lead to big frequency jumps in the signal to be decoded (that's why you're doing that, after all), and the structures in charge of recovering timing will not like that; that's kind of expected.

    Unfortunately, I haven't found even a single decent book on GNU Radio

    There is none. GNU Radio's been evolving rapidly, and so none of the people close to the development "core" circles had the time to write something like that.

    and hence most of my references are based on some random websites including the official GNU Radio page.

    Well, the official GNU Radio website certainly isn't random, but the right place to go!

    I'll refer to GNU Radio terms such as hierarchical block, connection etc from here; if you don't understand all of those, I'd recommend going through the official Guided Tutorials!

    the GFSK demod block, which apparently doesnt have any documentation except its source code

    Well, there's a documentation comment in the source code, which does get extracted by Sphynx; however, that documentation isn't visible in GRC. We need to work on that!

    However, the documentation comment is pretty verbose:

    Hierarchical block for Gaussian Minimum Shift Key (GFSK)
    demodulation.
    
    The input is the complex modulated signal at baseband.
    The output is a stream of bits packed 1 bit per byte (the LSB)
    
    Args:
        samples_per_symbol: samples per baud (integer)
        verbose: Print information about modulator? (bool)
        log: Print modualtion data to files? (bool)
    
    Clock recovery parameters.  These all have reasonble defaults.
    
    Args:
        gain_mu: controls rate of mu adjustment (float)
        mu: fractional delay [0.0, 1.0] (float)
        omega_relative_limit: sets max variation in omega (float, typically 0.000200 (200 ppm))
        freq_error: bit rate error as a fraction
        float: 
    

    Basically, you can fully adjust the parameters of the timing recovery and FM demodulator contained within the hierarchical block.

    Now, obviously, that did not work out for you this far! I think you should go ahead and recreate the hierarchical flow in a GRC graph:

    Reading the same source, you'll find

        self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)
    

    which means:

    As the hierarchical block that gfsk_demod is,

    • connect it's input port to the input of fmdemod,
    • connect fmdemod's output to the input of the clock_recovery, and then
    • take the output of the clock recovery block and convert it to discrete numbers (using the slicer).

    A few lines up in the source code you'll find how these are parameterized.

    I suggest you first feed in your RX signal to a "stock" Quadrature Demod block. Mathematically, that will take the input signal, and convert it to its phase velocity (i.e. the "momentaneous frequency" of each sample, expressed as multiples of the sampling rate). Visualize the output with a scope/time sink! Does it look right, i.e. do you see alternating "high" and "low" values, in a roughly Gaussian pulse shape?

    If that's the case, replicate the Muller&Mueller Clock Recovery block in GRC (or replace it with the new, shiny PFB clock recovery, which deals a lot better with real-world signals); does the output look right?

    Use "decimating FIR" to reduce the output rate by samples_per_symbol; does that still look like your original bit stream as "soft" values? If it does, binary slice the result.