Forum: GNU Radio MSK Loopback question

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
27205589a693e406b58b2f3c8bba817a?d=identicon&s=25 Dan Tarr (Guest)
on 2009-03-24 17:45
(Received via mailing list)
Hi Everyone,

I apologize ahead of time if this question seems stupid or if the answer
already exists somewhere and I haven't been able to find it. I am
with a group that is attempting to recreate a 56kb/sec RF Modem
operating at 29MHz using Minimum Frequency Shift Keying. The end goal is
have the modem we are building using gnuradio and the usrp to
with one of the original hardware modems. As a proof of concept, I am
attempting to have my gnuradio code loopback on itself, to show that the
modulation-to-demodulation works as expected. I am attempting to do this
simply reading from a file, modulating, passing it through a channel
demodulating, and writing to a new file. The problem I am encountering
that the write data comes out as garbage, and I'm not sure what I'm
wrong. Here is the test code that I am trying to run:
from gnuradio import gr, gru, blks2
from gnuradio import usrp
from gnuradio import eng_notation
import copy
import sys
from gmsk import gmsk_demod

class my_top_block(gr.top_block):
    def __init__(self):

    self._file_name = 'testdata.dat'
    self.src = gr.file_source(gr.sizeof_char, self._file_name, False)
    self.unpacker = gr.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST)
    self.mod = gr.cpfsk_bc(.5, 1, 2) #Modulation index = .5 for MSK, 1
per symbol for BFSK, 2 samples per symbol
    self.chanmod = blks2.channel_model()
    #self.demod = gmsk_demod(2)
    self.demod = gr.quadrature_demod_cf(1)
    self.dec = gr.keep_one_in_n(gr.sizeof_float, 2) #2 Samples Per
    self.slicer = gr.binary_slicer_fb()
    self.repack = gr.unpacked_to_packed_bb(1, gr.GR_LSB_FIRST)
    self.out = gr.file_sink(gr.sizeof_char, 'outdata.dat')
    self.out2 = gr.file_sink(gr.sizeof_char, 'testout.dat')
    self.connect(self.src, self.unpacker, self.mod, self.chanmod,
self.demod, self.dec, self.slicer, self.repack, self.out)
    #self.connect(self.src, self.unpacker, self.repack, self.out)

if __name__ == '__main__':
    tb = my_top_block()
    except KeyboardInterrupt:

I originally tried this code, as seen from the commented section, using
demodulation method from gmsk included in blks2, as per my understanding
that demodulating a gmsk signal would be the same as an msk signal. When
this did not work correctly, I then searched the boards and found that
demodulating a BFSK signal had been done using the method I show above,
I'm still recieving incorrect data on the write side. I would really
appreciate any help on this, as I've been trying to solve it on my own
no success. The testfile 'testdata.dat' consists of a single line of
'This is a test file for GNU Radio'. Below are some examples of the
data that I have captured.
Run 1: Sensitivity = 1, Keep-N-In-One = 2

 ZÚ HÚ H  ]Ù   Y [  Ù  È S  T YÚ

Run 2: Sensitivity = 20, Keep-N-In-One = 2

 ZÚ HÚ H  ]Ù   Y [  Ù  È S  T YÚ

Run 3: Sensitivity = 1, Keep-N-In-One = 3

Ã<< ª "EURO £Š Õ) EURO  a3 #Õ

Run 4: Sensitivity =1, Keep All samples
g  g çá  a çá  a    æg çá æ    g   g     ç  á  á   ff   af   g ç


Thanks again for any help on this, I'm basically hitting my head against
brick wall.

D0072e69d706bb3ca211d33a1b536e2c?d=identicon&s=25 Johnathan Corgan (Guest)
on 2009-03-24 18:42
(Received via mailing list)
On Tue, 2009-03-24 at 11:59 -0400, Dan Tarr wrote:

> Thanks again for any help on this, I'm basically hitting my head against a brick wall.

What is happening is that the data coming out of the demodulator no
longer has the same byte boundaries as the data going into the
modulator.  Your output files are bit-shifted. In your script using the
quadrature demodulator, just take out the channel model.  It will work
(I've verified this.)

The channel model contains a block (the fractional interpolator) that
can delay outputting samples during startup, that is, it might eat a few
bits on the input before it starts outputting samples.  So, when you
have the channel model in place, the slicer bits are missing the first
four bits, and the repacker is placing the next four bits at the start
of the byte.

So that will get your artificial example working, but also understand
that during "real" reception, your receiver will need to handle
arbitrary bit offsets like this.  Generally, in data transmission
systems, this is handled by having a frame sync word or flag, which,
when detected, indicates the next bit is the start of the data boundary.

By the way, I debugged this by attaching file sinks to each of the
blocks in your flowgraph and viewing them using Octave, where it became
obvious what was happening.

This topic is locked and can not be replied to.