diff options
author | Johannes Schmitz <schmitz@ti.rwth-aachen.de> | 2013-11-25 11:06:20 -0800 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2014-04-22 15:07:20 -0700 |
commit | 8672457c57006498b1760ccd59fb11d164333e53 (patch) | |
tree | 29433e9596a35c93dd3fef77aa3e9e5aeba2b697 /gr-zeromq/examples | |
parent | 73f138eca0dede47a69ab34b1fb1abab76e6bf38 (diff) |
Initial import of gr-zmqblocks OOT project as-is, prior to rework for in-tree
Diffstat (limited to 'gr-zeromq/examples')
-rw-r--r-- | gr-zeromq/examples/CMakeLists.txt | 25 | ||||
-rwxr-xr-x | gr-zeromq/examples/client.py | 119 | ||||
-rwxr-xr-x | gr-zeromq/examples/fixui4py.sh | 2 | ||||
-rwxr-xr-x | gr-zeromq/examples/gui.py | 165 | ||||
-rwxr-xr-x | gr-zeromq/examples/loop.py | 141 | ||||
-rw-r--r-- | gr-zeromq/examples/main_window.ui | 199 | ||||
-rwxr-xr-x | gr-zeromq/examples/run_app.sh | 4 | ||||
-rwxr-xr-x | gr-zeromq/examples/server.py | 128 |
8 files changed, 783 insertions, 0 deletions
diff --git a/gr-zeromq/examples/CMakeLists.txt b/gr-zeromq/examples/CMakeLists.txt new file mode 100644 index 0000000000..c837d77f67 --- /dev/null +++ b/gr-zeromq/examples/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +include(GrPython) + +GR_PYTHON_INSTALL( + PROGRAMS + DESTINATION bin +) diff --git a/gr-zeromq/examples/client.py b/gr-zeromq/examples/client.py new file mode 100755 index 0000000000..455ae33f50 --- /dev/null +++ b/gr-zeromq/examples/client.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# +# Copyright 2013 Institute for Theoretical Information Technology, +# RWTH Aachen University +# +# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de> +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +############################################################################### +# Imports +############################################################################### +import zmqblocks +from gnuradio import gr +from gnuradio import blocks +from gnuradio import analog +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import numpy +import sys +from threading import Thread +import time + +############################################################################### +# GNU Radio top_block +############################################################################### +class top_block(gr.top_block): + def __init__(self, options): + gr.top_block.__init__(self) + + self.options = options + + # socket addresses + rpc_adr = "tcp://*:6667" + probe_adr = "tcp://*:5557" + source_adr = "tcp://"+self.options.servername+":5555" + + # blocks + #self.zmq_source = zmqblocks.source_reqrep_nopoll(gr.sizeof_float,source_adr) + self.zmq_source = zmqblocks.source_reqrep(gr.sizeof_float,source_adr) + #self.zmq_source = zmqblocks.source_pushpull(gr.sizeof_float,source_adr) + #self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float,probe_adr) + self.zmq_probe = zmqblocks.sink_pubsub(gr.sizeof_float,probe_adr) + + # connects + self.connect(self.zmq_source, self.zmq_probe) + + # ZeroMQ + self.rpc_manager = zmqblocks.rpc_manager() + self.rpc_manager.set_reply_socket(rpc_adr) + self.rpc_manager.add_interface("start_fg",self.start_fg) + self.rpc_manager.add_interface("stop_fg",self.stop_fg) + self.rpc_manager.start_watcher() + + def start_fg(self): + print "Start Flowgraph" + try: + self.start() + except RuntimeError: + print "Can't start, flowgraph already running!" + + def stop_fg(self): + print "Stop Flowgraph" + self.stop() + self.wait() + +############################################################################### +# Options Parser +############################################################################### +def parse_options(): + """ Options parser. """ + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + parser.add_option("-s", "--servername", type="string", default="localhost", + help="Server hostname") + (options, args) = parser.parse_args() + return options + +############################################################################### +# Waiter Thread +############################################################################### +class waiter(Thread): + """ To keep the program alive when flowgraph is stopped. """ + def run(self): + while keep_running: + time.sleep(1) + +############################################################################### +# Main +############################################################################### +if __name__ == "__main__": + options = parse_options() + tb = top_block(options) + try: + # keep the program running when flowgraph is stopped + while True: + time.sleep(1) + except KeyboardInterrupt: + pass + print "Shutting down flowgraph." + tb.rpc_manager.stop_watcher() + tb.stop() + tb.wait() + tb = None diff --git a/gr-zeromq/examples/fixui4py.sh b/gr-zeromq/examples/fixui4py.sh new file mode 100755 index 0000000000..d2978000bf --- /dev/null +++ b/gr-zeromq/examples/fixui4py.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sed -i 's/qwt_plot.h/PyQt4.Qwt5.Qwt/' $1 diff --git a/gr-zeromq/examples/gui.py b/gr-zeromq/examples/gui.py new file mode 100755 index 0000000000..eaa72da323 --- /dev/null +++ b/gr-zeromq/examples/gui.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# +# Copyright 2013 Institute for Theoretical Information Technology, +# RWTH Aachen University +# +# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de> +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +############################################################################### +# Imports +############################################################################### +from optparse import OptionParser +from gnuradio.eng_option import eng_option +import gui +import sys +import os +from PyQt4 import Qt, QtGui, QtCore, uic +import PyQt4.Qwt5 as Qwt +import zmqblocks +import signal + +class gui(QtGui.QMainWindow): + def __init__(self, window_name, options, parent=None): + QtGui.QMainWindow.__init__(self, parent) + + # give Ctrl+C back to system + signal.signal(signal.SIGINT, signal.SIG_DFL) + + self.gui = uic.loadUi(os.path.join(os.path.dirname(__file__),'main_window.ui'), self) + + self.update_timer = Qt.QTimer() + + # socket addresses + rpc_adr_server = "tcp://"+options.servername+":6666" + rpc_adr_client = "tcp://"+options.clientname+":6667" + probe_adr_server = "tcp://"+options.servername+":5556" + probe_adr_client = "tcp://"+options.clientname+":5557" + + # ZeroMQ + self.probe_manager = zmqblocks.probe_manager() + self.probe_manager.add_socket(probe_adr_server, 'float32', self.plot_data_server) + self.probe_manager.add_socket(probe_adr_client, 'float32', self.plot_data_client) + + self.rpc_mgr_server = zmqblocks.rpc_manager() + self.rpc_mgr_server.set_request_socket(rpc_adr_server) + self.rpc_mgr_client = zmqblocks.rpc_manager() + self.rpc_mgr_client.set_request_socket(rpc_adr_client) + + self.gui.setWindowTitle(window_name) + self.gui.qwtPlotServer.setTitle("Signal Scope") + self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples") + self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude") + self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100) + self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2) + self.gui.qwtPlotClient.setTitle("Signal Scope") + self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples") + self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude") + self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100) + self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2) + + # Grid + pen = Qt.QPen(Qt.Qt.DotLine) + pen.setColor(Qt.Qt.black) + pen.setWidth(0) + grid_server = Qwt.QwtPlotGrid() + grid_client = Qwt.QwtPlotGrid() + grid_server.setPen(pen) + grid_client.setPen(pen) + grid_server.attach(self.gui.qwtPlotServer) + grid_client.attach(self.gui.qwtPlotClient) + + #Signals + self.connect(self.update_timer, QtCore.SIGNAL("timeout()"), self.probe_manager.watcher) + self.connect(self.gui.pushButtonRunServer, QtCore.SIGNAL("clicked()"), self.start_fg_server) + self.connect(self.gui.pushButtonStopServer, QtCore.SIGNAL("clicked()"), self.stop_fg_server) + self.connect(self.gui.pushButtonRunClient, QtCore.SIGNAL("clicked()"), self.start_fg_client) + self.connect(self.gui.pushButtonStopClient, QtCore.SIGNAL("clicked()"), self.stop_fg_client) + self.connect(self.gui.comboBox, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_waveform) + self.connect(self.gui.spinBox, QtCore.SIGNAL("valueChanged(int)"), self.set_gain) + self.shortcut_start = QtGui.QShortcut(Qt.QKeySequence("Ctrl+S"), self.gui) + self.shortcut_stop = QtGui.QShortcut(Qt.QKeySequence("Ctrl+C"), self.gui) + self.shortcut_exit = QtGui.QShortcut(Qt.QKeySequence("Ctrl+D"), self.gui) + self.connect(self.shortcut_exit, QtCore.SIGNAL("activated()"), self.gui.close) + + # start update timer + self.update_timer.start(30) + + def start_fg_server(self): + self.rpc_mgr_server.request("start_fg") + + def stop_fg_server(self): + self.rpc_mgr_server.request("stop_fg") + + def start_fg_client(self): + self.rpc_mgr_client.request("start_fg") + + def stop_fg_client(self): + self.rpc_mgr_client.request("stop_fg") + + # plot the data from the queues + def plot_data(self, plot, samples): + self.x = range(0,len(samples),1) + self.y = samples + # clear the previous points from the plot + plot.clear() + # draw curve with new points and plot + curve = Qwt.QwtPlotCurve() + curve.setPen(Qt.QPen(Qt.Qt.blue, 2)) + curve.attach(plot) + curve.setData(self.x, self.y) + plot.replot() + + def plot_data_server(self, samples): + self.plot_data(self.gui.qwtPlotServer, samples) + + def plot_data_client(self, samples): + self.plot_data(self.gui.qwtPlotClient, samples) + + def set_waveform(self, waveform_str): + self.rpc_mgr_server.request("set_waveform",str(waveform_str)) + + def set_gain(self, gain): + self.rpc_set_gain(gain) + + def rpc_set_gain(self, gain): + self.rpc_mgr_server.request("set_k",gain) + +############################################################################### +# Options Parser +############################################################################### +def parse_options(): + """ Options parser. """ + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + parser.add_option("-s", "--servername", type="string", default="localhost", + help="Server hostname") + parser.add_option("-c", "--clientname", type="string", default="localhost", + help="Server hostname") + (options, args) = parser.parse_args() + return options + + +############################################################################### +# Main +############################################################################### +if __name__ == "__main__": + options = parse_options() + qapp = Qt.QApplication(sys.argv) + qapp.main_window = gui("Remote GNU Radio GUI",options) + qapp.main_window.show() + qapp.exec_() + diff --git a/gr-zeromq/examples/loop.py b/gr-zeromq/examples/loop.py new file mode 100755 index 0000000000..d2c822b8f7 --- /dev/null +++ b/gr-zeromq/examples/loop.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# +# Copyright 2013 Institute for Theoretical Information Technology, +# RWTH Aachen University +# +# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de> +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +############################################################################### +# Imports +############################################################################### +import zmqblocks +from gnuradio import gr +from gnuradio import blocks +from gnuradio import analog +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import numpy +import signal +import gui +from PyQt4 import QtGui +import sys + + +############################################################################### +# GNU Radio top_block +############################################################################### +class top_block(gr.top_block): + def __init__(self, options): + gr.top_block.__init__(self) + + self.options = options + + # create a QT application + self.qapp = QtGui.QApplication(sys.argv) + # give Ctrl+C back to system + signal.signal(signal.SIGINT, signal.SIG_DFL) + + # socket addresses + rpc_adr_server = "tcp://localhost:6666" + rpc_adr_reply = "tcp://*:6666" + probe_adr_gui = "tcp://localhost:5556" + probe_adr_fg = "tcp://*:5556" + sink_adr = "tcp://*:5555" + source_adr = "tcp://localhost:5555" + + # create the main window + self.ui = gui.gui("Loop",rpc_adr_server,rpc_adr_server,probe_adr_gui) + self.ui.show() + + # the strange sampling rate gives a nice movement in the plot :P + self.samp_rate = samp_rate = 48200 + + # blocks + self.gr_sig_source = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE , 1000, 1, 0) + self.null_source = blocks.null_source(gr.sizeof_float) + self.throttle = blocks.throttle(gr.sizeof_float, samp_rate) + self.zmq_source = zmqblocks.source_pushpull_feedback(gr.sizeof_float,source_adr) + self.mult_a = blocks.multiply_const_ff(1) + self.mult_b = blocks.multiply_const_ff(0.5) + self.add = blocks.add_ff(1) + #self.zmq_sink = zmqblocks.sink_reqrep_nopoll(gr.sizeof_float, sink_adr) + #self.zmq_sink = zmqblocks.sink_reqrep(gr.sizeof_float, sink_adr) + self.zmq_sink = zmqblocks.sink_pushpull(gr.sizeof_float, sink_adr) + self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float, probe_adr_fg) + #self.null_sink = blocks.null_sink(gr.sizeof_float) + + # connects + self.connect(self.gr_sig_source, self.mult_a) + self.connect(self.zmq_source, self.mult_b, (self.add,1)) +# self.connect(self.null_source, (self.add,1)) + self.connect(self.mult_a, (self.add, 0), self.throttle, self.zmq_sink) + self.connect(self.throttle, self.zmq_probe) + + # ZeroMQ + self.rpc_manager = zmqblocks.rpc_manager() + self.rpc_manager.set_reply_socket(rpc_adr_reply) + self.rpc_manager.add_interface("start_fg",self.start_fg) + self.rpc_manager.add_interface("stop_fg",self.stop_fg) + self.rpc_manager.add_interface("set_waveform",self.set_waveform) + self.rpc_manager.add_interface("set_k",self.mult_a.set_k) + self.rpc_manager.add_interface("get_sample_rate",self.throttle.sample_rate) + self.rpc_manager.start_watcher() + + def start_fg(self): + print "Start Flowgraph" + try: + self.start() + except RuntimeError: + print "Can't start, flowgraph already running!" + + def stop_fg(self): + print "Stop Flowgraph" + self.stop() + self.wait() + + def set_waveform(self, waveform_str): + waveform = {'Constant' : analog.GR_CONST_WAVE, + 'Sine' : analog.GR_SIN_WAVE, + 'Cosine' : analog.GR_COS_WAVE, + 'Square' : analog.GR_SQR_WAVE, + 'Triangle' : analog.GR_TRI_WAVE, + 'Saw Tooth' : analog.GR_SAW_WAVE}[waveform_str] + self.gr_sig_source.set_waveform(waveform) + + +############################################################################### +# Options Parser +############################################################################### +def parse_options(): + """ Options parser. """ + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + (options, args) = parser.parse_args() + return options + + +############################################################################### +# Main +############################################################################### +if __name__ == "__main__": + options = parse_options() + tb = top_block(options) + tb.qapp.exec_() + tb.stop() + tb = None diff --git a/gr-zeromq/examples/main_window.ui b/gr-zeromq/examples/main_window.ui new file mode 100644 index 0000000000..14f810e67d --- /dev/null +++ b/gr-zeromq/examples/main_window.ui @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ControlPort_Example</class> + <widget class="QMainWindow" name="ControlPort_Example"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1000</width> + <height>600</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="windowTitle"> + <string>ControlPort Example</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="2"> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Client</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="1" column="0"> + <widget class="QPushButton" name="pushButtonRunClient"> + <property name="text"> + <string>Run</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QwtPlot" name="qwtPlotClient"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButtonStopClient"> + <property name="text"> + <string>Stop</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="1" rowspan="4"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Waveform:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>Constant</string> + </property> + </item> + <item> + <property name="text"> + <string>Sine</string> + </property> + </item> + <item> + <property name="text"> + <string>Cosine</string> + </property> + </item> + <item> + <property name="text"> + <string>Square</string> + </property> + </item> + <item> + <property name="text"> + <string>Triangle</string> + </property> + </item> + <item> + <property name="text"> + <string>Saw Tooth</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Gain:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="spinBox"> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Server</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="0"> + <widget class="QPushButton" name="pushButtonRunServer"> + <property name="text"> + <string>Run</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButtonStopServer"> + <property name="text"> + <string>Stop</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QwtPlot" name="qwtPlotServer"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0"> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="Line" name="line_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1000</width> + <height>25</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <customwidgets> + <customwidget> + <class>QwtPlot</class> + <extends>QFrame</extends> + <header>PyQt4.Qwt5.Qwt</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/gr-zeromq/examples/run_app.sh b/gr-zeromq/examples/run_app.sh new file mode 100755 index 0000000000..a18ff14ee2 --- /dev/null +++ b/gr-zeromq/examples/run_app.sh @@ -0,0 +1,4 @@ +#!/bin/sh +export LD_LIBRARY_PATH="$PWD/../build/lib" +export PYTHONPATH="$PWD/../build/swig:$PWD/../python" +/usr/bin/python $1 $2 $3 $4 $5 $6 $7 $8 $9 diff --git a/gr-zeromq/examples/server.py b/gr-zeromq/examples/server.py new file mode 100755 index 0000000000..46bfa591eb --- /dev/null +++ b/gr-zeromq/examples/server.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright 2013 Institute for Theoretical Information Technology, +# RWTH Aachen University +# +# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de> +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +############################################################################### +# Imports +############################################################################### +import zmqblocks +from gnuradio import gr +from gnuradio import blocks +from gnuradio import analog +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import numpy +import sys +from threading import Thread +import time + + +############################################################################### +# GNU Radio top_block +############################################################################### +class top_block(gr.top_block): + def __init__(self, options): + gr.top_block.__init__(self) + + self.options = options + + # socket addresses + rpc_adr = "tcp://*:6666" + probe_adr = "tcp://*:5556" + sink_adr = "tcp://*:5555" + + # the strange sampling rate gives a nice movement in the plot :P + self.samp_rate = samp_rate = 48200 + + # blocks + self.gr_sig_source = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE , 1000, 1, 0) + self.throttle = blocks.throttle(gr.sizeof_float, samp_rate) + self.mult = blocks.multiply_const_ff(1) + #self.zmq_sink = zmqblocks.sink_reqrep_nopoll(gr.sizeof_float, sink_adr) + self.zmq_sink = zmqblocks.sink_reqrep(gr.sizeof_float, sink_adr) + #self.zmq_sink = zmqblocks.sink_pushpull(gr.sizeof_float, sink_adr) + #self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float, probe_adr) + self.zmq_probe = zmqblocks.sink_pubsub(gr.sizeof_float, probe_adr) + #self.null_sink = blocks.null_sink(gr.sizeof_float) + + # connects + self.connect(self.gr_sig_source, self.mult, self.throttle, self.zmq_sink) + self.connect(self.throttle, self.zmq_probe) + + # ZeroMQ + self.rpc_manager = zmqblocks.rpc_manager() + self.rpc_manager.set_reply_socket(rpc_adr) + self.rpc_manager.add_interface("start_fg",self.start_fg) + self.rpc_manager.add_interface("stop_fg",self.stop_fg) + self.rpc_manager.add_interface("set_waveform",self.set_waveform) + self.rpc_manager.add_interface("set_k",self.mult.set_k) + self.rpc_manager.add_interface("get_sample_rate",self.throttle.sample_rate) + self.rpc_manager.start_watcher() + + def start_fg(self): + print "Start Flowgraph" + try: + self.start() + except RuntimeError: + print "Can't start, flowgraph already running!" + + def stop_fg(self): + print "Stop Flowgraph" + self.stop() + self.wait() + + def set_waveform(self, waveform_str): + waveform = {'Constant' : analog.GR_CONST_WAVE, + 'Sine' : analog.GR_SIN_WAVE, + 'Cosine' : analog.GR_COS_WAVE, + 'Square' : analog.GR_SQR_WAVE, + 'Triangle' : analog.GR_TRI_WAVE, + 'Saw Tooth' : analog.GR_SAW_WAVE}[waveform_str] + self.gr_sig_source.set_waveform(waveform) + +############################################################################### +# Options Parser +############################################################################### +def parse_options(): + """ Options parser. """ + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + (options, args) = parser.parse_args() + return options + +############################################################################### +# Main +############################################################################### +if __name__ == "__main__": + options = parse_options() + tb = top_block(options) + try: + # keep the program running when flowgraph is stopped + while True: + time.sleep(1) + except KeyboardInterrupt: + pass + print "Shutting down flowgraph." + tb.rpc_manager.stop_watcher() + tb.stop() + tb.wait() + tb = None |