Editing Guided Tutorial GNU Radio in Python

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
[[Category:Guided Tutorials]]
+
<. [[Guided_Tutorial_GRC|Previous: Working with GRC]]
 +
>. [[Guided_Tutorial_GNU_Radio_in_C++|Next: Programming GNU Radio in C++]]
 +
 
  
== <b>NOTE:</b> This tutorial has been deprecated in GR 3.8. ==
+
= Tutorial: Working with GNU Radio in Python =
  
 
== Objectives ==
 
== Objectives ==
Line 14: Line 16:
 
== Prerequisites ==
 
== Prerequisites ==
  
* Working Installation of GNU Radio 3.7
+
* Working Installation of GNU Radio 3.7.4 or later
 
* [[Guided_Tutorial_GRC|GRC Tutorial]] (Recommended)
 
* [[Guided_Tutorial_GRC|GRC Tutorial]] (Recommended)
 
* Familiar with Python
 
* Familiar with Python
Line 186: Line 188:
  
 
<syntaxhighlight lang="python" line="line">
 
<syntaxhighlight lang="python" line="line">
#!/usr/bin/env Python3
+
#!/usr/bin/env Python
 
from gnuradio import gr
 
from gnuradio import gr
 
from gnuradio import audio
 
from gnuradio import audio
Line 215: Line 217:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
#!/usr/bin/env python3
+
#!/usr/bin/env python
 
</syntaxhighlight>
 
</syntaxhighlight>
 
Tells the shell that this file is a Python file and to use the Python interpreter to run this file. Should always be included at the top to run from the terminal.
 
Tells the shell that this file is a Python file and to use the Python interpreter to run this file. Should always be included at the top to run from the terminal.
Line 319: Line 321:
  
 
<syntaxhighlight lang="python" line="line">
 
<syntaxhighlight lang="python" line="line">
#!/usr/bin/env python3
+
#!/usr/bin/env python2
 
# -*- coding: utf-8 -*-
 
# -*- coding: utf-8 -*-
 
+
##################################################
#
 
# SPDX-License-Identifier: GPL-3.0
 
#
 
 
# GNU Radio Python Flow Graph
 
# GNU Radio Python Flow Graph
# Title: if_else
+
# Title: If Else
# GNU Radio version: 3.8.0.0
+
# Generated: Thu Sep 13 11:39:57 2018
 
+
##################################################
from distutils.version import StrictVersion
 
  
 
if __name__ == '__main__':
 
if __name__ == '__main__':
Line 339: Line 337:
 
             x11.XInitThreads()
 
             x11.XInitThreads()
 
         except:
 
         except:
             print("Warning: failed to XInitThreads()")
+
             print "Warning: failed to XInitThreads()"
  
from PyQt5 import Qt
+
from PyQt4 import Qt
 +
from gnuradio import analog
 +
from gnuradio import blocks
 
from gnuradio import eng_notation
 
from gnuradio import eng_notation
 +
from gnuradio import gr
 
from gnuradio import qtgui
 
from gnuradio import qtgui
 +
from gnuradio.eng_option import eng_option
 
from gnuradio.filter import firdes
 
from gnuradio.filter import firdes
 +
from optparse import OptionParser
 
import sip
 
import sip
from gnuradio import analog
 
from gnuradio import blocks
 
from gnuradio import gr
 
 
import sys
 
import sys
import signal
+
import threading
from argparse import ArgumentParser
 
from gnuradio.eng_arg import eng_float, intx
 
 
import time
 
import time
import threading
 
 
from gnuradio import qtgui
 
from gnuradio import qtgui
 +
  
 
class if_else(gr.top_block, Qt.QWidget):
 
class if_else(gr.top_block, Qt.QWidget):
  
 
     def __init__(self):
 
     def __init__(self):
         gr.top_block.__init__(self, "if_else")
+
         gr.top_block.__init__(self, "If Else")
 
         Qt.QWidget.__init__(self)
 
         Qt.QWidget.__init__(self)
         self.setWindowTitle("if_else")
+
         self.setWindowTitle("If Else")
 
         qtgui.util.check_set_qss()
 
         qtgui.util.check_set_qss()
 
         try:
 
         try:
Line 381: Line 379:
  
 
         self.settings = Qt.QSettings("GNU Radio", "if_else")
 
         self.settings = Qt.QSettings("GNU Radio", "if_else")
 +
        self.restoreGeometry(self.settings.value("geometry").toByteArray())
 +
  
        try:
 
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
 
                self.restoreGeometry(self.settings.value("geometry").toByteArray())
 
            else:
 
                self.restoreGeometry(self.settings.value("geometry"))
 
        except:
 
            pass
 
 
 
         ##################################################
 
         ##################################################
 
         # Variables
 
         # Variables
Line 403: Line 395:
 
         self.probe = blocks.probe_signal_f()
 
         self.probe = blocks.probe_signal_f()
 
         self._freq_tool_bar = Qt.QToolBar(self)
 
         self._freq_tool_bar = Qt.QToolBar(self)
         self._freq_tool_bar.addWidget(Qt.QLabel('freq' + ": "))
