Simulation example: FSK

From GNU Radio
Revision as of 20:47, 5 March 2022 by Duggabe (talk | contribs) (clarified versions)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

GNU Radio (GR) is an excellent tool for simulating a radio system and experimenting with changing parameters. This tutorial presents a simple Frequency Shift Keying (FSK) transmitter and receiver. It can be performed with GR version 3.8 (and later). The Graphical User Interface gnuradio-companion (GRC) is used to create the flowgraph. The QT_GUI_Eye_Sink requires GR version 3.9 or later, but can be left out if using 3.8. No special hardware is required.


Simulating a transmitter and receiver[edit]

Using gnuradio-companion (GRC) and the following Block descriptions, build this flowgraph:

FSK example fg.png

This flowgraph can be found at Media:FSK_example.grc It was generated with version 3.10.

Setting variables and parameters[edit]

Most of the parameters can be set from the screenshot of the flowgraph.

  • The Options block identifies the filename for the flowgraph, a title, author, etc.
    • id: FSK_example
    • Click on File -> Save As  Use the file name 'FSK_example'. the extension '.grc' is added automatically

For this tutorial I am using the baud rate for Baudot Radioteletype. It is defined as a bit time of 22 milliseconds, so the baud rate is set to 1/0.022 giving 45.4545

The repeat factor is (int)(samp_rate*0.022)

For this flowgraph, the standard RTTY (radioteletype) tones of 2295Hz (Mark=1) and 2125Hz (Space=0) are generated by the VCO. The calculations for this follow:

  • Choosing a full-scale frequency of 2500Hz (vco_max) for an input of +1, the VCO Sensitivity = (2 * math.pi * 2500 / 1) = 15708   Any frequency greater than 2295Hz could be used. 2500Hz is a nice round number.
  • Looking at the output of the Virtual Source "xmt_data", a Mark = +1.0 and a Space = 0.0
  • The Space frequency of 2125Hz is created by vco_offset = (2125 / 2500) = 0.850 + (0.0 * 0.068)
  • The Mark frequency of 2295Hz is created by a vector of inp_amp = (1.0 * 0.068) + vco_offset = 0.918     which is (2295/2500).

The Frequency Xlating FIR Filter taps parameter is 'firdes.low_pass(1.0,samp_rate,1000,400)'. Note that the desired signal has a deviation of 170Hz. so this filter rejects adjacent channel signals.

Description of data flow[edit]

For each of the GR blocks, you can find a detailed description in Block Docs.


Following the flowgraph signal path, the Random Source generates byte values from 0 to 255. The Unpack K Bits produces each bit of the input as a separate byte with the value in the least significant bit. Since there is no hardware involved, a Throttle block is used to limit the flow through the system. See Sample_Rate_Tutorial#When_there_is_no_hardware_block.

The Virtual Sink and Virtual Source blocks are used in place of a direct connection in order to produce a cleaner looking flowgraph. If you wish, you can do direct connections of the corresponding Stream IDs.


The Frequency Xlating FIR Filter shifts the received signal to be centered around the Center Frequency - half way between the Mark and Space frequencies.

Although not really needed for this simple simulation without noise, the squelch will be needed for real-world reception of RTTY signals.

The Quadrature Demod block produces a signal which is positive for input frequencies above zero and negative for frequencies below zero. When this signal is fed to a Binary Slicer, the output is a byte of 1 or 0. This is our received data (unpacked).

A QT GUI Eye Sink has been added. It is used when tuning live signals to determine the correct center frequency.


How do we know that it's the original bit stream? To verify that, we'll compare it to the input bit stream, which we can do because this is a simulation and we have access to the transmitted data (Stream ID: "xmt_data"). Comparing these two directly shows us that the received signal is some number of bits behind because the transmitter and receiver chain has many blocks and filters which delay the signal. To compensate, we have to delay the transmitted bits by the same amount using the Delay block. Then you can adjust the delay to find the correct value and see how the bits synchronize. Also you can subtract one signal from the other to see when they are synchronized because the output will be 0. Note that it takes a few seconds for the delay to adjust before it can be seen in the output. The correct delay is 145.

FSK example out.png

Further study[edit]

If you would like to add the effects of channel impairments, try adding a Channel Model before the Squelch. See Guided_Tutorial_PSK_Demodulation#Adding_Channel_Impairments.

For a complete RTTY terminal unit, see Basic radioteletype transmit and receive functions.