L11 Lab — Custom Block#
Custom Block
Build and test the course module, set the Energy Detector for a noisier signal, and write a Key Timer block of your own.
L11 Lab · Module 5: Custom Blocks & Midterm · Dr. Neil Rogers
Learning Objectives
- I can create a GNU Radio out-of-tree (OOT) module and add a custom Python block to it.
- I can implement a custom signal-processing block from scratch and integrate it into a GNU Radio flowgraph.
From Lesson to Bench
Pre-Lab: check your tools and work out the Morse timing at 15 WPM.
Bench: build
gr-ece448, set the levels from the plot, then write and time a Key Timer.Writeup: explain hysteresis and timing, and what a Morse decoder needs.
Lesson 11 packaged the Energy Detector in an out-of-tree module. Today you build and test that module on your own laptop, set the detector’s levels for a noisier signal than the lesson used, and then make a module of your own from an empty gr_modtool template and write a second block in it, the Key Timer, which measures how long each key-down and key-up lasts, the lengths Lesson 12’s Morse decoder needs.
The lab packet has three parts, and you turn it in once, complete, before the midterm. Part 1, the Pre-Lab, is on your own before the period. Part 2 is your own work in class, and Part 3, the Writeup, explains it. Nothing in this lab transmits: every flowgraph is a simulation on your laptop.
Part 1: Before the Period
Check that
gr_modtoolandcmakerun, and choose your route.Run
L11-keyed-carrier-epy.grc, which needs nothing installed.Work out the Morse timing at 15 WPM.
At the radioconda prompt, run gnuradio-config-info --version, gr_modtool --help, and cmake --version. If cmake is missing, run conda install -c conda-forge gnuradio-build-deps; on macOS, also run xcode-select --install once. Question 2 asks for the length of each Morse element at 15 words per minute, where one unit lasts \(1.2/15\) s, how long one sending of “ECE” lasts and how many points that is at 1 kHz, and how many detector outputs a dit spans. You read the Energy Detector’s levels off its Power plot at the bench.
Two Routes
Laptop |
Route |
|---|---|
Linux |
build both modules with CMake |
macOS |
the same, untested on a Mac |
Windows |
WSL2 with Ubuntu 24.04, then build both modules |
Windows, no WSL2 |
Embedded Python Blocks |
A Python-only module still runs CMake, and CMake needs a C++ compiler, which radioconda does not include, and which gnuradio-build-deps cannot supply by itself on Windows. On Windows, install WSL2 with Ubuntu 24.04, run sudo apt install gnuradio-dev cmake g++ inside it, and follow the Ubuntu steps; WSLg opens GRC in a window. Without WSL2, use L11-keyed-carrier-epy.grc for the Energy Detector, and write the Key Timer in an Embedded Python Block: GRC’s Python Block, with the class renamed blk. The code is the same in both routes. Questions 3(a) and 5 still need a real module and ctest, so as a last resort build those on a teammate’s Linux, macOS, or WSL2 laptop.
Part 2: Build and Test gr-ece448
Download
L11-gr-ece448.zipfrom the Lesson 11 page and unzip it. At the radioconda prompt,cdintogr-ece448.Check that the
gr_python_installline ofpython/ece448/CMakeLists.txtlistsenergy_detector.py.Run
mkdir build,cd build, andcmake -G Ninja -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_PREFIX_PATH=${CONDA_PREFIX} ... With Ubuntu’s own GNU Radio instead of radioconda, runcmake ..and usemakeandsudo make installbelow.Run
cmake --build ., thenctest --output-on-failure. Copy its output for Question 3(a).Run
cmake --install ., then close and restart GRC.Open and run
L11-keyed-carrier.grc. Double-click the Energy Detector and screenshot its properties dialog for Question 3(b).
Part 2: Set the Levels
In the running flowgraph, set the noise amplitude to 0.5.
Stop the flowgraph. Set the variable
wpmto 15, and set both Time Sinks’ Number of Points to one sending of “ECE” at 1 kHz, from your Question 2(b) answer. Run it again.Read the floor and the carrier-on level from the power plot, and note how far the floor wanders, for Question 4(a).
Set the threshold to the floor’s level and the hysteresis to 0, and watch the key.
Choose your own threshold and hysteresis so that the detected key follows the sent keying for at least 20 s. Record them and screenshot the window for Question 4(b). Save this flowgraph under a new name; Question 6 adds to it.
Part 2: Write the Key Timer
In a new directory, run
gr_modtool newmod l11lab, thencd gr-l11lab.Run
gr_modtool add -t sink -l python key_timer. Give your name as the copyright holder,rate=1000.0as the argument list, and answer yes to the Python QA code.In
python/l11lab/key_timer.py, setin_sig=[numpy.float32](the template importsnumpy), and write__init__(),work(),last_mark(),last_space(), andmark_count()to the specification in the packet’s Question 5.In
python/l11lab/qa_key_timer.py, replace the template’s test with one that feeds a known key from a Vector Source and checks all three methods.Fill in
grc/l11lab_key_timer.block.yml: a label, themaketemplate, onerealparameterrate, and onefloatinput.Check the
gr_python_installline listskey_timer.py. Then build, runctest, and install, as forgr-ece448, and restart GRC.
The Key Timer
Part |
What it is |
|---|---|
Type |
sink: one float input, no outputs |
Parameter |
|
Methods |
|
The Key Timer reads the Energy Detector’s key, a stream of 0s and 1s, and counts how many samples each run of 1s, a mark, and each run of 0s, a space, lasts. When the key changes, it converts the count to milliseconds with rate and keeps it as the last mark or the last space. Like the Energy Detector’s key state, the count must survive from one call of work() to the next, because a dah can span many calls.
Part 2: Time the Morse
Open your flowgraph from the Set the Levels steps. Add your Key Timer from the block library and connect the Energy Detector’s
keyoutput to it. Setratetosamp_rate / decim.Add three Function Probes, with Block ID your Key Timer’s ID, Function Names
last_mark,last_space, andmark_count, and a poll rate of 4 Hz.Add three QT GUI Labels that show the three probes, with GUI hints
3,0,1,1,3,1,1,1, and3,2,1,1.Run it. Watch the labels through several sendings and record the lengths you see for each element for Question 6(a). Screenshot the canvas and the window for Question 6(b).
Part 2: A Noisier Signal
Set the noise amplitude to 0.8. With 32 samples averaged, find the best threshold and hysteresis you can.
Stop the flowgraph, run it again, and record the Marks label after 30 s for Question 7(a).
Stop it, set the variable
decimto 128, and run it again. Watch how the floor on the power plot changes. Find your best settings again, and record the Marks label after 30 s and the dit length for Question 7(b).
If the Block Does Not Appear
Troubleshooting a Missing Block
CMake prints several warnings marked “for project developers” about policies and an old minimum version; they come from gr_modtool’s template and do not stop the build. Restart GRC after every install; it reads its block library only when it starts. Check that you ran CMake with -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} from the same radioconda prompt that runs GRC. A ModuleNotFoundError for your block means the gr_python_install line does not list its .py file; add it, then build and install again. A flowgraph with red arrows usually has a type mismatch: the Key Timer’s input must be float, to match the Energy Detector’s key output.
Part 3: After the Lab
Explain why hysteresis can lengthen a mark, and how a larger \(N\) smooths the floor but coarsens the timing.
Decide which blocks belong in a module.
Propose a rule that tells a dit from a dah at any speed.
The Writeup is three questions. The first explains why some marks read a millisecond or two long with hysteresis, and what the noisier signal showed about choosing the number of samples averaged. The second decides whether the Energy Detector and the Key Timer belong in a module or in Embedded Python Blocks for Lesson 12’s decoder, and what the unit test checks that the flowgraph cannot. The third proposes the timing rules a Morse decoder needs, which Lesson 12 builds.
Lab Packet
L11-gr-ece448.zip: the
gr-ece448module with the Energy Detector and its unit test.L11-keyed-carrier.grc: the keyed carrier through the installed Energy Detector. No hardware needed.
L11-keyed-carrier-epy.grc: the same flowgraph with the Energy Detector in an Embedded Python Block. Needs nothing installed.
Tutorials this lab follows, on the GNU Radio wiki:
Looking Ahead
Keep both modules installed and your flowgraph saved.
Lesson 12 decodes Morse from the key and its timing.
Keep gr-ece448, your own gr-l11lab, and your timed flowgraph. Lesson 12, on CW, receives Morse code: its receiver uses the Energy Detector to make the key and timing like the Key Timer’s to tell each dit from each dah.