+
         self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))
 
         self._freq_line_edit = Qt.QLineEdit(str(self.freq))
 
         self._freq_line_edit = Qt.QLineEdit(str(self.freq))
 
         self._freq_tool_bar.addWidget(self._freq_line_edit)
 
         self._freq_tool_bar.addWidget(self._freq_line_edit)
 
         self._freq_line_edit.returnPressed.connect(
 
         self._freq_line_edit.returnPressed.connect(
            lambda: self.set_freq(int(str(self._freq_line_edit.text()))))
+
        lambda: self.set_freq(int(str(self._freq_line_edit.text().toAscii()))))
 
         self.top_grid_layout.addWidget(self._freq_tool_bar)
 
         self.top_grid_layout.addWidget(self._freq_tool_bar)
 
         self._ampl_tool_bar = Qt.QToolBar(self)
 
         self._ampl_tool_bar = Qt.QToolBar(self)
         self._ampl_tool_bar.addWidget(Qt.QLabel('ampl' + ": "))
+
         self._ampl_tool_bar.addWidget(Qt.QLabel("ampl"+": "))
 
         self._ampl_line_edit = Qt.QLineEdit(str(self.ampl))
 
         self._ampl_line_edit = Qt.QLineEdit(str(self.ampl))
 
         self._ampl_tool_bar.addWidget(self._ampl_line_edit)
 
         self._ampl_tool_bar.addWidget(self._ampl_line_edit)
 
         self._ampl_line_edit.returnPressed.connect(
 
         self._ampl_line_edit.returnPressed.connect(
            lambda: self.set_ampl(int(str(self._ampl_line_edit.text()))))
+
        lambda: self.set_ampl(int(str(self._ampl_line_edit.text().toAscii()))))
 
         self.top_grid_layout.addWidget(self._ampl_tool_bar)
 
         self.top_grid_layout.addWidget(self._ampl_tool_bar)
 +
 
         def _variable_function_probe_0_probe():
 
         def _variable_function_probe_0_probe():
 
             while True:
 
             while True:
 
+
                 val = self.probe.level()
                 val = self.probe.get_number()
 
 
                 try:
 
                 try:
 
                     self.set_variable_function_probe_0(val)
 
                     self.set_variable_function_probe_0(val)
Line 430: Line 422:
  
 
         self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
 
         self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
            1024, #size
+
        1024, #size
            samp_rate, #samp_rate
+
        samp_rate, #samp_rate
            "", #name
+
        'QT GUI Plot', #name
            1 #number of inputs
+
        1 #number of inputs
 
         )
 
         )
 
         self.qtgui_time_sink_x_0.set_update_time(0.10)
 
         self.qtgui_time_sink_x_0.set_update_time(0.10)
Line 440: Line 432:
 
         self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
 
         self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
  
         self.qtgui_time_sink_x_0.enable_tags(True)
+
         self.qtgui_time_sink_x_0.enable_tags(-1, True)
 
         self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
 
         self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
 
         self.qtgui_time_sink_x_0.enable_autoscale(False)
 
         self.qtgui_time_sink_x_0.enable_autoscale(False)
Line 448: Line 440:
 
         self.qtgui_time_sink_x_0.enable_stem_plot(False)
 
         self.qtgui_time_sink_x_0.enable_stem_plot(False)
  
 +
        if not True:
 +
          self.qtgui_time_sink_x_0.disable_legend()
  
         labels = ['Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
+
         labels = ['', '', '', '', '',
            'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10']
+
                  '', '', '', '', '']
 
         widths = [1, 1, 1, 1, 1,
 
         widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
+
                  1, 1, 1, 1, 1]
         colors = ['blue', 'red', 'green', 'black', 'cyan',
+
         colors = ["blue", "red", "green", "black", "cyan",
            'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
+
                  "magenta", "yellow", "dark red", "dark green", "blue"]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
 
            1.0, 1.0, 1.0, 1.0, 1.0]
 
 
         styles = [1, 1, 1, 1, 1,
 
         styles = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
+
                  1, 1, 1, 1, 1]
 
         markers = [-1, -1, -1, -1, -1,
 
         markers = [-1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1]
+
                  -1, -1, -1, -1, -1]
 
+
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
 +
                  1.0, 1.0, 1.0, 1.0, 1.0]
  
         for i in range(1):
+
         for i in xrange(1):
 
             if len(labels[i]) == 0:
 
             if len(labels[i]) == 0:
 
                 self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
 
                 self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
Line 477: Line 470:
 
         self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
 
         self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
 
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
 
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
         self.analog_sig_source_x_0_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, freq, ampl, 0, 0)
+
         self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE, freq, ampl, 0)
         self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_SQR_WAVE, 0.1, 1, 0, 0)
+
         self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_SQR_WAVE, 0.1, 1, 0)
  
  
Line 486: Line 479:
 
         ##################################################
 
         ##################################################
 
         self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
 
         self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.analog_sig_source_x_0_0, 0), (self.qtgui_time_sink_x_0, 0))
+
         self.connect((self.analog_sig_source_x_1, 0), (self.qtgui_time_sink_x_0, 0))
 
         self.connect((self.blocks_throttle_0, 0), (self.probe, 0))
 
         self.connect((self.blocks_throttle_0, 0), (self.probe, 0))
  
