summaryrefslogtreecommitdiff
path: root/docs/exploring-gnuradio/exploring_gnuradio.dox
blob: d762db443b35c24a3da26f8ff8a1816b53c0cb3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*! \page page_exploring_gnuradio Exploring GNU Radio

Let's explore over two examples that are shipped with GNU Radio. We
start off with a very simple dial tone generating example that is done
in Python. The second example uses both GNU Radio Companion (GRC) and
Python for different stages of the example.

In either case, we will be actually working with Python code and the
modules as they exist in Python. However, in the following discussion,
we will refer to each block using the full C++ namespace so that we
can easily link to the block's documentation inside the manual.

The example files discussed in this page are installed with the
documentation and are located in $prefix/share/doc/gnuradio-$version/.

\section ex_dial_tone Dial Tone Example

This example is found in the dial_tone.py file and constructs a very
simple GNU Radio application that combines two sine waves to create a
dial tone. It calls a function to construct the flowgraph which
handles generating the signal sources.

The build_graph function sets up the sampling rate, which we will use
to set the rate of the audio sink as well as the amplitude, which we
use to scale the signal to control the volume of the output. We then
create a top_block. The top_block is the object that holds the
flowgraph, the basic data structure of a GNU Radio application. We
will use the top_block to connect together and hold the signal
processing blocks, which we build next.

This example uses three signal processing blocks. The first two are
gr::analog::sig_source_f blocks, which generate sine waves at
frequencies 350 and 440 Hz. We next create the connection to the
speaker system using gr::audio::sink, which takes in the sample rate
it will use to produce the output signal. The audio sink block can
also take in a second parameter to set the output device name, which
we use if there is a resource conflict or if using a sampling rate
that the hardware won't naturally support. Common device names are
"pulse" if using PulseAudio or "plughw:0,0", which is an ALSA device
that can handle resampling.

We next take the three blocks we've built and connect together the
flowgraph. The flowgraph connects sources to sinks through other
signal processing blocks. Here, we are directly connecting two sources
to a single sink. The next example uses more complex flowgraphs to
further explore these concepts. The two lines containing the
"tb.connect" statements are where the connections are made. The
flowgraph will look like:

\verbatim
sig_source_f (freq = 350) -->
                              audio.sink
sig_source_f (freq = 440) -->
\endverbatim

We're inputting two signals into a single block, which with the audio
sink allows us to output in stereo. The two signals combine to form
the dual frequencies of a standard dial tone.

In the connection of the signal source to the audio sink, notice how
we specify the sink as a Python tuple, (dst, X). Technically, we
specify all connections as ((source block, port out), (sink block,
port in)) because each block that outputs samples can have multiple
output ports just as a block that receives samples can have multiple
input ports. However, in the case of a gr::analog::sig_source_f, it
only produces samples on a single output and so the output port of 0
is implied. Otherwise, we could write this as "tb.connect((src0, 0),
(dst,0))" for complete representation of the connection.

When we are done connecting the blocks, we have a flowgraph in the
object "tb". While it's connected, the sources are not generating any
samples. We have to start running the flowgraph. In the main section,
we return the top_block object and then call the "start" function on
it. This is a non-blocking call that launches the flowgraph's main
thread, which initiates the sources to start sending samples through
the flowgraph. We then block until the user presses "Enter" at which
point we call the flowgraph's "stop" function to shut it down.


\section ex_fm_demod FM Demodulator

This example can be done completely in GRC or both GRC and Python. We
will generate an FM signal using GRC first and then using either a GRC
program or an example in Python to demodulate and play it back.

\subsection Modulator

We first launch GRC using the terminal command
"gnuradio-companion". This starts the graphical interface to create
our flowgraphs. We won't explore the GRC interface here; just use it
to generate a data file. With GRC launched, open the file
"fm_tx.grc". Exploring this flowgraph, it generates the dial tone
frequencies, adds them together, resamples the signal so we can use
integer upsampling in the wideband FM transmitter block (WBFM
Transmit) and output the data. While this is happening, we're also
outputting the original signal to the audio system as well as viewing
it in time and frequency at different stages.

The intent of this example is to generate a frequency-modulated dial
tone signal and save it to a file. While saving it to a file, we only
want to generate a signal large enough to make use of it, but it doesn't
have to be too large. So we put a gr::blocks::head block that limits
the number of samples into the file sink. Once this block has seen N
number of samples, it will stop the flowgraph. Meanwhile, we use a
gr::blocks::skiphead block to ignore the first M samples, which helps
us avoid the transients and group delay of the filters in the system.

We run this either using the menu "Build->Execute" or using the play
button on the toolbar. It will run for a short amount of time and stop
once the head has seen the items set in the "nitems" parameter. The
result is a file "dummy.dat" that contains the complex FM samples.

\subsection Demodulator

The demodulator part is shown in both a GRC graph and as a Python
script. Both the GRC graph, "fm_rx.grc", and the Python script,
"fm_demod.py", do the same thing and basically reverse the stages of
the modulator. It uses a gr::blocks::file_source to read the
"dummy.dat" file we created previously. This is sent to the FM
demodulator, which is simply implemented here using the
gr::analog::quadrature_demod_cf. This demodulates the signal and
converts the complex FM signal to a float signal.

We then resample it from the input signal at 200 ksps to the audio
rate of 44.1 ksps. Because this resampling cannot be done using an
integer decimation rate, we use an arbitrary resampler, the
gr::filter::pfb_arb_resampler_fff block, that allows us to resample at
any rate as well as filter the signal to the audio rate we want. The
output of this block is filtered to a 15 kHz bandwidth at a sample
rate of 44.1 ksps, which is ready for the gr::audio::sink block.

Both the GRC and Python files can be explored further to better
understand the operations of the blocks.

*/