summaryrefslogtreecommitdiff
path: root/gr-qtgui
diff options
context:
space:
mode:
Diffstat (limited to 'gr-qtgui')
-rw-r--r--gr-qtgui/CMakeLists.txt7
-rw-r--r--gr-qtgui/apps/CMakeLists.txt49
-rwxr-xr-xgr-qtgui/apps/gr_constellation_plot162
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_b184
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_c179
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_f179
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_i184
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_s184
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_b181
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_c176
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_f176
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_i181
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_s181
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_b172
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_c167
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_f166
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_i172
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_s172
-rw-r--r--gr-qtgui/apps/plot_form.py82
-rwxr-xr-xgr-qtgui/apps/qt_digital.py50
-rwxr-xr-xgr-qtgui/apps/uhd_display.py3
-rw-r--r--gr-qtgui/doc/qtgui.dox2
-rwxr-xr-xgr-qtgui/examples/pyqt_const_c.py172
-rwxr-xr-xgr-qtgui/examples/pyqt_freq_c.py177
-rwxr-xr-xgr-qtgui/examples/pyqt_freq_f.py176
-rwxr-xr-xgr-qtgui/examples/pyqt_time_c.py16
-rwxr-xr-xgr-qtgui/examples/pyqt_waterfall_c.py175
-rwxr-xr-xgr-qtgui/examples/pyqt_waterfall_f.py174
-rw-r--r--gr-qtgui/grc/qtgui_block_tree.xml48
-rw-r--r--gr-qtgui/grc/qtgui_check_box.xml1
-rw-r--r--gr-qtgui/grc/qtgui_chooser.xml1
-rw-r--r--gr-qtgui/grc/qtgui_const_sink_x.xml69
-rw-r--r--gr-qtgui/grc/qtgui_entry.xml1
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml122
-rw-r--r--gr-qtgui/grc/qtgui_label.xml1
-rw-r--r--gr-qtgui/grc/qtgui_range.xml1
-rw-r--r--gr-qtgui/grc/qtgui_sink_x.xml28
-rw-r--r--gr-qtgui/grc/qtgui_tab_widget.xml1
-rw-r--r--gr-qtgui/grc/qtgui_time_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml114
-rw-r--r--gr-qtgui/include/qtgui/CMakeLists.txt (renamed from gr-qtgui/include/CMakeLists.txt)21
-rw-r--r--gr-qtgui/include/qtgui/api.h (renamed from gr-qtgui/include/gr_qtgui_api.h)10
-rw-r--r--gr-qtgui/include/qtgui/const_sink_c.h81
-rw-r--r--gr-qtgui/include/qtgui/freq_sink_c.h95
-rw-r--r--gr-qtgui/include/qtgui/freq_sink_f.h95
-rw-r--r--gr-qtgui/include/qtgui/sink_c.h98
-rw-r--r--gr-qtgui/include/qtgui/sink_f.h98
-rw-r--r--gr-qtgui/include/qtgui/time_sink_c.h87
-rw-r--r--gr-qtgui/include/qtgui/time_sink_f.h85
-rw-r--r--gr-qtgui/include/qtgui/utils.h (renamed from gr-qtgui/include/qtgui_util.h)22
-rw-r--r--gr-qtgui/include/qtgui/waterfall_sink_c.h100
-rw-r--r--gr-qtgui/include/qtgui/waterfall_sink_f.h99
-rw-r--r--gr-qtgui/include/qtgui_sink_c.h128
-rw-r--r--gr-qtgui/include/qtgui_sink_f.h125
-rw-r--r--gr-qtgui/include/qtgui_time_sink_c.h101
-rw-r--r--gr-qtgui/include/qtgui_time_sink_f.h99
-rw-r--r--gr-qtgui/lib/CMakeLists.txt40
-rw-r--r--gr-qtgui/lib/ConstellationDisplayPlot.cc200
-rw-r--r--gr-qtgui/lib/ConstellationDisplayPlot.h69
-rw-r--r--gr-qtgui/lib/DisplayPlot.cc221
-rw-r--r--gr-qtgui/lib/DisplayPlot.h101
-rw-r--r--gr-qtgui/lib/FrequencyDisplayPlot.cc305
-rw-r--r--gr-qtgui/lib/FrequencyDisplayPlot.h67
-rw-r--r--gr-qtgui/lib/SpectrumGUIClass.cc32
-rw-r--r--gr-qtgui/lib/SpectrumGUIClass.h4
-rw-r--r--gr-qtgui/lib/TimeDomainDisplayPlot.cc185
-rw-r--r--gr-qtgui/lib/TimeDomainDisplayPlot.h61
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.cc477
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.h84
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.cc257
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.h86
-rw-r--r--gr-qtgui/lib/constellationdisplayform.cc96
-rw-r--r--gr-qtgui/lib/constellationdisplayform.h59
-rw-r--r--gr-qtgui/lib/displayform.cc260
-rw-r--r--gr-qtgui/lib/displayform.h104
-rw-r--r--gr-qtgui/lib/form_menus.h882
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.cc376
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.h110
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.cc380
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.h110
-rw-r--r--gr-qtgui/lib/freqdisplayform.cc162
-rw-r--r--gr-qtgui/lib/freqdisplayform.h75
-rw-r--r--gr-qtgui/lib/qtgui_sink_c.cc310
-rw-r--r--gr-qtgui/lib/qtgui_sink_f.cc294
-rw-r--r--gr-qtgui/lib/qtgui_time_sink_c.cc191
-rw-r--r--gr-qtgui/lib/qtgui_time_sink_f.cc189
-rw-r--r--gr-qtgui/lib/qtgui_types.h196
-rw-r--r--gr-qtgui/lib/qtgui_util.cc40
-rw-r--r--gr-qtgui/lib/sink_c_impl.cc335
-rw-r--r--gr-qtgui/lib/sink_c_impl.h106
-rw-r--r--gr-qtgui/lib/sink_f_impl.cc320
-rw-r--r--gr-qtgui/lib/sink_f_impl.h104
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.cc175
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.h106
-rw-r--r--gr-qtgui/lib/spectrumdisplayform.cc169
-rw-r--r--gr-qtgui/lib/spectrumdisplayform.ui70
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.cc256
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.h87
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.cc254
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.h87
-rw-r--r--gr-qtgui/lib/timedisplayform.cc123
-rw-r--r--gr-qtgui/lib/timedisplayform.h49
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc366
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.h106
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc368
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.h107
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.cc205
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.h86
-rw-r--r--gr-qtgui/python/__init__.py2
-rwxr-xr-xgr-qtgui/python/qa_qtgui.py45
-rw-r--r--gr-qtgui/swig/CMakeLists.txt7
-rw-r--r--gr-qtgui/swig/__init__.py4
-rw-r--r--gr-qtgui/swig/qtgui_sink_c.i66
-rw-r--r--gr-qtgui/swig/qtgui_sink_f.i66
-rw-r--r--gr-qtgui/swig/qtgui_swig.i40
-rw-r--r--gr-qtgui/swig/qtgui_time_sink_c.i56
-rw-r--r--gr-qtgui/swig/qtgui_time_sink_f.i56
117 files changed, 12427 insertions, 3050 deletions
diff --git a/gr-qtgui/CMakeLists.txt b/gr-qtgui/CMakeLists.txt
index f6260bc7e9..be35beeec2 100644
--- a/gr-qtgui/CMakeLists.txt
+++ b/gr-qtgui/CMakeLists.txt
@@ -46,7 +46,11 @@ GR_REGISTER_COMPONENT("gr-qtgui" ENABLE_GR_QTGUI
Boost_FOUND
QT4_FOUND
QWT_FOUND
+ ENABLE_GRUEL
+ ENABLE_VOLK
ENABLE_GR_CORE
+ ENABLE_GR_FFT
+ ENABLE_GR_FILTER
PYTHONLIBS_FOUND
${qt_gui_python_deps}
)
@@ -103,7 +107,7 @@ CPACK_COMPONENT("qtgui_swig"
########################################################################
# Add subdirectories
########################################################################
-add_subdirectory(include)
+add_subdirectory(include/qtgui)
add_subdirectory(lib)
add_subdirectory(doc)
if(ENABLE_PYTHON)
@@ -111,6 +115,7 @@ if(ENABLE_PYTHON)
add_subdirectory(swig)
add_subdirectory(python)
add_subdirectory(examples)
+ add_subdirectory(apps)
endif(ENABLE_PYTHON)
########################################################################
diff --git a/gr-qtgui/apps/CMakeLists.txt b/gr-qtgui/apps/CMakeLists.txt
new file mode 100644
index 0000000000..07a8298701
--- /dev/null
+++ b/gr-qtgui/apps/CMakeLists.txt
@@ -0,0 +1,49 @@
+# Copyright 2012 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(
+ FILES
+ plot_form.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/qtgui
+ COMPONENT "qtgui_python"
+)
+
+GR_PYTHON_INSTALL(
+ PROGRAMS
+ gr_time_plot_c
+ gr_time_plot_f
+ gr_time_plot_i
+ gr_time_plot_s
+ gr_time_plot_b
+ gr_psd_plot_c
+ gr_psd_plot_f
+ gr_psd_plot_i
+ gr_psd_plot_s
+ gr_psd_plot_b
+ gr_spectrogram_plot_c
+ gr_spectrogram_plot_f
+ gr_spectrogram_plot_i
+ gr_spectrogram_plot_s
+ gr_spectrogram_plot_b
+ gr_constellation_plot
+ DESTINATION ${GR_RUNTIME_DIR}
+ COMPONENT "qtgui_python"
+)
diff --git a/gr-qtgui/apps/gr_constellation_plot b/gr-qtgui/apps/gr_constellation_plot
new file mode 100755
index 0000000000..66d227ecc9
--- /dev/null
+++ b/gr-qtgui/apps/gr_constellation_plot
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_gr_complex, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, start, nsamples, max_nsamples):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start)
+ self.gui_snk = qtgui.const_sink_c(self._nsamps,
+ "GNU Radio Constellation Plot",
+ self._nsigs)
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_c(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, (self.gui_snk, i+1))
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots the constellations of a list of files."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.start, nsamples, max_nsamples);
+
+ main_box = dialog_box(tb, 'GNU Radio Constellation Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_psd_plot_b b/gr-qtgui/apps/gr_psd_plot_b
new file mode 100755
index 0000000000..e3e86a271f
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_b
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_char, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.uint8(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_b(data))
+ self.cnvrt.append(gr.char_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of chars/bytes."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1,
+ help="Set a scaling factor for the char->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_char)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average)
+
+ main_box = dialog_box(tb, 'GNU Radio PSD Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_psd_plot_c b/gr-qtgui/apps/gr_psd_plot_c
new file mode 100755
index 0000000000..faa0fc60a4
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_c
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_gr_complex, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [complex(0,0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start)
+ self.gui_snk = qtgui.freq_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_c(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of complex floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio PSD Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_psd_plot_f b/gr-qtgui/apps/gr_psd_plot_f
new file mode 100755
index 0000000000..326618f848
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_f
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_float, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.float32(0.0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_f(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_float)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio PSD Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_psd_plot_i b/gr-qtgui/apps/gr_psd_plot_i
new file mode 100755
index 0000000000..a0264ac1c9
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_i
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_int, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.int32(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_i(data))
+ self.cnvrt.append(gr.int_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of integers."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1,
+ help="Set a scaling factor for the int->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_int)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average)
+
+ main_box = dialog_box(tb, 'GNU Radio PSD Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_psd_plot_s b/gr-qtgui/apps/gr_psd_plot_s
new file mode 100755
index 0000000000..6852cf7d0f
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_s
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_short, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.int16(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_s(data))
+ self.cnvrt.append(gr.short_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of shorts."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1,
+ help="Set a scaling factor for the short->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_short)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average)
+
+ main_box = dialog_box(tb, 'GNU Radio PSD Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_spectrogram_plot_b b/gr-qtgui/apps/gr_spectrogram_plot_b
new file mode 100755
index 0000000000..41c1af521a
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_b
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_char, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.uint8(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.add = gr.add_ff()
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot")
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_b(data))
+ self.cnvrt.append(gr.char_to_float(1, self._scale))
+ n += 1
+
+ self.connect(self.add, self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs):
+ self.connect(s, self.cnvrt[i], (self.add, i))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of chars/bytes."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1,
+ help="Set a scaling factor for the char->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_char)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_spectrogram_plot_c b/gr-qtgui/apps/gr_spectrogram_plot_c
new file mode 100755
index 0000000000..28fa82f298
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_c
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_gr_complex, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [complex(0,0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start)
+ self.add = gr.add_cc()
+ self.gui_snk = qtgui.waterfall_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot")
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_c(data))
+ n += 1
+
+ self.connect(self.add, self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs):
+ self.connect(s, (self.add, i))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of complex floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_spectrogram_plot_f b/gr-qtgui/apps/gr_spectrogram_plot_f
new file mode 100755
index 0000000000..d1bb73212a
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_f
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_float, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.float32(0.0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.add = gr.add_ff()
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot")
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_f(data))
+ n += 1
+
+ self.connect(self.add, self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs):
+ self.connect(s, (self.add, i))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_float)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_spectrogram_plot_i b/gr-qtgui/apps/gr_spectrogram_plot_i
new file mode 100755
index 0000000000..a617f9087d
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_i
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_int, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.int32(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.add = gr.add_ff()
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot")
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_i(data))
+ self.cnvrt.append(gr.int_to_float(1, self._scale))
+ n += 1
+
+ self.connect(self.add, self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs):
+ self.connect(s, self.cnvrt[i], (self.add, i))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of integers."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1,
+ help="Set a scaling factor for the int->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_int)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_spectrogram_plot_s b/gr-qtgui/apps/gr_spectrogram_plot_s
new file mode 100755
index 0000000000..29f3d3df77
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_s
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples_and_pad(filename, start, in_size, min_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_short, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [scipy.int16(0)]
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, scale, avg=1.0):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._center_freq = fc
+ self._samp_rate = samp_rate
+ self._psd_size = psdsize
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+ self._avg = avg
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.add = gr.add_ff()
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot")
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ self.srcs.append(gr.vector_source_s(data))
+ self.cnvrt.append(gr.short_to_float(1, self._scale))
+ n += 1
+
+ self.connect(self.add, self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs):
+ self.connect(s, self.cnvrt[i], (self.add, i))
+
+ self.gui_snk.set_update_time(0);
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples_and_pad(f, self._start,
+ self._nsamps, self._psd_size)
+ s.set_data(data)
+
+ self.start()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of shorts."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-L", "--psd-size", type="int", default=2048,
+ help="Set the FFT size of the PSD [default=%default]")
+ parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
+ help="Set the center frequency of the signal [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-a", "--average", type="float", default=1.0,
+ help="Set amount of averaging (smaller=more averaging) [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1,
+ help="Set a scaling factor for the short->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_short)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, nsamples, max_nsamples,
+ options.scale, options.average);
+
+ main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_time_plot_b b/gr-qtgui/apps/gr_time_plot_b
new file mode 100755
index 0000000000..90043c91f6
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_b
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_char, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class gr_time_plot_f(gr.top_block):
+ def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_b(data))
+ self.cnvrt.append(gr.char_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of chars/bytes."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1,
+ help="Set a scaling factor for the char->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_char)
+ max_nsamples = min(filesizes)
+
+ tb = gr_time_plot_f(filelist, options.sample_rate,
+ options.start, nsamples, max_nsamples,
+ options.scale);
+
+ main_box = dialog_box(tb, 'GNU Radio Time Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_time_plot_c b/gr-qtgui/apps/gr_time_plot_c
new file mode 100755
index 0000000000..858bbce240
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_c
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_gr_complex, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start)
+ self.gui_snk = qtgui.time_sink_c(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_c(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "Re{{{0}}}".format(fname))
+ self.gui_snk.set_title(n+1, "Im{{{0}}}".format(fname))
+ n += 2
+
+ self.connect(self.srcs[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of complex floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex)
+ max_nsamples = min(filesizes)
+
+ tb = my_top_block(filelist, options.sample_rate,
+ options.start, nsamples, max_nsamples);
+
+ main_box = dialog_box(tb, 'GNU Radio Time Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_time_plot_f b/gr-qtgui/apps/gr_time_plot_f
new file mode 100755
index 0000000000..30834aca7a
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_f
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_float, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class gr_time_plot_f(gr.top_block):
+ def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_f(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of floats."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_float)
+ max_nsamples = min(filesizes)
+
+ tb = gr_time_plot_f(filelist, options.sample_rate,
+ options.start, nsamples, max_nsamples);
+
+ main_box = dialog_box(tb, 'GNU Radio Time Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_time_plot_i b/gr-qtgui/apps/gr_time_plot_i
new file mode 100755
index 0000000000..202fc32793
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_i
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_int, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class gr_time_plot_f(gr.top_block):
+ def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_i(data))
+ self.cnvrt.append(gr.int_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of integers."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1,
+ help="Set a scaling factor for the int->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_int)
+ max_nsamples = min(filesizes)
+
+ tb = gr_time_plot_f(filelist, options.sample_rate,
+ options.start, nsamples, max_nsamples,
+ options.scale);
+
+ main_box = dialog_box(tb, 'GNU Radio Time Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/gr_time_plot_s b/gr-qtgui/apps/gr_time_plot_s
new file mode 100755
index 0000000000..6788284833
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_s
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os, sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Scipy required (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_form import *
+except ImportError:
+ from plot_form import *
+
+def read_samples(filename, start, in_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_short, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size)
+ data = data.tolist()
+ fhandle.close()
+
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+
+ return data
+
+class gr_time_plot_f(gr.top_block):
+ def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._scale = scale
+ self._nsigs = len(self._filelist)
+
+ if(nsamples is None):
+ self._nsamps = max_nsamples
+ else:
+ self._nsamps = nsamples
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ self.skip = gr.skiphead(gr.sizeof_float, self._start)
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ n = 0
+ self.srcs = list()
+ self.cnvrt = list()
+ for f in filelist:
+ data = read_samples(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_s(data))
+ self.cnvrt.append(gr.short_to_float(1, self._scale))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_title(n, "{0}".format(fname))
+ n += 1
+
+ self.connect(self.srcs[0], self.cnvrt[0], self.skip)
+ self.connect(self.skip, (self.gui_snk, 0))
+
+ for i,s in enumerate(self.srcs[1:]):
+ self.connect(s, self.cnvrt[i], (self.gui_snk, i+1))
+
+ self.gui_snk.set_update_time(0);
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ def get_gui(self):
+ return self.pyWin
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ for s,f in zip(self.srcs, self._filelist):
+ data = read_samples(f, self._start, newnsamps)
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of shorts."
+ parser = OptionParser(option_class=eng_option, description=description,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=None,
+ help="Set the number of samples to display [default=prints entire file]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
+ help="Set the sample rate of the signal [default=%default]")
+ parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1,
+ help="Set a scaling factor for the short->float conversion [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+
+ filelist = list(args)
+
+ nsamples = options.nsamples
+
+ # Find the smallest number of samples in all files and use that as
+ # a maximum value possible.
+ filesizes = []
+ for f in filelist:
+ if(os.path.exists(f)):
+ filesizes.append(os.path.getsize(f) / gr.sizeof_short)
+ max_nsamples = min(filesizes)
+
+ tb = gr_time_plot_f(filelist, options.sample_rate,
+ options.start, nsamples, max_nsamples,
+ options.scale);
+
+ main_box = dialog_box(tb, 'GNU Radio Time Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py
new file mode 100644
index 0000000000..2fb19d72b8
--- /dev/null
+++ b/gr-qtgui/apps/plot_form.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, top_block, title=''):
+ QtGui.QWidget.__init__(self, None)
+
+ self._start = 0
+ self._end = 0
+
+ self.top_block = top_block
+
+ self.setWindowTitle(title)
+
+ self.size_val = QtGui.QIntValidator(0, top_block._max_nsamps, self)
+
+ self.start_form = QtGui.QFormLayout()
+ self.start_edit = QtGui.QLineEdit(self)
+ self.start_edit.setMinimumWidth(100)
+ self.start_edit.setText(QtCore.QString("%1").arg(top_block._start))
+ self.start_edit.setValidator(self.size_val)
+ self.start_form.addRow("Start:", self.start_edit)
+ self.connect(self.start_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_points)
+
+ end = top_block._start + top_block._nsamps
+ self.end_form = QtGui.QFormLayout()
+ self.end_edit = QtGui.QLineEdit(self)
+ self.end_edit.setMinimumWidth(100)
+ self.end_edit.setText(QtCore.QString("%1").arg(end))
+ self.end_edit.setValidator(self.size_val)
+ self.end_form.addRow("End:", self.end_edit)
+ self.connect(self.end_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_points)
+
+ self.layout = QtGui.QGridLayout(self)
+ self.layout.addWidget(top_block.get_gui(), 0,0,1,2)
+ self.layout.addLayout(self.start_form, 1,0,1,1)
+ self.layout.addLayout(self.end_form, 1,1,1,1)
+
+ self.resize(800, 500)
+
+ def update_points(self):
+ newstart = self.start_edit.text().toUInt()[0]
+ newend = self.end_edit.text().toUInt()[0]
+ if(newstart != self._start or newend != self._end):
+ if(newend < newstart):
+ QtGui.QMessageBox.information(
+ self, "Warning",
+ "End sample is less than start sample.",
+ QtGui.QMessageBox.Ok);
+ else:
+ newnsamps = newend - newstart
+ self.top_block.reset(newstart, newnsamps)
+ self._start = newstart
+ self._end = newend
diff --git a/gr-qtgui/apps/qt_digital.py b/gr-qtgui/apps/qt_digital.py
index 2bc039a31f..d353e0041c 100755
--- a/gr-qtgui/apps/qt_digital.py
+++ b/gr-qtgui/apps/qt_digital.py
@@ -20,7 +20,7 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, blks2
+from gnuradio import gr, digital
from gnuradio import eng_notation
import sys
@@ -60,7 +60,7 @@ class dialog_box(QtGui.QMainWindow):
self.set_time_offset(self.fg.timing_offset())
self.set_gain_mu(self.fg.rx_gain_mu())
- self.set_alpha(self.fg.rx_alpha())
+ self.set_loop_bw(self.fg.loop_bw())
# Add the qtsnk widgets to the hlayout box
self.gui.sinkLayout.addWidget(snkTx)
@@ -146,13 +146,13 @@ class dialog_box(QtGui.QMainWindow):
def set_gain_mu(self, gain):
self.gui.gainMuEdit.setText(QtCore.QString("%1").arg(gain))
- def set_alpha(self, alpha):
- self.gui.alphaEdit.setText(QtCore.QString("%1").arg(alpha))
+ def set_loop_bw(self, bw):
+ self.gui.alphaEdit.setText(QtCore.QString("%1").arg(bw))
def alphaEditText(self):
try:
- alpha = self.gui.alphaEdit.text().toDouble()[0]
- self.fg.set_rx_alpha(alpha)
+ bw = self.gui.alphaEdit.text().toDouble()[0]
+ self.fg.set_loop_bw(bw)
except RuntimeError:
pass
@@ -174,13 +174,16 @@ class my_top_block(gr.top_block):
self.sps = 2
self.excess_bw = 0.35
- self.gray_code = True
+ self.gray_code = digital.mod_codes.GRAY_CODE
fftsize = 2048
self.data = scipy.random.randint(0, 255, 1000)
self.src = gr.vector_source_b(self.data.tolist(), True)
- self.mod = blks2.dqpsk_mod(self.sps, self.excess_bw, self.gray_code, False, False)
+ self.mod = digital.dqpsk_mod(self.gray_code,
+ samples_per_symbol=self.sps,
+ excess_bw=self.excess_bw,
+ verbose=False, log=False)
self.rrctaps = gr.firdes.root_raised_cosine(1, self.sps, 1, self.excess_bw, 21)
self.rx_rrc = gr.fir_filter_ccf(1, self.rrctaps)
@@ -194,17 +197,16 @@ class my_top_block(gr.top_block):
self.gain_omega = .25 * self.gain_mu * self.gain_mu
self.omega_rel_lim = 0.05
- self.alpha = 0.15
- self.beta = 0.25 * self.alpha * self.alpha
+ self._loop_bw = 2*scipy.pi/100.0
self.fmin = -1000/self.sample_rate()
self.fmax = 1000/self.sample_rate()
- self.receiver = gr.mpsk_receiver_cc(self.arity, 0,
- self.alpha, self.beta,
- self.fmin, self.fmax,
- self.mu, self.gain_mu,
- self.omega, self.gain_omega,
- self.omega_rel_lim)
+ self.receiver = digital.mpsk_receiver_cc(self.arity, 0,
+ self._loop_bw,
+ self.fmin, self.fmax,
+ self.mu, self.gain_mu,
+ self.omega, self.gain_omega,
+ self.omega_rel_lim)
self.snr_dB = 15
@@ -288,18 +290,12 @@ class my_top_block(gr.top_block):
self.receiver.set_gain_mu(self.gain_mu)
self.receiver.set_gain_omega(self.gain_omega)
- def rx_alpha(self):
- return self.alpha
-
- def rx_beta(self):
- return self.beta
-
- def set_rx_alpha(self, alpha):
- self.alpha = alpha
- self.beta = .25 * self.alpha * self.alpha
- self.receiver.set_alpha(self.alpha)
- self.receiver.set_beta(self.beta)
+ def set_loop_bw(self, loop_bw):
+ self._loop_bw = bw
+ self.receiver.set_loop_bw(self._loop_bw)
+ def loop_bw(self):
+ return self._loop_bw
if __name__ == "__main__":
tb = my_top_block();
diff --git a/gr-qtgui/apps/uhd_display.py b/gr-qtgui/apps/uhd_display.py
index d02fbad9ee..250d757b6c 100755
--- a/gr-qtgui/apps/uhd_display.py
+++ b/gr-qtgui/apps/uhd_display.py
@@ -24,12 +24,11 @@ from gnuradio import gr
from gnuradio import uhd
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
-from gnuradio.qtgui import qtgui
from optparse import OptionParser
import sys
try:
- from gnuradio.qtgui import qtgui
+ from gnuradio import qtgui
from PyQt4 import QtGui, QtCore
import sip
except ImportError:
diff --git a/gr-qtgui/doc/qtgui.dox b/gr-qtgui/doc/qtgui.dox
index 8664af163d..c12fbf0106 100644
--- a/gr-qtgui/doc/qtgui.dox
+++ b/gr-qtgui/doc/qtgui.dox
@@ -51,7 +51,7 @@ while the GUI is alive.
\code
from PyQt4 import Qt
-from gnuradio.qtgui import qtgui
+from gnuradio import qtgui
import sys, sip
class grclass(gr.top_block):
diff --git a/gr-qtgui/examples/pyqt_const_c.py b/gr-qtgui/examples/pyqt_const_c.py
new file mode 100755
index 0000000000..e3cc3e527e
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_const_c.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+from gnuradio import gr
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, display, control):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+ self.boxlayout.addWidget(control)
+
+ self.resize(800, 500)
+
+class control_box(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.setWindowTitle('Control Panel')
+
+ self.setToolTip('Control the signals')
+ QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
+
+ self.layout = QtGui.QFormLayout(self)
+
+ # Control the first signal
+ self.freq1Edit = QtGui.QLineEdit(self)
+ self.freq1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Frequency:", self.freq1Edit)
+ self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq1EditText)
+
+ self.amp1Edit = QtGui.QLineEdit(self)
+ self.amp1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit)
+ self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp1EditText)
+
+
+ # Control the second signal
+ self.freq2Edit = QtGui.QLineEdit(self)
+ self.freq2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Frequency:", self.freq2Edit)
+ self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq2EditText)
+
+
+ self.amp2Edit = QtGui.QLineEdit(self)
+ self.amp2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit)
+ self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp2EditText)
+
+ self.quit = QtGui.QPushButton('Close', self)
+ self.quit.setMinimumWidth(100)
+ self.layout.addWidget(self.quit)
+
+ self.connect(self.quit, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def attach_signal1(self, signal):
+ self.signal1 = signal
+ self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency()))
+ self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude()))
+
+ def attach_signal2(self, signal):
+ self.signal2 = signal
+ self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency()))
+ self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude()))
+
+ def freq1EditText(self):
+ try:
+ newfreq = float(self.freq1Edit.text())
+ self.signal1.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp1EditText(self):
+ try:
+ newamp = float(self.amp1Edit.text())
+ self.signal1.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+ def freq2EditText(self):
+ try:
+ newfreq = float(self.freq2Edit.text())
+ self.signal2.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp2EditText(self):
+ try:
+ newamp = float(self.amp2Edit.text())
+ self.signal2.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ Rs = 8000
+ f1 = 100
+ f2 = 200
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.5, 0)
+ src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.5, 0)
+ src = gr.add_cc()
+ channel = gr.channel_model(0.001)
+ thr = gr.throttle(gr.sizeof_gr_complex, 100*npts)
+ self.snk1 = qtgui.const_sink_c(npts, "Constellation Example", 1)
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, channel, thr, (self.snk1, 0))
+
+ self.ctrl_win = control_box()
+ self.ctrl_win.attach_signal1(src1)
+ self.ctrl_win.attach_signal2(src2)
+
+ # Get the reference pointer to the SpectrumDisplayForm QWidget
+ pyQt = self.snk1.pyqwidget()
+
+ # Wrap the pointer as a PyQt SIP object
+ # This can now be manipulated as a PyQt4.QtGui.QWidget
+ pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ self.main_box = dialog_box(pyWin, self.ctrl_win)
+ self.main_box.show()
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.qapp.exec_()
+ tb.stop()
+
diff --git a/gr-qtgui/examples/pyqt_freq_c.py b/gr-qtgui/examples/pyqt_freq_c.py
new file mode 100755
index 0000000000..0422046204
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_freq_c.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, display, control):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+ self.boxlayout.addWidget(control)
+
+ self.resize(800, 500)
+
+class control_box(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.setWindowTitle('Control Panel')
+
+ self.setToolTip('Control the signals')
+ QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
+
+ self.layout = QtGui.QFormLayout(self)
+
+ # Control the first signal
+ self.freq1Edit = QtGui.QLineEdit(self)
+ self.freq1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Frequency:", self.freq1Edit)
+ self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq1EditText)
+
+ self.amp1Edit = QtGui.QLineEdit(self)
+ self.amp1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit)
+ self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp1EditText)
+
+
+ # Control the second signal
+ self.freq2Edit = QtGui.QLineEdit(self)
+ self.freq2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Frequency:", self.freq2Edit)
+ self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq2EditText)
+
+
+ self.amp2Edit = QtGui.QLineEdit(self)
+ self.amp2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit)
+ self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp2EditText)
+
+ self.quit = QtGui.QPushButton('Close', self)
+ self.quit.setMinimumWidth(100)
+ self.layout.addWidget(self.quit)
+
+ self.connect(self.quit, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def attach_signal1(self, signal):
+ self.signal1 = signal
+ self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency()))
+ self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude()))
+
+ def attach_signal2(self, signal):
+ self.signal2 = signal
+ self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency()))
+ self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude()))
+
+ def freq1EditText(self):
+ try:
+ newfreq = float(self.freq1Edit.text())
+ self.signal1.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp1EditText(self):
+ try:
+ newamp = float(self.amp1Edit.text())
+ self.signal1.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+ def freq2EditText(self):
+ try:
+ newfreq = float(self.freq2Edit.text())
+ self.signal2.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp2EditText(self):
+ try:
+ newamp = float(self.amp2Edit.text())
+ self.signal2.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ Rs = 8000
+ f1 = 100
+ f2 = 200
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0)
+ src = gr.add_cc()
+ channel = gr.channel_model(0.01)
+ thr = gr.throttle(gr.sizeof_gr_complex, 100*npts)
+ self.snk1 = qtgui.freq_sink_c(npts, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Complex Freq Example", 3)
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, channel, thr, (self.snk1, 0))
+ self.connect(src1, (self.snk1, 1))
+ self.connect(src2, (self.snk1, 2))
+
+ self.ctrl_win = control_box()
+ self.ctrl_win.attach_signal1(src1)
+ self.ctrl_win.attach_signal2(src2)
+
+ # Get the reference pointer to the SpectrumDisplayForm QWidget
+ pyQt = self.snk1.pyqwidget()
+
+ # Wrap the pointer as a PyQt SIP object
+ # This can now be manipulated as a PyQt4.QtGui.QWidget
+ pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ #pyWin.show()
+ self.main_box = dialog_box(pyWin, self.ctrl_win)
+ self.main_box.show()
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.qapp.exec_()
+ tb.stop()
+
diff --git a/gr-qtgui/examples/pyqt_freq_f.py b/gr-qtgui/examples/pyqt_freq_f.py
new file mode 100755
index 0000000000..fb7a9f93c6
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_freq_f.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, display, control):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+ self.boxlayout.addWidget(control)
+
+ self.resize(800, 500)
+
+class control_box(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.setWindowTitle('Control Panel')
+
+ self.setToolTip('Control the signals')
+ QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
+
+ self.layout = QtGui.QFormLayout(self)
+
+ # Control the first signal
+ self.freq1Edit = QtGui.QLineEdit(self)
+ self.freq1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Frequency:", self.freq1Edit)
+ self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq1EditText)
+
+ self.amp1Edit = QtGui.QLineEdit(self)
+ self.amp1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit)
+ self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp1EditText)
+
+
+ # Control the second signal
+ self.freq2Edit = QtGui.QLineEdit(self)
+ self.freq2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Frequency:", self.freq2Edit)
+ self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq2EditText)
+
+
+ self.amp2Edit = QtGui.QLineEdit(self)
+ self.amp2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit)
+ self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp2EditText)
+
+ self.quit = QtGui.QPushButton('Close', self)
+ self.quit.setMinimumWidth(100)
+ self.layout.addWidget(self.quit)
+
+ self.connect(self.quit, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def attach_signal1(self, signal):
+ self.signal1 = signal
+ self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency()))
+ self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude()))
+
+ def attach_signal2(self, signal):
+ self.signal2 = signal
+ self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency()))
+ self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude()))
+
+ def freq1EditText(self):
+ try:
+ newfreq = float(self.freq1Edit.text())
+ self.signal1.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp1EditText(self):
+ try:
+ newamp = float(self.amp1Edit.text())
+ self.signal1.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+ def freq2EditText(self):
+ try:
+ newfreq = float(self.freq2Edit.text())
+ self.signal2.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp2EditText(self):
+ try:
+ newamp = float(self.amp2Edit.text())
+ self.signal2.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ Rs = 8000
+ f1 = 100
+ f2 = 200
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0)
+ src = gr.add_ff()
+ thr = gr.throttle(gr.sizeof_float, 100*npts)
+ self.snk1 = qtgui.freq_sink_f(npts, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Real freq Example", 3)
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, thr, (self.snk1, 0))
+ self.connect(src1, (self.snk1, 1))
+ self.connect(src2, (self.snk1, 2))
+
+ self.ctrl_win = control_box()
+ self.ctrl_win.attach_signal1(src1)
+ self.ctrl_win.attach_signal2(src2)
+
+ # Get the reference pointer to the SpectrumDisplayForm QWidget
+ pyQt = self.snk1.pyqwidget()
+
+ # Wrap the pointer as a PyQt SIP object
+ # This can now be manipulated as a PyQt4.QtGui.QWidget
+ pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ #pyWin.show()
+ self.main_box = dialog_box(pyWin, self.ctrl_win)
+ self.main_box.show()
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.qapp.exec_()
+ tb.stop()
+
diff --git a/gr-qtgui/examples/pyqt_time_c.py b/gr-qtgui/examples/pyqt_time_c.py
index 04425e11f1..255cd1c855 100755
--- a/gr-qtgui/examples/pyqt_time_c.py
+++ b/gr-qtgui/examples/pyqt_time_c.py
@@ -145,13 +145,13 @@ class my_top_block(gr.top_block):
channel = gr.channel_model(0.01)
thr = gr.throttle(gr.sizeof_gr_complex, 100*npts)
self.snk1 = qtgui.time_sink_c(npts, Rs,
- "Complex Time Example", 3)
+ "Complex Time Example", 1)
self.connect(src1, (src,0))
self.connect(src2, (src,1))
self.connect(src, channel, thr, (self.snk1, 0))
- self.connect(src1, (self.snk1, 1))
- self.connect(src2, (self.snk1, 2))
+ #self.connect(src1, (self.snk1, 1))
+ #self.connect(src2, (self.snk1, 2))
self.ctrl_win = control_box()
self.ctrl_win.attach_signal1(src1)
@@ -169,14 +169,16 @@ class my_top_block(gr.top_block):
pyWin, QtCore.SLOT("setTitle(int, QString)"))
pyWin.emit(QtCore.SIGNAL("setTitle(int, QString)"), 0, "Re{sum}")
self.snk1.set_title(1, "Im{Sum}")
- self.snk1.set_title(2, "Re{src1}")
- self.snk1.set_title(3, "Im{src1}")
- self.snk1.set_title(4, "Re{src2}")
- self.snk1.set_title(5, "Im{src2}")
+ #self.snk1.set_title(2, "Re{src1}")
+ #self.snk1.set_title(3, "Im{src1}")
+ #self.snk1.set_title(4, "Re{src2}")
+ #self.snk1.set_title(5, "Im{src2}")
# Can also set the color of a curve
#self.snk1.set_color(5, "blue")
+ self.snk1.set_update_time(0.5)
+
#pyWin.show()
self.main_box = dialog_box(pyWin, self.ctrl_win)
self.main_box.show()
diff --git a/gr-qtgui/examples/pyqt_waterfall_c.py b/gr-qtgui/examples/pyqt_waterfall_c.py
new file mode 100755
index 0000000000..b7f8396ff3
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_waterfall_c.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, display, control):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+ self.boxlayout.addWidget(control)
+
+ self.resize(800, 500)
+
+class control_box(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.setWindowTitle('Control Panel')
+
+ self.setToolTip('Control the signals')
+ QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
+
+ self.layout = QtGui.QFormLayout(self)
+
+ # Control the first signal
+ self.freq1Edit = QtGui.QLineEdit(self)
+ self.freq1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Frequency:", self.freq1Edit)
+ self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq1EditText)
+
+ self.amp1Edit = QtGui.QLineEdit(self)
+ self.amp1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit)
+ self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp1EditText)
+
+
+ # Control the second signal
+ self.freq2Edit = QtGui.QLineEdit(self)
+ self.freq2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Frequency:", self.freq2Edit)
+ self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq2EditText)
+
+
+ self.amp2Edit = QtGui.QLineEdit(self)
+ self.amp2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit)
+ self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp2EditText)
+
+ self.quit = QtGui.QPushButton('Close', self)
+ self.quit.setMinimumWidth(100)
+ self.layout.addWidget(self.quit)
+
+ self.connect(self.quit, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def attach_signal1(self, signal):
+ self.signal1 = signal
+ self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency()))
+ self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude()))
+
+ def attach_signal2(self, signal):
+ self.signal2 = signal
+ self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency()))
+ self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude()))
+
+ def freq1EditText(self):
+ try:
+ newfreq = float(self.freq1Edit.text())
+ self.signal1.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp1EditText(self):
+ try:
+ newamp = float(self.amp1Edit.text())
+ self.signal1.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+ def freq2EditText(self):
+ try:
+ newfreq = float(self.freq2Edit.text())
+ self.signal2.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp2EditText(self):
+ try:
+ newamp = float(self.amp2Edit.text())
+ self.signal2.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ Rs = 8000
+ f1 = 100
+ f2 = 200
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0)
+ src = gr.add_cc()
+ channel = gr.channel_model(0.01)
+ thr = gr.throttle(gr.sizeof_gr_complex, 100*npts)
+ self.snk1 = qtgui.waterfall_sink_c(npts, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Complex Waterfall Example")
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, channel, thr, (self.snk1, 0))
+
+ self.ctrl_win = control_box()
+ self.ctrl_win.attach_signal1(src1)
+ self.ctrl_win.attach_signal2(src2)
+
+ # Get the reference pointer to the SpectrumDisplayForm QWidget
+ pyQt = self.snk1.pyqwidget()
+
+ # Wrap the pointer as a PyQt SIP object
+ # This can now be manipulated as a PyQt4.QtGui.QWidget
+ pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ #pyWin.show()
+ self.main_box = dialog_box(pyWin, self.ctrl_win)
+ self.main_box.show()
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.qapp.exec_()
+ tb.stop()
+
diff --git a/gr-qtgui/examples/pyqt_waterfall_f.py b/gr-qtgui/examples/pyqt_waterfall_f.py
new file mode 100755
index 0000000000..29ae259e5f
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_waterfall_f.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 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.
+#
+
+from gnuradio import gr
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class dialog_box(QtGui.QWidget):
+ def __init__(self, display, control):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+ self.boxlayout.addWidget(control)
+
+ self.resize(800, 500)
+
+class control_box(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.setWindowTitle('Control Panel')
+
+ self.setToolTip('Control the signals')
+ QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
+
+ self.layout = QtGui.QFormLayout(self)
+
+ # Control the first signal
+ self.freq1Edit = QtGui.QLineEdit(self)
+ self.freq1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Frequency:", self.freq1Edit)
+ self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq1EditText)
+
+ self.amp1Edit = QtGui.QLineEdit(self)
+ self.amp1Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit)
+ self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp1EditText)
+
+
+ # Control the second signal
+ self.freq2Edit = QtGui.QLineEdit(self)
+ self.freq2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Frequency:", self.freq2Edit)
+ self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.freq2EditText)
+
+
+ self.amp2Edit = QtGui.QLineEdit(self)
+ self.amp2Edit.setMinimumWidth(100)
+ self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit)
+ self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"),
+ self.amp2EditText)
+
+ self.quit = QtGui.QPushButton('Close', self)
+ self.quit.setMinimumWidth(100)
+ self.layout.addWidget(self.quit)
+
+ self.connect(self.quit, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def attach_signal1(self, signal):
+ self.signal1 = signal
+ self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency()))
+ self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude()))
+
+ def attach_signal2(self, signal):
+ self.signal2 = signal
+ self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency()))
+ self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude()))
+
+ def freq1EditText(self):
+ try:
+ newfreq = float(self.freq1Edit.text())
+ self.signal1.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp1EditText(self):
+ try:
+ newamp = float(self.amp1Edit.text())
+ self.signal1.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+ def freq2EditText(self):
+ try:
+ newfreq = float(self.freq2Edit.text())
+ self.signal2.set_frequency(newfreq)
+ except ValueError:
+ print "Bad frequency value entered"
+
+ def amp2EditText(self):
+ try:
+ newamp = float(self.amp2Edit.text())
+ self.signal2.set_amplitude(newamp)
+ except ValueError:
+ print "Bad amplitude value entered"
+
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ Rs = 8000
+ f1 = 100
+ f2 = 200
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0)
+ src = gr.add_ff()
+ thr = gr.throttle(gr.sizeof_float, 100*npts)
+ self.snk1 = qtgui.waterfall_sink_f(npts, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Real Waterfall Example")
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, thr, (self.snk1, 0))
+
+ self.ctrl_win = control_box()
+ self.ctrl_win.attach_signal1(src1)
+ self.ctrl_win.attach_signal2(src2)
+
+ # Get the reference pointer to the SpectrumDisplayForm QWidget
+ pyQt = self.snk1.pyqwidget()
+
+ # Wrap the pointer as a PyQt SIP object
+ # This can now be manipulated as a PyQt4.QtGui.QWidget
+ pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ #pyWin.show()
+ self.main_box = dialog_box(pyWin, self.ctrl_win)
+ self.main_box.show()
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.qapp.exec_()
+ tb.stop()
+
diff --git a/gr-qtgui/grc/qtgui_block_tree.xml b/gr-qtgui/grc/qtgui_block_tree.xml
new file mode 100644
index 0000000000..898c1c0044
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_block_tree.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright 2012 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.
+-->
+
+<!--
+###################################################
+##Block Tree for GR QTGUI blocks.
+###################################################
+ -->
+<cat>
+ <name></name> <!-- Blank for Root Name -->
+ <cat>
+ <name>QT GUI Sinks</name>
+ <block>qtgui_sink_x</block>
+ <block>qtgui_freq_sink_x</block>
+ <block>qtgui_time_sink_x</block>
+ <block>qtgui_const_sink_x</block>
+ <block>qtgui_waterfall_sink_x</block>
+ </cat>
+ <cat>
+ <name>QT GUI Widgets</name>
+ <block>qtgui_tab_widget</block>
+ <block>variable_qtgui_range</block>
+ <block>variable_qtgui_chooser</block>
+ <block>variable_qtgui_check_box</block>
+ <block>variable_qtgui_entry</block>
+ <block>variable_qtgui_label</block>
+ </cat>
+</cat>
diff --git a/gr-qtgui/grc/qtgui_check_box.xml b/gr-qtgui/grc/qtgui_check_box.xml
index 95f4f968a6..e3a00d002e 100644
--- a/gr-qtgui/grc/qtgui_check_box.xml
+++ b/gr-qtgui/grc/qtgui_check_box.xml
@@ -8,7 +8,6 @@
<block>
<name>QT GUI Check Box</name>
<key>variable_qtgui_check_box</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#set $win = '_%s_check_box'%$id
diff --git a/gr-qtgui/grc/qtgui_chooser.xml b/gr-qtgui/grc/qtgui_chooser.xml
index cb50902897..6a8760cbe6 100644
--- a/gr-qtgui/grc/qtgui_chooser.xml
+++ b/gr-qtgui/grc/qtgui_chooser.xml
@@ -8,7 +8,6 @@
<block>
<name>QT GUI Chooser</name>
<key>variable_qtgui_chooser</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#slurp
diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml b/gr-qtgui/grc/qtgui_const_sink_x.xml
new file mode 100644
index 0000000000..536237d164
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Sink
+###################################################
+ -->
+<block>
+ <name>QT GUI Constellation Sink</name>
+ <key>qtgui_const_sink_x</key>
+ <import>from PyQt4 import Qt</import>
+ <import>from gnuradio import qtgui</import>
+ <import>import sip</import>
+ <make>#set $win = 'self._%s_win'%$id
+qtgui.$(type.fcn)(
+ $size, \#size
+ $name, \#name
+ $nconnections \#number of inputs
+)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+ <callback>set_resize($width, $height)</callback>
+ <callback>set_update_time($t)</callback>
+ <callback>set_title($which, $title)</callback>
+ <callback>set_color($which, $color)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>complex</value>
+ <type>enum</type>
+ <option><name>Complex</name><key>complex</key><opt>fcn:const_sink_c</opt></option>
+<!-- <option><name>Float</name><key>float</key><opt>fcn:const_sink_f</opt></option> -->
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <value>QT GUI Plot</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Number of Points</name>
+ <key>size</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$nconnections</nports>
+ </sink>
+ <doc>
+The GUI hint can be used to position the widget within the application. \
+The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
+Both the tab specification and the grid position are optional.
+ </doc>
+</block>
diff --git a/gr-qtgui/grc/qtgui_entry.xml b/gr-qtgui/grc/qtgui_entry.xml
index 1a98402a0f..514071afab 100644
--- a/gr-qtgui/grc/qtgui_entry.xml
+++ b/gr-qtgui/grc/qtgui_entry.xml
@@ -8,7 +8,6 @@
<block>
<name>QT GUI Entry</name>
<key>variable_qtgui_entry</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<import>from gnuradio import eng_notation</import>
<var_make>self.$(id) = $(id) = $value</var_make>
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
new file mode 100644
index 0000000000..69ce5f4e68
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Sink
+###################################################
+ -->
+<block>
+ <name>QT GUI Frequency Sink</name>
+ <key>qtgui_freq_sink_x</key>
+ <import>from PyQt4 import Qt</import>
+ <import>from gnuradio import qtgui</import>
+ <import>from gnuradio.gr import firdes</import>
+ <import>import sip</import>
+ <make>#set $win = 'self._%s_win'%$id
+qtgui.$(type.fcn)(
+ $fftsize, \#size
+ $wintype, \#wintype
+ $fc, \#fc
+ $bw, \#bw
+ $name, \#name
+ $nconnections \#number of inputs
+)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+ <callback>set_frequency_range($fc, $bw)</callback>
+ <callback>set_update_time($t)</callback>
+ <callback>set_title($which, $title)</callback>
+ <callback>set_color($which, $color)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>complex</value>
+ <type>enum</type>
+ <option><name>Complex</name><key>complex</key><opt>fcn:freq_sink_c</opt></option>
+ <option><name>Float</name><key>float</key><opt>fcn:freq_sink_f</opt></option>
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <value>QT GUI Plot</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>FFT Size</name>
+ <key>fftsize</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Window Type</name>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ <type>int</type>
+ <hide>part</hide>
+ <option>
+ <name>Blackman-harris</name>
+ <key>firdes.WIN_BLACKMAN_hARRIS</key>
+ </option>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Center Frequency (Hz)</name>
+ <key>fc</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Bandwidth (Hz)</name>
+ <key>bw</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Update Rate</name>
+ <key>rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$nconnections</nports>
+ </sink>
+ <doc>
+The GUI hint can be used to position the widget within the application. \
+The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
+Both the tab specification and the grid position are optional.
+ </doc>
+</block>
diff --git a/gr-qtgui/grc/qtgui_label.xml b/gr-qtgui/grc/qtgui_label.xml
index 5049118c47..3615574c4c 100644
--- a/gr-qtgui/grc/qtgui_label.xml
+++ b/gr-qtgui/grc/qtgui_label.xml
@@ -8,7 +8,6 @@
<block>
<name>QT GUI Label</name>
<key>variable_qtgui_label</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<import>from gnuradio import eng_notation</import>
<var_make>self.$(id) = $(id) = $value</var_make>
diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml
index 6b0555f98e..f2d42f1a5f 100644
--- a/gr-qtgui/grc/qtgui_range.xml
+++ b/gr-qtgui/grc/qtgui_range.xml
@@ -8,7 +8,6 @@
<block>
<name>QT GUI Range</name>
<key>variable_qtgui_range</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<import>import PyQt4.Qwt5 as Qwt</import>
<var_make>self.$(id) = $(id) = $value</var_make>
diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml
index 83d6ec2879..9ea9dc583f 100644
--- a/gr-qtgui/grc/qtgui_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_sink_x.xml
@@ -7,9 +7,8 @@
<block>
<name>QT GUI Sink</name>
<key>qtgui_sink_x</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
- <import>from gnuradio.qtgui import qtgui</import>
+ <import>from gnuradio import qtgui</import>
<import>from gnuradio.gr import firdes</import>
<import>import sip</import>
<make>#set $win = 'self._%s_win'%$id
@@ -24,8 +23,18 @@ qtgui.$(type.fcn)(
$plottime, \#plottime
$plotconst, \#plotconst
)
+self.$(id).set_update_time(1.0/$rate)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint()($win))
+
+#if $freqchangevar() is not None
+def $(id)_callback(p, num):
+ if num == 1 or num == 2: self.set_$(freqchangevar)(p.x())
+
+Qt.QObject.connect(self._$(id)_win, Qt.SIGNAL("plotPointSelected(QPointF, int)"), $(id)_callback )
+#end if
+
+</make>
<callback>set_frequency_range($fc, $bw)</callback>
<param>
<name>Type</name>
@@ -91,6 +100,12 @@ $(gui_hint()($win))</make>
<type>real</type>
</param>
<param>
+ <name>Update Rate</name>
+ <key>rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <param>
<name>Plot Frequency</name>
<key>plotfreq</key>
<value>True</value>
@@ -133,6 +148,13 @@ $(gui_hint()($win))</make>
<type>gui_hint</type>
<hide>part</hide>
</param>
+ <param>
+ <name>Clicked freq variable</name>
+ <key>freqchangevar</key>
+ <value>None</value>
+ <type>raw</type>
+ <hide>part</hide>
+ </param>
<sink>
<name>in</name>
<type>$type</type>
diff --git a/gr-qtgui/grc/qtgui_tab_widget.xml b/gr-qtgui/grc/qtgui_tab_widget.xml
index f900541093..c098c9fef5 100644
--- a/gr-qtgui/grc/qtgui_tab_widget.xml
+++ b/gr-qtgui/grc/qtgui_tab_widget.xml
@@ -7,7 +7,6 @@
<block>
<name>QT GUI Tab Widget</name>
<key>qtgui_tab_widget</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
<make>#set $win = 'self.%s'%$id
Qt.QTabWidget()
diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml
index 9c8da6fbcf..17b2cfd016 100644
--- a/gr-qtgui/grc/qtgui_time_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_time_sink_x.xml
@@ -7,9 +7,8 @@
<block>
<name>QT GUI Time Sink</name>
<key>qtgui_time_sink_x</key>
- <category>QT GUI Widgets</category>
<import>from PyQt4 import Qt</import>
- <import>from gnuradio.qtgui import qtgui</import>
+ <import>from gnuradio import qtgui</import>
<import>from gnuradio.gr import firdes</import>
<import>import sip</import>
<make>#set $win = 'self._%s_win'%$id
diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
new file mode 100644
index 0000000000..47de5b593c
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Sink
+###################################################
+ -->
+<block>
+ <name>QT GUI Waterfall Sink</name>
+ <key>qtgui_waterfall_sink_x</key>
+ <import>from PyQt4 import Qt</import>
+ <import>from gnuradio import qtgui</import>
+ <import>from gnuradio.gr import firdes</import>
+ <import>import sip</import>
+ <make>#set $win = 'self._%s_win'%$id
+qtgui.$(type.fcn)(
+ $fftsize, \#size
+ $wintype, \#wintype
+ $fc, \#fc
+ $bw, \#bw
+ $name, \#name
+)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+ <callback>set_frequency_range($fc, $bw)</callback>
+ <callback>set_update_time($t)</callback>
+ <callback>set_title($which, $title)</callback>
+ <callback>set_color($which, $color)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>complex</value>
+ <type>enum</type>
+ <option><name>Complex</name><key>complex</key><opt>fcn:waterfall_sink_c</opt></option>
+ <option><name>Float</name><key>float</key><opt>fcn:waterfall_sink_f</opt></option>
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <value>QT GUI Plot</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>FFT Size</name>
+ <key>fftsize</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Window Type</name>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ <type>int</type>
+ <hide>part</hide>
+ <option>
+ <name>Blackman-harris</name>
+ <key>firdes.WIN_BLACKMAN_hARRIS</key>
+ </option>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Center Frequency (Hz)</name>
+ <key>fc</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Bandwidth (Hz)</name>
+ <key>bw</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Update Rate</name>
+ <key>rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>1</nports>
+ </sink>
+ <doc>
+The GUI hint can be used to position the widget within the application. \
+The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
+Both the tab specification and the grid position are optional.
+ </doc>
+</block>
diff --git a/gr-qtgui/include/CMakeLists.txt b/gr-qtgui/include/qtgui/CMakeLists.txt
index ef4cb11752..d0d3d13fb5 100644
--- a/gr-qtgui/include/CMakeLists.txt
+++ b/gr-qtgui/include/qtgui/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Free Software Foundation, Inc.
+# Copyright 2010-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,12 +21,17 @@
# Install the header files
########################################################################
install(FILES
- gr_qtgui_api.h
- qtgui_time_sink_c.h
- qtgui_time_sink_f.h
- qtgui_sink_c.h
- qtgui_sink_f.h
- qtgui_util.h
- DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ api.h
+ time_sink_c.h
+ time_sink_f.h
+ freq_sink_c.h
+ freq_sink_f.h
+ const_sink_c.h
+ waterfall_sink_c.h
+ waterfall_sink_f.h
+ sink_c.h
+ sink_f.h
+ utils.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/qtgui
COMPONENT "qtgui_devel"
)
diff --git a/gr-qtgui/include/gr_qtgui_api.h b/gr-qtgui/include/qtgui/api.h
index c39add1e82..e88948e07b 100644
--- a/gr-qtgui/include/gr_qtgui_api.h
+++ b/gr-qtgui/include/qtgui/api.h
@@ -19,15 +19,15 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_GR_QTGUI_API_H
-#define INCLUDED_GR_QTGUI_API_H
+#ifndef INCLUDED_QTGUI_API_H
+#define INCLUDED_QTGUI_API_H
#include <gruel/attributes.h>
#ifdef gnuradio_qtgui_EXPORTS
-# define GR_QTGUI_API __GR_ATTR_EXPORT
+# define QTGUI_API __GR_ATTR_EXPORT
#else
-# define GR_QTGUI_API __GR_ATTR_IMPORT
+# define QTGUI_API __GR_ATTR_IMPORT
#endif
-#endif /* INCLUDED_GR_QTGUI_API_H */
+#endif /* INCLUDED_QTGUI_API_H */
diff --git a/gr-qtgui/include/qtgui/const_sink_c.h b/gr-qtgui/include/qtgui/const_sink_c.h
new file mode 100644
index 0000000000..48da4b9fa1
--- /dev/null
+++ b/gr-qtgui/include/qtgui/const_sink_c.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_CONST_SINK_C_H
+#define INCLUDED_QTGUI_CONST_SINK_C_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display the IQ constellation of multiple signals.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a complex
+ * streams and plots them on an IQ constellation plot.
+ */
+ class QTGUI_API const_sink_c : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::const_sink_c::sptr
+ typedef boost::shared_ptr<const_sink_c> sptr;
+
+ /*!
+ * \brief Build a complex PSD sink.
+ *
+ * \param size number of points to plot at once
+ * \param name title for the plot
+ * \param nconnections number of signals connected to sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(int which, const std::string &title) = 0;
+ virtual void set_color(int which, const std::string &color) = 0;
+ virtual void set_line_width(int which, int width) = 0;
+ virtual void set_line_style(int which, Qt::PenStyle style) = 0;
+ virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_CONST_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui/freq_sink_c.h b/gr-qtgui/include/qtgui/freq_sink_c.h
new file mode 100644
index 0000000000..2bef9035e8
--- /dev/null
+++ b/gr-qtgui/include/qtgui/freq_sink_c.h
@@ -0,0 +1,95 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_FREQ_SINK_C_H
+#define INCLUDED_QTGUI_FREQ_SINK_C_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals in frequency.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a complex
+ * streams and plots the PSD. Each signal is plotted with a
+ * different color, and the \a set_title and \a set_color
+ * functions can be used to change the lable and color for a given
+ * input number.
+ */
+ class QTGUI_API freq_sink_c : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::freq_sink_c::sptr
+ typedef boost::shared_ptr<freq_sink_c> sptr;
+
+ /*!
+ * \brief Build a complex PSD sink.
+ *
+ * \param fftsize size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param nconnections number of signals connected to sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+ virtual void set_fft_average(const float fftavg) = 0;
+ virtual float fft_average() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0;
+ virtual void set_fft_power_db(double min, double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(int which, const std::string &title) = 0;
+ virtual void set_color(int which, const std::string &color) = 0;
+ virtual void set_line_width(int which, int width) = 0;
+ virtual void set_line_style(int which, Qt::PenStyle style) = 0;
+ virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_FREQ_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui/freq_sink_f.h b/gr-qtgui/include/qtgui/freq_sink_f.h
new file mode 100644
index 0000000000..51c4ac10a1
--- /dev/null
+++ b/gr-qtgui/include/qtgui/freq_sink_f.h
@@ -0,0 +1,95 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_FREQ_SINK_F_H
+#define INCLUDED_QTGUI_FREQ_SINK_F_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals in frequency.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a floating
+ * point streams and plots the PSD. Each signal is plotted with a
+ * different color, and the \a set_title and \a set_color
+ * functions can be used to change the lable and color for a given
+ * input number.
+ */
+ class QTGUI_API freq_sink_f : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::freq_sink_f::sptr
+ typedef boost::shared_ptr<freq_sink_f> sptr;
+
+ /*!
+ * \brief Build a floating point PSD sink.
+ *
+ * \param fftsize size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param nconnections number of signals connected to sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+ virtual void set_fft_average(const float fftavg) = 0;
+ virtual float fft_average() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0;
+ virtual void set_fft_power_db(double min, double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(int which, const std::string &title) = 0;
+ virtual void set_color(int which, const std::string &color) = 0;
+ virtual void set_line_width(int which, int width) = 0;
+ virtual void set_line_style(int which, Qt::PenStyle style) = 0;
+ virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_FREQ_SINK_F_H */
diff --git a/gr-qtgui/include/qtgui/sink_c.h b/gr-qtgui/include/qtgui/sink_c.h
new file mode 100644
index 0000000000..f8d58ddbe0
--- /dev/null
+++ b/gr-qtgui/include/qtgui/sink_c.h
@@ -0,0 +1,98 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_SINK_C_H
+#define INCLUDED_QTGUI_SINK_C_H
+
+#include <qtgui/api.h>
+#include <gr_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display freq, spec, time, and const plots.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes a complex stream and
+ * plots it. The default action is to plot the signal as a PSD (FFT),
+ * spectrogram (waterfall), time domain I&Q, and constellation (I
+ * vs. Q) plots. The plots may be turned off by setting the
+ * appropriate boolean value in the constructor to False.
+ */
+
+ class QTGUI_API sink_c : virtual public gr_block
+ {
+ public:
+ // gr::qtgui::sink_c::sptr
+ typedef boost::shared_ptr<sink_c> sptr;
+
+ /*!
+ * \brief Build a complex qtgui sink.
+ *
+ * \param fftsize size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param plotfreq Toggle frequency plot on/off
+ * \param plotwaterfall Toggle waterfall plot on/off
+ * \param plottime Toggle time plot on/off
+ * \param plotconst Toggle constellation plot on/off
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+ virtual void set_fft_power_db(double min, double max) = 0;
+
+ //void set_time_domain_axis(double min, double max);
+ //void set_constellation_axis(double xmin, double xmax,
+ // double ymin, double ymax);
+ //void set_constellation_pen_size(int size);
+
+ virtual void set_update_time(double t) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui/sink_f.h b/gr-qtgui/include/qtgui/sink_f.h
new file mode 100644
index 0000000000..0af49ba9e2
--- /dev/null
+++ b/gr-qtgui/include/qtgui/sink_f.h
@@ -0,0 +1,98 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_SINK_F_H
+#define INCLUDED_QTGUI_SINK_F_H
+
+#include <qtgui/api.h>
+#include <gr_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display freq, spec, and time.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes a float stream and
+ * plots it. The default action is to plot the signal as a PSD (FFT),
+ * spectrogram (waterfall), and time domain plots. The plots may be
+ * turned off by setting the appropriate boolean value in the
+ * constructor to False.
+ */
+
+ class QTGUI_API sink_f : virtual public gr_block
+ {
+ public:
+ // gr::qtgui::sink_f::sptr
+ typedef boost::shared_ptr<sink_f> sptr;
+
+ /*!
+ * \brief Build a floating point qtgui sink.
+ *
+ * \param fftsize size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param plotfreq Toggle frequency plot on/off
+ * \param plotwaterfall Toggle waterfall plot on/off
+ * \param plottime Toggle time plot on/off
+ * \param plotconst Toggle constellation plot on/off
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+ virtual void set_fft_power_db(double min, double max) = 0;
+
+ //void set_time_domain_axis(double min, double max);
+ //void set_constellation_axis(double xmin, double xmax,
+ // double ymin, double ymax);
+ //void set_constellation_pen_size(int size);
+
+ virtual void set_update_time(double t) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_SINK_F_H */
diff --git a/gr-qtgui/include/qtgui/time_sink_c.h b/gr-qtgui/include/qtgui/time_sink_c.h
new file mode 100644
index 0000000000..17176e65f9
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_sink_c.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_TIME_SINK_C_H
+#define INCLUDED_QTGUI_TIME_SINK_C_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals in time.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a complex
+ * streams and plots them in the time domain. For each signal, both
+ * the signal's I and Q parts are plotted, and they are all plotted
+ * with a different color, and the \a set_title and \a set_color
+ * functions can be used to change the lable and color for a given
+ * input number.
+ */
+ class QTGUI_API time_sink_c : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::time_sink_c::sptr
+ typedef boost::shared_ptr<time_sink_c> sptr;
+
+ /*!
+ * \brief Build complex time sink
+ *
+ * \param size number of points to plot at once
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param nconnections number of signals connected to sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_time_domain_axis(double min, double max) = 0;
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(int which, const std::string &title) = 0;
+ virtual void set_color(int which, const std::string &color) = 0;
+ virtual void set_line_width(int which, int width) = 0;
+ virtual void set_line_style(int which, Qt::PenStyle style) = 0;
+ virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui/time_sink_f.h b/gr-qtgui/include/qtgui/time_sink_f.h
new file mode 100644
index 0000000000..df6ba9f554
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_sink_f.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_QTGUI_TIME_SINK_F_H
+#define INCLUDED_QTGUI_TIME_SINK_F_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals in time.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a float streams
+ * and plots them in the time domain. Each signal is plotted with a
+ * different color, and the \a set_title and \a set_color functions
+ * can be used to change the lable and color for a given input number.
+ */
+ class QTGUI_API time_sink_f : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::time_sink_f::sptr
+ typedef boost::shared_ptr<time_sink_f> sptr;
+
+ /*!
+ * \brief Build floating point time sink
+ *
+ * \param size number of points to plot at once
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param nconnections number of signals connected to sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_time_domain_axis(double min, double max) = 0;
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(int which, const std::string &title) = 0;
+ virtual void set_color(int which, const std::string &color) = 0;
+ virtual void set_line_width(int which, int width) = 0;
+ virtual void set_line_style(int which, Qt::PenStyle style) = 0;
+ virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_SINK_F_H */
diff --git a/gr-qtgui/include/qtgui_util.h b/gr-qtgui/include/qtgui/utils.h
index 2deaddb947..f490c48567 100644
--- a/gr-qtgui/include/qtgui_util.h
+++ b/gr-qtgui/include/qtgui/utils.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011 Free Software Foundation, Inc.
+ * Copyright 2011,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,16 +20,15 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_QTGUI_UTIL_H
-#define INCLUDED_QTGUI_UTIL_H
+#ifndef INCLUDED_QTGUI_UTILS_H
+#define INCLUDED_QTGUI_UTILS_H
#include <qevent.h>
-#include <gr_qtgui_api.h>
+#include <qtgui/api.h>
#include <qwt_plot_picker.h>
#include <qwt_picker_machine.h>
-
-class GR_QTGUI_API QwtDblClickPlotPicker: public QwtPlotPicker
+class QTGUI_API QwtDblClickPlotPicker: public QwtPlotPicker
{
public:
QwtDblClickPlotPicker(QwtPlotCanvas *);
@@ -38,20 +37,19 @@ public:
virtual QwtPickerMachine * stateMachine(int) const;
};
-class GR_QTGUI_API QwtPickerDblClickPointMachine: public QwtPickerMachine
+class QTGUI_API QwtPickerDblClickPointMachine: public QwtPickerMachine
{
public:
QwtPickerDblClickPointMachine();
~QwtPickerDblClickPointMachine();
#if QWT_VERSION < 0x060000
- virtual CommandList transition( const QwtEventPattern &eventPattern,
- const QEvent *e);
+ virtual CommandList
#else
virtual QList<QwtPickerMachine::Command>
- transition( const QwtEventPattern &eventPattern,
- const QEvent *e);
#endif
+ transition( const QwtEventPattern &eventPattern,
+ const QEvent *e);
};
-#endif /* INCLUDED_QTGUI_UTIL_H */
+#endif /* INCLUDED_QTGUI_UTILS_H */
diff --git a/gr-qtgui/include/qtgui/waterfall_sink_c.h b/gr-qtgui/include/qtgui/waterfall_sink_c.h
new file mode 100644
index 0000000000..838d50f44d
--- /dev/null
+++ b/gr-qtgui/include/qtgui/waterfall_sink_c.h
@@ -0,0 +1,100 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_WATERFALL_SINK_C_H
+#define INCLUDED_QTGUI_WATERFALL_SINK_C_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals on a
+ * waterfall (spectrogram) plot.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a complex
+ * streams and plots a waterfall (spectrogram) plot.
+ *
+ * Note that unlike the other qtgui sinks, this one does not
+ * support multiple input streams. We have yet to figure out a
+ * good way to display multiple, independent signals on this kind
+ * of a plot. If there are any suggestions or examples of this, we
+ * would love to see them. Otherwise, to display multiple signals
+ * here, it's probably best to sum the signals together and
+ * connect that here.
+ */
+ class QTGUI_API waterfall_sink_c : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::waterfall_sink_c::sptr
+ typedef boost::shared_ptr<waterfall_sink_c> sptr;
+
+
+ /*!
+ * \brief Build a complex waterfall sink.
+ *
+ * \param size size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+ virtual void set_fft_average(const float fftavg) = 0;
+ virtual float fft_average() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_color(const std::string &color) = 0;
+ virtual void set_line_width(int width) = 0;
+ virtual void set_line_style(Qt::PenStyle style) = 0;
+ virtual void set_line_marker(QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_WATERFALL_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui/waterfall_sink_f.h b/gr-qtgui/include/qtgui/waterfall_sink_f.h
new file mode 100644
index 0000000000..0ee38256c3
--- /dev/null
+++ b/gr-qtgui/include/qtgui/waterfall_sink_f.h
@@ -0,0 +1,99 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_WATERFALL_SINK_F_H
+#define INCLUDED_QTGUI_WATERFALL_SINK_F_H
+
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+
+#include <Python.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals on a
+ * waterfall (spectrogram) plot.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink the takes set of a floating
+ * point streams and plots a waterfall (spectrogram) plot.
+ *
+ * Note that unlike the other qtgui sinks, this one does not
+ * support multiple input streams. We have yet to figure out a
+ * good way to display multiple, independent signals on this kind
+ * of a plot. If there are any suggestions or examples of this, we
+ * would love to see them. Otherwise, to display multiple signals
+ * here, it's probably best to sum the signals together and
+ * connect that here.
+ */
+ class QTGUI_API waterfall_sink_f : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::waterfall_sink_f::sptr
+ typedef boost::shared_ptr<waterfall_sink_f> sptr;
+
+ /*!
+ * \brief Build a floating point waterfall sink.
+ *
+ * \param size size of the FFT to compute and display
+ * \param wintype type of window to apply (see filter/firdes.h)
+ * \param fc center frequency of signal (use for x-axis labels)
+ * \param bw bandwidth of signal (used to set x-axis labels)
+ * \param name title for the plot
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_fft_size(const int fftsize) = 0;
+ virtual int fft_size() const = 0;
+ virtual void set_fft_average(const float fftavg) = 0;
+ virtual float fft_average() const = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_color(const std::string &color) = 0;
+ virtual void set_line_width(int width) = 0;
+ virtual void set_line_style(Qt::PenStyle style) = 0;
+ virtual void set_line_marker(QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_WATERFALL_SINK_F_H */
diff --git a/gr-qtgui/include/qtgui_sink_c.h b/gr-qtgui/include/qtgui_sink_c.h
deleted file mode 100644
index 68fff368a9..0000000000
--- a/gr-qtgui/include/qtgui_sink_c.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,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.
- */
-
-#ifndef INCLUDED_QTGUI_SINK_C_H
-#define INCLUDED_QTGUI_SINK_C_H
-
-#include <Python.h>
-#include <gr_qtgui_api.h>
-#include <gr_block.h>
-#include <gr_firdes.h>
-#include <gri_fft.h>
-#include <qapplication.h>
-#include <gruel/high_res_timer.h>
-#include "SpectrumGUIClass.h"
-
-class qtgui_sink_c;
-typedef boost::shared_ptr<qtgui_sink_c> qtgui_sink_c_sptr;
-
-GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype,
- double fc=0, double bandwidth=1.0,
- const std::string &name="Spectrum Display",
- bool plotfreq=true, bool plotwaterfall=true,
- bool plottime=true, bool plotconst=true,
- QWidget *parent=NULL);
-
-/*!
- * \brief A graphical sink to display freq, spec, time, and const plots.
- * \ingroup qtgui_blk
- *
- * This is a QT-based graphical sink the takes a complex stream and
- * plots it. The default action is to plot the signal as a PSD (FFT),
- * spectrogram (waterfall), time domain I&Q, and constellation (I
- * vs. Q) plots. The plots may be turned off by setting the
- * appropriate boolean value in the constructor to False.
- */
-
-class GR_QTGUI_API qtgui_sink_c : public gr_block
-{
-private:
- friend GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
- qtgui_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
-
- void forecast(int noutput_items, gr_vector_int &ninput_items_required);
-
- void initialize();
-
- int d_fftsize;
- gr_firdes::win_type d_wintype;
- std::vector<float> d_window;
- double d_center_freq;
- double d_bandwidth;
- std::string d_name;
- gruel::high_res_timer_type d_last_update;
- bool d_update_active;
-
- bool d_shift;
- gri_fft_complex *d_fft;
-
- int d_index;
- gr_complex *d_residbuf;
-
- bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst;
-
- gruel::high_res_timer_type d_update_time;
-
- QWidget *d_parent;
- SpectrumGUIClass *d_main_gui;
-
- void windowreset();
- void buildwindow();
- void fftresize();
- void fft(const gr_complex *data_in, int size);
-
-public:
- ~qtgui_sink_c();
- void exec_();
- QWidget* qwidget();
- PyObject* pyqwidget();
-
- void set_frequency_range(const double centerfreq,
- const double bandwidth);
-
- void set_time_domain_axis(double min, double max);
- void set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax);
- void set_constellation_pen_size(int size);
- void set_frequency_axis(double min, double max);
-
- void set_update_time(double t);
-
- QApplication *d_qApplication;
-
- int general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_QTGUI_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui_sink_f.h b/gr-qtgui/include/qtgui_sink_f.h
deleted file mode 100644
index 709f02a2f5..0000000000
--- a/gr-qtgui/include/qtgui_sink_f.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,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.
- */
-
-#ifndef INCLUDED_QTGUI_SINK_F_H
-#define INCLUDED_QTGUI_SINK_F_H
-
-#include <Python.h>
-#include <gr_qtgui_api.h>
-#include <gr_block.h>
-#include <gr_firdes.h>
-#include <gri_fft.h>
-#include <qapplication.h>
-#include "SpectrumGUIClass.h"
-
-class qtgui_sink_f;
-typedef boost::shared_ptr<qtgui_sink_f> qtgui_sink_f_sptr;
-
-GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype,
- double fc=0, double bw=1.0,
- const std::string &name="Spectrum Display",
- bool plotfreq=true, bool plotwaterfall=true,
- bool plottime=true, bool plotconst=false,
- QWidget *parent=NULL);
-
-/*!
- * \brief A graphical sink to display freq, spec, and time.
- * \ingroup qtgui_blk
- *
- * This is a QT-based graphical sink the takes a float stream and
- * plots it. The default action is to plot the signal as a PSD (FFT),
- * spectrogram (waterfall), and time domain plots. The plots may be
- * turned off by setting the appropriate boolean value in the
- * constructor to False.
- */
-
-class GR_QTGUI_API qtgui_sink_f : public gr_block
-{
-private:
- friend GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
- qtgui_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
-
- void forecast(int noutput_items, gr_vector_int &ninput_items_required);
-
- void initialize();
-
- int d_fftsize;
- gr_firdes::win_type d_wintype;
- std::vector<float> d_window;
- double d_center_freq;
- double d_bandwidth;
- std::string d_name;
-
- bool d_shift;
- gri_fft_complex *d_fft;
-
- int d_index;
- float *d_residbuf;
-
- bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst;
-
- double d_update_time;
-
- QWidget *d_parent;
- SpectrumGUIClass *d_main_gui;
-
- void windowreset();
- void buildwindow();
- void fftresize();
- void fft(const float *data_in, int size);
-
-public:
- ~qtgui_sink_f();
- void exec_();
- QWidget* qwidget();
- PyObject* pyqwidget();
-
- void set_frequency_range(const double centerfreq,
- const double bandwidth);
-
- void set_time_domain_axis(double min, double max);
- void set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax);
- void set_constellation_pen_size(int size);
- void set_frequency_axis(double min, double max);
-
- void set_update_time(double t);
-
- QApplication *d_qApplication;
-
- int general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_QTGUI_SINK_F_H */
diff --git a/gr-qtgui/include/qtgui_time_sink_c.h b/gr-qtgui/include/qtgui_time_sink_c.h
deleted file mode 100644
index 561d796cfa..0000000000
--- a/gr-qtgui/include/qtgui_time_sink_c.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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.
- */
-
-#ifndef INCLUDED_QTGUI_TIME_SINK_C_H
-#define INCLUDED_QTGUI_TIME_SINK_C_H
-
-#include <Python.h>
-#include <gr_qtgui_api.h>
-#include <gr_sync_block.h>
-#include <gr_firdes.h>
-#include <gri_fft.h>
-#include <qapplication.h>
-#include <timedisplayform.h>
-
-class qtgui_time_sink_c;
-typedef boost::shared_ptr<qtgui_time_sink_c> qtgui_time_sink_c_sptr;
-
-GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnectons=1,
- QWidget *parent=NULL);
-
-/*!
- * \brief A graphical sink to display multiple signals in time.
- * \ingroup qtgui_blk
- *
- * This is a QT-based graphical sink the takes set of a complex
- * streams and plots them in the time domain. For each signal, both
- * the signal's I and Q parts are plotted, and they are all plotted
- * with a different color, and the \a set_title and \a set_color
- * functions can be used to change the lable and color for a given
- * input number.
- */
-class GR_QTGUI_API qtgui_time_sink_c : public gr_sync_block
-{
-private:
- friend GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent);
- qtgui_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent=NULL);
-
- void initialize();
-
- int d_size;
- double d_bandwidth;
- std::string d_name;
- int d_nconnections;
-
- int d_index;
- std::vector<double*> d_residbufs;
-
- double d_update_time;
-
- QWidget *d_parent;
- TimeDisplayForm *d_main_gui;
-
- gruel::high_res_timer_type d_current_time;
- gruel::high_res_timer_type d_last_time;
-
-public:
- ~qtgui_time_sink_c();
- void exec_();
- QWidget* qwidget();
- PyObject* pyqwidget();
-
- void set_time_domain_axis(double min, double max);
- void set_update_time(double t);
- void set_title(int which, const std::string &title);
- void set_color(int which, const std::string &color);
-
- QApplication *d_qApplication;
-
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_QTGUI_TIME_SINK_C_H */
diff --git a/gr-qtgui/include/qtgui_time_sink_f.h b/gr-qtgui/include/qtgui_time_sink_f.h
deleted file mode 100644
index 993e0556cf..0000000000
--- a/gr-qtgui/include/qtgui_time_sink_f.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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.
- */
-
-#ifndef INCLUDED_QTGUI_TIME_SINK_F_H
-#define INCLUDED_QTGUI_TIME_SINK_F_H
-
-#include <Python.h>
-#include <gr_qtgui_api.h>
-#include <gr_sync_block.h>
-#include <gr_firdes.h>
-#include <gri_fft.h>
-#include <qapplication.h>
-#include <timedisplayform.h>
-
-class qtgui_time_sink_f;
-typedef boost::shared_ptr<qtgui_time_sink_f> qtgui_time_sink_f_sptr;
-
-GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnectons=1,
- QWidget *parent=NULL);
-
-/*!
- * \brief A graphical sink to display multiple signals in time.
- * \ingroup qtgui_blk
- *
- * This is a QT-based graphical sink the takes set of a float streams
- * and plots them in the time domain. Each signal is plotted with a
- * different color, and the \a set_title and \a set_color functions
- * can be used to change the lable and color for a given input number.
- */
-class GR_QTGUI_API qtgui_time_sink_f : public gr_sync_block
-{
-private:
- friend GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent);
- qtgui_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent=NULL);
-
- void initialize();
-
- int d_size;
- double d_bandwidth;
- std::string d_name;
- int d_nconnections;
-
- int d_index;
- std::vector<double*> d_residbufs;
-
- double d_update_time;
-
- QWidget *d_parent;
- TimeDisplayForm *d_main_gui;
-
- gruel::high_res_timer_type d_current_time;
- gruel::high_res_timer_type d_last_time;
-
-public:
- ~qtgui_time_sink_f();
- void exec_();
- QWidget* qwidget();
- PyObject* pyqwidget();
-
- void set_time_domain_axis(double min, double max);
- void set_update_time(double t);
- void set_title(int which, const std::string &title);
- void set_color(int which, const std::string &color);
-
- QApplication *d_qApplication;
-
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_QTGUI_TIME_SINK_F_H */
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index 2dc35e81cb..beebd98cc5 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -22,7 +22,13 @@
########################################################################
set(qtgui_moc_hdrs
spectrumdisplayform.h
+ displayform.h
timedisplayform.h
+ freqdisplayform.h
+ constellationdisplayform.h
+ waterfalldisplayform.h
+ form_menus.h
+ DisplayPlot.h
FrequencyDisplayPlot.h
TimeDomainDisplayPlot.h
WaterfallDisplayPlot.h
@@ -41,20 +47,30 @@ endif(NOT EXISTS ${spectrum_ui_hdr})
set(qtgui_srcs
${qtgui_moc_srcs}
${qtgui_ui_hdrs}
+ DisplayPlot.cc
FrequencyDisplayPlot.cc
TimeDomainDisplayPlot.cc
WaterfallDisplayPlot.cc
waterfallGlobalData.cc
ConstellationDisplayPlot.cc
spectrumdisplayform.cc
+ displayform.cc
timedisplayform.cc
+ freqdisplayform.cc
+ constellationdisplayform.cc
+ waterfalldisplayform.cc
SpectrumGUIClass.cc
spectrumUpdateEvents.cc
plot_waterfall.cc
- qtgui_sink_c.cc
- qtgui_sink_f.cc
- qtgui_time_sink_c.cc
- qtgui_time_sink_f.cc
+ sink_c_impl.cc
+ sink_f_impl.cc
+ time_sink_c_impl.cc
+ time_sink_f_impl.cc
+ freq_sink_c_impl.cc
+ freq_sink_f_impl.cc
+ const_sink_c_impl.cc
+ waterfall_sink_c_impl.cc
+ waterfall_sink_f_impl.cc
qtgui_util.cc
)
@@ -63,12 +79,18 @@ set(qtgui_srcs
########################################################################
include_directories(
${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${GR_QTGUI_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
+include_directories(${FFTW3F_INCLUDE_DIRS})
+link_directories(${FFTW3F_LIBRARY_DIRS})
+
include_directories(${QWT_INCLUDE_DIRS})
link_directories(${QWT_LIBRARY_DIRS})
@@ -80,9 +102,13 @@ include_directories(${PYTHON_INCLUDE_PATH}) #deprecated for dirs (cmake 2.6)
########################################################################
list(APPEND qtgui_libs
gnuradio-core
+ gnuradio-fft
+ gnuradio-filter
+ volk
${QT_LIBRARIES}
${QWT_LIBRARIES}
${PYTHON_LIBRARIES}
+ ${FFTW3F_LIBRARIES}
)
add_definitions(-DQWT_DLL) #setup QWT library linkage
@@ -94,6 +120,7 @@ GR_LIBRARY_FOO(gnuradio-qtgui RUNTIME_COMPONENT "qtgui_runtime" DEVEL_COMPONENT
# Install the header files
########################################################################
install(FILES
+ DisplayPlot.h
FrequencyDisplayPlot.h
TimeDomainDisplayPlot.h
WaterfallDisplayPlot.h
@@ -101,7 +128,12 @@ install(FILES
ConstellationDisplayPlot.h
plot_waterfall.h
spectrumdisplayform.h
+ displayform.h
timedisplayform.h
+ freqdisplayform.h
+ constellationdisplayform.h
+ waterfalldisplayform.h
+ form_menus.h
SpectrumGUIClass.h
spectrumUpdateEvents.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc
index 7a595fef45..5bc89f83fa 100644
--- a/gr-qtgui/lib/ConstellationDisplayPlot.cc
+++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,6 +27,7 @@
#include <qwt_scale_draw.h>
#include <qwt_legend.h>
+#include <QColor>
#include <iostream>
class ConstellationDisplayZoomer: public QwtPlotZoomer
@@ -47,42 +48,22 @@ public:
protected:
using QwtPlotZoomer::trackerText;
- virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ virtual QwtText trackerText( const QPoint& p ) const
{
- QwtText t(QString("(%1, %2)").arg(p.x(), 0, 'f', 4).
- arg(p.y(), 0, 'f', 4));
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ QwtText t(QString("(%1, %2)").arg(dp.x(), 0, 'f', 4).
+ arg(dp.y(), 0, 'f', 4));
return t;
}
};
-ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent)
- : QwtPlot(parent)
+ConstellationDisplayPlot::ConstellationDisplayPlot(int nplots, QWidget* parent)
+ : DisplayPlot(nplots, parent)
{
- _lastReplot = 0;
-
resize(parent->width(), parent->height());
_numPoints = 1024;
_penSize = 5;
- _realDataPoints = new double[_numPoints];
- _imagDataPoints = new double[_numPoints];
-
- // Disable polygon clipping
-#if QWT_VERSION < 0x060000
- QwtPainter::setDeviceClipping(false);
-#else
- QwtPainter::setPolylineSplitting(false);
-#endif
-
-#if QWT_VERSION < 0x060000
- // We don't need the cache here
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
-#endif
-
- QPalette palette;
- palette.setColor(canvas()->backgroundRole(), QColor("white"));
- canvas()->setPalette(palette);
setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
set_xaxis(-2.0, 2.0);
@@ -92,21 +73,6 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent)
set_yaxis(-2.0, 2.0);
setAxisTitle(QwtPlot::yLeft, "Quadrature");
- // Automatically deleted when parent is deleted
- _plot_curve = new QwtPlotCurve("Constellation Points");
- _plot_curve->attach(this);
- _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- _plot_curve->setStyle(QwtPlotCurve::Dots);
-
-#if QWT_VERSION < 0x060000
- _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints);
-#else
- _plot_curve->setRawSamples(_realDataPoints, _imagDataPoints, _numPoints);
-#endif
-
- memset(_realDataPoints, 0x0, _numPoints*sizeof(double));
- memset(_imagDataPoints, 0x0, _numPoints*sizeof(double));
-
_zoomer = new ConstellationDisplayZoomer(canvas());
#if QWT_VERSION < 0x060000
@@ -118,56 +84,55 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent)
_zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
Qt::RightButton);
- _panner = new QwtPlotPanner(canvas());
- _panner->setAxisEnabled(QwtPlot::yRight, false);
- _panner->setMouseButton(Qt::MidButton);
-
- // Avoid jumping when labels with more/less digits
- // appear/disappear when scrolling vertically
-
- const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
- QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
- sd->setMinimumExtent( fm.width("100.00") );
-
const QColor c(Qt::darkRed);
_zoomer->setRubberBandPen(c);
_zoomer->setTrackerPen(c);
- // emit the position of clicks on widget
- _picker = new QwtDblClickPlotPicker(canvas());
+ QList<QColor> colors;
+ colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
+ << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta)
+ << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed)
+ << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray);
+
+ // Setup dataPoints and plot vectors
+ // Automatically deleted when parent is deleted
+ for(int i = 0; i < _nplots; i++) {
+ _realDataPoints.push_back(new double[_numPoints]);
+ _imagDataPoints.push_back(new double[_numPoints]);
+ memset(_realDataPoints[i], 0x0, _numPoints*sizeof(double));
+ memset(_imagDataPoints[i], 0x0, _numPoints*sizeof(double));
+
+ _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
+ _plot_curve[i]->attach(this);
+ _plot_curve[i]->setPen(QPen(colors[i]));
+
+ QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7));
#if QWT_VERSION < 0x060000
- connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
- this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
+ _plot_curve[i]->setRawData(_realDataPoints[i], _imagDataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(*symbol);
#else
- connect(_picker, SIGNAL(selected(const QPointF &)),
- this, SLOT(OnPickerPointSelected6(const QPointF &)));
+ _plot_curve[i]->setRawSamples(_realDataPoints[i], _imagDataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(symbol);
#endif
- connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool ) ),
- this, SLOT(LegendEntryChecked(QwtPlotItem *, bool ) ));
+ setLineStyle(i, Qt::NoPen);
+ setLineMarker(i, QwtSymbol::Ellipse);
+ }
}
ConstellationDisplayPlot::~ConstellationDisplayPlot()
{
- delete[] _realDataPoints;
- delete[] _imagDataPoints;
+ for(int i = 0; i < _nplots; i++) {
+ delete [] _realDataPoints[i];
+ delete [] _imagDataPoints[i];
+ }
// _fft_plot_curves deleted when parent deleted
// _zoomer and _panner deleted when parent deleted
}
void
-ConstellationDisplayPlot::set_pen_size(int size)
-{
- if(size > 0 && size < 30){
- _penSize = size;
- _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
-}
-
-
-void
ConstellationDisplayPlot::set_xaxis(double min, double max)
{
setAxisScale(QwtPlot::xBottom, min, max);
@@ -187,69 +152,72 @@ ConstellationDisplayPlot::set_axis(double xmin, double xmax,
set_yaxis(ymin, ymax);
}
-void ConstellationDisplayPlot::replot()
+void
+ConstellationDisplayPlot::set_pen_size(int size)
{
- QwtPlot::replot();
+ if(size > 0 && size < 30){
+ _penSize = size;
+ for(int i = 0; i < _nplots; i++) {
+ _plot_curve[i]->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ }
+ }
}
void
-ConstellationDisplayPlot::resizeSlot( QSize *s )
+ConstellationDisplayPlot::replot()
{
- resize(s->width(), s->height());
+ QwtPlot::replot();
}
-void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints,
- const double* imagDataPoints,
- const int64_t numDataPoints,
- const double timeInterval)
-{
- if((numDataPoints > 0) &&
- (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) {
- if(numDataPoints != _numPoints){
- _numPoints = numDataPoints;
-
- delete[] _realDataPoints;
- delete[] _imagDataPoints;
- _realDataPoints = new double[_numPoints];
- _imagDataPoints = new double[_numPoints];
+void
+ConstellationDisplayPlot::PlotNewData(const std::vector<double*> realDataPoints,
+ const std::vector<double*> imagDataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval)
+{
+ if(!_stop) {
+ if((numDataPoints > 0)) {
+ if(numDataPoints != _numPoints) {
+ _numPoints = numDataPoints;
+
+ for(int i = 0; i < _nplots; i++) {
+ delete [] _realDataPoints[i];
+ delete [] _imagDataPoints[i];
+ _realDataPoints[i] = new double[_numPoints];
+ _imagDataPoints[i] = new double[_numPoints];
#if QWT_VERSION < 0x060000
- _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints);
+ _plot_curve[i]->setRawData(_realDataPoints[i], _imagDataPoints[i], _numPoints);
#else
- _plot_curve->setRawSamples(_realDataPoints, _imagDataPoints, _numPoints);
+ _plot_curve[i]->setRawSamples(_realDataPoints[i], _imagDataPoints[i], _numPoints);
#endif
- }
+ }
+ }
- memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double));
- memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double));
+ for(int i = 0; i < _nplots; i++) {
+ memcpy(_realDataPoints[i], realDataPoints[i], numDataPoints*sizeof(double));
+ memcpy(_imagDataPoints[i], imagDataPoints[i], numDataPoints*sizeof(double));
+ }
- replot();
+ replot();
- _lastReplot = gruel::high_res_timer_now();
+ }
}
}
void
-ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
-{
- plotItem->setVisible(!on);
-}
-
-void
-ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
-{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
-}
-
-void
-ConstellationDisplayPlot::OnPickerPointSelected6(const QPointF & p)
+ConstellationDisplayPlot::PlotNewData(const double* realDataPoints,
+ const double* imagDataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval)
{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
+ std::vector<double*> vecRealDataPoints;
+ std::vector<double*> vecImagDataPoints;
+ vecRealDataPoints.push_back((double*)realDataPoints);
+ vecImagDataPoints.push_back((double*)imagDataPoints);
+ PlotNewData(vecRealDataPoints, vecImagDataPoints,
+ numDataPoints, timeInterval);
}
#endif /* CONSTELLATION_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h
index 9e0f6f26a8..f3cbeef1cb 100644
--- a/gr-qtgui/lib/ConstellationDisplayPlot.h
+++ b/gr-qtgui/lib/ConstellationDisplayPlot.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,43 +20,34 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef CONSTELLATION_DISPLAY_PLOT_HPP
-#define CONSTELLATION_DISPLAY_PLOT_HPP
+#ifndef CONSTELLATION_DISPLAY_PLOT_H
+#define CONSTELLATION_DISPLAY_PLOT_H
#include <stdint.h>
#include <cstdio>
-#include <qwt_plot.h>
-#include <qwt_painter.h>
-#include <qwt_plot_canvas.h>
-#include <qwt_plot_curve.h>
-#include <qwt_scale_engine.h>
-#include <qwt_scale_widget.h>
-#include <qwt_plot_zoomer.h>
-#include <qwt_plot_panner.h>
-#include <qwt_plot_marker.h>
-#include <gruel/high_res_timer.h>
-#include <qwt_symbol.h>
-#include <qtgui_util.h>
+#include <vector>
+#include "DisplayPlot.h"
-#if QWT_VERSION >= 0x060000
-#include <qwt_point_3d.h> // doesn't seem necessary, but is...
-#include <qwt_compat.h>
-#endif
-
-class ConstellationDisplayPlot : public QwtPlot
+class ConstellationDisplayPlot : public DisplayPlot
{
Q_OBJECT
public:
- ConstellationDisplayPlot(QWidget*);
+ ConstellationDisplayPlot(int nplots, QWidget*);
virtual ~ConstellationDisplayPlot();
+ void PlotNewData(const std::vector<double*> realDataPoints,
+ const std::vector<double*> imagDataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval);
+
+ // Old method to be removed
void PlotNewData(const double* realDataPoints,
const double* imagDataPoints,
const int64_t numDataPoints,
const double timeInterval);
- virtual void replot();
+ void replot();
void set_xaxis(double min, double max);
void set_yaxis(double min, double max);
@@ -65,37 +56,13 @@ public:
void set_pen_size(int size);
public slots:
- void resizeSlot( QSize *s );
-
- // Because of the preprocessing of slots in QT, these are no
- // easily separated by the version check. Make one for each
- // version until it's worked out.
- void OnPickerPointSelected(const QwtDoublePoint & p);
- void OnPickerPointSelected6(const QPointF & p);
-
-signals:
- void plotPointSelected(const QPointF p);
-
-protected slots:
- void LegendEntryChecked(QwtPlotItem *plotItem, bool on);
-
-protected:
+ // set axis
private:
- QwtPlotCurve* _plot_curve;
-
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
- QwtDblClickPlotPicker *_picker;
-
- double* _realDataPoints;
- double* _imagDataPoints;
-
- gruel::high_res_timer_type _lastReplot;
+ std::vector<double*> _realDataPoints;
+ std::vector<double*> _imagDataPoints;
- int64_t _numPoints;
int64_t _penSize;
};
-#endif /* CONSTELLATION_DISPLAY_PLOT_HPP */
+#endif /* CONSTELLATION_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/DisplayPlot.cc b/gr-qtgui/lib/DisplayPlot.cc
new file mode 100644
index 0000000000..577b4f1483
--- /dev/null
+++ b/gr-qtgui/lib/DisplayPlot.cc
@@ -0,0 +1,221 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 <DisplayPlot.h>
+
+#include <qwt_scale_draw.h>
+#include <qwt_legend.h>
+#include <QColor>
+#include <cmath>
+#include <iostream>
+
+DisplayPlot::DisplayPlot(int nplots, QWidget* parent)
+ : QwtPlot(parent), _nplots(nplots), _stop(false)
+{
+ resize(parent->width(), parent->height());
+
+ // Disable polygon clipping
+#if QWT_VERSION < 0x060000
+ QwtPainter::setDeviceClipping(false);
+#else
+ QwtPainter::setPolylineSplitting(false);
+#endif
+
+#if QWT_VERSION < 0x060000
+ // We don't need the cache here
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
+#endif
+
+ QPalette palette;
+ palette.setColor(canvas()->backgroundRole(), QColor("white"));
+ canvas()->setPalette(palette);
+
+ _panner = new QwtPlotPanner(canvas());
+ _panner->setAxisEnabled(QwtPlot::yRight, false);
+ _panner->setMouseButton(Qt::MidButton);
+
+ // emit the position of clicks on widget
+ _picker = new QwtDblClickPlotPicker(canvas());
+
+#if QWT_VERSION < 0x060000
+ connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
+ this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
+#else
+ _picker->setStateMachine(new QwtPickerDblClickPointMachine());
+ connect(_picker, SIGNAL(selected(const QPointF &)),
+ this, SLOT(OnPickerPointSelected6(const QPointF &)));
+#endif
+
+ // Configure magnify on mouse wheel
+ _magnifier = new QwtPlotMagnifier(canvas());
+ _magnifier->setAxisEnabled(QwtPlot::xBottom, false);
+
+ // Avoid jumping when labels with more/less digits
+ // appear/disappear when scrolling vertically
+
+ const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
+ QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
+ sd->setMinimumExtent( fm.width("100.00") );
+
+ QwtLegend* legendDisplay = new QwtLegend(this);
+ legendDisplay->setItemMode(QwtLegend::CheckableItem);
+ insertLegend(legendDisplay);
+
+ connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),
+ this, SLOT(LegendEntryChecked(QwtPlotItem *, bool)));
+}
+
+DisplayPlot::~DisplayPlot()
+{
+ // _zoomer and _panner deleted when parent deleted
+}
+
+void
+DisplayPlot::setYaxis(double min, double max)
+{
+ setAxisScale(QwtPlot::yLeft, min, max);
+ _zoomer->setZoomBase();
+}
+
+void
+DisplayPlot::setXaxis(double min, double max)
+{
+ setAxisScale(QwtPlot::xBottom, min, max);
+ _zoomer->setZoomBase();
+}
+
+void
+DisplayPlot::setTitle(int which, QString title)
+{
+ _plot_curve[which]->setTitle(title);
+}
+
+QString
+DisplayPlot::title(int which)
+{
+ return _plot_curve[which]->title().text();
+}
+
+void
+DisplayPlot::setColor(int which, QString color)
+{
+ // Set the color of the pen
+ QPen pen(_plot_curve[which]->pen());
+ pen.setColor(color);
+ _plot_curve[which]->setPen(pen);
+
+ // And set the color of the markers
+#if QWT_VERSION < 0x060000
+ //_plot_curve[which]->setBrush(QBrush(QColor(color)));
+ _plot_curve[which]->setPen(pen);
+
+ QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol();
+ setLineMarker(which, sym.style());
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ sym->setColor(color);
+ sym->setPen(pen);
+ _plot_curve[which]->setSymbol(sym);
+#endif
+}
+
+void
+DisplayPlot::setLineWidth(int which, int width)
+{
+ // Set the new line width
+ QPen pen(_plot_curve[which]->pen());
+ pen.setWidth(width);
+ _plot_curve[which]->setPen(pen);
+
+ // Scale the marker size proportionally
+#if QWT_VERSION < 0x060000
+ QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol();
+ sym.setSize(7+10*log10(width), 7+10*log10(width));
+ _plot_curve[which]->setSymbol(sym);
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ sym->setSize(7+10*log10(width), 7+10*log10(width));
+ _plot_curve[which]->setSymbol(sym);
+#endif
+}
+
+void
+DisplayPlot::setLineStyle(int which, Qt::PenStyle style)
+{
+ QPen pen(_plot_curve[which]->pen());
+ pen.setStyle(style);
+ _plot_curve[which]->setPen(pen);
+}
+
+void
+DisplayPlot::setLineMarker(int which, QwtSymbol::Style marker)
+{
+#if QWT_VERSION < 0x060000
+ QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol();
+ QPen pen(_plot_curve[which]->pen());
+ QBrush brush(pen.color());
+ sym.setStyle(marker);
+ sym.setPen(pen);
+ sym.setBrush(brush);
+ _plot_curve[which]->setSymbol(sym);
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ sym->setStyle(marker);
+ _plot_curve[which]->setSymbol(sym);
+#endif
+}
+
+void
+DisplayPlot::setStop(bool on)
+{
+ _stop = on;
+}
+
+void
+DisplayPlot::resizeSlot( QSize *s )
+{
+ // -10 is to spare some room for the legend and x-axis label
+ resize(s->width()-10, s->height()-10);
+}
+
+void DisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
+{
+ plotItem->setVisible(!on);
+ replot();
+}
+
+void
+DisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
+{
+ QPointF point = p;
+ //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
+ emit plotPointSelected(point);
+}
+
+void
+DisplayPlot::OnPickerPointSelected6(const QPointF & p)
+{
+ QPointF point = p;
+ //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
+ emit plotPointSelected(point);
+}
diff --git a/gr-qtgui/lib/DisplayPlot.h b/gr-qtgui/lib/DisplayPlot.h
new file mode 100644
index 0000000000..975a92a18d
--- /dev/null
+++ b/gr-qtgui/lib/DisplayPlot.h
@@ -0,0 +1,101 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2010,2011,2012 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.
+ */
+
+#ifndef DOMAIN_DISPLAY_PLOT_H
+#define DOMAIN_DISPLAY_PLOT_H
+
+#include <stdint.h>
+#include <cstdio>
+#include <vector>
+#include <qwt_plot.h>
+#include <qwt_painter.h>
+#include <qwt_plot_canvas.h>
+#include <qwt_plot_curve.h>
+#include <qwt_scale_engine.h>
+#include <qwt_scale_widget.h>
+#include <qwt_plot_zoomer.h>
+#include <qwt_plot_panner.h>
+#include <qwt_plot_magnifier.h>
+#include <qwt_plot_marker.h>
+#include <qwt_symbol.h>
+#include <qtgui/utils.h>
+
+#if QWT_VERSION >= 0x060000
+#include <qwt_compat.h>
+#endif
+
+class DisplayPlot:public QwtPlot{
+ Q_OBJECT
+
+public:
+ DisplayPlot(int nplots, QWidget*);
+ virtual ~DisplayPlot();
+
+ virtual void replot() = 0;
+
+ // Make sure to create your won PlotNewData method in the derived
+ // class:
+ // void PlotNewData(...);
+
+public slots:
+ void setYaxis(double min, double max);
+ void setXaxis(double min, double max);
+ void setTitle(int which, QString title);
+ void setColor(int which, QString color);
+ void setLineWidth(int which, int width);
+ void setLineStyle(int which, Qt::PenStyle style);
+ void setLineMarker(int which, QwtSymbol::Style marker);
+
+ void setStop(bool on);
+
+ QString title(int which);
+
+ void resizeSlot(QSize *s);
+
+ // Because of the preprocessing of slots in QT, these are not
+ // easily separated by the version check. Make one for each
+ // version until it's worked out.
+ void OnPickerPointSelected(const QwtDoublePoint & p);
+ void OnPickerPointSelected6(const QPointF & p);
+
+signals:
+ void plotPointSelected(const QPointF p);
+
+protected slots:
+ void LegendEntryChecked(QwtPlotItem *plotItem, bool on);
+
+protected:
+ int _nplots;
+ std::vector<QwtPlotCurve*> _plot_curve;
+
+ QwtPlotPanner* _panner;
+ QwtPlotZoomer* _zoomer;
+
+ QwtDblClickPlotPicker *_picker;
+ QwtPlotMagnifier *_magnifier;
+
+ int64_t _numPoints;
+
+ bool _stop;
+};
+
+#endif /* DOMAIN_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc
index b74d460150..c9fb94ad68 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.cc
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc
@@ -25,73 +25,28 @@
#include <FrequencyDisplayPlot.h>
+#include "qtgui_types.h"
#include <qwt_scale_draw.h>
-
-class FreqPrecisionClass
-{
-public:
- FreqPrecisionClass(const int freqPrecision)
- {
- _frequencyPrecision = freqPrecision;
- }
-
- virtual ~FreqPrecisionClass()
- {
- }
-
- virtual unsigned int GetFrequencyPrecision() const
- {
- return _frequencyPrecision;
- }
-
- virtual void SetFrequencyPrecision(const unsigned int newPrecision)
- {
- _frequencyPrecision = newPrecision;
- }
-protected:
- unsigned int _frequencyPrecision;
-
-private:
-
-};
-
-class FreqDisplayScaleDraw: public QwtScaleDraw, public FreqPrecisionClass
-{
-public:
- FreqDisplayScaleDraw(const unsigned int precision)
- : QwtScaleDraw(), FreqPrecisionClass(precision)
- {
- }
-
- virtual ~FreqDisplayScaleDraw()
- {
- }
-
- virtual QwtText label(double value) const
- {
- return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision());
- }
-
-protected:
-
-private:
-
-};
-
-class FreqDisplayZoomer: public QwtPlotZoomer, public FreqPrecisionClass
+#include <qwt_legend.h>
+#include <qwt_legend_item.h>
+#include <QColor>
+#include <iostream>
+
+/***********************************************************************
+ * Widget to provide mouse pointer coordinate text
+ **********************************************************************/
+class FreqDisplayZoomer: public QwtPlotZoomer, public FreqOffsetAndPrecisionClass
{
public:
FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision)
- : QwtPlotZoomer(canvas),FreqPrecisionClass(freqPrecision)
+ : QwtPlotZoomer(canvas),
+ FreqOffsetAndPrecisionClass(freqPrecision)
{
setTrackerMode(QwtPicker::AlwaysOn);
}
-
- virtual ~FreqDisplayZoomer(){
-
- }
-
- virtual void updateTrackerText(){
+
+ virtual void updateTrackerText()
+ {
updateDisplay();
}
@@ -102,11 +57,12 @@ public:
protected:
using QwtPlotZoomer::trackerText;
- virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ virtual QwtText trackerText(QPoint const &p) const
{
- QwtText t(QString("%1 %2, %3 dB").
- arg(p.x(), 0, 'f', GetFrequencyPrecision()).
- arg(_unitType.c_str()).arg(p.y(), 0, 'f', 2));
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ QwtText t(QString("%1 %2, %3 dB")
+ .arg(dp.x(), 0, 'f', GetFrequencyPrecision())
+ .arg(_unitType.c_str()).arg(dp.y(), 0, 'f', 2));
return t;
}
@@ -114,41 +70,23 @@ private:
std::string _unitType;
};
-FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
- : QwtPlot(parent)
+
+/***********************************************************************
+ * Main frequency display plotter widget
+ **********************************************************************/
+FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent)
+ : DisplayPlot(nplots, parent)
{
_startFrequency = 0;
_stopFrequency = 4000;
- _lastReplot = 0;
-
- resize(parent->width(), parent->height());
-
_useCenterFrequencyFlag = false;
_numPoints = 1024;
- _dataPoints = new double[_numPoints];
_minFFTPoints = new double[_numPoints];
_maxFFTPoints = new double[_numPoints];
_xAxisPoints = new double[_numPoints];
- // Disable polygon clipping
-#if QWT_VERSION < 0x060000
- QwtPainter::setDeviceClipping(false);
-#else
- QwtPainter::setPolylineSplitting(false);
-#endif
-
-#if QWT_VERSION < 0x060000
- // We don't need the cache here
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
-#endif
-
- QPalette palette;
- palette.setColor(canvas()->backgroundRole(), QColor("white"));
- canvas()->setPalette(palette);
-
setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
@@ -158,16 +96,31 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
setAxisTitle(QwtPlot::yLeft, "Power (dB)");
- // Automatically deleted when parent is deleted
- _fft_plot_curve = new QwtPlotCurve("Power Spectrum");
- _fft_plot_curve->attach(this);
- _fft_plot_curve->setPen(QPen(Qt::blue));
+ QList<QColor> colors;
+ colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
+ << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta)
+ << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed)
+ << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray);
+ // Automatically deleted when parent is deleted
+ for(int i = 0; i < _nplots; i++) {
+ _dataPoints.push_back(new double[_numPoints]);
+ memset(_dataPoints[i], 0x0, _numPoints*sizeof(double));
+
+ _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
+ _plot_curve[i]->attach(this);
+ _plot_curve[i]->setPen(QPen(colors[i]));
+
+ const QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7));
+
#if QWT_VERSION < 0x060000
- _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
+ _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(*symbol);
#else
- _fft_plot_curve->setRawSamples(_xAxisPoints, _dataPoints, _numPoints);
+ _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(symbol);
#endif
+ }
_min_fft_plot_curve = new QwtPlotCurve("Minimum Power");
_min_fft_plot_curve->attach(this);
@@ -203,7 +156,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
_upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine));
_upper_intensity_marker->attach(this);
- memset(_dataPoints, 0x0, _numPoints*sizeof(double));
memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
for(int64_t number = 0; number < _numPoints; number++){
@@ -248,21 +200,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
replot();
- // emit the position of clicks on widget
- _picker = new QwtDblClickPlotPicker(canvas());
-
-#if QWT_VERSION < 0x060000
- connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
- this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
-#else
- connect(_picker, SIGNAL(selected(const QPointF &)),
- this, SLOT(OnPickerPointSelected6(const QPointF &)));
-#endif
-
- // Configure magnify on mouse wheel
- _magnifier = new QwtPlotMagnifier(canvas());
- _magnifier->setAxisEnabled(QwtPlot::xBottom, false);
-
_zoomer = new FreqDisplayZoomer(canvas(), 0);
#if QWT_VERSION < 0x060000
@@ -274,16 +211,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
_zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
Qt::RightButton);
- _panner = new QwtPlotPanner(canvas());
- _panner->setAxisEnabled(QwtPlot::yRight, false);
- _panner->setMouseButton(Qt::MidButton);
-
- // Avoid jumping when labels with more/less digits
- // appear/disappear when scrolling vertically
-
- const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
- QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
- sd->setMinimumExtent( fm.width("100.00") );
const QColor c(Qt::darkRed);
_zoomer->setRubberBandPen(c);
@@ -291,17 +218,24 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
// Do this after the zoomer has been built
_resetXAxisPoints();
+
+ // Turn off min/max hold plots in legend
+ QWidget *w;
+ QwtLegend* legendDisplay = legend();
+ w = legendDisplay->find(_min_fft_plot_curve);
+ ((QwtLegendItem*)w)->setChecked(true);
+ w = legendDisplay->find(_max_fft_plot_curve);
+ ((QwtLegendItem*)w)->setChecked(true);
}
FrequencyDisplayPlot::~FrequencyDisplayPlot()
{
- delete[] _dataPoints;
+ for(int i = 0; i < _nplots; i++)
+ delete [] _dataPoints[i];
+
delete[] _maxFFTPoints;
delete[] _minFFTPoints;
delete[] _xAxisPoints;
-
- // _fft_plot_curves deleted when parent deleted
- // _zoomer and _panner deleted when parent deleted
}
void
@@ -390,73 +324,83 @@ FrequencyDisplayPlot::replot()
}
void
-FrequencyDisplayPlot::resizeSlot( QSize *s )
-{
- resize(s->width(), s->height());
-}
-
-void
-FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints,
+FrequencyDisplayPlot::PlotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
const double noiseFloorAmplitude, const double peakFrequency,
const double peakAmplitude, const double timeInterval)
{
- // Only update plot if there is data and if the time interval has elapsed
- if((numDataPoints > 0) &&
- (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) {
-
- if(numDataPoints != _numPoints) {
- _numPoints = numDataPoints;
-
- delete[] _dataPoints;
- delete[] _minFFTPoints;
- delete[] _maxFFTPoints;
- delete[] _xAxisPoints;
- _dataPoints = new double[_numPoints];
- _xAxisPoints = new double[_numPoints];
- _minFFTPoints = new double[_numPoints];
- _maxFFTPoints = new double[_numPoints];
+ if(!_stop) {
+ if(numDataPoints > 0) {
+ if(numDataPoints != _numPoints) {
+ _numPoints = numDataPoints;
+
+ delete[] _minFFTPoints;
+ delete[] _maxFFTPoints;
+ delete[] _xAxisPoints;
+ _xAxisPoints = new double[_numPoints];
+ _minFFTPoints = new double[_numPoints];
+ _maxFFTPoints = new double[_numPoints];
+
+ for(int i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ _dataPoints[i] = new double[_numPoints];
#if QWT_VERSION < 0x060000
- _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
- _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
- _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
+ _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
+ _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
#else
- _fft_plot_curve->setRawSamples(_xAxisPoints, _dataPoints, _numPoints);
- _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints);
- _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints);
+ _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints);
+ _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints);
+ _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints);
#endif
+ }
- _resetXAxisPoints();
- ClearMaxData();
- ClearMinData();
- }
-
- memcpy(_dataPoints, dataPoints, numDataPoints*sizeof(double));
- for(int64_t point = 0; point < numDataPoints; point++){
- if(dataPoints[point] < _minFFTPoints[point]){
- _minFFTPoints[point] = dataPoints[point];
+ _resetXAxisPoints();
+ ClearMaxData();
+ ClearMinData();
}
- if(dataPoints[point] > _maxFFTPoints[point]){
- _maxFFTPoints[point] = dataPoints[point];
+
+ for(int i = 0; i < _nplots; i++) {
+ memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
}
- }
- _noiseFloorAmplitude = noiseFloorAmplitude;
- _peakFrequency = peakFrequency;
- _peakAmplitude = peakAmplitude;
+ for(int64_t point = 0; point < numDataPoints; point++){
+ if(dataPoints[0][point] < _minFFTPoints[point]) {
+ _minFFTPoints[point] = dataPoints[0][point];
+ }
+ if(dataPoints[0][point] > _maxFFTPoints[point]) {
+ _maxFFTPoints[point] = dataPoints[0][point];
+ }
+ }
- SetUpperIntensityLevel(_peakAmplitude);
+ _noiseFloorAmplitude = noiseFloorAmplitude;
+ _peakFrequency = peakFrequency;
+ _peakAmplitude = peakAmplitude;
- replot();
+ SetUpperIntensityLevel(_peakAmplitude);
- _lastReplot = gruel::high_res_timer_now();
+ replot();
+ }
}
}
void
+FrequencyDisplayPlot::PlotNewData(const double* dataPoints,
+ const int64_t numDataPoints,
+ const double noiseFloorAmplitude, const double peakFrequency,
+ const double peakAmplitude, const double timeInterval)
+{
+ std::vector<double*> vecDataPoints;
+ vecDataPoints.push_back((double*)dataPoints);
+ PlotNewData(vecDataPoints, numDataPoints, noiseFloorAmplitude,
+ peakFrequency, peakAmplitude, timeInterval);
+}
+
+void
FrequencyDisplayPlot::ClearMaxData()
{
- for(int64_t number = 0; number < _numPoints; number++){
+ for(int64_t number = 0; number < _numPoints; number++) {
_maxFFTPoints[number] = _minYAxis;
}
}
@@ -464,7 +408,7 @@ FrequencyDisplayPlot::ClearMaxData()
void
FrequencyDisplayPlot::ClearMinData()
{
- for(int64_t number = 0; number < _numPoints; number++){
+ for(int64_t number = 0; number < _numPoints; number++) {
_minFFTPoints[number] = _maxYAxis;
}
}
@@ -484,9 +428,10 @@ FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag)
void
FrequencyDisplayPlot::_resetXAxisPoints()
{
- double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(_numPoints);
+ double fft_bin_size = (_stopFrequency-_startFrequency)
+ / static_cast<double>(_numPoints);
double freqValue = _startFrequency;
- for(int64_t loc = 0; loc < _numPoints; loc++){
+ for(int64_t loc = 0; loc < _numPoints; loc++) {
_xAxisPoints[loc] = freqValue;
freqValue += fft_bin_size;
}
@@ -506,23 +451,23 @@ FrequencyDisplayPlot::_resetXAxisPoints()
void
FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel)
{
- _lower_intensity_marker->setYValue( lowerIntensityLevel );
+ _lower_intensity_marker->setYValue(lowerIntensityLevel);
}
void
FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel)
{
- _upper_intensity_marker->setYValue( upperIntensityLevel );
+ _upper_intensity_marker->setYValue(upperIntensityLevel);
}
void
-FrequencyDisplayPlot::SetTraceColour (QColor c)
+FrequencyDisplayPlot::SetTraceColour(QColor c)
{
- _fft_plot_curve->setPen(QPen(c));
+ _plot_curve[0]->setPen(QPen(c));
}
void
-FrequencyDisplayPlot::SetBGColour (QColor c)
+FrequencyDisplayPlot::SetBGColour(QColor c)
{
QPalette palette;
palette.setColor(canvas()->backgroundRole(), c);
@@ -530,7 +475,7 @@ FrequencyDisplayPlot::SetBGColour (QColor c)
}
void
-FrequencyDisplayPlot::ShowCFMarker (const bool show)
+FrequencyDisplayPlot::ShowCFMarker(const bool show)
{
if (show)
_markerCF->show();
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h
index 5c3ea708c3..17bb9d2391 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.h
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.h
@@ -25,29 +25,15 @@
#include <stdint.h>
#include <cstdio>
-#include <qwt_plot.h>
-#include <qwt_painter.h>
-#include <qwt_plot_canvas.h>
-#include <qwt_plot_curve.h>
-#include <qwt_scale_engine.h>
-#include <qwt_scale_widget.h>
-#include <qwt_plot_zoomer.h>
-#include <qwt_plot_panner.h>
-#include <qwt_plot_marker.h>
-#include <qwt_plot_magnifier.h>
-#include <gruel/high_res_timer.h>
-#include <qwt_symbol.h>
-#include <qtgui_util.h>
-
-#if QWT_VERSION >= 0x060000
-#include <qwt_compat.h>
-#endif
-
-class FrequencyDisplayPlot:public QwtPlot{
+#include <vector>
+#include "DisplayPlot.h"
+
+class FrequencyDisplayPlot: public DisplayPlot
+{
Q_OBJECT
public:
- FrequencyDisplayPlot(QWidget*);
+ FrequencyDisplayPlot(int nplots, QWidget*);
virtual ~FrequencyDisplayPlot();
void SetFrequencyRange(const double, const double,
@@ -57,7 +43,14 @@ public:
double GetStartFrequency()const;
double GetStopFrequency()const;
- void PlotNewData(const double* dataPoints, const int64_t numDataPoints,
+ void PlotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
+ const double noiseFloorAmplitude, const double peakFrequency,
+ const double peakAmplitude, const double timeInterval);
+
+ // Old method to be removed
+ void PlotNewData(const double* dataPoints,
+ const int64_t numDataPoints,
const double noiseFloorAmplitude, const double peakFrequency,
const double peakAmplitude, const double timeInterval);
@@ -67,7 +60,7 @@ public:
void SetMaxFFTVisible(const bool);
void SetMinFFTVisible(const bool);
- virtual void replot();
+ void replot();
void set_yaxis(double min, double max);
@@ -76,63 +69,43 @@ public:
void ShowCFMarker (const bool);
public slots:
- void resizeSlot( QSize *e );
void SetLowerIntensityLevel(const double);
void SetUpperIntensityLevel(const double);
- // Because of the preprocessing of slots in QT, these are no
- // easily separated by the version check. Make one for each
- // version until it's worked out.
void OnPickerPointSelected(const QwtDoublePoint & p);
void OnPickerPointSelected6(const QPointF & p);
-signals:
- void plotPointSelected(const QPointF p);
-
-protected:
-
private:
-
void _resetXAxisPoints();
+ std::vector<double*> _dataPoints;
+
+ QwtPlotCurve* _min_fft_plot_curve;
+ QwtPlotCurve* _max_fft_plot_curve;
+
double _startFrequency;
double _stopFrequency;
double _maxYAxis;
double _minYAxis;
- QwtPlotCurve* _fft_plot_curve;
- QwtPlotCurve* _min_fft_plot_curve;
- QwtPlotCurve* _max_fft_plot_curve;
-
QwtPlotMarker* _lower_intensity_marker;
QwtPlotMarker* _upper_intensity_marker;
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
QwtPlotMarker *_markerPeakAmplitude;
QwtPlotMarker *_markerNoiseFloorAmplitude;
QwtPlotMarker *_markerCF;
- QwtDblClickPlotPicker *_picker;
-
- QwtPlotMagnifier *_magnifier;
-
- double* _dataPoints;
double* _xAxisPoints;
int _xAxisMultiplier;
double* _minFFTPoints;
double* _maxFFTPoints;
- int64_t _numPoints;
double _peakFrequency;
double _peakAmplitude;
double _noiseFloorAmplitude;
- gruel::high_res_timer_type _lastReplot;
-
bool _useCenterFrequencyFlag;
};
diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc
index d2dbc77723..e73ee2d50c 100644
--- a/gr-qtgui/lib/SpectrumGUIClass.cc
+++ b/gr-qtgui/lib/SpectrumGUIClass.cc
@@ -27,6 +27,7 @@
//Added by qt3to4:
#include <QEvent>
#include <QCustomEvent>
+#include <volk/volk.h>
const long SpectrumGUIClass::MAX_FFT_SIZE = 32768;
const long SpectrumGUIClass::MIN_FFT_SIZE = 256;
@@ -88,13 +89,12 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
if(!_windowOpennedFlag){
if(!_fftBuffersCreatedFlag){
- _fftPoints = new std::complex<float>[_dataPoints];
+ _fftPoints = new float[_dataPoints];
_realTimeDomainPoints = new double[_dataPoints];
_imagTimeDomainPoints = new double[_dataPoints];
_fftBuffersCreatedFlag = true;
-
-
- memset(_fftPoints, 0x0, _dataPoints*sizeof(std::complex<float>));
+
+ memset(_fftPoints, 0x0, _dataPoints*sizeof(float));
memset(_realTimeDomainPoints, 0x0, _dataPoints*sizeof(double));
memset(_imagTimeDomainPoints, 0x0, _dataPoints*sizeof(double));
}
@@ -223,7 +223,7 @@ SpectrumGUIClass::GetCenterFrequency()
void
SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
- const std::complex<float>* fftBuffer,
+ const float* fftBuffer,
const uint64_t inputBufferSize,
const float* realTimeDomainData,
const uint64_t realTimeDomainDataSize,
@@ -242,9 +242,11 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
if(updateDisplayFlag){
if((fftBuffer != NULL) && (bufferSize > 0)){
- memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex<float>));
+ memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(float));
}
+ //ALL OF THIS SHIT SHOULD BE COMBINED WITH THE FFTSHIFT
+ //USE VOLK_32FC_DEINTERLEAVE_64F_X2_A TO GET REAL/IMAG FROM COMPLEX32
// Can't do a memcpy since ths is going from float to double data type
if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){
const float* realTimeDomainDataPtr = realTimeDomainData;
@@ -252,24 +254,18 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
double* realTimeDomainPointsPtr = _realTimeDomainPoints;
timeDomainBufferSize = realTimeDomainDataSize;
- memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double));
- for( uint64_t number = 0; number < realTimeDomainDataSize; number++){
+ memset(_imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double));
+ for(uint64_t number = 0; number < realTimeDomainDataSize; number++){
*realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++;
}
}
- // Can't do a memcpy since ths is going from float to double data type
if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){
- const float* complexTimeDomainDataPtr = complexTimeDomainData;
-
- double* realTimeDomainPointsPtr = _realTimeDomainPoints;
- double* imagTimeDomainPointsPtr = _imagTimeDomainPoints;
-
+ volk_32fc_deinterleave_64f_x2_a(_realTimeDomainPoints,
+ _imagTimeDomainPoints,
+ (const lv_32fc_t *)complexTimeDomainData,
+ complexTimeDomainDataSize);
timeDomainBufferSize = complexTimeDomainDataSize;
- for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){
- *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
- *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
- }
}
}
diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h
index e0612413b0..a1150199b2 100644
--- a/gr-qtgui/lib/SpectrumGUIClass.h
+++ b/gr-qtgui/lib/SpectrumGUIClass.h
@@ -62,7 +62,7 @@ public:
double GetStopFrequency();
double GetCenterFrequency();
- void UpdateWindow(const bool, const std::complex<float>*,
+ void UpdateWindow(const bool, const float*,
const uint64_t, const float*,
const uint64_t, const float*,
const uint64_t,
@@ -122,7 +122,7 @@ private:
SpectrumDisplayForm* _spectrumDisplayForm;
- std::complex<float>* _fftPoints;
+ float* _fftPoints;
double* _realTimeDomainPoints;
double* _imagTimeDomainPoints;
};
diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc
index 84b09af90f..a10418bddf 100644
--- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc
+++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -28,6 +28,7 @@
#include <qwt_scale_draw.h>
#include <qwt_legend.h>
#include <QColor>
+#include <cmath>
#include <iostream>
class TimePrecisionClass
@@ -80,11 +81,12 @@ public:
protected:
using QwtPlotZoomer::trackerText;
- virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ virtual QwtText trackerText( const QPoint& p ) const
{
- QwtText t(QString("%1 %2, %3 V").arg(p.x(), 0, 'f', GetTimePrecision()).
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ QwtText t(QString("%1 %2, %3 V").arg(dp.x(), 0, 'f', GetTimePrecision()).
arg(_unitType.c_str()).
- arg(p.y(), 0, 'f', 4));
+ arg(dp.y(), 0, 'f', 4));
return t;
}
@@ -93,11 +95,13 @@ private:
std::string _unitType;
};
+
+/***********************************************************************
+ * Main Time domain plotter widget
+ **********************************************************************/
TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
- : QwtPlot(parent), _nplots(nplots)
+ : DisplayPlot(nplots, parent)
{
- resize(parent->width(), parent->height());
-
_numPoints = 1024;
_xAxisPoints = new double[_numPoints];
memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
@@ -108,22 +112,14 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
_zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection);
#endif
- // Disable polygon clipping
-#if QWT_VERSION < 0x060000
- QwtPainter::setDeviceClipping(false);
-#else
- QwtPainter::setPolylineSplitting(false);
-#endif
-
-#if QWT_VERSION < 0x060000
- // We don't need the cache here
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
-#endif
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
+ Qt::RightButton);
- QPalette palette;
- palette.setColor(canvas()->backgroundRole(), QColor("white"));
- canvas()->setPalette(palette);
+ const QColor c(Qt::darkRed);
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
setXaxis(0, _numPoints);
@@ -149,57 +145,19 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
_plot_curve[i]->attach(this);
_plot_curve[i]->setPen(QPen(colors[i]));
+ QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7));
+
#if QWT_VERSION < 0x060000
_plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(*symbol);
#else
_plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setSymbol(symbol);
#endif
-}
+ }
_sampleRate = 1;
_resetXAxisPoints();
-
- _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
- Qt::RightButton, Qt::ControlModifier);
- _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
- Qt::RightButton);
-
- _panner = new QwtPlotPanner(canvas());
- _panner->setAxisEnabled(QwtPlot::yRight, false);
- _panner->setMouseButton(Qt::MidButton);
-
- // emit the position of clicks on widget
- _picker = new QwtDblClickPlotPicker(canvas());
-
-#if QWT_VERSION < 0x060000
- connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
- this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
-#else
- connect(_picker, SIGNAL(selected(const QPointF &)),
- this, SLOT(OnPickerPointSelected6(const QPointF &)));
-#endif
-
- // Configure magnify on mouse wheel
- _magnifier = new QwtPlotMagnifier(canvas());
- _magnifier->setAxisEnabled(QwtPlot::xBottom, false);
-
- // Avoid jumping when labels with more/less digits
- // appear/disappear when scrolling vertically
-
- const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
- QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
- sd->setMinimumExtent( fm.width("100.00") );
-
- const QColor c(Qt::darkRed);
- _zoomer->setRubberBandPen(c);
- _zoomer->setTrackerPen(c);
-
- QwtLegend* legendDisplay = new QwtLegend(this);
- legendDisplay->setItemMode(QwtLegend::CheckableItem);
- insertLegend(legendDisplay);
-
- connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ),
- this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
}
TimeDomainDisplayPlot::~TimeDomainDisplayPlot()
@@ -212,74 +170,45 @@ TimeDomainDisplayPlot::~TimeDomainDisplayPlot()
}
void
-TimeDomainDisplayPlot::setYaxis(double min, double max)
-{
- setAxisScale(QwtPlot::yLeft, min, max);
- _zoomer->setZoomBase();
-}
-
-void
-TimeDomainDisplayPlot::setXaxis(double min, double max)
-{
- setAxisScale(QwtPlot::xBottom, min, max);
- _zoomer->setZoomBase();
-}
-
-void
-TimeDomainDisplayPlot::setTitle(int which, QString title)
-{
- _plot_curve[which]->setTitle(title);
-}
-
-void
-TimeDomainDisplayPlot::setColor(int which, QString color)
-{
- _plot_curve[which]->setPen(QPen(color));
-}
-
-void TimeDomainDisplayPlot::replot()
+TimeDomainDisplayPlot::replot()
{
QwtPlot::replot();
}
void
-TimeDomainDisplayPlot::resizeSlot( QSize *s )
-{
- // -10 is to spare some room for the legend and x-axis label
- resize(s->width()-10, s->height()-10);
-}
-
-void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints,
- const int64_t numDataPoints,
- const double timeInterval)
+TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval)
{
- if((numDataPoints > 0)) {
- if(numDataPoints != _numPoints){
- _numPoints = numDataPoints;
+ if(!_stop) {
+ if((numDataPoints > 0)) {
+ if(numDataPoints != _numPoints){
+ _numPoints = numDataPoints;
- delete[] _xAxisPoints;
- _xAxisPoints = new double[_numPoints];
+ delete[] _xAxisPoints;
+ _xAxisPoints = new double[_numPoints];
- for(int i = 0; i < _nplots; i++) {
- delete[] _dataPoints[i];
- _dataPoints[i] = new double[_numPoints];
+ for(int i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ _dataPoints[i] = new double[_numPoints];
#if QWT_VERSION < 0x060000
- _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
#else
- _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints);
+ _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints);
#endif
+ }
+
+ setXaxis(0, numDataPoints);
+ _resetXAxisPoints();
}
- setXaxis(0, numDataPoints);
- _resetXAxisPoints();
- }
+ for(int i = 0; i < _nplots; i++) {
+ memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
+ }
- for(int i = 0; i < _nplots; i++) {
- memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
+ replot();
}
-
- replot();
}
}
@@ -301,11 +230,6 @@ void TimeDomainDisplayPlot::_resetXAxisPoints()
_zoomer->zoom(0);
}
-void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
-{
- plotItem->setVisible(!on);
-}
-
void
TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
const std::string &strunits)
@@ -325,21 +249,4 @@ TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
}
}
-
-void
-TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
-{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
-}
-
-void
-TimeDomainDisplayPlot::OnPickerPointSelected6(const QPointF & p)
-{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
-}
-
#endif /* TIME_DOMAIN_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h
index 356da25ad4..9c07e96ba0 100644
--- a/gr-qtgui/lib/TimeDomainDisplayPlot.h
+++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,30 +20,16 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef TIME_DOMAIN_DISPLAY_PLOT_HPP
-#define TIME_DOMAIN_DISPLAY_PLOT_HPP
+#ifndef TIME_DOMAIN_DISPLAY_PLOT_H
+#define TIME_DOMAIN_DISPLAY_PLOT_H
#include <stdint.h>
#include <cstdio>
#include <vector>
-#include <qwt_plot.h>
-#include <qwt_painter.h>
-#include <qwt_plot_canvas.h>
-#include <qwt_plot_curve.h>
-#include <qwt_scale_engine.h>
-#include <qwt_scale_widget.h>
-#include <qwt_plot_zoomer.h>
-#include <qwt_plot_panner.h>
-#include <qwt_plot_magnifier.h>
-#include <qwt_plot_marker.h>
-#include <qwt_symbol.h>
-#include <qtgui_util.h>
+#include "DisplayPlot.h"
-#if QWT_VERSION >= 0x060000
-#include <qwt_compat.h>
-#endif
-
-class TimeDomainDisplayPlot:public QwtPlot{
+class TimeDomainDisplayPlot: public DisplayPlot
+{
Q_OBJECT
public:
@@ -53,50 +39,19 @@ public:
void PlotNewData(const std::vector<double*> dataPoints,
const int64_t numDataPoints, const double timeInterval);
- virtual void replot();
+ void replot();
public slots:
- void setYaxis(double min, double max);
- void setXaxis(double min, double max);
- void setTitle(int which, QString title);
- void setColor(int which, QString color);
-
- void resizeSlot( QSize *s );
void SetSampleRate(double sr, double units,
const std::string &strunits);
- // Because of the preprocessing of slots in QT, these are no
- // easily separated by the version check. Make one for each
- // version until it's worked out.
- void OnPickerPointSelected(const QwtDoublePoint & p);
- void OnPickerPointSelected6(const QPointF & p);
-
-signals:
- void plotPointSelected(const QPointF p);
-
-protected slots:
- void LegendEntryChecked(QwtPlotItem *plotItem, bool on);
-
-protected:
-
private:
void _resetXAxisPoints();
- int _nplots;
- std::vector<QwtPlotCurve*> _plot_curve;
-
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
- QwtDblClickPlotPicker *_picker;
- QwtPlotMagnifier *_magnifier;
-
std::vector<double*> _dataPoints;
double* _xAxisPoints;
double _sampleRate;
-
- int64_t _numPoints;
};
-#endif /* TIME_DOMAIN_DISPLAY_PLOT_HPP */
+#endif /* TIME_DOMAIN_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc
index 63eb57ffe8..40d16d0072 100644
--- a/gr-qtgui/lib/WaterfallDisplayPlot.cc
+++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,128 +25,23 @@
#include <WaterfallDisplayPlot.h>
+#include "qtgui_types.h"
#include <qwt_color_map.h>
-#include <qwt_scale_widget.h>
#include <qwt_scale_draw.h>
-#include <qwt_plot_zoomer.h>
-#include <qwt_plot_panner.h>
+#include <qwt_legend.h>
+#include <qwt_legend_item.h>
#include <qwt_plot_layout.h>
-
-#include <qapplication.h>
+#include <QColor>
+#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace pt = boost::posix_time;
-class FreqOffsetAndPrecisionClass
-{
-public:
- FreqOffsetAndPrecisionClass(const int freqPrecision)
- {
- _frequencyPrecision = freqPrecision;
- _centerFrequency = 0;
- }
-
- virtual ~FreqOffsetAndPrecisionClass()
- {
- }
-
- virtual unsigned int GetFrequencyPrecision() const
- {
- return _frequencyPrecision;
- }
-
- virtual void SetFrequencyPrecision(const unsigned int newPrecision)
- {
- _frequencyPrecision = newPrecision;
- }
-
- virtual double GetCenterFrequency() const
- {
- return _centerFrequency;
- }
-
- virtual void SetCenterFrequency(const double newFreq)
- {
- _centerFrequency = newFreq;
- }
-
-protected:
- unsigned int _frequencyPrecision;
- double _centerFrequency;
-
-private:
-
-};
-
-class WaterfallFreqDisplayScaleDraw: public QwtScaleDraw, public FreqOffsetAndPrecisionClass{
-public:
- WaterfallFreqDisplayScaleDraw(const unsigned int precision)
- : QwtScaleDraw(), FreqOffsetAndPrecisionClass(precision)
- {
- }
-
- virtual ~WaterfallFreqDisplayScaleDraw()
- {
- }
-
- QwtText label(double value) const
- {
- return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision());
- }
-
- virtual void initiateUpdate()
- {
- invalidateCache();
- }
-
-protected:
-
-private:
-
-};
-
-class TimeScaleData
-{
-public:
- TimeScaleData()
- {
- _zeroTime = 0;
- _secondsPerLine = 1.0;
- }
-
- virtual ~TimeScaleData()
- {
- }
-
- virtual gruel::high_res_timer_type GetZeroTime() const
- {
- return _zeroTime;
- }
-
- virtual void SetZeroTime(const gruel::high_res_timer_type newTime)
- {
- _zeroTime = newTime - gruel::high_res_timer_epoch();
- }
-
- virtual void SetSecondsPerLine(const double newTime)
- {
- _secondsPerLine = newTime;
- }
-
- virtual double GetSecondsPerLine() const
- {
- return _secondsPerLine;
- }
-
-
-protected:
- gruel::high_res_timer_type _zeroTime;
- double _secondsPerLine;
-
-private:
-
-};
+#include <QDebug>
+/***********************************************************************
+ * Create a time label HH:MM:SS.SSS from an input time
+ **********************************************************************/
static QString
make_time_label(double secs)
{
@@ -160,6 +55,9 @@ make_time_label(double secs)
return QString("").sprintf("%s.%03ld", time_str.c_str(), long(std::fmod(secs*1000, 1000)));
}
+/***********************************************************************
+ * Text scale widget to provide Y (time) axis text
+ **********************************************************************/
class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData
{
public:
@@ -173,8 +71,8 @@ public:
virtual QwtText label(double value) const
{
- double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (value * GetSecondsPerLine());
- return QwtText(make_time_label(secs));
+ double secs = double(value * GetSecondsPerLine());
+ return QwtText(QString("").sprintf("%.1f", secs));
}
virtual void initiateUpdate()
@@ -190,7 +88,10 @@ private:
};
-class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData,
+/***********************************************************************
+ * Widget to provide mouse pointer coordinate text
+ **********************************************************************/
+class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData,
public FreqOffsetAndPrecisionClass
{
public:
@@ -217,12 +118,14 @@ public:
protected:
using QwtPlotZoomer::trackerText;
- virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ virtual QwtText trackerText( QPoint const &p ) const
{
- double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (p.y() * GetSecondsPerLine());
- QwtText t(QString("%1 %2, %3").
- arg(p.x(), 0, 'f', GetFrequencyPrecision()).
- arg(_unitType.c_str()).arg(make_time_label(secs)));
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ double secs = double(dp.y() * GetSecondsPerLine());
+ QwtText t(QString("%1 %2, %3 s")
+ .arg(dp.x(), 0, 'f', GetFrequencyPrecision())
+ .arg(_unitType.c_str())
+ .arg(secs, 0, 'f', 2));
return t;
}
@@ -230,100 +133,59 @@ private:
std::string _unitType;
};
-class ColorMap_MultiColor: public QwtLinearColorMap
-{
-public:
- ColorMap_MultiColor():
- QwtLinearColorMap(Qt::darkCyan, Qt::white)
- {
- addColorStop(0.25, Qt::cyan);
- addColorStop(0.5, Qt::yellow);
- addColorStop(0.75, Qt::red);
- }
-};
-
-class ColorMap_WhiteHot: public QwtLinearColorMap
-{
-public:
- ColorMap_WhiteHot():
- QwtLinearColorMap(Qt::black, Qt::white)
- {
- }
-};
-
-class ColorMap_BlackHot: public QwtLinearColorMap
-{
-public:
- ColorMap_BlackHot():
- QwtLinearColorMap(Qt::white, Qt::black)
- {
- }
-};
-
-class ColorMap_Incandescent: public QwtLinearColorMap
-{
-public:
- ColorMap_Incandescent():
- QwtLinearColorMap(Qt::black, Qt::white)
- {
- addColorStop(0.5, Qt::darkRed);
- }
-};
-
-class ColorMap_UserDefined: public QwtLinearColorMap
-{
-public:
- ColorMap_UserDefined(QColor low, QColor high):
- QwtLinearColorMap(low, high)
- {
- }
-};
-
/*********************************************************************
-MAIN WATERFALL PLOT WIDGET
+* Main waterfall plot widget
*********************************************************************/
-
-WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent)
- : QwtPlot(parent)
+WaterfallDisplayPlot::WaterfallDisplayPlot(int nplots, QWidget* parent)
+ : DisplayPlot(nplots, parent)
{
- _zoomer = NULL;
+ _zoomer = NULL; // need this for proper init
_startFrequency = 0;
_stopFrequency = 4000;
+ _useCenterFrequencyFlag = false;
resize(parent->width(), parent->height());
_numPoints = 1024;
- QPalette palette;
- palette.setColor(canvas()->backgroundRole(), QColor("white"));
- canvas()->setPalette(palette);
-
setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
- setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(0));
+ setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
- setAxisTitle(QwtPlot::yLeft, "Time");
+ setAxisTitle(QwtPlot::yLeft, "Time (s)");
setAxisScaleDraw(QwtPlot::yLeft, new QwtTimeScaleDraw());
_lastReplot = 0;
- _intensityColorMapType = INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR;
+ QList<int> colormaps;
+ colormaps << INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR
+ << INTENSITY_COLOR_MAP_TYPE_WHITE_HOT
+ << INTENSITY_COLOR_MAP_TYPE_BLACK_HOT
+ << INTENSITY_COLOR_MAP_TYPE_INCANDESCENT
+ << INTENSITY_COLOR_MAP_TYPE_USER_DEFINED;
- d_data = new WaterfallData(_startFrequency, _stopFrequency,
- _numPoints, 200);
+ for(int i = 0; i < _nplots; i++) {
+ d_data.push_back(new WaterfallData(_startFrequency, _stopFrequency,
+ _numPoints, 200));
#if QWT_VERSION < 0x060000
- d_spectrogram = new PlotWaterfall(d_data, "Waterfall Display");
-
- ColorMap_MultiColor colorMap;
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram.push_back(new PlotWaterfall(d_data[i], "Spectrogram"));
#else
- d_spectrogram = new QwtPlotSpectrogram("Spectrogram");
- d_spectrogram->setData(d_data);
- d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ImageMode, true);
- d_spectrogram->setColorMap(new ColorMap_MultiColor());
+ d_spectrogram.push_back(new QwtPlotSpectrogram("Spectrogram"));
+ d_spectrogram[i]->setData(d_data[i]);
+ d_spectrogram[i]->setDisplayMode(QwtPlotSpectrogram::ImageMode, true);
+ d_spectrogram[i]->setColorMap(new ColorMap_MultiColor());
#endif
- d_spectrogram->attach(this);
+ // a hack around the fact that we aren't using plot curves for the
+ // spectrogram plots.
+ _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
+
+ d_spectrogram[i]->attach(this);
+
+ _intensityColorMapType.push_back(colormaps[i%colormaps.size()]);
+ SetIntensityColorMapType(i, _intensityColorMapType[i],
+ QColor("white"), QColor("white"));
+ }
// LeftButton for the zooming
// MidButton for the panning
@@ -338,27 +200,6 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent)
_zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
Qt::RightButton);
- _panner = new QwtPlotPanner(canvas());
- _panner->setAxisEnabled(QwtPlot::yRight, false);
- _panner->setMouseButton(Qt::MidButton);
-
- // emit the position of clicks on widget
- _picker = new QwtDblClickPlotPicker(canvas());
-#if QWT_VERSION < 0x060000
- connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
- this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
-#else
- connect(_picker, SIGNAL(selected(const QPointF &)),
- this, SLOT(OnPickerPointSelected6(const QPointF &)));
-#endif
-
- // Avoid jumping when labels with more/less digits
- // appear/disappear when scrolling vertically
-
- const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
- QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
- sd->setMinimumExtent( fm.width("100.00") );
-
const QColor c(Qt::black);
_zoomer->setRubberBandPen(c);
_zoomer->setTrackerPen(c);
@@ -370,15 +211,15 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent)
WaterfallDisplayPlot::~WaterfallDisplayPlot()
{
- delete d_data;
- delete d_spectrogram;
}
void
WaterfallDisplayPlot::Reset()
{
- d_data->ResizeData(_startFrequency, _stopFrequency, _numPoints);
- d_data->Reset();
+ for(int i = 0; i < _nplots; i++) {
+ d_data[i]->ResizeData(_startFrequency, _stopFrequency, _numPoints);
+ d_data[i]->Reset();
+ }
setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency);
@@ -406,7 +247,7 @@ WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq,
_useCenterFrequencyFlag = useCenterFrequencyFlag;
- if(_useCenterFrequencyFlag){
+ if(_useCenterFrequencyFlag) {
startFreq = (startFreq + centerFreq);
stopFreq = (stopFreq + centerFreq);
}
@@ -419,9 +260,9 @@ WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq,
_startFrequency = startFreq;
_stopFrequency = stopFreq;
- if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){
+ if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)) {
double display_units = ceil(log10(units)/2.0);
- setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(display_units));
+ setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units));
setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str()));
if(reset) {
@@ -448,31 +289,35 @@ WaterfallDisplayPlot::GetStopFrequency() const
}
void
-WaterfallDisplayPlot::PlotNewData(const double* dataPoints,
+WaterfallDisplayPlot::PlotNewData(const std::vector<double*> dataPoints,
const int64_t numDataPoints,
const double timePerFFT,
const gruel::high_res_timer_type timestamp,
const int droppedFrames)
{
- if(numDataPoints > 0){
- if(numDataPoints != _numPoints){
- _numPoints = numDataPoints;
+ if(!_stop) {
+ if(numDataPoints > 0){
+ if(numDataPoints != _numPoints){
+ _numPoints = numDataPoints;
+
+ Reset();
- Reset();
+ for(int i = 0; i < _nplots; i++) {
+ d_spectrogram[i]->invalidateCache();
+ d_spectrogram[i]->itemChanged();
+ }
- d_spectrogram->invalidateCache();
- d_spectrogram->itemChanged();
+ if(isVisible()) {
+ replot();
+ }
- if(isVisible()){
- replot();
+ _lastReplot = gruel::high_res_timer_now();
}
- _lastReplot = gruel::high_res_timer_now();
- }
-
- if(gruel::high_res_timer_now() - _lastReplot > timePerFFT*gruel::high_res_timer_tps()) {
- d_data->addFFTData(dataPoints, numDataPoints, droppedFrames);
- d_data->IncrementNumLinesToUpdate();
+ for(int i = 0; i < _nplots; i++) {
+ d_data[i]->addFFTData(dataPoints[i], numDataPoints, droppedFrames);
+ d_data[i]->IncrementNumLinesToUpdate();
+ }
QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
timeScale->SetSecondsPerLine(timePerFFT);
@@ -481,30 +326,45 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints,
((WaterfallZoomer*)_zoomer)->SetSecondsPerLine(timePerFFT);
((WaterfallZoomer*)_zoomer)->SetZeroTime(timestamp);
- d_spectrogram->invalidateCache();
- d_spectrogram->itemChanged();
+ for(int i = 0; i < _nplots; i++) {
+ d_spectrogram[i]->invalidateCache();
+ d_spectrogram[i]->itemChanged();
+ }
replot();
-
- _lastReplot = gruel::high_res_timer_now();
}
}
}
void
+WaterfallDisplayPlot::PlotNewData(const double* dataPoints,
+ const int64_t numDataPoints,
+ const double timePerFFT,
+ const gruel::high_res_timer_type timestamp,
+ const int droppedFrames)
+{
+ std::vector<double*> vecDataPoints;
+ vecDataPoints.push_back((double*)dataPoints);
+ PlotNewData(vecDataPoints, numDataPoints, timePerFFT,
+ timestamp, droppedFrames);
+}
+
+void
WaterfallDisplayPlot::SetIntensityRange(const double minIntensity,
const double maxIntensity)
{
+ for(int i = 0; i < _nplots; i++) {
#if QWT_VERSION < 0x060000
- d_data->setRange(QwtDoubleInterval(minIntensity, maxIntensity));
+ d_data[i]->setRange(QwtDoubleInterval(minIntensity, maxIntensity));
#else
- d_data->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity));
+ d_data[i]->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity));
#endif
- emit UpdatedLowerIntensityLevel(minIntensity);
- emit UpdatedUpperIntensityLevel(maxIntensity);
+ emit UpdatedLowerIntensityLevel(minIntensity);
+ emit UpdatedUpperIntensityLevel(maxIntensity);
- _UpdateIntensityRangeDisplay();
+ _UpdateIntensityRangeDisplay();
+ }
}
void
@@ -513,8 +373,8 @@ WaterfallDisplayPlot::replot()
QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
timeScale->initiateUpdate();
- WaterfallFreqDisplayScaleDraw* freqScale = \
- (WaterfallFreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom);
+ FreqDisplayScaleDraw* freqScale = \
+ (FreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom);
freqScale->initiateUpdate();
// Update the time axis display
@@ -534,76 +394,71 @@ WaterfallDisplayPlot::replot()
QwtPlot::replot();
}
-void
-WaterfallDisplayPlot::resizeSlot( QSize *s )
-{
- resize(s->width(), s->height());
-}
-
int
-WaterfallDisplayPlot::GetIntensityColorMapType() const
+WaterfallDisplayPlot::GetIntensityColorMapType(int which) const
{
- return _intensityColorMapType;
+ return _intensityColorMapType[which];
}
void
-WaterfallDisplayPlot::SetIntensityColorMapType(const int newType,
+WaterfallDisplayPlot::SetIntensityColorMapType(const int which,
+ const int newType,
const QColor lowColor,
const QColor highColor)
{
- if((_intensityColorMapType != newType) ||
+ if((_intensityColorMapType[which] != newType) ||
((newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED) &&
(lowColor.isValid() && highColor.isValid()))){
switch(newType){
case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:{
- _intensityColorMapType = newType;
+ _intensityColorMapType[which] = newType;
#if QWT_VERSION < 0x060000
ColorMap_MultiColor colorMap;
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram[which]->setColorMap(colorMap);
#else
- d_spectrogram->setColorMap(new ColorMap_MultiColor());
+ d_spectrogram[which]->setColorMap(new ColorMap_MultiColor());
#endif
break;
}
case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:{
- _intensityColorMapType = newType;
+ _intensityColorMapType[which] = newType;
#if QWT_VERSION < 0x060000
ColorMap_WhiteHot colorMap;
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram[which]->setColorMap(colorMap);
#else
- d_spectrogram->setColorMap(new ColorMap_WhiteHot());
+ d_spectrogram[which]->setColorMap(new ColorMap_WhiteHot());
#endif
break;
}
case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:{
- _intensityColorMapType = newType;
+ _intensityColorMapType[which] = newType;
#if QWT_VERSION < 0x060000
ColorMap_BlackHot colorMap;
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram[which]->setColorMap(colorMap);
#else
- d_spectrogram->setColorMap(new ColorMap_BlackHot());
+ d_spectrogram[which]->setColorMap(new ColorMap_BlackHot());
#endif
break;
}
case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:{
- _intensityColorMapType = newType;
+ _intensityColorMapType[which] = newType;
#if QWT_VERSION < 0x060000
ColorMap_Incandescent colorMap;
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram[which]->setColorMap(colorMap);
#else
- d_spectrogram->setColorMap(new ColorMap_Incandescent());
+ d_spectrogram[which]->setColorMap(new ColorMap_Incandescent());
#endif
break;
}
case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:{
_userDefinedLowIntensityColor = lowColor;
_userDefinedHighIntensityColor = highColor;
- _intensityColorMapType = newType;
+ _intensityColorMapType[which] = newType;
#if QWT_VERSION < 0x060000
ColorMap_UserDefined colorMap(lowColor, highColor);
- d_spectrogram->setColorMap(colorMap);
+ d_spectrogram[which]->setColorMap(colorMap);
#else
- d_spectrogram->setColorMap(new ColorMap_UserDefined(lowColor, highColor));
+ d_spectrogram[which]->setColorMap(new ColorMap_UserDefined(lowColor, highColor));
#endif
break;
}
@@ -633,39 +488,41 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay()
rightAxis->setTitle("Intensity (dB)");
rightAxis->setColorBarEnabled(true);
+ for(int i = 0; i < _nplots; i++) {
#if QWT_VERSION < 0x060000
- rightAxis->setColorMap(d_spectrogram->data()->range(),
- d_spectrogram->colorMap());
- setAxisScale(QwtPlot::yRight,
- d_spectrogram->data()->range().minValue(),
- d_spectrogram->data()->range().maxValue());
+ rightAxis->setColorMap(d_spectrogram[i]->data()->range(),
+ d_spectrogram[i]->colorMap());
+ setAxisScale(QwtPlot::yRight,
+ d_spectrogram[i]->data()->range().minValue(),
+ d_spectrogram[i]->data()->range().maxValue());
#else
- QwtInterval intv = d_spectrogram->interval(Qt::ZAxis);
- switch(_intensityColorMapType) {
- case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:
- rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break;
- case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:
- rightAxis->setColorMap(intv, new ColorMap_WhiteHot()); break;
- case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:
- rightAxis->setColorMap(intv, new ColorMap_BlackHot()); break;
- case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:
- rightAxis->setColorMap(intv, new ColorMap_Incandescent()); break;
- case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:
- rightAxis->setColorMap(intv, new ColorMap_UserDefined(_userDefinedLowIntensityColor,
- _userDefinedHighIntensityColor)); break;
- default:
- rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break;
- }
- setAxisScale(QwtPlot::yRight, intv.minValue(), intv.maxValue());
+ QwtInterval intv = d_spectrogram[i]->interval(Qt::ZAxis);
+ switch(_intensityColorMapType[i]) {
+ case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:
+ rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break;
+ case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:
+ rightAxis->setColorMap(intv, new ColorMap_WhiteHot()); break;
+ case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:
+ rightAxis->setColorMap(intv, new ColorMap_BlackHot()); break;
+ case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:
+ rightAxis->setColorMap(intv, new ColorMap_Incandescent()); break;
+ case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:
+ rightAxis->setColorMap(intv, new ColorMap_UserDefined(_userDefinedLowIntensityColor,
+ _userDefinedHighIntensityColor)); break;
+ default:
+ rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break;
+ }
+ setAxisScale(QwtPlot::yRight, intv.minValue(), intv.maxValue());
#endif
- enableAxis(QwtPlot::yRight);
+ enableAxis(QwtPlot::yRight);
- plotLayout()->setAlignCanvasToScales(true);
+ plotLayout()->setAlignCanvasToScales(true);
- // Tell the display to redraw everything
- d_spectrogram->invalidateCache();
- d_spectrogram->itemChanged();
+ // Tell the display to redraw everything
+ d_spectrogram[i]->invalidateCache();
+ d_spectrogram[i]->itemChanged();
+ }
// Draw again
replot();
@@ -674,22 +531,4 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay()
_lastReplot = gruel::high_res_timer_now();
}
-void
-WaterfallDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
-{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- point.setX(point.x() * _xAxisMultiplier);
- emit plotPointSelected(point);
-}
-
-void
-WaterfallDisplayPlot::OnPickerPointSelected6(const QPointF & p)
-{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- point.setX(point.x() * _xAxisMultiplier);
- emit plotPointSelected(point);
-}
-
#endif /* WATERFALL_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h
index d189ca2cbd..adf5278059 100644
--- a/gr-qtgui/lib/WaterfallDisplayPlot.h
+++ b/gr-qtgui/lib/WaterfallDisplayPlot.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,18 +20,15 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef WATERFALL_DISPLAY_PLOT_HPP
-#define WATERFALL_DISPLAY_PLOT_HPP
+#ifndef WATERFALL_DISPLAY_PLOT_H
+#define WATERFALL_DISPLAY_PLOT_H
#include <stdint.h>
#include <cstdio>
-#include <qwt_plot.h>
+#include <vector>
#include <qwt_plot_spectrogram.h>
-#include <qwt_plot_zoomer.h>
-#include <qwt_plot_panner.h>
-#include <qtgui_util.h>
-#include <waterfallGlobalData.h>
-
+#include "DisplayPlot.h"
+#include "waterfallGlobalData.h"
#include <gruel/high_res_timer.h>
#if QWT_VERSION < 0x060000
@@ -40,11 +37,12 @@
#include <qwt_compat.h>
#endif
-class WaterfallDisplayPlot:public QwtPlot{
+class WaterfallDisplayPlot: public DisplayPlot
+{
Q_OBJECT
public:
- WaterfallDisplayPlot(QWidget*);
+ WaterfallDisplayPlot(int nplots, QWidget*);
virtual ~WaterfallDisplayPlot();
void Reset();
@@ -53,45 +51,34 @@ public:
const double, const bool,
const double units=1000.0,
const std::string &strunits = "kHz");
- double GetStartFrequency()const;
- double GetStopFrequency()const;
+ double GetStartFrequency() const;
+ double GetStopFrequency() const;
- void PlotNewData(const double* dataPoints, const int64_t numDataPoints,
- const double timePerFFT, const gruel::high_res_timer_type timestamp,
+ void PlotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
+ const double timePerFFT,
+ const gruel::high_res_timer_type timestamp,
const int droppedFrames);
- void SetIntensityRange(const double minIntensity, const double maxIntensity);
-
- virtual void replot(void);
-
- int GetIntensityColorMapType()const;
- void SetIntensityColorMapType( const int, const QColor, const QColor );
- const QColor GetUserDefinedLowIntensityColor()const;
- const QColor GetUserDefinedHighIntensityColor()const;
+ // to be removed
+ void PlotNewData(const double* dataPoints,
+ const int64_t numDataPoints,
+ const double timePerFFT,
+ const gruel::high_res_timer_type timestamp,
+ const int droppedFrames);
- enum{
- INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR = 0,
- INTENSITY_COLOR_MAP_TYPE_WHITE_HOT = 1,
- INTENSITY_COLOR_MAP_TYPE_BLACK_HOT = 2,
- INTENSITY_COLOR_MAP_TYPE_INCANDESCENT = 3,
- INTENSITY_COLOR_MAP_TYPE_USER_DEFINED = 4
- };
+ void SetIntensityRange(const double minIntensity, const double maxIntensity);
-public slots:
- void resizeSlot( QSize *s );
+ void replot(void);
- // Because of the preprocessing of slots in QT, these are no
- // easily separated by the version check. Make one for each
- // version until it's worked out.
- void OnPickerPointSelected(const QwtDoublePoint & p);
- void OnPickerPointSelected6(const QPointF & p);
+ int GetIntensityColorMapType(int) const;
+ void SetIntensityColorMapType(const int, const int, const QColor, const QColor);
+ const QColor GetUserDefinedLowIntensityColor() const;
+ const QColor GetUserDefinedHighIntensityColor() const;
signals:
void UpdatedLowerIntensityLevel(const double);
void UpdatedUpperIntensityLevel(const double);
- void plotPointSelected(const QPointF p);
-
-protected:
private:
void _UpdateIntensityRangeDisplay();
@@ -100,28 +87,21 @@ private:
double _stopFrequency;
int _xAxisMultiplier;
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
- QwtDblClickPlotPicker *_picker;
-
- WaterfallData *d_data;
+ std::vector<WaterfallData*> d_data;
#if QWT_VERSION < 0x060000
- PlotWaterfall *d_spectrogram;
+ std::vector<PlotWaterfall*> d_spectrogram;
#else
- QwtPlotSpectrogram *d_spectrogram;
+ std::vector<QwtPlotSpectrogram*> d_spectrogram;
#endif
gruel::high_res_timer_type _lastReplot;
bool _useCenterFrequencyFlag;
- int64_t _numPoints;
-
- int _intensityColorMapType;
+ std::vector<int> _intensityColorMapType;
QColor _userDefinedLowIntensityColor;
QColor _userDefinedHighIntensityColor;
};
-#endif /* WATERFALL_DISPLAY_PLOT_HPP */
+#endif /* WATERFALL_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc
new file mode 100644
index 0000000000..b504f7121d
--- /dev/null
+++ b/gr-qtgui/lib/const_sink_c_impl.cc
@@ -0,0 +1,257 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "const_sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace qtgui {
+
+ const_sink_c::sptr
+ const_sink_c::make(int size,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new const_sink_c_impl(size, name, nconnections, parent));
+ }
+
+ const_sink_c_impl::const_sink_c_impl(int size,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("const_sink_c",
+ gr_make_io_signature(nconnections, nconnections, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_size(size), d_name(name),
+ d_nconnections(nconnections), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs_real.push_back(fft::malloc_double(d_size));
+ d_residbufs_imag.push_back(fft::malloc_double(d_size));
+ memset(d_residbufs_real[i], 0, d_size*sizeof(double));
+ memset(d_residbufs_imag[i], 0, d_size*sizeof(double));
+ }
+
+ // Set alignment properties for VOLK
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(gr_complex);
+ set_alignment(std::max(1,alignment_multiple));
+
+ initialize();
+ }
+
+ const_sink_c_impl::~const_sink_c_impl()
+ {
+ // d_main_gui is a qwidget destroyed with its parent
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs_real[i]);
+ fft::free(d_residbufs_imag[i]);
+ }
+ }
+
+ void
+ const_sink_c_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new ConstellationDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetNPoints(d_size);
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ const_sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ const_sink_c_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ const_sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ const_sink_c_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ const_sink_c_impl::set_title(int which, const std::string &title)
+ {
+ d_main_gui->setTitle(which, title.c_str());
+ }
+
+ void
+ const_sink_c_impl::set_color(int which, const std::string &color)
+ {
+ d_main_gui->setColor(which, color.c_str());
+ }
+
+ void
+ const_sink_c_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ const_sink_c_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ const_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ const_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ const_sink_c_impl::set_nsamps(const int newsize)
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ if(newsize != d_size) {
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs_real[i]);
+ fft::free(d_residbufs_imag[i]);
+ d_residbufs_real[i] = fft::malloc_double(newsize);
+ d_residbufs_imag[i] = fft::malloc_double(newsize);
+
+ memset(d_residbufs_real[i], 0, newsize*sizeof(double));
+ memset(d_residbufs_imag[i], 0, newsize*sizeof(double));
+ }
+
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_size = newsize;
+ d_index = 0;
+
+ d_main_gui->SetNPoints(d_size);
+ }
+ }
+
+ void
+ const_sink_c_impl::npoints_resize()
+ {
+ int newsize = d_main_gui->GetNPoints();
+ set_nsamps(newsize);
+ }
+
+ int
+ const_sink_c_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int n=0, j=0, idx=0;
+ const gr_complex *in = (const gr_complex*)input_items[idx];
+
+ npoints_resize();
+
+ for(int i=0; i < noutput_items; i+=d_size) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_size-d_index;
+ idx = 0;
+
+ // If we have enough input for one full plot, do it
+ if(datasize >= resid) {
+
+ // Fill up residbufs with d_size number of items
+ for(n = 0; n < d_nconnections; n++) {
+ in = (const gr_complex*)input_items[idx++];
+ volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index],
+ &d_residbufs_imag[n][d_index],
+ &in[j], resid);
+ }
+
+ // Update the plot if its time
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new ConstUpdateEvent(d_residbufs_real,
+ d_residbufs_imag,
+ d_size));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+
+ // Otherwise, copy what we received into the residbufs for next time
+ else {
+ for(n = 0; n < d_nconnections; n++) {
+ in = (const gr_complex*)input_items[idx++];
+ volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index],
+ &d_residbufs_imag[n][d_index],
+ &in[j], datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/const_sink_c_impl.h b/gr-qtgui/lib/const_sink_c_impl.h
new file mode 100644
index 0000000000..a17a8793b4
--- /dev/null
+++ b/gr-qtgui/lib/const_sink_c_impl.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_CONST_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_CONST_SINK_C_IMPL_H
+
+#include <qtgui/const_sink_c.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <constellationdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API const_sink_c_impl : public const_sink_c
+ {
+ private:
+ void initialize();
+
+ gruel::mutex d_mutex;
+
+ int d_size;
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<double*> d_residbufs_real;
+ std::vector<double*> d_residbufs_imag;
+
+ QWidget *d_parent;
+ ConstellationDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void npoints_resize();
+
+ public:
+ const_sink_c_impl(int size,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~const_sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_update_time(double t);
+ void set_title(int which, const std::string &title);
+ void set_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, Qt::PenStyle style);
+ void set_line_marker(int which, QwtSymbol::Style marker);
+ void set_nsamps(const int size);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_CONST_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/constellationdisplayform.cc b/gr-qtgui/lib/constellationdisplayform.cc
new file mode 100644
index 0000000000..98375ebaed
--- /dev/null
+++ b/gr-qtgui/lib/constellationdisplayform.cc
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 <cmath>
+#include <QMessageBox>
+#include <constellationdisplayform.h>
+#include <iostream>
+
+ConstellationDisplayForm::ConstellationDisplayForm(int nplots, QWidget* parent)
+ : DisplayForm(nplots, parent)
+{
+ _intValidator = new QIntValidator(this);
+ _intValidator->setBottom(0);
+
+ _layout = new QGridLayout(this);
+ _displayPlot = new ConstellationDisplayPlot(nplots, this);
+ _layout->addWidget(_displayPlot, 0, 0);
+ setLayout(_layout);
+
+ NPointsMenu *nptsmenu = new NPointsMenu(this);
+ _menu->addAction(nptsmenu);
+ connect(nptsmenu, SIGNAL(whichTrigger(int)),
+ this, SLOT(SetNPoints(const int)));
+
+ Reset();
+
+ connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)),
+ this, SLOT(onPlotPointSelected(const QPointF)));
+}
+
+ConstellationDisplayForm::~ConstellationDisplayForm()
+{
+ // Qt deletes children when parent is deleted
+
+ // Don't worry about deleting Display Plots - they are deleted when parents are deleted
+ delete _intValidator;
+}
+
+ConstellationDisplayPlot*
+ConstellationDisplayForm::getPlot()
+{
+ return ((ConstellationDisplayPlot*)_displayPlot);
+}
+
+void
+ConstellationDisplayForm::newData(const QEvent* updateEvent)
+{
+ ConstUpdateEvent *tevent = (ConstUpdateEvent*)updateEvent;
+ const std::vector<double*> realDataPoints = tevent->getRealPoints();
+ const std::vector<double*> imagDataPoints = tevent->getImagPoints();
+ const uint64_t numDataPoints = tevent->getNumDataPoints();
+
+ getPlot()->PlotNewData(realDataPoints,
+ imagDataPoints,
+ numDataPoints,
+ d_update_time);
+}
+
+void
+ConstellationDisplayForm::customEvent(QEvent * e)
+{
+ if(e->type() == ConstUpdateEvent::Type()) {
+ newData(e);
+ }
+}
+
+int
+ConstellationDisplayForm::GetNPoints() const
+{
+ return d_npoints;
+}
+
+void
+ConstellationDisplayForm::SetNPoints(const int npoints)
+{
+ d_npoints = npoints;
+}
diff --git a/gr-qtgui/lib/constellationdisplayform.h b/gr-qtgui/lib/constellationdisplayform.h
new file mode 100644
index 0000000000..6832bd44cc
--- /dev/null
+++ b/gr-qtgui/lib/constellationdisplayform.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef CONSTELLATION_DISPLAY_FORM_H
+#define CONSTELLATION_DISPLAY_FORM_H
+
+#include <spectrumUpdateEvents.h>
+#include <ConstellationDisplayPlot.h>
+#include <QtGui/QtGui>
+#include <vector>
+
+#include "displayform.h"
+
+class ConstellationDisplayForm : public DisplayForm
+{
+ Q_OBJECT
+
+public:
+ ConstellationDisplayForm(int nplots=1, QWidget* parent = 0);
+ ~ConstellationDisplayForm();
+
+ ConstellationDisplayPlot* getPlot();
+
+ int GetNPoints() const;
+
+public slots:
+ void customEvent(QEvent * e);
+ void SetNPoints(const int);
+
+ // add set x/y axis
+
+private slots:
+ void newData(const QEvent*);
+
+private:
+ QIntValidator* _intValidator;
+ int d_npoints;
+};
+
+#endif /* CONSTELLATION_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/displayform.cc b/gr-qtgui/lib/displayform.cc
new file mode 100644
index 0000000000..68e1a5c4fd
--- /dev/null
+++ b/gr-qtgui/lib/displayform.cc
@@ -0,0 +1,260 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 <displayform.h>
+#include <iostream>
+
+DisplayForm::DisplayForm(int nplots, QWidget* parent)
+ : QWidget(parent), _nplots(nplots), _systemSpecifiedFlag(false)
+{
+ // Set the initial plot size
+ resize(QSize(800, 600));
+
+ // Set up a grid that can be turned on/off
+ _grid = new QwtPlotGrid();
+ _grid->setPen(QPen(QColor(Qt::gray)));
+
+ // Create a set of actions for the menu
+ _stop_act = new QAction("Stop", this);
+ _stop_act->setStatusTip(tr("Start/Stop"));
+ connect(_stop_act, SIGNAL(triggered()), this, SLOT(setStop()));
+ _stop_state = false;
+
+ _grid_act = new QAction("Grid On", this);
+ _grid_act->setStatusTip(tr("Toggle Grid on/off"));
+ connect(_grid_act, SIGNAL(triggered()), this, SLOT(setGrid()));
+ _grid_state = false;
+
+ // Create a pop-up menu for manipulating the figure
+ _menu = new QMenu(this);
+ _menu->addAction(_stop_act);
+ _menu->addAction(_grid_act);
+
+ for(int i = 0; i < _nplots; i++) {
+ _line_title_act.push_back(new LineTitleAction(i, this));
+ _line_color_menu.push_back(new LineColorMenu(i, this));
+ _line_width_menu.push_back(new LineWidthMenu(i, this));
+ _line_style_menu.push_back(new LineStyleMenu(i, this));
+ _line_marker_menu.push_back(new LineMarkerMenu(i, this));
+
+ connect(_line_title_act[i], SIGNAL(whichTrigger(int, const QString&)),
+ this, SLOT(setTitle(int, const QString&)));
+
+ for(int j = 0; j < _line_color_menu[i]->getNumActions(); j++) {
+ connect(_line_color_menu[i], SIGNAL(whichTrigger(int, const QString&)),
+ this, SLOT(setColor(int, const QString&)));
+ }
+
+ for(int j = 0; j < _line_width_menu[i]->getNumActions(); j++) {
+ connect(_line_width_menu[i], SIGNAL(whichTrigger(int, int)),
+ this, SLOT(setLineWidth(int, int)));
+ }
+
+ for(int j = 0; j < _line_style_menu[i]->getNumActions(); j++) {
+ connect(_line_style_menu[i], SIGNAL(whichTrigger(int, Qt::PenStyle)),
+ this, SLOT(setLineStyle(int, Qt::PenStyle)));
+ }
+
+ for(int j = 0; j < _line_marker_menu[i]->getNumActions(); j++) {
+ connect(_line_marker_menu[i], SIGNAL(whichTrigger(int, QwtSymbol::Style)),
+ this, SLOT(setLineMarker(int, QwtSymbol::Style)));
+ }
+
+ _lines_menu.push_back(new QMenu(tr(""), this));
+ _lines_menu[i]->addAction(_line_title_act[i]);
+ _lines_menu[i]->addMenu(_line_color_menu[i]);
+ _lines_menu[i]->addMenu(_line_width_menu[i]);
+ _lines_menu[i]->addMenu(_line_style_menu[i]);
+ _lines_menu[i]->addMenu(_line_marker_menu[i]);
+ _menu->addMenu(_lines_menu[i]);
+ }
+
+ Reset();
+
+ // Create a timer to update plots at the specified rate
+ d_displayTimer = new QTimer(this);
+ connect(d_displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer()));
+}
+
+DisplayForm::~DisplayForm()
+{
+ // Qt deletes children when parent is deleted
+
+ // Don't worry about deleting Display Plots - they are deleted when parents are deleted
+
+ d_displayTimer->stop();
+ delete d_displayTimer;
+}
+
+void
+DisplayForm::resizeEvent( QResizeEvent *e )
+{
+ QSize s = size();
+ emit _displayPlot->resizeSlot(&s);
+}
+
+void
+DisplayForm::mousePressEvent( QMouseEvent * e)
+{
+ if(e->button() == Qt::RightButton) {
+ QwtPlotLayout *plt = _displayPlot->plotLayout();
+ QRectF cvs = plt->canvasRect();
+
+ QRect plotrect;
+ plotrect.setLeft(cvs.x()-plt->spacing()-plt->canvasMargin(0));
+ plotrect.setRight(cvs.x()+cvs.width()+plt->spacing()+plt->canvasMargin(0));
+ plotrect.setBottom(cvs.y()-plt->spacing()-plt->canvasMargin(0));
+ plotrect.setTop(cvs.y()+cvs.width()+plt->spacing()+plt->canvasMargin(0));
+
+ if(!plotrect.contains(e->pos())) {
+ if(_stop_state == false)
+ _stop_act->setText(tr("Stop"));
+ else
+ _stop_act->setText(tr("Start"));
+
+ if(_grid_state == false)
+ _grid_act->setText(tr("Grid On"));
+ else
+ _grid_act->setText(tr("Grid Off"));
+
+ // Update the line titles if changed externally
+ for(int i = 0; i < _nplots; i++) {
+ _lines_menu[i]->setTitle(_displayPlot->title(i));
+ }
+ _menu->exec(e->globalPos());
+ }
+ }
+}
+
+void
+DisplayForm::updateGuiTimer()
+{
+ _displayPlot->canvas()->update();
+}
+
+void
+DisplayForm::onPlotPointSelected(const QPointF p)
+{
+ emit plotPointSelected(p, 3);
+}
+
+void
+DisplayForm::Reset()
+{
+}
+
+
+void
+DisplayForm::closeEvent( QCloseEvent *e )
+{
+ qApp->processEvents();
+ QWidget::closeEvent(e);
+}
+
+void
+DisplayForm::setUpdateTime(double t)
+{
+ d_update_time = t;
+ d_displayTimer->start(d_update_time);
+}
+
+void
+DisplayForm::setTitle(int which, const QString &title)
+{
+ _displayPlot->setTitle(which, title);
+}
+
+void
+DisplayForm::setColor(int which, const QString &color)
+{
+ _displayPlot->setColor(which, color);
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setLineWidth(int which, int width)
+{
+ _displayPlot->setLineWidth(which, width);
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setLineStyle(int which, Qt::PenStyle style)
+{
+ _displayPlot->setLineStyle(which, style);
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setLineMarker(int which, QwtSymbol::Style marker)
+{
+ _displayPlot->setLineMarker(which, marker);
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setStop(bool on)
+{
+ if(!on) {
+ // will auto-detach if already attached.
+ _displayPlot->setStop(false);
+ _stop_state = false;
+ }
+ else {
+ _displayPlot->setStop(true);
+ _stop_state = true;
+ }
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setStop()
+{
+ if(_stop_state == false)
+ setStop(true);
+ else
+ setStop(false);
+}
+
+void
+DisplayForm::setGrid(bool on)
+{
+ if(on) {
+ // will auto-detach if already attached.
+ _grid->attach(_displayPlot);
+ _grid_state = true;
+ }
+ else {
+ _grid->detach();
+ _grid_state = false;
+ }
+ _displayPlot->replot();
+}
+
+void
+DisplayForm::setGrid()
+{
+ if(_grid_state == false)
+ setGrid(true);
+ else
+ setGrid(false);
+}
diff --git a/gr-qtgui/lib/displayform.h b/gr-qtgui/lib/displayform.h
new file mode 100644
index 0000000000..82b28c745d
--- /dev/null
+++ b/gr-qtgui/lib/displayform.h
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef DISPLAY_FORM_H
+#define DISPLAY_FORM_H
+
+#include <spectrumUpdateEvents.h>
+#include <QtGui/QtGui>
+#include <vector>
+
+#include <qwt_plot_grid.h>
+#include <qwt_plot_layout.h>
+
+#include "DisplayPlot.h"
+#include "form_menus.h"
+
+class DisplayForm : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ DisplayForm(int nplots=1, QWidget* parent = 0);
+ ~DisplayForm();
+
+ virtual DisplayPlot* getPlot() = 0;
+ void Reset();
+
+public slots:
+ void resizeEvent( QResizeEvent * e );
+ void mousePressEvent( QMouseEvent * e);
+ virtual void customEvent( QEvent * e ) = 0;
+
+ void closeEvent( QCloseEvent * e );
+
+ void setUpdateTime(double t);
+
+ void setTitle(int which, const QString &title);
+ void setColor(int which, const QString &color);
+ void setLineWidth(int which, int width);
+ void setLineStyle(int which, Qt::PenStyle style);
+ void setLineMarker(int which, QwtSymbol::Style style);
+
+ void setStop(bool on);
+ void setStop();
+
+ void setGrid(bool on);
+ void setGrid();
+
+private slots:
+ virtual void newData(const QEvent*) = 0;
+ void updateGuiTimer();
+
+ void onPlotPointSelected(const QPointF p);
+
+signals:
+ void plotPointSelected(const QPointF p, int type);
+
+protected:
+ int _nplots;
+
+ QGridLayout *_layout;
+ DisplayPlot* _displayPlot;
+ bool _systemSpecifiedFlag;
+
+ QwtPlotGrid *_grid;
+
+ QMenu *_menu;
+
+ QAction *_stop_act;
+ bool _stop_state;
+ QAction *_grid_act;
+ bool _grid_state;
+
+ QList<QMenu*> _lines_menu;
+ QList<LineTitleAction*> _line_title_act;
+ QList<LineColorMenu*> _line_color_menu;
+ QList<LineWidthMenu*> _line_width_menu;
+ QList<LineStyleMenu*> _line_style_menu;
+ QList<LineMarkerMenu*> _line_marker_menu;
+
+ QTimer *d_displayTimer;
+ double d_update_time;
+};
+
+#endif /* DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/form_menus.h b/gr-qtgui/lib/form_menus.h
new file mode 100644
index 0000000000..01695f2c46
--- /dev/null
+++ b/gr-qtgui/lib/form_menus.h
@@ -0,0 +1,882 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef FORM_MENUS_H
+#define FORM_MENUS_H
+
+#include <stdexcept>
+#include <vector>
+#include <QtGui/QtGui>
+#include <qwt_symbol.h>
+#include <filter/firdes.h>
+#include "qtgui_types.h"
+
+class LineColorMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ LineColorMenu(int which, QWidget *parent)
+ : QMenu("Line Color", parent), d_which(which)
+ {
+ d_act.push_back(new QAction("Blue", this));
+ d_act.push_back(new QAction("Red", this));
+ d_act.push_back(new QAction("Green", this));
+ d_act.push_back(new QAction("Black", this));
+ d_act.push_back(new QAction("Cyan", this));
+ d_act.push_back(new QAction("Magenta", this));
+ d_act.push_back(new QAction("Yellow", this));
+ d_act.push_back(new QAction("Gray", this));
+ d_act.push_back(new QAction("Dark Red", this));
+ d_act.push_back(new QAction("Dark Green", this));
+ d_act.push_back(new QAction("Dark Blue", this));
+ d_act.push_back(new QAction("Dark Gray", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getBlue()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getRed()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getGreen()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getBlack()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getCyan()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(getMagenta()));
+ connect(d_act[6], SIGNAL(triggered()), this, SLOT(getYellow()));
+ connect(d_act[7], SIGNAL(triggered()), this, SLOT(getGray()));
+ connect(d_act[8], SIGNAL(triggered()), this, SLOT(getDarkRed()));
+ connect(d_act[9], SIGNAL(triggered()), this, SLOT(getDarkGreen()));
+ connect(d_act[10], SIGNAL(triggered()), this, SLOT(getDarkBlue()));
+ connect(d_act[11], SIGNAL(triggered()), this, SLOT(getDarkGray()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~LineColorMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("LineColorMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(int which, const QString &name);
+
+public slots:
+ void getBlue() { emit whichTrigger(d_which, "blue"); }
+ void getRed() { emit whichTrigger(d_which, "red"); }
+ void getGreen() { emit whichTrigger(d_which, "green"); }
+ void getBlack() { emit whichTrigger(d_which, "black"); }
+ void getCyan() { emit whichTrigger(d_which, "cyan"); }
+ void getMagenta() { emit whichTrigger(d_which, "magenta"); }
+ void getYellow() { emit whichTrigger(d_which, "yellow"); }
+ void getGray() { emit whichTrigger(d_which, "gray"); }
+ void getDarkRed() { emit whichTrigger(d_which, "darkred"); }
+ void getDarkGreen() { emit whichTrigger(d_which, "darkgreen"); }
+ void getDarkBlue() { emit whichTrigger(d_which, "darkblue"); }
+ void getDarkGray() { emit whichTrigger(d_which, "darkgray"); }
+
+private:
+ QList<QAction *> d_act;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class LineWidthMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ LineWidthMenu(int which, QWidget *parent)
+ : QMenu("Line Width", parent), d_which(which)
+ {
+ d_act.push_back(new QAction("1", this));
+ d_act.push_back(new QAction("2", this));
+ d_act.push_back(new QAction("3", this));
+ d_act.push_back(new QAction("4", this));
+ d_act.push_back(new QAction("5", this));
+ d_act.push_back(new QAction("6", this));
+ d_act.push_back(new QAction("7", this));
+ d_act.push_back(new QAction("8", this));
+ d_act.push_back(new QAction("9", this));
+ d_act.push_back(new QAction("10", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOne()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getTwo()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getThree()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getFour()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getFive()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(getSix()));
+ connect(d_act[6], SIGNAL(triggered()), this, SLOT(getSeven()));
+ connect(d_act[7], SIGNAL(triggered()), this, SLOT(getEight()));
+ connect(d_act[8], SIGNAL(triggered()), this, SLOT(getNine()));
+ connect(d_act[9], SIGNAL(triggered()), this, SLOT(getTen()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~LineWidthMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("LineWidthMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(int which, int width);
+
+public slots:
+ void getOne() { emit whichTrigger(d_which, 1); }
+ void getTwo() { emit whichTrigger(d_which, 2); }
+ void getThree() { emit whichTrigger(d_which, 3); }
+ void getFour() { emit whichTrigger(d_which, 4); }
+ void getFive() { emit whichTrigger(d_which, 5); }
+ void getSix() { emit whichTrigger(d_which, 6); }
+ void getSeven() { emit whichTrigger(d_which, 7); }
+ void getEight() { emit whichTrigger(d_which, 8); }
+ void getNine() { emit whichTrigger(d_which, 9); }
+ void getTen() { emit whichTrigger(d_which, 10); }
+
+private:
+ QList<QAction *> d_act;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class LineStyleMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ LineStyleMenu(int which, QWidget *parent)
+ : QMenu("Line Style", parent), d_which(which)
+ {
+ d_act.push_back(new QAction("None", this));
+ d_act.push_back(new QAction("Solid", this));
+ d_act.push_back(new QAction("Dash", this));
+ d_act.push_back(new QAction("Dots", this));
+ d_act.push_back(new QAction("Dash-Dot", this));
+ d_act.push_back(new QAction("Dash-Dot-Dot", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getSolid()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getDash()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getDots()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getDashDot()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(getDashDotDot()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~LineStyleMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("LineStyleMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(int which, Qt::PenStyle);
+
+public slots:
+ void getNone() { emit whichTrigger(d_which, Qt::NoPen); }
+ void getSolid() { emit whichTrigger(d_which, Qt::SolidLine); }
+ void getDash() { emit whichTrigger(d_which, Qt::DashLine); }
+ void getDots() { emit whichTrigger(d_which, Qt::DotLine); }
+ void getDashDot() { emit whichTrigger(d_which, Qt::DashDotLine); }
+ void getDashDotDot() { emit whichTrigger(d_which, Qt::DashDotDotLine); }
+
+private:
+ QList<QAction *> d_act;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class LineMarkerMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ LineMarkerMenu(int which, QWidget *parent)
+ : QMenu("Line Marker", parent), d_which(which)
+ {
+ d_act.push_back(new QAction("None", this));
+ d_act.push_back(new QAction("Circle", this));
+ d_act.push_back(new QAction("Rectangle", this));
+ d_act.push_back(new QAction("Diamond", this));
+ d_act.push_back(new QAction("Triangle", this));
+ d_act.push_back(new QAction("Down Triangle", this));
+ d_act.push_back(new QAction("Left Triangle", this));
+ d_act.push_back(new QAction("Right Triangle", this));
+ d_act.push_back(new QAction("Cross", this));
+ d_act.push_back(new QAction("X-Cross", this));
+ d_act.push_back(new QAction("Horiz. Line", this));
+ d_act.push_back(new QAction("Vert. Line", this));
+ d_act.push_back(new QAction("Star 1", this));
+ d_act.push_back(new QAction("Star 2", this));
+ d_act.push_back(new QAction("Hexagon", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getCircle()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getRect()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getDiamond()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getTriangle()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(getDTriangle()));
+ connect(d_act[6], SIGNAL(triggered()), this, SLOT(getLTriangle()));
+ connect(d_act[7], SIGNAL(triggered()), this, SLOT(getRTriangle()));
+ connect(d_act[8], SIGNAL(triggered()), this, SLOT(getCross()));
+ connect(d_act[9], SIGNAL(triggered()), this, SLOT(getXCross()));
+ connect(d_act[10], SIGNAL(triggered()), this, SLOT(getHLine()));
+ connect(d_act[11], SIGNAL(triggered()), this, SLOT(getVLine()));
+ connect(d_act[12], SIGNAL(triggered()), this, SLOT(getStar1()));
+ connect(d_act[13], SIGNAL(triggered()), this, SLOT(getStar2()));
+ connect(d_act[14], SIGNAL(triggered()), this, SLOT(getHexagon()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~LineMarkerMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("LineMarkerMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(int which, QwtSymbol::Style);
+
+public slots:
+ void getNone() { emit whichTrigger(d_which, QwtSymbol::NoSymbol); }
+ void getCircle() { emit whichTrigger(d_which, QwtSymbol::Ellipse); }
+ void getRect() { emit whichTrigger(d_which, QwtSymbol::Rect); }
+ void getDiamond() { emit whichTrigger(d_which, QwtSymbol::Diamond); }
+ void getTriangle() { emit whichTrigger(d_which, QwtSymbol::Triangle); }
+ void getDTriangle() { emit whichTrigger(d_which, QwtSymbol::DTriangle); }
+ void getLTriangle() { emit whichTrigger(d_which, QwtSymbol::LTriangle); }
+ void getRTriangle() { emit whichTrigger(d_which, QwtSymbol::RTriangle); }
+ void getCross() { emit whichTrigger(d_which, QwtSymbol::Cross); }
+ void getXCross() { emit whichTrigger(d_which, QwtSymbol::XCross); }
+ void getHLine() { emit whichTrigger(d_which, QwtSymbol::HLine); }
+ void getVLine() { emit whichTrigger(d_which, QwtSymbol::VLine); }
+ void getStar1() { emit whichTrigger(d_which, QwtSymbol::Star1); }
+ void getStar2() { emit whichTrigger(d_which, QwtSymbol::Star2); }
+ void getHexagon() { emit whichTrigger(d_which, QwtSymbol::Hexagon); }
+
+private:
+ QList<QAction *> d_act;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class LineTitleAction: public QAction
+{
+ Q_OBJECT
+
+public:
+ LineTitleAction(int which, QWidget *parent)
+ : QAction("Line Title", parent), d_which(which)
+ {
+ d_diag = new QDialog(parent);
+ d_diag->setModal(true);
+
+ d_text = new QLineEdit();
+
+ QGridLayout *layout = new QGridLayout(d_diag);
+ QPushButton *btn_ok = new QPushButton(tr("OK"));
+ QPushButton *btn_cancel = new QPushButton(tr("Cancel"));
+
+ layout->addWidget(d_text, 0, 0, 1, 2);
+ layout->addWidget(btn_ok, 1, 0);
+ layout->addWidget(btn_cancel, 1, 1);
+
+ connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText()));
+ connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close()));
+
+ connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag()));
+ }
+
+ ~LineTitleAction()
+ {}
+
+signals:
+ void whichTrigger(int which, const QString &text);
+
+public slots:
+ void getTextDiag()
+ {
+ d_diag->exec();
+ }
+
+private slots:
+ void getText()
+ {
+ emit whichTrigger(d_which, d_text->text());
+ d_diag->accept();
+ }
+
+private:
+ int d_which;
+
+ QDialog *d_diag;
+ QLineEdit *d_text;
+};
+
+
+/********************************************************************/
+
+
+class OtherAction: public QAction
+{
+ Q_OBJECT
+
+public:
+ OtherAction(QWidget *parent)
+ : QAction("Other", parent)
+ {
+ d_diag = new QDialog(parent);
+ d_diag->setModal(true);
+
+ d_text = new QLineEdit();
+
+ QGridLayout *layout = new QGridLayout(d_diag);
+ QPushButton *btn_ok = new QPushButton(tr("OK"));
+ QPushButton *btn_cancel = new QPushButton(tr("Cancel"));
+
+ layout->addWidget(d_text, 0, 0, 1, 2);
+ layout->addWidget(btn_ok, 1, 0);
+ layout->addWidget(btn_cancel, 1, 1);
+
+ connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText()));
+ connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close()));
+
+ connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag()));
+ }
+
+ ~OtherAction()
+ {}
+
+signals:
+ void whichTrigger(const QString &text);
+
+public slots:
+ void getTextDiag()
+ {
+ d_diag->exec();
+ }
+
+private slots:
+ void getText()
+ {
+ emit whichTrigger(d_text->text());
+ d_diag->accept();
+ }
+
+private:
+ QDialog *d_diag;
+ QLineEdit *d_text;
+};
+
+/********************************************************************/
+
+
+class OtherDualAction: public QAction
+{
+ Q_OBJECT
+
+public:
+ OtherDualAction(QString label0, QString label1, QWidget *parent)
+ : QAction("Other", parent)
+ {
+ d_diag = new QDialog(parent);
+ d_diag->setModal(true);
+
+ d_text0 = new QLineEdit();
+ d_text1 = new QLineEdit();
+
+ QLabel *_label0 = new QLabel(label0);
+ QLabel *_label1 = new QLabel(label1);
+
+ QGridLayout *layout = new QGridLayout(d_diag);
+ QPushButton *btn_ok = new QPushButton(tr("OK"));
+ QPushButton *btn_cancel = new QPushButton(tr("Cancel"));
+
+ layout->addWidget(_label0, 0, 0, 1, 2);
+ layout->addWidget(_label1, 1, 0, 1, 2);
+
+ layout->addWidget(d_text0, 0, 1, 1, 2);
+ layout->addWidget(d_text1, 1, 1, 1, 2);
+ layout->addWidget(btn_ok, 2, 0);
+ layout->addWidget(btn_cancel, 2, 1);
+
+ connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText()));
+ connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close()));
+
+ connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag()));
+ }
+
+ ~OtherDualAction()
+ {}
+
+signals:
+ void whichTrigger(const QString &text0, const QString &text1);
+
+public slots:
+ void getTextDiag()
+ {
+ d_diag->exec();
+ }
+
+private slots:
+ void getText()
+ {
+ emit whichTrigger(d_text0->text(), d_text1->text());
+ d_diag->accept();
+ }
+
+private:
+ QDialog *d_diag;
+ QLineEdit *d_text0;
+ QLineEdit *d_text1;
+};
+
+
+/********************************************************************/
+
+
+class FFTSizeMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ FFTSizeMenu(QWidget *parent)
+ : QMenu("FFT Size", parent)
+ {
+ d_act.push_back(new QAction("32", this));
+ d_act.push_back(new QAction("64", this));
+ d_act.push_back(new QAction("128", this));
+ d_act.push_back(new QAction("256", this));
+ d_act.push_back(new QAction("512", this));
+ d_act.push_back(new QAction("1024", this));
+ d_act.push_back(new QAction("2048", this));
+ d_act.push_back(new QAction("4096", this));
+ d_act.push_back(new QAction("8192", this));
+ d_act.push_back(new QAction("16384", this));
+ d_act.push_back(new QAction("32768", this));
+ d_act.push_back(new OtherAction(this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(get05()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(get06()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(get07()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(get08()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(get09()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(get10()));
+ connect(d_act[6], SIGNAL(triggered()), this, SLOT(get11()));
+ connect(d_act[7], SIGNAL(triggered()), this, SLOT(get12()));
+ connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13()));
+ connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14()));
+ connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15()));
+ connect(d_act[11], SIGNAL(whichTrigger(const QString&)),
+ this, SLOT(getOther(const QString&)));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~FFTSizeMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
+ }
+
+ signals:
+ void whichTrigger(int size);
+
+ public slots:
+ void get05() { emit whichTrigger(32); }
+ void get06() { emit whichTrigger(64); }
+ void get07() { emit whichTrigger(128); }
+ void get08() { emit whichTrigger(256); }
+ void get09() { emit whichTrigger(512); }
+ void get10() { emit whichTrigger(1024); }
+ void get11() { emit whichTrigger(2048); }
+ void get12() { emit whichTrigger(4096); }
+ void get13() { emit whichTrigger(8192); }
+ void get14() { emit whichTrigger(16384); }
+ void get15() { emit whichTrigger(32768); }
+ void getOther(const QString &str)
+ {
+ int value = str.toInt();
+ emit whichTrigger(value);
+ }
+
+private:
+ QList<QAction *> d_act;
+ OtherAction *d_other;
+};
+
+
+/********************************************************************/
+
+
+class FFTAverageMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ FFTAverageMenu(QWidget *parent)
+ : QMenu("FFT Average", parent)
+ {
+ d_act.push_back(new QAction("Off", this));
+ d_act.push_back(new QAction("High", this));
+ d_act.push_back(new QAction("Medium", this));
+ d_act.push_back(new QAction("Low", this));
+ d_act.push_back(new OtherAction(this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOff()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHigh()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getLow()));
+ connect(d_act[4], SIGNAL(whichTrigger(const QString&)),
+ this, SLOT(getOther(const QString&)));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~FFTAverageMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
+ }
+
+ signals:
+ void whichTrigger(float alpha);
+
+ public slots:
+ void getOff() { emit whichTrigger(1.0); }
+ void getHigh() { emit whichTrigger(0.05); }
+ void getMedium() { emit whichTrigger(0.1); }
+ void getLow() { emit whichTrigger(0.2); }
+ void getOther(const QString &str)
+ {
+ float value = str.toFloat();
+ emit whichTrigger(value);
+ }
+
+private:
+ QList<QAction *> d_act;
+ OtherAction *d_other;
+};
+
+
+/********************************************************************/
+
+
+class FFTWindowMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ FFTWindowMenu(QWidget *parent)
+ : QMenu("FFT Window", parent)
+ {
+ d_act.push_back(new QAction("None", this));
+ d_act.push_back(new QAction("Hamming", this));
+ d_act.push_back(new QAction("Hann", this));
+ d_act.push_back(new QAction("Blackman", this));
+ d_act.push_back(new QAction("Blackman-harris", this));
+ d_act.push_back(new QAction("Rectangular", this));
+ d_act.push_back(new QAction("Kaiser", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHamming()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getHann()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getBlackman()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getBlackmanharris()));
+ connect(d_act[5], SIGNAL(triggered()), this, SLOT(getRectangular()));
+ connect(d_act[6], SIGNAL(triggered()), this, SLOT(getKaiser()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~FFTWindowMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("FFTWindowMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(const gr::filter::firdes::win_type type);
+
+public slots:
+ void getNone() { emit whichTrigger(gr::filter::firdes::WIN_NONE); }
+ void getHamming() { emit whichTrigger(gr::filter::firdes::WIN_HAMMING); }
+ void getHann() { emit whichTrigger(gr::filter::firdes::WIN_HANN); }
+ void getBlackman() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN); }
+ void getBlackmanharris() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN_hARRIS); }
+ void getRectangular() { emit whichTrigger(gr::filter::firdes::WIN_RECTANGULAR); }
+ void getKaiser() { emit whichTrigger(gr::filter::firdes::WIN_KAISER); }
+
+private:
+ QList<QAction *> d_act;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class NPointsMenu: public QAction
+{
+ Q_OBJECT
+
+public:
+ NPointsMenu(QWidget *parent)
+ : QAction("Number of Points", parent)
+ {
+ d_diag = new QDialog(parent);
+ d_diag->setModal(true);
+
+ d_text = new QLineEdit();
+
+ QGridLayout *layout = new QGridLayout(d_diag);
+ QPushButton *btn_ok = new QPushButton(tr("OK"));
+ QPushButton *btn_cancel = new QPushButton(tr("Cancel"));
+
+ layout->addWidget(d_text, 0, 0, 1, 2);
+ layout->addWidget(btn_ok, 1, 0);
+ layout->addWidget(btn_cancel, 1, 1);
+
+ connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText()));
+ connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close()));
+
+ connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag()));
+ }
+
+ ~NPointsMenu()
+ {}
+
+signals:
+ void whichTrigger(const int npts);
+
+public slots:
+ void getTextDiag()
+ {
+ d_diag->show();
+ }
+
+private slots:
+ void getText()
+ {
+ emit whichTrigger(d_text->text().toInt());
+ d_diag->accept();
+ }
+
+private:
+ QDialog *d_diag;
+ QLineEdit *d_text;
+};
+
+
+/********************************************************************/
+
+
+class ColorMapMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ ColorMapMenu(QWidget *parent)
+ : QMenu("Color Map", parent)
+ {
+ d_act.push_back(new QAction("Multi-Color", this));
+ d_act.push_back(new QAction("White Hot", this));
+ d_act.push_back(new QAction("Black Hot", this));
+ d_act.push_back(new QAction("Incandescent", this));
+ d_act.push_back(new QAction("Other", this));
+ //d_act.push_back(new OtherDualAction("Min Intensity: ", "Max Intensity: ", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getMultiColor()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getWhiteHot()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getBlackHot()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getIncandescent()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getOther()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+
+ d_max_value = QColor("white");
+ d_min_value = QColor("white");
+ }
+
+ ~ColorMapMenu()
+ {}
+
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
+
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("ColorMapMenu::getAction: which out of range.\n");
+ }
+
+ signals:
+ void whichTrigger(const int type, const QColor &min_color=QColor(),
+ const QColor &max_color=QColor());
+
+ public slots:
+ void getMultiColor() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); }
+ void getWhiteHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_WHITE_HOT); }
+ void getBlackHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_BLACK_HOT); }
+ void getIncandescent() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_INCANDESCENT); }
+ //void getOther(const QString &min_str, const QString &max_str)
+ void getOther()
+ {
+ QMessageBox::information(this, "Set low and high intensities",
+ "In the next windows, select the low and then the high intensity colors.",
+ QMessageBox::Ok);
+ d_min_value = QColorDialog::getColor(d_min_value, this);
+ d_max_value = QColorDialog::getColor(d_max_value, this);
+
+ emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_USER_DEFINED,
+ d_min_value, d_max_value);
+ }
+
+private:
+ QList<QAction *> d_act;
+ OtherDualAction *d_other;
+ QColor d_max_value, d_min_value;
+};
+
+
+/********************************************************************/
+
+
+#endif /* FORM_MENUS_H */
diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc
new file mode 100644
index 0000000000..cf5c989c09
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_c_impl.cc
@@ -0,0 +1,376 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "freq_sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ freq_sink_c::sptr
+ freq_sink_c::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new freq_sink_c_impl(fftsize, wintype,
+ fc, bw, name,
+ nconnections,
+ parent));
+ }
+
+ freq_sink_c_impl::freq_sink_c_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("freq_sink_c",
+ gr_make_io_signature(1, -1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_fftsize(fftsize), d_fftavg(1.0),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_nconnections(nconnections), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+ d_index = 0;
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_complex(d_fftsize));
+ d_magbufs.push_back(fft::malloc_double(d_fftsize));
+
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(gr_complex));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
+ }
+
+ buildwindow();
+
+ initialize();
+ }
+
+ freq_sink_c_impl::~freq_sink_c_impl()
+ {
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+ }
+ delete d_fft;
+ fft::free(d_fbuf);
+ }
+
+ void
+ freq_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ freq_sink_c_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new FreqDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetFFTWindowType(d_wintype);
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ d_center_freq - d_bandwidth/2.0,
+ d_center_freq + d_bandwidth/2.0);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ freq_sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ freq_sink_c_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ freq_sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ freq_sink_c_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ freq_sink_c_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ freq_sink_c_impl::set_fft_average(const float fftavg)
+ {
+ d_fftavg = fftavg;
+ d_main_gui->SetFFTAverage(fftavg);
+ }
+
+ float
+ freq_sink_c_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ freq_sink_c_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ freq_sink_c_impl::set_fft_power_db(double min, double max)
+ {
+ d_main_gui->SetFrequencyAxis(min, max);
+ }
+
+ void
+ freq_sink_c_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ freq_sink_c_impl::set_title(int which, const std::string &title)
+ {
+ d_main_gui->setTitle(which, title.c_str());
+ }
+
+ void
+ freq_sink_c_impl::set_color(int which, const std::string &color)
+ {
+ d_main_gui->setColor(which, color.c_str());
+ }
+
+ void
+ freq_sink_c_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ freq_sink_c_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ freq_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ freq_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ freq_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size)
+ {
+ if(d_window.size()) {
+ volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in,
+ &d_window.front(), size);
+ }
+ else {
+ memcpy(d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size);
+ }
+
+ d_fft->execute(); // compute the fft
+
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+
+ // Perform shift operation
+ unsigned int len = (unsigned int)(floor(size/2.0));
+ float *tmp = (float*)malloc(sizeof(float)*len);
+ memcpy(tmp, &data_out[0], sizeof(float)*len);
+ memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len));
+ memcpy(&data_out[size - len], tmp, sizeof(float)*len);
+ free(tmp);
+ }
+
+ void
+ freq_sink_c_impl::windowreset()
+ {
+ filter::firdes::win_type newwintype;
+ newwintype = d_main_gui->GetFFTWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ freq_sink_c_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != filter::firdes::WIN_NONE) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ freq_sink_c_impl::fftresize()
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ int newfftsize = d_main_gui->GetFFTSize();
+ d_fftavg = d_main_gui->GetFFTAverage();
+
+ if(newfftsize != d_fftsize) {
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+
+ d_residbufs[i] = fft::malloc_complex(newfftsize);
+ d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(gr_complex));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
+ }
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+ }
+ }
+
+ int
+ freq_sink_c_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+
+ for(int n = 0; n < d_nconnections; n++) {
+ // Fill up residbuf with d_fftsize number of items
+ in = (const gr_complex*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid);
+
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
+ }
+
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new FreqUpdateEvent(d_magbufs, d_fftsize));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ for(int n = 0; n < d_nconnections; n++) {
+ in = (const gr_complex*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h
new file mode 100644
index 0000000000..106e50497d
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_c_impl.h
@@ -0,0 +1,110 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H
+
+#include <qtgui/freq_sink_c.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <freqdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API freq_sink_c_impl : public freq_sink_c
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ gruel::mutex d_mutex;
+
+ int d_fftsize;
+ float d_fftavg;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ std::vector<gr_complex*> d_residbufs;
+ std::vector<double*> d_magbufs;
+ float *d_fbuf;
+
+ QWidget *d_parent;
+ FreqDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const gr_complex *data_in, int size);
+
+ public:
+ freq_sink_c_impl(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~freq_sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_fft_power_db(double min, double max);
+
+ void set_update_time(double t);
+ void set_title(int which, const std::string &title);
+ void set_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, Qt::PenStyle style);
+ void set_line_marker(int which, QwtSymbol::Style marker);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc
new file mode 100644
index 0000000000..2cf43e9994
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_f_impl.cc
@@ -0,0 +1,380 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "freq_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ freq_sink_f::sptr
+ freq_sink_f::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new freq_sink_f_impl(fftsize, wintype,
+ fc, bw, name,
+ nconnections,
+ parent));
+ }
+
+ freq_sink_f_impl::freq_sink_f_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("freq_sink_f",
+ gr_make_io_signature(1, -1, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_fftsize(fftsize), d_fftavg(1.0),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_nconnections(nconnections), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+ d_index = 0;
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_float(d_fftsize));
+ d_magbufs.push_back(fft::malloc_double(d_fftsize));
+
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
+ }
+
+ buildwindow();
+
+ initialize();
+ }
+
+ freq_sink_f_impl::~freq_sink_f_impl()
+ {
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+ }
+ delete d_fft;
+ fft::free(d_fbuf);
+ }
+
+ void
+ freq_sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ freq_sink_f_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new FreqDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetFFTWindowType(d_wintype);
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ d_center_freq - d_bandwidth/2.0,
+ d_center_freq + d_bandwidth/2.0);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ freq_sink_f_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ freq_sink_f_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ freq_sink_f_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ freq_sink_f_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ freq_sink_f_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ freq_sink_f_impl::set_fft_average(const float fftavg)
+ {
+ d_fftavg = fftavg;
+ d_main_gui->SetFFTAverage(fftavg);
+ }
+
+ float
+ freq_sink_f_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ freq_sink_f_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ freq_sink_f_impl::set_fft_power_db(double min, double max)
+ {
+ d_main_gui->SetFrequencyAxis(min, max);
+ }
+
+ void
+ freq_sink_f_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ freq_sink_f_impl::set_title(int which, const std::string &title)
+ {
+ d_main_gui->setTitle(which, title.c_str());
+ }
+
+ void
+ freq_sink_f_impl::set_color(int which, const std::string &color)
+ {
+ d_main_gui->setColor(which, color.c_str());
+ }
+
+ void
+ freq_sink_f_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ freq_sink_f_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ freq_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+
+ void
+ freq_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ freq_sink_f_impl::fft(float *data_out, const float *data_in, int size)
+ {
+ // float to complex conversion
+ gr_complex *dst = d_fft->get_inbuf();
+ for (int i = 0; i < size; i++)
+ dst[i] = data_in[i];
+
+ if(d_window.size()) {
+ volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), dst,
+ &d_window.front(), size);
+ }
+
+ d_fft->execute(); // compute the fft
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+
+ // Perform shift operation
+ unsigned int len = (unsigned int)(floor(size/2.0));
+ float *tmp = (float*)malloc(sizeof(float)*len);
+ memcpy(tmp, &data_out[0], sizeof(float)*len);
+ memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len));
+ memcpy(&data_out[size - len], tmp, sizeof(float)*len);
+ free(tmp);
+ }
+
+ void
+ freq_sink_f_impl::windowreset()
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ filter::firdes::win_type newwintype;
+ newwintype = d_main_gui->GetFFTWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ freq_sink_f_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != filter::firdes::WIN_NONE) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ freq_sink_f_impl::fftresize()
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ int newfftsize = d_main_gui->GetFFTSize();
+ d_fftavg = d_main_gui->GetFFTAverage();
+
+ if(newfftsize != d_fftsize) {
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+
+ d_residbufs[i] = fft::malloc_float(newfftsize);
+ d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(float));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
+ }
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+ }
+ }
+
+ int
+ freq_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const float *in = (const float*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+
+ for(int n = 0; n < d_nconnections; n++) {
+ // Fill up residbuf with d_fftsize number of items
+ in = (const float*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid);
+
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
+ }
+
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new FreqUpdateEvent(d_magbufs, d_fftsize));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ for(int n = 0; n < d_nconnections; n++) {
+ in = (const float*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h
new file mode 100644
index 0000000000..a358953629
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_f_impl.h
@@ -0,0 +1,110 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H
+#define INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H
+
+#include <qtgui/freq_sink_f.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <freqdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API freq_sink_f_impl : public freq_sink_f
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ gruel::mutex d_mutex;
+
+ int d_fftsize;
+ float d_fftavg;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ std::vector<float*> d_residbufs;
+ std::vector<double*> d_magbufs;
+ float *d_fbuf;
+
+ QWidget *d_parent;
+ FreqDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const float *data_in, int size);
+
+ public:
+ freq_sink_f_impl(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~freq_sink_f_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_fft_power_db(double min, double max);
+
+ void set_update_time(double t);
+ void set_title(int which, const std::string &title);
+ void set_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, Qt::PenStyle style);
+ void set_line_marker(int which, QwtSymbol::Style marker);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H */
diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc
new file mode 100644
index 0000000000..6f12fe5090
--- /dev/null
+++ b/gr-qtgui/lib/freqdisplayform.cc
@@ -0,0 +1,162 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 <cmath>
+#include <QMessageBox>
+#include <freqdisplayform.h>
+#include <iostream>
+
+FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent)
+ : DisplayForm(nplots, parent)
+{
+ _intValidator = new QIntValidator(this);
+ _intValidator->setBottom(0);
+
+ _layout = new QGridLayout(this);
+ _displayPlot = new FrequencyDisplayPlot(nplots, this);
+ _layout->addWidget(_displayPlot, 0, 0);
+ setLayout(_layout);
+
+ _numRealDataPoints = 1024;
+ _fftsize = 1024;
+ _fftavg = 1.0;
+
+ FFTSizeMenu *sizemenu = new FFTSizeMenu(this);
+ FFTAverageMenu *avgmenu = new FFTAverageMenu(this);
+ FFTWindowMenu *winmenu = new FFTWindowMenu(this);
+ _menu->addMenu(sizemenu);
+ _menu->addMenu(avgmenu);
+ _menu->addMenu(winmenu);
+ connect(sizemenu, SIGNAL(whichTrigger(int)),
+ this, SLOT(SetFFTSize(const int)));
+ connect(avgmenu, SIGNAL(whichTrigger(float)),
+ this, SLOT(SetFFTAverage(const float)));
+ connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
+ this, SLOT(SetFFTWindowType(const gr::filter::firdes::win_type)));
+
+ Reset();
+
+ connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)),
+ this, SLOT(onPlotPointSelected(const QPointF)));
+}
+
+FreqDisplayForm::~FreqDisplayForm()
+{
+ // Qt deletes children when parent is deleted
+
+ // Don't worry about deleting Display Plots - they are deleted when parents are deleted
+ delete _intValidator;
+}
+
+FrequencyDisplayPlot*
+FreqDisplayForm::getPlot()
+{
+ return ((FrequencyDisplayPlot*)_displayPlot);
+}
+
+void
+FreqDisplayForm::newData(const QEvent *updateEvent)
+{
+ FreqUpdateEvent *fevent = (FreqUpdateEvent*)updateEvent;
+ const std::vector<double*> dataPoints = fevent->getPoints();
+ const uint64_t numDataPoints = fevent->getNumDataPoints();
+
+ getPlot()->PlotNewData(dataPoints, numDataPoints,
+ 0, 0, 0, d_update_time);
+}
+
+void
+FreqDisplayForm::customEvent( QEvent * e)
+{
+ if(e->type() == FreqUpdateEvent::Type()) {
+ newData(e);
+ }
+}
+
+int
+FreqDisplayForm::GetFFTSize() const
+{
+ return _fftsize;
+}
+
+float
+FreqDisplayForm::GetFFTAverage() const
+{
+ return _fftavg;
+}
+
+gr::filter::firdes::win_type
+FreqDisplayForm::GetFFTWindowType() const
+{
+ return _fftwintype;
+}
+
+void
+FreqDisplayForm::SetFFTSize(const int newsize)
+{
+ _fftsize = newsize;
+}
+
+void
+FreqDisplayForm::SetFFTAverage(const float newavg)
+{
+ _fftavg = newavg;
+ getPlot()->replot();
+}
+
+void
+FreqDisplayForm::SetFFTWindowType(const gr::filter::firdes::win_type newwin)
+{
+ _fftwintype = newwin;
+}
+
+void
+FreqDisplayForm::SetFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency)
+{
+ double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
+
+ if(fdiff > 0) {
+ std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
+ double units10 = floor(log10(fdiff));
+ double units3 = std::max(floor(units10 / 3.0), 0.0);
+ double units = pow(10, (units10-fmod(units10, 3.0)));
+ int iunit = static_cast<int>(units3);
+
+ _startFrequency = newStartFrequency;
+ _stopFrequency = newStopFrequency;
+ double centerFrequency = newCenterFrequency;
+
+ getPlot()->SetFrequencyRange(_startFrequency,
+ _stopFrequency,
+ centerFrequency,
+ true,
+ units, strunits[iunit]);
+ }
+}
+
+void
+FreqDisplayForm::SetFrequencyAxis(double min, double max)
+{
+ getPlot()->set_yaxis(min, max);
+}
diff --git a/gr-qtgui/lib/freqdisplayform.h b/gr-qtgui/lib/freqdisplayform.h
new file mode 100644
index 0000000000..ffce317c4f
--- /dev/null
+++ b/gr-qtgui/lib/freqdisplayform.h
@@ -0,0 +1,75 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef FREQ_DISPLAY_FORM_H
+#define FREQ_DISPLAY_FORM_H
+
+#include <spectrumUpdateEvents.h>
+#include <FrequencyDisplayPlot.h>
+#include <QtGui/QtGui>
+#include <vector>
+#include <filter/firdes.h>
+
+#include "displayform.h"
+
+class FreqDisplayForm : public DisplayForm
+{
+ Q_OBJECT
+
+ public:
+ FreqDisplayForm(int nplots=1, QWidget* parent = 0);
+ ~FreqDisplayForm();
+
+ FrequencyDisplayPlot* getPlot();
+
+ int GetFFTSize() const;
+ float GetFFTAverage() const;
+ gr::filter::firdes::win_type GetFFTWindowType() const;
+
+public slots:
+ void customEvent(QEvent *e);
+
+ void SetFFTSize(const int);
+ void SetFFTAverage(const float);
+ void SetFFTWindowType(const gr::filter::firdes::win_type);
+
+ void SetFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency);
+ void SetFrequencyAxis(double min, double max);
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ uint64_t _numRealDataPoints;
+ QIntValidator* _intValidator;
+
+ double _startFrequency;
+ double _stopFrequency;
+
+ int _fftsize;
+ float _fftavg;
+ gr::filter::firdes::win_type _fftwintype;
+};
+
+#endif /* FREQ_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc
deleted file mode 100644
index de730a8710..0000000000
--- a/gr-qtgui/lib/qtgui_sink_c.cc
+++ /dev/null
@@ -1,310 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,2010,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <qtgui_sink_c.h>
-#include <gr_io_signature.h>
-#include <string.h>
-
-#include <QTimer>
-
-qtgui_sink_c_sptr
-qtgui_make_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent)
-{
- return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype,
- fc, bw, name,
- plotfreq, plotwaterfall,
- plottime, plotconst,
- parent));
-}
-
-qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent)
- : gr_block ("sink_c",
- gr_make_io_signature (1, -1, sizeof(gr_complex)),
- gr_make_io_signature (0, 0, 0)),
- d_fftsize(fftsize),
- d_wintype((gr_firdes::win_type)(wintype)),
- d_center_freq(fc), d_bandwidth(bw), d_name(name),
- d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall),
- d_plottime(plottime), d_plotconst(plotconst),
- d_parent(parent)
-{
- d_main_gui = NULL;
-
- // Perform fftshift operation;
- // this is usually desired when plotting
- d_shift = true;
-
- d_fft = new gri_fft_complex (d_fftsize, true);
-
- d_index = 0;
- d_residbuf = new gr_complex[d_fftsize];
-
- buildwindow();
-
- initialize();
-}
-
-qtgui_sink_c::~qtgui_sink_c()
-{
- delete d_main_gui;
- delete [] d_residbuf;
- delete d_fft;
-}
-
-void
-qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required)
-{
- unsigned int ninputs = ninput_items_required.size();
- for (unsigned int i = 0; i < ninputs; i++) {
- ninput_items_required[i] = std::min(d_fftsize, 8191);
- }
-}
-
-void
-qtgui_sink_c::initialize()
-{
- if(qApp != NULL) {
- d_qApplication = qApp;
- }
- else {
- int argc=0;
- char **argv = NULL;
- d_qApplication = new QApplication(argc, argv);
- }
-
- if(d_center_freq < 0) {
- throw std::runtime_error("qtgui_sink_c: Received bad center frequency.\n");
- }
-
- uint64_t maxBufferSize = 32768;
- d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize,
- d_center_freq,
- -d_bandwidth/2.0,
- d_bandwidth/2.0);
-
- d_main_gui->SetDisplayTitle(d_name);
- d_main_gui->SetFFTSize(d_fftsize);
- d_main_gui->SetWindowType((int)d_wintype);
-
- d_main_gui->OpenSpectrumWindow(d_parent,
- d_plotfreq, d_plotwaterfall,
- d_plottime, d_plotconst);
-
- // initialize update time to 10 times a second
- set_update_time(0.5);
-
- d_last_update = gruel::high_res_timer_now();
- d_update_active = false;
-}
-
-
-void
-qtgui_sink_c::exec_()
-{
- d_qApplication->exec();
-}
-
-QWidget*
-qtgui_sink_c::qwidget()
-{
- return d_main_gui->qwidget();
-}
-
-PyObject*
-qtgui_sink_c::pyqwidget()
-{
- PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget());
- PyObject *retarg = Py_BuildValue("N", w);
- return retarg;
-}
-
-void
-qtgui_sink_c::set_frequency_range(const double centerfreq,
- const double bandwidth)
-{
- d_center_freq = centerfreq;
- d_bandwidth = bandwidth;
- d_main_gui->SetFrequencyRange(d_center_freq,
- -d_bandwidth/2.0,
- d_bandwidth/2.0);
-}
-
-void
-qtgui_sink_c::set_time_domain_axis(double min, double max)
-{
- d_main_gui->SetTimeDomainAxis(min, max);
-}
-
-void
-qtgui_sink_c::set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax)
-{
- d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax);
-}
-
-void
-qtgui_sink_c::set_constellation_pen_size(int size)
-{
- d_main_gui->SetConstellationPenSize(size);
-}
-
-
-void
-qtgui_sink_c::set_frequency_axis(double min, double max)
-{
- d_main_gui->SetFrequencyAxis(min, max);
-}
-
-void
-qtgui_sink_c::set_update_time(double t)
-{
- d_update_time = t * gruel::high_res_timer_tps();
- d_main_gui->SetUpdateTime(t);
-}
-
-void
-qtgui_sink_c::fft(const gr_complex *data_in, int size)
-{
- if (d_window.size()) {
- gr_complex *dst = d_fft->get_inbuf();
- int i;
- for (i = 0; i < size; i++) // apply window
- dst[i] = data_in[i] * d_window[i];
- }
- else {
- memcpy (d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size);
- }
-
- d_fft->execute (); // compute the fft
-}
-
-void
-qtgui_sink_c::windowreset()
-{
- gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType();
- if(d_wintype != newwintype) {
- d_wintype = newwintype;
- buildwindow();
- }
-}
-
-void
-qtgui_sink_c::buildwindow()
-{
- d_window.clear();
- if(d_wintype != 0) {
- d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76);
- }
-}
-
-void
-qtgui_sink_c::fftresize()
-{
- int newfftsize = d_main_gui->GetFFTSize();
-
- if(newfftsize != d_fftsize) {
-
- // Resize residbuf and replace data
- delete [] d_residbuf;
- d_residbuf = new gr_complex[newfftsize];
-
- // Set new fft size and reset buffer index
- // (throws away any currently held data, but who cares?)
- d_fftsize = newfftsize;
- d_index = 0;
-
- // Reset window to reflect new size
- buildwindow();
-
- // Reset FFTW plan for new size
- delete d_fft;
- d_fft = new gri_fft_complex (d_fftsize, true);
- }
-}
-
-
-int
-qtgui_sink_c::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- int j=0;
- const gr_complex *in = (const gr_complex*)input_items[0];
-
- // Update the FFT size from the application
- fftresize();
- windowreset();
-
- for(int i=0; i < noutput_items; i+=d_fftsize) {
- unsigned int datasize = noutput_items - i;
- unsigned int resid = d_fftsize-d_index;
-
- if (!d_update_active && (gruel::high_res_timer_now() - d_last_update) < d_update_time) {
- consume_each(noutput_items);
- return noutput_items;
- } else {
- d_last_update = gruel::high_res_timer_now();
- d_update_active = true;
- }
-
- // If we have enough input for one full FFT, do it
- if(datasize >= resid) {
- const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now();
-
- // Fill up residbuf with d_fftsize number of items
- memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid);
- d_index = 0;
-
- j += resid;
- fft(d_residbuf, d_fftsize);
-
- d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize,
- NULL, 0, (float*)d_residbuf, d_fftsize,
- currentTime, true);
- d_update_active = false;
- }
- // Otherwise, copy what we received into the residbuf for next time
- else {
- memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*datasize);
- d_index += datasize;
- j += datasize;
- }
- }
-
- consume_each(j);
- return j;
-}
diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc
deleted file mode 100644
index a02f89d0ac..0000000000
--- a/gr-qtgui/lib/qtgui_sink_f.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,2010,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <qtgui_sink_f.h>
-#include <gr_io_signature.h>
-#include <string.h>
-
-#include <QTimer>
-
-qtgui_sink_f_sptr
-qtgui_make_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent)
-{
- return gnuradio::get_initial_sptr(new qtgui_sink_f (fftsize, wintype,
- fc, bw, name,
- plotfreq, plotwaterfall,
- plottime, plotconst,
- parent));
-}
-
-qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent)
- : gr_block ("sink_f",
- gr_make_io_signature (1, 1, sizeof(float)),
- gr_make_io_signature (0, 0, 0)),
- d_fftsize(fftsize),
- d_wintype((gr_firdes::win_type)(wintype)),
- d_center_freq(fc), d_bandwidth(bw), d_name(name),
- d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall),
- d_plottime(plottime), d_plotconst(plotconst),
- d_parent(parent)
-{
- d_main_gui = NULL;
-
- // Perform fftshift operation;
- // this is usually desired when plotting
- d_shift = true;
-
- d_fft = new gri_fft_complex (d_fftsize, true);
-
- d_index = 0;
- d_residbuf = new float[d_fftsize];
-
- buildwindow();
-
- initialize();
-}
-
-qtgui_sink_f::~qtgui_sink_f()
-{
- delete d_main_gui;
- delete [] d_residbuf;
- delete d_fft;
-}
-
-void
-qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required)
-{
- unsigned int ninputs = ninput_items_required.size();
- for (unsigned int i = 0; i < ninputs; i++) {
- ninput_items_required[i] = std::min(d_fftsize, 8191);
- }
-}
-
-void
-qtgui_sink_f::initialize()
-{
- if(qApp != NULL) {
- d_qApplication = qApp;
- }
- else {
- int argc;
- char **argv = NULL;
- d_qApplication = new QApplication(argc, argv);
- }
-
-
- uint64_t maxBufferSize = 32768;
- d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize,
- d_center_freq,
- -d_bandwidth/2.0,
- d_bandwidth/2.0);
- d_main_gui->SetDisplayTitle(d_name);
- d_main_gui->SetFFTSize(d_fftsize);
- d_main_gui->SetWindowType((int)d_wintype);
-
- d_main_gui->OpenSpectrumWindow(d_parent,
- d_plotfreq, d_plotwaterfall,
- d_plottime, d_plotconst);
-
- // initialize update time to 10 times a second
- set_update_time(0.1);
-}
-
-void
-qtgui_sink_f::exec_()
-{
- d_qApplication->exec();
-}
-
-QWidget*
-qtgui_sink_f::qwidget()
-{
- return d_main_gui->qwidget();
-}
-
-PyObject*
-qtgui_sink_f::pyqwidget()
-{
- PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget());
- PyObject *retarg = Py_BuildValue("N", w);
- return retarg;
-}
-
-void
-qtgui_sink_f::set_frequency_range(const double centerfreq,
- const double bandwidth)
-{
- d_center_freq = centerfreq;
- d_bandwidth = bandwidth;
- d_main_gui->SetFrequencyRange(d_center_freq,
- -d_bandwidth/2.0,
- d_bandwidth/2.0);
-}
-
-void
-qtgui_sink_f::set_time_domain_axis(double min, double max)
-{
- d_main_gui->SetTimeDomainAxis(min, max);
-}
-
-void
-qtgui_sink_f::set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax)
-{
- d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax);
-}
-
-void
-qtgui_sink_f::set_constellation_pen_size(int size)
-{
- d_main_gui->SetConstellationPenSize(size);
-}
-
-
-void
-qtgui_sink_f::set_frequency_axis(double min, double max)
-{
- d_main_gui->SetFrequencyAxis(min, max);
-}
-
-void
-qtgui_sink_f::set_update_time(double t)
-{
- d_update_time = t;
- d_main_gui->SetUpdateTime(d_update_time);
-}
-
-void
-qtgui_sink_f::fft(const float *data_in, int size)
-{
- if (d_window.size()) {
- gr_complex *dst = d_fft->get_inbuf();
- for (int i = 0; i < size; i++) // apply window
- dst[i] = data_in[i] * d_window[i];
- }
- else {
- gr_complex *dst = d_fft->get_inbuf();
- for (int i = 0; i < size; i++) // float to complex conversion
- dst[i] = data_in[i];
- }
-
- d_fft->execute (); // compute the fft
-}
-
-void
-qtgui_sink_f::windowreset()
-{
- gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType();
- if(d_wintype != newwintype) {
- d_wintype = newwintype;
- buildwindow();
- }
-}
-
-void
-qtgui_sink_f::buildwindow()
-{
- d_window.clear();
- if(d_wintype != 0) {
- d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76);
- }
-}
-
-void
-qtgui_sink_f::fftresize()
-{
- int newfftsize = d_main_gui->GetFFTSize();
-
- if(newfftsize != d_fftsize) {
-
- // Resize residbuf and replace data
- delete [] d_residbuf;
- d_residbuf = new float[newfftsize];
-
- // Set new fft size and reset buffer index
- // (throws away any currently held data, but who cares?)
- d_fftsize = newfftsize;
- d_index = 0;
-
- // Reset window to reflect new size
- buildwindow();
-
- // Reset FFTW plan for new size
- delete d_fft;
- d_fft = new gri_fft_complex (d_fftsize, true);
- }
-}
-
-
-int
-qtgui_sink_f::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- int j=0;
- const float *in = (const float*)input_items[0];
-
- // Update the FFT size from the application
- fftresize();
- windowreset();
-
- for(int i=0; i < noutput_items; i+=d_fftsize) {
- unsigned int datasize = noutput_items - i;
- unsigned int resid = d_fftsize-d_index;
-
- // If we have enough input for one full FFT, do it
- if(datasize >= resid) {
- const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now();
-
- // Fill up residbuf with d_fftsize number of items
- memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid);
- d_index = 0;
-
- j += resid;
- fft(d_residbuf, d_fftsize);
-
- d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize,
- (float*)d_residbuf, d_fftsize, NULL, 0,
- currentTime, true);
- }
- // Otherwise, copy what we received into the residbuf for next time
- else {
- memcpy(d_residbuf+d_index, &in[j], sizeof(float)*datasize);
- d_index += datasize;
- j += datasize;
- }
- }
-
- consume_each(j);
- return j;
-}
diff --git a/gr-qtgui/lib/qtgui_time_sink_c.cc b/gr-qtgui/lib/qtgui_time_sink_c.cc
deleted file mode 100644
index 574fd93ad6..0000000000
--- a/gr-qtgui/lib/qtgui_time_sink_c.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <qtgui_time_sink_c.h>
-#include <gr_io_signature.h>
-#include <string.h>
-
-#include <QTimer>
-
-qtgui_time_sink_c_sptr
-qtgui_make_time_sink_c (int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent)
-{
- return gnuradio::get_initial_sptr(new qtgui_time_sink_c (size, bw, name,
- nconnections, parent));
-}
-
-qtgui_time_sink_c::qtgui_time_sink_c (int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent)
- : gr_sync_block ("time_sink_c",
- gr_make_io_signature (nconnections, nconnections, sizeof(gr_complex)),
- gr_make_io_signature (0, 0, 0)),
- d_size(size), d_bandwidth(bw), d_name(name),
- d_nconnections(2*nconnections), d_parent(parent)
-{
- d_main_gui = NULL;
-
- d_index = 0;
-
- for(int i = 0; i < d_nconnections; i++) {
- d_residbufs.push_back(new double[d_size]);
- }
-
- initialize();
- set_output_multiple(d_size);
-}
-
-qtgui_time_sink_c::~qtgui_time_sink_c()
-{
- // d_main_gui is a qwidget destroyed with its parent
- for(int i = 0; i < d_nconnections; i++) {
- delete [] d_residbufs[i];
- }
-}
-
-void
-qtgui_time_sink_c::initialize()
-{
- if(qApp != NULL) {
- d_qApplication = qApp;
- }
- else {
- int argc=0;
- char **argv = NULL;
- d_qApplication = new QApplication(argc, argv);
- }
-
- d_main_gui = new TimeDisplayForm(d_nconnections, d_parent);
-
- // initialize update time to 10 times a second
- set_update_time(0.1);
- d_last_time = 0;
-}
-
-
-void
-qtgui_time_sink_c::exec_()
-{
- d_qApplication->exec();
-}
-
-QWidget*
-qtgui_time_sink_c::qwidget()
-{
- return d_main_gui;
-}
-
-PyObject*
-qtgui_time_sink_c::pyqwidget()
-{
- PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
- PyObject *retarg = Py_BuildValue("N", w);
- return retarg;
-}
-
-void
-qtgui_time_sink_c::set_time_domain_axis(double min, double max)
-{
- d_main_gui->setTimeDomainAxis(min, max);
-}
-
-void
-qtgui_time_sink_c::set_update_time(double t)
-{
- d_update_time = t;
- d_main_gui->setUpdateTime(d_update_time);
-}
-
-void
-qtgui_time_sink_c::set_title(int which, const std::string &title)
-{
- d_main_gui->setTitle(which, title.c_str());
-}
-
-void
-qtgui_time_sink_c::set_color(int which, const std::string &color)
-{
- d_main_gui->setColor(which, color.c_str());
-}
-
-int
-qtgui_time_sink_c::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- int n=0, j=0, idx=0;
- const gr_complex *in = (const gr_complex*)input_items[idx];
-
- for(int i=0; i < noutput_items; i+=d_size) {
- unsigned int datasize = noutput_items - i;
- unsigned int resid = d_size-d_index;
- idx = 0;
-
- // If we have enough input for one full plot, do it
- if(datasize >= resid) {
- d_current_time = gruel::high_res_timer_now();
-
- // Fill up residbufs with d_size number of items
- for(n = 0; n < d_nconnections; n+=2) {
- in = (const gr_complex*)input_items[idx++];
- for(unsigned int k = 0; k < resid; k++) {
- d_residbufs[n][d_index+k] = in[j+k].real();
- d_residbufs[n+1][d_index+k] = in[j+k].imag();
- }
- }
-
- // Update the plot if its time
- if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
- d_last_time = d_current_time;
- d_qApplication->postEvent(d_main_gui,
- new TimeUpdateEvent(d_residbufs, d_size));
- }
-
- d_index = 0;
- j += resid;
- }
- // Otherwise, copy what we received into the residbufs for next time
- // because we set the output_multiple, this should never need to be called
- else {
- assert(0);
- for(n = 0; n < d_nconnections; n+=2) {
- in = (const gr_complex*)input_items[idx++];
- for(unsigned int k = 0; k < resid; k++) {
- d_residbufs[n][d_index+k] = in[j+k].real();
- d_residbufs[n+1][d_index+k] = in[j+k].imag();
- }
- }
- d_index += datasize;
- j += datasize;
- }
- }
-
- return noutput_items;
-}
diff --git a/gr-qtgui/lib/qtgui_time_sink_f.cc b/gr-qtgui/lib/qtgui_time_sink_f.cc
deleted file mode 100644
index 09fdf0a92e..0000000000
--- a/gr-qtgui/lib/qtgui_time_sink_f.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <qtgui_time_sink_f.h>
-#include <gr_io_signature.h>
-#include <string.h>
-
-#include <QTimer>
-
-qtgui_time_sink_f_sptr
-qtgui_make_time_sink_f (int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent)
-{
- return gnuradio::get_initial_sptr(new qtgui_time_sink_f (size, bw, name,
- nconnections, parent));
-}
-
-qtgui_time_sink_f::qtgui_time_sink_f (int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent)
- : gr_sync_block ("time_sink_f",
- gr_make_io_signature (nconnections, nconnections, sizeof(float)),
- gr_make_io_signature (0, 0, 0)),
- d_size(size), d_bandwidth(bw), d_name(name),
- d_nconnections(nconnections), d_parent(parent)
-{
- d_main_gui = NULL;
-
- d_index = 0;
-
- for(int i = 0; i < d_nconnections; i++) {
- d_residbufs.push_back(new double[d_size]);
- }
-
- initialize();
- set_output_multiple(d_size);
-}
-
-qtgui_time_sink_f::~qtgui_time_sink_f()
-{
- // d_main_gui is a qwidget destroyed with its parent
- for(int i = 0; i < d_nconnections; i++) {
- delete [] d_residbufs[i];
- }
-}
-
-void
-qtgui_time_sink_f::initialize()
-{
- if(qApp != NULL) {
- d_qApplication = qApp;
- }
- else {
- int argc=0;
- char **argv = NULL;
- d_qApplication = new QApplication(argc, argv);
- }
-
- d_main_gui = new TimeDisplayForm(d_nconnections, d_parent);
-
- // initialize update time to 10 times a second
- set_update_time(0.1);
- d_last_time = 0;
-}
-
-
-void
-qtgui_time_sink_f::exec_()
-{
- d_qApplication->exec();
-}
-
-QWidget*
-qtgui_time_sink_f::qwidget()
-{
- return d_main_gui;
-}
-
-PyObject*
-qtgui_time_sink_f::pyqwidget()
-{
- PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
- PyObject *retarg = Py_BuildValue("N", w);
- return retarg;
-}
-
-void
-qtgui_time_sink_f::set_time_domain_axis(double min, double max)
-{
- d_main_gui->setTimeDomainAxis(min, max);
-}
-
-void
-qtgui_time_sink_f::set_update_time(double t)
-{
- d_update_time = t;
- d_main_gui->setUpdateTime(d_update_time);
-}
-
-void
-qtgui_time_sink_f::set_title(int which, const std::string &title)
-{
- d_main_gui->setTitle(which, title.c_str());
-}
-
-void
-qtgui_time_sink_f::set_color(int which, const std::string &color)
-{
- d_main_gui->setColor(which, color.c_str());
-}
-
-int
-qtgui_time_sink_f::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- int n=0, j=0, idx=0;
- const float *in = (const float*)input_items[idx];
-
- for(int i=0; i < noutput_items; i+=d_size) {
- unsigned int datasize = noutput_items - i;
- unsigned int resid = d_size-d_index;
- idx = 0;
-
- // If we have enough input for one full plot, do it
- if(datasize >= resid) {
- d_current_time = gruel::high_res_timer_now();
-
- // Fill up residbufs with d_size number of items
- for(n = 0; n < d_nconnections; n++) {
- in = (const float*)input_items[idx++];
- for(unsigned int k = 0; k < resid; k++) {
- d_residbufs[n][d_index+k] = in[j+k];
- }
- }
-
- // Update the plot if its time
- if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
- d_last_time = d_current_time;
- d_qApplication->postEvent(d_main_gui,
- new TimeUpdateEvent(d_residbufs, d_size));
- }
-
- d_index = 0;
- j += resid;
- }
- // Otherwise, copy what we received into the residbufs for next time
- // because we set the output_multiple, this should never need to be called
- else {
- assert(0);
- for(n = 0; n < d_nconnections; n++) {
- in = (const float*)input_items[idx++];
- for(unsigned int k = 0; k < resid; k++) {
- d_residbufs[n][d_index+k] = in[j+k];
- }
- }
- d_index += datasize;
- j += datasize;
- }
- }
-
- return noutput_items;
-}
diff --git a/gr-qtgui/lib/qtgui_types.h b/gr-qtgui/lib/qtgui_types.h
new file mode 100644
index 0000000000..fd5dd6295f
--- /dev/null
+++ b/gr-qtgui/lib/qtgui_types.h
@@ -0,0 +1,196 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef QTGUI_TYPES_H
+#define QTGUI_TYPES_H
+
+#include <qwt_color_map.h>
+#include <qwt_scale_draw.h>
+#include <gruel/high_res_timer.h>
+
+class FreqOffsetAndPrecisionClass
+{
+public:
+ FreqOffsetAndPrecisionClass(const int freqPrecision)
+ {
+ _frequencyPrecision = freqPrecision;
+ _centerFrequency = 0;
+ }
+
+ virtual ~FreqOffsetAndPrecisionClass()
+ {
+ }
+
+ virtual unsigned int GetFrequencyPrecision() const
+ {
+ return _frequencyPrecision;
+ }
+
+ virtual void SetFrequencyPrecision(const unsigned int newPrecision)
+ {
+ _frequencyPrecision = newPrecision;
+ }
+
+ virtual double GetCenterFrequency() const
+ {
+ return _centerFrequency;
+ }
+
+ virtual void SetCenterFrequency(const double newFreq)
+ {
+ _centerFrequency = newFreq;
+ }
+
+protected:
+
+private:
+ unsigned int _frequencyPrecision;
+ double _centerFrequency;
+};
+
+class TimeScaleData
+{
+public:
+ TimeScaleData()
+ {
+ _zeroTime = 0;
+ _secondsPerLine = 1.0;
+ }
+
+ virtual ~TimeScaleData()
+ {
+ }
+
+ virtual gruel::high_res_timer_type GetZeroTime() const
+ {
+ return _zeroTime;
+ }
+
+ virtual void SetZeroTime(const gruel::high_res_timer_type newTime)
+ {
+ _zeroTime = newTime - gruel::high_res_timer_epoch();
+ }
+
+ virtual void SetSecondsPerLine(const double newTime)
+ {
+ _secondsPerLine = newTime;
+ }
+
+ virtual double GetSecondsPerLine() const
+ {
+ return _secondsPerLine;
+ }
+
+
+protected:
+
+private:
+ gruel::high_res_timer_type _zeroTime;
+ double _secondsPerLine;
+
+};
+
+/***********************************************************************
+ * Text scale widget to provide X (freq) axis text
+ **********************************************************************/
+class FreqDisplayScaleDraw: public QwtScaleDraw, FreqOffsetAndPrecisionClass
+{
+public:
+ FreqDisplayScaleDraw(const unsigned int precision)
+ : QwtScaleDraw(), FreqOffsetAndPrecisionClass(precision)
+ {
+ }
+
+ virtual QwtText label(double value) const
+ {
+ return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision());
+ }
+
+ virtual void initiateUpdate(void)
+ {
+ invalidateCache();
+ }
+
+protected:
+
+private:
+
+};
+
+enum{
+ INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR = 0,
+ INTENSITY_COLOR_MAP_TYPE_WHITE_HOT = 1,
+ INTENSITY_COLOR_MAP_TYPE_BLACK_HOT = 2,
+ INTENSITY_COLOR_MAP_TYPE_INCANDESCENT = 3,
+ INTENSITY_COLOR_MAP_TYPE_USER_DEFINED = 4
+};
+
+class ColorMap_MultiColor: public QwtLinearColorMap
+{
+public:
+ ColorMap_MultiColor():
+ QwtLinearColorMap(Qt::darkCyan, Qt::white)
+ {
+ addColorStop(0.25, Qt::cyan);
+ addColorStop(0.5, Qt::yellow);
+ addColorStop(0.75, Qt::red);
+ }
+};
+
+class ColorMap_WhiteHot: public QwtLinearColorMap
+{
+public:
+ ColorMap_WhiteHot():
+ QwtLinearColorMap(Qt::black, Qt::white)
+ {
+ }
+};
+
+class ColorMap_BlackHot: public QwtLinearColorMap
+{
+public:
+ ColorMap_BlackHot():
+ QwtLinearColorMap(Qt::white, Qt::black)
+ {
+ }
+};
+
+class ColorMap_Incandescent: public QwtLinearColorMap
+{
+public:
+ ColorMap_Incandescent():
+ QwtLinearColorMap(Qt::black, Qt::white)
+ {
+ addColorStop(0.5, Qt::darkRed);
+ }
+};
+
+class ColorMap_UserDefined: public QwtLinearColorMap
+{
+public:
+ ColorMap_UserDefined(QColor low, QColor high):
+ QwtLinearColorMap(low, high)
+ {
+ }
+};
+
+#endif //QTGUI_TYPES_H
diff --git a/gr-qtgui/lib/qtgui_util.cc b/gr-qtgui/lib/qtgui_util.cc
index 543ce1b1c7..70dcb483fb 100644
--- a/gr-qtgui/lib/qtgui_util.cc
+++ b/gr-qtgui/lib/qtgui_util.cc
@@ -20,53 +20,32 @@
* Boston, MA 02110-1301, USA.
*/
-#include <qtgui_util.h>
+#include <qtgui/utils.h>
+#include <QDebug>
-#if QWT_VERSION < 0x060000
QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine()
+#if QWT_VERSION < 0x060000
: QwtPickerMachine ()
-{
-}
#else
-QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine()
: QwtPickerMachine (PointSelection)
+#endif
{
}
-#endif
QwtPickerDblClickPointMachine::~QwtPickerDblClickPointMachine()
{
-
}
#if QWT_VERSION < 0x060000
-QwtPickerMachine::CommandList
-QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern,
- const QEvent *e)
-{
- QwtPickerMachine::CommandList cmdList;
- switch(e->type()) {
- case QEvent::MouseButtonDblClick:
- if ( eventPattern.mouseMatch(QwtEventPattern::MouseSelect1,
- (const QMouseEvent *)e) ) {
- cmdList += QwtPickerMachine::Begin;
- cmdList += QwtPickerMachine::Append;
- cmdList += QwtPickerMachine::End;
- }
- break;
- default:
- break;
- }
- return cmdList;
-}
-
+#define CMDLIST_TYPE QwtPickerMachine::CommandList
#else
-
-QList<QwtPickerMachine::Command>
+#define CMDLIST_TYPE QList<QwtPickerMachine::Command>
+#endif
+CMDLIST_TYPE
QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern,
const QEvent *e)
{
- QList<QwtPickerMachine::Command> cmdList;
+ CMDLIST_TYPE cmdList;
switch(e->type()) {
case QEvent::MouseButtonDblClick:
if ( eventPattern.mouseMatch(QwtEventPattern::MouseSelect1,
@@ -81,7 +60,6 @@ QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern,
}
return cmdList;
}
-#endif
QwtDblClickPlotPicker::QwtDblClickPlotPicker(QwtPlotCanvas* canvas)
: QwtPlotPicker(canvas)
diff --git a/gr-qtgui/lib/sink_c_impl.cc b/gr-qtgui/lib/sink_c_impl.cc
new file mode 100644
index 0000000000..29f56a5f39
--- /dev/null
+++ b/gr-qtgui/lib/sink_c_impl.cc
@@ -0,0 +1,335 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008-2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ sink_c::sptr
+ sink_c::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new sink_c_impl(fftsize, wintype,
+ fc, bw, name,
+ plotfreq, plotwaterfall,
+ plottime, plotconst,
+ parent));
+ }
+
+ sink_c_impl::sink_c_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent)
+ : gr_block("sink_c",
+ gr_make_io_signature(1, -1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_fftsize(fftsize),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall),
+ d_plottime(plottime), d_plotconst(plotconst),
+ d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex (d_fftsize, true);
+
+ d_index = 0;
+ d_residbuf = new gr_complex[d_fftsize];
+ d_magbuf = new float[d_fftsize];
+
+ buildwindow();
+
+ initialize();
+ }
+
+ sink_c_impl::~sink_c_impl()
+ {
+ delete d_main_gui;
+ delete [] d_residbuf;
+ delete [] d_magbuf;
+ delete d_fft;
+ }
+
+ void
+ sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for(unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ sink_c_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ if(d_center_freq < 0) {
+ throw std::runtime_error("sink_c_impl: Received bad center frequency.\n");
+ }
+
+ uint64_t maxBufferSize = 32768;
+ d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize,
+ d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+
+ d_main_gui->SetDisplayTitle(d_name);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetWindowType((int)d_wintype);
+
+ d_main_gui->OpenSpectrumWindow(d_parent,
+ d_plotfreq, d_plotwaterfall,
+ d_plottime, d_plotconst);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.5);
+
+ d_last_update = gruel::high_res_timer_now();
+ d_update_active = false;
+ }
+
+ void
+ sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ sink_c_impl::qwidget()
+ {
+ return d_main_gui->qwidget();
+ }
+
+ PyObject*
+ sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget());
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ sink_c_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ sink_c_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ sink_c_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ sink_c_impl::set_fft_power_db(double min, double max)
+ {
+ d_main_gui->SetFrequencyAxis(min, max);
+ }
+
+ /*
+ void
+ sink_c_impl::set_time_domain_axis(double min, double max)
+ {
+ d_main_gui->SetTimeDomainAxis(min, max);
+ }
+
+ void
+ sink_c_impl::set_constellation_axis(double xmin, double xmax,
+ double ymin, double ymax)
+ {
+ d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax);
+ }
+
+ void
+ sink_c_impl::set_constellation_pen_size(int size)
+ {
+ d_main_gui->SetConstellationPenSize(size);
+ }
+ */
+
+ void
+ sink_c_impl::set_update_time(double t)
+ {
+ d_update_time = t * gruel::high_res_timer_tps();
+ d_main_gui->SetUpdateTime(t);
+ }
+
+ void
+ sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size)
+ {
+ if (d_window.size()) {
+ volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in,
+ &d_window.front(), size);
+ }
+ else {
+ memcpy (d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size);
+ }
+
+ d_fft->execute (); // compute the fft
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+}
+
+ void
+ sink_c_impl::windowreset()
+ {
+ filter::firdes::win_type newwintype;
+ newwintype = (filter::firdes::win_type)d_main_gui->GetWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ sink_c_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != 0) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ sink_c_impl::fftresize()
+ {
+ int newfftsize = d_main_gui->GetFFTSize();
+
+ if(newfftsize != d_fftsize) {
+
+ // Resize residbuf and replace data
+ delete [] d_residbuf;
+ d_residbuf = new gr_complex[newfftsize];
+
+ delete [] d_magbuf;
+ d_magbuf = new float[newfftsize];
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex (d_fftsize, true);
+ }
+ }
+
+ int
+ sink_c_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ if (!d_update_active && (gruel::high_res_timer_now() - d_last_update) < d_update_time) {
+ consume_each(noutput_items);
+ return noutput_items;
+ }
+ else {
+ d_last_update = gruel::high_res_timer_now();
+ d_update_active = true;
+ }
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+ const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now();
+
+ // Fill up residbuf with d_fftsize number of items
+ memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid);
+ d_index = 0;
+
+ j += resid;
+ fft(d_magbuf, d_residbuf, d_fftsize);
+
+ d_main_gui->UpdateWindow(true, d_magbuf, d_fftsize,
+ NULL, 0, (float*)d_residbuf, d_fftsize,
+ currentTime, true);
+ d_update_active = false;
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*datasize);
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ consume_each(j);
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/sink_c_impl.h b/gr-qtgui/lib/sink_c_impl.h
new file mode 100644
index 0000000000..b201bcd5a2
--- /dev/null
+++ b/gr-qtgui/lib/sink_c_impl.h
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_SINK_C_IMPL_H
+
+#include <qtgui/sink_c.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <SpectrumGUIClass.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API sink_c_impl : public sink_c
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ int d_fftsize;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+ gruel::high_res_timer_type d_last_update;
+ bool d_update_active;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ gr_complex *d_residbuf;
+ float *d_magbuf;
+
+ bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst;
+
+ gruel::high_res_timer_type d_update_time;
+
+ QWidget *d_parent;
+ SpectrumGUIClass *d_main_gui;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const gr_complex *data_in, int size);
+
+ public:
+ sink_c_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent);
+ ~sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+
+ void set_frequency_range(const double centerfreq,
+ const double bandwidth);
+ void set_fft_power_db(double min, double max);
+
+ //void set_time_domain_axis(double min, double max);
+ //void set_constellation_axis(double xmin, double xmax,
+ // double ymin, double ymax);
+ //void set_constellation_pen_size(int size);
+
+ void set_update_time(double t);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/sink_f_impl.cc b/gr-qtgui/lib/sink_f_impl.cc
new file mode 100644
index 0000000000..580c774c0b
--- /dev/null
+++ b/gr-qtgui/lib/sink_f_impl.cc
@@ -0,0 +1,320 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008-2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ sink_f::sptr
+ sink_f::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new sink_f_impl(fftsize, wintype,
+ fc, bw, name,
+ plotfreq, plotwaterfall,
+ plottime, plotconst,
+ parent));
+ }
+
+ sink_f_impl::sink_f_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent)
+ : gr_block("sink_f",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature (0, 0, 0)),
+ d_fftsize(fftsize),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall),
+ d_plottime(plottime), d_plotconst(plotconst),
+ d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex (d_fftsize, true);
+
+ d_index = 0;
+ d_residbuf = new float[d_fftsize];
+ d_magbuf = new float[d_fftsize];
+
+ buildwindow();
+
+ initialize();
+ }
+
+ sink_f_impl::~sink_f_impl()
+ {
+ delete d_main_gui;
+ delete [] d_residbuf;
+ delete [] d_magbuf;
+ delete d_fft;
+ }
+
+ void
+ sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ sink_f_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ uint64_t maxBufferSize = 32768;
+ d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize,
+ d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ d_main_gui->SetDisplayTitle(d_name);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetWindowType((int)d_wintype);
+
+ d_main_gui->OpenSpectrumWindow(d_parent,
+ d_plotfreq, d_plotwaterfall,
+ d_plottime, d_plotconst);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ void
+ sink_f_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ sink_f_impl::qwidget()
+ {
+ return d_main_gui->qwidget();
+ }
+
+ PyObject*
+ sink_f_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget());
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ sink_f_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ sink_f_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ sink_f_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ sink_f_impl::set_fft_power_db(double min, double max)
+ {
+ d_main_gui->SetFrequencyAxis(min, max);
+ }
+
+ /*
+ void
+ sink_f_impl::set_time_domain_axis(double min, double max)
+ {
+ d_main_gui->SetTimeDomainAxis(min, max);
+ }
+
+ void
+ sink_f_impl::set_constellation_axis(double xmin, double xmax,
+ double ymin, double ymax)
+ {
+ d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax);
+ }
+
+ void
+ sink_f_impl::set_constellation_pen_size(int size)
+ {
+ d_main_gui->SetConstellationPenSize(size);
+ }
+ */
+
+ void
+ sink_f_impl::set_update_time(double t)
+ {
+ d_update_time = t;
+ d_main_gui->SetUpdateTime(d_update_time);
+ }
+
+ void
+ sink_f_impl::fft(float *data_out, const float *data_in, int size)
+ {
+ if (d_window.size()) {
+ gr_complex *dst = d_fft->get_inbuf();
+ for (int i = 0; i < size; i++) // apply window
+ dst[i] = data_in[i] * d_window[i];
+ }
+ else {
+ gr_complex *dst = d_fft->get_inbuf();
+ for (int i = 0; i < size; i++) // float to complex conversion
+ dst[i] = data_in[i];
+ }
+
+ d_fft->execute (); // compute the fft
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+ }
+
+ void
+ sink_f_impl::windowreset()
+ {
+ filter::firdes::win_type newwintype;
+ newwintype = (filter::firdes::win_type)d_main_gui->GetWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ sink_f_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != 0) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ sink_f_impl::fftresize()
+ {
+ int newfftsize = d_main_gui->GetFFTSize();
+
+ if(newfftsize != d_fftsize) {
+
+ // Resize residbuf and replace data
+ delete [] d_residbuf;
+ d_residbuf = new float[newfftsize];
+
+ delete [] d_magbuf;
+ d_magbuf = new float[newfftsize];
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex (d_fftsize, true);
+ }
+ }
+
+ int
+ sink_f_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const float *in = (const float*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+ const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now();
+
+ // Fill up residbuf with d_fftsize number of items
+ memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid);
+ d_index = 0;
+
+ j += resid;
+ fft(d_magbuf, d_residbuf, d_fftsize);
+
+ d_main_gui->UpdateWindow(true, d_magbuf, d_fftsize,
+ (float*)d_residbuf, d_fftsize, NULL, 0,
+ currentTime, true);
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ memcpy(d_residbuf+d_index, &in[j], sizeof(float)*datasize);
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ consume_each(j);
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/sink_f_impl.h b/gr-qtgui/lib/sink_f_impl.h
new file mode 100644
index 0000000000..93dc46e85f
--- /dev/null
+++ b/gr-qtgui/lib/sink_f_impl.h
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_SINK_F_IMPL_H
+#define INCLUDED_QTGUI_SINK_F_IMPL_H
+
+#include <qtgui/sink_f.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <SpectrumGUIClass.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API sink_f_impl : public sink_f
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ int d_fftsize;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ float *d_residbuf;
+ float *d_magbuf;
+
+ bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst;
+
+ double d_update_time;
+
+ QWidget *d_parent;
+ SpectrumGUIClass *d_main_gui;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const float *data_in, int size);
+
+ public:
+ sink_f_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ bool plotfreq, bool plotwaterfall,
+ bool plottime, bool plotconst,
+ QWidget *parent);
+ ~sink_f_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+
+ void set_frequency_range(const double centerfreq,
+ const double bandwidth);
+ void set_fft_power_db(double min, double max);
+
+ //void set_time_domain_axis(double min, double max);
+ //void set_constellation_axis(double xmin, double xmax,
+ // double ymin, double ymax);
+ //void set_constellation_pen_size(int size);
+
+ void set_update_time(double t);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_SINK_F_IMPL_H */
diff --git a/gr-qtgui/lib/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc
index bec39747b8..92dd807147 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.cc
+++ b/gr-qtgui/lib/spectrumUpdateEvents.cc
@@ -3,7 +3,7 @@
#include <spectrumUpdateEvents.h>
-SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints,
+SpectrumUpdateEvent::SpectrumUpdateEvent(const float* fftPoints,
const uint64_t numFFTDataPoints,
const double* realTimeDomainPoints,
const double* imagTimeDomainPoints,
@@ -13,7 +13,7 @@ SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints,
const bool lastOfMultipleUpdateFlag,
const gruel::high_res_timer_type generatedTimestamp,
const int droppedFFTFrames)
- : QEvent(QEvent::Type(10005))
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
{
if(numFFTDataPoints < 1) {
_numFFTDataPoints = 1;
@@ -29,9 +29,9 @@ SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints,
_numTimeDomainDataPoints = numTimeDomainDataPoints;
}
- _fftPoints = new std::complex<float>[_numFFTDataPoints];
- _fftPoints[0] = std::complex<float>(0,0);
- memcpy(_fftPoints, fftPoints, numFFTDataPoints*sizeof(std::complex<float>));
+ _fftPoints = new float[_numFFTDataPoints];
+ _fftPoints[0] = 0;
+ memcpy(_fftPoints, fftPoints, numFFTDataPoints*sizeof(float));
_realDataTimeDomainPoints = new double[_numTimeDomainDataPoints];
memset(_realDataTimeDomainPoints, 0x0, _numTimeDomainDataPoints*sizeof(double));
@@ -60,7 +60,7 @@ SpectrumUpdateEvent::~SpectrumUpdateEvent()
delete[] _imagDataTimeDomainPoints;
}
-const std::complex<float>*
+const float*
SpectrumUpdateEvent::getFFTPoints() const
{
return _fftPoints;
@@ -121,7 +121,7 @@ SpectrumUpdateEvent::getDroppedFFTFrames() const
}
SpectrumWindowCaptionEvent::SpectrumWindowCaptionEvent(const QString& newLbl)
- : QEvent(QEvent::Type(10008))
+ : QEvent(QEvent::Type(SpectrumWindowCaptionEventType))
{
_labelString = newLbl;
}
@@ -137,7 +137,7 @@ SpectrumWindowCaptionEvent::getLabel()
}
SpectrumWindowResetEvent::SpectrumWindowResetEvent()
- : QEvent(QEvent::Type(10009))
+ : QEvent(QEvent::Type(SpectrumWindowResetEventType))
{
}
@@ -148,7 +148,7 @@ SpectrumWindowResetEvent::~SpectrumWindowResetEvent()
SpectrumFrequencyRangeEvent::SpectrumFrequencyRangeEvent(const double centerFreq,
const double startFreq,
const double stopFreq)
- : QEvent(QEvent::Type(10010))
+ : QEvent(QEvent::Type(SpectrumFrequencyRangeEventType))
{
_centerFrequency = centerFreq;
_startFrequency = startFreq;
@@ -179,10 +179,11 @@ SpectrumFrequencyRangeEvent::GetStopFrequency() const
/***************************************************************************/
-#include <iostream>
+
+
TimeUpdateEvent::TimeUpdateEvent(const std::vector<double*> timeDomainPoints,
const uint64_t numTimeDomainDataPoints)
- : QEvent(QEvent::Type(10005))
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
{
if(numTimeDomainDataPoints < 1) {
_numTimeDomainDataPoints = 1;
@@ -220,4 +221,156 @@ TimeUpdateEvent::getNumTimeDomainDataPoints() const
return _numTimeDomainDataPoints;
}
+
+/***************************************************************************/
+
+
+FreqUpdateEvent::FreqUpdateEvent(const std::vector<double*> dataPoints,
+ const uint64_t numDataPoints)
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
+{
+ if(numDataPoints < 1) {
+ _numDataPoints = 1;
+ }
+ else {
+ _numDataPoints = numDataPoints;
+ }
+
+ _nplots = dataPoints.size();
+ for(size_t i = 0; i < _nplots; i++) {
+ _dataPoints.push_back(new double[_numDataPoints]);
+ if(numDataPoints > 0) {
+ memcpy(_dataPoints[i], dataPoints[i],
+ _numDataPoints*sizeof(double));
+ }
+ }
+}
+
+FreqUpdateEvent::~FreqUpdateEvent()
+{
+ for(size_t i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ }
+}
+
+const std::vector<double*>
+FreqUpdateEvent::getPoints() const
+{
+ return _dataPoints;
+}
+
+uint64_t
+FreqUpdateEvent::getNumDataPoints() const
+{
+ return _numDataPoints;
+}
+
+
+/***************************************************************************/
+
+
+ConstUpdateEvent::ConstUpdateEvent(const std::vector<double*> realDataPoints,
+ const std::vector<double*> imagDataPoints,
+ const uint64_t numDataPoints)
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
+{
+ if(numDataPoints < 1) {
+ _numDataPoints = 1;
+ }
+ else {
+ _numDataPoints = numDataPoints;
+ }
+
+ _nplots = realDataPoints.size();
+ for(size_t i = 0; i < _nplots; i++) {
+ _realDataPoints.push_back(new double[_numDataPoints]);
+ _imagDataPoints.push_back(new double[_numDataPoints]);
+ if(numDataPoints > 0) {
+ memcpy(_realDataPoints[i], realDataPoints[i],
+ _numDataPoints*sizeof(double));
+ memcpy(_imagDataPoints[i], imagDataPoints[i],
+ _numDataPoints*sizeof(double));
+ }
+ }
+}
+
+ConstUpdateEvent::~ConstUpdateEvent()
+{
+ for(size_t i = 0; i < _nplots; i++) {
+ delete[] _realDataPoints[i];
+ delete[] _imagDataPoints[i];
+ }
+}
+
+const std::vector<double*>
+ConstUpdateEvent::getRealPoints() const
+{
+ return _realDataPoints;
+}
+
+const std::vector<double*>
+ConstUpdateEvent::getImagPoints() const
+{
+ return _imagDataPoints;
+}
+
+uint64_t
+ConstUpdateEvent::getNumDataPoints() const
+{
+ return _numDataPoints;
+}
+
+
+/***************************************************************************/
+
+
+WaterfallUpdateEvent::WaterfallUpdateEvent(const std::vector<double*> dataPoints,
+ const uint64_t numDataPoints,
+ const gruel::high_res_timer_type dataTimestamp)
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
+{
+ if(numDataPoints < 1) {
+ _numDataPoints = 1;
+ }
+ else {
+ _numDataPoints = numDataPoints;
+ }
+
+ _nplots = dataPoints.size();
+ for(size_t i = 0; i < _nplots; i++) {
+ _dataPoints.push_back(new double[_numDataPoints]);
+ if(numDataPoints > 0) {
+ memcpy(_dataPoints[i], dataPoints[i],
+ _numDataPoints*sizeof(double));
+ }
+ }
+
+ _dataTimestamp = dataTimestamp;
+}
+
+WaterfallUpdateEvent::~WaterfallUpdateEvent()
+{
+ for(size_t i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ }
+}
+
+const std::vector<double*>
+WaterfallUpdateEvent::getPoints() const
+{
+ return _dataPoints;
+}
+
+uint64_t
+WaterfallUpdateEvent::getNumDataPoints() const
+{
+ return _numDataPoints;
+}
+
+gruel::high_res_timer_type
+WaterfallUpdateEvent::getDataTimestamp() const
+{
+ return _dataTimestamp;
+}
+
#endif /* SPECTRUM_UPDATE_EVENTS_C */
diff --git a/gr-qtgui/lib/spectrumUpdateEvents.h b/gr-qtgui/lib/spectrumUpdateEvents.h
index faef0f0875..e663980bc6 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.h
+++ b/gr-qtgui/lib/spectrumUpdateEvents.h
@@ -8,10 +8,15 @@
#include <vector>
#include <gruel/high_res_timer.h>
+static const int SpectrumUpdateEventType = 10005;
+static const int SpectrumWindowCaptionEventType = 10008;
+static const int SpectrumWindowResetEventType = 10009;
+static const int SpectrumFrequencyRangeEventType = 10010;
+
class SpectrumUpdateEvent:public QEvent{
public:
- SpectrumUpdateEvent(const std::complex<float>* fftPoints,
+ SpectrumUpdateEvent(const float* fftPoints,
const uint64_t numFFTDataPoints,
const double* realTimeDomainPoints,
const double* imagTimeDomainPoints,
@@ -24,7 +29,7 @@ public:
~SpectrumUpdateEvent();
- const std::complex<float>* getFFTPoints() const;
+ const float* getFFTPoints() const;
const double* getRealTimeDomainPoints() const;
const double* getImagTimeDomainPoints() const;
uint64_t getNumFFTDataPoints() const;
@@ -38,7 +43,7 @@ public:
protected:
private:
- std::complex<float>* _fftPoints;
+ float* _fftPoints;
double* _realDataTimeDomainPoints;
double* _imagDataTimeDomainPoints;
uint64_t _numFFTDataPoints;
@@ -103,6 +108,9 @@ public:
uint64_t getNumTimeDomainDataPoints() const;
bool getRepeatDataFlag() const;
+ static QEvent::Type Type()
+ { return QEvent::Type(SpectrumUpdateEventType); }
+
protected:
private:
@@ -112,4 +120,96 @@ private:
};
+/********************************************************************/
+
+
+class FreqUpdateEvent: public QEvent
+{
+public:
+ FreqUpdateEvent(const std::vector<double*> dataPoints,
+ const uint64_t numDataPoints);
+
+ ~FreqUpdateEvent();
+
+ int which() const;
+ const std::vector<double*> getPoints() const;
+ uint64_t getNumDataPoints() const;
+ bool getRepeatDataFlag() const;
+
+ static QEvent::Type Type()
+ { return QEvent::Type(SpectrumUpdateEventType); }
+
+protected:
+
+private:
+ size_t _nplots;
+ std::vector<double*> _dataPoints;
+ uint64_t _numDataPoints;
+};
+
+
+/********************************************************************/
+
+
+class ConstUpdateEvent: public QEvent
+{
+public:
+ ConstUpdateEvent(const std::vector<double*> realDataPoints,
+ const std::vector<double*> imagDataPoints,
+ const uint64_t numDataPoints);
+
+ ~ConstUpdateEvent();
+
+ int which() const;
+ const std::vector<double*> getRealPoints() const;
+ const std::vector<double*> getImagPoints() const;
+ uint64_t getNumDataPoints() const;
+ bool getRepeatDataFlag() const;
+
+ static QEvent::Type Type()
+ { return QEvent::Type(SpectrumUpdateEventType); }
+
+protected:
+
+private:
+ size_t _nplots;
+ std::vector<double*> _realDataPoints;
+ std::vector<double*> _imagDataPoints;
+ uint64_t _numDataPoints;
+};
+
+
+/********************************************************************/
+
+
+class WaterfallUpdateEvent: public QEvent
+{
+public:
+ WaterfallUpdateEvent(const std::vector<double*> dataPoints,
+ const uint64_t numDataPoints,
+ const gruel::high_res_timer_type dataTimestamp);
+
+ ~WaterfallUpdateEvent();
+
+ int which() const;
+ const std::vector<double*> getPoints() const;
+ uint64_t getNumDataPoints() const;
+ bool getRepeatDataFlag() const;
+
+ gruel::high_res_timer_type getDataTimestamp() const;
+
+ static QEvent::Type Type()
+ { return QEvent::Type(SpectrumUpdateEventType); }
+
+protected:
+
+private:
+ size_t _nplots;
+ std::vector<double*> _dataPoints;
+ uint64_t _numDataPoints;
+
+ gruel::high_res_timer_type _dataTimestamp;
+};
+
+
#endif /* SPECTRUM_UPDATE_EVENTS_H */
diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc
index dd9011dbdd..6de6caa1b1 100644
--- a/gr-qtgui/lib/spectrumdisplayform.cc
+++ b/gr-qtgui/lib/spectrumdisplayform.cc
@@ -24,6 +24,7 @@
#include <QColorDialog>
#include <QMessageBox>
#include <spectrumdisplayform.h>
+#include "qtgui_types.h"
SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent)
: QWidget(parent)
@@ -33,10 +34,10 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent)
_systemSpecifiedFlag = false;
_intValidator = new QIntValidator(this);
_intValidator->setBottom(0);
- _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame);
- _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame);
+ _frequencyDisplayPlot = new FrequencyDisplayPlot(1, FrequencyPlotDisplayFrame);
+ _waterfallDisplayPlot = new WaterfallDisplayPlot(1, WaterfallPlotDisplayFrame);
_timeDomainDisplayPlot = new TimeDomainDisplayPlot(2, TimeDomainDisplayFrame);
- _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame);
+ _constellationDisplayPlot = new ConstellationDisplayPlot(1, ConstellationDisplayFrame);
_numRealDataPoints = 1024;
_realFFTDataPoints = new double[_numRealDataPoints];
_averagedValues = new double[_numRealDataPoints];
@@ -48,13 +49,11 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent)
AvgLineEdit->setRange(0, 500); // Set range of Average box value from 0 to 500
MinHoldCheckBox_toggled( false );
MaxHoldCheckBox_toggled( false );
-
- WaterfallMaximumIntensityWheel->setRange(-200, 0);
- WaterfallMaximumIntensityWheel->setTickCnt(50);
- WaterfallMinimumIntensityWheel->setRange(-200, 0);
- WaterfallMinimumIntensityWheel->setTickCnt(50);
- WaterfallMinimumIntensityWheel->setValue(-200);
-
+
+ WaterfallMaximumIntensitySlider->setRange(-200, 0);
+ WaterfallMinimumIntensitySlider->setRange(-200, 0);
+ WaterfallMinimumIntensitySlider->setValue(-200);
+
_peakFrequency = 0;
_peakAmplitude = -HUGE_VAL;
@@ -137,11 +136,57 @@ SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem,
}
}
+/***********************************************************************
+ * This is kind of gross because we're combining three operations:
+ * Conversion from float to double (which is what the plotter wants)
+ * Finding the peak and mean
+ * Doing the "FFT shift" to put 0Hz at the center of the plot
+ * I feel like this might want to be part of the sink block
+ **********************************************************************/
+static void fftshift_and_sum(double *outFFT, const float *inFFT, uint64_t num_points, double &sum_mean, double &peak_ampl, int &peak_bin) {
+ const float* inptr = inFFT+num_points/2;
+ double* outptr = outFFT;
+
+ sum_mean = 0;
+ peak_ampl = -HUGE_VAL;
+ peak_bin = 0;
+
+ // Run this twice to perform the fftshift operation on the data here as well
+ for(uint64_t point = 0; point < num_points/2; point++){
+ float pt = (*inptr);
+ *outptr = pt;
+ if(*outptr > peak_ampl) {
+ peak_bin = point;
+ peak_ampl = *outptr;
+ }
+ sum_mean += *outptr;
+
+ inptr++;
+ outptr++;
+ }
+
+ // This loop takes the first half of the input data and puts it in the
+ // second half of the plotted data
+ inptr = inFFT;
+ for(uint64_t point = 0; point < num_points/2; point++){
+ float pt = (*inptr);
+ *outptr = pt;
+ if(*outptr > peak_ampl) {
+ peak_bin = point;
+ peak_ampl = *outptr;
+ }
+ sum_mean += *outptr;
+
+ inptr++;
+ outptr++;
+ }
+}
+
void
SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
{
//_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent);
- const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
+ const float* fftMagDataPoints = spectrumUpdateEvent->getFFTPoints();
const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
const gruel::high_res_timer_type dataTimestamp = spectrumUpdateEvent->getDataTimestamp();
@@ -158,68 +203,34 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate
// REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
- // Calculate the Magnitude of the complex point
- const std::complex<float>* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2;
- double* realFFTDataPointsPtr = _realFFTDataPoints;
-
- double sumMean = 0.0;
- double localPeakAmplitude = -HUGE_VAL;
- double localPeakFrequency = 0.0;
const double fftBinSize = (_stopFrequency-_startFrequency) /
static_cast<double>(numFFTDataPoints);
- // Run this twice to perform the fftshift operation on the data here as well
- std::complex<float> scaleFactor = std::complex<float>((float)numFFTDataPoints);
- for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
- std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor;
- *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
-
- if(*realFFTDataPointsPtr > localPeakAmplitude) {
- localPeakFrequency = static_cast<float>(point) * fftBinSize;
- localPeakAmplitude = *realFFTDataPointsPtr;
- }
- sumMean += *realFFTDataPointsPtr;
-
- complexDataPointsPtr++;
- realFFTDataPointsPtr++;
- }
-
- // This loop takes the first half of the input data and puts it in the
- // second half of the plotted data
- complexDataPointsPtr = complexDataPoints;
- for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
- std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor;
- *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
-
- if(*realFFTDataPointsPtr > localPeakAmplitude) {
- localPeakFrequency = static_cast<float>(point) * fftBinSize;
- localPeakAmplitude = *realFFTDataPointsPtr;
- }
- sumMean += *realFFTDataPointsPtr;
-
- complexDataPointsPtr++;
- realFFTDataPointsPtr++;
- }
+ //this does the fftshift, conversion to double, and calculation of sum, peak amplitude, peak freq.
+ double sum_mean, peak_ampl;
+ int peak_bin;
+ fftshift_and_sum(_realFFTDataPoints, fftMagDataPoints, numFFTDataPoints, sum_mean, peak_ampl, peak_bin);
+ double peak_freq = peak_bin * fftBinSize;
// Don't update the averaging history if this is repeated data
if(!repeatDataFlag){
_AverageHistory(_realFFTDataPoints);
// Only use the local info if we are not repeating data
- _peakAmplitude = localPeakAmplitude;
- _peakFrequency = localPeakFrequency;
+ _peakAmplitude = peak_ampl;
+ _peakFrequency = peak_freq;
// calculate the spectral mean
// +20 because for the comparison below we only want to throw out bins
// that are significantly higher (and would, thus, affect the mean more)
- const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
+ const double meanAmplitude = (sum_mean / numFFTDataPoints) + 20.0;
// now throw out any bins higher than the mean
- sumMean = 0.0;
+ sum_mean = 0.0;
uint64_t newNumDataPoints = numFFTDataPoints;
for(uint64_t number = 0; number < numFFTDataPoints; number++){
if (_realFFTDataPoints[number] <= meanAmplitude)
- sumMean += _realFFTDataPoints[number];
+ sum_mean += _realFFTDataPoints[number];
else
newNumDataPoints--;
}
@@ -227,7 +238,7 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate
if (newNumDataPoints == 0) // in the odd case that all
_noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
else
- _noiseFloorAmplitude = sumMean / newNumDataPoints;
+ _noiseFloorAmplitude = sum_mean / newNumDataPoints;
}
if(lastOfMultipleUpdatesFlag){
@@ -296,26 +307,26 @@ SpectrumDisplayForm::customEvent( QEvent * e)
FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
}
- waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
- waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
+ waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensitySlider->value());
+ waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensitySlider->value());
// Clear any previous display
Reset();
}
- else if(e->type() == 10005){
+ else if(e->type() == SpectrumUpdateEventType){
SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
newFrequencyData(spectrumUpdateEvent);
}
- else if(e->type() == 10008){
+ else if(e->type() == SpectrumWindowCaptionEventType){
setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
}
- else if(e->type() == 10009){
+ else if(e->type() == SpectrumWindowResetEventType){
Reset();
if(_systemSpecifiedFlag){
_system->ResetPendingGUIUpdateEvents();
}
}
- else if(e->type() == 10010){
+ else if(e->type() == SpectrumFrequencyRangeEventType){
_startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
_stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
_centerFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
@@ -535,7 +546,7 @@ SpectrumDisplayForm::closeEvent( QCloseEvent *e )
qApp->processEvents();
- QWidget::closeEvent(e);
+ QWidget::closeEvent(e); //equivalent to e->accept()
}
@@ -558,30 +569,30 @@ SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
void
SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
{
- if(newValue > WaterfallMinimumIntensityWheel->value()){
+ if(newValue > WaterfallMinimumIntensitySlider->value()){
WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
}
else{
- WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
+ WaterfallMinimumIntensitySlider->setValue(newValue - 2);
}
- _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
- WaterfallMaximumIntensityWheel->value());
+ _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensitySlider->value(),
+ WaterfallMaximumIntensitySlider->value());
}
void
SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
{
- if(newValue < WaterfallMaximumIntensityWheel->value()){
+ if(newValue < WaterfallMaximumIntensitySlider->value()){
WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
}
else{
- WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
+ WaterfallMaximumIntensitySlider->setValue(newValue + 2);
}
- _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
- WaterfallMaximumIntensityWheel->value());
+ _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensitySlider->value(),
+ WaterfallMaximumIntensitySlider->value());
}
void
@@ -597,15 +608,15 @@ void
SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
{
double minimumIntensity = _noiseFloorAmplitude - 5;
- if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
- minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
+ if(minimumIntensity < WaterfallMinimumIntensitySlider->minValue()){
+ minimumIntensity = WaterfallMinimumIntensitySlider->minValue();
}
- WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
+ WaterfallMinimumIntensitySlider->setValue(minimumIntensity);
double maximumIntensity = _peakAmplitude + 10;
- if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
- maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
+ if(maximumIntensity > WaterfallMaximumIntensitySlider->maxValue()){
+ maximumIntensity = WaterfallMaximumIntensitySlider->maxValue();
}
- WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
+ WaterfallMaximumIntensitySlider->setValue(maximumIntensity);
waterfallMaximumIntensityChangedCB(maximumIntensity);
}
@@ -614,7 +625,7 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
{
QColor lowIntensityColor;
QColor highIntensityColor;
- if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
+ if(newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
// Select the Low Intensity Color
lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
if(!lowIntensityColor.isValid()){
@@ -632,7 +643,7 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
}
- _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
+ _waterfallDisplayPlot->SetIntensityColorMapType(0, newType, lowIntensityColor, highIntensityColor);
}
void
diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui
index 049d4ffeb4..9b06f44f0d 100644
--- a/gr-qtgui/lib/spectrumdisplayform.ui
+++ b/gr-qtgui/lib/spectrumdisplayform.ui
@@ -177,13 +177,13 @@
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
- <verstretch>0</verstretch>
+ <verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>617</width>
- <height>400</height>
+ <width>320</width>
+ <height>200</height>
</size>
</property>
<property name="sizeIncrement">
@@ -283,7 +283,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>200</width>
+ <width>100</width>
<height>20</height>
</size>
</property>
@@ -304,7 +304,7 @@
<widget class="QLabel" name="textLabel1">
<property name="maximumSize">
<size>
- <width>100</width>
+ <width>130</width>
<height>16777215</height>
</size>
</property>
@@ -317,10 +317,10 @@
</widget>
</item>
<item row="0" column="2">
- <widget class="QwtWheel" name="WaterfallMaximumIntensityWheel">
+ <widget class="QwtSlider" name="WaterfallMaximumIntensitySlider">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>50</width>
<height>0</height>
</size>
</property>
@@ -328,20 +328,11 @@
<bool>true</bool>
</property>
<property name="focusPolicy">
- <enum>Qt::WheelFocus</enum>
+ <enum>Qt::ClickFocus</enum>
</property>
<property name="valid">
<bool>true</bool>
</property>
- <property name="totalAngle">
- <double>200.000000000000000</double>
- </property>
- <property name="viewAngle">
- <double>20.000000000000000</double>
- </property>
- <property name="mass">
- <double>0.000000000000000</double>
- </property>
</widget>
</item>
<item row="0" column="3">
@@ -364,8 +355,8 @@
<widget class="QFrame" name="WaterfallPlotDisplayFrame">
<property name="minimumSize">
<size>
- <width>617</width>
- <height>338</height>
+ <width>320</width>
+ <height>200</height>
</size>
</property>
<property name="frameShape">
@@ -377,24 +368,21 @@
</widget>
</item>
<item row="2" column="2">
- <widget class="QwtWheel" name="WaterfallMinimumIntensityWheel">
+ <widget class="QwtSlider" name="WaterfallMinimumIntensitySlider">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>50</width>
<height>0</height>
</size>
</property>
<property name="valid">
<bool>true</bool>
</property>
- <property name="totalAngle">
- <double>200.000000000000000</double>
- </property>
- <property name="viewAngle">
- <double>20.000000000000000</double>
+ <property name="mouseTracking">
+ <bool>true</bool>
</property>
- <property name="mass">
- <double>0.000000000000000</double>
+ <property name="focusPolicy">
+ <enum>Qt::ClickFocus</enum>
</property>
</widget>
</item>
@@ -476,8 +464,8 @@
<widget class="QFrame" name="TimeDomainDisplayFrame">
<property name="minimumSize">
<size>
- <width>617</width>
- <height>404</height>
+ <width>320</width>
+ <height>200</height>
</size>
</property>
<property name="frameShape">
@@ -499,8 +487,8 @@
<widget class="QFrame" name="ConstellationDisplayFrame">
<property name="minimumSize">
<size>
- <width>617</width>
- <height>406</height>
+ <width>320</width>
+ <height>200</height>
</size>
</property>
<property name="frameShape">
@@ -520,18 +508,18 @@
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
- <customwidget>
- <class>QwtWheel</class>
+ <customwidget>
+ <class>QwtSlider</class>
<extends>QWidget</extends>
- <header>qwt_wheel.h</header>
- </customwidget>
+ <header>qwt_slider.h</header>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>SpectrumTypeTab</tabstop>
<tabstop>UseRFFrequenciesCheckBox</tabstop>
<tabstop>FFTSizeComboBox</tabstop>
- <tabstop>WaterfallMaximumIntensityWheel</tabstop>
- <tabstop>WaterfallMinimumIntensityWheel</tabstop>
+ <tabstop>WaterfallMaximumIntensitySlider</tabstop>
+ <tabstop>WaterfallMinimumIntensitySlider</tabstop>
</tabstops>
<includes>
<include location="global">SpectrumGUIClass.h</include>
@@ -540,7 +528,7 @@
<include location="global">TimeDomainDisplayPlot.h</include>
<include location="global">qvalidator.h</include>
<include location="global">vector</include>
- <include location="local">qwt_wheel.h</include>
+ <include location="local">qwt_slider.h</include>
</includes>
<resources/>
<connections>
@@ -641,7 +629,7 @@
</hints>
</connection>
<connection>
- <sender>WaterfallMaximumIntensityWheel</sender>
+ <sender>WaterfallMaximumIntensitySlider</sender>
<signal>valueChanged(double)</signal>
<receiver>SpectrumDisplayForm</receiver>
<slot>waterfallMaximumIntensityChangedCB(double)</slot>
@@ -657,7 +645,7 @@
</hints>
</connection>
<connection>
- <sender>WaterfallMinimumIntensityWheel</sender>
+ <sender>WaterfallMinimumIntensitySlider</sender>
<signal>valueChanged(double)</signal>
<receiver>SpectrumDisplayForm</receiver>
<slot>waterfallMinimumIntensityChangedCB(double)</slot>
diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc
new file mode 100644
index 0000000000..83ab76eb6e
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_c_impl.cc
@@ -0,0 +1,256 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "time_sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_sink_c::sptr
+ time_sink_c::make(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_sink_c_impl(size, bw, name, nconnections, parent));
+ }
+
+ time_sink_c_impl::time_sink_c_impl(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("time_sink_c",
+ gr_make_io_signature(nconnections, nconnections, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_size(size), d_bandwidth(bw), d_name(name),
+ d_nconnections(2*nconnections), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_double(d_size));
+ memset(d_residbufs[i], 0, d_size*sizeof(double));
+ }
+
+ // Set alignment properties for VOLK
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(gr_complex);
+ set_alignment(std::max(1,alignment_multiple));
+
+ initialize();
+ }
+
+ time_sink_c_impl::~time_sink_c_impl()
+ {
+ // d_main_gui is a qwidget destroyed with its parent
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ void
+ time_sink_c_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new TimeDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetNPoints(d_size);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ time_sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ time_sink_c_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ time_sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ time_sink_c_impl::set_time_domain_axis(double min, double max)
+ {
+ d_main_gui->setTimeDomainAxis(min, max);
+ }
+
+ void
+ time_sink_c_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ time_sink_c_impl::set_title(int which, const std::string &title)
+ {
+ d_main_gui->setTitle(which, title.c_str());
+ }
+
+ void
+ time_sink_c_impl::set_color(int which, const std::string &color)
+ {
+ d_main_gui->setColor(which, color.c_str());
+ }
+
+ void
+ time_sink_c_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ time_sink_c_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ time_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ time_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ time_sink_c_impl::set_nsamps(const int newsize)
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ if(newsize != d_size) {
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ d_residbufs[i] = fft::malloc_double(newsize);
+
+ memset(d_residbufs[i], 0, newsize*sizeof(double));
+ }
+
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_size = newsize;
+ d_index = 0;
+
+ d_main_gui->SetNPoints(d_size);
+ }
+ }
+
+ void
+ time_sink_c_impl::npoints_resize()
+ {
+ int newsize = d_main_gui->GetNPoints();
+ set_nsamps(newsize);
+ }
+
+ int
+ time_sink_c_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int n=0, j=0, idx=0;
+ const gr_complex *in = (const gr_complex*)input_items[idx];
+
+ npoints_resize();
+
+ for(int i=0; i < noutput_items; i+=d_size) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_size-d_index;
+ idx = 0;
+
+ // If we have enough input for one full plot, do it
+ if(datasize >= resid) {
+
+ // Fill up residbufs with d_size number of items
+ for(n = 0; n < d_nconnections; n+=2) {
+ in = (const gr_complex*)input_items[idx++];
+ volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index],
+ &d_residbufs[n+1][d_index],
+ &in[j], resid);
+ }
+
+ // Update the plot if its time
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new TimeUpdateEvent(d_residbufs, d_size));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+
+ // Otherwise, copy what we received into the residbufs for next time
+ else {
+ for(n = 0; n < d_nconnections; n+=2) {
+ in = (const gr_complex*)input_items[idx++];
+ volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index],
+ &d_residbufs[n+1][d_index],
+ &in[j], datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h
new file mode 100644
index 0000000000..0cace14890
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_c_impl.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_TIME_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_TIME_SINK_C_IMPL_H
+
+#include <qtgui/time_sink_c.h>
+#include <timedisplayform.h>
+#include <gruel/thread.h>
+#include <gruel/high_res_timer.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API time_sink_c_impl : public time_sink_c
+ {
+ private:
+ void initialize();
+
+ gruel::mutex d_mutex;
+
+ int d_size;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<double*> d_residbufs;
+
+ QWidget *d_parent;
+ TimeDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void npoints_resize();
+
+ public:
+ time_sink_c_impl(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_time_domain_axis(double min, double max);
+ void set_update_time(double t);
+ void set_title(int which, const std::string &title);
+ void set_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, Qt::PenStyle style);
+ void set_line_marker(int which, QwtSymbol::Style marker);
+ void set_nsamps(const int size);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc
new file mode 100644
index 0000000000..4b965b648c
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_f_impl.cc
@@ -0,0 +1,254 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "time_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_sink_f::sptr
+ time_sink_f::make(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_sink_f_impl(size, bw, name, nconnections, parent));
+ }
+
+ time_sink_f_impl::time_sink_f_impl(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("time_sink_f",
+ gr_make_io_signature(nconnections, nconnections, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_size(size), d_bandwidth(bw), d_name(name),
+ d_nconnections(nconnections), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_double(d_size));
+ memset(d_residbufs[i], 0, d_size*sizeof(double));
+ }
+
+ // Set alignment properties for VOLK
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(gr_complex);
+ set_alignment(std::max(1,alignment_multiple));
+
+ initialize();
+ }
+
+ time_sink_f_impl::~time_sink_f_impl()
+ {
+ // d_main_gui is a qwidget destroyed with its parent
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ void
+ time_sink_f_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new TimeDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetNPoints(d_size);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ time_sink_f_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ time_sink_f_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ time_sink_f_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ time_sink_f_impl::set_time_domain_axis(double min, double max)
+ {
+ d_main_gui->setTimeDomainAxis(min, max);
+ }
+
+ void
+ time_sink_f_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ time_sink_f_impl::set_title(int which, const std::string &title)
+ {
+ d_main_gui->setTitle(which, title.c_str());
+ }
+
+ void
+ time_sink_f_impl::set_color(int which, const std::string &color)
+ {
+ d_main_gui->setColor(which, color.c_str());
+ }
+
+ void
+ time_sink_f_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ time_sink_f_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ time_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ time_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ time_sink_f_impl::set_nsamps(const int newsize)
+ {
+ gruel::scoped_lock lock(d_mutex);
+
+ if(newsize != d_size) {
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ d_residbufs[i] = fft::malloc_double(newsize);
+
+ memset(d_residbufs[i], 0, newsize*sizeof(double));
+ }
+
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_size = newsize;
+ d_index = 0;
+
+ d_main_gui->SetNPoints(d_size);
+ }
+ }
+
+ void
+ time_sink_f_impl::npoints_resize()
+ {
+ int newsize = d_main_gui->GetNPoints();
+ set_nsamps(newsize);
+ }
+
+ int
+ time_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int n=0, j=0, idx=0;
+ const float *in = (const float*)input_items[idx];
+
+ npoints_resize();
+
+ for(int i=0; i < noutput_items; i+=d_size) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_size-d_index;
+ idx = 0;
+
+ // If we have enough input for one full plot, do it
+ if(datasize >= resid) {
+
+ // Fill up residbufs with d_size number of items
+ for(n = 0; n < d_nconnections; n++) {
+ in = (const float*)input_items[idx++];
+ volk_32f_convert_64f_u(&d_residbufs[n][d_index],
+ &in[j], resid);
+ }
+
+ // Update the plot if its time
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new TimeUpdateEvent(d_residbufs, d_size));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+ // Otherwise, copy what we received into the residbufs for next time
+ // because we set the output_multiple, this should never need to be called
+ else {
+ for(n = 0; n < d_nconnections; n++) {
+ in = (const float*)input_items[idx++];
+ volk_32f_convert_64f_u(&d_residbufs[n][d_index],
+ &in[j], datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h
new file mode 100644
index 0000000000..69c07fbdab
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_f_impl.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_TIME_SINK_F_IMPL_H
+#define INCLUDED_QTGUI_TIME_SINK_F_IMPL_H
+
+#include <qtgui/time_sink_f.h>
+#include <timedisplayform.h>
+#include <gruel/thread.h>
+#include <gruel/high_res_timer.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API time_sink_f_impl : public time_sink_f
+ {
+ private:
+ void initialize();
+
+ gruel::mutex d_mutex;
+
+ int d_size;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<double*> d_residbufs;
+
+ QWidget *d_parent;
+ TimeDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void npoints_resize();
+
+ public:
+ time_sink_f_impl(int size, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_sink_f_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_time_domain_axis(double min, double max);
+ void set_update_time(double t);
+ void set_title(int which, const std::string &title);
+ void set_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, Qt::PenStyle style);
+ void set_line_marker(int which, QwtSymbol::Style marker);
+ void set_nsamps(const int newsize);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_SINK_F_IMPL_H */
diff --git a/gr-qtgui/lib/timedisplayform.cc b/gr-qtgui/lib/timedisplayform.cc
index c650cd3eb0..3d94d20094 100644
--- a/gr-qtgui/lib/timedisplayform.cc
+++ b/gr-qtgui/lib/timedisplayform.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011 Free Software Foundation, Inc.
+ * Copyright 2011,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -21,34 +21,30 @@
*/
#include <cmath>
-#include <QColorDialog>
#include <QMessageBox>
#include <timedisplayform.h>
#include <iostream>
TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent)
- : QWidget(parent)
+ : DisplayForm(nplots, parent)
{
- _systemSpecifiedFlag = false;
_intValidator = new QIntValidator(this);
_intValidator->setBottom(0);
_layout = new QGridLayout(this);
- _timeDomainDisplayPlot = new TimeDomainDisplayPlot(nplots, this);
- _layout->addWidget(_timeDomainDisplayPlot, 0, 0);
-
- _numRealDataPoints = 1024;
-
+ _displayPlot = new TimeDomainDisplayPlot(nplots, this);
+ _layout->addWidget(_displayPlot, 0, 0);
setLayout(_layout);
- Reset();
+ NPointsMenu *nptsmenu = new NPointsMenu(this);
+ _menu->addAction(nptsmenu);
+ connect(nptsmenu, SIGNAL(whichTrigger(int)),
+ this, SLOT(SetNPoints(const int)));
- // Create a timer to update plots at the specified rate
- displayTimer = new QTimer(this);
- connect(displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer()));
+ Reset();
- connect(_timeDomainDisplayPlot, SIGNAL(plotPointSelected(const QPointF)),
- this, SLOT(onTimePlotPointSelected(const QPointF)));
+ connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)),
+ this, SLOT(onPlotPointSelected(const QPointF)));
}
TimeDisplayForm::~TimeDisplayForm()
@@ -57,57 +53,32 @@ TimeDisplayForm::~TimeDisplayForm()
// Don't worry about deleting Display Plots - they are deleted when parents are deleted
delete _intValidator;
-
- displayTimer->stop();
- delete displayTimer;
}
-void
-TimeDisplayForm::newData( const TimeUpdateEvent* spectrumUpdateEvent)
+TimeDomainDisplayPlot*
+TimeDisplayForm::getPlot()
{
- const std::vector<double*> timeDomainDataPoints = spectrumUpdateEvent->getTimeDomainPoints();
- const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
-
- _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints,
- numTimeDomainDataPoints,
- d_update_time);
+ return ((TimeDomainDisplayPlot*)_displayPlot);
}
void
-TimeDisplayForm::resizeEvent( QResizeEvent *e )
+TimeDisplayForm::newData(const QEvent* updateEvent)
{
- QSize s = size();
- emit _timeDomainDisplayPlot->resizeSlot(&s);
-}
+ TimeUpdateEvent *tevent = (TimeUpdateEvent*)updateEvent;
+ const std::vector<double*> dataPoints = tevent->getTimeDomainPoints();
+ const uint64_t numDataPoints = tevent->getNumTimeDomainDataPoints();
-void
-TimeDisplayForm::customEvent( QEvent * e)
-{
- if(e->type() == 10005) {
- TimeUpdateEvent* timeUpdateEvent = (TimeUpdateEvent*)e;
- newData(timeUpdateEvent);
- }
- //else if(e->type() == 10008){
- //setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
- //}
- //else if(e->type() == 10009){
- //Reset();
- //if(_systemSpecifiedFlag){
- // _system->ResetPendingGUIUpdateEvents();
- //}
- //}
-}
-
-void
-TimeDisplayForm::updateGuiTimer()
-{
- _timeDomainDisplayPlot->canvas()->update();
+ getPlot()->PlotNewData(dataPoints,
+ numDataPoints,
+ d_update_time);
}
void
-TimeDisplayForm::onTimePlotPointSelected(const QPointF p)
+TimeDisplayForm::customEvent(QEvent * e)
{
- emit plotPointSelected(p, 3);
+ if(e->type() == TimeUpdateEvent::Type()) {
+ newData(e);
+ }
}
void
@@ -126,52 +97,26 @@ TimeDisplayForm::setFrequencyRange(const double newCenterFrequency,
_startFrequency = newStartFrequency;
_stopFrequency = newStopFrequency;
-
- _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency,
- units, strtime[iunit]);
+
+ getPlot()->SetSampleRate(_stopFrequency - _startFrequency,
+ units, strtime[iunit]);
}
}
void
-TimeDisplayForm::Reset()
-{
-}
-
-
-void
-TimeDisplayForm::closeEvent( QCloseEvent *e )
-{
- //if(_systemSpecifiedFlag){
- // _system->SetWindowOpenFlag(false);
- //}
-
- qApp->processEvents();
-
- QWidget::closeEvent(e);
-}
-
-void
TimeDisplayForm::setTimeDomainAxis(double min, double max)
{
- _timeDomainDisplayPlot->setYaxis(min, max);
-}
-
-void
-TimeDisplayForm::setUpdateTime(double t)
-{
- d_update_time = t;
- // QTimer class takes millisecond input
- displayTimer->start(d_update_time*1000);
+ getPlot()->setYaxis(min, max);
}
-void
-TimeDisplayForm::setTitle(int which, QString title)
+int
+TimeDisplayForm::GetNPoints() const
{
- _timeDomainDisplayPlot->setTitle(which, title);
+ return d_npoints;
}
void
-TimeDisplayForm::setColor(int which, QString color)
+TimeDisplayForm::SetNPoints(const int npoints)
{
- _timeDomainDisplayPlot->setColor(which, color);
+ d_npoints = npoints;
}
diff --git a/gr-qtgui/lib/timedisplayform.h b/gr-qtgui/lib/timedisplayform.h
index dd3f62a83f..806fc4053f 100644
--- a/gr-qtgui/lib/timedisplayform.h
+++ b/gr-qtgui/lib/timedisplayform.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011 Free Software Foundation, Inc.
+ * Copyright 2011,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -24,17 +24,13 @@
#define TIME_DISPLAY_FORM_H
#include <spectrumUpdateEvents.h>
-#include <FrequencyDisplayPlot.h>
-#include <WaterfallDisplayPlot.h>
#include <TimeDomainDisplayPlot.h>
-#include <ConstellationDisplayPlot.h>
-#include <QtGui/QApplication>
-#include <QtGui/QGridLayout>
-#include <QValidator>
-#include <QTimer>
+#include <QtGui/QtGui>
#include <vector>
-class TimeDisplayForm : public QWidget
+#include "displayform.h"
+
+class TimeDisplayForm : public DisplayForm
{
Q_OBJECT
@@ -42,44 +38,29 @@ class TimeDisplayForm : public QWidget
TimeDisplayForm(int nplots=1, QWidget* parent = 0);
~TimeDisplayForm();
- void Reset();
+ TimeDomainDisplayPlot* getPlot();
+
+ int GetNPoints() const;
public slots:
- void resizeEvent( QResizeEvent * e );
- void customEvent( QEvent * e );
- void setFrequencyRange( const double newCenterFrequency,
- const double newStartFrequency,
- const double newStopFrequency );
- void closeEvent( QCloseEvent * e );
+ void customEvent(QEvent * e);
+ void setFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency);
void setTimeDomainAxis(double min, double max);
-
- void setUpdateTime(double t);
-
- void setTitle(int which, QString title);
- void setColor(int which, QString color);
+ void SetNPoints(const int);
private slots:
- void newData( const TimeUpdateEvent* );
- void updateGuiTimer();
-
- void onTimePlotPointSelected(const QPointF p);
-
-signals:
- void plotPointSelected(const QPointF p, int type);
+ void newData(const QEvent*);
private:
- uint64_t _numRealDataPoints;
QIntValidator* _intValidator;
- QGridLayout *_layout;
- TimeDomainDisplayPlot* _timeDomainDisplayPlot;
- bool _systemSpecifiedFlag;
double _startFrequency;
double _stopFrequency;
- QTimer *displayTimer;
- double d_update_time;
+ int d_npoints;
};
#endif /* TIME_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc
new file mode 100644
index 0000000000..0611d37974
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -0,0 +1,366 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "waterfall_sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ waterfall_sink_c::sptr
+ waterfall_sink_c::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new waterfall_sink_c_impl(fftsize, wintype,
+ fc, bw, name,
+ parent));
+ }
+
+ waterfall_sink_c_impl::waterfall_sink_c_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent)
+ : gr_sync_block("waterfall_sink_c",
+ gr_make_io_signature(1, -1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_fftsize(fftsize), d_fftavg(1.0),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_nconnections(1), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+ d_index = 0;
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_complex(d_fftsize));
+ d_magbufs.push_back(fft::malloc_double(d_fftsize));
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
+ }
+
+ buildwindow();
+
+ initialize();
+ }
+
+ waterfall_sink_c_impl::~waterfall_sink_c_impl()
+ {
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+ }
+ delete d_fft;
+ fft::free(d_fbuf);
+ }
+
+ void
+ waterfall_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ waterfall_sink_c_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetFFTWindowType(d_wintype);
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ d_center_freq - d_bandwidth/2.0,
+ d_center_freq + d_bandwidth/2.0);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ waterfall_sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ waterfall_sink_c_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ waterfall_sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ waterfall_sink_c_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ waterfall_sink_c_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ waterfall_sink_c_impl::set_fft_average(const float fftavg)
+ {
+ d_fftavg = fftavg;
+ d_main_gui->SetFFTAverage(fftavg);
+ }
+
+ float
+ waterfall_sink_c_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ waterfall_sink_c_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ waterfall_sink_c_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ waterfall_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(0, title.c_str());
+ }
+
+ void
+ waterfall_sink_c_impl::set_color(const std::string &color)
+ {
+ d_main_gui->setColor(0, color.c_str());
+ }
+
+ void
+ waterfall_sink_c_impl::set_line_width(int width)
+ {
+ d_main_gui->setLineWidth(0, width);
+ }
+
+ void
+ waterfall_sink_c_impl::set_line_style(Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(0, style);
+ }
+
+ void
+ waterfall_sink_c_impl::set_line_marker(QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(0, marker);
+ }
+
+ void
+ waterfall_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ waterfall_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size)
+ {
+ if(d_window.size()) {
+ volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in, &d_window.front(), size);
+ }
+ else {
+ memcpy(d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size);
+ }
+
+ d_fft->execute(); // compute the fft
+
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+
+ // Perform shift operation
+ unsigned int len = (unsigned int)(floor(size/2.0));
+ float *tmp = (float*)malloc(sizeof(float)*len);
+ memcpy(tmp, &data_out[0], sizeof(float)*len);
+ memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len));
+ memcpy(&data_out[size - len], tmp, sizeof(float)*len);
+ free(tmp);
+ }
+
+ void
+ waterfall_sink_c_impl::windowreset()
+ {
+ filter::firdes::win_type newwintype;
+ newwintype = d_main_gui->GetFFTWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ waterfall_sink_c_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != filter::firdes::WIN_NONE) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ waterfall_sink_c_impl::fftresize()
+ {
+ int newfftsize = d_main_gui->GetFFTSize();
+ d_fftavg = d_main_gui->GetFFTAverage();
+
+ if(newfftsize != d_fftsize) {
+
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+
+ d_residbufs[i] = fft::malloc_complex(newfftsize);
+ d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(gr_complex));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
+ }
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+ }
+ }
+
+ int
+ waterfall_sink_c_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+
+ for(int n = 0; n < d_nconnections; n++) {
+ // Fill up residbuf with d_fftsize number of items
+ in = (const gr_complex*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid);
+
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
+ }
+
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new WaterfallUpdateEvent(d_magbufs,
+ d_fftsize,
+ d_last_time));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ for(int n = 0; n < d_nconnections; n++) {
+ in = (const gr_complex*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h
new file mode 100644
index 0000000000..b51b1e66eb
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H
+
+#include <qtgui/waterfall_sink_c.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <waterfalldisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API waterfall_sink_c_impl : public waterfall_sink_c
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ int d_fftsize;
+ float d_fftavg;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ std::vector<gr_complex*> d_residbufs;
+ std::vector<double*> d_magbufs;
+ float *d_fbuf;
+
+ QWidget *d_parent;
+ WaterfallDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const gr_complex *data_in, int size);
+
+ public:
+ waterfall_sink_c_impl(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent=NULL);
+ ~waterfall_sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_color(const std::string &color);
+ void set_line_width(int width);
+ void set_line_style(Qt::PenStyle style);
+ void set_line_marker(QwtSymbol::Style marker);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc
new file mode 100644
index 0000000000..3fdb2b795a
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -0,0 +1,368 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "waterfall_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ waterfall_sink_f::sptr
+ waterfall_sink_f::make(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new waterfall_sink_f_impl(fftsize, wintype,
+ fc, bw, name,
+ parent));
+ }
+
+ waterfall_sink_f_impl::waterfall_sink_f_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent)
+ : gr_sync_block("waterfall_sink_f",
+ gr_make_io_signature(1, -1, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_fftsize(fftsize), d_fftavg(1.0),
+ d_wintype((filter::firdes::win_type)(wintype)),
+ d_center_freq(fc), d_bandwidth(bw), d_name(name),
+ d_nconnections(1), d_parent(parent)
+ {
+ d_main_gui = NULL;
+
+ // Perform fftshift operation;
+ // this is usually desired when plotting
+ d_shift = true;
+
+ d_fft = new fft::fft_complex(d_fftsize, true);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+
+ d_index = 0;
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_float(d_fftsize));
+ d_magbufs.push_back(fft::malloc_double(d_fftsize));
+ memset(d_residbufs[i], 0, d_fftsize*sizeof(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
+ }
+
+ buildwindow();
+
+ initialize();
+ }
+
+ waterfall_sink_f_impl::~waterfall_sink_f_impl()
+ {
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+ }
+ delete d_fft;
+ fft::free(d_fbuf);
+ }
+
+ void
+ waterfall_sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned int ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = std::min(d_fftsize, 8191);
+ }
+ }
+
+ void
+ waterfall_sink_f_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc=0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent);
+ d_main_gui->SetFFTSize(d_fftsize);
+ d_main_gui->SetFFTWindowType(d_wintype);
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ d_center_freq - d_bandwidth/2.0,
+ d_center_freq + d_bandwidth/2.0);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ waterfall_sink_f_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ waterfall_sink_f_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ waterfall_sink_f_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ waterfall_sink_f_impl::set_fft_size(const int fftsize)
+ {
+ d_fftsize = fftsize;
+ d_main_gui->SetFFTSize(fftsize);
+ }
+
+ int
+ waterfall_sink_f_impl::fft_size() const
+ {
+ return d_fftsize;
+ }
+
+ void
+ waterfall_sink_f_impl::set_fft_average(const float fftavg)
+ {
+ d_fftavg = fftavg;
+ d_main_gui->SetFFTAverage(fftavg);
+ }
+
+ float
+ waterfall_sink_f_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ waterfall_sink_f_impl::set_frequency_range(const double centerfreq,
+ const double bandwidth)
+ {
+ d_center_freq = centerfreq;
+ d_bandwidth = bandwidth;
+ d_main_gui->SetFrequencyRange(d_center_freq,
+ -d_bandwidth/2.0,
+ d_bandwidth/2.0);
+ }
+
+ void
+ waterfall_sink_f_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gruel::high_res_timer_type tps = gruel::high_res_timer_tps();
+ d_update_time = t * tps;
+ d_main_gui->setUpdateTime(t);
+ }
+
+ void
+ waterfall_sink_f_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(0, title.c_str());
+ }
+
+ void
+ waterfall_sink_f_impl::set_color(const std::string &color)
+ {
+ d_main_gui->setColor(0, color.c_str());
+ }
+
+ void
+ waterfall_sink_f_impl::set_line_width(int width)
+ {
+ d_main_gui->setLineWidth(0, width);
+ }
+
+ void
+ waterfall_sink_f_impl::set_line_style(Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(0, style);
+ }
+
+ void
+ waterfall_sink_f_impl::set_line_marker(QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(0, marker);
+ }
+
+ void
+ waterfall_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ waterfall_sink_f_impl::fft(float *data_out, const float *data_in, int size)
+ {
+ // float to complex conversion
+ gr_complex *dst = d_fft->get_inbuf();
+ for (int i = 0; i < size; i++)
+ dst[i] = data_in[i];
+
+ if(d_window.size()) {
+ volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), dst,
+ &d_window.front(), size);
+ }
+
+ d_fft->execute(); // compute the fft
+
+ volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(),
+ size, 1.0, size);
+
+ // Perform shift operation
+ unsigned int len = (unsigned int)(floor(size/2.0));
+ float *tmp = (float*)malloc(sizeof(float)*len);
+ memcpy(tmp, &data_out[0], sizeof(float)*len);
+ memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len));
+ memcpy(&data_out[size - len], tmp, sizeof(float)*len);
+ free(tmp);
+ }
+
+ void
+ waterfall_sink_f_impl::windowreset()
+ {
+ filter::firdes::win_type newwintype;
+ newwintype = d_main_gui->GetFFTWindowType();
+ if(d_wintype != newwintype) {
+ d_wintype = newwintype;
+ buildwindow();
+ }
+ }
+
+ void
+ waterfall_sink_f_impl::buildwindow()
+ {
+ d_window.clear();
+ if(d_wintype != filter::firdes::WIN_NONE) {
+ d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76);
+ }
+ }
+
+ void
+ waterfall_sink_f_impl::fftresize()
+ {
+ int newfftsize = d_fftsize;
+
+ if(newfftsize != d_fftsize) {
+
+ // Resize residbuf and replace data
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ fft::free(d_magbufs[i]);
+
+ d_residbufs[i] = fft::malloc_float(newfftsize);
+ d_magbufs[i] = fft::malloc_double(newfftsize);
+
+ memset(d_residbufs[i], 0, newfftsize*sizeof(float));
+ memset(d_magbufs[i], 0, newfftsize*sizeof(double));
+ }
+
+ // Set new fft size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_fftsize = newfftsize;
+ d_index = 0;
+
+ // Reset window to reflect new size
+ buildwindow();
+
+ // Reset FFTW plan for new size
+ delete d_fft;
+ d_fft = new fft::fft_complex(d_fftsize, true);
+
+ fft::free(d_fbuf);
+ d_fbuf = fft::malloc_float(d_fftsize);
+ memset(d_fbuf, 0, d_fftsize*sizeof(float));
+ }
+ }
+
+ int
+ waterfall_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int j=0;
+ const float *in = (const float*)input_items[0];
+
+ // Update the FFT size from the application
+ fftresize();
+ windowreset();
+
+ for(int i=0; i < noutput_items; i+=d_fftsize) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_fftsize-d_index;
+
+ // If we have enough input for one full FFT, do it
+ if(datasize >= resid) {
+
+ for(int n = 0; n < d_nconnections; n++) {
+ // Fill up residbuf with d_fftsize number of items
+ in = (const float*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid);
+
+ fft(d_fbuf, d_residbufs[n], d_fftsize);
+ for(int x = 0; x < d_fftsize; x++) {
+ d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]);
+ }
+ //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize);
+ }
+
+ if(gruel::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gruel::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new WaterfallUpdateEvent(d_magbufs,
+ d_fftsize,
+ d_last_time));
+ }
+
+ d_index = 0;
+ j += resid;
+ }
+ // Otherwise, copy what we received into the residbuf for next time
+ else {
+ for(int n = 0; n < d_nconnections; n++) {
+ in = (const float*)input_items[n];
+ memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h
new file mode 100644
index 0000000000..684e1dfb03
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H
+#define INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H
+
+
+#include <qtgui/waterfall_sink_f.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <waterfalldisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API waterfall_sink_f_impl : public waterfall_sink_f
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ int d_fftsize;
+ float d_fftavg;
+ filter::firdes::win_type d_wintype;
+ std::vector<float> d_window;
+ double d_center_freq;
+ double d_bandwidth;
+ std::string d_name;
+ int d_nconnections;
+
+ bool d_shift;
+ fft::fft_complex *d_fft;
+
+ int d_index;
+ std::vector<float*> d_residbufs;
+ std::vector<double*> d_magbufs;
+ float *d_fbuf;
+
+ QWidget *d_parent;
+ WaterfallDisplayForm *d_main_gui;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ void windowreset();
+ void buildwindow();
+ void fftresize();
+ void fft(float *data_out, const float *data_in, int size);
+
+ public:
+ waterfall_sink_f_impl(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ QWidget *parent=NULL);
+ ~waterfall_sink_f_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_color(const std::string &color);
+ void set_line_width(int width);
+ void set_line_style(Qt::PenStyle style);
+ void set_line_marker(QwtSymbol::Style marker);
+
+ void set_size(int width, int height);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H */
diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc
new file mode 100644
index 0000000000..1a69e97d10
--- /dev/null
+++ b/gr-qtgui/lib/waterfalldisplayform.cc
@@ -0,0 +1,205 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 <cmath>
+#include <QColorDialog>
+#include <QMessageBox>
+#include <waterfalldisplayform.h>
+#include <iostream>
+
+WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent)
+ : DisplayForm(nplots, parent)
+{
+ _intValidator = new QIntValidator(this);
+ _intValidator->setBottom(0);
+
+ _layout = new QGridLayout(this);
+ _displayPlot = new WaterfallDisplayPlot(nplots, this);
+ _layout->addWidget(_displayPlot, 0, 0);
+ setLayout(_layout);
+
+ _numRealDataPoints = 1024;
+ _fftsize = 1024;
+ _fftavg = 1.0;
+
+ _min_val = 1000;
+ _max_val = -1000;
+
+ QAction *autoscale_act = new QAction("Auto Scale", this);
+ autoscale_act->setStatusTip(tr("Autoscale intensity range"));
+ connect(autoscale_act, SIGNAL(triggered()), this, SLOT(AutoScale()));
+
+ FFTSizeMenu *sizemenu = new FFTSizeMenu(this);
+ FFTAverageMenu *avgmenu = new FFTAverageMenu(this);
+ FFTWindowMenu *winmenu = new FFTWindowMenu(this);
+ ColorMapMenu *colormenu = new ColorMapMenu(this);
+ _menu->addMenu(sizemenu);
+ _menu->addMenu(avgmenu);
+ _menu->addMenu(winmenu);
+ _menu->addMenu(colormenu);
+ _menu->addAction(autoscale_act);
+ connect(sizemenu, SIGNAL(whichTrigger(int)),
+ this, SLOT(SetFFTSize(const int)));
+ connect(avgmenu, SIGNAL(whichTrigger(float)),
+ this, SLOT(SetFFTAverage(const float)));
+ connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
+ this, SLOT(SetFFTWindowType(const gr::filter::firdes::win_type)));
+ connect(colormenu, SIGNAL(whichTrigger(const int, const QColor&, const QColor&)),
+ this, SLOT(SetColorMap(const int, const QColor&, const QColor&)));
+
+ Reset();
+
+ connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)),
+ this, SLOT(onPlotPointSelected(const QPointF)));
+}
+
+WaterfallDisplayForm::~WaterfallDisplayForm()
+{
+ // Qt deletes children when parent is deleted
+
+ // Don't worry about deleting Display Plots - they are deleted when parents are deleted
+ delete _intValidator;
+}
+
+WaterfallDisplayPlot*
+WaterfallDisplayForm::getPlot()
+{
+ return ((WaterfallDisplayPlot*)_displayPlot);
+}
+
+void
+WaterfallDisplayForm::newData(const QEvent *updateEvent)
+{
+ WaterfallUpdateEvent *event = (WaterfallUpdateEvent*)updateEvent;
+ const std::vector<double*> dataPoints = event->getPoints();
+ const uint64_t numDataPoints = event->getNumDataPoints();
+ const gruel::high_res_timer_type dataTimestamp = event->getDataTimestamp();
+
+ _min_val = 1000;
+ _max_val = -1000;
+ for(size_t i=0; i < dataPoints.size(); i++) {
+ double *min_val = std::min_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]);
+ double *max_val = std::max_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]);
+ if(*min_val < _min_val)
+ _min_val = *min_val;
+ if(*max_val > _max_val)
+ _max_val = *max_val;
+ }
+
+ getPlot()->PlotNewData(dataPoints, numDataPoints,
+ d_update_time, dataTimestamp, 0);
+}
+
+void
+WaterfallDisplayForm::customEvent( QEvent * e)
+{
+ if(e->type() == WaterfallUpdateEvent::Type()) {
+ newData(e);
+ }
+}
+
+int
+WaterfallDisplayForm::GetFFTSize() const
+{
+ return _fftsize;
+}
+
+float
+WaterfallDisplayForm::GetFFTAverage() const
+{
+ return _fftavg;
+}
+
+gr::filter::firdes::win_type
+WaterfallDisplayForm::GetFFTWindowType() const
+{
+ return _fftwintype;
+}
+
+void
+WaterfallDisplayForm::SetFFTSize(const int newsize)
+{
+ _fftsize = newsize;
+}
+
+void
+WaterfallDisplayForm::SetFFTAverage(const float newavg)
+{
+ _fftavg = newavg;
+}
+
+void
+WaterfallDisplayForm::SetFFTWindowType(const gr::filter::firdes::win_type newwin)
+{
+ _fftwintype = newwin;
+}
+
+void
+WaterfallDisplayForm::SetFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency)
+{
+ double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
+
+ if(fdiff > 0) {
+ std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
+ double units10 = floor(log10(fdiff));
+ double units3 = std::max(floor(units10 / 3.0), 0.0);
+ double units = pow(10, (units10-fmod(units10, 3.0)));
+ int iunit = static_cast<int>(units3);
+
+ _startFrequency = newStartFrequency;
+ _stopFrequency = newStopFrequency;
+ double centerFrequency = newCenterFrequency;
+
+ getPlot()->SetFrequencyRange(_startFrequency,
+ _stopFrequency,
+ centerFrequency,
+ true,
+ units, strunits[iunit]);
+ }
+}
+
+void
+WaterfallDisplayForm::SetColorMap(const int newType,
+ const QColor lowColor,
+ const QColor highColor)
+{
+ getPlot()->SetIntensityColorMapType(0, newType,
+ lowColor, highColor);
+}
+
+void
+WaterfallDisplayForm::SetIntensityRange(const double minIntensity,
+ const double maxIntensity)
+{
+ getPlot()->SetIntensityRange(minIntensity, maxIntensity);
+}
+
+void
+WaterfallDisplayForm::AutoScale()
+{
+ double min_int = _min_val - 5;
+ double max_int = _max_val + 10;
+
+ getPlot()->SetIntensityRange(min_int, max_int);
+}
diff --git a/gr-qtgui/lib/waterfalldisplayform.h b/gr-qtgui/lib/waterfalldisplayform.h
new file mode 100644
index 0000000000..46e0d815e0
--- /dev/null
+++ b/gr-qtgui/lib/waterfalldisplayform.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifndef WATERFALL_DISPLAY_FORM_H
+#define WATERFALL_DISPLAY_FORM_H
+
+#include <spectrumUpdateEvents.h>
+#include <WaterfallDisplayPlot.h>
+#include <QtGui/QtGui>
+#include <vector>
+#include <filter/firdes.h>
+
+#include "displayform.h"
+
+class WaterfallDisplayForm : public DisplayForm
+{
+ Q_OBJECT
+
+ public:
+ WaterfallDisplayForm(int nplots=1, QWidget* parent = 0);
+ ~WaterfallDisplayForm();
+
+ WaterfallDisplayPlot* getPlot();
+
+ int GetFFTSize() const;
+ float GetFFTAverage() const;
+ gr::filter::firdes::win_type GetFFTWindowType() const;
+
+public slots:
+ void customEvent(QEvent *e);
+
+ void SetFFTSize(const int);
+ void SetFFTAverage(const float);
+ void SetFFTWindowType(const gr::filter::firdes::win_type);
+
+ void SetFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency);
+
+ void SetIntensityRange(const double minIntensity,
+ const double maxIntensity);
+
+ void SetColorMap(const int newType,
+ const QColor lowColor,
+ const QColor highColor);
+
+ void AutoScale();
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ uint64_t _numRealDataPoints;
+ QIntValidator* _intValidator;
+
+ double _startFrequency;
+ double _stopFrequency;
+
+ int _fftsize;
+ float _fftavg;
+ gr::filter::firdes::win_type _fftwintype;
+
+ double _min_val;
+ double _max_val;
+};
+
+#endif /* WATERFALL_DISPLAY_FORM_H */
diff --git a/gr-qtgui/python/__init__.py b/gr-qtgui/python/__init__.py
index c7024e4f72..82e36597be 100644
--- a/gr-qtgui/python/__init__.py
+++ b/gr-qtgui/python/__init__.py
@@ -27,4 +27,4 @@ sinks.
# The presence of this file turns this directory into a Python package
from qtgui_swig import *
-import qtgui_swig as qtgui # to preserve the old interface
+#import qtgui_swig as qtgui # to preserve the old interface
diff --git a/gr-qtgui/python/qa_qtgui.py b/gr-qtgui/python/qa_qtgui.py
index 562706701a..eb402a2084 100755
--- a/gr-qtgui/python/qa_qtgui.py
+++ b/gr-qtgui/python/qa_qtgui.py
@@ -21,7 +21,7 @@
#
from gnuradio import gr, gr_unittest
-import qtgui_swig
+import qtgui_swig as qtgui
class test_qtgui(gr_unittest.TestCase):
@@ -31,18 +31,41 @@ class test_qtgui(gr_unittest.TestCase):
def tearDown (self):
self.tb = None
- def test01 (self):
- # Test to make sure we can instantiate the sink
- self.qtsnk = qtgui_swig.sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
- 0, 1, "Test",
- True, True, True, True)
+ # Tests to make sure we can instantiate the sink
+ def test01(self):
+ self.qtsnk = qtgui.sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test",
+ True, True, True, True)
- def test02 (self):
- # Test to make sure we can instantiate the sink
- self.qtsnk = qtgui_swig.sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
- 0, 1, "Test",
- True, True, True, True)
+ def test02(self):
+ self.qtsnk = qtgui.sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test",
+ True, True, True, True)
+ def test03(self):
+ self.qtsnk = qtgui.time_sink_c(1024, 1, "Test", 1)
+
+ def test04(self):
+ self.qtsnk = qtgui.time_sink_f(1024, 1, "Test", 1)
+
+ def test05(self):
+ self.qtsnk = qtgui.freq_sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test", 1)
+
+ def test06(self):
+ self.qtsnk = qtgui.freq_sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test", 1)
+
+ def test07(self):
+ self.qtsnk = qtgui.waterfall_sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test")
+
+ def test08(self):
+ self.qtsnk = qtgui.waterfall_sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS,
+ 0, 1, "Test")
+
+ def test09(self):
+ self.qtsnk = qtgui.const_sink_c(1024, "Test", 1)
if __name__ == '__main__':
gr_unittest.run(test_qtgui, "test_qtgui.xml")
diff --git a/gr-qtgui/swig/CMakeLists.txt b/gr-qtgui/swig/CMakeLists.txt
index e84035b9f7..74545f4cfe 100644
--- a/gr-qtgui/swig/CMakeLists.txt
+++ b/gr-qtgui/swig/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Free Software Foundation, Inc.
+# Copyright 2010-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -28,6 +28,7 @@ set(GR_SWIG_TARGET_DEPS core_swig)
set(GR_SWIG_INCLUDE_DIRS
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${GR_QTGUI_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
${QWT_INCLUDE_DIRS}
)
@@ -46,10 +47,6 @@ GR_SWIG_INSTALL(
install(FILES
qtgui_swig.i
- qtgui_sink_c.i
- qtgui_sink_f.i
- qtgui_time_sink_c.i
- qtgui_time_sink_f.i
${CMAKE_CURRENT_BINARY_DIR}/qtgui_swig_doc.i
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
COMPONENT "qtgui_swig"
diff --git a/gr-qtgui/swig/__init__.py b/gr-qtgui/swig/__init__.py
index e52e326cb3..8f3fca0f4a 100644
--- a/gr-qtgui/swig/__init__.py
+++ b/gr-qtgui/swig/__init__.py
@@ -21,4 +21,8 @@
# The presence of this file turns this directory into a Python package
+'''
+Provides a GUI interface using the Qt backend.
+'''
+
from qtgui_swig import *
diff --git a/gr-qtgui/swig/qtgui_sink_c.i b/gr-qtgui/swig/qtgui_sink_c.i
deleted file mode 100644
index 65e7d1c82b..0000000000
--- a/gr-qtgui/swig/qtgui_sink_c.i
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,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 "gnuradio.i"
-
-%{
-#include <qtgui_sink_c.h>
-%}
-
-GR_SWIG_BLOCK_MAGIC(qtgui,sink_c)
-
-qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype,
- double fc=0, double bw=1.0,
- const std::string &name="Display",
- bool plotfreq=true, bool plotwaterfall=true,
- bool plottime=true, bool plotconst=true,
- QWidget *parent=NULL);
-
-class qtgui_sink_c : public gr_block
-{
-private:
- friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
- qtgui_sink_c (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
-
-public:
- void exec_();
- PyObject* pyqwidget();
-
- void set_frequency_range(const double centerfreq,
- const double bandwidth);
- void set_time_domain_axis(double min, double max);
- void set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax);
- void set_frequency_axis(double min, double max);
- void set_constellation_pen_size(int size);
- void set_update_time(double t);
-};
diff --git a/gr-qtgui/swig/qtgui_sink_f.i b/gr-qtgui/swig/qtgui_sink_f.i
deleted file mode 100644
index b07eaa9ec8..0000000000
--- a/gr-qtgui/swig/qtgui_sink_f.i
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009,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 "gnuradio.i"
-
-%{
-#include <qtgui_sink_f.h>
-%}
-
-GR_SWIG_BLOCK_MAGIC(qtgui,sink_f)
-
-qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype,
- double fc=0, double bw=0.0,
- const std::string &name="Display",
- bool plotfreq=true, bool plotwaterfall=true,
- bool plottime=true, bool plotconst=false,
- QWidget *parent=NULL);
-
-class qtgui_sink_f : public gr_block
-{
-private:
- friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
- qtgui_sink_f (int fftsize, int wintype,
- double fc, double bw,
- const std::string &name,
- bool plotfreq, bool plotwaterfall,
- bool plottime, bool plotconst,
- QWidget *parent);
-
-public:
- void exec_();
- PyObject* pyqwidget();
-
- void set_frequency_range(const double centerfreq,
- const double bandwidth);
- void set_time_domain_axis(double min, double max);
- void set_constellation_axis(double xmin, double xmax,
- double ymin, double ymax);
- void set_frequency_axis(double min, double max);
- void set_constellation_pen_size(int size);
- void set_update_time(double t);
-};
diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i
index 0d77e22da8..9821ccf440 100644
--- a/gr-qtgui/swig/qtgui_swig.i
+++ b/gr-qtgui/swig/qtgui_swig.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,19 +20,41 @@
* Boston, MA 02110-1301, USA.
*/
+#define QTGUI_API
+
%include "gnuradio.i"
//load generated python docstrings
%include "qtgui_swig_doc.i"
%{
-#include "qtgui_sink_c.h"
-#include "qtgui_sink_f.h"
-#include "qtgui_time_sink_c.h"
-#include "qtgui_time_sink_f.h"
+#include "qtgui/sink_c.h"
+#include "qtgui/sink_f.h"
+#include "qtgui/time_sink_c.h"
+#include "qtgui/time_sink_f.h"
+#include "qtgui/freq_sink_c.h"
+#include "qtgui/freq_sink_f.h"
+#include "qtgui/const_sink_c.h"
+#include "qtgui/waterfall_sink_c.h"
+#include "qtgui/waterfall_sink_f.h"
%}
-%include "qtgui_sink_c.i"
-%include "qtgui_sink_f.i"
-%include "qtgui_time_sink_c.i"
-%include "qtgui_time_sink_f.i"
+%include "qtgui/sink_c.h"
+%include "qtgui/sink_f.h"
+%include "qtgui/time_sink_c.h"
+%include "qtgui/time_sink_f.h"
+%include "qtgui/freq_sink_c.h"
+%include "qtgui/freq_sink_f.h"
+%include "qtgui/const_sink_c.h"
+%include "qtgui/waterfall_sink_c.h"
+%include "qtgui/waterfall_sink_f.h"
+
+GR_SWIG_BLOCK_MAGIC2(qtgui, sink_c);
+GR_SWIG_BLOCK_MAGIC2(qtgui, sink_f);
+GR_SWIG_BLOCK_MAGIC2(qtgui, time_sink_c);
+GR_SWIG_BLOCK_MAGIC2(qtgui, time_sink_f);
+GR_SWIG_BLOCK_MAGIC2(qtgui, freq_sink_c);
+GR_SWIG_BLOCK_MAGIC2(qtgui, freq_sink_f);
+GR_SWIG_BLOCK_MAGIC2(qtgui, const_sink_c);
+GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_c);
+GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_f);
diff --git a/gr-qtgui/swig/qtgui_time_sink_c.i b/gr-qtgui/swig/qtgui_time_sink_c.i
deleted file mode 100644
index b78ca5386b..0000000000
--- a/gr-qtgui/swig/qtgui_time_sink_c.i
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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 "gnuradio.i"
-
-%{
-#include <qtgui_time_sink_c.h>
-%}
-
-GR_SWIG_BLOCK_MAGIC(qtgui,time_sink_c)
-
-qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnections=1,
- QWidget *parent=NULL);
-
-class qtgui_time_sink_c : public gr_sync_block
-{
-private:
- friend qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent);
- qtgui_time_sink_c(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent=NULL);
-
-public:
- void exec_();
- PyObject* pyqwidget();
-
- void set_time_domain_axis(double min, double max);
- void set_update_time(double t);
- void set_title(int which, const std::string &title);
- void set_color(int which, const std::string &color);
-};
diff --git a/gr-qtgui/swig/qtgui_time_sink_f.i b/gr-qtgui/swig/qtgui_time_sink_f.i
deleted file mode 100644
index 9d59f93643..0000000000
--- a/gr-qtgui/swig/qtgui_time_sink_f.i
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- c++ -*- */
-/*
- * 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 "gnuradio.i"
-
-%{
-#include <qtgui_time_sink_f.h>
-%}
-
-GR_SWIG_BLOCK_MAGIC(qtgui,time_sink_f)
-
-qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnections=1,
- QWidget *parent=NULL);
-
-class qtgui_time_sink_f : public gr_sync_block
-{
-private:
- friend qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent);
- qtgui_time_sink_f(int size, double bw,
- const std::string &name,
- int nconnections,
- QWidget *parent=NULL);
-
-public:
- void exec_();
- PyObject* pyqwidget();
-
- void set_time_domain_axis(double min, double max);
- void set_update_time(double t);
- void set_title(int which, const std::string &title);
- void set_color(int which, const std::string &color);
-};