Line 505: Line 498:
 
     def set_samp_rate(self, samp_rate):
 
     def set_samp_rate(self, samp_rate):
 
         self.samp_rate = samp_rate
 
         self.samp_rate = samp_rate
 +
        self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
 +
        self.blocks_throttle_0.set_sample_rate(self.samp_rate)
 +
        self.analog_sig_source_x_1.set_sampling_freq(self.samp_rate)
 
         self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
 
         self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
        self.analog_sig_source_x_0_0.set_sampling_freq(self.samp_rate)
 
        self.blocks_throttle_0.set_sample_rate(self.samp_rate)
 
        self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
 
  
 
     def get_freq(self):
 
     def get_freq(self):
Line 516: Line 509:
 
         self.freq = freq
 
         self.freq = freq
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
         self.analog_sig_source_x_0_0.set_frequency(self.freq)
+
         self.analog_sig_source_x_1.set_frequency(self.freq)
  
 
     def get_ampl(self):
 
     def get_ampl(self):
Line 524: Line 517:
 
         self.ampl = ampl
 
         self.ampl = ampl
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
         self.analog_sig_source_x_0_0.set_amplitude(self.ampl)
+
         self.analog_sig_source_x_1.set_amplitude(self.ampl)
 
 
  
  
 
def main(top_block_cls=if_else, options=None):
 
def main(top_block_cls=if_else, options=None):
  
     if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
+
    from distutils.version import StrictVersion
 +
     if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
 
         style = gr.prefs().get_string('qtgui', 'style', 'raster')
 
         style = gr.prefs().get_string('qtgui', 'style', 'raster')
 
         Qt.QApplication.setGraphicsSystem(style)
 
         Qt.QApplication.setGraphicsSystem(style)
Line 539: Line 532:
 
     tb.show()
 
     tb.show()
  
    def sig_handler(sig=None, frame=None):
+
     def quitting():
        Qt.QApplication.quit()
+
         tb.stop()
 
 
    signal.signal(signal.SIGINT, sig_handler)
 
    signal.signal(signal.SIGTERM, sig_handler)
 
 
 
    timer = Qt.QTimer()
 
    timer.start(500)
 
    timer.timeout.connect(lambda: None)
 
 
 
     def quitting():
 
         tb.stop()
 
 
         tb.wait()
 
         tb.wait()
     qapp.aboutToQuit.connect(quitting)
+
     qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
 
     qapp.exec_()
 
     qapp.exec_()
  
Line 564: Line 547:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
        def _variable_function_probe_0_probe():
+
      def _variable_function_probe_0_probe():
 
             while True:
 
             while True:
 
 
                 val = self.probe.level()
 
                 val = self.probe.level()
 
                 try:
 
                 try:
Line 577: Line 559:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
    def set_freq(self, freq):
+
  def set_freq(self, freq):
 
         self.freq = freq
 
         self.freq = freq
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
         self.analog_sig_source_x_0_0.set_frequency(self.freq)
+
         self.analog_sig_source_x_1.set_frequency(self.freq)
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 586: Line 568:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
    def set_ampl(self, ampl):
+
  def set_ampl(self, ampl):
 
         self.ampl = ampl
 
         self.ampl = ampl
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
         self.analog_sig_source_x_0_0.set_amplitude(self.ampl)
+
         self.analog_sig_source_x_1.set_amplitude(self.ampl)
 
</syntaxhighlight>
 
</syntaxhighlight>
 
We can see that the functions set_ampl and set_freq can be used for just that - setting the amplitude and the frequency. Thus we can go back and modify our probe function with the if-else statement to give power to our friend.
 
We can see that the functions set_ampl and set_freq can be used for just that - setting the amplitude and the frequency. Thus we can go back and modify our probe function with the if-else statement to give power to our friend.
Line 595: Line 577:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
        def _variable_funct ion_probe_0_probe():
+
      def _variable_function_probe_0_probe():
 
             while True:
 
             while True:
 
 
                 val = self.probe.level()
 
                 val = self.probe.level()
 
                 print val
 
                 print val
Line 613: Line 594:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Now there is one more thing we need to take care of. GRC has compiled the python file in the order of creation of the elements, which was okay as long as there were no crossreferences. With the introduced adaptation (calling set_ampl and set_freq inside the _variable_function_probe_0_probe()) we need to fix the order of declarations. As set_ampl and set_freq both modify parameters of analog_sig_source_x_0_0 but analog_sig_source_x_0_0 is not instantiated before line  150, we have to move the declaration of the _variable_function_probe_0_probe() and everything related below that.
+
Now there is one more thing we need to take care of. GRC has compiled the python file in the order of creation of the elements, which was okay as long as there were no crossreferences. With the introduced adaptation (calling set_ampl and set_freq inside the _variable_function_probe_0_probe()) we need to fix the order of declarations. As set_ampl and set_freq both modify parameters of analog_sig_source_x_1 but analog_sig_source_x_1 is not instantiated before line  150, we have to move the declaration of the _variable_function_probe_0_probe() and everything related below that.
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
Line 627: Line 608:
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
#!/usr/bin/env python3
+
#!/usr/bin/env python2
 
# -*- coding: utf-8 -*-
 
# -*- coding: utf-8 -*-
 
+
##################################################
#
 
# SPDX-License-Identifier: GPL-3.0
 
#
 
 
# GNU Radio Python Flow Graph
 
# GNU Radio Python Flow Graph
# Title: if_else
+
# Title: If Else
# GNU Radio version: 3.8.0.0
+
# Generated: Thu Sep 13 11:39:57 2018
 
