summaryrefslogtreecommitdiff
path: root/gnuradio-core
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core')
-rw-r--r--gnuradio-core/gnuradio-core.conf1
-rw-r--r--gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc64
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.cc16
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py682
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor66
5 files changed, 366 insertions, 463 deletions
diff --git a/gnuradio-core/gnuradio-core.conf b/gnuradio-core/gnuradio-core.conf
index 3ed9892c73..cf3df4aea7 100644
--- a/gnuradio-core/gnuradio-core.conf
+++ b/gnuradio-core/gnuradio-core.conf
@@ -12,4 +12,5 @@ export = True
[ControlPort]
on = False
+edges_list = False
config = # ${prefix}/etc/gnuradio/ctrlport.conf
diff --git a/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc b/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc
index f19c7303d2..5287257d77 100644
--- a/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc
+++ b/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Thu Feb 21 19:08:22 2013</timestamp>
+ <timestamp>Tue Feb 26 14:26:03 2013</timestamp>
<block>
<key>options</key>
<param>
@@ -613,37 +613,6 @@
</param>
</block>
<block>
- <key>blocks_throttle</key>
- <param>
- <key>id</key>
- <value>blocks_throttle_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(623, 64)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
<key>gr_vector_source_x</key>
<param>
<key>id</key>
@@ -748,6 +717,37 @@
<value>0</value>
</param>
</block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(623, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
<connection>
<source_block_id>blocks_throttle_0</source_block_id>
<sink_block_id>digital_psk_mod_0</sink_block_id>
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc
index e5859768de..c6118bcfdd 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc
@@ -138,13 +138,15 @@ gr_top_block::setup_rpc()
"items", "Max number of output items",
RPC_PRIVLVL_MIN, DISPNULL)));
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, std::string>(
- alias(), "edge list",
- &gr_top_block::edge_list,
- pmt::mp(""), pmt::mp(""), pmt::mp(""),
- "edges", "List of edges in the graph",
- RPC_PRIVLVL_MIN, DISPNULL)));
+ if(gr_prefs::singleton()->get_bool("ControlPort", "edges_list", false)) {
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, std::string>(
+ alias(), "edge list",
+ &gr_top_block::edge_list,
+ pmt::mp(""), pmt::mp(""), pmt::mp(""),
+ "edges", "List of edges in the graph",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+ }
// Setters
add_rpc_variable(
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
index 091f0642c6..f797271970 100644
--- a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012 Free Software Foundation, Inc.
+# Copyright 2012,2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -32,34 +32,68 @@ except ImportError:
print "Error: Program requires PyQt4 and gr-qtgui."
sys.exit(1)
-class GrDataPlotterC(gr.top_block):
- def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+class GrDataPlotParent(gr.top_block, QtGui.QWidget):
+ # Setup signals
+ plotupdated = QtCore.pyqtSignal(QtGui.QWidget)
+
+ def __init__(self, name, rate, pmin=None, pmax=None):
gr.top_block.__init__(self)
+ QtGui.QWidget.__init__(self, None)
- self._stripchart = stripchart
self._name = name
self._npts = 500
- samp_rate = 1.0
+ self._rate = rate
+ self.knobnames = [name,]
+
+ self.layout = QtGui.QVBoxLayout()
+ self.setLayout(self.layout)
+
+ self.setAcceptDrops(True)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ def _setup(self, nconnections):
+ self.stop()
+ self.wait()
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.time_sink_c(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ if(self.layout.count() > 0):
+ # Remove and disconnect. Making sure no references to snk
+ # remain so that the plot gets deleted.
+ self.layout.removeWidget(self.py_window)
+ self.disconnect(self.thr, (self.snk, 0))
+ self.disconnect(self.src[0], self.thr)
+ for n in xrange(1, self._ncons):
+ self.disconnect(self.src[n], (self.snk,n))
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._ncons = nconnections
+ self._data_len = self._ncons*[0,]
- self.snk.set_line_label(0, "Real")
- self.snk.set_line_label(1, "Imag")
+ self.thr = blocks.throttle(self._datasize, self._rate)
+ self.snk = self.get_qtsink()
+
+ self.connect(self.thr, (self.snk, 0))
+
+ self._last_data = []
+ self.src = []
+ for n in xrange(self._ncons):
+ self.set_line_label(n, self.knobnames[n])
+
+ self._last_data.append(int(self._npts)*[0,])
+ self.src.append(self.get_vecsource())
+
+ if(n == 0):
+ self.connect(self.src[n], self.thr)
+ else:
+ self.connect(self.src[n], (self.snk,n))
self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self.layout.addWidget(self.py_window)
+
def __del__(self):
pass
+ def close(self):
+ self.snk.close()
+
def qwidget(self):
return self.py_window
@@ -69,162 +103,172 @@ class GrDataPlotterC(gr.top_block):
def semilogy(self, en=True):
self.snk.enable_semilogy(en)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ def dragEnterEvent(self, e):
+ e.acceptProposedAction()
+
+ def dropEvent(self, e):
+ if(e.mimeData().hasFormat("text/plain")):
+ data = str(e.mimeData().text())
+
+ #"PlotData:{0}:{1}".format(tag, iscomplex)
+ datalst = data.split(":::")
+ tag = datalst[0]
+ name = datalst[1]
+ cpx = datalst[2] != "0"
+
+ if(tag == "PlotData" and cpx == self._iscomplex):
+ self.knobnames.append(name)
+
+ # create a new qwidget plot with the new data stream.
+ self._setup(len(self.knobnames))
+
+ # emit that this plot has been updated with a new qwidget.
+ self.plotupdated.emit(self)
+
+ e.acceptProposedAction()
+
+ def data_to_complex(self, data):
+ if(self._iscomplex):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ return data
def update(self, data):
# Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
+ npts = self.get_npts()
if(self._npts != npts):
# Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
+ for n in xrange(self._ncons):
+ if(npts < self._npts):
+ if(self._data_len[n] < npts):
+ self._last_data[n] = self._last_data[n][0:npts]
+ else:
+ self._last_data[n] = self._last_data[n][self._data_len[n]-npts:self._data_len[n]]
+ self._data_len[n] = npts
else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
+ self._last_data[n] += (npts - self._npts)*[0,]
self._npts = npts
self.snk.reset()
-
+
if(self._stripchart):
# Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) == list):
+ data[n] = self.data_to_complex(data[n])
+ if(len(data[n]) > self._npts):
+ self.src[n].set_data(data[n])
+ self._last_data[n] = data[n][-self._npts:]
+ else:
+ newdata = self._last_data[n][-(self._npts-len(data)):]
+ newdata += data[n]
+ self.src[n].set_data(newdata)
+ self._last_data[n] = newdata
+
+ else: # single value update
+ if(self._iscomplex):
+ data[n] = complex(data[n][0], data[n][1])
+ if(self._data_len[n] < self._npts):
+ self._last_data[n][self._data_len[n]] = data[n]
+ self._data_len[n] += 1
+ else:
+ self._last_data[n] = self._last_data[n][1:]
+ self._last_data[n].append(data[n])
+ self.src[n].set_data(self._last_data[n])
else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) != list):
+ data[n] = [data[n],]
+ data[n] = self.data_to_complex(data[n])
+ self.src[n].set_data(data[n])
+
+
-class GrDataPlotterF(gr.top_block):
+class GrDataPlotterC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
self._stripchart = stripchart
- self._name = name
- self._npts = 500
- samp_rate = 1.0
+ self._datasize = gr.sizeof_gr_complex
+ self._iscomplex = True
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._setup(1)
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_sink_f(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.time_sink_c(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def __del__(self):
- pass
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
- def qwidget(self):
- return self.py_window
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(2*n+0, "Re{" + self.knobnames[n] + "}")
+ self.snk.set_line_label(2*n+1, "Im{" + self.knobnames[n] + "}")
- def name(self):
- return self._name
- def semilogy(self, en=True):
- self.snk.enable_semilogy(en)
+class GrDataPlotterF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ self._stripchart = stripchart
+ self._datasize = gr.sizeof_float
+ self._iscomplex = False
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
+ self._setup(1)
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- if(self._stripchart):
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
- else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ def get_qtsink(self):
+ snk = qtgui.time_sink_f(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return gr.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterConst(gr.top_block):
- def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 500
- samp_rate = 1.0
- self._last_data = self._npts*[0,]
- self._data_len = 0
-
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.const_sink_c(self._npts,
- self._name, 1)
- self.snk.enable_autoscale(True)
+class GrDataPlotterConst(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = False
+ self._iscomplex = True
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self._setup(1)
- def __del__(self):
- pass
+ def get_qtsink(self):
+ snk = qtgui.const_sink_c(self._npts,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- def qwidget(self):
- return self.py_window
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
def scatter(self, en=True):
if(en):
@@ -232,327 +276,133 @@ class GrDataPlotterConst(gr.top_block):
else:
self.snk.set_line_style(0, 1)
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterPsdC(gr.top_block):
+class GrDataPlotterPsdC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = True
+ self._iscomplex = True
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.freq_sink_c(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ self._setup(1)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_c(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
-
- def __del__(self):
- pass
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def qwidget(self):
- return self.py_window
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- def name(self):
- return self._name
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
-
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
-class GrDataPlotterPsdF(gr.top_block):
+class GrDataPlotterPsdF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_float
+ self._stripchart = True
+ self._iscomplex = False
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.freq_sink_f(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ self._setup(1)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_f(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
-
- def __del__(self):
- pass
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def qwidget(self):
- return self.py_window
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- def name(self):
- return self._name
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
-
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
-
-class GrTimeRasterF(gr.top_block):
+class GrTimeRasterF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
-
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_raster_sink_f(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._npts = 10
+ self._rows = 40
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._datasize = gr.sizeof_float
+ self._stripchart = False
+ self._iscomplex = False
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self._setup(1)
- def __del__(self):
- pass
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_f(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def qwidget(self):
- return self.py_window
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = int(self.snk.num_cols())
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrTimeRasterB(gr.top_block):
+class GrTimeRasterB(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._npts = 10
+ self._rows = 40
- self.src = gr.vector_source_b([])
- self.thr = blocks.throttle(gr.sizeof_char, rate)
- self.snk = qtgui.time_raster_sink_b(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._datasize = gr.sizeof_char
+ self._stripchart = False
+ self._iscomplex = False
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._setup(1)
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_b(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def __del__(self):
- pass
-
- def qwidget(self):
- return self.py_window
-
- def name(self):
- return self._name
+ def get_vecsource(self):
+ return gr.vector_source_b([])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.num_cols()
- if(self._npts != npts):
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
class GrDataPlotterValueTable:
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
index 60a810b04e..e71cd92ab7 100755
--- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012 Free Software Foundation, Inc.
+# Copyright 2012,2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -24,7 +24,7 @@ from gnuradio import gr, ctrlport
from PyQt4 import QtCore,Qt
import PyQt4.QtGui as QtGui
-import sys, time
+import os, sys, time
import Ice
from gnuradio.ctrlport.IceRadioClient import *
@@ -55,7 +55,7 @@ class MAINWindow(QtGui.QMainWindow):
def __init__(self, radio, port, interface):
super(MAINWindow, self).__init__()
- self.updateRate = 2000;
+ self.updateRate = 1000;
self.conns = []
self.plots = []
self.knobprops = []
@@ -83,6 +83,11 @@ class MAINWindow(QtGui.QMainWindow):
icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
self.setWindowIcon(icon)
+ # Locally turn off ControlPort export from GR. This prevents
+ # our GR-based plotters from launching their own ControlPort
+ # instance (and possibly causing a port collision if one has
+ # been specified).
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'False'
def setUpdateRate(self,nur):
self.updateRate = int(nur);
@@ -217,17 +222,55 @@ class MAINWindow(QtGui.QMainWindow):
else:
self.newPlotPsdC(tag, uid, title)
+ def startDrag(self, e):
+ drag = QtGui.QDrag(self)
+ mime_data = QtCore.QMimeData()
+
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ knobprop = self.knobprops[tree.uid][tag]
+ disp = knobprop.display
+ iscomplex = (disp & gr.DISPOPTCPLX) or (disp & gr.DISPXY)
+
+ if(disp != gr.DISPNULL):
+ data = "PlotData:::{0}:::{1}".format(tag, iscomplex)
+ else:
+ data = "OtherData:::{0}:::{1}".format(tag, iscomplex)
+
+ mime_data.setText(data)
+ drag.setMimeData(mime_data)
+
+ drop = drag.start()
+
def createPlot(self, plot, uid, title):
plot.start()
self.plots[uid].append(plot)
- self.mdiArea.addSubWindow(plot.qwidget())
- plot.qwidget().setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.mdiArea.addSubWindow(plot)
+ plot.setWindowTitle("{0}: {1}".format(title, plot.name()))
self.connect(plot.qwidget(),
QtCore.SIGNAL('destroyed(QObject*)'),
self.destroyPlot)
- plot.qwidget().show()
+ # when the plot is updated via drag-and-drop, we need to be
+ # notified of the new qwidget that's created so we can
+ # properly destroy it.
+ plot.plotupdated.connect(self.plotUpdated)
+
+ plot.show()
+
+ def plotUpdated(self, q):
+ # the plot has been updated with a new qwidget; make sure this
+ # gets dies to the destroyPlot function.
+ for i, plots in enumerate(self.plots):
+ for p in plots:
+ if(p == q):
+ #plots.remove(p)
+ #plots.append(q)
+ self.connect(q.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ break
def destroyPlot(self, obj):
for plots in self.plots:
@@ -275,7 +318,9 @@ class MAINWindow(QtGui.QMainWindow):
def update(self, knobs, uid):
#sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
for plot in self.plots[uid]:
- data = knobs[plot.name()].value
+ data = []
+ for n in plot.knobnames:
+ data.append(knobs[n].value)
plot.update(data)
plot.stop()
plot.wait()
@@ -639,7 +684,7 @@ class MForm(QtGui.QWidget):
self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed)
self.table.treeWidget.setSortingEnabled(True)
self.table.treeWidget.setDragEnabled(True)
-
+
# add things to layouts
self.horizontalLayout.addWidget(self.table.treeWidget)
@@ -657,6 +702,11 @@ class MForm(QtGui.QWidget):
QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
self.parent.newSub);
+ # Allow drag/drop event from table item to plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'),
+ self.parent.startDrag)
+
def openMenu(self, pos):
index = self.table.treeWidget.selectedIndexes()
item = self.table.treeWidget.itemFromIndex(index[0])