+
##################################################
from distutils.version import StrictVersion
 
  
 
if __name__ == '__main__':
 
if __name__ == '__main__':
Line 647: Line 624:
 
             x11.XInitThreads()
 
             x11.XInitThreads()
 
         except:
 
         except:
             print("Warning: failed to XInitThreads()")
+
             print "Warning: failed to XInitThreads()"
  
from PyQt5 import Qt
+
from PyQt4 import Qt
 +
from gnuradio import analog
 +
from gnuradio import blocks
 
from gnuradio import eng_notation
 
from gnuradio import eng_notation
 +
from gnuradio import gr
 
from gnuradio import qtgui
 
from gnuradio import qtgui
 +
from gnuradio.eng_option import eng_option
 
from gnuradio.filter import firdes
 
from gnuradio.filter import firdes
 +
from optparse import OptionParser
 
import sip
 
import sip
from gnuradio import analog
 
from gnuradio import blocks
 
from gnuradio import gr
 
 
import sys
 
import sys
import signal
+
import threading
from argparse import ArgumentParser
 
from gnuradio.eng_arg import eng_float, intx
 
 
import time
 
import time
import threading
 
 
from gnuradio import qtgui
 
from gnuradio import qtgui
 +
  
 
class if_else(gr.top_block, Qt.QWidget):
 
class if_else(gr.top_block, Qt.QWidget):
  
 
     def __init__(self):
 
     def __init__(self):
         gr.top_block.__init__(self, "if_else")
+
         gr.top_block.__init__(self, "If Else")
 
         Qt.QWidget.__init__(self)
 
         Qt.QWidget.__init__(self)
         self.setWindowTitle("if_else")
+
         self.setWindowTitle("If Else")
 
         qtgui.util.check_set_qss()
 
         qtgui.util.check_set_qss()
 
         try:
 
         try:
Line 689: Line 666:
  
 
         self.settings = Qt.QSettings("GNU Radio", "if_else")
 
         self.settings = Qt.QSettings("GNU Radio", "if_else")
 +
        self.restoreGeometry(self.settings.value("geometry").toByteArray())
  
        try:
 
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
 
                self.restoreGeometry(self.settings.value("geometry").toByteArray())
 
            else:
 
                self.restoreGeometry(self.settings.value("geometry"))
 
        except:
 
            pass
 
  
 
         ##################################################
 
         ##################################################
Line 711: Line 682:
 
         self.probe = blocks.probe_signal_f()
 
         self.probe = blocks.probe_signal_f()
 
         self._freq_tool_bar = Qt.QToolBar(self)
 
         self._freq_tool_bar = Qt.QToolBar(self)
         self._freq_tool_bar.addWidget(Qt.QLabel('freq' + ": "))
+
         self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))
 
         self._freq_line_edit = Qt.QLineEdit(str(self.freq))
 
         self._freq_line_edit = Qt.QLineEdit(str(self.freq))
 
         self._freq_tool_bar.addWidget(self._freq_line_edit)
 
         self._freq_tool_bar.addWidget(self._freq_line_edit)
 
         self._freq_line_edit.returnPressed.connect(
 
         self._freq_line_edit.returnPressed.connect(
            lambda: self.set_freq(int(str(self._freq_line_edit.text()))))
+
        lambda: self.set_freq(int(str(self._freq_line_edit.text().toAscii()))))
 
         self.top_grid_layout.addWidget(self._freq_tool_bar)
 
         self.top_grid_layout.addWidget(self._freq_tool_bar)
 
         self._ampl_tool_bar = Qt.QToolBar(self)
 
         self._ampl_tool_bar = Qt.QToolBar(self)
         self._ampl_tool_bar.addWidget(Qt.QLabel('ampl' + ": "))
+
         self._ampl_tool_bar.addWidget(Qt.QLabel("ampl"+": "))
 
         self._ampl_line_edit = Qt.QLineEdit(str(self.ampl))
 
         self._ampl_line_edit = Qt.QLineEdit(str(self.ampl))
 
         self._ampl_tool_bar.addWidget(self._ampl_line_edit)
 
         self._ampl_tool_bar.addWidget(self._ampl_line_edit)
 
         self._ampl_line_edit.returnPressed.connect(
 
         self._ampl_line_edit.returnPressed.connect(
            lambda: self.set_ampl(int(str(self._ampl_line_edit.text()))))
+
        lambda: self.set_ampl(int(str(self._ampl_line_edit.text().toAscii()))))
 
         self.top_grid_layout.addWidget(self._ampl_tool_bar)
 
         self.top_grid_layout.addWidget(self._ampl_tool_bar)
  
 
         self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
 
         self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
            1024, #size
+
        1024, #size
            samp_rate, #samp_rate
+
        samp_rate, #samp_rate
            "", #name
+
        'QT GUI Plot', #name
            1 #number of inputs
+
        1 #number of inputs
 
         )
 
         )
 
         self.qtgui_time_sink_x_0.set_update_time(0.10)
 
         self.qtgui_time_sink_x_0.set_update_time(0.10)
Line 736: Line 707:
 
         self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
 
         self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
  
         self.qtgui_time_sink_x_0.enable_tags(True)
+
         self.qtgui_time_sink_x_0.enable_tags(-1, True)
 
         self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
 
         self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
 
         self.qtgui_time_sink_x_0.enable_autoscale(False)
 
         self.qtgui_time_sink_x_0.enable_autoscale(False)
Line 744: Line 715:
 
         self.qtgui_time_sink_x_0.enable_stem_plot(False)
 
         self.qtgui_time_sink_x_0.enable_stem_plot(False)
  
 +
        if not True:
 +
          self.qtgui_time_sink_x_0.disable_legend()
  
         labels = ['Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
+
         labels = ['', '', '', '', '',
            'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10']
+
                  '', '', '', '', '']
 
         widths = [1, 1, 1, 1, 1,
 
         widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
+
                  1, 1, 1, 1, 1]
         colors = ['blue', 'red', 'green', 'black', 'cyan',
+
         colors = ["blue", "red", "green", "black", "cyan",
            'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
+
                  "magenta", "yellow", "dark red", "dark green", "blue"]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
 
            1.0, 1.0, 1.0, 1.0, 1.0]
 
 
         styles = [1, 1, 1, 1, 1,
 
         styles = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
+
                  1, 1, 1, 1, 1]
 
         markers = [-1, -1, -1, -1, -1,
 
         markers = [-1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1]
+
                  -1, -1, -1, -1, -1]
 
+
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
 +
                  1.0, 1.0, 1.0, 1.0, 1.0]
  
         for i in range(1):
+
         for i in xrange(1):
 
             if len(labels[i]) == 0:
 
             if len(labels[i]) == 0:
 
                 self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
 
                 self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
Line 773: Line 745:
 
         self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
 
         self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
 
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
 
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
         self.analog_sig_source_x_0_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, freq, ampl, 0, 0)
+
         self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE, freq, ampl, 0)
         self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_SQR_WAVE, 0.1, 1, 0, 0)
+
         self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_SQR_WAVE, 0.1, 1, 0)
  
 
         def _variable_function_probe_0_probe():
 
         def _variable_function_probe_0_probe():
 
             while True:
 
             while True:
 
 
                 val = self.probe.level()
 
                 val = self.probe.level()
                 print (val)
+
                 print val
 
                 if val == 1:
 
                 if val == 1:
 
                     self.set_ampl(1)
 
                     self.set_ampl(1)
Line 800: Line 771:
 
         ##################################################
 
         ##################################################
 
         self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
 
         self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.analog_sig_source_x_0_0, 0), (self.qtgui_time_sink_x_0, 0))
+
         self.connect((self.analog_sig_source_x_1, 0), (self.qtgui_time_sink_x_0, 0))
 
         self.connect((self.blocks_throttle_0, 0), (self.probe, 0))
 
         self.connect((self.blocks_throttle_0, 0), (self.probe, 0))
  
Line 819: Line 790:
 
     def set_samp_rate(self, samp_rate):
 
     def set_samp_rate(self, samp_rate):
 
         self.samp_rate = samp_rate
 
         self.samp_rate = samp_rate
 +
        self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
 +
        self.blocks_throttle_0.set_sample_rate(self.samp_rate)
 +
        self.analog_sig_source_x_1.set_sampling_freq(self.samp_rate)
 
         self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
 
         self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
        self.analog_sig_source_x_0_0.set_sampling_freq(self.samp_rate)
 
        self.blocks_throttle_0.set_sample_rate(self.samp_rate)
 
        self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
 
  
 
     def get_freq(self):
 
     def get_freq(self):
Line 830: Line 801:
 
         self.freq = freq
 
         self.freq = freq
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
 
         Qt.QMetaObject.invokeMethod(self._freq_line_edit, "setText", Qt.Q_ARG("QString", str(self.freq)))
         self.analog_sig_source_x_0_0.set_frequency(self.freq)
+
         self.analog_sig_source_x_1.set_frequency(self.freq)
  
 
     def get_ampl(self):
 
     def get_ampl(self):
Line 838: Line 809:
 
         self.ampl = ampl
 
         self.ampl = ampl
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
 
         Qt.QMetaObject.invokeMethod(self._ampl_line_edit, "setText", Qt.Q_ARG("QString", str(self.ampl)))
         self.analog_sig_source_x_0_0.set_amplitude(self.ampl)
+
         self.analog_sig_source_x_1.set_amplitude(self.ampl)
 
 
  
  
 
def main(top_block_cls=if_else, options=None):
 
def main(top_block_cls=if_else, options=None):
  
     if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
+
    from distutils.version import StrictVersion
 +
     if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
 
         style = gr.prefs().get_string('qtgui', 'style', 'raster')
 
         style = gr.prefs().get_string('qtgui', 'style', 'raster')
 
         Qt.QApplication.setGraphicsSystem(style)
 
         Qt.QApplication.setGraphicsSystem(style)
Line 852: Line 823:
 
     tb.start()
 
     tb.start()
 
     tb.show()
 
     tb.show()
 
    def sig_handler(sig=None, frame=None):
 
        Qt.QApplication.quit()
 
 
    signal.signal(signal.SIGINT, sig_handler)
 
    signal.signal(signal.SIGTERM, sig_handler)
 
 
    timer = Qt.QTimer()
 
    timer.start(500)
 
    timer.timeout.connect(lambda: None)
 
  
 
     def quitting():
 
     def quitting():
 
         tb.stop()
 
         tb.stop()
 
         tb.wait()
 
         tb.wait()
     qapp.aboutToQuit.connect(quitting)
+
     qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
 
     qapp.exec_()
 
     qapp.exec_()
  
Line 878: Line 839:
  
 
<pre>
 
<pre>
$ python3 if_else_mod.py
+
$ python if_else_mod.py
 
</pre>
 
</pre>
 
We should be able to see the numbers 0 and 1 on the terminal and the sine wave changing amplitude and frequency as the numbers change.
 
We should be able to see the numbers 0 and 1 on the terminal and the sine wave changing amplitude and frequency as the numbers change.
 +
 +
This tutorial is merely an introduction on using python in GNU Radio, for a more advanced tutorial see [[TutorialsWritePythonApplications]] .
  
 
== 3.2. Where Do Blocks Come From? ==
 
== 3.2. Where Do Blocks Come From? ==
Line 890: Line 853:
 
Before we begin, we need to figure out what the commands for gr_modtool are so let's ask for help.
 
Before we begin, we need to figure out what the commands for gr_modtool are so let's ask for help.
  
<pre>$ gr_modtool --help
+
<pre>$ gr_modtool help
Usage: gr_modtool [OPTIONS] COMMAND [ARGS]...
+
Usage:
 +
gr_modtool [options] -- Run  with the given options.
 +
gr_modtool help -- Show a list of commands.
 +
gr_modtool help  -- Shows the help for a given command.
  
  A tool for editing GNU Radio out-of-tree modules.
+
List of possible commands:
 
 
Options:
 
  --help  Show this message and exit.
 
 
 
Commands:
 
  add      Adds a block to the out-of-tree module.
 
  disable  Disable selected block in module.
 
  info      Return information about a given module
 
  makeyaml  Generate YAML files for GRC block bindings.
 
  newmod    Create new empty module, use add to add blocks.
 
  rename    Rename a block inside a module.
 
  rm        Remove a block from a module.
 
  update    Update the grc bindings for a block
 
 
 
  Manipulate with GNU Radio modules source code tree. Call it without
 
  options to run specified command interactively
 
  
 +
Name      Aliases          Description
 +
=====================================================================
 +
disable  dis              Disable block (comments out CMake entries for files)
 +
info      getinfo,inf      Return information about a given module
 +
remove    rm,del          Remove block (delete files and remove Makefile entries)
 +
makexml  mx              Make XML file for GRC block bindings
 +
add      insert          Add block to the out-of-tree module.
 +
newmod    nm,create        Create a new out-of-tree module
 
</pre>
 
</pre>
 
We immediately see there are many commands available. In this tutorial we will only cover '''newmod''' and '''add'''; however, the thorough explanation should enable smooth usage of the other gr_modtool commands without guidance.
 
We immediately see there are many commands available. In this tutorial we will only cover '''newmod''' and '''add'''; however, the thorough explanation should enable smooth usage of the other gr_modtool commands without guidance.
Line 917: Line 875:
  
 
<pre>
 
<pre>
$ gr_modtool newmod --help
+
$ gr_modtool help newmod
Usage: gr_modtool newmod [OPTIONS] MODULE-NAME
+
Usage: gr_modtool nm [options].
 
+
Call gr_modtool without any options to run it interactively.
  Create a new out-of-tree module
 
 
 
  The argument MODULE-NAME is the name of the module to be added.
 
  
 
Options:
 
Options:
   --srcdir TEXT            Source directory for the module template.
+
   General options:
  -d, --directory TEXT      Base directory of the module. Defaults to the cwd.
+
    -h, --help          Displays this help message.
  --skip-lib               Don't do anything in the lib/ subdirectory.
+
    -d DIRECTORY, --directory=DIRECTORY
  --skip-swig               Don't do anything in the swig/ subdirectory.
+
                        Base directory of the module. Defaults to the cwd.
  --skip-python            Don't do anything in the python/ subdirectory.
+
    -n MODULE_NAME, --module-name=MODULE_NAME
  --skip-grc               Don't do anything in the grc/ subdirectory.
+
                        Use this to override the current module's name (is
  --scm-mode [yes|no|auto]  Use source control management [ yes | no | auto ]).
+
                        normally autodetected).
  -y, --yes                 Answer all questions with 'yes'. This can
+
    -N BLOCK_NAME, --block-name=BLOCK_NAME
                            overwrite and delete your files, so be careful.
+
                        Name of the block, where applicable.
  --help                    Show this message and exit.
+
    --skip-lib         Don't do anything in the lib/ subdirectory.
 +
    --skip-swig         Don't do anything in the swig/ subdirectory.
 +
    --skip-Python      Don't do anything in the Python/ subdirectory.
 +
    --skip-grc         Don't do anything in the grc/ subdirectory.
 +
    --scm-mode=SCM_MODE
 +
                        Use source control management (yes, no or auto).
 +
    -y, --yes           Answer all questions with 'yes'. This can overwrite
 +
                        and delete your files, so be careful.
  
 +
  New out-of-tree module options:
 +
    --srcdir=SRCDIR    Source directory for the module template
 
</pre>
 
</pre>
 
Now that we have read over the list of commands for newmod, we can deduce that the one we want to pick is -n which is the default so we can simply type the MODULE_NAME after newmod. It is actually advised to avoid using "-n" as for other commands it can override the auto-detected name. For now, let's ignore the other options.
 
Now that we have read over the list of commands for newmod, we can deduce that the one we want to pick is -n which is the default so we can simply type the MODULE_NAME after newmod. It is actually advised to avoid using "-n" as for other commands it can override the auto-detected name. For now, let's ignore the other options.
Line 990: Line 954:
 
Adding file 'Python/qa_multiply_py_ff.py'...
 
Adding file 'Python/qa_multiply_py_ff.py'...
 
Editing Python/CMakeLists.txt...
 
Editing Python/CMakeLists.txt...
Adding file 'grc/tutorial_multiply_py_ff.yml'...
+
Adding file 'grc/tutorial_multiply_py_ff.xml'...
 
Editing grc/CMakeLists.txt...
 
Editing grc/CMakeLists.txt...
 
</pre>
 
</pre>
Line 1,097: Line 1,061:
  
 
if __name__ == '__main__':
 
if __name__ == '__main__':
     gr_unittest.run(qa_multiply_py_ff)
+
     gr_unittest.run(qa_multiply_py_ff, "qa_multiply_py_ff.xml")
 
</syntaxhighlight>
 
</syntaxhighlight>
 
gr_unittest adds support for checking approximate equality of tuples of float and complex numbers. The only part we need to worry about is the def test_001_t function. We know we need input data so let us create data. We want it to be in the form of a vector so that we can test multiple values at once. Let us create a vector of floats
 
gr_unittest adds support for checking approximate equality of tuples of float and complex numbers. The only part we need to worry about is the def test_001_t function. We know we need input data so let us create data. We want it to be in the form of a vector so that we can test multiple values at once. Let us create a vector of floats
Line 1,171: Line 1,135:
 
While we are here, we should take a break to change one of the numbers in the src_data to ensure that the block is actually checking the values and to simply see what an error looks like. Python allows for really quick testing of blocks without having to compile anything; simply change something and re-run the QA test.
 
While we are here, we should take a break to change one of the numbers in the src_data to ensure that the block is actually checking the values and to simply see what an error looks like. Python allows for really quick testing of blocks without having to compile anything; simply change something and re-run the QA test.
  
=== 3.2.5. YAML Files ===
+
=== 3.2.5. XML Files ===
  
At this point we should have written a Python block and a QA test for that block. The next thing to do is edit the YAML file in the grc folder so that we can get another step closer to using it in GRC. GRC uses the YAML files for all the options we see. We actually don't need to write any Python or C++ code to have a block display in GRC but of course if we would connect it, it wouldn't do anything but give errors. We should get out of the python folder and go to the grc folder where all the YAML files reside. There is a tool in gr_modtool called makexml but it is only available for C++ blocks. Let us open the tutorial_multiply_py_ff.xml file copied below:
+
At this point we should have written a Python block and a QA test for that block. The next thing to do is edit the XML file in the grc folder so that we can get another step closer to using it in GRC. GRC uses the XML files for all the options we see. We actually don't need to write any Python or C++ code to have a block display in GRC but of course if we would connect it, it wouldn't do anything but give errors. We should get out of the python folder and go to the grc folder where all the XML files reside. There is a tool in gr_modtool called makexml but it is only available for C++ blocks. Let us open the tutorial_multiply_py_ff.xml file copied below:
  
<syntaxhighlight lang="YAML" line="line">
+
<syntaxhighlight lang="XML" line="line">
id: tutorial_multiply_py_ff
+
<?xml version="1.0"?>
label: multiply_py_ff
+
<block>
category: '[tutorial]'
+
  <name>multiply_py_ff</name>
 +
  <key>tutorial_multiply_py_ff</key>
 +
  <category>tutorial</category>
 +
  <import>import tutorial</import>
 +
  <make>tutorial.multiply_py_ff($multiple)</make>
 +
  <!-- Make one 'param' node for every Parameter you want settable from the GUI.
 +
      Sub-nodes:
 +
      * name
 +
      * key (makes the value accessible as $keyname, e.g. in the make node)
 +
      * type -->
 +
  <param>
 +
    <name>...</name>
 +
    <key>...</key>
 +
    <type>...</type>
 +
  </param>
  
templates:
+
  <!-- Make one 'sink' node per input. Sub-nodes:
   imports: import tutorial
+
      * name (an identifier for the GUI)
   make: tutorial.multiply_py_ff(${multiple})
+
      * type
 +
      * vlen
 +
      * optional (set to 1 for optional inputs) -->
 +
   <sink>
 +
    <name>in</name>
 +
    <type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
 +
   </sink>
  
#  Make one 'parameters' list entry for every Parameter you want settable from the GUI.
+
   <!-- Make one 'source' node per output. Sub-nodes:
#    Sub-entries of dictionary:
+
      * name (an identifier for the GUI)
#    * id (makes the value accessible as \$keyname, e.g. in the make entry)
+
      * type
#    * label
+
      * vlen
#    * dtype
+
      * optional (set to 1 for optional inputs) -->
parameters:
+
   <source>
- id: ...
+
    <name>out</name>
   label: ...
+
    <type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
  dtype: ...
+
  </source>
- id: ...
+
</block></syntaxhighlight>
  label: ...
 
  dtype: ...
 
 
 
#  Make one 'inputs' list entry per input. Sub-entries of dictionary:
 
#      * label (an identifier for the GUI)
 
#      * domain
 
#      * dtype
 
#      * vlen
 
#      * optional (set to 1 for optional inputs)
 
inputs:
 
- label: ...
 
  domain: ...
 
  dtype: ...
 
  vlen: ...
 
 
 
Make one 'outputs' list entry per output. Sub-entries of dictionary:
 
#      * label (an identifier for the GUI)
 
#      * dtype
 
#      * vlen
 
#      * optional (set to 1 for optional inputs)  
 
- label: ...
 
   domain: ...
 
  dtype: ... #!-- e.g. int, float, complex, byte, short, xxx_vector, ...--
 
 
 
file_format: 1
 
</syntaxhighlight>
 
  
 
We can change the name that appears and the category it will appear in GRC. The category is where the block will be found in GRC. Examples of categories tag are '''Audio''' and '''Waveform Generators''' used in previous examples. Examples of names tag are the '''QT GUI Time Sink''' or the '''Audio Sink'''. Again, we can go through the file and find the modtool place holders. The first is copied below:
 
We can change the name that appears and the category it will appear in GRC. The category is where the block will be found in GRC. Examples of categories tag are '''Audio''' and '''Waveform Generators''' used in previous examples. Examples of names tag are the '''QT GUI Time Sink''' or the '''Audio Sink'''. Again, we can go through the file and find the modtool place holders. The first is copied below:
  
<syntaxhighlight lang="YAML" line="line">
+
<syntaxhighlight lang="XML" line="line">
Make one 'parameters' list entry for every Parameter you want settable from the GUI.
+
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
#    Sub-entries of dictionary:
+
      Sub-nodes:
#    * id (makes the value accessible as \$keyname, e.g. in the make entry)
+
      * name
#    * label
+
      * key (makes the value accessible as $keyname, e.g. in the make node)
#    * dtype
+
      * type -->
 
</syntaxhighlight>
 
</syntaxhighlight>
 
This is referring to the parameter that we used in the very beginning when creating our block: the variable called "multiple". We can fill it in as below:
 
This is referring to the parameter that we used in the very beginning when creating our block: the variable called "multiple". We can fill it in as below:
  
<syntaxhighlight lang="YAML" line="line">   
+
<syntaxhighlight lang="XML" line="line">   
parameters:
+
  <param>
- id: multiple
+
    <name>Multiple</name>
  label: Multiple
+
    <key>multiple</key>
   dtype: float
+
    <type>float</type>
 +
   </param>
 
</syntaxhighlight>
 
</syntaxhighlight>
The next placeholder can be found in the inputs and outputs tags:
+
The next placeholder can be found in the sink and source tags:
  
<syntaxhighlight lang="YAML" line="line">   
+
<syntaxhighlight lang="XML" line="line">  
inputs:
+
  <sink>
- label: in
+
    <name>in</name>
  dtype: float
+
    <type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
 
+
  </sink>
outputs:
 
- label: out
 
  dtype: float #!-- e.g. int, float, complex, byte, short, xxx_vector, ...--
 
 
</syntaxhighlight>
 
</syntaxhighlight>
We can see that it is asking for a type so we can simply erase everything in the tag and replace it with "float" for both the source and the sink blocks. That should do it for this block. The best way to get more experience writing YAML files is to look at the source code of previously made blocks such as the existing multiple block. Let's go back to this and use the documentation tag!
+
We can see that it is asking for a type so we can simply erase everything in the tag and replace it with "float" for both the source and the sink blocks. That should do it for this block. The best way to get more experience writing xml files is to look at the source code of previously made blocks such as the existing multiple block. Let's go back to this and use the documentation tag!
  
 
=== 3.2.6. Installing Python Blocks ===
 
=== 3.2.6. Installing Python Blocks ===
Line 1,610: Line 1,566:
 
1. How do we set input- and output signatures in Python blocks?<br />
 
1. How do we set input- and output signatures in Python blocks?<br />
 
2. Consider this I/O signature: (FIXME). Which input types and output types does it take?
 
2. Consider this I/O signature: (FIXME). Which input types and output types does it take?
 +
 +
=== 3.4.2. Links to Further Information ===
 +
 +
* [http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide Blocks Coding Guide]
 +
* [http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules Out-of-Tree Modules]
 +
* [http://gnuradio.org/redmine/projects/gnuradio/wiki/TutorialsWritePythonApplications Writing Python Applications]
  
 
== 3.5. Candidates for Future Sections ==
 
== 3.5. Candidates for Future Sections ==
Line 1,616: Line 1,578:
 
- How to add documentation to blocks<br />
 
- How to add documentation to blocks<br />
 
- Constructor arguments, History, Output Multiple
 
- Constructor arguments, History, Output Multiple
 +
 +
 +
-----
 +
 +
&lt;. [[Guided_Tutorial_GRC|Previous: Working with GRC]]
 +
&gt;. [[Guided_Tutorial_GNU_Radio_in_C++|Next: Programming GNU Radio in C++]]
 +
 +
[[Category:Guided Tutorials]]

Please note that all contributions to GNU Radio are considered to be released under the Creative Commons Attribution-ShareAlike (see GNU Radio:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)