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.txt61
-rwxr-xr-xgr-qtgui/apps/gr_constellation_plot187
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_b78
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_c79
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_f79
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_i79
-rwxr-xr-xgr-qtgui/apps/gr_psd_plot_s78
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_b79
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_c79
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_f79
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_i79
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot_s79
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_b74
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_c76
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_f74
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_i74
-rwxr-xr-xgr-qtgui/apps/gr_time_plot_s74
-rwxr-xr-xgr-qtgui/apps/gr_time_raster_b78
-rwxr-xr-xgr-qtgui/apps/gr_time_raster_f78
-rw-r--r--gr-qtgui/apps/grc_qt_example.grc184
-rw-r--r--gr-qtgui/apps/plot_base.py164
-rw-r--r--gr-qtgui/apps/plot_constellation_form.py74
-rw-r--r--gr-qtgui/apps/plot_form.py401
-rw-r--r--gr-qtgui/apps/plot_psd_base.py163
-rw-r--r--gr-qtgui/apps/plot_psd_form.py98
-rw-r--r--gr-qtgui/apps/plot_spectrogram_base.py168
-rw-r--r--gr-qtgui/apps/plot_spectrogram_form.py164
-rw-r--r--gr-qtgui/apps/plot_time_base.py184
-rw-r--r--gr-qtgui/apps/plot_time_form.py79
-rw-r--r--gr-qtgui/apps/plot_time_raster_base.py183
-rw-r--r--gr-qtgui/apps/plot_time_raster_form.py157
-rwxr-xr-xgr-qtgui/apps/qt_digital.py65
-rwxr-xr-xgr-qtgui/apps/uhd_display.py15
-rw-r--r--gr-qtgui/doc/qtgui.dox47
-rw-r--r--gr-qtgui/examples/dark.qss115
-rwxr-xr-xgr-qtgui/examples/pyqt_const_c.py185
-rwxr-xr-xgr-qtgui/examples/pyqt_example_c.py37
-rwxr-xr-xgr-qtgui/examples/pyqt_example_f.py27
-rwxr-xr-xgr-qtgui/examples/pyqt_freq_c.py194
-rwxr-xr-xgr-qtgui/examples/pyqt_freq_f.py184
-rwxr-xr-xgr-qtgui/examples/pyqt_time_c.py57
-rwxr-xr-xgr-qtgui/examples/pyqt_time_f.py33
-rwxr-xr-xgr-qtgui/examples/pyqt_time_raster_b.py86
-rwxr-xr-xgr-qtgui/examples/pyqt_time_raster_f.py86
-rwxr-xr-xgr-qtgui/examples/pyqt_waterfall_c.py196
-rwxr-xr-xgr-qtgui/examples/pyqt_waterfall_f.py182
-rw-r--r--gr-qtgui/grc/qtgui_block_tree.xml49
-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.xml107
-rw-r--r--gr-qtgui/grc/qtgui_entry.xml1
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml139
-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.xml33
-rw-r--r--gr-qtgui/grc/qtgui_tab_widget.xml1
-rw-r--r--gr-qtgui/grc/qtgui_time_raster_x.xml108
-rw-r--r--gr-qtgui/grc/qtgui_time_sink_x.xml38
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml124
-rw-r--r--gr-qtgui/include/qtgui/CMakeLists.txt (renamed from gr-qtgui/include/CMakeLists.txt)23
-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.h97
-rw-r--r--gr-qtgui/include/qtgui/freq_sink_c.h112
-rw-r--r--gr-qtgui/include/qtgui/freq_sink_f.h111
-rw-r--r--gr-qtgui/include/qtgui/sink_c.h97
-rw-r--r--gr-qtgui/include/qtgui/sink_f.h97
-rw-r--r--gr-qtgui/include/qtgui/time_raster_sink_b.h120
-rw-r--r--gr-qtgui/include/qtgui/time_raster_sink_f.h117
-rw-r--r--gr-qtgui/include/qtgui/time_sink_c.h105
-rw-r--r--gr-qtgui/include/qtgui/time_sink_f.h103
-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.h118
-rw-r--r--gr-qtgui/include/qtgui/waterfall_sink_f.h117
-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.txt62
-rw-r--r--gr-qtgui/lib/ConstellationDisplayPlot.cc241
-rw-r--r--gr-qtgui/lib/ConstellationDisplayPlot.h71
-rw-r--r--gr-qtgui/lib/DisplayPlot.cc416
-rw-r--r--gr-qtgui/lib/DisplayPlot.h287
-rw-r--r--gr-qtgui/lib/FrequencyDisplayPlot.cc591
-rw-r--r--gr-qtgui/lib/FrequencyDisplayPlot.h155
-rw-r--r--gr-qtgui/lib/SpectrumGUIClass.cc150
-rw-r--r--gr-qtgui/lib/SpectrumGUIClass.h60
-rw-r--r--gr-qtgui/lib/TimeDomainDisplayPlot.cc299
-rw-r--r--gr-qtgui/lib/TimeDomainDisplayPlot.h71
-rw-r--r--gr-qtgui/lib/TimeRasterDisplayPlot.cc570
-rw-r--r--gr-qtgui/lib/TimeRasterDisplayPlot.h104
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.cc612
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.h110
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.cc357
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.h106
-rw-r--r--gr-qtgui/lib/constellationdisplayform.cc122
-rw-r--r--gr-qtgui/lib/constellationdisplayform.h62
-rw-r--r--gr-qtgui/lib/displayform.cc376
-rw-r--r--gr-qtgui/lib/displayform.h131
-rw-r--r--gr-qtgui/lib/form_menus.h1001
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.cc470
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.h130
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.cc473
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.h129
-rw-r--r--gr-qtgui/lib/freqdisplayform.cc175
-rw-r--r--gr-qtgui/lib/freqdisplayform.h74
-rw-r--r--gr-qtgui/lib/plot_raster.cc350
-rw-r--r--gr-qtgui/lib/plot_raster.h93
-rw-r--r--gr-qtgui/lib/plot_waterfall.cc22
-rw-r--r--gr-qtgui/lib/plot_waterfall.h22
-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.cc192
-rw-r--r--gr-qtgui/lib/qtgui_time_sink_f.cc190
-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.cc341
-rw-r--r--gr-qtgui/lib/sink_c_impl.h108
-rw-r--r--gr-qtgui/lib/sink_f_impl.cc326
-rw-r--r--gr-qtgui/lib/sink_f_impl.h106
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.cc241
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.h155
-rw-r--r--gr-qtgui/lib/spectrumdisplayform.cc386
-rw-r--r--gr-qtgui/lib/spectrumdisplayform.h78
-rw-r--r--gr-qtgui/lib/spectrumdisplayform.ui92
-rw-r--r--gr-qtgui/lib/timeRasterGlobalData.cc240
-rw-r--r--gr-qtgui/lib/timeRasterGlobalData.h78
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.cc441
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.h124
-rw-r--r--gr-qtgui/lib/time_raster_sink_c_impl.cc222
-rw-r--r--gr-qtgui/lib/time_raster_sink_c_impl.h87
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.cc436
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.h123
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.cc377
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.h110
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.cc375
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.h110
-rw-r--r--gr-qtgui/lib/timedisplayform.cc166
-rw-r--r--gr-qtgui/lib/timedisplayform.h62
-rw-r--r--gr-qtgui/lib/timerasterdisplayform.cc251
-rw-r--r--gr-qtgui/lib/timerasterdisplayform.h89
-rw-r--r--gr-qtgui/lib/waterfallGlobalData.cc64
-rw-r--r--gr-qtgui/lib/waterfallGlobalData.h40
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc446
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.h125
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc447
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.h126
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.cc268
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.h95
-rw-r--r--gr-qtgui/python/__init__.py2
-rwxr-xr-xgr-qtgui/python/qa_qtgui.py56
-rw-r--r--gr-qtgui/swig/CMakeLists.txt8
-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.i50
-rw-r--r--gr-qtgui/swig/qtgui_time_sink_c.i56
-rw-r--r--gr-qtgui/swig/qtgui_time_sink_f.i56
158 files changed, 19984 insertions, 3634 deletions
diff --git a/gr-qtgui/CMakeLists.txt b/gr-qtgui/CMakeLists.txt
index d7d889e93a..a2485b8921 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}
)
@@ -104,7 +108,7 @@ CPACK_COMPONENT("qtgui_swig"
########################################################################
# Add subdirectories
########################################################################
-add_subdirectory(include)
+add_subdirectory(include/qtgui)
add_subdirectory(lib)
add_subdirectory(doc)
if(ENABLE_PYTHON)
@@ -112,6 +116,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..05accc64d2
--- /dev/null
+++ b/gr-qtgui/apps/CMakeLists.txt
@@ -0,0 +1,61 @@
+# 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_base.py
+ plot_psd_base.py
+ plot_spectrogram_base.py
+ plot_time_base.py
+ plot_time_raster_base.py
+ plot_form.py
+ plot_constellation_form.py
+ plot_psd_form.py
+ plot_spectrogram_form.py
+ plot_time_form.py
+ plot_time_raster_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_time_raster_f
+ gr_time_raster_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..0687443218
--- /dev/null
+++ b/gr-qtgui/apps/gr_constellation_plot
@@ -0,0 +1,187 @@
+#!/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_constellation_form import *
+ from gnuradio.qtgui.plot_base import *
+except ImportError:
+ from plot_constellation_form import *
+ from plot_base import *
+
+class my_top_block(gr.top_block):
+ def __init__(self, filelist, start, nsamples, max_nsamples):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = 0
+ self._center_freq = 0
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._nsamps = nsamples
+ self._auto_scale = True
+
+ self._y_min = -20
+ self._y_max = 20
+ self._y_range = 4
+ self._y_value = 2
+ self.gui_y_axis = None
+
+ 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()
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for f in filelist:
+ data,_min,_max = read_samples_c(f, self._start, self._nsamps)
+ self.srcs.append(gr.vector_source_c(data))
+
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_line_label(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.enable_menu(False)
+
+ # 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,_min,_max = read_samples_c(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 set_y_axis(self, y_min, y_max):
+ y_min = -y_max
+ self.gui_snk.set_y_axis(y_min, y_max)
+ self.gui_snk.set_x_axis(y_min, y_max)
+ return y_min, y_max
+
+ def auto_scale(self, state):
+ if(state > 0):
+ self.set_y_axis(self._data_min, self._data_max)
+ self._auto_scale = True
+ self._y_value = self._data_max
+ self._y_range = self._data_max - self._data_min
+ self._y_min = 10*self._data_min
+ self._y_max = 10*self._data_max
+
+ if(self.gui_y_axis):
+ self.gui_y_axis(self._data_min, self._data_max)
+ else:
+ self._auto_scale = False
+
+
+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=1000000,
+ help="Set the number of samples to display [default=%default]")
+ 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 = plot_constellation_form(tb, 'GNU Radio Constellation Plot', 10000.0)
+ for n in xrange(tb._nsigs):
+ main_box._style_edit[n].setCurrentIndex(0)
+ 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..44ea997e6e
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_b
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_psd_base as plot_base
+except ImportError:
+ import plot_psd_base as plot_base
+
+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 psd_plot_b(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0, auto_scale=True):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_b
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_chars_to_float
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of bytes."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = psd_plot_b(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average)
+
+ main_box = plot_base.plot_psd_form(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..f2789ef34b
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_c
@@ -0,0 +1,79 @@
+#!/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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_psd_base as plot_base
+except ImportError:
+ import plot_psd_base as plot_base
+
+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 psd_plot_c(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_c
+ self.dsize = gr.sizeof_gr_complex
+ self.src_type = gr.vector_source_c
+ self.gui_snk = qtgui.freq_sink_c(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of complex floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = psd_plot_c(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average)
+
+ main_box = plot_base.plot_psd_form(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..c6b70baf27
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_f
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_psd_base as plot_base
+except ImportError:
+ import plot_psd_base as plot_base
+
+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 psd_plot_f(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0, auto_scale=True):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_f
+ self.dsize = gr.sizeof_float
+ self.src_type = gr.vector_source_f
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = psd_plot_f(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average)
+
+ main_box = plot_base.plot_psd_form(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..b2ae5f7103
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_i
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_psd_base as plot_base
+except ImportError:
+ import plot_psd_base as plot_base
+
+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 psd_plot_i(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0, auto_scale=True):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_i
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_ints_to_float
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of integers."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = psd_plot_i(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average)
+
+ main_box = plot_base.plot_psd_form(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..07a573b56a
--- /dev/null
+++ b/gr-qtgui/apps/gr_psd_plot_s
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_psd_base as plot_base
+except ImportError:
+ import plot_psd_base as plot_base
+
+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 psd_plot_s(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0, auto_scale=True):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_s
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_shorts_to_float
+ self.gui_snk = qtgui.freq_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio PSD Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the PSDs of a list of files. Files are a binary list of shorts."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = psd_plot_s(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average)
+
+ main_box = plot_base.plot_psd_form(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..82a443038e
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_b
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+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 spectrogram_plot_b(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_b
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_chars_to_float
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of chars."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = spectrogram_plot_b(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+
+ main_box = plot_base.plot_spectrogram_form(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_spectrogram_plot_c b/gr-qtgui/apps/gr_spectrogram_plot_c
new file mode 100755
index 0000000000..059f65cd99
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_c
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+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 spectrogram_plot_c(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_c
+ self.dsize = gr.sizeof_gr_complex
+ self.src_type = gr.vector_source_c
+ self.gui_snk = qtgui.waterfall_sink_c(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of complex floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = spectrogram_plot_c(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+
+ main_box = plot_base.plot_spectrogram_form(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..be9c981532
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_f
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+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 spectrogram_plot_f(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_f
+ self.dsize = gr.sizeof_float
+ self.src_type = gr.vector_source_f
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = spectrogram_plot_f(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+
+ main_box = plot_base.plot_spectrogram_form(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_spectrogram_plot_i b/gr-qtgui/apps/gr_spectrogram_plot_i
new file mode 100755
index 0000000000..27a1bebd45
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_i
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+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 spectrogram_plot_i(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_i
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_ints_to_float
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of ints."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = spectrogram_plot_i(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+
+ main_box = plot_base.plot_spectrogram_form(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_spectrogram_plot_s b/gr-qtgui/apps/gr_spectrogram_plot_s
new file mode 100755
index 0000000000..b41b650a64
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot_s
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import filter
+import scipy
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+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 spectrogram_plot_s(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+
+ self.read_samples = plot_base.read_samples_s
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_shorts_to_float
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of shorts."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = spectrogram_plot_s(filelist,
+ options.center_frequency, options.sample_rate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+
+ main_box = plot_base.plot_spectrogram_form(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_b b/gr-qtgui/apps/gr_time_plot_b
new file mode 100755
index 0000000000..20522095de
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_b
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_base as plot_base
+except ImportError:
+ import plot_time_base as plot_base
+
+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 plot_time_b(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self.read_samples = plot_base.read_samples_b
+ self.dsize = gr.sizeof_float # already converted
+ self.src_type = plot_base.source_chars_to_float
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of chars."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_b(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_form(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..a7c39a24b9
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_c
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_base as plot_base
+except ImportError:
+ import plot_time_base as plot_base
+
+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 plot_time_c(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self.read_samples = plot_base.read_samples_c
+ self.dsize = gr.sizeof_gr_complex
+ self.src_type = gr.vector_source_c
+ self.gui_snk = qtgui.time_sink_c(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ self._nsigs *= 2 # complex plots have real/imag
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of complex floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_c(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot', 10000.0)
+ 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..9b29709b10
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_f
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_base as plot_base
+except ImportError:
+ import plot_time_base as plot_base
+
+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 plot_time_f(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self.read_samples = plot_base.read_samples_f
+ self.dsize = gr.sizeof_float
+ self.src_type = gr.vector_source_f
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_f(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot', 10000.0)
+ 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..04229de0cd
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_i
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_base as plot_base
+except ImportError:
+ import plot_time_base as plot_base
+
+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 plot_time_i(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self.read_samples = plot_base.read_samples_i
+ self.dsize = gr.sizeof_float # already converted
+ self.src_type = plot_base.source_ints_to_float
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of integers."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_i(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_form(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..cc4a8a7812
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_plot_s
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_base as plot_base
+except ImportError:
+ import plot_time_base as plot_base
+
+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 plot_time_s(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self.read_samples = plot_base.read_samples_s
+ self.dsize = gr.sizeof_float # already converted
+ self.src_type = plot_base.source_shorts_to_float
+ self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate,
+ "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of shorts."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_s(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_form(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_raster_b b/gr-qtgui/apps/gr_time_raster_b
new file mode 100755
index 0000000000..a326a126c4
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_raster_b
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_raster_base as plot_base
+except ImportError:
+ import plot_time_raster_base as plot_base
+
+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 plot_time_raster_b(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ nrows, ncols,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self._nrows = nrows
+ self._ncols = ncols
+ self.read_samples = plot_base.read_samples_b
+ self.dsize = gr.sizeof_char
+ self.src_type = gr.vector_source_b
+ self.gui_snk = qtgui.time_raster_sink_b(self._samp_rate, self._nrows, self._ncols,
+ [], [], "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of chars."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_raster_b(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ options.nrows, options.ncols,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_raster_form(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_raster_f b/gr-qtgui/apps/gr_time_raster_f
new file mode 100755
index 0000000000..a6cb897c0b
--- /dev/null
+++ b/gr-qtgui/apps/gr_time_raster_f
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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 scipy
+
+try:
+ import gnuradio.qtgui.plot_time_raster_base as plot_base
+except ImportError:
+ import plot_time_raster_base as plot_base
+
+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 plot_time_raster_f(plot_base.plot_base):
+ def __init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ nrows, ncols,
+ auto_scale):
+ plot_base.plot_base.__init__(self, filelist, samp_rate,
+ start, nsamples, max_nsamples,
+ auto_scale)
+ self._nrows = nrows
+ self._ncols = ncols
+ self.read_samples = plot_base.read_samples_f
+ self.dsize = gr.sizeof_float
+ self.src_type = gr.vector_source_f
+ self.gui_snk = qtgui.time_raster_sink_f(self._samp_rate, self._nrows, self._ncols,
+ [], [], "GNU Radio Time Plot", self._nsigs)
+ self.setup()
+
+def main():
+ description = "Plots a list of files on a scope plot. Files are a binary list of floats."
+ (options, args) = plot_base.setup_options(description)
+
+ filelist = list(args)
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+
+ tb = plot_time_raster_f(filelist, options.sample_rate,
+ options.start, options.nsamples, max_nsamples,
+ options.nrows, options.ncols,
+ not options.no_auto_scale)
+
+ main_box = plot_base.plot_time_raster_form(tb, 'GNU Radio Time Plot', 10000.0)
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gr-qtgui/apps/grc_qt_example.grc b/gr-qtgui/apps/grc_qt_example.grc
index 170cd546ad..320320edcc 100644
--- a/gr-qtgui/apps/grc_qt_example.grc
+++ b/gr-qtgui/apps/grc_qt_example.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Sun Apr 10 16:49:13 2011</timestamp>
+ <timestamp>Sat Nov 10 14:58:46 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,6 +44,10 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
@@ -80,37 +84,6 @@
</param>
</block>
<block>
- <key>gr_throttle</key>
- <param>
- <key>id</key>
- <value>gr_throttle_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(511, 96)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
<key>variable_qtgui_range</key>
<param>
<key>id</key>
@@ -166,49 +139,6 @@
</param>
</block>
<block>
- <key>gr_sig_source_x</key>
- <param>
- <key>id</key>
- <value>gr_sig_source_x_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>samp_rate</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>waveform</key>
- <value>gr.GR_COS_WAVE</value>
- </param>
- <param>
- <key>freq</key>
- <value>freq</value>
- </param>
- <param>
- <key>amp</key>
- <value>amp</value>
- </param>
- <param>
- <key>offset</key>
- <value>0</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(295, 64)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
<key>variable_qtgui_range</key>
<param>
<key>id</key>
@@ -319,10 +249,41 @@
</param>
</block>
<block>
- <key>gr_channel_model</key>
+ <key>blocks_throttle</key>
<param>
<key>id</key>
- <value>gr_channel_model_0</value>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(511, 96)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>channels_channel_model</key>
+ <param>
+ <key>id</key>
+ <value>channels_channel_model_0</value>
</param>
<param>
<key>_enabled</key>
@@ -346,11 +307,11 @@
</param>
<param>
<key>seed</key>
- <value>42</value>
+ <value>-42</value>
</param>
<param>
<key>_coordinate</key>
- <value>(727, 64)</value>
+ <value>(724, 64)</value>
</param>
<param>
<key>_rotation</key>
@@ -392,6 +353,10 @@
<value>samp_rate</value>
</param>
<param>
+ <key>rate</key>
+ <value>10</value>
+ </param>
+ <param>
<key>plotfreq</key>
<value>True</value>
</param>
@@ -412,8 +377,55 @@
<value></value>
</param>
<param>
+ <key>freqchangevar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(958, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>analog.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>amp</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(958, 72)</value>
+ <value>(297, 64)</value>
</param>
<param>
<key>_rotation</key>
@@ -421,20 +433,20 @@
</param>
</block>
<connection>
- <source_block_id>gr_sig_source_x_0</source_block_id>
- <sink_block_id>gr_throttle_0</sink_block_id>
+ <source_block_id>analog_sig_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_throttle_0</source_block_id>
- <sink_block_id>gr_channel_model_0</sink_block_id>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>qtgui_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>qtgui_sink_x_0</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-qtgui/apps/plot_base.py b/gr-qtgui/apps/plot_base.py
new file mode 100644
index 0000000000..52c888cff3
--- /dev/null
+++ b/gr-qtgui/apps/plot_base.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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, blocks
+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_constellation_form import *
+ from gnuradio.qtgui.plot_psd_form import *
+ from gnuradio.qtgui.plot_spectrogram_form import *
+ from gnuradio.qtgui.plot_time_form import *
+ from gnuradio.qtgui.plot_time_raster_form import *
+except ImportError:
+ from plot_constellation_form import *
+ from plot_psd_form import *
+ from plot_spectrogram_form import *
+ from plot_time_form import *
+ from plot_time_raster_form import *
+
+def read_samples(filename, start, in_size, min_size, dtype, dtype_size):
+ # Read in_size number of samples from file
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*dtype_size, 0)
+ data = scipy.fromfile(fhandle, dtype=dtype, count=in_size)
+ data_min = 1.1*data.min()
+ data_max = 1.1*data.max()
+ data = data.tolist()
+ fhandle.close()
+
+ if(min_size > 0):
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+ else:
+ # If we have to, append 0's to create min_size samples of data
+ if(len(data) < min_size):
+ data += (min_size - len(data)) * [dtype(0)]
+
+
+ return data, data_min, data_max
+
+def read_samples_f(filename, start, in_size, min_size=0):
+ return read_samples(filename, start, in_size, min_size,
+ scipy.float32, gr.sizeof_float)
+
+def read_samples_i(filename, start, in_size, min_size=0):
+ return read_samples(filename, start, in_size, min_size,
+ scipy.int32, gr.sizeof_int)
+
+def read_samples_s(filename, start, in_size, min_size=0):
+ return read_samples(filename, start, in_size, min_size,
+ scipy.int16, gr.sizeof_short)
+
+def read_samples_b(filename, start, in_size, min_size=0):
+ d,mn,mx = read_samples(filename, start, in_size, min_size,
+ scipy.int8, gr.sizeof_char)
+
+ # Bit of a hack since we want to read the data as signed ints, but
+ # the gr.vector_source_b will only accept unsigned. We read in as
+ # signed, do our min/max and things on that, then convert here.
+ d = scipy.array(d, dtype=scipy.uint8).tolist()
+ return d,mn,mx
+
+def read_samples_c(filename, start, in_size, min_size=0):
+ # Complex samples are handled differently
+ fhandle = open(filename, 'r')
+ fhandle.seek(start*gr.sizeof_gr_complex, 0)
+ data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size)
+ data_min = 1.1*float(min(data.real.min(), data.imag.min()))
+ data_max = 1.1*float(max(data.real.max(), data.imag.max()))
+ data = data.tolist()
+ fhandle.close()
+
+ if(min_size > 0):
+ if(len(data) < in_size):
+ print "Warning: read in {0} samples but asked for {1} samples.".format(
+ len(data), in_size)
+ else:
+ # 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, data_min, data_max
+
+class source_ints_to_float(gr.hier_block2):
+ def __init__(self, data):
+ gr.hier_block2.__init__(self, "ints_to_floats",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(1, 1, gr.sizeof_float))
+ self.src = gr.vector_source_i(data)
+ self.cvt = blocks.int_to_float()
+ self.connect(self.src, self.cvt, self)
+
+ def set_data(self, data):
+ self.src.set_data(data)
+
+class source_shorts_to_float(gr.hier_block2):
+ def __init__(self, data):
+ gr.hier_block2.__init__(self, "shorts_to_floats",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(1, 1, gr.sizeof_float))
+ self.src = gr.vector_source_s(data)
+ self.cvt = blocks.short_to_float()
+ self.connect(self.src, self.cvt, self)
+
+ def set_data(self, data):
+ self.src.set_data(data)
+
+class source_chars_to_float(gr.hier_block2):
+ def __init__(self, data):
+ gr.hier_block2.__init__(self, "chars_to_floats",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(1, 1, gr.sizeof_float))
+ self.src = gr.vector_source_b(data)
+ self.cvt = blocks.char_to_float()
+ self.connect(self.src, self.cvt, self)
+
+ def set_data(self, data):
+ self.src.set_data(data)
+
+def find_max_nsamples(filelist):
+ # 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)
+ return max_nsamples
diff --git a/gr-qtgui/apps/plot_constellation_form.py b/gr-qtgui/apps/plot_constellation_form.py
new file mode 100644
index 0000000000..d5e37bb33c
--- /dev/null
+++ b/gr-qtgui/apps/plot_constellation_form.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import sys
+from gnuradio import filter
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_from import plot_form
+except ImportError:
+ from plot_form import plot_form
+
+class plot_constellation_form(plot_form):
+ def __init__(self, top_block, title='', scale=1):
+ plot_form.__init__(self, top_block, title, scale)
+
+ self.right_col_layout = QtGui.QVBoxLayout()
+ self.right_col_form = QtGui.QFormLayout()
+ self.right_col_layout.addLayout(self.right_col_form)
+ self.layout.addLayout(self.right_col_layout, 1,4,1,1)
+
+ # Constellation resizing scales x and y together.
+ # Set the bar to go from 0.001 to max
+ self.ybar.setMinimum(1)
+ self.ybar.setMaximum(self._pos_scale*self.top_block._y_max)
+ self.ybar.setSingleStep(self._pos_scale*(max(self.top_block._y_range/10, 0.010)))
+ self.ybar.setPageStep(self._pos_scale*(max(self.top_block._y_range/2, 0.010)))
+
+ self.auto_scale = QtGui.QCheckBox("Auto Scale", self)
+ if(self.top_block._auto_scale):
+ self.auto_scale.setChecked(self.top_block._auto_scale)
+ self.set_auto_scale(self.top_block._auto_scale)
+ self.connect(self.auto_scale, QtCore.SIGNAL("stateChanged(int)"),
+ self.set_auto_scale)
+ self.right_col_layout.addWidget(self.auto_scale)
+
+ self.ybar.setValue(1000*self.top_block._y_value)
+
+ self.add_line_control(self.right_col_layout)
+
+ def set_auto_scale(self, state):
+ if(state):
+ self.top_block.auto_scale(True)
+ else:
+ self.top_block.auto_scale(False)
+
+ def update_samp_rate(self):
+ pass
+
diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py
new file mode 100644
index 0000000000..2e1a6c5f77
--- /dev/null
+++ b/gr-qtgui/apps/plot_form.py
@@ -0,0 +1,401 @@
+#!/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)
+
+import numpy
+
+class plot_form(QtGui.QWidget):
+ def __init__(self, top_block, title='', scale=1):
+ QtGui.QWidget.__init__(self, None)
+
+ self._start = 0
+ self._end = 0
+ self._y_min = 0
+ self._y_max = 0
+ self._pos_scale = scale
+
+ self.top_block = top_block
+ self.top_block.gui_y_axis = self.gui_y_axis
+
+ self.setWindowTitle(title)
+
+ self.layout = QtGui.QGridLayout(self)
+ self.layout.addWidget(top_block.get_gui(), 1,2,1,2)
+
+ # Create a save action
+ self.save_act = QtGui.QAction("Save", self)
+ self.save_act.setShortcut(QtGui.QKeySequence.Save)
+ self.connect(self.save_act, QtCore.SIGNAL("triggered()"),
+ self.save_figure)
+
+ # Create an exit action
+ self.exit_act = QtGui.QAction("Exit", self)
+ self.exit_act.setShortcut(QtGui.QKeySequence.Close)
+ self.connect(self.exit_act, QtCore.SIGNAL("triggered()"),
+ self.close)
+
+ # Create a menu for the window
+ self.menu = QtGui.QToolBar("Menu", self)
+ self.menu.addAction(self.save_act)
+ self.menu.addAction(self.exit_act)
+
+ self.layout.addWidget(self.menu, 0,0,1,4)
+
+ self.left_col_form = QtGui.QFormLayout()
+ self.layout.addLayout(self.left_col_form, 1,0,1,1)
+ self.layout.setColumnStretch(0, 0)
+ self.layout.setColumnStretch(2, 1)
+
+ # Create Edit boxes for X-axis start/stop
+ self.size_val = QtGui.QIntValidator(0, top_block._max_nsamps, self)
+
+ self.start_edit = QtGui.QLineEdit(self)
+ self.start_edit.setMinimumWidth(100)
+ self.start_edit.setMaximumWidth(100)
+ self.start_edit.setText(QtCore.QString("%1").arg(top_block._start))
+ self.start_edit.setValidator(self.size_val)
+ self.left_col_form.addRow("Start:", self.start_edit)
+ self.connect(self.start_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_xaxis_pos)
+
+ end = top_block._start + top_block._nsamps
+ self.end_edit = QtGui.QLineEdit(self)
+ self.end_edit.setMinimumWidth(100)
+ self.end_edit.setMaximumWidth(100)
+ self.end_edit.setText(QtCore.QString("%1").arg(end))
+ self.end_edit.setValidator(self.size_val)
+ self.left_col_form.addRow("End:", self.end_edit)
+ self.connect(self.end_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_xaxis_pos)
+
+ # Create a slider to move the position in the file
+ self.posbar = QtGui.QSlider(QtCore.Qt.Horizontal, self)
+ self.posbar.setMaximum(self.top_block._max_nsamps)
+ self.posbar.setPageStep(self.top_block._nsamps)
+ self.connect(self.posbar, QtCore.SIGNAL("valueChanged(int)"),
+ self.update_xaxis_slider)
+ self.layout.addWidget(self.posbar, 2,2,1,1)
+
+ # Create Edit boxes for Y-axis min/max
+ self.y_max_edit = QtGui.QLineEdit(self)
+ self.y_max_edit.setMinimumWidth(100)
+ self.y_max_edit.setMaximumWidth(100)
+ self.left_col_form.addRow("Y Max:", self.y_max_edit)
+ self.connect(self.y_max_edit, QtCore.SIGNAL("editingFinished()"),
+ self.update_yaxis_pos)
+
+ self.y_min_edit = QtGui.QLineEdit(self)
+ self.y_min_edit.setMinimumWidth(100)
+ self.y_min_edit.setMaximumWidth(100)
+ self.left_col_form.addRow("Y Min:", self.y_min_edit)
+ self.connect(self.y_min_edit, QtCore.SIGNAL("editingFinished()"),
+ self.update_yaxis_pos)
+
+ self.grid_check = QtGui.QCheckBox("Grid", self)
+ self.connect(self.grid_check, QtCore.SIGNAL("stateChanged(int)"),
+ self.set_grid_check)
+ self.left_col_form.addWidget(self.grid_check)
+
+ # Create a slider to move the plot's y-axis offset
+ _ymax = numpy.int32(min(numpy.iinfo(numpy.int32).max, self.top_block._y_max))
+ _ymin = numpy.int32(max(numpy.iinfo(numpy.int32).min, self.top_block._y_min))
+ _yrng = numpy.int32(min(numpy.iinfo(numpy.int32).max, self.top_block._y_range))
+ _yval = numpy.int32(min(numpy.iinfo(numpy.int32).max, self.top_block._y_value))
+ self.ybar = QtGui.QSlider(QtCore.Qt.Vertical, self)
+ self.ybar.setMinimum(self._pos_scale*_ymin)
+ self.ybar.setMaximum(self._pos_scale*_ymax)
+ self.ybar.setSingleStep(self._pos_scale*(_yrng/10))
+ self.ybar.setPageStep(self._pos_scale*(_yrng/2))
+ self.ybar.setValue(self._pos_scale*_ymax)
+ self.connect(self.ybar, QtCore.SIGNAL("valueChanged(int)"),
+ self.update_yaxis_slider)
+ self.layout.addWidget(self.ybar, 1,1,1,1)
+
+ self.gui_y_axis(top_block._y_value-top_block._y_range, top_block._y_value)
+
+ # Create an edit box for the Sample Rate
+ sr = top_block._samp_rate
+ self.samp_rate_edit = QtGui.QLineEdit(self)
+ self.samp_rate_edit.setMinimumWidth(100)
+ self.samp_rate_edit.setMaximumWidth(100)
+ self.samp_rate_edit.setText(QtCore.QString("%1").arg(sr))
+ self.left_col_form.addRow("Sample Rate:", self.samp_rate_edit)
+ self.connect(self.samp_rate_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_samp_rate)
+
+ # Create an edit box for the center frequency
+ freq = top_block._center_freq
+ self.freq_edit = QtGui.QLineEdit(self)
+ self.freq_edit.setMinimumWidth(100)
+ self.freq_edit.setMaximumWidth(100)
+ self.freq_edit.setText(QtCore.QString("%1").arg(freq))
+ self.left_col_form.addRow("Frequency:", self.freq_edit)
+ self.connect(self.freq_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_samp_rate)
+
+ self.resize(1000, 500)
+
+ def add_line_control(self, layout):
+ self._line_tabs = QtGui.QTabWidget()
+
+ self._line_pages = []
+ self._line_forms = []
+ self._label_edit = []
+ self._size_edit = []
+ self._color_edit = []
+ self._style_edit = []
+ self._marker_edit = []
+ self._alpha_edit = []
+ for n in xrange(self.top_block._nsigs):
+ self._line_pages.append(QtGui.QDialog())
+ self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1]))
+
+ label = self.top_block.gui_snk.line_label(n)
+ self._label_edit.append(QtGui.QLineEdit(self))
+ self._label_edit[-1].setMinimumWidth(125)
+ self._label_edit[-1].setMaximumWidth(125)
+ self._label_edit[-1].setText(QtCore.QString("%1").arg(label))
+ self._line_forms[-1].addRow("Label:", self._label_edit[-1])
+ self.connect(self._label_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_label)
+
+ width_val = QtGui.QIntValidator(1, 20, self)
+ self._size_edit.append(QtGui.QLineEdit(self))
+ self._size_edit[-1].setValidator(width_val)
+ self._size_edit[-1].setMinimumWidth(100)
+ self._size_edit[-1].setMaximumWidth(100)
+ self._size_edit[-1].setText(QtCore.QString("%1").arg(1))
+ self._line_forms[-1].addRow("Width:", self._size_edit[-1])
+ self.connect(self._size_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_size)
+
+ color = self.top_block.gui_snk.line_color(n)
+ self._color_edit.append(QtGui.QLineEdit(self))
+ self._color_edit[-1].setMinimumWidth(100)
+ self._color_edit[-1].setMaximumWidth(100)
+ self._color_edit[-1].setText(QtCore.QString("%1").arg(color))
+ self._line_forms[-1].addRow("Color:", self._color_edit[-1])
+ self.connect(self._color_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_color)
+
+ self._qtstyles = {"None": QtCore.Qt.NoPen,
+ "Solid": QtCore.Qt.SolidLine,
+ "Dash": QtCore.Qt.DashLine,
+ "Dot": QtCore.Qt.DotLine,
+ "DashDot": QtCore.Qt.DashDotLine,
+ "DashDotDot": QtCore.Qt.DashDotDotLine}
+ self._style_edit.append(QtGui.QComboBox(self))
+ self._style_edit[-1].addItems(["None", "Solid", "Dash",
+ "Dot", "DashDot", "DashDotDot"])
+ self._style_edit[-1].setCurrentIndex(1)
+ self._line_forms[-1].addRow("Style:", self._style_edit[-1])
+ self.connect(self._style_edit[-1],
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_line_style)
+
+ # A bit dangerous, this. If QWT ever changes the lineup,
+ # we will have to adjust this, too. But we also can't
+ # really rely on PyQwt right now.
+ self._qwtmarkers = {"None": -1,
+ "Circle": 0,
+ "Rectangle": 1,
+ "Diamond": 2,
+ "Triangle": 3,
+ "Down Triangle": 4,
+ "Left Triangle": 6,
+ "Right Triangle": 7,
+ "Cross": 8,
+ "X-Cross": 9,
+ "Horiz. Line": 10,
+ "Vert. Line": 11,
+ "Star 1": 12,
+ "Star 2": 13,
+ "Hexagon": 14}
+ self._marker_edit.append(QtGui.QComboBox(self))
+ self._marker_edit[-1].addItems(["None", "Circle", "Rectangle", "Diamond",
+ "Triangle", "Down Triangle", "Left Triangle",
+ "Right Triangle", "Cross", "X-Cross",
+ "Horiz. Line", "Vert. Line", "Star 1",
+ "Star 2", "Hexagon"])
+ self._line_forms[-1].addRow("Marker:", self._marker_edit[-1])
+ self.connect(self._marker_edit[-1],
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_line_marker)
+
+ alpha_val = QtGui.QDoubleValidator(0, 1.0, 2, self)
+ alpha_val.setTop(1.0)
+ alpha = self.top_block.gui_snk.line_alpha(n)
+ self._alpha_edit.append(QtGui.QLineEdit(self))
+ self._alpha_edit[-1].setMinimumWidth(50)
+ self._alpha_edit[-1].setMaximumWidth(100)
+ self._alpha_edit[-1].setText(QtCore.QString("%1").arg(alpha))
+ self._alpha_edit[-1].setValidator(alpha_val)
+ self._line_forms[-1].addRow("Alpha:", self._alpha_edit[-1])
+ self.connect(self._alpha_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_alpha)
+
+ self._line_tabs.addTab(self._line_pages[-1], "{0}".format(label))
+
+ layout.addWidget(self._line_tabs)
+
+ def update_line_label(self):
+ index = self._line_tabs.currentIndex()
+ label = self._label_edit[index].text()
+ self._line_tabs.setTabText(index, label)
+ self.top_block.gui_snk.set_line_label(index, str(label))
+
+ def update_line_size(self):
+ index = self._line_tabs.currentIndex()
+ width = self._size_edit[index].text().toUInt()[0]
+ self.top_block.gui_snk.set_line_width(index, width)
+ self.update_line_alpha()
+
+ def update_line_color(self):
+ index = self._line_tabs.currentIndex()
+ color = str(self._color_edit[index].text())
+ self.top_block.gui_snk.set_line_color(index, color)
+ self.update_line_alpha()
+
+ def update_line_style(self, s_index):
+ index = self._line_tabs.currentIndex()
+ style_str = self._style_edit[index].itemText(s_index)
+ style = self._qtstyles[str(style_str)]
+ self.top_block.gui_snk.set_line_style(index, int(style))
+
+ def update_line_marker(self, m_index):
+ index = self._line_tabs.currentIndex()
+ marker_str = self._marker_edit[index].itemText(m_index)
+ marker = self._qwtmarkers[str(marker_str)]
+ self.top_block.gui_snk.set_line_marker(index, int(marker))
+
+ def update_line_alpha(self):
+ index = self._line_tabs.currentIndex()
+ alpha = self._alpha_edit[index].text().toDouble()[0]
+ self.top_block.gui_snk.set_line_alpha(index, alpha)
+
+ def update_xaxis_pos(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
+ self.posbar.setPageStep(self.top_block._nsamps)
+ self.posbar.setValue(self._start)
+
+ def update_xaxis_slider(self, value):
+ self._start = value
+ self._end = value + self.posbar.pageStep()
+
+ self.start_edit.setText("{0}".format(self._start))
+ self.end_edit.setText("{0}".format(self._end))
+
+ if(value != self.top_block._max_nsamps):
+ self.top_block.reset(self._start, self.posbar.pageStep())
+
+ def update_yaxis_pos(self):
+ if(not self.top_block._auto_scale):
+ newmin = self.y_min_edit.text().toDouble()[0]
+ newmax = self.y_max_edit.text().toDouble()[0]
+ if(newmin != self._y_min or newmax != self._y_max):
+ self._y_min = newmin
+ self._y_max = newmax
+ self.top_block._y_range = newmax - newmin
+ self.top_block.set_y_axis(self._y_min, self._y_max)
+ self.ybar.setValue(self._y_max*self._pos_scale)
+ else:
+ self.y_min_edit.setText("{0:.2f}".format(self._y_min))
+ self.y_max_edit.setText("{0:.2f}".format(self._y_max))
+
+ def update_yaxis_slider(self, value):
+ if(not self.top_block._auto_scale):
+ value = value/self._pos_scale
+ self.top_block._y_value = value
+ self._y_min = value - self.top_block._y_range
+ self._y_max = value
+
+ ret = self.top_block.set_y_axis(self._y_min, self._y_max)
+ if(ret):
+ self._y_min = ret[0]
+ self._y_max = ret[1]
+
+ self.gui_y_axis(self._y_min, self._y_max)
+ else:
+ self.ybar.setValue(self._y_max*self._pos_scale)
+
+ def update_samp_rate(self):
+ sr = self.samp_rate_edit.text().toDouble()[0]
+ fr = self.freq_edit.text().toDouble()[0]
+ self.top_block.gui_snk.set_frequency_range(fr, sr)
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def gui_y_axis(self, ymin, ymax):
+ self.y_min_edit.setText("{0:.2f}".format(ymin))
+ self.y_max_edit.setText("{0:.2f}".format(ymax))
+ self._y_min = ymin
+ self._y_max = ymax
+ self.ybar.setValue(self._pos_scale*ymax)
+
+ def set_grid_check(self, state):
+ if(state):
+ self.top_block.gui_snk.enable_grid(True)
+ else:
+ self.top_block.gui_snk.enable_grid(False)
+
+ def save_figure(self):
+ qpix = QtGui.QPixmap.grabWidget(self.top_block.pyWin)
+ types = "JPEG file (*.jpg);;" + \
+ "Portable Network Graphics file (*.png);;" + \
+ "Bitmap file (*.bmp);;" + \
+ "TIFF file (*.tiff)"
+ filebox = QtGui.QFileDialog(self, "Save Image", "./", types)
+ filebox.setViewMode(QtGui.QFileDialog.Detail)
+ if(filebox.exec_()):
+ filename = filebox.selectedFiles()[0]
+ filetype = filebox.selectedNameFilter()
+ else:
+ return
+
+ if(filetype.contains(".jpg")):
+ qpix.save(filename, "JPEG");
+ elif(filetype.contains(".png")):
+ qpix.save(filename, "PNG");
+ elif(filetype.contains(".bmp")):
+ qpix.save(filename, "BMP");
+ elif(filetype.contains(".tiff")):
+ qpix.save(filename, "TIFF");
+ else:
+ qpix.save(filename, "JPEG");
diff --git a/gr-qtgui/apps/plot_psd_base.py b/gr-qtgui/apps/plot_psd_base.py
new file mode 100644
index 0000000000..a4a6cb871a
--- /dev/null
+++ b/gr-qtgui/apps/plot_psd_base.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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, blocks
+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 *
+ from gnuradio.qtgui.plot_base import *
+except ImportError:
+ from plot_form import *
+ from plot_base import *
+
+class plot_base(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
+ self._nsamps = nsamples
+ self._auto_scale = False
+
+ self._y_min = -200
+ self._y_max = 400
+ self._y_range = 130
+ self._y_value = 10
+
+ self._is_setup = False
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ def setup(self):
+ self.skip = gr.skiphead(self.dsize, self._start)
+
+ n = 0
+ self.srcs = list()
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for f in self._filelist:
+ data,_min,_max = self.read_samples(f, self._start,
+ self._nsamps, self._psd_size)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ self.srcs.append(self.src_type(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_line_label(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.enable_menu(False)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ self._is_setup = True
+
+ def is_setup(self):
+ return self._is_setup
+
+ def set_y_axis(self, y_min, y_max):
+ self.gui_snk.set_y_axis(y_min, y_max)
+ return y_min, y_max
+
+ def get_gui(self):
+ if(self.is_setup()):
+ return self.pyWin
+ else:
+ return None
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for s,f in zip(self.srcs, self._filelist):
+ data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ s.set_data(data)
+
+ self.start()
+
+def setup_options(desc):
+ parser = OptionParser(option_class=eng_option, description=desc,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=1000000,
+ 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)
+ return (options,args)
diff --git a/gr-qtgui/apps/plot_psd_form.py b/gr-qtgui/apps/plot_psd_form.py
new file mode 100644
index 0000000000..262734bd67
--- /dev/null
+++ b/gr-qtgui/apps/plot_psd_form.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import sys
+from gnuradio import filter
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_from import plot_form
+except ImportError:
+ from plot_form import plot_form
+
+class plot_psd_form(plot_form):
+ def __init__(self, top_block, title=''):
+ plot_form.__init__(self, top_block, title)
+
+ self.right_col_layout = QtGui.QVBoxLayout()
+ self.right_col_form = QtGui.QFormLayout()
+ self.right_col_layout.addLayout(self.right_col_form)
+ self.layout.addLayout(self.right_col_layout, 1,4,1,1)
+
+ self.psd_size_val = QtGui.QIntValidator(0, 2**18, self)
+ self.psd_size_edit = QtGui.QLineEdit(self)
+ self.psd_size_edit.setMinimumWidth(50)
+ self.psd_size_edit.setMaximumWidth(100)
+ self.psd_size_edit.setText(QtCore.QString("%1").arg(top_block._psd_size))
+ self.psd_size_edit.setValidator(self.psd_size_val)
+ self.right_col_form.addRow("FFT:", self.psd_size_edit)
+ self.connect(self.psd_size_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_psd_size)
+
+ self.psd_win_combo = QtGui.QComboBox(self)
+ self.psd_win_combo.addItems(["None", "Hamming", "Hann", "Blackman",
+ "Rectangular", "Kaiser", "Blackman-harris"])
+ self.psd_win_combo.setCurrentIndex(self.top_block.gui_snk.fft_window()+1)
+ self.right_col_form.addRow("Window:", self.psd_win_combo)
+ self.connect(self.psd_win_combo,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_psd_win)
+
+ self.psd_avg_val = QtGui.QDoubleValidator(0, 1.0, 4, self)
+ self.psd_avg_edit = QtGui.QLineEdit(self)
+ self.psd_avg_edit.setMinimumWidth(50)
+ self.psd_avg_edit.setMaximumWidth(100)
+ self.psd_avg_edit.setText(QtCore.QString("%1").arg(top_block._avg))
+ self.psd_avg_edit.setValidator(self.psd_avg_val)
+ self.right_col_form.addRow("Average:", self.psd_avg_edit)
+ self.connect(self.psd_avg_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_psd_avg)
+
+ self.add_line_control(self.right_col_layout)
+
+ def update_psd_size(self):
+ newpsdsize = self.psd_size_edit.text().toInt()[0]
+ if(newpsdsize != self.top_block._psd_size):
+ self.top_block.gui_snk.set_fft_size(newpsdsize)
+ self.top_block._psd_size = newpsdsize
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def update_psd_win(self, index):
+ self.top_block.gui_snk.set_fft_window(index-1)
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def update_psd_avg(self):
+ newpsdavg = self.psd_avg_edit.text().toDouble()[0]
+ if(newpsdavg != self.top_block._avg):
+ self.top_block.gui_snk.set_fft_average(newpsdavg)
+ self.top_block._avg = newpsdavg
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
diff --git a/gr-qtgui/apps/plot_spectrogram_base.py b/gr-qtgui/apps/plot_spectrogram_base.py
new file mode 100644
index 0000000000..adfbfd032f
--- /dev/null
+++ b/gr-qtgui/apps/plot_spectrogram_base.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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, blocks
+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 *
+ from gnuradio.qtgui.plot_base import *
+except ImportError:
+ from plot_form import *
+ from plot_base import *
+
+class plot_base(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
+ self._nsamps = nsamples
+ self._auto_scale = False
+
+ self._y_min = -200
+ self._y_max = 400
+ self._y_range = 130
+ self._y_value = 10
+
+ self._is_setup = False
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ def setup(self):
+ self.skip = gr.skiphead(self.dsize, self._start)
+
+ n = 0
+ self.srcs = list()
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for f in self._filelist:
+ data,_min,_max = self.read_samples(f, self._start,
+ self._nsamps, self._psd_size)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ self.srcs.append(self.src_type(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ self.gui_snk.set_line_label(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.enable_menu(False)
+ self.gui_snk.set_fft_average(self._avg)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ self._is_setup = True
+
+ def is_setup(self):
+ return self._is_setup
+
+ def set_y_axis(self, y_min, y_max):
+ self.gui_snk.set_intensity_range(y_min, y_max)
+ return y_min, y_max
+
+ def get_gui(self):
+ if(self.is_setup()):
+ return self.pyWin
+ else:
+ return None
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+ self.gui_snk.clear_data()
+
+ self._start = newstart
+ self._nsamps = newnsamps
+
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for s,f in zip(self.srcs, self._filelist):
+ data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ s.set_data(data)
+
+ self.start()
+
+def setup_options(desc):
+ parser = OptionParser(option_class=eng_option, description=desc,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=1000000,
+ help="Set the number of samples to display [default=%default]")
+ 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)
+
+ return (options, args)
+
diff --git a/gr-qtgui/apps/plot_spectrogram_form.py b/gr-qtgui/apps/plot_spectrogram_form.py
new file mode 100644
index 0000000000..7f8361e6b1
--- /dev/null
+++ b/gr-qtgui/apps/plot_spectrogram_form.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import sys
+from gnuradio import filter
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_from import plot_form
+except ImportError:
+ from plot_form import plot_form
+
+class plot_spectrogram_form(plot_form):
+ def __init__(self, top_block, title=''):
+ plot_form.__init__(self, top_block, title)
+
+ self.right_col_layout = QtGui.QVBoxLayout()
+ self.right_col_form = QtGui.QFormLayout()
+ self.right_col_layout.addLayout(self.right_col_form)
+ self.layout.addLayout(self.right_col_layout, 1,4,1,1)
+
+ self.psd_size_val = QtGui.QIntValidator(0, 2**18, self)
+ self.psd_size_edit = QtGui.QLineEdit(self)
+ self.psd_size_edit.setMinimumWidth(50)
+ self.psd_size_edit.setMaximumWidth(100)
+ self.psd_size_edit.setText(QtCore.QString("%1").arg(top_block._psd_size))
+ self.psd_size_edit.setValidator(self.psd_size_val)
+ self.right_col_form.addRow("FFT Size:", self.psd_size_edit)
+ self.connect(self.psd_size_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_psd_size)
+
+ self.psd_win_combo = QtGui.QComboBox(self)
+ self.psd_win_combo.addItems(["None", "Hamming", "Hann", "Blackman",
+ "Rectangular", "Kaiser", "Blackman-harris"])
+ self.psd_win_combo.setCurrentIndex(self.top_block.gui_snk.fft_window()+1)
+ self.right_col_form.addRow("Window:", self.psd_win_combo)
+ self.connect(self.psd_win_combo,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_psd_win)
+
+ self.psd_avg_val = QtGui.QDoubleValidator(0, 1.0, 4, self)
+ self.psd_avg_edit = QtGui.QLineEdit(self)
+ self.psd_avg_edit.setMinimumWidth(50)
+ self.psd_avg_edit.setMaximumWidth(100)
+ self.psd_avg_edit.setText(QtCore.QString("%1").arg(top_block._avg))
+ self.psd_avg_edit.setValidator(self.psd_avg_val)
+ self.right_col_form.addRow("Average:", self.psd_avg_edit)
+ self.connect(self.psd_avg_edit, QtCore.SIGNAL("returnPressed()"),
+ self.update_psd_avg)
+
+ self.autoscale_button = QtGui.QPushButton("Auto Scale", self)
+ self.autoscale_button.setMaximumWidth(100)
+ self.right_col_layout.addWidget(self.autoscale_button)
+ self.connect(self.autoscale_button, QtCore.SIGNAL("clicked()"),
+ self.spectrogram_auto_scale)
+
+ self.add_spectrogram_control(self.right_col_layout)
+
+ def update_psd_size(self):
+ newpsdsize = self.psd_size_edit.text().toInt()[0]
+ if(newpsdsize != self.top_block._psd_size):
+ self.top_block.gui_snk.set_fft_size(newpsdsize)
+ self.top_block._psd_size = newpsdsize
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def update_psd_win(self, index):
+ self.top_block.gui_snk.set_fft_window(index-1)
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def update_psd_avg(self):
+ newpsdavg = self.psd_avg_edit.text().toDouble()[0]
+ if(newpsdavg != self.top_block._avg):
+ self.top_block.gui_snk.set_fft_average(newpsdavg)
+ self.top_block._avg = newpsdavg
+ self.top_block.reset(self.top_block._start,
+ self.top_block._nsamps)
+
+ def add_spectrogram_control(self, layout):
+ self._line_tabs = QtGui.QTabWidget()
+
+ self._line_pages = []
+ self._line_forms = []
+ self._label_edit = []
+ self._size_edit = []
+ self._color_edit = []
+ self._style_edit = []
+ self._marker_edit = []
+ self._alpha_edit = []
+ for n in xrange(self.top_block._nsigs):
+ self._line_pages.append(QtGui.QDialog())
+ self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1]))
+
+ label = self.top_block.gui_snk.line_label(n)
+ self._label_edit.append(QtGui.QLineEdit(self))
+ self._label_edit[-1].setMinimumWidth(125)
+ self._label_edit[-1].setMaximumWidth(125)
+ self._label_edit[-1].setText(QtCore.QString("%1").arg(label))
+ self._line_forms[-1].addRow("Label:", self._label_edit[-1])
+ self.connect(self._label_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_label)
+
+ self._qtcolormaps = ["Multi Color", "White Hot",
+ "Black Hot", "Incandescent"]
+ self._color_edit.append(QtGui.QComboBox(self))
+ self._color_edit[-1].addItems(self._qtcolormaps)
+ self._line_forms[-1].addRow("Color Map:", self._color_edit[-1])
+ self.connect(self._color_edit[-1],
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_color_map)
+
+ alpha_val = QtGui.QDoubleValidator(0, 1.0, 2, self)
+ alpha_val.setTop(1.0)
+ alpha = self.top_block.gui_snk.line_alpha(n)
+ self._alpha_edit.append(QtGui.QLineEdit(self))
+ self._alpha_edit[-1].setMinimumWidth(50)
+ self._alpha_edit[-1].setMaximumWidth(100)
+ self._alpha_edit[-1].setText(QtCore.QString("%1").arg(alpha))
+ self._alpha_edit[-1].setValidator(alpha_val)
+ self._line_forms[-1].addRow("Alpha:", self._alpha_edit[-1])
+ self.connect(self._alpha_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_alpha)
+
+ self._line_tabs.addTab(self._line_pages[-1], "{0}".format(label))
+
+ layout.addWidget(self._line_tabs)
+
+ def update_color_map(self, c_index):
+ index = self._line_tabs.currentIndex()
+ self.top_block.gui_snk.set_color_map(index, c_index)
+ self.update_line_alpha()
+
+ def spectrogram_auto_scale(self):
+ self.top_block.gui_snk.auto_scale()
+ _min = self.top_block.gui_snk.min_intensity(0)
+ _max = self.top_block.gui_snk.max_intensity(0)
+ if(self.gui_y_axis):
+ self.gui_y_axis(_min, _max)
diff --git a/gr-qtgui/apps/plot_time_base.py b/gr-qtgui/apps/plot_time_base.py
new file mode 100644
index 0000000000..c80bace1b6
--- /dev/null
+++ b/gr-qtgui/apps/plot_time_base.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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, blocks
+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 *
+ from gnuradio.qtgui.plot_base import *
+except ImportError:
+ from plot_form import *
+ from plot_base import *
+
+class plot_base(gr.top_block):
+ def __init__(self, filelist, samp_rate, start,
+ nsamples, max_nsamples,
+ auto_scale):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._center_freq = 0
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._auto_scale = auto_scale
+ self._nsamps = nsamples
+ self._is_setup = False
+
+ self._y_min = -20
+ self._y_max = 20
+ self._y_range = 2
+ self._y_value = 1
+ self.gui_y_axis = None
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ def setup(self):
+ self.skip = gr.skiphead(self.dsize, self._start)
+
+ n = 0
+ self.srcs = list()
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for f in self._filelist:
+ data,_min,_max = self.read_samples(f, self._start, self._nsamps)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ self.srcs.append(self.src_type(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ if(type(self.gui_snk) == qtgui.time_sink_c_sptr):
+ self.gui_snk.set_line_label(n, "Re{{{0}}}".format(fname))
+ self.gui_snk.set_line_label(n+1, "Im{{{0}}}".format(fname))
+ n += 2
+ else:
+ self.gui_snk.set_line_label(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.enable_menu(False)
+ self.auto_scale(self._auto_scale)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ self._is_setup = True
+
+ def is_setup(self):
+ return self._is_setup
+
+ def set_y_axis(self, y_min, y_max):
+ self.gui_snk.set_y_axis(y_min, y_max)
+ return y_min, y_max
+
+ def get_gui(self):
+ if(self.is_setup()):
+ return self.pyWin
+ else:
+ return None
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for s,f in zip(self.srcs, self._filelist):
+ data,_min,_max = self.read_samples(f, self._start, newnsamps)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self.auto_scale(self._auto_scale)
+
+ self._nsamps = newnsamps
+ self.gui_snk.set_nsamps(self._nsamps)
+
+ self.start()
+
+ def auto_scale(self, state):
+ if(state > 0):
+ self.gui_snk.set_y_axis(self._data_min, self._data_max)
+ self._auto_scale = True
+ self._y_value = self._data_max
+ self._y_range = self._data_max - self._data_min
+ self._y_min = 10*self._data_min
+ self._y_max = 10*self._data_max
+
+ if(self.gui_y_axis):
+ self.gui_y_axis(self._data_min, self._data_max)
+ else:
+ self._auto_scale = False
+
+def setup_options(desc):
+ parser = OptionParser(option_class=eng_option, description=desc,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=1000000,
+ help="Set the number of samples to display [default=%default]")
+ 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("", "--no-auto-scale", action="store_true", default=False,
+ help="Do not auto-scale the plot [default=%default]")
+ (options,args) = parser.parse_args()
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+ return (options,args)
+
diff --git a/gr-qtgui/apps/plot_time_form.py b/gr-qtgui/apps/plot_time_form.py
new file mode 100644
index 0000000000..30701c8d37
--- /dev/null
+++ b/gr-qtgui/apps/plot_time_form.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import sys
+from gnuradio import filter
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_from import plot_form
+except ImportError:
+ from plot_form import plot_form
+
+class plot_time_form(plot_form):
+ def __init__(self, top_block, title='', scale=1):
+ plot_form.__init__(self, top_block, title, scale)
+
+ self.right_col_layout = QtGui.QVBoxLayout()
+ self.right_col_form = QtGui.QFormLayout()
+ self.right_col_layout.addLayout(self.right_col_form)
+ self.layout.addLayout(self.right_col_layout, 1,4,1,1)
+
+ self.auto_scale = QtGui.QCheckBox("Auto Scale", self)
+ if(self.top_block._auto_scale):
+ self.auto_scale.setChecked(self.top_block._auto_scale)
+ self.connect(self.auto_scale, QtCore.SIGNAL("stateChanged(int)"),
+ self.set_auto_scale)
+ self.right_col_layout.addWidget(self.auto_scale)
+
+ self.stem = QtGui.QCheckBox("Stem", self)
+ self.connect(self.stem, QtCore.SIGNAL("stateChanged(int)"),
+ self.enable_stem)
+ self.right_col_layout.addWidget(self.stem)
+
+ self.add_line_control(self.right_col_layout)
+
+ def set_auto_scale(self, state):
+ if(state):
+ self.top_block.auto_scale(True)
+ else:
+ self.top_block.auto_scale(False)
+
+ def enable_stem(self, state):
+ self.top_block.gui_snk.enable_stem_plot(state)
+ if(state):
+ index = self._qwtmarkers['Circle']+1
+ else:
+ index = self._qwtmarkers['None']+1
+ for n in xrange(self.top_block._nsigs):
+ self._marker_edit[n].setCurrentIndex(index)
+
+ def update_samp_rate(self):
+ sr = self.samp_rate_edit.text().toDouble()[0]
+ self.top_block.gui_snk.set_samp_rate(sr)
+
diff --git a/gr-qtgui/apps/plot_time_raster_base.py b/gr-qtgui/apps/plot_time_raster_base.py
new file mode 100644
index 0000000000..ff3cc2869d
--- /dev/null
+++ b/gr-qtgui/apps/plot_time_raster_base.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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, blocks
+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 *
+ from gnuradio.qtgui.plot_base import *
+except ImportError:
+ from plot_form import *
+ from plot_base import *
+
+class plot_base(gr.top_block):
+ def __init__(self, filelist, samp_rate, start,
+ nsamples, max_nsamples,
+ auto_scale):
+ gr.top_block.__init__(self)
+
+ self._filelist = filelist
+ self._samp_rate = samp_rate
+ self._center_freq = 0
+ self._start = start
+ self._max_nsamps = max_nsamples
+ self._nsigs = len(self._filelist)
+ self._auto_scale = auto_scale
+ self._nsamps = nsamples
+ self._is_setup = False
+
+ self._y_min = -20
+ self._y_max = 20
+ self._y_range = 2
+ self._y_value = 1
+ self.gui_y_axis = None
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ def setup(self):
+ self.skip = gr.skiphead(self.dsize, self._start)
+
+ n = 0
+ self.srcs = list()
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for f in self._filelist:
+ data,_min,_max = self.read_samples(f, self._start, self._nsamps)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ self.srcs.append(self.src_type(data))
+
+ # Set default labels based on file names
+ fname = f.split("/")[-1]
+ #self.gui_snk.set_line_label(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.enable_menu(False)
+ self.auto_scale(self._auto_scale)
+
+ # Get Python Qt references
+ pyQt = self.gui_snk.pyqwidget()
+ self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
+
+ self._is_setup = True
+
+ def is_setup(self):
+ return self._is_setup
+
+ def set_y_axis(self, y_min, y_max):
+ if(not self._auto_scale):
+ self.gui_snk.set_intensity_range(y_min, y_max)
+ return y_min, y_max
+ else:
+ return None
+
+ def get_gui(self):
+ if(self.is_setup()):
+ return self.pyWin
+ else:
+ return None
+
+ def reset(self, newstart, newnsamps):
+ self.stop()
+ self.wait()
+
+ self._start = newstart
+
+ self._data_min = sys.maxint
+ self._data_max = -sys.maxint - 1
+ for s,f in zip(self.srcs, self._filelist):
+ data,_min,_max = self.read_samples(f, self._start, newnsamps)
+ if(_min < self._data_min):
+ self._data_min = _min
+ if(_max > self._data_max):
+ self._data_max = _max
+
+ s.set_data(data)
+ if(len(data) < newnsamps):
+ newnsamps = len(data)
+
+ self.auto_scale(self._auto_scale)
+ self._nsamps = newnsamps
+ self.start()
+
+ def auto_scale(self, state):
+ if(state > 0):
+ self.gui_snk.set_intensity_range(self._data_min, self._data_max)
+ self._auto_scale = True
+ self._y_value = self._data_max
+ self._y_range = self._data_max - self._data_min
+ self._y_min = 10*self._data_min
+ self._y_max = 10*self._data_max
+
+ if(self.gui_y_axis):
+ self.gui_y_axis(self._data_min, self._data_max)
+ else:
+ self._auto_scale = False
+
+def setup_options(desc):
+ parser = OptionParser(option_class=eng_option, description=desc,
+ conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=1000000,
+ help="Set the number of samples to display [default=%default]")
+ parser.add_option("-S", "--start", type="int", default=0,
+ help="Starting sample number [default=%default]")
+ parser.add_option("-C", "--ncols", type="int", default=100,
+ help="Number of columns [default=%default]")
+ parser.add_option("-R", "--nrows", type="int", default=100,
+ help="Number of rows [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("", "--no-auto-scale", action="store_true", default=False,
+ help="Do not auto-scale the plot [default=%default]")
+ (options,args) = parser.parse_args()
+ if(len(args) < 1):
+ parser.print_help()
+ sys.exit(0)
+ return (options,args)
+
diff --git a/gr-qtgui/apps/plot_time_raster_form.py b/gr-qtgui/apps/plot_time_raster_form.py
new file mode 100644
index 0000000000..32d93744d5
--- /dev/null
+++ b/gr-qtgui/apps/plot_time_raster_form.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import sys, math
+from gnuradio import filter
+
+try:
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ from gnuradio.qtgui.plot_from import plot_form
+except ImportError:
+ from plot_form import plot_form
+
+class plot_time_raster_form(plot_form):
+ def __init__(self, top_block, title='', scale=1):
+ plot_form.__init__(self, top_block, title, scale)
+
+ self.right_col_layout = QtGui.QVBoxLayout()
+ self.right_col_form = QtGui.QFormLayout()
+ self.right_col_layout.addLayout(self.right_col_form)
+ self.layout.addLayout(self.right_col_layout, 1,4,1,1)
+
+ self.auto_scale = QtGui.QCheckBox("Auto Scale", self)
+ if(self.top_block._auto_scale):
+ self.auto_scale.setChecked(self.top_block._auto_scale)
+ self.connect(self.auto_scale, QtCore.SIGNAL("stateChanged(int)"),
+ self.set_auto_scale)
+ self.right_col_layout.addWidget(self.auto_scale)
+
+ self.ncols_edit = QtGui.QLineEdit(self)
+ self.ncols_edit.setMinimumWidth(100)
+ self.ncols_edit.setMaximumWidth(100)
+ self.ncols_edit.setText(QtCore.QString("%1").arg(top_block._ncols))
+ self.right_col_form.addRow("Num. Cols.", self.ncols_edit)
+ self.connect(self.ncols_edit, QtCore.SIGNAL("returnPressed()"),
+ self.ncols_update)
+
+ self.nrows_edit = QtGui.QLineEdit(self)
+ self.nrows_edit.setMinimumWidth(100)
+ self.nrows_edit.setMaximumWidth(100)
+ self.nrows_edit.setText(QtCore.QString("%1").arg(top_block._nrows))
+ self.right_col_form.addRow("Num. Rows.", self.nrows_edit)
+ self.connect(self.nrows_edit, QtCore.SIGNAL("returnPressed()"),
+ self.nrows_update)
+
+
+ self.add_raster_control(self.right_col_layout)
+
+ def add_raster_control(self, layout):
+ self._line_tabs = QtGui.QTabWidget()
+
+ self._line_pages = []
+ self._line_forms = []
+ self._label_edit = []
+ self._size_edit = []
+ self._color_edit = []
+ self._style_edit = []
+ self._marker_edit = []
+ self._alpha_edit = []
+ for n in xrange(self.top_block._nsigs):
+ self._line_pages.append(QtGui.QDialog())
+ self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1]))
+
+ label = self.top_block.gui_snk.line_label(n)
+ self._label_edit.append(QtGui.QLineEdit(self))
+ self._label_edit[-1].setMinimumWidth(125)
+ self._label_edit[-1].setMaximumWidth(125)
+ self._label_edit[-1].setText(QtCore.QString("%1").arg(label))
+ self._line_forms[-1].addRow("Label:", self._label_edit[-1])
+ self.connect(self._label_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_label)
+
+ self._qtcolormaps = ["Multi Color", "White Hot",
+ "Black Hot", "Incandescent"]
+ self._color_edit.append(QtGui.QComboBox(self))
+ self._color_edit[-1].addItems(self._qtcolormaps)
+ self._color_edit[-1].setCurrentIndex(1)
+ self._line_forms[-1].addRow("Color Map:", self._color_edit[-1])
+ self.connect(self._color_edit[-1],
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.update_color_map)
+
+ alpha_val = QtGui.QDoubleValidator(0, 1.0, 2, self)
+ alpha_val.setTop(1.0)
+ alpha = self.top_block.gui_snk.line_alpha(n)
+ self._alpha_edit.append(QtGui.QLineEdit(self))
+ self._alpha_edit[-1].setMinimumWidth(50)
+ self._alpha_edit[-1].setMaximumWidth(100)
+ self._alpha_edit[-1].setText(QtCore.QString("%1").arg(alpha))
+ self._alpha_edit[-1].setValidator(alpha_val)
+ self._line_forms[-1].addRow("Alpha:", self._alpha_edit[-1])
+ self.connect(self._alpha_edit[-1], QtCore.SIGNAL("returnPressed()"),
+ self.update_line_alpha)
+
+ self._line_tabs.addTab(self._line_pages[-1], "{0}".format(label))
+
+ layout.addWidget(self._line_tabs)
+
+ def update_color_map(self, c_index):
+ index = self._line_tabs.currentIndex()
+ self.top_block.gui_snk.set_color_map(index, c_index)
+ self.update_line_alpha()
+
+ def set_auto_scale(self, state):
+ if(state):
+ self.top_block.auto_scale(True)
+ else:
+ self.top_block.auto_scale(False)
+
+ def update_samp_rate(self):
+ sr = self.samp_rate_edit.text().toDouble()[0]
+ self.top_block.gui_snk.set_samp_rate(sr)
+
+ nsamps = int(math.ceil((self.top_block._nrows+1)*self.top_block._ncols))
+ self.top_block.reset(self._start, nsamps)
+
+ def ncols_update(self):
+ n = self.ncols_edit.text().toDouble()[0]
+ self.top_block.gui_snk.set_num_cols(n)
+ self.top_block._ncols = n
+
+ nsamps = int(math.ceil((self.top_block._nrows+1)*n))
+ self.top_block.reset(self._start, nsamps)
+
+ def nrows_update(self):
+ n = self.nrows_edit.text().toInt()[0]
+ self.top_block.gui_snk.set_num_rows(n)
+ self.top_block._nrows = n
+
+ nsamps = int(math.ceil(self.top_block._ncols*(n+1)))
+ self.top_block.reset(self._start, nsamps)
+
+
diff --git a/gr-qtgui/apps/qt_digital.py b/gr-qtgui/apps/qt_digital.py
index 2bc039a31f..445d6d4fc1 100755
--- a/gr-qtgui/apps/qt_digital.py
+++ b/gr-qtgui/apps/qt_digital.py
@@ -20,7 +20,10 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, blks2
+from gnuradio import gr, digital
+from gnuradio import blocks
+from gnuradio import filter
+from gnuradio import channels
from gnuradio import eng_notation
import sys
@@ -60,7 +63,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 +149,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,16 +177,19 @@ 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)
+ self.rrctaps = filter.firdes.root_raised_cosine(1, self.sps, 1, self.excess_bw, 21)
+ self.rx_rrc = filter.fir_filter_ccf(1, self.rrctaps)
# Set up the carrier & clock recovery parameters
@@ -194,31 +200,30 @@ 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
noise = self.get_noise_voltage(self.snr_dB)
self.fo = 100/self.sample_rate()
self.to = 1.0
- self.channel = gr.channel_model(noise, self.fo, self.to)
+ self.channel = channels.channel_model(noise, self.fo, self.to)
- self.thr = gr.throttle(gr.sizeof_char, self._sample_rate)
- self.snk_tx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self.thr = blocks.throttle(gr.sizeof_char, self._sample_rate)
+ self.snk_tx = qtgui.sink_c(fftsize, filter.firdes.WIN_BLACKMAN_hARRIS,
0, self._sample_rate*self.sps,
"Tx", True, True, True, True)
- self.snk_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS,
+ self.snk_rx = qtgui.sink_c(fftsize, filter.firdes.WIN_BLACKMAN_hARRIS,
0, self._sample_rate,
"Rx", True, True, True, True)
@@ -288,18 +293,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..0e0c8a177d 100755
--- a/gr-qtgui/apps/uhd_display.py
+++ b/gr-qtgui/apps/uhd_display.py
@@ -21,15 +21,16 @@
#
from gnuradio import gr
+from gnuradio import filter
+from gnuradio import blocks
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:
@@ -193,20 +194,20 @@ class my_top_block(gr.top_block):
self._fftsize = options.fft_size
self.snk = qtgui.sink_c(options.fft_size,
- gr.firdes.WIN_BLACKMAN_hARRIS,
+ filter.firdes.WIN_BLACKMAN_hARRIS,
self._freq, self._bandwidth,
"UHD Display",
True, True, True, False)
# Set up internal amplifier
- self.amp = gr.multiply_const_cc(0.0)
+ self.amp = blocks.multiply_const_cc(0.0)
self.set_amplifier_gain(100)
# Create a single-pole IIR filter to remove DC
# but don't connect it yet
self.dc_gain = 0.001
- self.dc = gr.single_pole_iir_filter_cc(self.dc_gain)
- self.dc_sub = gr.sub_cc()
+ self.dc = filter.single_pole_iir_filter_cc(self.dc_gain)
+ self.dc_sub = blocks.sub_cc()
self.connect(self.u, self.amp, self.snk)
@@ -234,7 +235,7 @@ class my_top_block(gr.top_block):
self.lock()
# Add file sink to save data
- self.file_sink = gr.file_sink(gr.sizeof_gr_complex, name)
+ self.file_sink = blocks.file_sink(gr.sizeof_gr_complex, name)
self.connect(self.amp, self.file_sink)
self.unlock()
diff --git a/gr-qtgui/doc/qtgui.dox b/gr-qtgui/doc/qtgui.dox
index 8664af163d..c3ba512107 100644
--- a/gr-qtgui/doc/qtgui.dox
+++ b/gr-qtgui/doc/qtgui.dox
@@ -22,6 +22,40 @@ by using:
help(qtgui)
\endcode
+\subsection Blocks
+
+There are a number of available QTGUI blocks for different plotting
+purposes. These include:
+
+\li Time Domain: x-axis is time, y-axis is amplitude.
+\li Frequency Domain or PSD: x-axis is frequency, y-axis is magnitude
+in dB.
+\li Waterfall or spectrogram: x-axis is frequency, y-axis is time,
+z-axis is intensity related to magnitude in dB.
+\li Constellation: polar plot of real vs. imaginary.
+\li Time Raster: time vs. time with the z-axis being intensity based
+on value of the sample.
+\li Combined Sink: combines time, frequency, waterfall, and
+constellation plots into one widget.
+
+The time domain, frequency domain, and waterfall have both a complex
+and a floating point block. The constellation plot only makes sense
+with complex inputs. The time raster plots accept bits and floats.
+
+Because the time raster plots are designed to show structure over time
+in a signal, frame, packet, etc., they never drop samples. This is a
+fairly taxing job and performance can be an issue. Since it is
+expected that this block will work on a frame or packet structure, we
+tend to be at the lowest possible rate at this point, so that will
+help. Expect performance issues at high data rates.
+
+Note: There seem to be extra performance issue with the raster
+plotters in QWT version 5 that were fixed with QWT version 6. As such,
+the time raster plots have incredibly poor performance with QWT5 to
+the point of almost being unusable. In the future, we may restrict
+compilation and installation of these plots only if QWT6 or higher is
+discovered. For now, just be aware of this limitation.
+
\section Dependencies
@@ -51,7 +85,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):
@@ -70,8 +104,15 @@ def main():
tb.start()
qapp.exec_()
tb.stop()
-
-
\endcode
+There are graphical controls in all but the combined plotting
+tools. In the margins of the GUIs (that is, not on the canvas showing
+the signal itself), right-clicking the mouse will pull up a drop-down
+menu that will allow you to change difference parameters of the
+plots. These include things like the look of the lines (width, color,
+style, markers, etc.), the ability to start and stop the display, the
+ability to save to a file, and other plot-specific controls (FFT size
+for the frequency and waterfall plots, etc.).
+
*/
diff --git a/gr-qtgui/examples/dark.qss b/gr-qtgui/examples/dark.qss
new file mode 100644
index 0000000000..77a3756733
--- /dev/null
+++ b/gr-qtgui/examples/dark.qss
@@ -0,0 +1,115 @@
+QWidget
+{
+ color: white;
+ background-color: black;
+}
+
+QwtPlot
+{
+ padding: 10px;
+ font-size: 18px;
+}
+
+DisplayPlot {
+ qproperty-zoomer_color: green;
+ qproperty-line_color1: green;
+ qproperty-line_color2: green;
+ qproperty-line_color3: green;
+ qproperty-line_style1: SolidLine;
+ qproperty-line_style2: DashLine;
+ qproperty-line_style3: DotLine;
+ qproperty-axes_label_font_size: 18;
+}
+
+WaterfallDisplayPlot {
+ qproperty-intensity_color_map_type1: 1;
+ qproperty-low_intensity_color: black;
+ qproperty-high_intensity_color: green;
+}
+
+FrequencyDisplayPlot {
+ qproperty-max_fft_color: palegreen;
+ qproperty-min_fft_color: palegreen;
+ qproperty-marker_lower_intensity_color: white;
+ qproperty-marker_upper_intensity_color: red;
+ qproperty-marker_lower_intensity_visible: false;
+ qproperty-marker_upper_intensity_visible: false;
+ qproperty-marker_noise_floor_amplitude_color: red;
+ qproperty-marker_noise_floor_amplitude_visible: false;
+}
+
+QwtPlotCanvas
+{
+ border: 1px solid White;
+ border-radius: 10px;
+}
+
+QwtScaleWidget
+{
+ font-size: 14px;
+}
+
+QwtLegend
+{
+ padding: 3px;
+ margin: 3px;
+ font-size: 14px;
+}
+
+QwtLegendItem
+{
+ padding: 2px;
+ margin: 2px;
+}
+
+QLineEdit,
+QPlainTextEdit,
+QComboBox,
+QMenu {
+ selection-color: black;
+ selection-background-color: lightgrey;
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 black, stop: 1 rgb(128, 128, 128));
+ border: 1px solid gray;
+ padding: 2px;
+ border-radius: 3px;
+}
+
+QPushButton,
+QToolButton {
+ selection-color: black;
+ selection-background-color: white;
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 black, stop: 1 rgb(128, 128, 128));
+ border: 1px solid gray;
+ padding: 2px;
+ border-radius: 3px;
+}
+
+QTabWidget::pane {
+ border: 1px solid white;
+}
+
+QTabBar {
+ margin: 20px;
+ padding: 20px;
+}
+
+QTabBar::tab {
+ background-color: rgb(100, 100, 100);
+ border: 1px solid white;
+ padding: 5px;
+}
+
+QTabBar::tab:first {
+ border-top-left-radius: 4px;
+}
+
+QTabBar::tab:last {
+ border-top-right-radius: 4px;
+}
+
+QTabBar::tab:selected {
+ background-color: rgb(200, 200, 200);
+ color: black;
+}
+
+
diff --git a/gr-qtgui/examples/pyqt_const_c.py b/gr-qtgui/examples/pyqt_const_c.py
new file mode 100755
index 0000000000..3a43bf9a92
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_const_c.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+from gnuradio import gr, filter
+from gnuradio import blocks
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import channels
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-channels.\n")
+ 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 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f1, 0.5, 0)
+ src2 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f2, 0.5, 0)
+ src = blocks.add_cc()
+ channel = channels.channel_model(0.001)
+ thr = blocks.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_example_c.py b/gr-qtgui/examples/pyqt_example_c.py
index 0b43fce0e5..cb708360f1 100755
--- a/gr-qtgui/examples/pyqt_example_c.py
+++ b/gr-qtgui/examples/pyqt_example_c.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011 Free Software Foundation, Inc.
+# Copyright 2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -20,7 +20,8 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr
+from gnuradio import gr, filter
+from gnuradio import blocks
import sys
try:
@@ -28,7 +29,19 @@ try:
from PyQt4 import QtGui, QtCore
import sip
except ImportError:
- print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import channels
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-channels.\n")
sys.exit(1)
class dialog_box(QtGui.QWidget):
@@ -138,13 +151,17 @@ class my_top_block(gr.top_block):
fftsize = 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.001)
- thr = gr.throttle(gr.sizeof_gr_complex, 100*fftsize)
- self.snk1 = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS,
+ ss = open('dark.qss')
+ sstext = ss.read()
+ ss.close()
+ self.qapp.setStyleSheet(sstext)
+
+ src1 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_cc()
+ channel = channels.channel_model(0.001)
+ thr = blocks.throttle(gr.sizeof_gr_complex, 100*fftsize)
+ self.snk1 = qtgui.sink_c(fftsize, filter.firdes.WIN_BLACKMAN_hARRIS,
0, Rs,
"Complex Signal Example",
True, True, True, False)
diff --git a/gr-qtgui/examples/pyqt_example_f.py b/gr-qtgui/examples/pyqt_example_f.py
index d00011f403..5bd582d1e1 100755
--- a/gr-qtgui/examples/pyqt_example_f.py
+++ b/gr-qtgui/examples/pyqt_example_f.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011 Free Software Foundation, Inc.
+# Copyright 2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -20,7 +20,8 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr
+from gnuradio import gr, filter
+from gnuradio import blocks
import sys
try:
@@ -28,7 +29,13 @@ try:
from PyQt4 import QtGui, QtCore
import sip
except ImportError:
- print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
sys.exit(1)
class dialog_box(QtGui.QWidget):
@@ -139,13 +146,13 @@ class my_top_block(gr.top_block):
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*fftsize)
- noise = gr.noise_source_f(gr.GR_GAUSSIAN, 0.001)
- add = gr.add_ff()
- self.snk1 = qtgui.sink_f(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS,
+ src1 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_ff()
+ thr = blocks.throttle(gr.sizeof_float, 100*fftsize)
+ noise = analog.noise_source_f(analog.GR_GAUSSIAN, 0.001)
+ add = blocks.add_ff()
+ self.snk1 = qtgui.sink_f(fftsize, filter.firdes.WIN_BLACKMAN_hARRIS,
0, Rs,
"Float Signal Example",
True, True, True, False)
diff --git a/gr-qtgui/examples/pyqt_freq_c.py b/gr-qtgui/examples/pyqt_freq_c.py
new file mode 100755
index 0000000000..7632176878
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_freq_c.py
@@ -0,0 +1,194 @@
+#!/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, filter
+from gnuradio import blocks
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import channels
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-channels.\n")
+ 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)
+ ss = open('dark.qss')
+ sstext = ss.read()
+ ss.close()
+ self.qapp.setStyleSheet(sstext)
+
+ src1 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_cc()
+ channel = channels.channel_model(0.01)
+ thr = blocks.throttle(gr.sizeof_gr_complex, 100*npts)
+ self.snk1 = qtgui.freq_sink_c(npts, filter.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..668b54d249
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_freq_f.py
@@ -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, filter
+from gnuradio import blocks
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ 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 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_ff()
+ thr = blocks.throttle(gr.sizeof_float, 100*npts)
+ self.snk1 = qtgui.freq_sink_f(npts, filter.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..ae8ebfc257 100755
--- a/gr-qtgui/examples/pyqt_time_c.py
+++ b/gr-qtgui/examples/pyqt_time_c.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011 Free Software Foundation, Inc.
+# Copyright 2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,6 +21,7 @@
#
from gnuradio import gr
+from gnuradio import blocks
import sys
try:
@@ -28,7 +29,19 @@ try:
from PyQt4 import QtGui, QtCore
import sip
except ImportError:
- print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import channels
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-channels.\n")
sys.exit(1)
class dialog_box(QtGui.QWidget):
@@ -138,20 +151,24 @@ class my_top_block(gr.top_block):
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)
+ ss = open('dark.qss')
+ sstext = ss.read()
+ ss.close()
+ self.qapp.setStyleSheet(sstext)
+
+ src1 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_cc()
+ channel = channels.channel_model(0.01)
+ thr = blocks.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)
@@ -165,18 +182,20 @@ class my_top_block(gr.top_block):
pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
# Example of using signal/slot to set the title of a curve
- pyWin.connect(pyWin, QtCore.SIGNAL("setTitle(int, QString)"),
- 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}")
+ pyWin.connect(pyWin, QtCore.SIGNAL("setLineLabel(int, QString)"),
+ pyWin, QtCore.SLOT("setLineLabel(int, QString)"))
+ pyWin.emit(QtCore.SIGNAL("setLineLabel(int, QString)"), 0, "Re{sum}")
+ self.snk1.set_line_label(1, "Im{Sum}")
+ #self.snk1.set_line_label(2, "Re{src1}")
+ #self.snk1.set_line_label(3, "Im{src1}")
+ #self.snk1.set_line_label(4, "Re{src2}")
+ #self.snk1.set_line_label(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_time_f.py b/gr-qtgui/examples/pyqt_time_f.py
index 464d8939b0..b733a5a809 100755
--- a/gr-qtgui/examples/pyqt_time_f.py
+++ b/gr-qtgui/examples/pyqt_time_f.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011 Free Software Foundation, Inc.
+# Copyright 2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,6 +21,7 @@
#
from gnuradio import gr
+from gnuradio import blocks
import sys
try:
@@ -28,7 +29,13 @@ try:
from PyQt4 import QtGui, QtCore
import sip
except ImportError:
- print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
sys.exit(1)
class dialog_box(QtGui.QWidget):
@@ -139,12 +146,12 @@ class my_top_block(gr.top_block):
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)
- noise = gr.noise_source_f(gr.GR_GAUSSIAN, 0.001)
- add = gr.add_ff()
+ src1 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_ff()
+ thr = blocks.throttle(gr.sizeof_float, 100*npts)
+ noise = analog.noise_source_f(analog.GR_GAUSSIAN, 0.001)
+ add = blocks.add_ff()
self.snk1 = qtgui.time_sink_f(npts, Rs,
"Complex Time Example", 3)
@@ -168,11 +175,11 @@ class my_top_block(gr.top_block):
pyWin = sip.wrapinstance(pyQt, QtGui.QWidget)
# Example of using signal/slot to set the title of a curve
- pyWin.connect(pyWin, QtCore.SIGNAL("setTitle(int, QString)"),
- pyWin, QtCore.SLOT("setTitle(int, QString)"))
- pyWin.emit(QtCore.SIGNAL("setTitle(int, QString)"), 0, "sum")
- self.snk1.set_title(1, "src1")
- self.snk1.set_title(2, "src2")
+ pyWin.connect(pyWin, QtCore.SIGNAL("setLineLabel(int, QString)"),
+ pyWin, QtCore.SLOT("setLineLabel(int, QString)"))
+ pyWin.emit(QtCore.SIGNAL("setLineLabel(int, QString)"), 0, "sum")
+ self.snk1.set_line_label(1, "src1")
+ self.snk1.set_line_label(2, "src2")
# Can also set the color of a curve
#self.snk1.set_color(5, "blue")
diff --git a/gr-qtgui/examples/pyqt_time_raster_b.py b/gr-qtgui/examples/pyqt_time_raster_b.py
new file mode 100755
index 0000000000..b29403819d
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_time_raster_b.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import blocks
+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):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+
+ self.resize(800, 500)
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ data0 = 10*[0,] + 40*[1,0] + 10*[0,]
+ data0 += 10*[0,] + 40*[0,1] + 10*[0,]
+ data1 = 20*[0,] + [0,0,0,1,1,1,0,0,0,0] + 70*[0,]
+
+ # Adjust these to change the layout of the plot.
+ # Can be set to fractions.
+ ncols = 100.25
+ nrows = 100
+
+ fs = 200
+ src0 = gr.vector_source_b(data0, True)
+ src1 = gr.vector_source_b(data1, True)
+ thr = blocks.throttle(gr.sizeof_char, 50000)
+ head = gr.head(gr.sizeof_char, 10000000)
+ self.snk1 = qtgui.time_raster_sink_b(fs, nrows, ncols, [], [],
+ "Time Raster Example", 2)
+
+ self.connect(src0, thr, (self.snk1, 0))
+ self.connect(src1, (self.snk1, 1))
+
+ # 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.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_raster_f.py b/gr-qtgui/examples/pyqt_time_raster_f.py
new file mode 100755
index 0000000000..957e694b38
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_time_raster_f.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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 import blocks
+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):
+ QtGui.QWidget.__init__(self, None)
+ self.setWindowTitle('PyQt Test GUI')
+
+ self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
+ self.boxlayout.addWidget(display, 1)
+
+ self.resize(800, 500)
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ data0 = 10*[0,] + 40*[1,0] + 10*[0,]
+ data0 += 10*[0,] + 40*[0,1] + 10*[0,]
+ data1 = 20*[0,] + [0,0,0,1,1,1,0,0,0,0] + 70*[0,]
+
+ # Adjust these to change the layout of the plot.
+ # Can be set to fractions.
+ ncols = 100.25
+ nrows = 100
+
+ fs = 200
+ src0 = gr.vector_source_f(data0, True)
+ src1 = gr.vector_source_f(data1, True)
+ thr = blocks.throttle(gr.sizeof_float, 50000)
+ hed = gr.head(gr.sizeof_float, 10000000)
+ self.snk1 = qtgui.time_raster_sink_f(fs, nrows, ncols, [], [],
+ "Float Time Raster Example", 2)
+
+ self.connect(src0, thr, (self.snk1, 0))
+ self.connect(src1, (self.snk1, 1))
+
+ # 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.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_c.py b/gr-qtgui/examples/pyqt_waterfall_c.py
new file mode 100755
index 0000000000..118a3df660
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_waterfall_c.py
@@ -0,0 +1,196 @@
+#!/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, filter
+from gnuradio import blocks
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import channels
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-channels.\n")
+ 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 = 2000
+
+ npts = 2048
+
+ taps = filter.firdes.complex_band_pass_2(1, Rs, 1500, 2500, 100, 60)
+
+ self.qapp = QtGui.QApplication(sys.argv)
+ ss = open('dark.qss')
+ sstext = ss.read()
+ ss.close()
+ self.qapp.setStyleSheet(sstext)
+
+ src1 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_c(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_cc()
+ channel = channels.channel_model(0.01)
+ thr = blocks.throttle(gr.sizeof_gr_complex, 100*npts)
+ filt = filter.fft_filter_ccc(1, taps)
+ self.snk1 = qtgui.waterfall_sink_c(npts, filter.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Complex Waterfall Example", 2)
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, channel, thr, (self.snk1, 0))
+ self.connect(thr, filt, (self.snk1, 1))
+
+ 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..f9680c28cf
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_waterfall_f.py
@@ -0,0 +1,182 @@
+#!/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, filter
+from gnuradio import blocks
+import sys
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ sys.stderr.write("Error: Program requires PyQt4 and gr-qtgui.\n")
+ sys.exit(1)
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("Error: Program requires gr-analog.\n")
+ 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 = 2000
+
+ npts = 2048
+
+ self.qapp = QtGui.QApplication(sys.argv)
+
+ src1 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f1, 0.1, 0)
+ src2 = analog.sig_source_f(Rs, analog.GR_SIN_WAVE, f2, 0.1, 0)
+ src = blocks.add_ff()
+ thr = blocks.throttle(gr.sizeof_float, 100*npts)
+ self.snk1 = qtgui.waterfall_sink_f(npts, filter.firdes.WIN_BLACKMAN_hARRIS,
+ 0, Rs,
+ "Real Waterfall Example", 2)
+
+ self.connect(src1, (src,0))
+ self.connect(src2, (src,1))
+ self.connect(src, thr, (self.snk1, 0))
+ self.connect(src1, (self.snk1, 1))
+
+ 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..3eaaf49295
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_block_tree.xml
@@ -0,0 +1,49 @@
+<?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>
+ <block>qtgui_time_raster_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..c751c89437
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -0,0 +1,107 @@
+<?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).set_update_time($update_time)
+self.$(id).set_y_axis($ymin, $ymax)
+self.$(id).set_x_axis($xmin, $xmax)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+ <callback>set_resize($width, $height)</callback>
+ <callback>set_update_time($update_time)</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>Y min</name>
+ <key>ymin</key>
+ <value>-2</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Y max</name>
+ <key>ymax</key>
+ <value>2</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>X min</name>
+ <key>xmin</key>
+ <value>-2</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>X max</name>
+ <key>xmax</key>
+ <value>2</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Update Period</name>
+ <key>update_time</key>
+ <value>0.10</value>
+ <type>real</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..35edf61ed8
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -0,0 +1,139 @@
+<?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.filter 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).set_update_time($update_time)
+self.$(id).set_y_axis($ymin, $ymax)
+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($update_time)</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>Y min</name>
+ <key>ymin</key>
+ <value>-140</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Y max</name>
+ <key>ymax</key>
+ <value>10</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Update Period</name>
+ <key>update_time</key>
+ <value>0.10</value>
+ <type>real</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 6488ac04cd..6e13481397 100644
--- a/gr-qtgui/grc/qtgui_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_sink_x.xml
@@ -7,10 +7,9 @@
<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.gr import firdes</import>
+ <import>from gnuradio import qtgui</import>
+ <import>from gnuradio.filter import firdes</import>
<import>import sip</import>
<make>#set $win = 'self._%s_win'%$id
qtgui.$(type.fcn)(
@@ -24,9 +23,18 @@ qtgui.$(type.fcn)(
$plottime, \#plottime
$plotconst, \#plotconst
)
-self.$(id).set_update_time(1.0 / $rate)
+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>
@@ -92,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>
@@ -135,10 +149,11 @@ $(gui_hint()($win))</make>
<hide>part</hide>
</param>
<param>
- <name>Update Rate</name>
- <key>rate</key>
- <value>10</value>
- <type>real</type>
+ <name>Clicked freq variable</name>
+ <key>freqchangevar</key>
+ <value>None</value>
+ <type>raw</type>
+ <hide>part</hide>
</param>
<sink>
<name>in</name>
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_raster_x.xml b/gr-qtgui/grc/qtgui_time_raster_x.xml
new file mode 100644
index 0000000000..7d880ab084
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_time_raster_x.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Sink
+###################################################
+ -->
+<block>
+ <name>QT GUI Time Raster Sink</name>
+ <key>qtgui_time_raster_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)(
+ $samp_rate,
+ $nrows,
+ $ncols,
+ $mult,
+ $offset,
+ $name,
+ $nconnections,
+ )
+self.$(id).set_update_time($update_time)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+ <callback>set_num_rows($nrows)</callback>
+ <callback>set_num_cols($ncols)</callback>
+ <callback>set_multiplier($mult)</callback>
+ <callback>set_offset($offset)</callback>
+ <callback>set_update_time($update_time)</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>Byte</name><key>byte</key><opt>fcn:time_raster_sink_b</opt></option>
+ <option><name>Float</name><key>float</key><opt>fcn:time_raster_sink_f</opt></option>
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <value>QT GUI Plot</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Num. Rows</name>
+ <key>nrows</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num. Cols</name>
+ <key>ncols</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Multiplier</name>
+ <key>mult</key>
+ <value>[]</value>
+ <type>real_vector</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Offset</name>
+ <key>offset</key>
+ <value>[]</value>
+ <type>real_vector</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Update Period</name>
+ <key>update_time</key>
+ <value>0.10</value>
+ <type>real</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_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml
index 9c8da6fbcf..d64ce2e237 100644
--- a/gr-qtgui/grc/qtgui_time_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_time_sink_x.xml
@@ -7,24 +7,27 @@
<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.gr import firdes</import>
+ <import>from gnuradio import qtgui</import>
+ <import>from gnuradio.filter import firdes</import>
<import>import sip</import>
<make>#set $win = 'self._%s_win'%$id
qtgui.$(type.fcn)(
$size, \#size
- $bw, \#bw
+ $srate, \#samp_rate
$name, \#name
$nconnections \#number of inputs
)
+self.$(id).set_update_time($update_time)
+self.$(id).set_y_axis($ymin, $ymax)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
$(gui_hint()($win))</make>
<callback>set_time_domain_axis($min, $max)</callback>
- <callback>set_update_time($t)</callback>
+ <callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
<callback>set_color($which, $color)</callback>
+ <callback>set_y_axis($ymin, $ymax)</callback>
+ <callback>set_samp_rate($srate)</callback>
<param>
<name>Type</name>
<key>type</key>
@@ -46,12 +49,26 @@ $(gui_hint()($win))</make>
<type>int</type>
</param>
<param>
- <name>Bandwidth (Hz)</name>
- <key>bw</key>
+ <name>Sample Rate</name>
+ <key>srate</key>
<value>samp_rate</value>
<type>real</type>
</param>
<param>
+ <name>Y min</name>
+ <key>ymin</key>
+ <value>-1</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Y max</name>
+ <key>ymax</key>
+ <value>1</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
<name>Number of Inputs</name>
<key>nconnections</key>
<value>1</value>
@@ -59,6 +76,13 @@ $(gui_hint()($win))</make>
<hide>part</hide>
</param>
<param>
+ <name>Update Period</name>
+ <key>update_time</key>
+ <value>0.10</value>
+ <type>real</type>
+ <hide>part</hide>
+ </param>
+ <param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
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..176a907e9e
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -0,0 +1,124 @@
+<?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.filter 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).set_update_time($update_time)
+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($update_time)</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>Number of Inputs</name>
+ <key>nconnections</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Update Period</name>
+ <key>update_time</key>
+ <value>0.10</value>
+ <type>real</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/include/CMakeLists.txt b/gr-qtgui/include/qtgui/CMakeLists.txt
index ef4cb11752..f3ef6808e8 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,19 @@
# 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
+ time_raster_sink_b.h
+ time_raster_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..e0c358bcad
--- /dev/null
+++ b/gr-qtgui/include/qtgui/const_sink_c.h
@@ -0,0 +1,97 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <filter/firdes.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=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_y_axis(double min, double max) = 0;
+ virtual void set_x_axis(double min, double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &label) = 0;
+ virtual void set_line_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, int style) = 0;
+ virtual void set_line_marker(int which, int marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_autoscale(bool en) = 0;
+ virtual int nsamps() const = 0;
+ virtual void reset() = 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..79d3f2e8f0
--- /dev/null
+++ b/gr-qtgui/include/qtgui/freq_sink_c.h
@@ -0,0 +1,112 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <filter/firdes.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=1,
+ 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_fft_window(const gr::filter::firdes::win_type win) = 0;
+ virtual gr::filter::firdes::win_type fft_window() = 0;
+
+ virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0;
+ virtual void set_y_axis(double min, double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &label) = 0;
+ virtual void set_line_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, int style) = 0;
+ virtual void set_line_marker(int which, int marker) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 0;
+ virtual void enable_autoscale(bool en=true) = 0;
+ virtual void reset() = 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..131801f531
--- /dev/null
+++ b/gr-qtgui/include/qtgui/freq_sink_f.h
@@ -0,0 +1,111 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <filter/firdes.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=1,
+ 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_fft_window(const gr::filter::firdes::win_type win) = 0;
+ virtual gr::filter::firdes::win_type fft_window() = 0;
+
+ virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0;
+ virtual void set_y_axis(double min, double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &label) = 0;
+ virtual void set_line_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, int style) = 0;
+ virtual void set_line_marker(int which, int marker) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 0;
+ virtual void enable_autoscale(bool en=true) = 0;
+ virtual void reset() = 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..45b980686c
--- /dev/null
+++ b/gr-qtgui/include/qtgui/sink_c.h
@@ -0,0 +1,97 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_block.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..c2bed902d9
--- /dev/null
+++ b/gr-qtgui/include/qtgui/sink_f.h
@@ -0,0 +1,97 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_block.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_raster_sink_b.h b/gr-qtgui/include/qtgui/time_raster_sink_b.h
new file mode 100644
index 0000000000..132ab9715c
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_raster_sink_b.h
@@ -0,0 +1,120 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_RASTER_SINK_B_H
+#define INCLUDED_QTGUI_TIME_RASTER_SINK_B_H
+
+#include <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals on a
+ * time_raster plot.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink that takes in byte
+ * streams and plots a time_raster (spectrogram) plot.
+ *
+ * Input stream: This expects a bit stream (0, 1 in the LSB of a
+ * byte). It will display packed bytes but the display will have
+ * to be autoscaled.
+ */
+ class QTGUI_API time_raster_sink_b : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::time_raster_sink_b::sptr
+ typedef boost::shared_ptr<time_raster_sink_b> sptr;
+
+ /*!
+ * \brief Build a bit time raster sink.
+ *
+ * \param samp_rate sample rate of signal
+ * \param cols number of cols to plot
+ * \param rows number of rows to plot
+ * \param mult vector of floats as a scaling multiplier for each input stream
+ * \param offset vector of floats as an offset for each input stream
+ * \param name title for the plot
+ * \param nconnections number of streams connected
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &lable) = 0;
+ virtual void set_line_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_line_alpha(int which, double alpha) = 0;
+ virtual void set_color_map(int which, const int color) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+ virtual int color_map(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void set_samp_rate(const double samp_rate) = 0;
+ virtual void set_num_rows(double rows) = 0;
+ virtual void set_num_cols(double cols) = 0;
+
+ virtual double num_rows() = 0;
+ virtual double num_cols() = 0;
+
+ virtual void set_multiplier(const std::vector<float> &mult) = 0;
+ virtual void set_offset(const std::vector<float> &offset) = 0;
+
+ virtual void set_intensity_range(float min, float max) = 0;
+
+ virtual void enable_menu(bool en) = 0;
+ virtual void enable_grid(bool en) = 0;
+ virtual void enable_autoscale(bool en) = 0;
+ virtual void reset() = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_RASTER_SINK_B_H */
diff --git a/gr-qtgui/include/qtgui/time_raster_sink_f.h b/gr-qtgui/include/qtgui/time_raster_sink_f.h
new file mode 100644
index 0000000000..7215373bec
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_raster_sink_f.h
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_RASTER_SINK_F_H
+#define INCLUDED_QTGUI_TIME_RASTER_SINK_F_H
+
+#include <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief A graphical sink to display multiple signals on a
+ * time_raster plot.
+ * \ingroup qtgui_blk
+ *
+ * This is a QT-based graphical sink that takes set of a floating
+ * point streams and plots a time_raster (spectrogram) plot.
+ *
+ */
+ class QTGUI_API time_raster_sink_f : virtual public gr_sync_block
+ {
+ public:
+ // gr::qtgui::time_raster_sink_f::sptr
+ typedef boost::shared_ptr<time_raster_sink_f> sptr;
+
+ /*!
+ * \brief Build a floating point time raster sink.
+ *
+ * \param samp_rate sample rate of signal
+ * \param cols number of cols to plot
+ * \param rows number of rows to plot
+ * \param mult vector of floats as a scaling multiplier for each input stream
+ * \param offset vector of floats as an offset for each input stream
+ * \param name title for the plot
+ * \param nconnections number of streams connected
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &lable) = 0;
+ virtual void set_line_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_line_alpha(int which, double alpha) = 0;
+ virtual void set_color_map(int which, const int color) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+ virtual int color_map(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void set_samp_rate(const double samp_rate) = 0;
+ virtual void set_num_rows(double rows) = 0;
+ virtual void set_num_cols(double cols) = 0;
+
+ virtual double num_rows() = 0;
+ virtual double num_cols() = 0;
+
+ virtual void set_multiplier(const std::vector<float> &mult) = 0;
+ virtual void set_offset(const std::vector<float> &offset) = 0;
+
+ virtual void set_intensity_range(float min, float max) = 0;
+
+ virtual void enable_menu(bool en) = 0;
+ virtual void enable_grid(bool en) = 0;
+ virtual void enable_autoscale(bool en) = 0;
+ virtual void reset() = 0;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_RASTER_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..82ab27d443
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_sink_c.h
@@ -0,0 +1,105 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.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 samp_rate sample rate (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 samp_rate,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_y_axis(double min, double max) = 0;
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &label) = 0;
+ virtual void set_line_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, int style) = 0;
+ virtual void set_line_marker(int which, int marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+ virtual void set_samp_rate(const double samp_rate) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 0;
+ virtual void enable_autoscale(bool en=true) = 0;
+ virtual void enable_stem_plot(bool en=true) = 0;
+ virtual void enable_semilogx(bool en=true) = 0;
+ virtual void enable_semilogy(bool en=true) = 0;
+ virtual int nsamps() const = 0;
+ virtual void reset() = 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..6c0788f715
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_sink_f.h
@@ -0,0 +1,103 @@
+/* -*- 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 <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.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 samp_rate sample rate (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 samp_rate,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void set_y_axis(double min, double max) = 0;
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &line) = 0;
+ virtual void set_line_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, int style) = 0;
+ virtual void set_line_marker(int which, int marker) = 0;
+ virtual void set_nsamps(const int newsize) = 0;
+ virtual void set_samp_rate(const double samp_rate) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual std::string line_color(int which) = 0;
+ virtual int line_width(int which) = 0;
+ virtual int line_style(int which) = 0;
+ virtual int line_marker(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 0;
+ virtual void enable_autoscale(bool en=true) = 0;
+ virtual void enable_stem_plot(bool en=true) = 0;
+ virtual void enable_semilogx(bool en=true) = 0;
+ virtual void enable_semilogy(bool en=true) = 0;
+ virtual int nsamps() const = 0;
+ virtual void reset() = 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..5bc921ccb3
--- /dev/null
+++ b/gr-qtgui/include/qtgui/waterfall_sink_c.h
@@ -0,0 +1,118 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <filter/firdes.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 nconnections number of signals to be connected to the sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void clear_data() = 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_fft_window(const gr::filter::firdes::win_type win) = 0;
+ virtual gr::filter::firdes::win_type fft_window() = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+ virtual void set_intensity_range(const double min,
+ const double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &line) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+ virtual void set_color_map(int which, const int color) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+ virtual int color_map(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void auto_scale() = 0;
+ virtual double min_intensity(int which) = 0;
+ virtual double max_intensity(int which) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 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..98a434e668
--- /dev/null
+++ b/gr-qtgui/include/qtgui/waterfall_sink_f.h
@@ -0,0 +1,117 @@
+/* -*- 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 <Python.h>
+#include <qtgui/api.h>
+#include <gr_sync_block.h>
+#include <qapplication.h>
+#include <filter/firdes.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 nconnections number of signals to be connected to the sink
+ * \param parent a QWidget parent object, if any
+ */
+ static sptr make(int size, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections=1,
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual PyObject* pyqwidget() = 0;
+
+ virtual void clear_data() = 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_fft_window(const gr::filter::firdes::win_type win) = 0;
+ virtual gr::filter::firdes::win_type fft_window() = 0;
+
+ virtual void set_frequency_range(const double centerfreq,
+ const double bandwidth) = 0;
+ virtual void set_intensity_range(const double min,
+ const double max) = 0;
+
+ virtual void set_update_time(double t) = 0;
+ virtual void set_title(const std::string &title) = 0;
+ virtual void set_line_label(int which, const std::string &line) = 0;
+ virtual void set_line_alpha(int which, double alpha) = 0;
+ virtual void set_color_map(int which, const int color) = 0;
+
+ virtual std::string title() = 0;
+ virtual std::string line_label(int which) = 0;
+ virtual double line_alpha(int which) = 0;
+ virtual int color_map(int which) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void auto_scale() = 0;
+ virtual double min_intensity(int which) = 0;
+ virtual double max_intensity(int which) = 0;
+
+ virtual void enable_menu(bool en=true) = 0;
+ virtual void enable_grid(bool en=true) = 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 955db49e72..ff1e64ce31 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -22,9 +22,17 @@
########################################################################
set(qtgui_moc_hdrs
spectrumdisplayform.h
+ displayform.h
timedisplayform.h
+ timerasterdisplayform.h
+ freqdisplayform.h
+ constellationdisplayform.h
+ waterfalldisplayform.h
+ form_menus.h
+ DisplayPlot.h
FrequencyDisplayPlot.h
TimeDomainDisplayPlot.h
+ TimeRasterDisplayPlot.h
WaterfallDisplayPlot.h
ConstellationDisplayPlot.h
)
@@ -41,20 +49,36 @@ endif(NOT EXISTS ${spectrum_ui_hdr})
set(qtgui_srcs
${qtgui_moc_srcs}
${qtgui_ui_hdrs}
+ DisplayPlot.cc
FrequencyDisplayPlot.cc
TimeDomainDisplayPlot.cc
+ TimeRasterDisplayPlot.cc
+ timeRasterGlobalData.cc
WaterfallDisplayPlot.cc
waterfallGlobalData.cc
ConstellationDisplayPlot.cc
spectrumdisplayform.cc
+ displayform.cc
timedisplayform.cc
+ timerasterdisplayform.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
+ plot_raster.cc
+ sink_c_impl.cc
+ sink_f_impl.cc
+ time_sink_c_impl.cc
+ time_sink_f_impl.cc
+ time_raster_sink_b_impl.cc
+ time_raster_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
)
@@ -77,31 +101,45 @@ endif(MSVC)
########################################################################
include_directories(
${GR_QTGUI_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${GNURADIO_CORE_INCLUDE_DIRS}
${GRUEL_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
${QWT_INCLUDE_DIRS}
${QT_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
${LOG4CPP_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)
link_directories(
- ${QWT_LIBRARY_DIRS}
- ${LOG4CPP_LIBRARY_DIRS}
- ${Boost_LIBRARY_DIRS}
+ ${QWT_LIBRARY_DIRS}
+ ${FFTW3F_LIBRARY_DIRS}
+ ${LOG4CPP_LIBRARY_DIRS}
+ ${Boost_LIBRARY_DIRS}
)
include_directories(${PYTHON_INCLUDE_PATH}) #deprecated for dirs (cmake 2.6)
+if(ENABLE_GR_CTRLPORT)
+ ADD_DEFINITIONS(-DGR_CTRLPORT)
+ include_directories(${ICE_INCLUDE_DIR})
+endif(ENABLE_GR_CTRLPORT)
+
########################################################################
# Setup library
########################################################################
list(APPEND qtgui_libs
gnuradio-core
+ gnuradio-fft
+ gnuradio-filter
+ volk
${QWT_LIBRARIES}
${QT_LIBRARIES}
${PYTHON_LIBRARIES}
+ ${FFTW3F_LIBRARIES}
${LOG4CPP_LIBRARIES}
)
@@ -114,14 +152,24 @@ GR_LIBRARY_FOO(gnuradio-qtgui RUNTIME_COMPONENT "qtgui_runtime" DEVEL_COMPONENT
# Install the header files
########################################################################
install(FILES
+ DisplayPlot.h
FrequencyDisplayPlot.h
TimeDomainDisplayPlot.h
+ TimeRasterDisplayPlot.h
+ timeRasterGlobalData.h
WaterfallDisplayPlot.h
waterfallGlobalData.h
ConstellationDisplayPlot.h
plot_waterfall.h
+ plot_raster.h
spectrumdisplayform.h
+ displayform.h
timedisplayform.h
+ timerasterdisplayform.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..f3951534a9 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,65 +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);
- setAxisTitle(QwtPlot::xBottom, "In-phase");
-
- setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
- 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());
@@ -118,65 +76,73 @@ 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());
+ setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
+ set_xaxis(-2.0, 2.0);
+ setAxisTitle(QwtPlot::xBottom, "In-phase");
+
+ setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
+ set_yaxis(-2.0, 2.0);
+ setAxisTitle(QwtPlot::yLeft, "Quadrature");
+ updateAxes();
+
+ 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);
+ setXaxis(min, max);
}
void
ConstellationDisplayPlot::set_yaxis(double min, double max)
{
- setAxisScale(QwtPlot::yLeft, min, max);
+ setYaxis(min, max);
}
void
@@ -187,69 +153,104 @@ 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));
+ }
+
+ if(_autoscale_state) {
+ double bottom=1e20, top=-1e20;
+ for(int n = 0; n < _nplots; n++) {
+ for(int64_t point = 0; point < numDataPoints; point++) {
+ double b = std::min(realDataPoints[n][point], imagDataPoints[n][point]);
+ double t = std::max(realDataPoints[n][point], imagDataPoints[n][point]);
+ if(b < bottom) {
+ bottom = b;
+ }
+ if(t > top) {
+ top = t;
+ }
+ }
+ }
+ _autoScale(bottom, top);
+ }
+
+ replot();
- replot();
-
- _lastReplot = gruel::high_res_timer_now();
+ }
}
}
void
-ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
+ConstellationDisplayPlot::plotNewData(const double* realDataPoints,
+ const double* imagDataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval)
{
- plotItem->setVisible(!on);
+ std::vector<double*> vecRealDataPoints;
+ std::vector<double*> vecImagDataPoints;
+ vecRealDataPoints.push_back((double*)realDataPoints);
+ vecImagDataPoints.push_back((double*)imagDataPoints);
+ plotNewData(vecRealDataPoints, vecImagDataPoints,
+ numDataPoints, timeInterval);
}
void
-ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
+ConstellationDisplayPlot::_autoScale(double bottom, double top)
{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
+ // Auto scale the x- and y-axis with a margin of 20%
+ double b = bottom - fabs(bottom)*0.20;
+ double t = top + fabs(top)*0.20;
+ set_axis(b, t, b, t);
}
void
-ConstellationDisplayPlot::OnPickerPointSelected6(const QPointF & p)
+ConstellationDisplayPlot::setAutoScale(bool state)
{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
+ _autoscale_state = state;
}
#endif /* CONSTELLATION_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h
index 9e0f6f26a8..b68b01f6d8 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 double* realDataPoints,
+ 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,15 @@ 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:
+ void setAutoScale(bool state);
private:
- QwtPlotCurve* _plot_curve;
-
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
- QwtDblClickPlotPicker *_picker;
-
- double* _realDataPoints;
- double* _imagDataPoints;
+ void _autoScale(double bottom, double top);
- 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..1c9de3d0ae
--- /dev/null
+++ b/gr-qtgui/lib/DisplayPlot.cc
@@ -0,0 +1,416 @@
+/* -*- 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>
+#include <QDebug>
+
+DisplayPlot::DisplayPlot(int nplots, QWidget* parent)
+ : QwtPlot(parent), _nplots(nplots), _stop(false)
+{
+ qRegisterMetaType<QColorList>("QColorList");
+ resize(parent->width(), parent->height());
+
+ _autoscale_state = false;
+
+ // 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
+
+ QColor default_palette_color = QColor("white");
+ setPaletteColor(default_palette_color);
+
+ _panner = new QwtPlotPanner(canvas());
+ _panner->setAxisEnabled(QwtPlot::yRight, false);
+ _panner->setMouseButton(Qt::MidButton, Qt::ControlModifier);
+
+ // 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);
+ if(!_autoscale_state)
+ _zoomer->setZoomBase();
+}
+
+void
+DisplayPlot::setXaxis(double min, double max)
+{
+ setAxisScale(QwtPlot::xBottom, min, max);
+ _zoomer->setZoomBase();
+}
+
+void
+DisplayPlot::setLineLabel(int which, QString label)
+{
+ _plot_curve[which]->setTitle(label);
+}
+
+QString
+DisplayPlot::getLineLabel(int which)
+{
+ return _plot_curve[which]->title().text();
+}
+
+void
+DisplayPlot::setLineColor(int which, QColor color)
+{
+ if (which < _nplots) {
+ // 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();
+ if(sym) {
+ sym->setColor(color);
+ sym->setPen(pen);
+ _plot_curve[which]->setSymbol(sym);
+ }
+#endif
+ }
+}
+
+QColor
+DisplayPlot::getLineColor(int which) const {
+ // If that plot doesn't exist then return black.
+ if (which < _nplots)
+ return _plot_curve[which]->pen().color();
+ return QColor("black");
+}
+
+// Use a preprocessor macro to create a bunch of hooks for Q_PROPERTY and hence the stylesheet.
+#define SETUPLINE(i, im1) \
+ void DisplayPlot::setLineColor ## i (QColor c) {setLineColor(im1, c);} \
+ const QColor DisplayPlot::getLineColor ## i () const {return getLineColor(im1);} \
+ void DisplayPlot::setLineWidth ## i (int width) {setLineWidth(im1, width);} \
+ int DisplayPlot::getLineWidth ## i () const {return getLineWidth(im1);} \
+ void DisplayPlot::setLineStyle ## i (Qt::PenStyle ps) {setLineStyle(im1, ps);} \
+ const Qt::PenStyle DisplayPlot::getLineStyle ## i () const {return getLineStyle(im1);} \
+ void DisplayPlot::setLineMarker ## i (QwtSymbol::Style ms) {setLineMarker(im1, ms);} \
+ const QwtSymbol::Style DisplayPlot::getLineMarker ## i () const {return getLineMarker(im1);} \
+ void DisplayPlot::setMarkerAlpha ## i (int alpha) {setMarkerAlpha(im1, alpha);} \
+ int DisplayPlot::getMarkerAlpha ## i () const {return getMarkerAlpha(im1);}
+SETUPLINE(1, 0)
+SETUPLINE(2, 1)
+SETUPLINE(3, 2)
+SETUPLINE(4, 3)
+SETUPLINE(5, 4)
+SETUPLINE(6, 5)
+SETUPLINE(7, 6)
+SETUPLINE(8, 7)
+SETUPLINE(9, 8)
+
+void
+DisplayPlot::setZoomerColor(QColor c) {
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
+}
+
+QColor
+DisplayPlot::getZoomerColor() const {
+ return _zoomer->rubberBandPen().color();
+}
+
+void
+DisplayPlot::setPaletteColor(QColor c) {
+ QPalette palette;
+ palette.setColor(canvas()->backgroundRole(), c);
+ canvas()->setPalette(palette);
+}
+
+QColor
+DisplayPlot::getPaletteColor() const {
+ return canvas()->palette().color(canvas()->backgroundRole());
+}
+
+void
+DisplayPlot::setAxisLabelFontSize(int axisId, int fs) {
+ QwtText axis_title = QwtText(axisWidget(axisId)->title());
+ QFont font = QFont(axis_title.font());
+ font.setPointSize(fs);
+ axis_title.setFont(font);
+ axisWidget(axisId)->setTitle(axis_title);
+}
+
+int
+DisplayPlot::getAxisLabelFontSize(int axisId) const {
+ return axisWidget(axisId)->title().font().pointSize();
+}
+
+void
+DisplayPlot::setYaxisLabelFontSize(int fs) {
+ setAxisLabelFontSize(QwtPlot::yLeft, fs);
+}
+
+int
+DisplayPlot::getYaxisLabelFontSize() const {
+ int fs = getAxisLabelFontSize(QwtPlot::yLeft);
+ return fs;
+}
+
+void
+DisplayPlot::setXaxisLabelFontSize(int fs) {
+ setAxisLabelFontSize(QwtPlot::xBottom, fs);
+}
+
+int
+DisplayPlot::getXaxisLabelFontSize() const {
+ int fs = getAxisLabelFontSize(QwtPlot::xBottom);
+ return fs;
+}
+
+void
+DisplayPlot::setAxesLabelFontSize(int fs) {
+ setAxisLabelFontSize(QwtPlot::yLeft, fs);
+ setAxisLabelFontSize(QwtPlot::xBottom, fs);
+}
+
+int
+DisplayPlot::getAxesLabelFontSize() const {
+ // Returns 0 if all axes do not have the same font size.
+ int fs = getAxisLabelFontSize(QwtPlot::yLeft);
+ if (getAxisLabelFontSize(QwtPlot::xBottom) != fs)
+ return 0;
+ return fs;
+}
+
+void
+DisplayPlot::setLineWidth(int which, int width)
+{
+ if (which < _nplots) {
+ // 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(1.0*width), 7+10*log10(1.0*width));
+ _plot_curve[which]->setSymbol(sym);
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ if(sym) {
+ sym->setSize(7+10*log10(1.0*width), 7+10*log10(1.0*width));
+ _plot_curve[which]->setSymbol(sym);
+ }
+#endif
+ }
+}
+
+int
+DisplayPlot::getLineWidth(int which) const {
+ if (which < _nplots) {
+ return _plot_curve[which]->pen().width();
+ } else {
+ return 0;
+ }
+}
+
+void
+DisplayPlot::setLineStyle(int which, Qt::PenStyle style)
+{
+ if (which < _nplots) {
+ QPen pen(_plot_curve[which]->pen());
+ pen.setStyle(style);
+ _plot_curve[which]->setPen(pen);
+ }
+}
+
+const Qt::PenStyle
+DisplayPlot::getLineStyle(int which) const
+{
+ if (which < _nplots) {
+ return _plot_curve[which]->pen().style();
+ } else {
+ return Qt::SolidLine;
+ }
+}
+
+void
+DisplayPlot::setLineMarker(int which, QwtSymbol::Style marker)
+{
+ if (which < _nplots) {
+#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();
+ if(sym) {
+ sym->setStyle(marker);
+ _plot_curve[which]->setSymbol(sym);
+ }
+#endif
+ }
+}
+
+const QwtSymbol::Style
+DisplayPlot::getLineMarker(int which) const
+{
+ if(which < _nplots) {
+#if QWT_VERSION < 0x060000
+ QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol();
+ return sym.style();
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ return sym->style();
+#endif
+ }
+ else {
+ return QwtSymbol::NoSymbol;
+ }
+}
+
+void
+DisplayPlot::setMarkerAlpha(int which, int alpha)
+{
+ if (which < _nplots) {
+ // Get the pen color
+ QPen pen(_plot_curve[which]->pen());
+ QColor color = pen.color();
+
+ // Set new alpha and update pen
+ color.setAlpha(alpha);
+ pen.setColor(color);
+ _plot_curve[which]->setPen(pen);
+
+ // And set the new color for the markers
+#if QWT_VERSION < 0x060000
+ QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol();
+ setLineMarker(which, sym.style());
+#else
+ QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol();
+ if(sym) {
+ sym->setColor(color);
+ sym->setPen(pen);
+ _plot_curve[which]->setSymbol(sym);
+ }
+#endif
+ }
+}
+
+int
+DisplayPlot::getMarkerAlpha(int which) const
+{
+ if (which < _nplots) {
+ return _plot_curve[which]->pen().color().alpha();
+ } else {
+ return 0;
+ }
+}
+
+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..d9ee16e087
--- /dev/null
+++ b/gr-qtgui/lib/DisplayPlot.h
@@ -0,0 +1,287 @@
+/* -*- 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.
+ */
+
+#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
+
+typedef QList<QColor> QColorList;
+Q_DECLARE_METATYPE ( QColorList )
+
+class DisplayPlot:public QwtPlot{
+ Q_OBJECT
+
+ Q_PROPERTY ( QColor line_color1 READ getLineColor1 WRITE setLineColor1 )
+ Q_PROPERTY ( QColor line_color2 READ getLineColor2 WRITE setLineColor2 )
+ Q_PROPERTY ( QColor line_color3 READ getLineColor3 WRITE setLineColor3 )
+ Q_PROPERTY ( QColor line_color4 READ getLineColor4 WRITE setLineColor4 )
+ Q_PROPERTY ( QColor line_color5 READ getLineColor5 WRITE setLineColor5 )
+ Q_PROPERTY ( QColor line_color6 READ getLineColor6 WRITE setLineColor6 )
+ Q_PROPERTY ( QColor line_color7 READ getLineColor7 WRITE setLineColor7 )
+ Q_PROPERTY ( QColor line_color8 READ getLineColor8 WRITE setLineColor8 )
+ Q_PROPERTY ( QColor line_color9 READ getLineColor9 WRITE setLineColor9 )
+
+ Q_PROPERTY ( int line_width1 READ getLineWidth1 WRITE setLineWidth1 )
+ Q_PROPERTY ( int line_width2 READ getLineWidth2 WRITE setLineWidth2 )
+ Q_PROPERTY ( int line_width3 READ getLineWidth3 WRITE setLineWidth3 )
+ Q_PROPERTY ( int line_width4 READ getLineWidth4 WRITE setLineWidth4 )
+ Q_PROPERTY ( int line_width5 READ getLineWidth5 WRITE setLineWidth5 )
+ Q_PROPERTY ( int line_width6 READ getLineWidth6 WRITE setLineWidth6 )
+ Q_PROPERTY ( int line_width7 READ getLineWidth7 WRITE setLineWidth7 )
+ Q_PROPERTY ( int line_width8 READ getLineWidth8 WRITE setLineWidth8 )
+ Q_PROPERTY ( int line_width9 READ getLineWidth9 WRITE setLineWidth9 )
+
+ Q_PROPERTY ( Qt::PenStyle line_style1 READ getLineStyle1 WRITE setLineStyle1 )
+ Q_PROPERTY ( Qt::PenStyle line_style2 READ getLineStyle2 WRITE setLineStyle2 )
+ Q_PROPERTY ( Qt::PenStyle line_style3 READ getLineStyle3 WRITE setLineStyle3 )
+ Q_PROPERTY ( Qt::PenStyle line_style4 READ getLineStyle4 WRITE setLineStyle4 )
+ Q_PROPERTY ( Qt::PenStyle line_style5 READ getLineStyle5 WRITE setLineStyle5 )
+ Q_PROPERTY ( Qt::PenStyle line_style6 READ getLineStyle6 WRITE setLineStyle6 )
+ Q_PROPERTY ( Qt::PenStyle line_style7 READ getLineStyle7 WRITE setLineStyle7 )
+ Q_PROPERTY ( Qt::PenStyle line_style8 READ getLineStyle8 WRITE setLineStyle8 )
+ Q_PROPERTY ( Qt::PenStyle line_style9 READ getLineStyle9 WRITE setLineStyle9 )
+
+ typedef QwtSymbol::Style QwtSymbolStyle;
+
+ Q_ENUMS ( QwtSymbolStyle )
+ Q_PROPERTY ( QwtSymbolStyle line_marker1 READ getLineMarker1 WRITE setLineMarker1 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker2 READ getLineMarker2 WRITE setLineMarker2 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker3 READ getLineMarker3 WRITE setLineMarker3 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker4 READ getLineMarker4 WRITE setLineMarker4 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker5 READ getLineMarker5 WRITE setLineMarker5 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker6 READ getLineMarker6 WRITE setLineMarker6 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker7 READ getLineMarker7 WRITE setLineMarker7 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker8 READ getLineMarker8 WRITE setLineMarker8 )
+ Q_PROPERTY ( QwtSymbolStyle line_marker9 READ getLineMarker9 WRITE setLineMarker9 )
+
+ Q_PROPERTY ( int marker_alpha1 READ getMarkerAlpha1 WRITE setMarkerAlpha1 )
+ Q_PROPERTY ( int marker_alpha2 READ getMarkerAlpha2 WRITE setMarkerAlpha2 )
+ Q_PROPERTY ( int marker_alpha3 READ getMarkerAlpha3 WRITE setMarkerAlpha3 )
+ Q_PROPERTY ( int marker_alpha4 READ getMarkerAlpha4 WRITE setMarkerAlpha4 )
+ Q_PROPERTY ( int marker_alpha5 READ getMarkerAlpha5 WRITE setMarkerAlpha5 )
+ Q_PROPERTY ( int marker_alpha6 READ getMarkerAlpha6 WRITE setMarkerAlpha6 )
+ Q_PROPERTY ( int marker_alpha7 READ getMarkerAlpha7 WRITE setMarkerAlpha7 )
+ Q_PROPERTY ( int marker_alpha8 READ getMarkerAlpha8 WRITE setMarkerAlpha8 )
+ Q_PROPERTY ( int marker_alpha9 READ getMarkerAlpha9 WRITE setMarkerAlpha9 )
+
+ Q_PROPERTY ( QColor zoomer_color READ getZoomerColor WRITE setZoomerColor )
+ Q_PROPERTY ( QColor palette_color READ getPaletteColor WRITE setPaletteColor )
+ Q_PROPERTY ( int yaxis_label_font_size READ getYaxisLabelFontSize WRITE setYaxisLabelFontSize )
+ Q_PROPERTY ( int xaxis_label_font_size READ getXaxisLabelFontSize WRITE setXaxisLabelFontSize )
+ Q_PROPERTY ( int axes_label_font_size READ getAxesLabelFontSize WRITE setAxesLabelFontSize )
+
+public:
+ DisplayPlot(int nplots, QWidget*);
+ virtual ~DisplayPlot();
+
+ virtual void replot() = 0;
+
+ const QColor getLineColor1 () const;
+ const QColor getLineColor2 () const;
+ const QColor getLineColor3 () const;
+ const QColor getLineColor4 () const;
+ const QColor getLineColor5 () const;
+ const QColor getLineColor6 () const;
+ const QColor getLineColor7 () const;
+ const QColor getLineColor8 () const;
+ const QColor getLineColor9 () const;
+
+ int getLineWidth1 () const;
+ int getLineWidth2 () const;
+ int getLineWidth3 () const;
+ int getLineWidth4 () const;
+ int getLineWidth5 () const;
+ int getLineWidth6 () const;
+ int getLineWidth7 () const;
+ int getLineWidth8 () const;
+ int getLineWidth9 () const;
+
+ const Qt::PenStyle getLineStyle1 () const;
+ const Qt::PenStyle getLineStyle2 () const;
+ const Qt::PenStyle getLineStyle3 () const;
+ const Qt::PenStyle getLineStyle4 () const;
+ const Qt::PenStyle getLineStyle5 () const;
+ const Qt::PenStyle getLineStyle6 () const;
+ const Qt::PenStyle getLineStyle7 () const;
+ const Qt::PenStyle getLineStyle8 () const;
+ const Qt::PenStyle getLineStyle9 () const;
+
+ const QwtSymbol::Style getLineMarker1 () const;
+ const QwtSymbol::Style getLineMarker2 () const;
+ const QwtSymbol::Style getLineMarker3 () const;
+ const QwtSymbol::Style getLineMarker4 () const;
+ const QwtSymbol::Style getLineMarker5 () const;
+ const QwtSymbol::Style getLineMarker6 () const;
+ const QwtSymbol::Style getLineMarker7 () const;
+ const QwtSymbol::Style getLineMarker8 () const;
+ const QwtSymbol::Style getLineMarker9 () const;
+
+ int getMarkerAlpha1 () const;
+ int getMarkerAlpha2 () const;
+ int getMarkerAlpha3 () const;
+ int getMarkerAlpha4 () const;
+ int getMarkerAlpha5 () const;
+ int getMarkerAlpha6 () const;
+ int getMarkerAlpha7 () const;
+ int getMarkerAlpha8 () const;
+ int getMarkerAlpha9 () const;
+
+ QColor getZoomerColor() const;
+ QColor getPaletteColor() const;
+ int getAxisLabelFontSize(int axisId) const;
+ int getYaxisLabelFontSize() const;
+ int getXaxisLabelFontSize() const;
+ int getAxesLabelFontSize() const;
+
+ // 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 setLineLabel(int which, QString label);
+ QString getLineLabel(int which);
+ void setLineColor(int which, QColor color);
+ QColor getLineColor(int which) const;
+ void setLineWidth(int which, int width);
+ int getLineWidth(int which) const;
+ void setLineStyle(int which, Qt::PenStyle style);
+ const Qt::PenStyle getLineStyle(int which) const;
+ void setLineMarker(int which, QwtSymbol::Style marker);
+ const QwtSymbol::Style getLineMarker(int which) const;
+ void setMarkerAlpha(int which, int alpha);
+ int getMarkerAlpha(int which) const;
+ // Need a function for each curve for setting via stylesheet.
+ // Can't use preprocessor directives because we're inside a Q_OBJECT.
+ void setLineColor1 (QColor);
+ void setLineColor2 (QColor);
+ void setLineColor3 (QColor);
+ void setLineColor4 (QColor);
+ void setLineColor5 (QColor);
+ void setLineColor6 (QColor);
+ void setLineColor7 (QColor);
+ void setLineColor8 (QColor);
+ void setLineColor9 (QColor);
+
+ void setLineWidth1 (int);
+ void setLineWidth2 (int);
+ void setLineWidth3 (int);
+ void setLineWidth4 (int);
+ void setLineWidth5 (int);
+ void setLineWidth6 (int);
+ void setLineWidth7 (int);
+ void setLineWidth8 (int);
+ void setLineWidth9 (int);
+
+ void setLineStyle1 (Qt::PenStyle);
+ void setLineStyle2 (Qt::PenStyle);
+ void setLineStyle3 (Qt::PenStyle);
+ void setLineStyle4 (Qt::PenStyle);
+ void setLineStyle5 (Qt::PenStyle);
+ void setLineStyle6 (Qt::PenStyle);
+ void setLineStyle7 (Qt::PenStyle);
+ void setLineStyle8 (Qt::PenStyle);
+ void setLineStyle9 (Qt::PenStyle);
+
+ void setLineMarker1 (QwtSymbol::Style);
+ void setLineMarker2 (QwtSymbol::Style);
+ void setLineMarker3 (QwtSymbol::Style);
+ void setLineMarker4 (QwtSymbol::Style);
+ void setLineMarker5 (QwtSymbol::Style);
+ void setLineMarker6 (QwtSymbol::Style);
+ void setLineMarker7 (QwtSymbol::Style);
+ void setLineMarker8 (QwtSymbol::Style);
+ void setLineMarker9 (QwtSymbol::Style);
+
+ void setMarkerAlpha1 (int);
+ void setMarkerAlpha2 (int);
+ void setMarkerAlpha3 (int);
+ void setMarkerAlpha4 (int);
+ void setMarkerAlpha5 (int);
+ void setMarkerAlpha6 (int);
+ void setMarkerAlpha7 (int);
+ void setMarkerAlpha8 (int);
+ void setMarkerAlpha9 (int);
+
+ void setZoomerColor(QColor c);
+ void setPaletteColor(QColor c);
+ void setAxisLabelFontSize(int axisId, int fs);
+ void setYaxisLabelFontSize(int fs);
+ void setXaxisLabelFontSize(int fs);
+ void setAxesLabelFontSize(int fs);
+
+ void setStop(bool on);
+
+ 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;
+
+ QList<QColor> _trace_colors;
+
+ bool _autoscale_state;
+};
+
+#endif /* DOMAIN_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc
index b74d460150..e279155544 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.cc
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,88 +25,44 @@
#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();
}
- void SetUnitType(const std::string &type)
+ void setUnitType(const std::string &type)
{
_unitType = type;
}
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,21 @@ private:
std::string _unitType;
};
-FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
- : QwtPlot(parent)
-{
- _startFrequency = 0;
- _stopFrequency = 4000;
-
- _lastReplot = 0;
-
- resize(parent->width(), parent->height());
- _useCenterFrequencyFlag = false;
+/***********************************************************************
+ * Main frequency display plotter widget
+ **********************************************************************/
+FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent)
+ : DisplayPlot(nplots, parent)
+{
+ _startFrequency = -1;
+ _stopFrequency = 1;
_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,52 +94,67 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
setAxisTitle(QwtPlot::yLeft, "Power (dB)");
+ QList<QColor> default_colors;
+ default_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
- _fft_plot_curve = new QwtPlotCurve("Power Spectrum");
- _fft_plot_curve->attach(this);
- _fft_plot_curve->setPen(QPen(Qt::blue));
+ 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);
+
+ QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(default_colors[i]),
+ QPen(default_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
-
+ setLineColor(i, default_colors[i]);
+ }
+
_min_fft_plot_curve = new QwtPlotCurve("Minimum Power");
_min_fft_plot_curve->attach(this);
- _min_fft_plot_curve->setPen(QPen(Qt::magenta));
-
+ const QColor _default_min_fft_color = Qt::magenta;
+ setMinFFTColor(_default_min_fft_color);
#if QWT_VERSION < 0x060000
_min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
#else
_min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints);
#endif
-
_min_fft_plot_curve->setVisible(false);
-
+
_max_fft_plot_curve = new QwtPlotCurve("Maximum Power");
_max_fft_plot_curve->attach(this);
- _max_fft_plot_curve->setPen(QPen(Qt::darkYellow));
-
+ QColor _default_max_fft_color = Qt::darkYellow;
+ setMaxFFTColor(_default_max_fft_color);
#if QWT_VERSION < 0x060000
_max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
#else
_max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints);
#endif
-
_max_fft_plot_curve->setVisible(false);
-
+
_lower_intensity_marker= new QwtPlotMarker();
_lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
- _lower_intensity_marker->setLinePen(QPen(Qt::cyan));
+ QColor _default_marker_lower_intensity_color = Qt::cyan;
+ setMarkerLowerIntensityColor(_default_marker_lower_intensity_color);
_lower_intensity_marker->attach(this);
-
+
_upper_intensity_marker = new QwtPlotMarker();
_upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
- _upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine));
+ QColor _default_marker_upper_intensity_color = Qt::green;
+ setMarkerUpperIntensityColor(_default_marker_upper_intensity_color);
_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++){
@@ -211,33 +162,22 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
_maxFFTPoints[number] = -280.0;
}
- // set up peak marker
- QwtSymbol symbol;
-
_markerPeakAmplitude = new QwtPlotMarker();
- _markerPeakAmplitude->setLinePen(QPen(Qt::yellow));
- symbol.setStyle(QwtSymbol::Diamond);
- symbol.setSize(8);
- symbol.setPen(QPen(Qt::yellow));
- symbol.setBrush(QBrush(Qt::yellow));
-
-#if QWT_VERSION < 0x060000
- _markerPeakAmplitude->setSymbol(symbol);
-#else
- _markerPeakAmplitude->setSymbol(&symbol);
-#endif
-
+ QColor _default_marker_peak_amplitude_color = Qt::yellow;
+ setMarkerPeakAmplitudeColor(_default_marker_peak_amplitude_color);
/// THIS CAUSES A PROBLEM!
//_markerPeakAmplitude->attach(this);
_markerNoiseFloorAmplitude = new QwtPlotMarker();
_markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine);
- _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine));
+ QColor _default_marker_noise_floor_amplitude_color = Qt::darkRed;
+ setMarkerNoiseFloorAmplitudeColor(_default_marker_noise_floor_amplitude_color);
_markerNoiseFloorAmplitude->attach(this);
_markerCF= new QwtPlotMarker();
_markerCF->setLineStyle(QwtPlotMarker::VLine);
- _markerCF->setLinePen(QPen(Qt::lightGray, 0, Qt::DotLine));
+ QColor _default_marker_CF_color = Qt::lightGray;
+ setMarkerCFColor(_default_marker_CF_color);
_markerCF->attach(this);
_markerCF->hide();
@@ -248,21 +188,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,38 +199,33 @@ 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);
- _zoomer->setTrackerPen(c);
+ const QColor default_zoomer_color(Qt::darkRed);
+ setZoomerColor(default_zoomer_color);
// 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
-FrequencyDisplayPlot::set_yaxis(double min, double max)
+FrequencyDisplayPlot::setYaxis(double min, double max)
{
// Get the new max/min values for the plot
_minYAxis = min;
@@ -314,28 +234,21 @@ FrequencyDisplayPlot::set_yaxis(double min, double max)
// Set the axis max/min to the new values
setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
- // Reset the base zoom level to the new axis scale set here
- _zoomer->setZoomBase();
+ // Reset the base zoom level to the new axis scale set here.
+ // But don't do it if we set the axis due to auto scaling.
+ if(!_autoscale_state)
+ _zoomer->setZoomBase();
}
void
-FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq,
- const double constStopFreq,
- const double constCenterFreq,
- const bool useCenterFrequencyFlag,
+FrequencyDisplayPlot::setFrequencyRange(const double centerfreq,
+ const double bandwidth,
const double units, const std::string &strunits)
{
- double startFreq = constStartFreq / units;
- double stopFreq = constStopFreq / units;
- double centerFreq = constCenterFreq / units;
+ double startFreq = (centerfreq - bandwidth/2.0f) / units;
+ double stopFreq = (centerfreq + bandwidth/2.0f) / units;
_xAxisMultiplier = units;
- _useCenterFrequencyFlag = useCenterFrequencyFlag;
-
- if(_useCenterFrequencyFlag){
- startFreq = (startFreq + centerFreq);
- stopFreq = (stopFreq + centerFreq);
- }
bool reset = false;
if((startFreq != _startFrequency) || (stopFreq != _stopFrequency))
@@ -345,7 +258,7 @@ FrequencyDisplayPlot::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 FreqDisplayScaleDraw(display_units));
setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str()));
@@ -353,21 +266,21 @@ FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq,
if(reset)
_resetXAxisPoints();
- ((FreqDisplayZoomer*)_zoomer)->SetFrequencyPrecision(display_units);
- ((FreqDisplayZoomer*)_zoomer)->SetUnitType(strunits);
+ ((FreqDisplayZoomer*)_zoomer)->setFrequencyPrecision(display_units);
+ ((FreqDisplayZoomer*)_zoomer)->setUnitType(strunits);
}
}
}
double
-FrequencyDisplayPlot::GetStartFrequency() const
+FrequencyDisplayPlot::getStartFrequency() const
{
return _startFrequency;
}
double
-FrequencyDisplayPlot::GetStopFrequency() const
+FrequencyDisplayPlot::getStopFrequency() const
{
return _stopFrequency;
}
@@ -376,117 +289,169 @@ void
FrequencyDisplayPlot::replot()
{
_markerNoiseFloorAmplitude->setYValue(_noiseFloorAmplitude);
+ _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency);
// Make sure to take into account the start frequency
- if(_useCenterFrequencyFlag){
- _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency);
- }
- else{
- _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency);
- }
+// if(_useCenterFrequencyFlag){
+// _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency);
+// }
+// else{
+// _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency);
+// }
_markerPeakAmplitude->setYValue(_peakAmplitude);
QwtPlot::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);
#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);
#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];
+ }
+#if QWT_VERSION < 0x060000
+ _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
+ _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
+#else
+ _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints);
+ _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints);
+#endif
+ _resetXAxisPoints();
+ clearMaxData();
+ clearMinData();
+ }
+
+ for(int i = 0; i < _nplots; i++) {
+ memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
}
- if(dataPoints[point] > _maxFFTPoints[point]){
- _maxFFTPoints[point] = dataPoints[point];
+
+ double bottom=1e20, top=-1e20;
+ for(int n = 0; n < _nplots; n++) {
+ for(int64_t point = 0; point < numDataPoints; point++) {
+ if(dataPoints[n][point] < _minFFTPoints[point]) {
+ _minFFTPoints[point] = dataPoints[n][point];
+ }
+ if(dataPoints[n][point] > _maxFFTPoints[point]) {
+ _maxFFTPoints[point] = dataPoints[n][point];
+ }
+
+ // Find overall top and bottom values in plot.
+ // Used for autoscaling y-axis.
+ if(dataPoints[n][point] < bottom) {
+ bottom = dataPoints[n][point];
+ }
+ if(dataPoints[n][point] > top) {
+ top = dataPoints[n][point];
+ }
+ }
}
+
+ if(_autoscale_state)
+ _autoScale(bottom, top);
+
+ _noiseFloorAmplitude = noiseFloorAmplitude;
+ _peakFrequency = peakFrequency;
+ _peakAmplitude = peakAmplitude;
+
+ setUpperIntensityLevel(_peakAmplitude);
+
+ replot();
}
-
- _noiseFloorAmplitude = noiseFloorAmplitude;
- _peakFrequency = peakFrequency;
- _peakAmplitude = peakAmplitude;
-
- SetUpperIntensityLevel(_peakAmplitude);
-
- replot();
-
- _lastReplot = gruel::high_res_timer_now();
}
}
void
-FrequencyDisplayPlot::ClearMaxData()
+FrequencyDisplayPlot::plotNewData(const double* dataPoints,
+ const int64_t numDataPoints,
+ const double noiseFloorAmplitude, const double peakFrequency,
+ const double peakAmplitude, const double timeInterval)
{
- for(int64_t number = 0; number < _numPoints; number++){
+ 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++) {
_maxFFTPoints[number] = _minYAxis;
}
}
void
-FrequencyDisplayPlot::ClearMinData()
+FrequencyDisplayPlot::clearMinData()
{
- for(int64_t number = 0; number < _numPoints; number++){
+ for(int64_t number = 0; number < _numPoints; number++) {
_minFFTPoints[number] = _maxYAxis;
}
}
void
-FrequencyDisplayPlot::SetMaxFFTVisible(const bool visibleFlag)
+FrequencyDisplayPlot::_autoScale(double bottom, double top)
+{
+ // Auto scale the y-axis with a margin of 10 dB on either side.
+ setYaxis(bottom - 10, top + 10);
+}
+
+void
+FrequencyDisplayPlot::setAutoScale(bool state)
+{
+ _autoscale_state = state;
+}
+
+void
+FrequencyDisplayPlot::setMaxFFTVisible(const bool visibleFlag)
{
+ _max_fft_visible = visibleFlag;
_max_fft_plot_curve->setVisible(visibleFlag);
}
+const bool FrequencyDisplayPlot::getMaxFFTVisible() const
+{
+ return _max_fft_visible;
+}
void
-FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag)
+FrequencyDisplayPlot::setMinFFTVisible(const bool visibleFlag)
{
+ _min_fft_visible = visibleFlag;
_min_fft_plot_curve->setVisible(visibleFlag);
}
+const bool FrequencyDisplayPlot::getMinFFTVisible() const
+{
+ return _min_fft_visible;
+}
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;
}
@@ -500,29 +465,30 @@ FrequencyDisplayPlot::_resetXAxisPoints()
zbase.setRight(_stopFrequency);
_zoomer->zoom(zbase);
_zoomer->setZoomBase(zbase);
+ _zoomer->setZoomBase(true);
_zoomer->zoom(0);
}
void
-FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel)
+FrequencyDisplayPlot::setLowerIntensityLevel(const double lowerIntensityLevel)
{
- _lower_intensity_marker->setYValue( lowerIntensityLevel );
+ _lower_intensity_marker->setYValue(lowerIntensityLevel);
}
void
-FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel)
+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 +496,7 @@ FrequencyDisplayPlot::SetBGColour (QColor c)
}
void
-FrequencyDisplayPlot::ShowCFMarker (const bool show)
+FrequencyDisplayPlot::showCFMarker(const bool show)
{
if (show)
_markerCF->show();
@@ -540,21 +506,128 @@ FrequencyDisplayPlot::ShowCFMarker (const bool show)
void
-FrequencyDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
+FrequencyDisplayPlot::onPickerPointSelected(const QwtDoublePoint & p)
{
QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier);
+ //fprintf(stderr,"onPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier);
point.setX(point.x() * _xAxisMultiplier);
emit plotPointSelected(point);
}
void
-FrequencyDisplayPlot::OnPickerPointSelected6(const QPointF & p)
+FrequencyDisplayPlot::onPickerPointSelected6(const QPointF & p)
{
QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier);
+ //fprintf(stderr,"onPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier);
point.setX(point.x() * _xAxisMultiplier);
emit plotPointSelected(point);
}
+void
+FrequencyDisplayPlot::setMinFFTColor (QColor c)
+{
+ _min_fft_color = c;
+ _min_fft_plot_curve->setPen(QPen(c));
+}
+const QColor
+FrequencyDisplayPlot::getMinFFTColor() const {return _min_fft_color;}
+
+void
+FrequencyDisplayPlot::setMaxFFTColor (QColor c)
+{
+ _max_fft_color = c;
+ _max_fft_plot_curve->setPen(QPen(c));
+}
+const QColor
+FrequencyDisplayPlot::getMaxFFTColor() const {return _max_fft_color;}
+
+void
+FrequencyDisplayPlot::setMarkerLowerIntensityColor (QColor c)
+{
+ _marker_lower_intensity_color = c;
+ _lower_intensity_marker->setLinePen(QPen(c));
+}
+const QColor
+FrequencyDisplayPlot::getMarkerLowerIntensityColor () const {return _marker_lower_intensity_color;}
+void
+FrequencyDisplayPlot::setMarkerLowerIntensityVisible (bool visible)
+{
+ _marker_lower_intensity_visible = visible;
+ if (visible)
+ _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
+ else
+ _lower_intensity_marker->setLineStyle(QwtPlotMarker::NoLine);
+}
+const bool
+FrequencyDisplayPlot::getMarkerLowerIntensityVisible () const {return _marker_lower_intensity_visible;}
+
+void
+FrequencyDisplayPlot::setMarkerUpperIntensityColor (QColor c)
+{
+ _marker_upper_intensity_color = c;
+ _upper_intensity_marker->setLinePen(QPen(c, 0, Qt::DotLine));
+}
+const QColor
+FrequencyDisplayPlot::getMarkerUpperIntensityColor () const {return _marker_upper_intensity_color;}
+void
+FrequencyDisplayPlot::setMarkerUpperIntensityVisible (bool visible)
+{
+ _marker_upper_intensity_visible = visible;
+ if (visible)
+ _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
+ else
+ _upper_intensity_marker->setLineStyle(QwtPlotMarker::NoLine);
+}
+const bool
+FrequencyDisplayPlot::getMarkerUpperIntensityVisible () const {return _marker_upper_intensity_visible;}
+
+void
+FrequencyDisplayPlot::setMarkerPeakAmplitudeColor (QColor c)
+{
+ _marker_peak_amplitude_color = c;
+ _markerPeakAmplitude->setLinePen(QPen(c));
+ QwtSymbol symbol;
+ symbol.setStyle(QwtSymbol::Diamond);
+ symbol.setSize(8);
+ symbol.setPen(QPen(c));
+ symbol.setBrush(QBrush(c));
+#if QWT_VERSION < 0x060000
+ _markerPeakAmplitude->setSymbol(symbol);
+#else
+ _markerPeakAmplitude->setSymbol(&symbol);
+#endif
+}
+const QColor
+FrequencyDisplayPlot::getMarkerPeakAmplitudeColor () const {return _marker_peak_amplitude_color;}
+
+void
+FrequencyDisplayPlot::setMarkerNoiseFloorAmplitudeColor (QColor c)
+{
+ _marker_noise_floor_amplitude_color = c;
+ _markerNoiseFloorAmplitude->setLinePen(QPen(c, 0, Qt::DotLine));
+}
+const QColor
+FrequencyDisplayPlot::getMarkerNoiseFloorAmplitudeColor () const {return _marker_noise_floor_amplitude_color;}
+
+void
+FrequencyDisplayPlot::setMarkerNoiseFloorAmplitudeVisible (bool visible)
+{
+ _marker_noise_floor_amplitude_visible = visible;
+ if (visible)
+ _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine);
+ else
+ _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::NoLine);
+}
+const bool
+FrequencyDisplayPlot::getMarkerNoiseFloorAmplitudeVisible () const {return _marker_noise_floor_amplitude_visible;}
+
+void
+FrequencyDisplayPlot::setMarkerCFColor (QColor c)
+{
+ _marker_CF_color = c;
+ _markerCF->setLinePen(QPen(c, 0, Qt::DotLine));
+}
+const QColor
+FrequencyDisplayPlot::getMarkerCFColor () const {return _marker_CF_color;}
+
#endif /* FREQUENCY_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h
index 5c3ea708c3..22d2be0055 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.h
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,115 +25,136 @@
#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
+ Q_PROPERTY ( QColor min_fft_color READ getMinFFTColor WRITE setMinFFTColor )
+ Q_PROPERTY ( QColor max_fft_color READ getMaxFFTColor WRITE setMaxFFTColor )
+ Q_PROPERTY ( bool min_fft_visible READ getMinFFTVisible WRITE setMinFFTVisible )
+ Q_PROPERTY ( bool max_fft_visible READ getMaxFFTVisible WRITE setMaxFFTVisible )
+ Q_PROPERTY ( QColor marker_lower_intensity_color READ getMarkerLowerIntensityColor WRITE setMarkerLowerIntensityColor )
+ Q_PROPERTY ( bool marker_lower_intensity_visible READ getMarkerLowerIntensityVisible WRITE setMarkerLowerIntensityVisible )
+ Q_PROPERTY ( QColor marker_upper_intensity_color READ getMarkerUpperIntensityColor WRITE setMarkerUpperIntensityColor )
+ Q_PROPERTY ( bool marker_upper_intensity_visible READ getMarkerUpperIntensityVisible WRITE setMarkerUpperIntensityVisible )
+ Q_PROPERTY ( QColor marker_peak_amplitude_color READ getMarkerPeakAmplitudeColor WRITE setMarkerPeakAmplitudeColor )
+ Q_PROPERTY ( QColor marker_noise_floor_amplitude_color READ getMarkerNoiseFloorAmplitudeColor WRITE setMarkerNoiseFloorAmplitudeColor )
+ Q_PROPERTY ( bool marker_noise_floor_amplitude_visible READ getMarkerNoiseFloorAmplitudeVisible WRITE setMarkerNoiseFloorAmplitudeVisible )
+ Q_PROPERTY ( QColor marker_CF_color READ getMarkerCFColor WRITE setMarkerCFColor )
+
public:
- FrequencyDisplayPlot(QWidget*);
+ FrequencyDisplayPlot(int nplots, QWidget*);
virtual ~FrequencyDisplayPlot();
- void SetFrequencyRange(const double, const double,
- const double, const bool,
+ void setFrequencyRange(const double, const double,
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,
+ void plotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
const double noiseFloorAmplitude, const double peakFrequency,
const double peakAmplitude, const double timeInterval);
- void ClearMaxData();
- void ClearMinData();
-
- void SetMaxFFTVisible(const bool);
- void SetMinFFTVisible(const bool);
+ // 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);
- virtual void replot();
+ void clearMaxData();
+ void clearMinData();
- void set_yaxis(double min, double max);
+ void replot();
- void SetTraceColour (QColor);
- void SetBGColour (QColor c);
- void ShowCFMarker (const bool);
+ void setYaxis(double min, double max);
-public slots:
- void resizeSlot( QSize *e );
- void SetLowerIntensityLevel(const double);
- void SetUpperIntensityLevel(const double);
+ void setTraceColour (QColor);
+ void setBGColour (QColor c);
+ void showCFMarker (const bool);
- // 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);
+ const bool getMaxFFTVisible() const;
+ const bool getMinFFTVisible() const;
+ const QColor getMinFFTColor() const;
+ const QColor getMaxFFTColor() const;
+ const QColor getMarkerLowerIntensityColor () const;
+ const bool getMarkerLowerIntensityVisible () const;
+ const QColor getMarkerUpperIntensityColor () const;
+ const bool getMarkerUpperIntensityVisible () const;
+ const QColor getMarkerPeakAmplitudeColor () const;
+ const bool getMarkerNoiseFloorAmplitudeVisible () const;
+ const QColor getMarkerNoiseFloorAmplitudeColor () const;
+ const QColor getMarkerCFColor () const;
-signals:
- void plotPointSelected(const QPointF p);
-
-protected:
+public slots:
+ void setMaxFFTVisible(const bool);
+ void setMinFFTVisible(const bool);
+ void setMinFFTColor (QColor c);
+ void setMaxFFTColor (QColor c);
+ void setMarkerLowerIntensityColor (QColor c);
+ void setMarkerLowerIntensityVisible (bool visible);
+ void setMarkerUpperIntensityColor (QColor c);
+ void setMarkerUpperIntensityVisible (bool visible);
+ void setMarkerPeakAmplitudeColor (QColor c);
+ void setMarkerNoiseFloorAmplitudeVisible (bool visible);
+ void setMarkerNoiseFloorAmplitudeColor (QColor c);
+ void setMarkerCFColor (QColor c);
+
+ void setLowerIntensityLevel(const double);
+ void setUpperIntensityLevel(const double);
+
+ void onPickerPointSelected(const QwtDoublePoint & p);
+ void onPickerPointSelected6(const QPointF & p);
+
+ void setAutoScale(bool state);
private:
-
void _resetXAxisPoints();
+ void _autoScale(double bottom, double top);
+
+ std::vector<double*> _dataPoints;
+
+ QwtPlotCurve* _min_fft_plot_curve;
+ QwtPlotCurve* _max_fft_plot_curve;
+ QColor _min_fft_color;
+ bool _min_fft_visible;
+ QColor _max_fft_color;
+ bool _max_fft_visible;
+ QColor _marker_lower_intensity_color;
+ bool _marker_lower_intensity_visible;
+ QColor _marker_upper_intensity_color;
+ bool _marker_upper_intensity_visible;
+ QColor _marker_peak_amplitude_color;
+ QColor _marker_noise_floor_amplitude_color;
+ bool _marker_noise_floor_amplitude_visible;
+ QColor _marker_CF_color;
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;
};
#endif /* FREQUENCY_DISPLAY_PLOT_HPP */
diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc
index d2dbc77723..40c7fb02b6 100644
--- a/gr-qtgui/lib/SpectrumGUIClass.cc
+++ b/gr-qtgui/lib/SpectrumGUIClass.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -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;
@@ -67,7 +68,7 @@ SpectrumGUIClass::~SpectrumGUIClass()
// We don't need to delete this since as a QWidget, it is supposed to be destroyed
// with it's parent. Deleting it causes a segmentation fault, and not deleting it
// does not leave any extra memory.
- //if(GetWindowOpenFlag()){
+ //if(getWindowOpenFlag()){
//delete _spectrumDisplayForm;
//}
@@ -79,22 +80,21 @@ SpectrumGUIClass::~SpectrumGUIClass()
}
void
-SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
+SpectrumGUIClass::openSpectrumWindow(QWidget* parent,
const bool frequency, const bool waterfall,
const bool time, const bool constellation)
{
d_mutex.lock();
- if(!_windowOpennedFlag){
+ if(!_windowOpennedFlag) {
- if(!_fftBuffersCreatedFlag){
- _fftPoints = new std::complex<float>[_dataPoints];
+ if(!_fftBuffersCreatedFlag) {
+ _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));
}
@@ -103,10 +103,10 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
_spectrumDisplayForm = new SpectrumDisplayForm(parent);
// Toggle Windows on/off
- _spectrumDisplayForm->ToggleTabFrequency(frequency);
- _spectrumDisplayForm->ToggleTabWaterfall(waterfall);
- _spectrumDisplayForm->ToggleTabTime(time);
- _spectrumDisplayForm->ToggleTabConstellation(constellation);
+ _spectrumDisplayForm->toggleTabFrequency(frequency);
+ _spectrumDisplayForm->toggleTabWaterfall(waterfall);
+ _spectrumDisplayForm->toggleTabTime(time);
+ _spectrumDisplayForm->toggleTabConstellation(constellation);
_windowOpennedFlag = true;
@@ -117,8 +117,8 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
d_mutex.unlock();
- SetDisplayTitle(_title);
- Reset();
+ setDisplayTitle(_title);
+ reset();
qApp->postEvent(_spectrumDisplayForm,
new QEvent(QEvent::Type(QEvent::User+3)));
@@ -126,19 +126,19 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
_lastGUIUpdateTime = 0;
// Draw Blank Display
- UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, gruel::high_res_timer_now(), true);
+ updateWindow(false, NULL, 0, NULL, 0, NULL, 0, gruel::high_res_timer_now(), true);
// Set up the initial frequency axis settings
- SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
+ setFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
// GUI Thread only
qApp->processEvents();
}
void
-SpectrumGUIClass::Reset()
+SpectrumGUIClass::reset()
{
- if(GetWindowOpenFlag()) {
+ if(getWindowOpenFlag()) {
qApp->postEvent(_spectrumDisplayForm,
new SpectrumFrequencyRangeEvent(_centerFrequency,
_startFrequency,
@@ -151,18 +151,18 @@ SpectrumGUIClass::Reset()
}
void
-SpectrumGUIClass::SetDisplayTitle(const std::string newString)
+SpectrumGUIClass::setDisplayTitle(const std::string newString)
{
_title.assign(newString);
- if(GetWindowOpenFlag()){
+ if(getWindowOpenFlag()){
qApp->postEvent(_spectrumDisplayForm,
new SpectrumWindowCaptionEvent(_title.c_str()));
}
}
bool
-SpectrumGUIClass::GetWindowOpenFlag()
+SpectrumGUIClass::getWindowOpenFlag()
{
gruel::scoped_lock lock(d_mutex);
bool returnFlag = false;
@@ -172,14 +172,14 @@ SpectrumGUIClass::GetWindowOpenFlag()
void
-SpectrumGUIClass::SetWindowOpenFlag(const bool newFlag)
+SpectrumGUIClass::setWindowOpenFlag(const bool newFlag)
{
gruel::scoped_lock lock(d_mutex);
_windowOpennedFlag = newFlag;
}
void
-SpectrumGUIClass::SetFrequencyRange(const double centerFreq,
+SpectrumGUIClass::setFrequencyRange(const double centerFreq,
const double startFreq,
const double stopFreq)
{
@@ -188,13 +188,13 @@ SpectrumGUIClass::SetFrequencyRange(const double centerFreq,
_startFrequency = startFreq;
_stopFrequency = stopFreq;
- _spectrumDisplayForm->SetFrequencyRange(_centerFrequency,
+ _spectrumDisplayForm->setFrequencyRange(_centerFrequency,
_startFrequency,
_stopFrequency);
}
double
-SpectrumGUIClass::GetStartFrequency()
+SpectrumGUIClass::getStartFrequency()
{
gruel::scoped_lock lock(d_mutex);
double returnValue = 0.0;
@@ -203,7 +203,7 @@ SpectrumGUIClass::GetStartFrequency()
}
double
-SpectrumGUIClass::GetStopFrequency()
+SpectrumGUIClass::getStopFrequency()
{
gruel::scoped_lock lock(d_mutex);
double returnValue = 0.0;
@@ -212,7 +212,7 @@ SpectrumGUIClass::GetStopFrequency()
}
double
-SpectrumGUIClass::GetCenterFrequency()
+SpectrumGUIClass::getCenterFrequency()
{
gruel::scoped_lock lock(d_mutex);
double returnValue = 0.0;
@@ -222,8 +222,8 @@ SpectrumGUIClass::GetCenterFrequency()
void
-SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
- const std::complex<float>* fftBuffer,
+SpectrumGUIClass::updateWindow(const bool updateDisplayFlag,
+ const float* fftBuffer,
const uint64_t inputBufferSize,
const float* realTimeDomainData,
const uint64_t realTimeDomainDataSize,
@@ -240,11 +240,13 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
}
int64_t timeDomainBufferSize = 0;
- if(updateDisplayFlag){
- if((fftBuffer != NULL) && (bufferSize > 0)){
- memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex<float>));
+ if(updateDisplayFlag) {
+ if((fftBuffer != NULL) && (bufferSize > 0)) {
+ 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,48 +254,42 @@ 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;
-
+ if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)) {
+ 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++;
- }
}
}
// If bufferSize is zero, then just update the display by sending over the old data
- if(bufferSize < 1){
+ if(bufferSize < 1) {
bufferSize = _lastDataPointCount;
repeatDataFlag = true;
}
- else{
+ else {
// Since there is data this time, update the count
_lastDataPointCount = bufferSize;
}
const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now();
- const gruel::high_res_timer_type lastUpdateGUITime = GetLastGUIUpdateTime();
+ const gruel::high_res_timer_type lastUpdateGUITime = getLastGUIUpdateTime();
if((currentTime - lastUpdateGUITime > (4*_updateTime)*gruel::high_res_timer_tps()) &&
- (GetPendingGUIUpdateEvents() > 0) && lastUpdateGUITime != 0) {
+ (getPendingGUIUpdateEvents() > 0) && lastUpdateGUITime != 0) {
// Do not update the display if too much data is pending to be displayed
_droppedEntriesCount++;
}
- else{
+ else {
// Draw the Data
- IncrementPendingGUIUpdateEvents();
+ incrementPendingGUIUpdateEvents();
qApp->postEvent(_spectrumDisplayForm,
new SpectrumUpdateEvent(_fftPoints, bufferSize,
_realTimeDomainPoints,
@@ -307,14 +303,14 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
// Only reset the dropped entries counter if this is not
// repeat data since repeat data is dropped by the display systems
- if(!repeatDataFlag){
+ if(!repeatDataFlag) {
_droppedEntriesCount = 0;
}
}
}
float
-SpectrumGUIClass::GetPowerValue()
+SpectrumGUIClass::getPowerValue()
{
gruel::scoped_lock lock(d_mutex);
float returnValue = 0;
@@ -323,14 +319,14 @@ SpectrumGUIClass::GetPowerValue()
}
void
-SpectrumGUIClass::SetPowerValue(const float value)
+SpectrumGUIClass::setPowerValue(const float value)
{
gruel::scoped_lock lock(d_mutex);
_powerValue = value;
}
int
-SpectrumGUIClass::GetWindowType()
+SpectrumGUIClass::getWindowType()
{
gruel::scoped_lock lock(d_mutex);
int returnValue = 0;
@@ -339,14 +335,14 @@ SpectrumGUIClass::GetWindowType()
}
void
-SpectrumGUIClass::SetWindowType(const int newType)
+SpectrumGUIClass::setWindowType(const int newType)
{
gruel::scoped_lock lock(d_mutex);
_windowType = newType;
}
int
-SpectrumGUIClass::GetFFTSize()
+SpectrumGUIClass::getFFTSize()
{
int returnValue = 0;
returnValue = _fftSize;
@@ -354,10 +350,10 @@ SpectrumGUIClass::GetFFTSize()
}
int
-SpectrumGUIClass::GetFFTSizeIndex()
+SpectrumGUIClass::getFFTSizeIndex()
{
gruel::scoped_lock lock(d_mutex);
- int fftsize = GetFFTSize();
+ int fftsize = getFFTSize();
switch(fftsize) {
case(1024): return 0; break;
case(2048): return 1; break;
@@ -370,14 +366,14 @@ SpectrumGUIClass::GetFFTSizeIndex()
}
void
-SpectrumGUIClass::SetFFTSize(const int newSize)
+SpectrumGUIClass::setFFTSize(const int newSize)
{
gruel::scoped_lock lock(d_mutex);
_fftSize = newSize;
}
gruel::high_res_timer_type
-SpectrumGUIClass::GetLastGUIUpdateTime()
+SpectrumGUIClass::getLastGUIUpdateTime()
{
gruel::scoped_lock lock(d_mutex);
gruel::high_res_timer_type returnValue;
@@ -386,14 +382,14 @@ SpectrumGUIClass::GetLastGUIUpdateTime()
}
void
-SpectrumGUIClass::SetLastGUIUpdateTime(const gruel::high_res_timer_type newTime)
+SpectrumGUIClass::setLastGUIUpdateTime(const gruel::high_res_timer_type newTime)
{
gruel::scoped_lock lock(d_mutex);
_lastGUIUpdateTime = newTime;
}
unsigned int
-SpectrumGUIClass::GetPendingGUIUpdateEvents()
+SpectrumGUIClass::getPendingGUIUpdateEvents()
{
gruel::scoped_lock lock(d_mutex);
unsigned int returnValue = 0;
@@ -402,14 +398,14 @@ SpectrumGUIClass::GetPendingGUIUpdateEvents()
}
void
-SpectrumGUIClass::IncrementPendingGUIUpdateEvents()
+SpectrumGUIClass::incrementPendingGUIUpdateEvents()
{
gruel::scoped_lock lock(d_mutex);
_pendingGUIUpdateEventsCount++;
}
void
-SpectrumGUIClass::DecrementPendingGUIUpdateEvents()
+SpectrumGUIClass::decrementPendingGUIUpdateEvents()
{
gruel::scoped_lock lock(d_mutex);
if(_pendingGUIUpdateEventsCount > 0){
@@ -418,7 +414,7 @@ SpectrumGUIClass::DecrementPendingGUIUpdateEvents()
}
void
-SpectrumGUIClass::ResetPendingGUIUpdateEvents()
+SpectrumGUIClass::resetPendingGUIUpdateEvents()
{
gruel::scoped_lock lock(d_mutex);
_pendingGUIUpdateEventsCount = 0;
@@ -433,41 +429,41 @@ SpectrumGUIClass::qwidget()
}
void
-SpectrumGUIClass::SetTimeDomainAxis(double min, double max)
+SpectrumGUIClass::setTimeDomainAxis(double min, double max)
{
gruel::scoped_lock lock(d_mutex);
- _spectrumDisplayForm->SetTimeDomainAxis(min, max);
+ _spectrumDisplayForm->setTimeDomainAxis(min, max);
}
void
-SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax,
+SpectrumGUIClass::setConstellationAxis(double xmin, double xmax,
double ymin, double ymax)
{
gruel::scoped_lock lock(d_mutex);
- _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax);
+ _spectrumDisplayForm->setConstellationAxis(xmin, xmax, ymin, ymax);
}
void
-SpectrumGUIClass::SetConstellationPenSize(int size)
+SpectrumGUIClass::setConstellationPenSize(int size)
{
gruel::scoped_lock lock(d_mutex);
- _spectrumDisplayForm->SetConstellationPenSize(size);
+ _spectrumDisplayForm->setConstellationPenSize(size);
}
void
-SpectrumGUIClass::SetFrequencyAxis(double min, double max)
+SpectrumGUIClass::setFrequencyAxis(double min, double max)
{
gruel::scoped_lock lock(d_mutex);
- _spectrumDisplayForm->SetFrequencyAxis(min, max);
+ _spectrumDisplayForm->setFrequencyAxis(min, max);
}
void
-SpectrumGUIClass::SetUpdateTime(double t)
+SpectrumGUIClass::setUpdateTime(double t)
{
gruel::scoped_lock lock(d_mutex);
_updateTime = t;
- _spectrumDisplayForm->SetUpdateTime(_updateTime);
+ _spectrumDisplayForm->setUpdateTime(_updateTime);
}
diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h
index e0612413b0..9a2233d168 100644
--- a/gr-qtgui/lib/SpectrumGUIClass.h
+++ b/gr-qtgui/lib/SpectrumGUIClass.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -47,57 +47,57 @@ public:
const double newStartFrequency,
const double newStopFrequency);
~SpectrumGUIClass();
- void Reset();
+ void reset();
- void OpenSpectrumWindow(QWidget*,
+ void openSpectrumWindow(QWidget*,
const bool frequency=true, const bool waterfall=true,
const bool time=true, const bool constellation=true);
- void SetDisplayTitle(const std::string);
+ void setDisplayTitle(const std::string);
- bool GetWindowOpenFlag();
- void SetWindowOpenFlag(const bool);
+ bool getWindowOpenFlag();
+ void setWindowOpenFlag(const bool);
- void SetFrequencyRange(const double, const double, const double);
- double GetStartFrequency();
- double GetStopFrequency();
- double GetCenterFrequency();
+ void setFrequencyRange(const double, const double, const double);
+ double getStartFrequency();
+ 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,
const gruel::high_res_timer_type, const bool);
- float GetPowerValue();
- void SetPowerValue(const float);
+ float getPowerValue();
+ void setPowerValue(const float);
- int GetWindowType();
- void SetWindowType(const int);
+ int getWindowType();
+ void setWindowType(const int);
- int GetFFTSize();
- int GetFFTSizeIndex();
- void SetFFTSize(const int);
+ int getFFTSize();
+ int getFFTSizeIndex();
+ void setFFTSize(const int);
- gruel::high_res_timer_type GetLastGUIUpdateTime();
- void SetLastGUIUpdateTime(const gruel::high_res_timer_type);
+ gruel::high_res_timer_type getLastGUIUpdateTime();
+ void setLastGUIUpdateTime(const gruel::high_res_timer_type);
- unsigned int GetPendingGUIUpdateEvents();
- void IncrementPendingGUIUpdateEvents();
- void DecrementPendingGUIUpdateEvents();
- void ResetPendingGUIUpdateEvents();
+ unsigned int getPendingGUIUpdateEvents();
+ void incrementPendingGUIUpdateEvents();
+ void decrementPendingGUIUpdateEvents();
+ void resetPendingGUIUpdateEvents();
static const long MAX_FFT_SIZE;
static const long MIN_FFT_SIZE;
QWidget* qwidget();
- void SetTimeDomainAxis(double min, double max);
- void SetConstellationAxis(double xmin, double xmax,
+ void setTimeDomainAxis(double min, double max);
+ void setConstellationAxis(double xmin, double xmax,
double ymin, double ymax);
- void SetConstellationPenSize(int size);
- void SetFrequencyAxis(double min, double max);
+ void setConstellationPenSize(int size);
+ void setFrequencyAxis(double min, double max);
- void SetUpdateTime(double t);
+ void setUpdateTime(double t);
protected:
@@ -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..032da2547d 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,7 +28,9 @@
#include <qwt_scale_draw.h>
#include <qwt_legend.h>
#include <QColor>
+#include <cmath>
#include <iostream>
+#include <volk/volk.h>
class TimePrecisionClass
{
@@ -42,12 +44,12 @@ public:
{
}
- virtual unsigned int GetTimePrecision() const
+ virtual unsigned int getTimePrecision() const
{
return _timePrecision;
}
- virtual void SetTimePrecision(const unsigned int newPrecision)
+ virtual void setTimePrecision(const unsigned int newPrecision)
{
_timePrecision = newPrecision;
}
@@ -73,18 +75,29 @@ public:
updateDisplay();
}
- void SetUnitType(const std::string &type)
+ void setUnitType(const std::string &type)
{
_unitType = type;
}
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()).
- arg(_unitType.c_str()).
- arg(p.y(), 0, 'f', 4));
+ QwtText t;
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ if((dp.y() > 0.0001) && (dp.y() < 10000)) {
+ t.setText(QString("%1 %2, %3 V").
+ arg(dp.x(), 0, 'f', getTimePrecision()).
+ arg(_unitType.c_str()).
+ arg(dp.y(), 0, 'f', 4));
+ }
+ else {
+ t.setText(QString("%1 %2, %3 V").
+ arg(dp.x(), 0, 'f', getTimePrecision()).
+ arg(_unitType.c_str()).
+ arg(dp.y(), 0, 'e', 4));
+ }
return t;
}
@@ -93,11 +106,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 +123,17 @@ 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
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
+ Qt::RightButton);
-#if QWT_VERSION < 0x060000
- // We don't need the cache here
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
- canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
-#endif
+ const QColor c(Qt::darkRed);
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
- QPalette palette;
- palette.setColor(canvas()->backgroundRole(), QColor("white"));
- canvas()->setPalette(palette);
+ d_semilogx = false;
+ d_semilogy = false;
setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
setXaxis(0, _numPoints);
@@ -132,7 +142,7 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
setYaxis(-2.0, 2.0);
setAxisTitle(QwtPlot::yLeft, "Amplitude");
-
+
QList<QColor> colors;
colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
<< QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta)
@@ -148,58 +158,22 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
_plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
_plot_curve[i]->attach(this);
_plot_curve[i]->setPen(QPen(colors[i]));
+ _plot_curve[i]->setRenderHint(QwtPlotItem::RenderAntialiased);
+ 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,102 +186,123 @@ 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
+ }
+
+ _resetXAxisPoints();
}
- setXaxis(0, numDataPoints);
- _resetXAxisPoints();
- }
+ for(int i = 0; i < _nplots; i++) {
+ if(d_semilogy) {
+ for(int n = 0; n < numDataPoints; n++)
+ _dataPoints[i][n] = fabs(dataPoints[i][n]);
+ }
+ else {
+ memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
+ }
+ }
- for(int i = 0; i < _nplots; i++) {
- memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
+ if(_autoscale_state) {
+ double bottom=1e20, top=-1e20;
+ for(int n = 0; n < _nplots; n++) {
+ for(int64_t point = 0; point < numDataPoints; point++) {
+ if(_dataPoints[n][point] < bottom) {
+ bottom = _dataPoints[n][point];
+ }
+ if(_dataPoints[n][point] > top) {
+ top = _dataPoints[n][point];
+ }
+ }
+ }
+ _autoScale(bottom, top);
+ }
+
+ replot();
}
-
- replot();
}
}
-void TimeDomainDisplayPlot::_resetXAxisPoints()
+void
+TimeDomainDisplayPlot::_resetXAxisPoints()
{
double delt = 1.0/_sampleRate;
for(long loc = 0; loc < _numPoints; loc++){
_xAxisPoints[loc] = loc*delt;
}
- setAxisScale(QwtPlot::xBottom, 0, _numPoints*delt);
// Set up zoomer base for maximum unzoom x-axis
// and reset to maximum unzoom level
QwtDoubleRect zbase = _zoomer->zoomBase();
- zbase.setLeft(0);
+
+ if(d_semilogx) {
+ setAxisScale(QwtPlot::xBottom, 1e-1, _numPoints*delt);
+ zbase.setLeft(1e-1);
+ }
+ else {
+ setAxisScale(QwtPlot::xBottom, 0, _numPoints*delt);
+ zbase.setLeft(0);
+ }
+
zbase.setRight(_numPoints*delt);
_zoomer->zoom(zbase);
_zoomer->setZoomBase(zbase);
_zoomer->zoom(0);
+
}
-void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
+void
+TimeDomainDisplayPlot::_autoScale(double bottom, double top)
{
- plotItem->setVisible(!on);
+ // Auto scale the y-axis with a margin of 20% (10 dB for log scale)
+ double _bot = bottom - fabs(bottom)*0.20;
+ double _top = top + fabs(top)*0.20;
+ if(d_semilogy) {
+ if(bottom > 0) {
+ setYaxis(_bot-10, _top+10);
+ }
+ else {
+ setYaxis(1e-3, _top+10);
+ }
+ }
+ else {
+ setYaxis(_bot, _top);
+ }
+}
+
+void
+TimeDomainDisplayPlot::setAutoScale(bool state)
+{
+ _autoscale_state = state;
}
void
-TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
+TimeDomainDisplayPlot::setSampleRate(double sr, double units,
const std::string &strunits)
{
double newsr = sr/units;
@@ -320,26 +315,56 @@ TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
//double display_units = ceil(log10(units)/2.0);
double display_units = 4;
setAxisTitle(QwtPlot::xBottom, QString("Time (%1)").arg(strunits.c_str()));
- ((TimeDomainDisplayZoomer*)_zoomer)->SetTimePrecision(display_units);
- ((TimeDomainDisplayZoomer*)_zoomer)->SetUnitType(strunits);
+ ((TimeDomainDisplayZoomer*)_zoomer)->setTimePrecision(display_units);
+ ((TimeDomainDisplayZoomer*)_zoomer)->setUnitType(strunits);
}
}
+void
+TimeDomainDisplayPlot::stemPlot(bool en)
+{
+ if(en) {
+ for(int i = 0; i < _nplots; i++) {
+ _plot_curve[i]->setStyle(QwtPlotCurve::Sticks);
+ setLineMarker(i, QwtSymbol::Ellipse);
+ }
+ }
+ else {
+ for(int i = 0; i < _nplots; i++) {
+ _plot_curve[i]->setStyle(QwtPlotCurve::Lines);
+ setLineMarker(i, QwtSymbol::NoSymbol);
+ }
+ }
+}
void
-TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
+TimeDomainDisplayPlot::setSemilogx(bool en)
{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
+ d_semilogx = en;
+ if(!d_semilogx) {
+ setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
+ }
+ else {
+ setAxisScaleEngine(QwtPlot::xBottom, new QwtLog10ScaleEngine);
+ }
+ _resetXAxisPoints();
}
void
-TimeDomainDisplayPlot::OnPickerPointSelected6(const QPointF & p)
+TimeDomainDisplayPlot::setSemilogy(bool en)
{
- QPointF point = p;
- //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
- emit plotPointSelected(point);
+ if(d_semilogy != en) {
+ d_semilogy = en;
+ double max = axisScaleDiv(QwtPlot::yLeft)->upperBound();
+ if(!d_semilogy) {
+ setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
+ setYaxis(-pow(10.0, max/10.0), pow(10.0, max/10.0));
+ }
+ else {
+ setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
+ setYaxis(1e-10, 10.0*log10(max));
+ }
+ }
}
#endif /* TIME_DOMAIN_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h
index 356da25ad4..9996f84fc3 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,83 +20,48 @@
* 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:
TimeDomainDisplayPlot(int nplots, QWidget*);
virtual ~TimeDomainDisplayPlot();
- void PlotNewData(const std::vector<double*> dataPoints,
+ 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 stemPlot(bool en);
- void resizeSlot( QSize *s );
- void SetSampleRate(double sr, double units,
+public slots:
+ 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:
+ void setAutoScale(bool state);
+ void setSemilogx(bool en);
+ void setSemilogy(bool en);
private:
void _resetXAxisPoints();
-
- int _nplots;
- std::vector<QwtPlotCurve*> _plot_curve;
-
- QwtPlotPanner* _panner;
- QwtPlotZoomer* _zoomer;
-
- QwtDblClickPlotPicker *_picker;
- QwtPlotMagnifier *_magnifier;
+ void _autoScale(double bottom, double top);
std::vector<double*> _dataPoints;
double* _xAxisPoints;
double _sampleRate;
- int64_t _numPoints;
+ bool d_semilogx;
+ bool d_semilogy;
};
-#endif /* TIME_DOMAIN_DISPLAY_PLOT_HPP */
+#endif /* TIME_DOMAIN_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/TimeRasterDisplayPlot.cc b/gr-qtgui/lib/TimeRasterDisplayPlot.cc
new file mode 100644
index 0000000000..48fb7f7b4a
--- /dev/null
+++ b/gr-qtgui/lib/TimeRasterDisplayPlot.cc
@@ -0,0 +1,570 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 TIMERASTER_DISPLAY_PLOT_C
+#define TIMERASTER_DISPLAY_PLOT_C
+
+#include <TimeRasterDisplayPlot.h>
+
+#include "qtgui_types.h"
+#include <qwt_color_map.h>
+#include <qwt_scale_draw.h>
+#include <qwt_legend.h>
+#include <qwt_legend_item.h>
+#include <qwt_plot_layout.h>
+#include <QColor>
+#include <iostream>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+namespace pt = boost::posix_time;
+
+#include <QDebug>
+
+/***********************************************************************
+ * Text scale widget to provide X (time) axis text
+ **********************************************************************/
+class QwtXScaleDraw: public QwtScaleDraw, public TimeScaleData
+{
+public:
+ QwtXScaleDraw():QwtScaleDraw(),TimeScaleData() { }
+
+ virtual ~QwtXScaleDraw() { }
+
+ virtual QwtText label(double value) const
+ {
+ double secs = double(value * getSecondsPerLine());
+ return QwtText(QString("").sprintf("%.2f", secs));
+ }
+
+ virtual void initiateUpdate()
+ {
+ // Do this in one call rather than when zeroTime and secondsPerLine
+ // updates is to prevent the display from being updated too often...
+ invalidateCache();
+ }
+};
+
+/***********************************************************************
+ * Text scale widget to provide Y axis text
+ **********************************************************************/
+class QwtYScaleDraw: public QwtScaleDraw
+{
+public:
+ QwtYScaleDraw(): QwtScaleDraw(), _rows(0) { }
+
+ virtual ~QwtYScaleDraw() { }
+
+ virtual QwtText label(double value) const
+ {
+ if(_rows > 0)
+ value = _rows - value;
+ return QwtText(QString("").sprintf("%.0f", value));
+ }
+
+ virtual void initiateUpdate()
+ {
+ // Do this in one call rather than when zeroTime and secondsPerLine
+ // updates is to prevent the display from being updated too often...
+ invalidateCache();
+ }
+
+ void setRows(double rows) { rows>0 ? _rows = rows : _rows = 0; }
+
+private:
+ double _rows;
+};
+
+class TimePrecisionClass
+{
+public:
+ TimePrecisionClass(const int timePrecision)
+ {
+ _timePrecision = timePrecision;
+ }
+
+ virtual ~TimePrecisionClass()
+ {
+ }
+
+ virtual unsigned int getTimePrecision() const
+ {
+ return _timePrecision;
+ }
+
+ virtual void setTimePrecision(const unsigned int newPrecision)
+ {
+ _timePrecision = newPrecision;
+ }
+protected:
+ unsigned int _timePrecision;
+};
+
+/***********************************************************************
+ * Widget to provide mouse pointer coordinate text
+ **********************************************************************/
+class TimeRasterZoomer: public QwtPlotZoomer, public TimePrecisionClass,
+ public TimeScaleData
+{
+public:
+ TimeRasterZoomer(QwtPlotCanvas* canvas, double rows, double cols,
+ const unsigned int timePrecision)
+ : QwtPlotZoomer(canvas), TimePrecisionClass(timePrecision), TimeScaleData(),
+ d_rows(static_cast<double>(rows)), d_cols(static_cast<double>(cols))
+ {
+ setTrackerMode(QwtPicker::AlwaysOn);
+ }
+
+ virtual ~TimeRasterZoomer()
+ {
+ }
+
+ virtual void updateTrackerText()
+ {
+ updateDisplay();
+ }
+
+ void setUnitType(const std::string &type)
+ {
+ _unitType = type;
+ }
+
+ void setColumns(const double cols)
+ {
+ d_cols = cols;
+ }
+
+ void setRows(const double rows)
+ {
+ d_rows = rows;
+ }
+
+protected:
+ using QwtPlotZoomer::trackerText;
+ virtual QwtText trackerText( QPoint const &p ) const
+ {
+ QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
+ double x = dp.x() * getSecondsPerLine();
+ //double y = dp.y() * getSecondsPerLine() * d_cols;
+ double y = floor(d_rows - dp.y());
+ QwtText t(QString("%1 %2, %3")
+ .arg(x, 0, 'f', getTimePrecision())
+ .arg(_unitType.c_str())
+ .arg(y, 0, 'f', 0));
+ return t;
+ }
+
+private:
+ std::string _unitType;
+ double d_rows, d_cols;
+};
+
+/*********************************************************************
+* Main time raster plot widget
+*********************************************************************/
+TimeRasterDisplayPlot::TimeRasterDisplayPlot(int nplots,
+ double samp_rate,
+ double rows, double cols,
+ QWidget* parent)
+ : DisplayPlot(nplots, parent)
+{
+ _zoomer = NULL; // need this for proper init
+
+ resize(parent->width(), parent->height());
+
+ d_samp_rate = samp_rate;
+ d_cols = cols;
+ d_rows = rows;
+ _numPoints = d_cols;
+
+ setAxisScaleDraw(QwtPlot::xBottom, new QwtXScaleDraw());
+ setAxisScaleDraw(QwtPlot::yLeft, new QwtYScaleDraw());
+
+ for(int i = 0; i < _nplots; i++) {
+ d_data.push_back(new TimeRasterData(d_rows, d_cols));
+ d_raster.push_back(new PlotTimeRaster("Raster"));
+ d_raster[i]->setData(d_data[i]);
+
+ // a hack around the fact that we aren't using plot curves for the
+ // raster plots.
+ _plot_curve.push_back(new QwtPlotCurve(QString("Data")));
+
+ d_raster[i]->attach(this);
+
+ d_color_map_type.push_back(INTENSITY_COLOR_MAP_TYPE_BLACK_HOT);
+ setAlpha(i, 255/_nplots);
+ }
+
+ // Set bottom plot with no transparency as a base
+ setAlpha(0, 255);
+
+ // LeftButton for the zooming
+ // MidButton for the panning
+ // RightButton: zoom out by 1
+ // Ctrl+RighButton: zoom out to full size
+ _zoomer = new TimeRasterZoomer(canvas(), d_rows, d_cols, 0);
+#if QWT_VERSION < 0x060000
+ _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection);
+#endif
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
+ Qt::RightButton);
+
+ const QColor c(Qt::red);
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
+
+ // Set intensity color now (needed _zoomer before we could do this).
+ // We've made sure the old type is different than here so we'll
+ // force and update.
+ for(int i = 0; i < _nplots; i++) {
+ setIntensityColorMapType(i, INTENSITY_COLOR_MAP_TYPE_WHITE_HOT,
+ QColor("white"), QColor("white"));
+ }
+
+ _updateIntensityRangeDisplay();
+
+ reset();
+}
+
+TimeRasterDisplayPlot::~TimeRasterDisplayPlot()
+{
+}
+
+void
+TimeRasterDisplayPlot::reset()
+{
+ for(int i = 0; i < _nplots; i++) {
+ d_data[i]->resizeData(d_rows, d_cols);
+ d_data[i]->reset();
+ }
+
+ // Update zoomer/picker text units
+ std::string strunits[4] = {"sec", "ms", "us", "ns"};
+ double units10 = floor(log10(d_samp_rate));
+ double units3 = std::max(floor(units10/3), 0.0);
+ double units = pow(10, (units10-fmod(units10, 3.0)));
+ int iunit = static_cast<int>(units3);
+
+ double sec_per_samp = units/d_samp_rate;
+
+ QwtYScaleDraw* yScale = (QwtYScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
+ yScale->setRows(d_rows);
+
+ QwtXScaleDraw* xScale = (QwtXScaleDraw*)axisScaleDraw(QwtPlot::xBottom);
+ xScale->setSecondsPerLine(sec_per_samp);
+ setAxisTitle(QwtPlot::xBottom, QString("Time (%1)")
+ .arg(strunits[iunit].c_str()));
+ xScale->initiateUpdate();
+
+ // Load up the new base zoom settings
+ if(_zoomer) {
+ double display_units = 4;
+ ((TimeRasterZoomer*)_zoomer)->setColumns(d_cols);
+ ((TimeRasterZoomer*)_zoomer)->setRows(d_rows);
+ ((TimeRasterZoomer*)_zoomer)->setSecondsPerLine(sec_per_samp);
+ ((TimeRasterZoomer*)_zoomer)->setTimePrecision(display_units);
+ ((TimeRasterZoomer*)_zoomer)->setUnitType(strunits[iunit]);
+
+ QwtDoubleRect newSize = _zoomer->zoomBase();
+ newSize.setLeft(0);
+ newSize.setWidth(d_cols);
+ newSize.setBottom(0);
+ newSize.setHeight(d_rows);
+
+ _zoomer->zoom(newSize);
+ _zoomer->setZoomBase(newSize);
+ _zoomer->zoom(0);
+ }
+}
+
+void
+TimeRasterDisplayPlot::setNumRows(double rows)
+{
+ d_rows = rows;
+ reset();
+}
+
+void
+TimeRasterDisplayPlot::setNumCols(double cols)
+{
+ d_cols = cols;
+ reset();
+}
+
+void
+TimeRasterDisplayPlot::setAlpha(int which, int alpha)
+{
+ d_raster[which]->setAlpha(alpha);
+}
+
+void
+TimeRasterDisplayPlot::setSampleRate(double samprate)
+{
+ d_samp_rate = samprate;
+ reset();
+}
+
+double
+TimeRasterDisplayPlot::numRows() const
+{
+ return d_rows;
+}
+
+double
+TimeRasterDisplayPlot::numCols() const
+{
+ return d_cols;
+}
+
+int
+TimeRasterDisplayPlot::getAlpha(int which)
+{
+ return d_raster[which]->alpha();
+}
+
+void
+TimeRasterDisplayPlot::setPlotDimensions(const double rows, const double cols,
+ const double units, const std::string &strunits)
+{
+ bool rst = false;
+ if((rows != d_rows) || (cols != d_cols))
+ rst = true;
+
+ d_rows = rows;
+ d_cols = cols;
+
+ if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)) {
+ if(rst) {
+ reset();
+ }
+ }
+}
+
+void
+TimeRasterDisplayPlot::plotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints)
+{
+ if(!_stop) {
+ if(numDataPoints > 0) {
+ for(int i = 0; i < _nplots; i++) {
+ d_data[i]->addData(dataPoints[i], numDataPoints);
+ d_raster[i]->invalidateCache();
+ d_raster[i]->itemChanged();
+ }
+
+ replot();
+ }
+ }
+}
+
+void
+TimeRasterDisplayPlot::plotNewData(const double* dataPoints,
+ const int64_t numDataPoints)
+{
+ std::vector<double*> vecDataPoints;
+ vecDataPoints.push_back((double*)dataPoints);
+ plotNewData(vecDataPoints, numDataPoints);
+}
+
+void
+TimeRasterDisplayPlot::setIntensityRange(const double minIntensity,
+ const double maxIntensity)
+{
+ for(int i = 0; i < _nplots; i++) {
+#if QWT_VERSION < 0x060000
+ d_data[i]->setRange(QwtDoubleInterval(minIntensity, maxIntensity));
+#else
+ d_data[i]->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity));
+#endif
+
+ emit updatedLowerIntensityLevel(minIntensity);
+ emit updatedUpperIntensityLevel(maxIntensity);
+
+ _updateIntensityRangeDisplay();
+ }
+}
+
+double
+TimeRasterDisplayPlot::getMinIntensity(int which) const
+{
+#if QWT_VERSION < 0x060000
+ QwtDoubleInterval r = d_data[which]->range();
+#else
+ QwtInterval r = d_data[which]->interval(Qt::ZAxis);
+#endif
+
+ return r.minValue();
+}
+
+double
+TimeRasterDisplayPlot::getMaxIntensity(int which) const
+{
+#if QWT_VERSION < 0x060000
+ QwtDoubleInterval r = d_data[which]->range();
+#else
+ QwtInterval r = d_data[which]->interval(Qt::ZAxis);
+#endif
+
+ return r.maxValue();
+}
+
+void
+TimeRasterDisplayPlot::replot()
+{
+ // Update the x-axis display
+ if(axisWidget(QwtPlot::yLeft) != NULL) {
+ axisWidget(QwtPlot::yLeft)->update();
+ }
+
+ // Update the y-axis display
+ if(axisWidget(QwtPlot::xBottom) != NULL) {
+ axisWidget(QwtPlot::xBottom)->update();
+ }
+
+ if(_zoomer != NULL) {
+ ((TimeRasterZoomer*)_zoomer)->updateTrackerText();
+ }
+
+ QwtPlot::replot();
+}
+
+int
+TimeRasterDisplayPlot::getIntensityColorMapType(int which) const
+{
+ if(which >= (int)d_color_map_type.size())
+ throw std::runtime_error("TimerasterDisplayPlot::GetIntesityColorMap: invalid which.\n");
+
+ return d_color_map_type[which];
+}
+
+void
+TimeRasterDisplayPlot::setIntensityColorMapType(const int which,
+ const int newType,
+ const QColor lowColor,
+ const QColor highColor)
+{
+ if(which >= (int)d_color_map_type.size())
+ throw std::runtime_error("TimerasterDisplayPlot::setIntesityColorMap: invalid which.\n");
+
+ if((d_color_map_type[which] != newType) ||
+ ((newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED) &&
+ (lowColor.isValid() && highColor.isValid()))) {
+ switch(newType) {
+ case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR: {
+ d_color_map_type[which] = newType;
+
+ d_raster[which]->setColorMap(new ColorMap_MultiColor());
+ if(_zoomer)
+ _zoomer->setTrackerPen(QColor(Qt::black));
+ break;
+ }
+ case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT: {
+ d_color_map_type[which] = newType;
+ d_raster[which]->setColorMap(new ColorMap_WhiteHot());
+ break;
+ }
+ case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT: {
+ d_color_map_type[which] = newType;
+ d_raster[which]->setColorMap(new ColorMap_BlackHot());
+ break;
+ }
+ case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT: {
+ d_color_map_type[which] = newType;
+ d_raster[which]->setColorMap(new ColorMap_Incandescent());
+ break;
+ }
+ case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED: {
+ d_low_intensity = lowColor;
+ d_high_intensity = highColor;
+ d_color_map_type[which] = newType;
+ d_raster[which]->setColorMap(new ColorMap_UserDefined(lowColor, highColor));
+ break;
+ }
+ default: break;
+ }
+
+ _updateIntensityRangeDisplay();
+ }
+}
+
+const QColor
+TimeRasterDisplayPlot::getUserDefinedLowIntensityColor() const
+{
+ return d_low_intensity;
+}
+
+const QColor
+TimeRasterDisplayPlot::getUserDefinedHighIntensityColor() const
+{
+ return d_high_intensity;
+}
+
+void
+TimeRasterDisplayPlot::_updateIntensityRangeDisplay()
+{
+ QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight);
+ rightAxis->setTitle("Intensity");
+ rightAxis->setColorBarEnabled(true);
+
+ for(int i = 0; i < _nplots; i++) {
+#if QWT_VERSION < 0x060000
+ rightAxis->setColorMap(d_raster[i]->data()->range(),
+ d_raster[i]->colorMap());
+ setAxisScale(QwtPlot::yRight,
+ d_raster[i]->data()->range().minValue(),
+ d_raster[i]->data()->range().maxValue());
+#else
+ QwtInterval intv = d_raster[i]->interval(Qt::ZAxis);
+ switch(d_color_map_type[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(d_low_intensity,
+ d_high_intensity));
+ break;
+ default:
+ rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break;
+ }
+ setAxisScale(QwtPlot::yRight, intv.minValue(), intv.maxValue());
+#endif
+
+ enableAxis(QwtPlot::yRight);
+
+ plotLayout()->setAlignCanvasToScales(true);
+
+ // Tell the display to redraw everything
+ d_raster[i]->invalidateCache();
+ d_raster[i]->itemChanged();
+ }
+
+ // Draw again
+ replot();
+}
+
+#endif /* TIMERASTER_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/TimeRasterDisplayPlot.h b/gr-qtgui/lib/TimeRasterDisplayPlot.h
new file mode 100644
index 0000000000..e4e292a54d
--- /dev/null
+++ b/gr-qtgui/lib/TimeRasterDisplayPlot.h
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 TIMERASTER_DISPLAY_PLOT_H
+#define TIMERASTER_DISPLAY_PLOT_H
+
+#include <stdint.h>
+#include <cstdio>
+#include <vector>
+#include <qwt_plot_rasteritem.h>
+#include "DisplayPlot.h"
+#include "timeRasterGlobalData.h"
+#include "plot_raster.h"
+#include <gruel/high_res_timer.h>
+
+#if QWT_VERSION < 0x060000
+#include <plot_waterfall.h>
+#else
+#include <qwt_compat.h>
+#endif
+
+class TimeRasterDisplayPlot: public DisplayPlot
+{
+ Q_OBJECT
+
+public:
+ TimeRasterDisplayPlot(int nplots,
+ double samp_rate,
+ double rows, double cols,
+ QWidget*);
+ virtual ~TimeRasterDisplayPlot();
+
+ void reset();
+
+ void setNumRows(double rows);
+ void setNumCols(double cols);
+ void setAlpha(int which, int alpha);
+ void setSampleRate(double samprate);
+
+ double numRows() const;
+ double numCols() const;
+
+ int getAlpha(int which);
+
+ void setPlotDimensions(const double rows, const double cols,
+ const double units, const std::string &strunits);
+
+ void plotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints);
+
+ void plotNewData(const double* dataPoints,
+ const int64_t numDataPoints);
+
+ void setIntensityRange(const double minIntensity,
+ const double maxIntensity);
+
+ void replot(void);
+
+ int getIntensityColorMapType(int) const;
+ void setIntensityColorMapType(const int, const int, const QColor, const QColor);
+ const QColor getUserDefinedLowIntensityColor() const;
+ const QColor getUserDefinedHighIntensityColor() const;
+
+ double getMinIntensity(int which) const;
+ double getMaxIntensity(int which) const;
+
+signals:
+ void updatedLowerIntensityLevel(const double);
+ void updatedUpperIntensityLevel(const double);
+
+private:
+ void _updateIntensityRangeDisplay();
+
+ std::vector<TimeRasterData*> d_data;
+ std::vector<PlotTimeRaster*> d_raster;
+
+ double d_samp_rate;
+ double d_rows, d_cols;
+
+ std::vector<int> d_color_map_type;
+ QColor d_low_intensity;
+ QColor d_high_intensity;
+};
+
+#endif /* TIMERASTER_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc
index 63eb57ffe8..05c89e3ecb 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,141 +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:
-
-};
-
-static QString
-make_time_label(double secs)
-{
- std::string time_str = pt::to_simple_string(pt::from_time_t(time_t(secs)));
-
- // lops off the YYYY-mmm-DD part of the string
- size_t ind = time_str.find(" ");
- if(ind != std::string::npos)
- time_str = time_str.substr(ind);
-
- return QString("").sprintf("%s.%03ld", time_str.c_str(), long(std::fmod(secs*1000, 1000)));
-}
+#include <QDebug>
+/***********************************************************************
+ * Text scale widget to provide Y (time) axis text
+ **********************************************************************/
class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData
{
public:
@@ -173,8 +55,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 +72,10 @@ private:
};
-class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData,
+/***********************************************************************
+ * Widget to provide mouse pointer coordinate text
+ **********************************************************************/
+class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData,
public FreqOffsetAndPrecisionClass
{
public:
@@ -210,19 +95,21 @@ public:
updateDisplay();
}
- void SetUnitType(const std::string &type)
+ void setUnitType(const std::string &type)
{
_unitType = type;
}
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 +117,56 @@ 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;
- _startFrequency = 0;
- _stopFrequency = 4000;
+ _zoomer = NULL; // need this for proper init
+ _startFrequency = -1;
+ _stopFrequency = 1;
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;
-
- 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(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR);
+ setIntensityColorMapType(i, _intensityColorMapType[i],
+ QColor("white"), QColor("white"));
+
+ setAlpha(i, 255/_nplots);
+ }
+
+ // Set bottom plot with no transparency as a base
+ setAlpha(0, 255);
// LeftButton for the zooming
// MidButton for the panning
@@ -338,79 +181,49 @@ 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);
- _UpdateIntensityRangeDisplay();
+ _updateIntensityRangeDisplay();
_xAxisMultiplier = 1;
}
WaterfallDisplayPlot::~WaterfallDisplayPlot()
{
- delete d_data;
- delete d_spectrogram;
}
void
-WaterfallDisplayPlot::Reset()
+WaterfallDisplayPlot::resetAxis()
{
- 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);
// Load up the new base zoom settings
- QwtDoubleRect newSize = _zoomer->zoomBase();
- newSize.setLeft(_startFrequency);
- newSize.setWidth(_stopFrequency-_startFrequency);
- _zoomer->zoom(newSize);
- _zoomer->setZoomBase(newSize);
+ QwtDoubleRect zbase = _zoomer->zoomBase();
+ zbase.setLeft(_startFrequency);
+ zbase.setRight(_stopFrequency);
+ _zoomer->zoom(zbase);
+ _zoomer->setZoomBase(zbase);
+ _zoomer->setZoomBase(true);
_zoomer->zoom(0);
}
void
-WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq,
- const double constStopFreq,
- const double constCenterFreq,
- const bool useCenterFrequencyFlag,
+WaterfallDisplayPlot::setFrequencyRange(const double centerfreq,
+ const double bandwidth,
const double units, const std::string &strunits)
{
- double startFreq = constStartFreq / units;
- double stopFreq = constStopFreq / units;
- double centerFreq = constCenterFreq / units;
+ double startFreq = (centerfreq - bandwidth/2.0f) / units;
+ double stopFreq = (centerfreq + bandwidth/2.0f) / units;
_xAxisMultiplier = units;
- _useCenterFrequencyFlag = useCenterFrequencyFlag;
-
- if(_useCenterFrequencyFlag){
- startFreq = (startFreq + centerFreq);
- stopFreq = (stopFreq + centerFreq);
- }
-
bool reset = false;
if((startFreq != _startFrequency) || (stopFreq != _stopFrequency))
reset = true;
@@ -419,92 +232,135 @@ 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) {
- Reset();
+ resetAxis();
}
- ((WaterfallZoomer*)_zoomer)->SetFrequencyPrecision(display_units);
- ((WaterfallZoomer*)_zoomer)->SetUnitType(strunits);
+ ((WaterfallZoomer*)_zoomer)->setFrequencyPrecision(display_units);
+ ((WaterfallZoomer*)_zoomer)->setUnitType(strunits);
}
}
}
double
-WaterfallDisplayPlot::GetStartFrequency() const
+WaterfallDisplayPlot::getStartFrequency() const
{
return _startFrequency;
}
double
-WaterfallDisplayPlot::GetStopFrequency() const
+WaterfallDisplayPlot::getStopFrequency() const
{
return _stopFrequency;
}
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();
+ resetAxis();
- d_spectrogram->invalidateCache();
- d_spectrogram->itemChanged();
+ for(int i = 0; i < _nplots; i++) {
+ d_spectrogram[i]->invalidateCache();
+ d_spectrogram[i]->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);
- timeScale->SetZeroTime(timestamp);
+ timeScale->setSecondsPerLine(timePerFFT);
+ timeScale->setZeroTime(timestamp);
- ((WaterfallZoomer*)_zoomer)->SetSecondsPerLine(timePerFFT);
- ((WaterfallZoomer*)_zoomer)->SetZeroTime(timestamp);
+ ((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::SetIntensityRange(const double minIntensity,
+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[i]->setRange(QwtDoubleInterval(minIntensity, maxIntensity));
+#else
+ d_data[i]->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity));
+#endif
+
+ emit updatedLowerIntensityLevel(minIntensity);
+ emit updatedUpperIntensityLevel(maxIntensity);
+
+ _updateIntensityRangeDisplay();
+ }
+}
+
+double
+WaterfallDisplayPlot::getMinIntensity(int which) const
+{
#if QWT_VERSION < 0x060000
- d_data->setRange(QwtDoubleInterval(minIntensity, maxIntensity));
+ QwtDoubleInterval r = d_data[which]->range();
#else
- d_data->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity));
+ QwtInterval r = d_data[which]->interval(Qt::ZAxis);
#endif
- emit UpdatedLowerIntensityLevel(minIntensity);
- emit UpdatedUpperIntensityLevel(maxIntensity);
+ return r.minValue();
+}
- _UpdateIntensityRangeDisplay();
+double
+WaterfallDisplayPlot::getMaxIntensity(int which) const
+{
+#if QWT_VERSION < 0x060000
+ QwtDoubleInterval r = d_data[which]->range();
+#else
+ QwtInterval r = d_data[which]->interval(Qt::ZAxis);
+#endif
+
+ return r.maxValue();
}
void
@@ -513,8 +369,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
@@ -535,137 +391,179 @@ WaterfallDisplayPlot::replot()
}
void
-WaterfallDisplayPlot::resizeSlot( QSize *s )
+WaterfallDisplayPlot::clearData()
{
- resize(s->width(), s->height());
+ for(int i = 0; i < _nplots; i++) {
+ d_data[i]->reset();
+ }
}
+
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;
}
default: break;
}
- _UpdateIntensityRangeDisplay();
+ _updateIntensityRangeDisplay();
}
}
+void
+WaterfallDisplayPlot::setIntensityColorMapType1(int newType)
+{
+ setIntensityColorMapType(0, newType, _userDefinedLowIntensityColor, _userDefinedHighIntensityColor);
+}
+
+int
+WaterfallDisplayPlot::getIntensityColorMapType1() const
+{
+ return getIntensityColorMapType(0);
+}
+
+void
+WaterfallDisplayPlot::setUserDefinedLowIntensityColor(QColor c)
+{
+ _userDefinedLowIntensityColor = c;
+}
+
const QColor
-WaterfallDisplayPlot::GetUserDefinedLowIntensityColor() const
+WaterfallDisplayPlot::getUserDefinedLowIntensityColor() const
{
return _userDefinedLowIntensityColor;
}
+void
+WaterfallDisplayPlot::setUserDefinedHighIntensityColor(QColor c)
+{
+ _userDefinedHighIntensityColor = c;
+}
+
const QColor
-WaterfallDisplayPlot::GetUserDefinedHighIntensityColor() const
+WaterfallDisplayPlot::getUserDefinedHighIntensityColor() const
{
return _userDefinedHighIntensityColor;
}
+int
+WaterfallDisplayPlot::getAlpha(int which)
+{
+ return d_spectrogram[which]->alpha();
+}
+
+void
+WaterfallDisplayPlot::setAlpha(int which, int alpha)
+{
+ d_spectrogram[which]->setAlpha(alpha);
+}
+
void
-WaterfallDisplayPlot::_UpdateIntensityRangeDisplay()
+WaterfallDisplayPlot::_updateIntensityRangeDisplay()
{
QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight);
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 +572,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..6637adc594 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,88 +37,85 @@
#include <qwt_compat.h>
#endif
-class WaterfallDisplayPlot:public QwtPlot{
+class WaterfallDisplayPlot: public DisplayPlot
+{
Q_OBJECT
+ Q_PROPERTY ( int intensity_color_map_type1 READ getIntensityColorMapType1 WRITE setIntensityColorMapType1 )
+ Q_PROPERTY ( QColor low_intensity_color READ getUserDefinedLowIntensityColor WRITE setUserDefinedLowIntensityColor )
+ Q_PROPERTY ( QColor high_intensity_color READ getUserDefinedHighIntensityColor WRITE setUserDefinedHighIntensityColor )
+
+
public:
- WaterfallDisplayPlot(QWidget*);
+ WaterfallDisplayPlot(int nplots, QWidget*);
virtual ~WaterfallDisplayPlot();
- void Reset();
+ void resetAxis();
- void SetFrequencyRange(const double, const double,
- const double, const bool,
+ void setFrequencyRange(const double, const double,
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);
+ // 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);
- virtual void replot(void);
+ void setIntensityRange(const double minIntensity, const double maxIntensity);
+ double getMinIntensity(int which) const;
+ double getMaxIntensity(int which) const;
- int GetIntensityColorMapType()const;
- void SetIntensityColorMapType( const int, const QColor, const QColor );
- const QColor GetUserDefinedLowIntensityColor()const;
- const QColor GetUserDefinedHighIntensityColor()const;
+ void replot(void);
+ void clearData();
- 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
- };
+ int getIntensityColorMapType(int) const;
+ int getIntensityColorMapType1() const;
+ const QColor getUserDefinedLowIntensityColor() const;
+ const QColor getUserDefinedHighIntensityColor() const;
-public slots:
- void resizeSlot( QSize *s );
+ int getAlpha(int which);
+ void setAlpha(int which, int alpha);
- // 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);
+public slots:
+ void setIntensityColorMapType(const int, const int, const QColor, const QColor);
+ void setIntensityColorMapType1(int);
+ void setUserDefinedLowIntensityColor(QColor);
+ void setUserDefinedHighIntensityColor(QColor);
signals:
- void UpdatedLowerIntensityLevel(const double);
- void UpdatedUpperIntensityLevel(const double);
- void plotPointSelected(const QPointF p);
-
-protected:
+ void updatedLowerIntensityLevel(const double);
+ void updatedUpperIntensityLevel(const double);
private:
- void _UpdateIntensityRangeDisplay();
+ void _updateIntensityRangeDisplay();
double _startFrequency;
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..b623dc2175
--- /dev/null
+++ b/gr-qtgui/lib/const_sink_c_impl.cc
@@ -0,0 +1,357 @@
+/* -*- 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>
+#include <qwt_symbol.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()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ // 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]);
+ }
+ }
+
+ bool
+ const_sink_c_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ }
+
+ 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_y_axis(double min, double max)
+ {
+ d_main_gui->setYaxis(min, max);
+ }
+
+ void
+ const_sink_c_impl::set_x_axis(double min, double max)
+ {
+ d_main_gui->setXaxis(min, max);
+ }
+
+ 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);
+ d_last_time = 0;
+ }
+
+ void
+ const_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ const_sink_c_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ const_sink_c_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(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, int style)
+ {
+ d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
+ }
+
+ void
+ const_sink_c_impl::set_line_marker(int which, int marker)
+ {
+ d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
+ }
+
+ void
+ const_sink_c_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ const_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ const_sink_c_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ const_sink_c_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ const_sink_c_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ const_sink_c_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ const_sink_c_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ const_sink_c_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ double
+ const_sink_c_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ 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::nsamps() const
+ {
+ return d_size;
+ }
+
+ void
+ const_sink_c_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ const_sink_c_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ const_sink_c_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ 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..81cdb9881f
--- /dev/null
+++ b/gr-qtgui/lib/const_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_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();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_y_axis(double min, double max);
+ void set_x_axis(double min, double max);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, int style);
+ void set_line_marker(int which, int marker);
+ void set_nsamps(const int size);
+ void set_line_alpha(int which, double alpha);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+
+ void set_size(int width, int height);
+
+ int nsamps() const;
+ void enable_menu(bool en);
+ void enable_autoscale(bool en);
+ void reset();
+
+ 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..e3c65ec41d
--- /dev/null
+++ b/gr-qtgui/lib/constellationdisplayform.cc
@@ -0,0 +1,122 @@
+/* -*- 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;
+}
+
+void
+ConstellationDisplayForm::setYaxis(double min, double max)
+{
+ getPlot()->set_yaxis(min, max);
+}
+
+void
+ConstellationDisplayForm::setXaxis(double min, double max)
+{
+ getPlot()->set_xaxis(min, max);
+}
+
+void
+ConstellationDisplayForm::autoScale(bool en)
+{
+ _autoscale_state = en;
+ _autoscale_act->setChecked(en);
+ getPlot()->setAutoScale(_autoscale_state);
+ getPlot()->replot();
+}
+
+void
+ConstellationDisplayForm::setSampleRate(const QString &samprate)
+{
+}
diff --git a/gr-qtgui/lib/constellationdisplayform.h b/gr-qtgui/lib/constellationdisplayform.h
new file mode 100644
index 0000000000..06a8e7ed5f
--- /dev/null
+++ b/gr-qtgui/lib/constellationdisplayform.h
@@ -0,0 +1,62 @@
+/* -*- 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);
+
+ void setSampleRate(const QString &samprate);
+ void setYaxis(double min, double max);
+ void setXaxis(double min, double max);
+ void autoScale(bool en);
+
+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..276539cdde
--- /dev/null
+++ b/gr-qtgui/lib/displayform.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.
+ */
+
+#include <displayform.h>
+#include <iostream>
+#include <QPixmap>
+#include <QFileDialog>
+
+DisplayForm::DisplayForm(int nplots, QWidget* parent)
+ : QWidget(parent), _nplots(nplots), _systemSpecifiedFlag(false)
+{
+ _isclosed = 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", this);
+ _grid_act->setCheckable(true);
+ _grid_act->setStatusTip(tr("Toggle Grid on/off"));
+ connect(_grid_act, SIGNAL(triggered(bool)),
+ this, SLOT(setGrid(bool)));
+ _grid_state = false;
+
+ // Create a pop-up menu for manipulating the figure
+ _menu_on = true;
+ _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));
+ _marker_alpha_menu.push_back(new MarkerAlphaMenu(i, this));
+
+ connect(_line_title_act[i], SIGNAL(whichTrigger(int, const QString&)),
+ this, SLOT(setLineLabel(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(setLineColor(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)));
+ }
+
+ for(int j = 0; j < _marker_alpha_menu[i]->getNumActions(); j++) {
+ connect(_marker_alpha_menu[i], SIGNAL(whichTrigger(int, int)),
+ this, SLOT(setMarkerAlpha(int, int)));
+ }
+
+ _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]);
+ _lines_menu[i]->addMenu(_marker_alpha_menu[i]);
+ _menu->addMenu(_lines_menu[i]);
+ }
+
+ _samp_rate_act = new PopupMenu("Sample Rate", this);
+ _samp_rate_act->setStatusTip(tr("Set Sample Rate"));
+ connect(_samp_rate_act, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setSampleRate(QString)));
+ _menu->addAction(_samp_rate_act);
+
+ _autoscale_act = new QAction("Auto Scale", this);
+ _autoscale_act->setStatusTip(tr("Autoscale Plot"));
+ _autoscale_act->setCheckable(true);
+ connect(_autoscale_act, SIGNAL(triggered(bool)),
+ this, SLOT(autoScale(bool)));
+ _autoscale_state = false;
+ _menu->addAction(_autoscale_act);
+
+ _save_act = new QAction("Save", this);
+ _save_act->setStatusTip(tr("Save Figure"));
+ connect(_save_act, SIGNAL(triggered()), this, SLOT(saveFigure()));
+ _menu->addAction(_save_act);
+
+ 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()
+{
+ _isclosed = true;
+
+ // 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)
+{
+ bool ctrloff = Qt::ControlModifier != QApplication::keyboardModifiers();
+ if((e->button() == Qt::MiddleButton) && ctrloff && (_menu_on)) {
+ if(_stop_state == false)
+ _stop_act->setText(tr("Stop"));
+ else
+ _stop_act->setText(tr("Start"));
+
+ // Update the line titles if changed externally
+ for(int i = 0; i < _nplots; i++) {
+ _lines_menu[i]->setTitle(_displayPlot->getLineLabel(i));
+ }
+ _menu->exec(e->globalPos());
+ }
+}
+
+void
+DisplayForm::updateGuiTimer()
+{
+ _displayPlot->canvas()->update();
+}
+
+void
+DisplayForm::onPlotPointSelected(const QPointF p)
+{
+ emit plotPointSelected(p, 3);
+}
+
+void
+DisplayForm::Reset()
+{
+}
+
+bool
+DisplayForm::isClosed() const
+{
+ return _isclosed;
+}
+
+void
+DisplayForm::enableMenu(bool en)
+{
+ _menu_on = en;
+}
+
+void
+DisplayForm::closeEvent(QCloseEvent *e)
+{
+ _isclosed = true;
+ qApp->processEvents();
+ QWidget::closeEvent(e);
+}
+
+void
+DisplayForm::setUpdateTime(double t)
+{
+ d_update_time = t;
+ d_displayTimer->start(d_update_time);
+}
+
+void
+DisplayForm::setTitle(const QString &title)
+{
+ _displayPlot->setTitle(title);
+}
+
+void
+DisplayForm::setLineLabel(int which, const QString &label)
+{
+ _displayPlot->setLineLabel(which, label);
+}
+
+void
+DisplayForm::setLineColor(int which, const QString &color)
+{
+ QColor c = QColor(color);
+ _displayPlot->setLineColor(which, c);
+ _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::setMarkerAlpha(int which, int alpha)
+{
+ _displayPlot->setMarkerAlpha(which, alpha);
+ _displayPlot->replot();
+}
+
+QString
+DisplayForm::title()
+{
+ return _displayPlot->title().text();
+}
+
+QString
+DisplayForm::lineLabel(int which)
+{
+ return _displayPlot->getLineLabel(which);
+}
+
+QString
+DisplayForm::lineColor(int which)
+{
+ return _displayPlot->getLineColor(which).name();
+}
+
+int
+DisplayForm::lineWidth(int which)
+{
+ return _displayPlot->getLineWidth(which);
+}
+
+Qt::PenStyle
+DisplayForm::lineStyle(int which)
+{
+ return _displayPlot->getLineStyle(which);
+}
+
+QwtSymbol::Style
+DisplayForm::lineMarker(int which)
+{
+ return _displayPlot->getLineMarker(which);
+}
+
+int
+DisplayForm::markerAlpha(int which)
+{
+ return _displayPlot->getMarkerAlpha(which);
+}
+
+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::saveFigure()
+{
+ QPixmap qpix = QPixmap::grabWidget(this);
+
+ QString types = QString(tr("JPEG file (*.jpg);;Portable Network Graphics file (*.png);;Bitmap file (*.bmp);;TIFF file (*.tiff)"));
+
+ QString filename, filetype;
+ QFileDialog *filebox = new QFileDialog(0, "Save Image", "./", types);
+ filebox->setViewMode(QFileDialog::Detail);
+ if(filebox->exec()) {
+ filename = filebox->selectedFiles()[0];
+ filetype = filebox->selectedNameFilter();
+ }
+ else {
+ return;
+ }
+
+ if(filetype.contains(".jpg")) {
+ qpix.save(filename, "JPEG");
+ }
+ else if(filetype.contains(".png")) {
+ qpix.save(filename, "PNG");
+ }
+ else if(filetype.contains(".bmp")) {
+ qpix.save(filename, "BMP");
+ }
+ else if(filetype.contains(".tiff")) {
+ qpix.save(filename, "TIFF");
+ }
+ else {
+ qpix.save(filename, "JPEG");
+ }
+
+ delete filebox;
+}
diff --git a/gr-qtgui/lib/displayform.h b/gr-qtgui/lib/displayform.h
new file mode 100644
index 0000000000..31dc757bb6
--- /dev/null
+++ b/gr-qtgui/lib/displayform.h
@@ -0,0 +1,131 @@
+/* -*- 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();
+ bool isClosed() const;
+
+ void enableMenu(bool en=true);
+
+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(const QString &title);
+ void setLineLabel(int which, const QString &label);
+ void setLineColor(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 setMarkerAlpha(int which, int alpha);
+
+ QString title();
+ QString lineLabel(int which);
+ QString lineColor(int which);
+ int lineWidth(int which);
+ Qt::PenStyle lineStyle(int which);
+ QwtSymbol::Style lineMarker(int which);
+ int markerAlpha(int which);
+
+ virtual void setSampleRate(const QString &rate) = 0;
+
+ void setStop(bool on);
+ void setStop();
+
+ void setGrid(bool on);
+
+ void saveFigure();
+
+private slots:
+ virtual void newData(const QEvent*) = 0;
+ virtual void autoScale(bool) = 0;
+ void updateGuiTimer();
+
+ void onPlotPointSelected(const QPointF p);
+
+signals:
+ void plotPointSelected(const QPointF p, int type);
+
+protected:
+ bool _isclosed;
+
+ int _nplots;
+
+ QGridLayout *_layout;
+ DisplayPlot* _displayPlot;
+ bool _systemSpecifiedFlag;
+
+ QwtPlotGrid *_grid;
+
+ bool _menu_on;
+ QMenu *_menu;
+
+ QAction *_stop_act;
+ bool _stop_state;
+ QAction *_grid_act;
+ bool _grid_state;
+
+ QAction *_autoscale_act;
+ bool _autoscale_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;
+ QList<MarkerAlphaMenu*> _marker_alpha_menu;
+
+ PopupMenu *_samp_rate_act;
+ QAction *_save_act;
+
+ 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..63ab35ed95
--- /dev/null
+++ b/gr-qtgui/lib/form_menus.h
@@ -0,0 +1,1001 @@
+/* -*- 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 MarkerAlphaMenu: public QMenu
+{
+ Q_OBJECT
+
+public:
+ MarkerAlphaMenu(int which, QWidget *parent)
+ : QMenu("Line Transparency", parent), d_which(which)
+ {
+ d_act.push_back(new QAction("None", this));
+ d_act.push_back(new QAction("Low", this));
+ d_act.push_back(new QAction("Medium", this));
+ d_act.push_back(new QAction("High", this));
+ d_act.push_back(new QAction("Off", this));
+
+ connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone()));
+ connect(d_act[1], SIGNAL(triggered()), this, SLOT(getLow()));
+ connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium()));
+ connect(d_act[3], SIGNAL(triggered()), this, SLOT(getHigh()));
+ connect(d_act[4], SIGNAL(triggered()), this, SLOT(getOff()));
+
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
+
+ ~MarkerAlphaMenu()
+ {}
+
+ 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("MarkerAlphaMenu::getAction: which out of range.\n");
+ }
+
+signals:
+ void whichTrigger(int which, int);
+
+public slots:
+ void getNone() { emit whichTrigger(d_which, 255); }
+ void getLow() { emit whichTrigger(d_which, 200); }
+ void getMedium() { emit whichTrigger(d_which, 125); }
+ void getHigh() { emit whichTrigger(d_which, 50); }
+ void getOff() { emit whichTrigger(d_which, 0); }
+
+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(int which, QWidget *parent)
+ : QMenu("Color Map", parent), d_which(which)
+ {
+ 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(int which, const int type,
+ const QColor &min_color=QColor(),
+ const QColor &max_color=QColor());
+
+ public slots:
+ void getMultiColor() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); }
+ void getWhiteHot() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_WHITE_HOT); }
+ void getBlackHot() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_BLACK_HOT); }
+ void getIncandescent() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_INCANDESCENT); }
+ //void getOther(d_which, 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(d_which, 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;
+ int d_which;
+};
+
+
+/********************************************************************/
+
+
+class PopupMenu: public QAction
+{
+ Q_OBJECT
+
+public:
+ PopupMenu(QString desc, QWidget *parent)
+ : QAction(desc, 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()));
+ }
+
+ ~PopupMenu()
+ {}
+
+signals:
+ void whichTrigger(const QString data);
+
+public slots:
+ void getTextDiag()
+ {
+ d_diag->show();
+ }
+
+private slots:
+ void getText()
+ {
+ emit whichTrigger(d_text->text());
+ d_diag->accept();
+ }
+
+private:
+ QDialog *d_diag;
+ QLineEdit *d_text;
+};
+
+
+/********************************************************************/
+
+
+#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..b1f9a2b1a1
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_c_impl.cc
@@ -0,0 +1,470 @@
+/* -*- 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>
+#include <qwt_symbol.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()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ 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);
+ }
+
+ bool
+ freq_sink_c_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ set_fft_window(d_wintype);
+ set_fft_size(d_fftsize);
+ set_frequency_range(d_center_freq, d_bandwidth);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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_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_main_gui->setFFTAverage(fftavg);
+ }
+
+ float
+ freq_sink_c_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ freq_sink_c_impl::set_fft_window(const filter::firdes::win_type win)
+ {
+ d_main_gui->setFFTWindowType(win);
+ }
+
+ filter::firdes::win_type
+ freq_sink_c_impl::fft_window()
+ {
+ return d_wintype;
+ }
+
+ 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);
+ }
+
+ void
+ freq_sink_c_impl::set_y_axis(double min, double max)
+ {
+ d_main_gui->setYaxis(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);
+ d_last_time = 0;
+ }
+
+ void
+ freq_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ freq_sink_c_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ freq_sink_c_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(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, int style)
+ {
+ d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
+ }
+
+ void
+ freq_sink_c_impl::set_line_marker(int which, int marker)
+ {
+ d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
+ }
+
+ void
+ freq_sink_c_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ freq_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ freq_sink_c_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ freq_sink_c_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ freq_sink_c_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ freq_sink_c_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ freq_sink_c_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ freq_sink_c_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ double
+ freq_sink_c_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ void
+ freq_sink_c_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ freq_sink_c_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ freq_sink_c_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ freq_sink_c_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ 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..0567b914c8
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_c_impl.h
@@ -0,0 +1,130 @@
+/* -*- 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();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ 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_fft_window(const filter::firdes::win_type win);
+ filter::firdes::win_type fft_window();
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_y_axis(double min, double max);
+
+ void set_update_time(double t);
+
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, int style);
+ void set_line_marker(int which, int marker);
+ void set_line_alpha(int which, double alpha);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+
+ void set_size(int width, int height);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void reset();
+
+ 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..f357ae10be
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_f_impl.cc
@@ -0,0 +1,473 @@
+/* -*- 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>
+#include <qwt_symbol.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()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ 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);
+ }
+
+ bool
+ freq_sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ set_fft_window(d_wintype);
+ set_fft_size(d_fftsize);
+ set_frequency_range(d_center_freq, d_bandwidth/2.0);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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_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_main_gui->setFFTAverage(fftavg);
+ }
+
+ float
+ freq_sink_f_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ freq_sink_f_impl::set_fft_window(const filter::firdes::win_type win)
+ {
+ d_main_gui->setFFTWindowType(win);
+ }
+
+ filter::firdes::win_type
+ freq_sink_f_impl::fft_window()
+ {
+ return d_wintype;
+ }
+
+ 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);
+ }
+
+ void
+ freq_sink_f_impl::set_y_axis(double min, double max)
+ {
+ d_main_gui->setYaxis(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);
+ d_last_time = 0;
+ }
+
+ void
+ freq_sink_f_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ freq_sink_f_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ freq_sink_f_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(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, int style)
+ {
+ d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
+ }
+
+ void
+ freq_sink_f_impl::set_line_marker(int which, int marker)
+ {
+ d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
+ }
+
+ void
+ freq_sink_f_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ freq_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ freq_sink_f_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ freq_sink_f_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ freq_sink_f_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ freq_sink_f_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ freq_sink_f_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ freq_sink_f_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ double
+ freq_sink_f_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ void
+ freq_sink_f_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ freq_sink_f_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ freq_sink_f_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ freq_sink_f_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ 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..b79127f3dd
--- /dev/null
+++ b/gr-qtgui/lib/freq_sink_f_impl.h
@@ -0,0 +1,129 @@
+/* -*- 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();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ 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_fft_window(const filter::firdes::win_type win);
+ filter::firdes::win_type fft_window();
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_y_axis(double min, double max);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, int style);
+ void set_line_marker(int which, int marker);
+ void set_line_alpha(int which, double alpha);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+
+ void set_size(int width, int height);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void reset();
+
+ 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..c90e8b7961
--- /dev/null
+++ b/gr-qtgui/lib/freqdisplayform.cc
@@ -0,0 +1,175 @@
+/* -*- 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::setSampleRate(const QString &samprate)
+{
+ setFrequencyRange(_center_freq, samprate.toDouble());
+}
+
+void
+FreqDisplayForm::setFFTSize(const int newsize)
+{
+ _fftsize = newsize;
+ getPlot()->replot();
+}
+
+void
+FreqDisplayForm::setFFTAverage(const float newavg)
+{
+ _fftavg = newavg;
+ getPlot()->replot();
+}
+
+void
+FreqDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin)
+{
+ _fftwintype = newwin;
+ getPlot()->replot();
+}
+
+void
+FreqDisplayForm::setFrequencyRange(const double centerfreq,
+ const double bandwidth)
+{
+ std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
+ double units10 = floor(log10(bandwidth));
+ 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);
+
+ _center_freq = centerfreq;
+ _samp_rate = bandwidth;
+
+ getPlot()->setFrequencyRange(centerfreq, bandwidth,
+ units, strunits[iunit]);
+}
+
+void
+FreqDisplayForm::setYaxis(double min, double max)
+{
+ getPlot()->setYaxis(min, max);
+}
+
+void
+FreqDisplayForm::autoScale(bool en)
+{
+ if(en) {
+ _autoscale_state = true;
+ }
+ else {
+ _autoscale_state = false;
+ }
+
+ getPlot()->setAutoScale(_autoscale_state);
+ getPlot()->replot();
+}
diff --git a/gr-qtgui/lib/freqdisplayform.h b/gr-qtgui/lib/freqdisplayform.h
new file mode 100644
index 0000000000..b22cd93c51
--- /dev/null
+++ b/gr-qtgui/lib/freqdisplayform.h
@@ -0,0 +1,74 @@
+/* -*- 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 setSampleRate(const QString &samprate);
+ void setFFTSize(const int);
+ void setFFTAverage(const float);
+ void setFFTWindowType(const gr::filter::firdes::win_type);
+
+ void setFrequencyRange(const double centerfreq,
+ const double bandwidth);
+ void setYaxis(double min, double max);
+ void autoScale(bool en);
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ uint64_t _numRealDataPoints;
+ QIntValidator* _intValidator;
+
+ double _samp_rate, _center_freq;
+ int _fftsize;
+ float _fftavg;
+ gr::filter::firdes::win_type _fftwintype;
+};
+
+#endif /* FREQ_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/plot_raster.cc b/gr-qtgui/lib/plot_raster.cc
new file mode 100644
index 0000000000..76bff473e9
--- /dev/null
+++ b/gr-qtgui/lib/plot_raster.cc
@@ -0,0 +1,350 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 <iostream>
+#include <qimage.h>
+#include <qpen.h>
+#include <qpainter.h>
+#include "qwt_painter.h"
+#include "qwt_scale_map.h"
+#include "qwt_color_map.h"
+#include "plot_raster.h"
+
+#if QWT_VERSION < 0x060000
+#include "qwt_double_interval.h"
+#endif
+
+typedef QVector<QRgb> QwtColorTable;
+
+class PlotTimeRasterImage: public QImage
+{
+ // This class hides some Qt3/Qt4 API differences
+public:
+ PlotTimeRasterImage(const QSize &size, QwtColorMap::Format format):
+ QImage(size, format == QwtColorMap::RGB
+ ? QImage::Format_ARGB32 : QImage::Format_Indexed8 )
+ {
+ }
+
+ PlotTimeRasterImage(const QImage &other):
+ QImage(other)
+ {
+ }
+
+ void initColorTable(const QImage& other)
+ {
+ setColorTable(other.colorTable());
+ }
+};
+
+class PlotTimeRaster::PrivateData
+{
+public:
+ PrivateData()
+ {
+ data = NULL;
+ colorMap = new QwtLinearColorMap();
+ }
+
+ ~PrivateData()
+ {
+ delete colorMap;
+ }
+
+ TimeRasterData *data;
+ QwtColorMap *colorMap;
+};
+
+/*!
+ Sets the following item attributes:
+ - QwtPlotItem::AutoScale: true
+ - QwtPlotItem::Legend: false
+
+ The z value is initialized to 8.0.
+
+ \param title Title
+
+ \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ()
+*/
+PlotTimeRaster::PlotTimeRaster(const QString &title)
+ : QwtPlotRasterItem(title)
+{
+ d_data = new PrivateData();
+
+ setItemAttribute(QwtPlotItem::AutoScale, true);
+ setItemAttribute(QwtPlotItem::Legend, false);
+
+ setZ(1.0);
+}
+
+//! Destructor
+PlotTimeRaster::~PlotTimeRaster()
+{
+ delete d_data;
+}
+
+const TimeRasterData*
+PlotTimeRaster::data()const
+{
+ return d_data->data;
+}
+
+void
+PlotTimeRaster::setData(TimeRasterData *data)
+{
+ d_data->data = data;
+}
+
+//! \return QwtPlotItem::Rtti_PlotSpectrogram
+int
+PlotTimeRaster::rtti() const
+{
+ return QwtPlotItem::Rtti_PlotGrid;
+}
+
+/*!
+ Change the color map
+
+ Often it is useful to display the mapping between intensities and
+ colors as an additional plot axis, showing a color bar.
+
+ \param map Color Map
+
+ \sa colorMap(), QwtScaleWidget::setColorBarEnabled(),
+ QwtScaleWidget::setColorMap()
+*/
+void
+PlotTimeRaster::setColorMap(const QwtColorMap *map)
+{
+ delete d_data->colorMap;
+ d_data->colorMap = (QwtColorMap*)map;
+
+ invalidateCache();
+ itemChanged();
+}
+
+/*!
+ \return Color Map used for mapping the intensity values to colors
+ \sa setColorMap()
+*/
+const QwtColorMap &PlotTimeRaster::colorMap() const
+{
+ return *d_data->colorMap;
+}
+
+/*!
+ \return Bounding rect of the data
+ \sa QwtRasterData::boundingRect
+*/
+#if QWT_VERSION < 0x060000
+QwtDoubleRect PlotTimeRaster::boundingRect() const
+{
+ return d_data->data->boundingRect();
+}
+#endif
+
+/*!
+ \brief Returns the recommended raster for a given rect.
+
+ F.e the raster hint is used to limit the resolution of
+ the image that is rendered.
+
+ \param rect Rect for the raster hint
+ \return data().rasterHint(rect)
+*/
+#if QWT_VERSION < 0x060000
+QSize PlotTimeRaster::rasterHint(const QwtDoubleRect &rect) const
+{
+ return d_data->data->rasterHint(rect);
+}
+#endif
+
+/*!
+ \brief Render an image from the data and color map.
+
+ The area is translated into a rect of the paint device.
+ For each pixel of this rect the intensity is mapped
+ into a color.
+
+ \param xMap X-Scale Map
+ \param yMap Y-Scale Map
+ \param area Area that should be rendered in scale coordinates.
+
+ \return A QImage::Format_Indexed8 or QImage::Format_ARGB32 depending
+ on the color map.
+
+ \sa QwtRasterData::intensity(), QwtColorMap::rgb(),
+ QwtColorMap::colorIndex()
+*/
+#if QWT_VERSION < 0x060000
+QImage PlotTimeRaster::renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QwtDoubleRect &area) const
+#else
+QImage PlotTimeRaster::renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRectF &area,
+ const QSize &size) const
+#endif
+{
+ if(area.isEmpty())
+ return QImage();
+
+#if QWT_VERSION < 0x060000
+ QRect rect = transform(xMap, yMap, area);
+ const QSize res = d_data->data->rasterHint(area);
+#else
+ QRect rect = QwtScaleMap::transform(xMap, yMap, area).toRect();
+ const QSize res(-1,-1);
+
+#endif
+
+ QwtScaleMap xxMap = xMap;
+ QwtScaleMap yyMap = yMap;
+
+ if(res.isValid()) {
+ /*
+ It is useless to render an image with a higher resolution
+ than the data offers. Of course someone will have to
+ scale this image later into the size of the given rect, but f.e.
+ in case of postscript this will done on the printer.
+ */
+ rect.setSize(rect.size().boundedTo(res));
+
+ int px1 = rect.x();
+ int px2 = rect.x() + rect.width();
+ if(xMap.p1() > xMap.p2())
+ qSwap(px1, px2);
+
+ double sx1 = area.x();
+ double sx2 = area.x() + area.width();
+ if(xMap.s1() > xMap.s2())
+ qSwap(sx1, sx2);
+
+ int py1 = rect.y();
+ int py2 = rect.y() + rect.height();
+ if(yMap.p1() > yMap.p2())
+ qSwap(py1, py2);
+
+ double sy1 = area.y();
+ double sy2 = area.y() + area.height();
+ if(yMap.s1() > yMap.s2())
+ qSwap(sy1, sy2);
+
+ xxMap.setPaintInterval(px1, px2);
+ xxMap.setScaleInterval(sx1, sx2);
+ yyMap.setPaintInterval(py1, py2);
+ yyMap.setScaleInterval(sy1, sy2);
+ }
+
+ PlotTimeRasterImage image(rect.size(), d_data->colorMap->format());
+
+#if QWT_VERSION < 0x060000
+ const QwtDoubleInterval intensityRange = d_data->data->range();
+#else
+ const QwtInterval intensityRange = d_data->data->interval(Qt::ZAxis);
+#endif
+ if(!intensityRange.isValid())
+ return image;
+
+ d_data->data->initRaster(area, rect.size());
+
+ if(d_data->colorMap->format() == QwtColorMap::RGB) {
+ for(int y = rect.top(); y <= rect.bottom(); y++) {
+ const double ty = yyMap.invTransform(y);
+
+ QRgb *line = (QRgb *)image.scanLine(y - rect.top());
+
+ for(int x = rect.left(); x <= rect.right(); x++) {
+ const double tx = xxMap.invTransform(x);
+
+ *line++ = d_data->colorMap->rgb(intensityRange,
+ d_data->data->value(tx, ty));
+ }
+ }
+ d_data->data->incrementResidual();
+ }
+ else if(d_data->colorMap->format() == QwtColorMap::Indexed) {
+ image.setColorTable(d_data->colorMap->colorTable(intensityRange));
+
+ for(int y = rect.top(); y <= rect.bottom(); y++) {
+ const double ty = yyMap.invTransform(y);
+
+ unsigned char *line = image.scanLine(y - rect.top());
+ for(int x = rect.left(); x <= rect.right(); x++) {
+ const double tx = xxMap.invTransform(x);
+
+ *line++ = d_data->colorMap->colorIndex(intensityRange,
+ d_data->data->value(tx, ty));
+ }
+ }
+ }
+
+ d_data->data->discardRaster();
+
+ // Mirror the image in case of inverted maps
+
+ const bool hInvert = xxMap.p1() > xxMap.p2();
+ const bool vInvert = yyMap.p1() > yyMap.p2();
+ if(hInvert || vInvert) {
+ image = image.mirrored(hInvert, vInvert);
+ }
+
+ return image;
+}
+
+#if QWT_VERSION < 0x060000
+QwtDoubleInterval
+PlotTimeRaster::interval(Qt::Axis ax) const
+{
+ return d_data->data->range();
+}
+
+#else
+
+QwtInterval
+PlotTimeRaster::interval(Qt::Axis ax) const
+{
+ return d_data->data->interval(ax);
+}
+#endif
+
+/*!
+ \brief Draw the raster
+
+ \param painter Painter
+ \param xMap Maps x-values into pixel coordinates.
+ \param yMap Maps y-values into pixel coordinates.
+ \param canvasRect Contents rect of the canvas in painter coordinates
+
+ \sa setDisplayMode, renderImage,
+ QwtPlotRasterItem::draw, drawContourLines
+*/
+
+void PlotTimeRaster::draw(QPainter *painter,
+ const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRect &canvasRect) const
+{
+ QwtPlotRasterItem::draw(painter, xMap, yMap, canvasRect);
+}
+
diff --git a/gr-qtgui/lib/plot_raster.h b/gr-qtgui/lib/plot_raster.h
new file mode 100644
index 0000000000..7bea0a4d57
--- /dev/null
+++ b/gr-qtgui/lib/plot_raster.h
@@ -0,0 +1,93 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 PLOT_TIMERASTER_H
+#define PLOT_TIMERASTER_H
+
+#include <qglobal.h>
+#include <timeRasterGlobalData.h>
+#include <qwt_plot_rasteritem.h>
+
+#if QWT_VERSION >= 0x060000
+#include <qwt_point_3d.h> // doesn't seem necessary, but is...
+#include <qwt_compat.h>
+#endif
+
+class QwtColorMap;
+
+/*!
+ \brief A plot item, which displays a time raster.
+
+ A time raster displays threedimenional data, where the 3rd dimension
+ ( the intensity ) is displayed using colors. The colors are calculated
+ from the values using a color map.
+
+ \sa QwtRasterData, QwtColorMap
+*/
+
+class PlotTimeRaster: public QwtPlotRasterItem
+{
+public:
+ explicit PlotTimeRaster(const QString &title = QString::null);
+ virtual ~PlotTimeRaster();
+
+ const TimeRasterData* data()const;
+
+ void setData(TimeRasterData *data);
+
+ void setColorMap(const QwtColorMap *map);
+
+ const QwtColorMap &colorMap() const;
+
+#if QWT_VERSION < 0x060000
+ virtual QwtDoubleRect boundingRect() const;
+ virtual QSize rasterHint(const QwtDoubleRect &) const;
+ virtual QwtDoubleInterval interval(Qt::Axis ax) const;
+#else
+ virtual QwtInterval interval(Qt::Axis ax) const;
+#endif
+
+ virtual int rtti() const;
+
+ virtual void draw(QPainter *p,
+ const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRect &rect) const;
+
+protected:
+#if QWT_VERSION < 0x060000
+ QImage renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QwtDoubleRect &rect) const;
+#else
+ QImage renderImage(const QwtScaleMap &xMap,
+ const QwtScaleMap &yMap,
+ const QRectF &rect,
+ const QSize &size=QSize(0,0)) const;
+#endif
+
+private:
+ class PrivateData;
+ PrivateData *d_data;
+};
+
+#endif
diff --git a/gr-qtgui/lib/plot_waterfall.cc b/gr-qtgui/lib/plot_waterfall.cc
index 517ec0275a..84915e3f31 100644
--- a/gr-qtgui/lib/plot_waterfall.cc
+++ b/gr-qtgui/lib/plot_waterfall.cc
@@ -1,3 +1,25 @@
+/* -*- 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.
+ */
+
#include <qimage.h>
#include <qpen.h>
#include <qpainter.h>
diff --git a/gr-qtgui/lib/plot_waterfall.h b/gr-qtgui/lib/plot_waterfall.h
index df2537b57a..40ee4eccb3 100644
--- a/gr-qtgui/lib/plot_waterfall.h
+++ b/gr-qtgui/lib/plot_waterfall.h
@@ -1,3 +1,25 @@
+/* -*- 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.
+ */
+
#ifndef PLOT_WATERFALL_H
#define PLOT_WATERFALL_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 7731994622..0000000000
--- a/gr-qtgui/lib/qtgui_time_sink_c.cc
+++ /dev/null
@@ -1,192 +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);
- d_main_gui->setFrequencyRange(0, 0, d_bandwidth);
-
- // 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 1a23023b5e..0000000000
--- a/gr-qtgui/lib/qtgui_time_sink_f.cc
+++ /dev/null
@@ -1,190 +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);
- d_main_gui->setFrequencyRange(0, 0, d_bandwidth);
-
- // 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..f4b16dfef2
--- /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..a8a0526e77
--- /dev/null
+++ b/gr-qtgui/lib/sink_c_impl.cc
@@ -0,0 +1,341 @@
+/* -*- 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;
+ }
+
+ bool
+ sink_c_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == 1;
+ }
+
+ 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->setWindowType((int)d_wintype);
+ set_fft_size(d_fftsize);
+
+ 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..ddfb0865d5
--- /dev/null
+++ b/gr-qtgui/lib/sink_c_impl.h
@@ -0,0 +1,108 @@
+/* -*- 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();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ 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..5cb14db672
--- /dev/null
+++ b/gr-qtgui/lib/sink_f_impl.cc
@@ -0,0 +1,326 @@
+/* -*- 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;
+ }
+
+ bool
+ sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == 1;
+ }
+
+ 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->setWindowType((int)d_wintype);
+ set_fft_size(d_fftsize);
+
+ 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..394d5c3428
--- /dev/null
+++ b/gr-qtgui/lib/sink_f_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_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();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ 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..bda89651b6 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.cc
+++ b/gr-qtgui/lib/spectrumUpdateEvents.cc
@@ -1,9 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008-2013 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 SPECTRUM_UPDATE_EVENTS_C
#define SPECTRUM_UPDATE_EVENTS_C
#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 +35,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 +51,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 +82,7 @@ SpectrumUpdateEvent::~SpectrumUpdateEvent()
delete[] _imagDataTimeDomainPoints;
}
-const std::complex<float>*
+const float*
SpectrumUpdateEvent::getFFTPoints() const
{
return _fftPoints;
@@ -121,7 +143,7 @@ SpectrumUpdateEvent::getDroppedFFTFrames() const
}
SpectrumWindowCaptionEvent::SpectrumWindowCaptionEvent(const QString& newLbl)
- : QEvent(QEvent::Type(10008))
+ : QEvent(QEvent::Type(SpectrumWindowCaptionEventType))
{
_labelString = newLbl;
}
@@ -137,7 +159,7 @@ SpectrumWindowCaptionEvent::getLabel()
}
SpectrumWindowResetEvent::SpectrumWindowResetEvent()
- : QEvent(QEvent::Type(10009))
+ : QEvent(QEvent::Type(SpectrumWindowResetEventType))
{
}
@@ -148,7 +170,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 +201,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 +243,200 @@ 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;
+}
+
+
+/***************************************************************************/
+
+
+TimeRasterUpdateEvent::TimeRasterUpdateEvent(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));
+ }
+ }
+}
+
+TimeRasterUpdateEvent::~TimeRasterUpdateEvent()
+{
+ for(size_t i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ }
+}
+
+const std::vector<double*>
+TimeRasterUpdateEvent::getPoints() const
+{
+ return _dataPoints;
+}
+
+uint64_t
+TimeRasterUpdateEvent::getNumDataPoints() const
+{
+ return _numDataPoints;
+}
+
#endif /* SPECTRUM_UPDATE_EVENTS_C */
diff --git a/gr-qtgui/lib/spectrumUpdateEvents.h b/gr-qtgui/lib/spectrumUpdateEvents.h
index faef0f0875..97d9c90146 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.h
+++ b/gr-qtgui/lib/spectrumUpdateEvents.h
@@ -1,3 +1,25 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008-2013 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 SPECTRUM_UPDATE_EVENTS_H
#define SPECTRUM_UPDATE_EVENTS_H
@@ -8,10 +30,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 +51,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 +65,7 @@ public:
protected:
private:
- std::complex<float>* _fftPoints;
+ float* _fftPoints;
double* _realDataTimeDomainPoints;
double* _imagDataTimeDomainPoints;
uint64_t _numFFTDataPoints;
@@ -103,6 +130,9 @@ public:
uint64_t getNumTimeDomainDataPoints() const;
bool getRepeatDataFlag() const;
+ static QEvent::Type Type()
+ { return QEvent::Type(SpectrumUpdateEventType); }
+
protected:
private:
@@ -112,4 +142,123 @@ 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;
+};
+
+
+/********************************************************************/
+
+
+class TimeRasterUpdateEvent: public QEvent
+{
+public:
+ TimeRasterUpdateEvent(const std::vector<double*> dataPoints,
+ const uint64_t numDataPoints);
+ ~TimeRasterUpdateEvent();
+
+ 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;
+};
+
+
#endif /* SPECTRUM_UPDATE_EVENTS_H */
diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc
index dd9011dbdd..8d7caebda8 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,59 +34,57 @@ 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];
_historyVector = new std::vector<double*>;
- _timeDomainDisplayPlot->setTitle(0, "real");
- _timeDomainDisplayPlot->setTitle(1, "imag");
+ _timeDomainDisplayPlot->setLineLabel(0, "real");
+ _timeDomainDisplayPlot->setLineLabel(1, "imag");
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);
-
+ minHoldCheckBox_toggled( false );
+ maxHoldCheckBox_toggled( false );
+
+ WaterfallMaximumIntensitySlider->setRange(-200, 0);
+ WaterfallMinimumIntensitySlider->setRange(-200, 0);
+ WaterfallMinimumIntensitySlider->setValue(-200);
+
_peakFrequency = 0;
_peakAmplitude = -HUGE_VAL;
_noiseFloorAmplitude = -HUGE_VAL;
- connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)),
- _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
- connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)),
- _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
+ connect(_waterfallDisplayPlot, SIGNAL(updatedLowerIntensityLevel(const double)),
+ _frequencyDisplayPlot, SLOT(setLowerIntensityLevel(const double)));
+ connect(_waterfallDisplayPlot, SIGNAL(updatedUpperIntensityLevel(const double)),
+ _frequencyDisplayPlot, SLOT(setUpperIntensityLevel(const double)));
- _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
- _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
+ _frequencyDisplayPlot->setLowerIntensityLevel(-200);
+ _frequencyDisplayPlot->setUpperIntensityLevel(-200);
// Load up the acceptable FFT sizes...
FFTSizeComboBox->clear();
for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
}
- Reset();
+ reset();
- ToggleTabFrequency(false);
- ToggleTabWaterfall(false);
- ToggleTabTime(false);
- ToggleTabConstellation(false);
+ toggleTabFrequency(false);
+ toggleTabWaterfall(false);
+ toggleTabTime(false);
+ toggleTabConstellation(false);
_historyEntry = 0;
_historyEntryCount = 0;
// Create a timer to update plots at the specified rate
displayTimer = new QTimer(this);
- connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer()));
+ connect(displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer()));
// Connect double click signals up
connect(_frequencyDisplayPlot, SIGNAL(plotPointSelected(const QPointF)),
@@ -122,26 +121,75 @@ SpectrumDisplayForm::~SpectrumDisplayForm()
}
void
-SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem,
- const uint64_t numFFTDataPoints,
- const uint64_t numTimeDomainDataPoints )
+SpectrumDisplayForm::setSystem(SpectrumGUIClass * newSystem,
+ const uint64_t numFFTDataPoints,
+ const uint64_t numTimeDomainDataPoints)
{
- ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
+ resizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
- if(newSystem != NULL){
+ if(newSystem != NULL) {
_system = newSystem;
_systemSpecifiedFlag = true;
}
- else{
+ else {
_systemSpecifiedFlag = false;
}
}
+/***********************************************************************
+ * 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();
@@ -156,70 +204,36 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate
timeDomainDataPoints.push_back(imagTimeDomainDataPoints);
// REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
- ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
+ 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);
+ _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,23 +241,23 @@ 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){
int tabindex = SpectrumTypeTab->currentIndex();
if(tabindex == d_plot_fft) {
- _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints,
+ _frequencyDisplayPlot->plotNewData(_averagedValues, numFFTDataPoints,
_noiseFloorAmplitude, _peakFrequency,
_peakAmplitude, d_update_time);
}
if(tabindex == d_plot_time) {
- _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints,
+ _timeDomainDisplayPlot->plotNewData(timeDomainDataPoints,
numTimeDomainDataPoints,
d_update_time);
}
if(tabindex == d_plot_constellation) {
- _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints,
+ _constellationDisplayPlot->plotNewData(realTimeDomainDataPoints,
imagTimeDomainDataPoints,
numTimeDomainDataPoints,
d_update_time);
@@ -252,7 +266,7 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate
// Don't update the repeated data for the waterfall
if(!repeatDataFlag){
if(tabindex == d_plot_waterfall) {
- _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints,
+ _waterfallDisplayPlot->plotNewData(_realFFTDataPoints, numFFTDataPoints,
d_update_time, dataTimestamp,
spectrumUpdateEvent->getDroppedFFTFrames());
}
@@ -260,8 +274,8 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate
// Tell the system the GUI has been updated
if(_systemSpecifiedFlag){
- _system->SetLastGUIUpdateTime(generatedTimestamp);
- _system->DecrementPendingGUIUpdateEvents();
+ _system->setLastGUIUpdateTime(generatedTimestamp);
+ _system->decrementPendingGUIUpdateEvents();
}
}
}
@@ -292,40 +306,40 @@ SpectrumDisplayForm::customEvent( QEvent * e)
{
if(e->type() == QEvent::User+3){
if(_systemSpecifiedFlag){
- WindowComboBox->setCurrentIndex(_system->GetWindowType());
- FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
+ WindowComboBox->setCurrentIndex(_system->getWindowType());
+ FFTSizeComboBox->setCurrentIndex(_system->getFFTSizeIndex());
}
- waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
- waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
+ waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensitySlider->value());
+ waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensitySlider->value());
// Clear any previous display
- Reset();
+ 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){
- Reset();
+ else if(e->type() == SpectrumWindowResetEventType) {
+ reset();
if(_systemSpecifiedFlag){
- _system->ResetPendingGUIUpdateEvents();
+ _system->resetPendingGUIUpdateEvents();
}
}
- else if(e->type() == 10010){
+ else if(e->type() == SpectrumFrequencyRangeEventType) {
_startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
_stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
_centerFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
- UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
+ useRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
}
}
void
-SpectrumDisplayForm::UpdateGuiTimer()
+SpectrumDisplayForm::updateGuiTimer()
{
// This is called by the displayTimer and redraws the canvases of
// all of the plots.
@@ -337,55 +351,55 @@ SpectrumDisplayForm::UpdateGuiTimer()
void
-SpectrumDisplayForm::AvgLineEdit_valueChanged( int value )
+SpectrumDisplayForm::avgLineEdit_valueChanged( int value )
{
- SetAverageCount(value);
+ setAverageCount(value);
}
void
-SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
+SpectrumDisplayForm::maxHoldCheckBox_toggled( bool newState )
{
MaxHoldResetBtn->setEnabled(newState);
- _frequencyDisplayPlot->SetMaxFFTVisible(newState);
- MaxHoldResetBtn_clicked();
+ _frequencyDisplayPlot->setMaxFFTVisible(newState);
+ maxHoldResetBtn_clicked();
}
void
-SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
+SpectrumDisplayForm::minHoldCheckBox_toggled( bool newState )
{
MinHoldResetBtn->setEnabled(newState);
- _frequencyDisplayPlot->SetMinFFTVisible(newState);
- MinHoldResetBtn_clicked();
+ _frequencyDisplayPlot->setMinFFTVisible(newState);
+ minHoldResetBtn_clicked();
}
void
-SpectrumDisplayForm::MinHoldResetBtn_clicked()
+SpectrumDisplayForm::minHoldResetBtn_clicked()
{
- _frequencyDisplayPlot->ClearMinData();
+ _frequencyDisplayPlot->clearMinData();
_frequencyDisplayPlot->replot();
}
void
-SpectrumDisplayForm::MaxHoldResetBtn_clicked()
+SpectrumDisplayForm::maxHoldResetBtn_clicked()
{
- _frequencyDisplayPlot->ClearMaxData();
+ _frequencyDisplayPlot->clearMaxData();
_frequencyDisplayPlot->replot();
}
void
-SpectrumDisplayForm::TabChanged(int index)
+SpectrumDisplayForm::tabChanged(int index)
{
// This might be dangerous to call this with NULL
resizeEvent(NULL);
}
void
-SpectrumDisplayForm::SetFrequencyRange(const double newCenterFrequency,
+SpectrumDisplayForm::setFrequencyRange(const double newCenterFrequency,
const double newStartFrequency,
const double newStopFrequency)
{
@@ -409,58 +423,52 @@ SpectrumDisplayForm::SetFrequencyRange(const double newCenterFrequency,
_stopFrequency = newStopFrequency;
_centerFrequency = newCenterFrequency;
- _frequencyDisplayPlot->SetFrequencyRange(_startFrequency,
- _stopFrequency,
- _centerFrequency,
- UseRFFrequenciesCheckBox->isChecked(),
+ _frequencyDisplayPlot->setFrequencyRange(_centerFrequency, fdiff,
units, strunits[iunit]);
- _waterfallDisplayPlot->SetFrequencyRange(_startFrequency,
- _stopFrequency,
- _centerFrequency,
- UseRFFrequenciesCheckBox->isChecked(),
+ _waterfallDisplayPlot->setFrequencyRange(_centerFrequency, fdiff,
units, strunits[iunit]);
- _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency,
+ _timeDomainDisplayPlot->setSampleRate(_stopFrequency - _startFrequency,
units, strtime[iunit]);
}
}
int
-SpectrumDisplayForm::GetAverageCount()
+SpectrumDisplayForm::getAverageCount()
{
return _historyVector->size();
}
void
-SpectrumDisplayForm::SetAverageCount(const int newCount)
+SpectrumDisplayForm::setAverageCount(const int newCount)
{
- if(newCount > -1){
- if(newCount != static_cast<int>(_historyVector->size())){
+ if(newCount > -1) {
+ if(newCount != static_cast<int>(_historyVector->size())) {
std::vector<double*>::iterator pos;
- while(newCount < static_cast<int>(_historyVector->size())){
+ while(newCount < static_cast<int>(_historyVector->size())) {
pos = _historyVector->begin();
delete[] (*pos);
_historyVector->erase(pos);
}
- while(newCount > static_cast<int>(_historyVector->size())){
+ while(newCount > static_cast<int>(_historyVector->size())) {
_historyVector->push_back(new double[_numRealDataPoints]);
}
- AverageDataReset();
+ averageDataReset();
}
}
}
void
-SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
+SpectrumDisplayForm::_averageHistory(const double* newBuffer)
{
- if(_numRealDataPoints > 0){
- if(_historyVector->size() > 0){
+ if(_numRealDataPoints > 0) {
+ if(_historyVector->size() > 0) {
memcpy(_historyVector->operator[](_historyEntry), newBuffer,
_numRealDataPoints*sizeof(double));
// Increment the next location to store data
_historyEntryCount++;
- if(_historyEntryCount > static_cast<int>(_historyVector->size())){
+ if(_historyEntryCount > static_cast<int>(_historyVector->size())) {
_historyEntryCount = _historyVector->size();
}
_historyEntry += 1;
@@ -468,26 +476,26 @@ SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
// Total up and then average the values
double sum;
- for(uint64_t location = 0; location < _numRealDataPoints; location++){
+ for(uint64_t location = 0; location < _numRealDataPoints; location++) {
sum = 0;
- for(int number = 0; number < _historyEntryCount; number++){
+ for(int number = 0; number < _historyEntryCount; number++) {
sum += _historyVector->operator[](number)[location];
}
_averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
}
}
- else{
+ else {
memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
}
}
}
void
-SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
- const uint64_t /*numTimeDomainDataPoints*/ )
+SpectrumDisplayForm::resizeBuffers(const uint64_t numFFTDataPoints,
+ const uint64_t /*numTimeDomainDataPoints*/)
{
// Convert from Complex to Real for certain Displays
- if(_numRealDataPoints != numFFTDataPoints){
+ if(_numRealDataPoints != numFFTDataPoints) {
_numRealDataPoints = numFFTDataPoints;
delete[] _realFFTDataPoints;
delete[] _averagedValues;
@@ -497,126 +505,126 @@ SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
const int historySize = _historyVector->size();
- SetAverageCount(0); // Clear the existing history
- SetAverageCount(historySize);
+ setAverageCount(0); // Clear the existing history
+ setAverageCount(historySize);
- Reset();
+ reset();
}
}
void
-SpectrumDisplayForm::Reset()
+SpectrumDisplayForm::reset()
{
- AverageDataReset();
+ averageDataReset();
- _waterfallDisplayPlot->Reset();
+ _waterfallDisplayPlot->resetAxis();
}
void
-SpectrumDisplayForm::AverageDataReset()
+SpectrumDisplayForm::averageDataReset()
{
_historyEntry = 0;
_historyEntryCount = 0;
memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
- MaxHoldResetBtn_clicked();
- MinHoldResetBtn_clicked();
+ maxHoldResetBtn_clicked();
+ minHoldResetBtn_clicked();
}
void
-SpectrumDisplayForm::closeEvent( QCloseEvent *e )
+SpectrumDisplayForm::closeEvent(QCloseEvent *e)
{
if(_systemSpecifiedFlag){
- _system->SetWindowOpenFlag(false);
+ _system->setWindowOpenFlag(false);
}
qApp->processEvents();
- QWidget::closeEvent(e);
+ QWidget::closeEvent(e); //equivalent to e->accept()
}
void
-SpectrumDisplayForm::WindowTypeChanged( int newItem )
+SpectrumDisplayForm::windowTypeChanged(int newItem)
{
- if(_systemSpecifiedFlag){
- _system->SetWindowType(newItem);
+ if(_systemSpecifiedFlag) {
+ _system->setWindowType(newItem);
}
}
void
-SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
+SpectrumDisplayForm::useRFFrequenciesCB(bool useRFFlag)
{
- SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
+ setFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
}
void
-SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
+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
-SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
+SpectrumDisplayForm::fftComboBoxSelectedCB(const QString &fftSizeString)
{
if(_systemSpecifiedFlag){
- _system->SetFFTSize(fftSizeString.toLong());
+ _system->setFFTSize(fftSizeString.toLong());
}
}
void
-SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
+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);
}
void
-SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
+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();
+ lowIntensityColor = _waterfallDisplayPlot->getUserDefinedLowIntensityColor();
if(!lowIntensityColor.isValid()){
lowIntensityColor = Qt::black;
}
@@ -624,7 +632,7 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
// Select the High Intensity Color
- highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
+ highIntensityColor = _waterfallDisplayPlot->getUserDefinedHighIntensityColor();
if(!highIntensityColor.isValid()){
highIntensityColor = Qt::white;
}
@@ -632,11 +640,11 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
}
- _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
+ _waterfallDisplayPlot->setIntensityColorMapType(0, newType, lowIntensityColor, highIntensityColor);
}
void
-SpectrumDisplayForm::ToggleTabFrequency(const bool state)
+SpectrumDisplayForm::toggleTabFrequency(const bool state)
{
if(state == true) {
if(d_plot_fft == -1) {
@@ -651,7 +659,7 @@ SpectrumDisplayForm::ToggleTabFrequency(const bool state)
}
void
-SpectrumDisplayForm::ToggleTabWaterfall(const bool state)
+SpectrumDisplayForm::toggleTabWaterfall(const bool state)
{
if(state == true) {
if(d_plot_waterfall == -1) {
@@ -666,7 +674,7 @@ SpectrumDisplayForm::ToggleTabWaterfall(const bool state)
}
void
-SpectrumDisplayForm::ToggleTabTime(const bool state)
+SpectrumDisplayForm::toggleTabTime(const bool state)
{
if(state == true) {
if(d_plot_time == -1) {
@@ -681,7 +689,7 @@ SpectrumDisplayForm::ToggleTabTime(const bool state)
}
void
-SpectrumDisplayForm::ToggleTabConstellation(const bool state)
+SpectrumDisplayForm::toggleTabConstellation(const bool state)
{
if(state == true) {
if(d_plot_constellation == -1) {
@@ -697,32 +705,32 @@ SpectrumDisplayForm::ToggleTabConstellation(const bool state)
void
-SpectrumDisplayForm::SetTimeDomainAxis(double min, double max)
+SpectrumDisplayForm::setTimeDomainAxis(double min, double max)
{
_timeDomainDisplayPlot->setYaxis(min, max);
}
void
-SpectrumDisplayForm::SetConstellationAxis(double xmin, double xmax,
+SpectrumDisplayForm::setConstellationAxis(double xmin, double xmax,
double ymin, double ymax)
{
_constellationDisplayPlot->set_axis(xmin, xmax, ymin, ymax);
}
void
-SpectrumDisplayForm::SetConstellationPenSize(int size)
+SpectrumDisplayForm::setConstellationPenSize(int size)
{
_constellationDisplayPlot->set_pen_size( size );
}
void
-SpectrumDisplayForm::SetFrequencyAxis(double min, double max)
+SpectrumDisplayForm::setFrequencyAxis(double min, double max)
{
- _frequencyDisplayPlot->set_yaxis(min, max);
+ _frequencyDisplayPlot->setYaxis(min, max);
}
void
-SpectrumDisplayForm::SetUpdateTime(double t)
+SpectrumDisplayForm::setUpdateTime(double t)
{
d_update_time = t;
// QTimer class takes millisecond input
diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h
index 63dd304d52..c5b714e73f 100644
--- a/gr-qtgui/lib/spectrumdisplayform.h
+++ b/gr-qtgui/lib/spectrumdisplayform.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ * Copyright 2008-2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -45,53 +45,53 @@ class SpectrumDisplayForm : public QWidget, public Ui::SpectrumDisplayForm
SpectrumDisplayForm(QWidget* parent = 0);
~SpectrumDisplayForm();
- void setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints,
- const uint64_t numTimeDomainDataPoints );
+ void setSystem(SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints,
+ const uint64_t numTimeDomainDataPoints);
- int GetAverageCount();
- void SetAverageCount( const int newCount );
- void Reset();
- void AverageDataReset();
- void ResizeBuffers( const uint64_t numFFTDataPoints,
- const uint64_t numTimeDomainDataPoints );
+ int getAverageCount();
+ void setAverageCount(const int newCount);
+ void reset();
+ void averageDataReset();
+ void resizeBuffers(const uint64_t numFFTDataPoints,
+ const uint64_t numTimeDomainDataPoints);
public slots:
- void resizeEvent( QResizeEvent * e );
- void customEvent( QEvent * e );
- void AvgLineEdit_valueChanged( int valueString );
- void MaxHoldCheckBox_toggled( bool newState );
- void MinHoldCheckBox_toggled( bool newState );
- void MinHoldResetBtn_clicked();
- void MaxHoldResetBtn_clicked();
- void TabChanged(int index);
-
- void SetFrequencyRange( const double newCenterFrequency,
- const double newStartFrequency,
- const double newStopFrequency );
- void closeEvent( QCloseEvent * e );
- void WindowTypeChanged( int newItem );
- void UseRFFrequenciesCB( bool useRFFlag );
+ void resizeEvent(QResizeEvent * e);
+ void customEvent(QEvent * e);
+ void avgLineEdit_valueChanged(int valueString);
+ void maxHoldCheckBox_toggled(bool newState);
+ void minHoldCheckBox_toggled(bool newState);
+ void minHoldResetBtn_clicked();
+ void maxHoldResetBtn_clicked();
+ void tabChanged(int index);
+
+ void setFrequencyRange(const double newCenterFrequency,
+ const double newStartFrequency,
+ const double newStopFrequency);
+ void closeEvent(QCloseEvent * e);
+ void windowTypeChanged(int newItem);
+ void useRFFrequenciesCB(bool useRFFlag);
void waterfallMaximumIntensityChangedCB(double);
void waterfallMinimumIntensityChangedCB(double);
- void WaterfallIntensityColorTypeChanged(int);
- void WaterfallAutoScaleBtnCB();
- void FFTComboBoxSelectedCB(const QString&);
+ void waterfallIntensityColorTypeChanged(int);
+ void waterfallAutoScaleBtnCB();
+ void fftComboBoxSelectedCB(const QString&);
- void ToggleTabFrequency(const bool state);
- void ToggleTabWaterfall(const bool state);
- void ToggleTabTime(const bool state);
- void ToggleTabConstellation(const bool state);
+ void toggleTabFrequency(const bool state);
+ void toggleTabWaterfall(const bool state);
+ void toggleTabTime(const bool state);
+ void toggleTabConstellation(const bool state);
- void SetTimeDomainAxis(double min, double max);
- void SetConstellationAxis(double xmin, double xmax,
+ void setTimeDomainAxis(double min, double max);
+ void setConstellationAxis(double xmin, double xmax,
double ymin, double ymax);
- void SetConstellationPenSize(int size);
- void SetFrequencyAxis(double min, double max);
- void SetUpdateTime(double t);
+ void setConstellationPenSize(int size);
+ void setFrequencyAxis(double min, double max);
+ void setUpdateTime(double t);
private slots:
- void newFrequencyData( const SpectrumUpdateEvent* );
- void UpdateGuiTimer();
+ void newFrequencyData(const SpectrumUpdateEvent*);
+ void updateGuiTimer();
void onFFTPlotPointSelected(const QPointF p);
void onWFallPlotPointSelected(const QPointF p);
@@ -102,7 +102,7 @@ signals:
void plotPointSelected(const QPointF p, int type);
private:
- void _AverageHistory( const double * newBuffer );
+ void _averageHistory(const double * newBuffer);
int _historyEntryCount;
int _historyEntry;
diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui
index 049d4ffeb4..f1e1f08f98 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>
@@ -548,7 +536,7 @@
<sender>MaxHoldCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>MaxHoldCheckBox_toggled(bool)</slot>
+ <slot>maxHoldCheckBox_toggled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>22</x>
@@ -564,7 +552,7 @@
<sender>MaxHoldResetBtn</sender>
<signal>clicked()</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>MaxHoldResetBtn_clicked()</slot>
+ <slot>maxHoldResetBtn_clicked()</slot>
<hints>
<hint type="sourcelabel">
<x>107</x>
@@ -580,7 +568,7 @@
<sender>MinHoldCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>MinHoldCheckBox_toggled(bool)</slot>
+ <slot>minHoldCheckBox_toggled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>22</x>
@@ -596,7 +584,7 @@
<sender>MinHoldResetBtn</sender>
<signal>clicked()</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>MinHoldResetBtn_clicked()</slot>
+ <slot>minHoldResetBtn_clicked()</slot>
<hints>
<hint type="sourcelabel">
<x>107</x>
@@ -612,7 +600,7 @@
<sender>WindowComboBox</sender>
<signal>activated(int)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>WindowTypeChanged(int)</slot>
+ <slot>windowTypeChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
@@ -628,7 +616,7 @@
<sender>UseRFFrequenciesCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>UseRFFrequenciesCB(bool)</slot>
+ <slot>useRFFrequenciesCB(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
@@ -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>
@@ -676,7 +664,7 @@
<sender>FFTSizeComboBox</sender>
<signal>activated(QString)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>FFTComboBoxSelectedCB(QString)</slot>
+ <slot>fftComboBoxSelectedCB(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
@@ -692,7 +680,7 @@
<sender>WaterfallAutoScaleBtn</sender>
<signal>clicked()</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>WaterfallAutoScaleBtnCB()</slot>
+ <slot>waterfallAutoScaleBtnCB()</slot>
<hints>
<hint type="sourcelabel">
<x>22</x>
@@ -708,7 +696,7 @@
<sender>WaterfallIntensityComboBox</sender>
<signal>activated(int)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>WaterfallIntensityColorTypeChanged(int)</slot>
+ <slot>waterfallIntensityColorTypeChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>92</x>
@@ -724,7 +712,7 @@
<sender>SpectrumTypeTab</sender>
<signal>currentChanged(int)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>TabChanged(int)</slot>
+ <slot>tabChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>314</x>
@@ -740,7 +728,7 @@
<sender>AvgLineEdit</sender>
<signal>valueChanged(int)</signal>
<receiver>SpectrumDisplayForm</receiver>
- <slot>AvgLineEdit_valueChanged(int)</slot>
+ <slot>avgLineEdit_valueChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>604</x>
diff --git a/gr-qtgui/lib/timeRasterGlobalData.cc b/gr-qtgui/lib/timeRasterGlobalData.cc
new file mode 100644
index 0000000000..556196f644
--- /dev/null
+++ b/gr-qtgui/lib/timeRasterGlobalData.cc
@@ -0,0 +1,240 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 TIMERASTER_GLOBAL_DATA_CPP
+#define TIMERASTER_GLOBAL_DATA_CPP
+
+#include <timeRasterGlobalData.h>
+#include <cstdio>
+#include <cmath>
+#include <iostream>
+
+TimeRasterData::TimeRasterData(const double rows, const double cols)
+#if QWT_VERSION < 0x060000
+ : QwtRasterData(QwtDoubleRect(0, 0, rows, cols))
+#else
+ : QwtRasterData()
+#endif
+{
+ d_nitems = 0;
+ d_rows = rows;
+ d_cols = cols;
+ d_resid = 0;
+
+ // We add 1 here so we always have the next row already started
+ // (helps when d_cols is fractional and we have to slide).
+ d_totalitems = static_cast<int>((d_rows+1)*floor(d_cols));
+ d_data_size = d_totalitems + static_cast<int>(floor(d_cols));
+
+ d_intensityRange = QwtDoubleInterval(0.0, 10.0);
+ d_data = new double[d_data_size];
+
+#if QWT_VERSION >= 0x060000
+ setInterval(Qt::XAxis, QwtInterval(0, cols));
+ setInterval(Qt::YAxis, QwtInterval(0, rows));
+ setInterval(Qt::ZAxis, QwtInterval(0.0, 10.0));
+#endif
+
+ reset();
+}
+
+TimeRasterData::~TimeRasterData()
+{
+ delete [] d_data;
+}
+
+void TimeRasterData::reset()
+{
+ d_resid = 0;
+ d_nitems = 0;
+ memset(d_data, 0x0, d_data_size*sizeof(double));
+}
+
+void TimeRasterData::copy(const TimeRasterData* rhs)
+{
+#if QWT_VERSION < 0x060000
+ if((d_cols != rhs->getNumCols()) ||
+ (boundingRect() != rhs->boundingRect()) ){
+ d_cols = rhs->getNumCols();
+ d_rows = rhs->getNumRows();
+ d_totalitems = static_cast<int>((d_rows+1)*floor(d_cols));
+ d_data_size = d_totalitems + static_cast<int>(floor(d_cols));
+ setBoundingRect(rhs->boundingRect());
+ delete [] d_data;
+ d_data = new double[d_data_size];
+ }
+#else
+ if((d_cols != rhs->getNumCols()) || (d_rows != rhs->getNumRows())) {
+ d_cols = rhs->getNumCols();
+ d_rows = rhs->getNumRows();
+ d_totalitems = static_cast<int>((d_rows+1)*floor(d_cols));
+ d_data_size = d_totalitems + static_cast<int>(floor(d_cols));
+ delete [] d_data;
+ d_data = new double[d_data_size];
+ }
+#endif
+
+ reset();
+
+#if QWT_VERSION < 0x060000
+ setRange(rhs->range());
+#else
+ setInterval(Qt::XAxis, rhs->interval(Qt::XAxis));
+ setInterval(Qt::YAxis, rhs->interval(Qt::YAxis));
+ setInterval(Qt::ZAxis, rhs->interval(Qt::ZAxis));
+#endif
+}
+
+void TimeRasterData::resizeData(const double rows, const double cols)
+{
+#if QWT_VERSION < 0x060000
+ if((cols != getNumCols()) || (boundingRect().width() != cols) ||
+ (rows != getNumRows()) || (boundingRect().height() != cols)) {
+ setBoundingRect(QwtDoubleRect(0, 0, cols, rows));
+ d_cols = cols;
+ d_rows = rows;
+ d_totalitems = static_cast<int>((d_rows+1)*floor(d_cols));
+ d_data_size = d_totalitems + static_cast<int>(floor(d_cols));
+ delete [] d_data;
+ d_data = new double[d_data_size];
+ }
+
+#else
+ if((cols != getNumCols()) || (interval(Qt::XAxis).width() != cols) ||
+ (rows != getNumRows()) || (interval(Qt::YAxis).width() != rows)) {
+
+ setInterval(Qt::XAxis, QwtInterval(0, cols));
+ setInterval(Qt::YAxis, QwtInterval(0, rows));
+
+ d_cols = cols;
+ d_rows = rows;
+ d_totalitems = static_cast<int>((d_rows+1)*floor(d_cols));
+ d_data_size = d_totalitems + static_cast<int>(floor(d_cols));
+
+ delete [] d_data;
+ d_data = new double[d_data_size];
+ }
+#endif
+
+ reset();
+}
+
+QwtRasterData *TimeRasterData::copy() const
+{
+#if QWT_VERSION < 0x060000
+ TimeRasterData* returnData = \
+ new TimeRasterData(d_cols, d_rows);
+#else
+ TimeRasterData* returnData = \
+ new TimeRasterData(d_cols, d_rows);
+#endif
+
+ returnData->copy(this);
+ return returnData;
+}
+
+
+#if QWT_VERSION < 0x060000
+QwtDoubleInterval TimeRasterData::range() const
+{
+ return d_intensityRange;
+}
+
+void TimeRasterData::setRange(const QwtDoubleInterval& newRange)
+{
+ d_intensityRange = newRange;
+}
+
+#endif
+
+
+double
+TimeRasterData::value(double x, double y) const
+{
+ double returnValue = 0.0;
+
+#if QWT_VERSION < 0x060000
+ double top = boundingRect().top();
+ double bottom = top - boundingRect().height();
+ double left = boundingRect().left();
+ double right = left - boundingRect().width();
+#else
+ double top = interval(Qt::YAxis).maxValue();
+ double bottom = interval(Qt::YAxis).minValue();
+ double left = interval(Qt::XAxis).minValue();
+ double right = interval(Qt::XAxis).maxValue();
+#endif
+
+ if((x < left) || (x > right) || (y < bottom) || (y > top))
+ return 0.0;
+
+ double _y = floor(top - y);
+ double _loc = _y*(d_cols) + x + d_resid;
+ int location = static_cast<int>(_loc);
+
+ if((location > -1) && (location < d_data_size)) {
+ returnValue = d_data[location];
+ }
+
+ return returnValue;
+}
+
+void
+TimeRasterData::incrementResidual()
+{
+ // After a full set of rows are drawn, we want to add up the
+ // residual due to any fractional value of d_cols to appropriately
+ // shift the next data in.
+ double icols = floor(d_cols);
+ d_resid = fmod(d_resid + (d_cols - icols) * d_rows, icols);
+}
+
+double
+TimeRasterData::getNumCols() const
+{
+ return d_cols;
+}
+
+double
+TimeRasterData::getNumRows() const
+{
+ return d_rows;
+}
+
+void
+TimeRasterData::addData(const double* data,
+ const int dataSize)
+{
+ int cols = static_cast<int>(d_cols);
+ if(dataSize == cols) {
+ if(d_nitems < d_totalitems) {
+ memcpy(&d_data[d_nitems], data, cols*sizeof(double));
+ d_nitems += cols;
+ }
+ else {
+ memcpy(&d_data[d_nitems], data, cols*sizeof(double));
+ memmove(d_data, &d_data[cols], d_totalitems*sizeof(double));
+ }
+ }
+}
+
+#endif /* TIMERASTER_GLOBAL_DATA_CPP */
diff --git a/gr-qtgui/lib/timeRasterGlobalData.h b/gr-qtgui/lib/timeRasterGlobalData.h
new file mode 100644
index 0000000000..0a414432d1
--- /dev/null
+++ b/gr-qtgui/lib/timeRasterGlobalData.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 TIMERASTER_GLOBAL_DATA_HPP
+#define TIMERASTER_GLOBAL_DATA_HPP
+
+#include <qwt_raster_data.h>
+#include <inttypes.h>
+
+#if QWT_VERSION >= 0x060000
+#include <qwt_point_3d.h> // doesn't seem necessary, but is...
+#include <qwt_compat.h>
+#endif
+
+class TimeRasterData: public QwtRasterData
+{
+public:
+ TimeRasterData(const double rows, const double cols);
+ virtual ~TimeRasterData();
+
+ virtual void reset();
+ virtual void copy(const TimeRasterData*);
+
+ virtual void resizeData(const double rows, const double cols);
+
+ virtual QwtRasterData *copy() const;
+
+#if QWT_VERSION < 0x060000
+ virtual QwtDoubleInterval range() const;
+ virtual void setRange(const QwtDoubleInterval&);
+#endif
+
+ virtual double value(double x, double y) const;
+
+ virtual double getNumCols()const;
+ virtual double getNumRows()const;
+
+ virtual void addData(const double*, const int);
+
+ void incrementResidual();
+
+protected:
+
+ double* d_data;
+ double d_rows, d_cols;
+ double d_resid;
+ int d_nitems, d_totalitems, d_data_size;
+
+#if QWT_VERSION < 0x060000
+ QwtDoubleInterval d_intensityRange;
+#else
+ QwtInterval d_intensityRange;
+#endif
+
+private:
+
+};
+
+#endif /* TIMERASTER_GLOBAL_DATA_HPP */
diff --git a/gr-qtgui/lib/time_raster_sink_b_impl.cc b/gr-qtgui/lib/time_raster_sink_b_impl.cc
new file mode 100644
index 0000000000..d90661b968
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.cc
@@ -0,0 +1,441 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_raster_sink_b_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_raster_sink_b::sptr
+ time_raster_sink_b::make(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_raster_sink_b_impl(samp_rate,
+ rows, cols,
+ mult, offset,
+ name,
+ nconnections,
+ parent));
+ }
+
+ time_raster_sink_b_impl::time_raster_sink_b_impl(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("time_raster_sink_b",
+ gr_make_io_signature(1, -1, sizeof(char)),
+ gr_make_io_signature(0, 0, 0)),
+ d_name(name), d_nconnections(nconnections), d_parent(parent),
+ d_rows(rows), d_cols(cols),
+ d_mult(std::vector<float>(nconnections,1)),
+ d_offset(std::vector<float>(nconnections,0)),
+ d_samp_rate(samp_rate)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+
+ d_scale = 1.0f;
+
+ d_icols = static_cast<int>(ceil(d_cols));
+ d_tmpflt = fft::malloc_float(d_icols);
+ memset(d_tmpflt, 0, d_icols*sizeof(float));
+
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_double(d_icols));
+ memset(d_residbufs[i], 0, d_icols*sizeof(double));
+ }
+
+ set_multiplier(mult);
+ set_offset(offset);
+
+ initialize();
+ }
+
+ time_raster_sink_b_impl::~time_raster_sink_b_impl()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ fft::free(d_tmpflt);
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ bool
+ time_raster_sink_b_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ void
+ time_raster_sink_b_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc = 0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ // Create time raster plot; as a bit input, we expect to see 1's
+ // and 0's from each stream, so we set the maximum intensity
+ // (zmax) to the number of connections so after adding the
+ // streams, the max will the the max of 1's from all streams.
+ d_main_gui = new TimeRasterDisplayForm(d_nconnections,
+ d_samp_rate,
+ d_rows, d_cols,
+ 1, d_parent);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ void
+ time_raster_sink_b_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ time_raster_sink_b_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ time_raster_sink_b_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ time_raster_sink_b_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);
+ d_last_time = 0;
+ }
+
+ void
+ time_raster_sink_b_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(which, color.c_str());
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ time_raster_sink_b_impl::set_color_map(int which, const int color)
+ {
+ d_main_gui->setColorMap(which, color);
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ time_raster_sink_b_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ time_raster_sink_b_impl::set_samp_rate(const double samp_rate)
+ {
+ d_samp_rate = samp_rate;
+ d_main_gui->setSampleRate(d_samp_rate);
+ }
+
+ void
+ time_raster_sink_b_impl::set_num_rows(double rows)
+ {
+ d_main_gui->setNumRows(rows);
+ }
+
+ void
+ time_raster_sink_b_impl::set_num_cols(double cols)
+ {
+ d_main_gui->setNumCols(cols);
+ }
+
+ std::string
+ time_raster_sink_b_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ time_raster_sink_b_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ time_raster_sink_b_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ time_raster_sink_b_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ time_raster_sink_b_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ time_raster_sink_b_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ int
+ time_raster_sink_b_impl::color_map(int which)
+ {
+ return d_main_gui->getColorMap(which);
+ }
+
+ double
+ time_raster_sink_b_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ double
+ time_raster_sink_b_impl::num_rows()
+ {
+ return d_main_gui->numRows();
+ }
+
+ double
+ time_raster_sink_b_impl::num_cols()
+ {
+ return d_main_gui->numCols();
+ }
+
+ void
+ time_raster_sink_b_impl::set_multiplier(const std::vector<float> &mult)
+ {
+ if(mult.size() == 0) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_mult[i] = 1.0f;
+ }
+ }
+ else if(mult.size() == (size_t)d_nconnections) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_mult[i] = mult[i];
+ }
+ }
+ else {
+ throw std::runtime_error("time_raster_sink_b_impl::set_multiplier incorrect dimensions.\n");
+ }
+ }
+
+ void
+ time_raster_sink_b_impl::set_offset(const std::vector<float> &offset)
+ {
+ if(offset.size() == 0) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_offset[i] = 0.0f;
+ }
+ }
+ else if(offset.size() == (size_t)d_nconnections) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_offset[i] = offset[i];
+ }
+ }
+ else {
+ throw std::runtime_error("time_raster_sink_b_impl::set_offset incorrect dimensions.\n");
+ }
+ }
+
+ void
+ time_raster_sink_b_impl::set_intensity_range(float min, float max)
+ {
+ d_main_gui->setIntensityRange(min, max);
+ }
+
+ void
+ time_raster_sink_b_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ time_raster_sink_b_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ time_raster_sink_b_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ time_raster_sink_b_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ int
+ time_raster_sink_b_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 int8_t *in = (const int8_t*)input_items[0];
+
+ unsigned int cols = d_main_gui->numCols();
+ if(d_cols != cols) {
+ d_cols = cols;
+ d_index = 0;
+ d_icols = static_cast<int>(ceil(d_cols));
+ fft::free(d_tmpflt);
+ d_tmpflt = fft::malloc_float(d_icols);
+ memset(d_tmpflt, 0, d_icols*sizeof(float));
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ d_residbufs[i] = fft::malloc_double(d_icols);
+ memset(d_residbufs[i], 0, d_icols*sizeof(double));
+ }
+ }
+
+ for(int i = 0; i < noutput_items; i += d_icols) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_icols-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 int8_t*)input_items[idx++];
+ volk_8i_s32f_convert_32f(d_tmpflt, &in[j],
+ d_scale, resid);
+
+ // Scale and add offset
+ volk_32f_s32f_multiply_32f(d_tmpflt, d_tmpflt, d_mult[n], resid);
+ for(unsigned int s = 0; s < resid; s++)
+ d_tmpflt[s] = d_tmpflt[s] + d_offset[n];
+
+ volk_32f_convert_64f_u(&d_residbufs[n][d_index],
+ d_tmpflt, resid);
+ }
+
+ 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 TimeRasterUpdateEvent(d_residbufs, d_icols));
+ }
+
+ 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 int8_t*)input_items[idx++];
+ volk_8i_s32f_convert_32f(d_tmpflt, &in[j],
+ d_scale, datasize);
+
+ // Scale and add offset
+ volk_32f_s32f_multiply_32f(d_tmpflt, d_tmpflt, d_mult[n], datasize);
+ for(unsigned int s = 0; s < datasize; s++)
+ d_tmpflt[s] = d_tmpflt[s] + d_offset[n];
+
+ volk_32f_convert_64f(&d_residbufs[n][d_index],
+ d_tmpflt, datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/time_raster_sink_b_impl.h b/gr-qtgui/lib/time_raster_sink_b_impl.h
new file mode 100644
index 0000000000..68dfa25aac
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.h
@@ -0,0 +1,124 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_RASTER_SINK_B_IMPL_H
+#define INCLUDED_QTGUI_TIME_RASTER_SINK_B_IMPL_H
+
+#include <qtgui/time_raster_sink_b.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <timerasterdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API time_raster_sink_b_impl : public time_raster_sink_b
+ {
+ private:
+ void initialize();
+
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<double*> d_residbufs;
+
+ float d_scale;
+ float *d_tmpflt;
+
+ QWidget *d_parent;
+ TimeRasterDisplayForm *d_main_gui;
+
+ int d_icols;
+ double d_rows, d_cols;
+ std::vector<float> d_mult;
+ std::vector<float> d_offset;
+ double d_samp_rate;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ public:
+ time_raster_sink_b_impl(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_raster_sink_b_impl();
+
+ bool check_topology (int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_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_line_alpha(int which, double alpha);
+ void set_color_map(int which, const int color);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+ int color_map(int which);
+
+ void set_size(int width, int height);
+
+ void set_samp_rate(const double samp_rate);
+ void set_num_rows(double rows);
+ void set_num_cols(double cols);
+
+ double num_rows();
+ double num_cols();
+
+ void set_multiplier(const std::vector<float> &mult);
+ void set_offset(const std::vector<float> &offset);
+
+ void set_intensity_range(float min, float max);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void reset();
+
+ 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_RASTER_SINK_B_IMPL_H */
diff --git a/gr-qtgui/lib/time_raster_sink_c_impl.cc b/gr-qtgui/lib/time_raster_sink_c_impl.cc
new file mode 100644
index 0000000000..17098f0d93
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_c_impl.cc
@@ -0,0 +1,222 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_raster_sink_c_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_raster_sink_c::sptr
+ time_raster_sink_c::make(unsignedint rows,
+ unsigned int cols,
+ const std::string &name,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_raster_sink_c_impl(rows, cols,
+ name, parent));
+ }
+
+ time_raster_sink_c_impl::time_raster_sink_c_impl(unsignedint rows,
+ unsigned int cols,
+ const std::string &name,
+ QWidget *parent)
+ : gr_sync_block("time_raster_sink_c",
+ gr_make_io_signature(1, -1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_name(name), d_nconnections(1), d_parent(parent),
+ d_rows(rows), d_cols(cols)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_complex(rows));
+ memset(d_residbufs[i], 0, rows*sizeof(float));
+ }
+
+ initialize();
+ }
+
+ time_raster_sink_c_impl::~time_raster_sink_c_impl()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ void
+ time_raster_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_rows, 8191);
+ }
+ }
+
+ void
+ time_raster_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 TimeRasterDisplayForm(d_nconnections, d_rows, d_cols, d_parent);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ d_last_time = 0;
+ }
+
+ void
+ time_raster_sink_c_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ time_raster_sink_c_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ time_raster_sink_c_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ time_raster_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_raster_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ time_raster_sink_c_impl::set_line_label(const std::string &label)
+ {
+ d_main_gui->setLineLabel(0, label.c_str());
+ }
+
+ void
+ time_raster_sink_c_impl::set_line_color(const std::string &color)
+ {
+ d_main_gui->setLineColor(0, color.c_str());
+ }
+
+ void
+ time_raster_sink_c_impl::set_line_width(int width)
+ {
+ d_main_gui->setLineWidth(0, width);
+ }
+
+ void
+ time_raster_sink_c_impl::set_line_style(Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(0, style);
+ }
+
+ void
+ time_raster_sink_c_impl::set_line_marker(QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(0, marker);
+ }
+
+ void
+ time_raster_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ int
+ time_raster_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];
+
+ for(int i=0; i < noutput_items; i+=d_cols) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_cols-d_index;
+
+ // If we have enough input for one full column
+ if(datasize >= resid) {
+
+ 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)*resid);
+ }
+
+ 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 TimeRasterUpdateEvent(d_residbufs,
+ 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/time_raster_sink_c_impl.h b/gr-qtgui/lib/time_raster_sink_c_impl.h
new file mode 100644
index 0000000000..f3594d58a5
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_c_impl.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_RASTER_SINK_C_IMPL_H
+#define INCLUDED_QTGUI_TIME_RASTER_SINK_C_IMPL_H
+
+#include <qtgui/time_raster_sink_c.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <time_rasterdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API time_raster_sink_c_impl : public time_raster_sink_c
+ {
+ private:
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ void initialize();
+
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<gr_complex*> d_residbufs;
+ float *d_fbuf;
+
+ QWidget *d_parent;
+ TimeRasterDisplayForm *d_main_gui;
+
+ unsigned int d_rows, d_cols;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ public:
+ time_raster_sink_c_impl(unsignedint rows,
+ unsigned int cols,
+ const std::string &name,
+ QWidget *parent=NULL);
+ ~time_raster_sink_c_impl();
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(const std::string &label);
+ void set_line_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_TIME_RASTER_SINK_C_IMPL_H */
diff --git a/gr-qtgui/lib/time_raster_sink_f_impl.cc b/gr-qtgui/lib/time_raster_sink_f_impl.cc
new file mode 100644
index 0000000000..39237e2912
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.cc
@@ -0,0 +1,436 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_raster_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_raster_sink_f::sptr
+ time_raster_sink_f::make(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_raster_sink_f_impl(samp_rate,
+ rows, cols,
+ mult, offset,
+ name,
+ nconnections,
+ parent));
+ }
+
+ time_raster_sink_f_impl::time_raster_sink_f_impl(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("time_raster_sink_f",
+ gr_make_io_signature(1, -1, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_name(name), d_nconnections(nconnections), d_parent(parent),
+ d_rows(rows), d_cols(cols),
+ d_mult(std::vector<float>(nconnections,1)),
+ d_offset(std::vector<float>(nconnections,0)),
+ d_samp_rate(samp_rate)
+ {
+ d_main_gui = NULL;
+
+ d_index = 0;
+
+ d_icols = static_cast<int>(ceil(d_cols));
+ d_tmpflt = fft::malloc_float(d_icols);
+ memset(d_tmpflt, 0, d_icols*sizeof(float));
+
+ for(int i = 0; i < d_nconnections; i++) {
+ d_residbufs.push_back(fft::malloc_double(d_icols));
+ memset(d_residbufs[i], 0, d_icols*sizeof(double));
+ }
+
+ set_multiplier(mult);
+ set_offset(offset);
+
+ initialize();
+ }
+
+ time_raster_sink_f_impl::~time_raster_sink_f_impl()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ fft::free(d_tmpflt);
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ bool
+ time_raster_sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ void
+ time_raster_sink_f_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ int argc = 0;
+ char **argv = NULL;
+ d_qApplication = new QApplication(argc, argv);
+ }
+
+ // Create time raster plot; as a bit input, we expect to see 1's
+ // and 0's from each stream, so we set the maximum intensity
+ // (zmax) to the number of connections so after adding the
+ // streams, the max will the the max of 1's from all streams.
+ d_main_gui = new TimeRasterDisplayForm(d_nconnections,
+ d_samp_rate,
+ d_rows, d_cols,
+ 1, d_parent);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ void
+ time_raster_sink_f_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ time_raster_sink_f_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+ PyObject*
+ time_raster_sink_f_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+
+ void
+ time_raster_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);
+ d_last_time = 0;
+ }
+
+ void
+ time_raster_sink_f_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(which, color.c_str());
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_width(int which, int width)
+ {
+ d_main_gui->setLineWidth(which, width);
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_style(int which, Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(which, style);
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(which, marker);
+ }
+
+ void
+ time_raster_sink_f_impl::set_color_map(int which, const int color)
+ {
+ d_main_gui->setColorMap(which, color);
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ time_raster_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ void
+ time_raster_sink_f_impl::set_samp_rate(const double samp_rate)
+ {
+ d_samp_rate = samp_rate;
+ d_main_gui->setSampleRate(d_samp_rate);
+ }
+
+ void
+ time_raster_sink_f_impl::set_num_rows(double rows)
+ {
+ d_main_gui->setNumRows(rows);
+ }
+
+ void
+ time_raster_sink_f_impl::set_num_cols(double cols)
+ {
+ d_main_gui->setNumCols(cols);
+ }
+
+ std::string
+ time_raster_sink_f_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ time_raster_sink_f_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ time_raster_sink_f_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ time_raster_sink_f_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ time_raster_sink_f_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ time_raster_sink_f_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ int
+ time_raster_sink_f_impl::color_map(int which)
+ {
+ return d_main_gui->getColorMap(which);
+ }
+
+ double
+ time_raster_sink_f_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ double
+ time_raster_sink_f_impl::num_rows()
+ {
+ return d_main_gui->numRows();
+ }
+
+ double
+ time_raster_sink_f_impl::num_cols()
+ {
+ return d_main_gui->numCols();
+ }
+
+ void
+ time_raster_sink_f_impl::set_multiplier(const std::vector<float> &mult)
+ {
+ if(mult.size() == 0) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_mult[i] = 1.0f;
+ }
+ }
+ else if(mult.size() == (size_t)d_nconnections) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_mult[i] = mult[i];
+ }
+ }
+ else {
+ throw std::runtime_error("time_raster_sink_f_impl::set_multiplier incorrect dimensions.\n");
+ }
+ }
+
+ void
+ time_raster_sink_f_impl::set_offset(const std::vector<float> &offset)
+ {
+ if(offset.size() == 0) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_offset[i] = 0.0f;
+ }
+ }
+ else if(offset.size() == (size_t)d_nconnections) {
+ for(int i = 0; i < d_nconnections; i++) {
+ d_offset[i] = offset[i];
+ }
+ }
+ else {
+ throw std::runtime_error("time_raster_sink_f_impl::set_offset incorrect dimensions.\n");
+ }
+ }
+
+ void
+ time_raster_sink_f_impl::set_intensity_range(float min, float max)
+ {
+ d_main_gui->setIntensityRange(min, max);
+ }
+
+ void
+ time_raster_sink_f_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ time_raster_sink_f_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ time_raster_sink_f_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ time_raster_sink_f_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ int
+ time_raster_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[0];
+
+ double cols = d_main_gui->numCols();
+ if(d_cols != cols) {
+ d_cols = cols;
+ d_index = 0;
+ d_icols = static_cast<int>(ceil(d_cols));
+ fft::free(d_tmpflt);
+ d_tmpflt = fft::malloc_float(d_icols);
+ memset(d_tmpflt, 0, d_icols*sizeof(float));
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ d_residbufs[i] = fft::malloc_double(d_icols);
+ memset(d_residbufs[i], 0, d_icols*sizeof(double));
+ }
+ }
+
+ for(int i = 0; i < noutput_items; i += d_icols) {
+ unsigned int datasize = noutput_items - i;
+ unsigned int resid = d_icols-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++];
+
+ // Scale and add offset
+ volk_32f_s32f_multiply_32f(d_tmpflt, &in[j], d_mult[n], resid);
+ for(unsigned int s = 0; s < resid; s++)
+ d_tmpflt[s] = d_tmpflt[s] + d_offset[n];
+
+ volk_32f_convert_64f_u(&d_residbufs[n][d_index],
+ d_tmpflt, 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 TimeRasterUpdateEvent(d_residbufs, d_cols));
+ }
+
+ 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++];
+
+ // Scale and add offset
+ volk_32f_s32f_multiply_32f(d_tmpflt, &in[j], d_mult[n], datasize);
+ for(unsigned int s = 0; s < datasize; s++)
+ d_tmpflt[s] = d_tmpflt[s] + d_offset[n];
+
+ volk_32f_convert_64f(&d_residbufs[n][d_index],
+ d_tmpflt, datasize);
+ }
+ d_index += datasize;
+ j += datasize;
+ }
+ }
+
+ return j;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/time_raster_sink_f_impl.h b/gr-qtgui/lib/time_raster_sink_f_impl.h
new file mode 100644
index 0000000000..1d7d791202
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.h
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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_RASTER_SINK_F_IMPL_H
+#define INCLUDED_QTGUI_TIME_RASTER_SINK_F_IMPL_H
+
+#include <qtgui/time_raster_sink_f.h>
+#include <filter/firdes.h>
+#include <fft/fft.h>
+#include <gruel/high_res_timer.h>
+#include <gruel/thread.h>
+#include <timerasterdisplayform.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API time_raster_sink_f_impl : public time_raster_sink_f
+ {
+ private:
+ void initialize();
+
+ std::string d_name;
+ int d_nconnections;
+
+ int d_index;
+ std::vector<double*> d_residbufs;
+
+ float *d_tmpflt;
+
+ QWidget *d_parent;
+ TimeRasterDisplayForm *d_main_gui;
+
+ int d_icols;
+ double d_rows, d_cols;
+ std::vector<float> d_mult;
+ std::vector<float> d_offset;
+ double d_samp_rate;
+
+ gruel::high_res_timer_type d_update_time;
+ gruel::high_res_timer_type d_last_time;
+
+ public:
+ time_raster_sink_f_impl(double samp_rate,
+ double rows, double cols,
+ const std::vector<float> &mult,
+ const std::vector<float> &offset,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_raster_sink_f_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_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_line_alpha(int which, double alpha);
+ void set_color_map(int which, const int color);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+ int color_map(int which);
+
+ void set_size(int width, int height);
+
+ void set_samp_rate(const double samp_rate);
+ void set_num_rows(double rows);
+ void set_num_cols(double cols);
+
+ double num_rows();
+ double num_cols();
+
+ void set_multiplier(const std::vector<float> &mult);
+ void set_offset(const std::vector<float> &offset);
+
+ void set_intensity_range(float min, float max);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void reset();
+
+ 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_RASTER_SINK_F_IMPL_H */
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..2edb83fa12
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_c_impl.cc
@@ -0,0 +1,377 @@
+/* -*- 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>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_sink_c::sptr
+ time_sink_c::make(int size, double samp_rate,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_sink_c_impl(size, samp_rate, name, nconnections, parent));
+ }
+
+ time_sink_c_impl::time_sink_c_impl(int size, double samp_rate,
+ 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_samp_rate(samp_rate), 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()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ // d_main_gui is a qwidget destroyed with its parent
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ bool
+ time_sink_c_impl::check_topology(int ninputs, int noutputs)
+ {
+ return 2*ninputs == d_nconnections;
+ }
+
+ 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);
+ d_main_gui->setSampleRate(d_samp_rate);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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_y_axis(double min, double max)
+ {
+ d_main_gui->setYaxis(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);
+ d_last_time = 0;
+ }
+
+ void
+ time_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ time_sink_c_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ time_sink_c_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(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, int style)
+ {
+ d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
+ }
+
+ void
+ time_sink_c_impl::set_line_marker(int which, int marker)
+ {
+ d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
+ }
+
+ void
+ time_sink_c_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ time_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ time_sink_c_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ time_sink_c_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ time_sink_c_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ time_sink_c_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ time_sink_c_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ time_sink_c_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ double
+ time_sink_c_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ 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::set_samp_rate(const double samp_rate)
+ {
+ gruel::scoped_lock lock(d_mutex);
+ d_samp_rate = samp_rate;
+ d_main_gui->setSampleRate(d_samp_rate);
+ }
+
+ void
+ time_sink_c_impl::npoints_resize()
+ {
+ int newsize = d_main_gui->getNPoints();
+ set_nsamps(newsize);
+ }
+
+ int
+ time_sink_c_impl::nsamps() const
+ {
+ return d_size;
+ }
+
+ void
+ time_sink_c_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ time_sink_c_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ time_sink_c_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ time_sink_c_impl::enable_stem_plot(bool en)
+ {
+ d_main_gui->setStem(en);
+ }
+
+ void
+ time_sink_c_impl::enable_semilogx(bool en)
+ {
+ d_main_gui->setSemilogx(en);
+ }
+
+ void
+ time_sink_c_impl::enable_semilogy(bool en)
+ {
+ d_main_gui->setSemilogy(en);
+ }
+
+ void
+ time_sink_c_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ 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..96bdf937b1
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_c_impl.h
@@ -0,0 +1,110 @@
+/* -*- 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_samp_rate;
+ 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 samp_rate,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_sink_c_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_y_axis(double min, double max);
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, int style);
+ void set_line_marker(int which, int marker);
+ void set_nsamps(const int size);
+ void set_samp_rate(const double samp_rate);
+ void set_line_alpha(int which, double alpha);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+
+ void set_size(int width, int height);
+
+ int nsamps() const;
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void enable_stem_plot(bool en);
+ void enable_semilogx(bool en);
+ void enable_semilogy(bool en);
+ void reset();
+
+ 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..39a62d3d6b
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_f_impl.cc
@@ -0,0 +1,375 @@
+/* -*- 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>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ time_sink_f::sptr
+ time_sink_f::make(int size, double samp_rate,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new time_sink_f_impl(size, samp_rate, name, nconnections, parent));
+ }
+
+ time_sink_f_impl::time_sink_f_impl(int size, double samp_rate,
+ 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_samp_rate(samp_rate), 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()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ // d_main_gui is a qwidget destroyed with its parent
+ for(int i = 0; i < d_nconnections; i++) {
+ fft::free(d_residbufs[i]);
+ }
+ }
+
+ bool
+ time_sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ d_main_gui->setSampleRate(d_samp_rate);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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_y_axis(double min, double max)
+ {
+ d_main_gui->setYaxis(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);
+ d_last_time = 0;
+ }
+
+ void
+ time_sink_f_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ time_sink_f_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ time_sink_f_impl::set_line_color(int which, const std::string &color)
+ {
+ d_main_gui->setLineColor(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, int style)
+ {
+ d_main_gui->setLineStyle(which, (Qt::PenStyle)style);
+ }
+
+ void
+ time_sink_f_impl::set_line_marker(int which, int marker)
+ {
+ d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker);
+ }
+
+ void
+ time_sink_f_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ time_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ time_sink_f_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ time_sink_f_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ std::string
+ time_sink_f_impl::line_color(int which)
+ {
+ return d_main_gui->lineColor(which).toStdString();
+ }
+
+ int
+ time_sink_f_impl::line_width(int which)
+ {
+ return d_main_gui->lineWidth(which);
+ }
+
+ int
+ time_sink_f_impl::line_style(int which)
+ {
+ return d_main_gui->lineStyle(which);
+ }
+
+ int
+ time_sink_f_impl::line_marker(int which)
+ {
+ return d_main_gui->lineMarker(which);
+ }
+
+ double
+ time_sink_f_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ 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::set_samp_rate(const double samp_rate)
+ {
+ gruel::scoped_lock lock(d_mutex);
+ d_samp_rate = samp_rate;
+ d_main_gui->setSampleRate(d_samp_rate);
+ }
+
+ int
+ time_sink_f_impl::nsamps() const
+ {
+ return d_size;
+ }
+
+ void
+ time_sink_f_impl::npoints_resize()
+ {
+ int newsize = d_main_gui->getNPoints();
+ set_nsamps(newsize);
+ }
+
+ void
+ time_sink_f_impl::enable_stem_plot(bool en)
+ {
+ d_main_gui->setStem(en);
+ }
+
+ void
+ time_sink_f_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ time_sink_f_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ void
+ time_sink_f_impl::enable_autoscale(bool en)
+ {
+ d_main_gui->autoScale(en);
+ }
+
+ void
+ time_sink_f_impl::enable_semilogx(bool en)
+ {
+ d_main_gui->setSemilogx(en);
+ }
+
+ void
+ time_sink_f_impl::enable_semilogy(bool en)
+ {
+ d_main_gui->setSemilogy(en);
+ }
+
+ void
+ time_sink_f_impl::reset()
+ {
+ d_index = 0;
+ }
+
+ 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..522511da01
--- /dev/null
+++ b/gr-qtgui/lib/time_sink_f_impl.h
@@ -0,0 +1,110 @@
+/* -*- 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_samp_rate;
+ 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 samp_rate,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~time_sink_f_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void set_y_axis(double min, double max);
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_color(int which, const std::string &color);
+ void set_line_width(int which, int width);
+ void set_line_style(int which, int style);
+ void set_line_marker(int which, int marker);
+ void set_nsamps(const int newsize);
+ void set_samp_rate(const double samp_rate);
+ void set_line_alpha(int which, double alpha);
+
+ std::string title();
+ std::string line_label(int which);
+ std::string line_color(int which);
+ int line_width(int which);
+ int line_style(int which);
+ int line_marker(int which);
+ double line_alpha(int which);
+
+ void set_size(int width, int height);
+
+ int nsamps() const;
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+ void enable_autoscale(bool en);
+ void enable_stem_plot(bool en);
+ void enable_semilogx(bool en);
+ void enable_semilogy(bool en);
+ void reset();
+
+ 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..5e1fbfb570 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,52 @@
*/
#include <cmath>
-#include <QColorDialog>
#include <QMessageBox>
#include <timedisplayform.h>
#include <iostream>
TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent)
- : QWidget(parent)
+ : DisplayForm(nplots, parent)
{
- _systemSpecifiedFlag = false;
+ d_stem = false;
+ d_semilogx = false;
+ d_semilogy = 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)));
+
+ d_stemmenu = new QAction("Stem Plot", this);
+ d_stemmenu->setCheckable(true);
+ _menu->addAction(d_stemmenu);
+ connect(d_stemmenu, SIGNAL(triggered(bool)),
+ this, SLOT(setStem(bool)));
+
+ d_semilogxmenu = new QAction("Semilog X", this);
+ d_semilogxmenu->setCheckable(true);
+ _menu->addAction(d_semilogxmenu);
+ connect(d_semilogxmenu, SIGNAL(triggered(bool)),
+ this, SLOT(setSemilogx(bool)));
+
+ d_semilogymenu = new QAction("Semilog Y", this);
+ d_semilogymenu->setCheckable(true);
+ _menu->addAction(d_semilogymenu);
+ connect(d_semilogymenu, SIGNAL(triggered(bool)),
+ this, SLOT(setSemilogy(bool)));
- // 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,121 +75,107 @@ 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();
- //}
- //}
+ getPlot()->plotNewData(dataPoints,
+ numDataPoints,
+ d_update_time);
}
void
-TimeDisplayForm::updateGuiTimer()
+TimeDisplayForm::customEvent(QEvent * e)
{
- _timeDomainDisplayPlot->canvas()->update();
+ if(e->type() == TimeUpdateEvent::Type()) {
+ newData(e);
+ }
}
void
-TimeDisplayForm::onTimePlotPointSelected(const QPointF p)
+TimeDisplayForm::setSampleRate(const QString &samprate)
{
- emit plotPointSelected(p, 3);
+ setSampleRate(samprate.toDouble());
}
void
-TimeDisplayForm::setFrequencyRange(const double newCenterFrequency,
- const double newStartFrequency,
- const double newStopFrequency)
+TimeDisplayForm::setSampleRate(const double samprate)
{
- double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
-
- if(fdiff > 0) {
+ if(samprate > 0) {
std::string strtime[4] = {"sec", "ms", "us", "ns"};
- double units10 = floor(log10(fdiff));
+ double units10 = floor(log10(samprate));
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;
-
- _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency,
- units, strtime[iunit]);
+ getPlot()->setSampleRate(samprate, units, strtime[iunit]);
+ }
+ else {
+ throw std::runtime_error("TimeDisplayForm: samprate must be > 0.\n");
}
}
void
-TimeDisplayForm::Reset()
+TimeDisplayForm::setYaxis(double min, double max)
{
+ getPlot()->setYaxis(min, max);
}
+int
+TimeDisplayForm::getNPoints() const
+{
+ return d_npoints;
+}
void
-TimeDisplayForm::closeEvent( QCloseEvent *e )
+TimeDisplayForm::setNPoints(const int npoints)
{
- //if(_systemSpecifiedFlag){
- // _system->SetWindowOpenFlag(false);
- //}
-
- qApp->processEvents();
-
- QWidget::closeEvent(e);
+ d_npoints = npoints;
}
void
-TimeDisplayForm::setTimeDomainAxis(double min, double max)
+TimeDisplayForm::setStem(bool en)
{
- _timeDomainDisplayPlot->setYaxis(min, max);
+ d_stem = en;
+ d_stemmenu->setChecked(en);
+ getPlot()->stemPlot(d_stem);
+ getPlot()->replot();
}
void
-TimeDisplayForm::setUpdateTime(double t)
+TimeDisplayForm::autoScale(bool en)
{
- d_update_time = t;
- // QTimer class takes millisecond input
- displayTimer->start(d_update_time*1000);
+ _autoscale_state = en;
+ _autoscale_act->setChecked(en);
+ getPlot()->setAutoScale(_autoscale_state);
+ getPlot()->replot();
}
void
-TimeDisplayForm::setTitle(int which, QString title)
+TimeDisplayForm::setSemilogx(bool en)
{
- _timeDomainDisplayPlot->setTitle(which, title);
+ d_semilogx = en;
+ d_semilogxmenu->setChecked(en);
+ getPlot()->setSemilogx(d_semilogx);
+ getPlot()->replot();
}
void
-TimeDisplayForm::setColor(int which, QString color)
+TimeDisplayForm::setSemilogy(bool en)
{
- _timeDomainDisplayPlot->setColor(which, color);
+ d_semilogy = en;
+ d_semilogymenu->setChecked(en);
+ getPlot()->setSemilogy(d_semilogy);
+ getPlot()->replot();
}
diff --git a/gr-qtgui/lib/timedisplayform.h b/gr-qtgui/lib/timedisplayform.h
index dd3f62a83f..4bc99f622d 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,40 @@ class TimeDisplayForm : public QWidget
TimeDisplayForm(int nplots=1, QWidget* parent = 0);
~TimeDisplayForm();
- void Reset();
-
-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 );
+ TimeDomainDisplayPlot* getPlot();
- void setTimeDomainAxis(double min, double max);
+ int getNPoints() const;
- void setUpdateTime(double t);
+public slots:
+ void customEvent(QEvent * e);
- void setTitle(int which, QString title);
- void setColor(int which, QString color);
+ void setSampleRate(const double samprate);
+ void setSampleRate(const QString &samprate);
+ void setYaxis(double min, double max);
+ void setNPoints(const int);
+ void setStem(bool en);
+ void autoScale(bool en);
+ void setSemilogx(bool en);
+ void setSemilogy(bool en);
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;
+
+ bool d_stem;
+ bool d_semilogx;
+ bool d_semilogy;
+
+ QAction *d_stemmenu;
+ QAction *d_semilogxmenu;
+ QAction *d_semilogymenu;
};
#endif /* TIME_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/timerasterdisplayform.cc b/gr-qtgui/lib/timerasterdisplayform.cc
new file mode 100644
index 0000000000..ed17cf45ce
--- /dev/null
+++ b/gr-qtgui/lib/timerasterdisplayform.cc
@@ -0,0 +1,251 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 <timerasterdisplayform.h>
+#include <iostream>
+
+TimeRasterDisplayForm::TimeRasterDisplayForm(int nplots,
+ double samp_rate,
+ double rows, double cols,
+ double zmax,
+ QWidget* parent)
+ : DisplayForm(nplots, parent)
+{
+#if QWT_VERSION < 0x060000
+ std::cerr << "Warning: QWT5 has been found which has serious performance issues with raster plots."
+ << std::endl << " Consider updating to QWT version 6 to use the time raster GUIs."
+ << std::endl << std::endl;
+#endif
+
+ _layout = new QGridLayout(this);
+ _displayPlot = new TimeRasterDisplayPlot(nplots, samp_rate, rows, cols, this);
+ _layout->addWidget(_displayPlot, 0, 0);
+ setLayout(_layout);
+
+ _min_val = 10;
+ _max_val = -10;
+
+ // We don't use the normal menus that are part of the displayform.
+ // Clear them out to get rid of their resources.
+ for(int i = 0; i < nplots; i++) {
+ _lines_menu[i]->clear();
+ }
+ _line_title_act.clear();
+ _line_color_menu.clear();
+ _line_width_menu.clear();
+ _line_style_menu.clear();
+ _line_marker_menu.clear();
+ _marker_alpha_menu.clear();
+
+ // Now create our own menus
+ for(int i = 0; i < nplots; i++) {
+ ColorMapMenu *colormap = new ColorMapMenu(i, this);
+ connect(colormap, SIGNAL(whichTrigger(int, const int, const QColor&, const QColor&)),
+ this, SLOT(setColorMap(int, const int, const QColor&, const QColor&)));
+ _lines_menu[i]->addMenu(colormap);
+
+ _marker_alpha_menu.push_back(new MarkerAlphaMenu(i, this));
+ connect(_marker_alpha_menu[i], SIGNAL(whichTrigger(int, int)),
+ this, SLOT(setAlpha(int, int)));
+ _lines_menu[i]->addMenu(_marker_alpha_menu[i]);
+ }
+
+ // One scales once when clicked, so no on/off toggling
+ _autoscale_act->setText(tr("Auto Scale"));
+ _autoscale_act->setCheckable(false);
+
+ PopupMenu *colsmenu = new PopupMenu("Num. Columns", this);
+ _menu->addAction(colsmenu);
+ connect(colsmenu, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setNumCols(QString)));
+
+ PopupMenu *rowsmenu = new PopupMenu("Num. Rows", this);
+ _menu->addAction(rowsmenu);
+ connect(rowsmenu, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setNumRows(QString)));
+
+ getPlot()->setIntensityRange(0, zmax);
+
+ Reset();
+
+ connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)),
+ this, SLOT(onPlotPointSelected(const QPointF)));
+}
+
+TimeRasterDisplayForm::~TimeRasterDisplayForm()
+{
+ // Don't worry about deleting Display Plots - they are deleted when
+ // parents are deleted
+}
+
+TimeRasterDisplayPlot*
+TimeRasterDisplayForm::getPlot()
+{
+ return ((TimeRasterDisplayPlot*)_displayPlot);
+}
+
+double
+TimeRasterDisplayForm::numRows()
+{
+ return getPlot()->numRows();
+}
+
+double
+TimeRasterDisplayForm::numCols()
+{
+ return getPlot()->numCols();
+}
+
+int
+TimeRasterDisplayForm::getColorMap(int which)
+{
+ return getPlot()->getIntensityColorMapType(which);
+}
+
+int
+TimeRasterDisplayForm::getAlpha(int which)
+{
+ return getPlot()->getAlpha(which);
+}
+
+double
+TimeRasterDisplayForm::getMinIntensity(int which)
+{
+ return getPlot()->getMinIntensity(which);
+}
+
+double
+TimeRasterDisplayForm::getMaxIntensity(int which)
+{
+ return getPlot()->getMaxIntensity(which);
+}
+
+
+void
+TimeRasterDisplayForm::newData(const QEvent *updateEvent)
+{
+ TimeRasterUpdateEvent *event = (TimeRasterUpdateEvent*)updateEvent;
+ const std::vector<double*> dataPoints = event->getPoints();
+ const uint64_t numDataPoints = event->getNumDataPoints();
+
+ _min_val = 10;
+ _max_val = -10;
+ 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);
+}
+
+void
+TimeRasterDisplayForm::customEvent( QEvent * e)
+{
+ if(e->type() == TimeRasterUpdateEvent::Type()) {
+ newData(e);
+ }
+}
+
+void
+TimeRasterDisplayForm::setNumRows(double rows)
+{
+ getPlot()->setNumRows(rows);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setNumRows(QString rows)
+{
+ getPlot()->setNumRows(rows.toDouble());
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setNumCols(double cols)
+{
+ getPlot()->setNumCols(cols);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setNumCols(QString cols)
+{
+ getPlot()->setNumCols(cols.toDouble());
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setSampleRate(const double rate)
+{
+ getPlot()->setSampleRate(rate);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setSampleRate(const QString &rate)
+{
+ getPlot()->setSampleRate(rate.toDouble());
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setColorMap(int which,
+ const int newType,
+ const QColor lowColor,
+ const QColor highColor)
+{
+ getPlot()->setIntensityColorMapType(which, newType,
+ lowColor, highColor);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setAlpha(int which, int alpha)
+{
+ getPlot()->setAlpha(which, alpha);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::setIntensityRange(const double minIntensity,
+ const double maxIntensity)
+{
+ getPlot()->setIntensityRange(minIntensity, maxIntensity);
+ getPlot()->replot();
+}
+
+void
+TimeRasterDisplayForm::autoScale(bool en)
+{
+ double min_int = _min_val;
+ double max_int = _max_val;
+
+ getPlot()->setIntensityRange(min_int, max_int);
+ getPlot()->replot();
+}
diff --git a/gr-qtgui/lib/timerasterdisplayform.h b/gr-qtgui/lib/timerasterdisplayform.h
new file mode 100644
index 0000000000..f5341f5ecf
--- /dev/null
+++ b/gr-qtgui/lib/timerasterdisplayform.h
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,2013 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 TIMERASTER_DISPLAY_FORM_H
+#define TIMERASTER_DISPLAY_FORM_H
+
+#include <spectrumUpdateEvents.h>
+#include <TimeRasterDisplayPlot.h>
+#include <QtGui/QtGui>
+#include <vector>
+#include <filter/firdes.h>
+
+#include "displayform.h"
+
+class TimeRasterDisplayForm : public DisplayForm
+{
+ Q_OBJECT
+
+ public:
+ TimeRasterDisplayForm(int nplots=1,
+ double samp_rate=1,
+ double rows=1,
+ double cols=1,
+ double zmax=1,
+ QWidget* parent = 0);
+ ~TimeRasterDisplayForm();
+
+ TimeRasterDisplayPlot* getPlot();
+
+ double numRows();
+ double numCols();
+
+ int getColorMap(int which);
+ int getAlpha(int which);
+ double getMinIntensity(int which);
+ double getMaxIntensity(int which);
+
+public slots:
+ void customEvent(QEvent *e);
+
+ void setNumRows(double rows);
+ void setNumCols(double cols);
+
+ void setNumRows(QString rows);
+ void setNumCols(QString cols);
+
+ void setSampleRate(const double samprate);
+ void setSampleRate(const QString &rate);
+
+ void setIntensityRange(const double minIntensity,
+ const double maxIntensity);
+
+ void setColorMap(int which,
+ const int newType,
+ const QColor lowColor=QColor("white"),
+ const QColor highColor=QColor("white"));
+
+ void setAlpha(int which, int alpha);
+
+ void autoScale(bool en=false);
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ double _min_val;
+ double _max_val;
+};
+
+#endif /* TIMERASTER_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/waterfallGlobalData.cc b/gr-qtgui/lib/waterfallGlobalData.cc
index f64ed14f18..8eb175b2c9 100644
--- a/gr-qtgui/lib/waterfallGlobalData.cc
+++ b/gr-qtgui/lib/waterfallGlobalData.cc
@@ -1,3 +1,25 @@
+/* -*- 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_GLOBAL_DATA_CPP
#define WATERFALL_GLOBAL_DATA_CPP
@@ -29,7 +51,7 @@ WaterfallData::WaterfallData(const double minimumFrequency,
setInterval(Qt::ZAxis, QwtInterval(-200, 0.0));
#endif
- Reset();
+ reset();
}
WaterfallData::~WaterfallData()
@@ -37,34 +59,34 @@ WaterfallData::~WaterfallData()
delete[] _spectrumData;
}
-void WaterfallData::Reset()
+void WaterfallData::reset()
{
memset(_spectrumData, 0x0, _fftPoints*_historyLength*sizeof(double));
_numLinesToUpdate = -1;
}
-void WaterfallData::Copy(const WaterfallData* rhs)
+void WaterfallData::copy(const WaterfallData* rhs)
{
#if QWT_VERSION < 0x060000
- if((_fftPoints != rhs->GetNumFFTPoints()) ||
+ if((_fftPoints != rhs->getNumFFTPoints()) ||
(boundingRect() != rhs->boundingRect()) ){
- _fftPoints = rhs->GetNumFFTPoints();
+ _fftPoints = rhs->getNumFFTPoints();
setBoundingRect(rhs->boundingRect());
delete[] _spectrumData;
_spectrumData = new double[_fftPoints * _historyLength];
}
#else
- if(_fftPoints != rhs->GetNumFFTPoints()) {
- _fftPoints = rhs->GetNumFFTPoints();
+ if(_fftPoints != rhs->getNumFFTPoints()) {
+ _fftPoints = rhs->getNumFFTPoints();
delete[] _spectrumData;
_spectrumData = new double[_fftPoints * _historyLength];
}
#endif
- Reset();
- SetSpectrumDataBuffer(rhs->GetSpectrumDataBuffer());
- SetNumLinesToUpdate(rhs->GetNumLinesToUpdate());
+ reset();
+ setSpectrumDataBuffer(rhs->getSpectrumDataBuffer());
+ setNumLinesToUpdate(rhs->getNumLinesToUpdate());
#if QWT_VERSION < 0x060000
setRange(rhs->range());
@@ -75,12 +97,12 @@ void WaterfallData::Copy(const WaterfallData* rhs)
#endif
}
-void WaterfallData::ResizeData(const double startFreq,
+void WaterfallData::resizeData(const double startFreq,
const double stopFreq,
const uint64_t fftPoints)
{
#if QWT_VERSION < 0x060000
- if((fftPoints != GetNumFFTPoints()) ||
+ if((fftPoints != getNumFFTPoints()) ||
(boundingRect().width() != (stopFreq - startFreq)) ||
(boundingRect().left() != startFreq)){
@@ -93,7 +115,7 @@ void WaterfallData::ResizeData(const double startFreq,
}
#else
- if((fftPoints != GetNumFFTPoints()) ||
+ if((fftPoints != getNumFFTPoints()) ||
(interval(Qt::XAxis).width() != (stopFreq - startFreq)) ||
(interval(Qt::XAxis).minValue() != startFreq)){
@@ -105,7 +127,7 @@ void WaterfallData::ResizeData(const double startFreq,
}
#endif
- Reset();
+ reset();
}
QwtRasterData *WaterfallData::copy() const
@@ -120,7 +142,7 @@ QwtRasterData *WaterfallData::copy() const
_fftPoints, _historyLength);
#endif
- returnData->Copy(this);
+ returnData->copy(this);
return returnData;
}
@@ -166,7 +188,7 @@ double WaterfallData::value(double x, double y) const
return returnValue;
}
-uint64_t WaterfallData::GetNumFFTPoints() const
+uint64_t WaterfallData::getNumFFTPoints() const
{
return _fftPoints;
}
@@ -202,27 +224,27 @@ void WaterfallData::addFFTData(const double* fftData,
}
}
-double* WaterfallData::GetSpectrumDataBuffer() const
+double* WaterfallData::getSpectrumDataBuffer() const
{
return _spectrumData;
}
-void WaterfallData::SetSpectrumDataBuffer(const double* newData)
+void WaterfallData::setSpectrumDataBuffer(const double* newData)
{
memcpy(_spectrumData, newData, _fftPoints * _historyLength * sizeof(double));
}
-int WaterfallData::GetNumLinesToUpdate() const
+int WaterfallData::getNumLinesToUpdate() const
{
return _numLinesToUpdate;
}
-void WaterfallData::SetNumLinesToUpdate(const int newNum)
+void WaterfallData::setNumLinesToUpdate(const int newNum)
{
_numLinesToUpdate = newNum;
}
-void WaterfallData::IncrementNumLinesToUpdate()
+void WaterfallData::incrementNumLinesToUpdate()
{
_numLinesToUpdate++;
}
diff --git a/gr-qtgui/lib/waterfallGlobalData.h b/gr-qtgui/lib/waterfallGlobalData.h
index 928c3b1759..8ab9590d0b 100644
--- a/gr-qtgui/lib/waterfallGlobalData.h
+++ b/gr-qtgui/lib/waterfallGlobalData.h
@@ -1,3 +1,25 @@
+/* -*- 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_GLOBAL_DATA_HPP
#define WATERFALL_GLOBAL_DATA_HPP
@@ -15,10 +37,10 @@ public:
WaterfallData(const double, const double, const uint64_t, const unsigned int);
virtual ~WaterfallData();
- virtual void Reset();
- virtual void Copy(const WaterfallData*);
+ virtual void reset();
+ virtual void copy(const WaterfallData*);
- virtual void ResizeData(const double, const double, const uint64_t);
+ virtual void resizeData(const double, const double, const uint64_t);
virtual QwtRasterData *copy() const;
@@ -29,15 +51,15 @@ public:
virtual double value(double x, double y) const;
- virtual uint64_t GetNumFFTPoints()const;
+ virtual uint64_t getNumFFTPoints()const;
virtual void addFFTData(const double*, const uint64_t, const int);
- virtual double* GetSpectrumDataBuffer()const;
- virtual void SetSpectrumDataBuffer(const double*);
+ virtual double* getSpectrumDataBuffer()const;
+ virtual void setSpectrumDataBuffer(const double*);
- virtual int GetNumLinesToUpdate()const;
- virtual void SetNumLinesToUpdate(const int);
- virtual void IncrementNumLinesToUpdate();
+ virtual int getNumLinesToUpdate()const;
+ virtual void setNumLinesToUpdate(const int);
+ virtual void incrementNumLinesToUpdate();
protected:
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..72908b51b9
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -0,0 +1,446 @@
+/* -*- 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>
+#include <qwt_symbol.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,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new waterfall_sink_c_impl(fftsize, wintype,
+ fc, bw, name,
+ nconnections,
+ parent));
+ }
+
+ waterfall_sink_c_impl::waterfall_sink_c_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ QWidget *parent)
+ : gr_sync_block("waterfall_sink_c",
+ gr_make_io_signature(1, nconnections, 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(float));
+ memset(d_magbufs[i], 0, d_fftsize*sizeof(double));
+ }
+
+ buildwindow();
+
+ initialize();
+ }
+
+ waterfall_sink_c_impl::~waterfall_sink_c_impl()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ 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);
+ }
+
+ bool
+ waterfall_sink_c_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ set_fft_window(d_wintype);
+ set_fft_size(d_fftsize);
+ set_frequency_range(d_center_freq, d_bandwidth);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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::clear_data()
+ {
+ d_main_gui->clearData();
+ }
+
+ void
+ waterfall_sink_c_impl::set_fft_size(const int 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_main_gui->setFFTAverage(fftavg);
+ }
+
+ float
+ waterfall_sink_c_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ waterfall_sink_c_impl::set_fft_window(const filter::firdes::win_type win)
+ {
+ d_main_gui->setFFTWindowType(win);
+ }
+
+ filter::firdes::win_type
+ waterfall_sink_c_impl::fft_window()
+ {
+ return d_wintype;
+ }
+
+ 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);
+ }
+
+ void
+ waterfall_sink_c_impl::set_intensity_range(const double min,
+ const double max)
+ {
+ d_main_gui->setIntensityRange(min, max);
+ }
+
+ 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);
+ d_last_time = 0;
+ }
+
+ void
+ waterfall_sink_c_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ waterfall_sink_c_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ waterfall_sink_c_impl::set_color_map(int which, const int color)
+ {
+ d_main_gui->setColorMap(which, color);
+ }
+
+ void
+ waterfall_sink_c_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ waterfall_sink_c_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ waterfall_sink_c_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ waterfall_sink_c_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ int
+ waterfall_sink_c_impl::color_map(int which)
+ {
+ return d_main_gui->getColorMap(which);
+ }
+
+ double
+ waterfall_sink_c_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->markerAlpha(which))/255.0;
+ }
+
+ void
+ waterfall_sink_c_impl::auto_scale()
+ {
+ d_main_gui->autoScale();
+ }
+
+ double
+ waterfall_sink_c_impl::min_intensity(int which)
+ {
+ return d_main_gui->getMinIntensity(which);
+ }
+
+ double
+ waterfall_sink_c_impl::max_intensity(int which)
+ {
+ return d_main_gui->getMaxIntensity(which);
+ }
+
+ void
+ waterfall_sink_c_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ waterfall_sink_c_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ 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..1d709c6c5f
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -0,0 +1,125 @@
+/* -*- 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,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~waterfall_sink_c_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void clear_data();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+ void set_fft_window(const gr::filter::firdes::win_type win);
+ gr::filter::firdes::win_type fft_window();
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_intensity_range(const double min, const double max);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_alpha(int which, double alpha);
+ void set_color_map(int which, const int color);
+
+ std::string title();
+ std::string line_label(int which);
+ double line_alpha(int which);
+ int color_map(int which);
+
+ void set_size(int width, int height);
+
+ void auto_scale();
+ double min_intensity(int which);
+ double max_intensity(int which);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+
+ 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..bdf1159e5a
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -0,0 +1,447 @@
+/* -*- 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,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new waterfall_sink_f_impl(fftsize, wintype,
+ fc, bw, name,
+ nconnections,
+ parent));
+ }
+
+ waterfall_sink_f_impl::waterfall_sink_f_impl(int fftsize, int wintype,
+ double fc, double bw,
+ const std::string &name,
+ int nconnections,
+ 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(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();
+ }
+
+ waterfall_sink_f_impl::~waterfall_sink_f_impl()
+ {
+ if(!d_main_gui->isClosed())
+ d_main_gui->close();
+
+ 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);
+ }
+
+ bool
+ waterfall_sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ 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);
+ set_fft_window(d_wintype);
+ set_fft_size(d_fftsize);
+ set_frequency_range(d_center_freq, d_bandwidth);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ 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::clear_data()
+ {
+ d_main_gui->clearData();
+ }
+
+ void
+ waterfall_sink_f_impl::set_fft_size(const int 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_main_gui->setFFTAverage(fftavg);
+ }
+
+ float
+ waterfall_sink_f_impl::fft_average() const
+ {
+ return d_fftavg;
+ }
+
+ void
+ waterfall_sink_f_impl::set_fft_window(const filter::firdes::win_type win)
+ {
+ d_main_gui->setFFTWindowType(win);
+ }
+
+ filter::firdes::win_type
+ waterfall_sink_f_impl::fft_window()
+ {
+ return d_wintype;
+ }
+
+ 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);
+ }
+
+ void
+ waterfall_sink_f_impl::set_intensity_range(const double min,
+ const double max)
+ {
+ d_main_gui->setIntensityRange(min, max);
+ }
+
+ 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);
+ d_last_time = 0;
+ }
+
+ void
+ waterfall_sink_f_impl::set_title(const std::string &title)
+ {
+ d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ waterfall_sink_f_impl::set_line_label(int which, const std::string &label)
+ {
+ d_main_gui->setLineLabel(which, label.c_str());
+ }
+
+ void
+ waterfall_sink_f_impl::set_color_map(int which, const int color)
+ {
+ d_main_gui->setColorMap(which, color);
+ }
+
+ void
+ waterfall_sink_f_impl::set_line_alpha(int which, double alpha)
+ {
+ d_main_gui->setAlpha(which, (int)(255.0*alpha));
+ }
+
+ void
+ waterfall_sink_f_impl::set_size(int width, int height)
+ {
+ d_main_gui->resize(QSize(width, height));
+ }
+
+ std::string
+ waterfall_sink_f_impl::title()
+ {
+ return d_main_gui->title().toStdString();
+ }
+
+ std::string
+ waterfall_sink_f_impl::line_label(int which)
+ {
+ return d_main_gui->lineLabel(which).toStdString();
+ }
+
+ int
+ waterfall_sink_f_impl::color_map(int which)
+ {
+ return d_main_gui->getColorMap(which);
+ }
+
+ double
+ waterfall_sink_f_impl::line_alpha(int which)
+ {
+ return (double)(d_main_gui->getAlpha(which))/255.0;
+ }
+
+ void
+ waterfall_sink_f_impl::auto_scale()
+ {
+ d_main_gui->autoScale();
+ }
+
+ double
+ waterfall_sink_f_impl::min_intensity(int which)
+ {
+ return d_main_gui->getMinIntensity(which);
+ }
+
+ double
+ waterfall_sink_f_impl::max_intensity(int which)
+ {
+ return d_main_gui->getMaxIntensity(which);
+ }
+
+ void
+ waterfall_sink_f_impl::enable_menu(bool en)
+ {
+ d_main_gui->enableMenu(en);
+ }
+
+ void
+ waterfall_sink_f_impl::enable_grid(bool en)
+ {
+ d_main_gui->setGrid(en);
+ }
+
+ 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..6185a25397
--- /dev/null
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -0,0 +1,126 @@
+/* -*- 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,
+ int nconnections,
+ QWidget *parent=NULL);
+ ~waterfall_sink_f_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+ PyObject* pyqwidget();
+
+ void clear_data();
+
+ void set_fft_size(const int fftsize);
+ int fft_size() const;
+ void set_fft_average(const float fftavg);
+ float fft_average() const;
+ void set_fft_window(const gr::filter::firdes::win_type win);
+ gr::filter::firdes::win_type fft_window();
+
+ void set_frequency_range(const double centerfreq, const double bandwidth);
+ void set_intensity_range(const double min, const double max);
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_line_label(int which, const std::string &label);
+ void set_line_alpha(int which, double alpha);
+ void set_color_map(int which, const int color);
+
+ std::string title();
+ std::string line_label(int which);
+ double line_alpha(int which);
+ int color_map(int which);
+
+ void set_size(int width, int height);
+
+ void auto_scale();
+ double min_intensity(int which);
+ double max_intensity(int which);
+
+ void enable_menu(bool en);
+ void enable_grid(bool en);
+
+ 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..e42e63fbc4
--- /dev/null
+++ b/gr-qtgui/lib/waterfalldisplayform.cc
@@ -0,0 +1,268 @@
+/* -*- 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);
+
+ _center_freq = 0;
+ _samp_rate = 0;
+
+ _numRealDataPoints = 1024;
+ _fftsize = 1024;
+ _fftavg = 1.0;
+
+ _min_val = 1000;
+ _max_val = -1000;
+
+ // We don't use the normal menus that are part of the displayform.
+ // Clear them out to get rid of their resources.
+ for(int i = 0; i < nplots; i++) {
+ _lines_menu[i]->clear();
+ }
+ _line_title_act.clear();
+ _line_color_menu.clear();
+ _line_width_menu.clear();
+ _line_style_menu.clear();
+ _line_marker_menu.clear();
+ _marker_alpha_menu.clear();
+
+ // Now create our own menus
+ for(int i = 0; i < nplots; i++) {
+ ColorMapMenu *colormap = new ColorMapMenu(i, this);
+ connect(colormap, SIGNAL(whichTrigger(int, const int, const QColor&, const QColor&)),
+ this, SLOT(setColorMap(int, const int, const QColor&, const QColor&)));
+ _lines_menu[i]->addMenu(colormap);
+
+ _marker_alpha_menu.push_back(new MarkerAlphaMenu(i, this));
+ connect(_marker_alpha_menu[i], SIGNAL(whichTrigger(int, int)),
+ this, SLOT(setAlpha(int, int)));
+ _lines_menu[i]->addMenu(_marker_alpha_menu[i]);
+ }
+
+ // One scales once when clicked, so no on/off toggling
+ _autoscale_act->setText(tr("Auto Scale"));
+ _autoscale_act->setCheckable(false);
+
+ 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)));
+}
+
+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,
+ _time_per_slice, 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;
+}
+
+int
+WaterfallDisplayForm::getColorMap(int which)
+{
+ return getPlot()->getIntensityColorMapType(which);
+}
+
+int
+WaterfallDisplayForm::getAlpha(int which)
+{
+ return getPlot()->getAlpha(which);
+}
+
+double
+WaterfallDisplayForm::getMinIntensity(int which)
+{
+ return getPlot()->getMinIntensity(which);
+}
+
+double
+WaterfallDisplayForm::getMaxIntensity(int which)
+{
+ return getPlot()->getMaxIntensity(which);
+}
+
+void
+WaterfallDisplayForm::setSampleRate(const QString &samprate)
+{
+ setFrequencyRange(_center_freq, samprate.toDouble());
+}
+
+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 centerfreq,
+ const double bandwidth)
+{
+ std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
+ double units10 = floor(log10(bandwidth));
+ 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);
+
+ _center_freq = centerfreq;
+ _samp_rate = bandwidth;
+ _time_per_slice = (1.0/bandwidth)*_fftsize;
+
+ getPlot()->setFrequencyRange(centerfreq, bandwidth,
+ units, strunits[iunit]);
+ getPlot()->replot();
+}
+
+void
+WaterfallDisplayForm::setColorMap(int which,
+ const int newType,
+ const QColor lowColor,
+ const QColor highColor)
+{
+ getPlot()->setIntensityColorMapType(which, newType,
+ lowColor, highColor);
+ getPlot()->replot();
+}
+
+void
+WaterfallDisplayForm::setAlpha(int which, int alpha)
+{
+ getPlot()->setAlpha(which, alpha);
+ getPlot()->replot();
+}
+
+void
+WaterfallDisplayForm::setIntensityRange(const double minIntensity,
+ const double maxIntensity)
+{
+ getPlot()->setIntensityRange(minIntensity, maxIntensity);
+ getPlot()->replot();
+}
+
+void
+WaterfallDisplayForm::autoScale(bool en)
+{
+ double min_int = _min_val - 5;
+ double max_int = _max_val + 10;
+
+ getPlot()->setIntensityRange(min_int, max_int);
+ getPlot()->replot();
+}
+
+void
+WaterfallDisplayForm::clearData()
+{
+ getPlot()->clearData();
+}
diff --git a/gr-qtgui/lib/waterfalldisplayform.h b/gr-qtgui/lib/waterfalldisplayform.h
new file mode 100644
index 0000000000..959f2fea68
--- /dev/null
+++ b/gr-qtgui/lib/waterfalldisplayform.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 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;
+
+ int getColorMap(int which);
+ int getAlpha(int which);
+ double getMinIntensity(int which);
+ double getMaxIntensity(int which);
+
+ void clearData();
+
+public slots:
+ void customEvent(QEvent *e);
+
+ void setSampleRate(const QString &samprate);
+ void setFFTSize(const int);
+ void setFFTAverage(const float);
+ void setFFTWindowType(const gr::filter::firdes::win_type);
+
+ void setFrequencyRange(const double centerfreq,
+ const double bandwidth);
+
+ void setIntensityRange(const double minIntensity,
+ const double maxIntensity);
+
+ void setAlpha(int which, int alpha);
+
+ void setColorMap(int which,
+ const int newType,
+ const QColor lowColor=QColor("white"),
+ const QColor highColor=QColor("white"));
+
+ void autoScale(bool en=false);
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ uint64_t _numRealDataPoints;
+ QIntValidator* _intValidator;
+
+ double _samp_rate, _center_freq;
+ double _time_per_slice;
+ 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..0761ed3be9 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,52 @@ 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.
+ # We use '5' in place of filter.firdes.WIN_BLACKMAN_hARRIS so we
+ # don't have to worry about importing filter just for this one
+ # constant.
+ def test01(self):
+ self.qtsnk = qtgui.sink_c(1024, 5,
+ 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, 5,
+ 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, 5,
+ 0, 1, "Test", 1)
+
+ def test06(self):
+ self.qtsnk = qtgui.freq_sink_f(1024, 5,
+ 0, 1, "Test", 1)
+
+ def test07(self):
+ self.qtsnk = qtgui.waterfall_sink_c(1024, 5,
+ 0, 1, "Test")
+
+ def test08(self):
+ self.qtsnk = qtgui.waterfall_sink_f(1024, 5,
+ 0, 1, "Test")
+
+ def test09(self):
+ self.qtsnk = qtgui.const_sink_c(1024, "Test", 1)
+
+ def test10(self):
+ self.qtsnk = qtgui.time_raster_sink_b(1024, 100, 100.5,
+ [], [], "Test", 1)
+
+ def test11(self):
+ self.qtsnk = qtgui.time_raster_sink_f(1024, 100, 100.5,
+ [], [], "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 a1f70240c3..d17130597e 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
#
@@ -25,6 +25,8 @@ include(GrSwig)
set(GR_SWIG_INCLUDE_DIRS
${GR_QTGUI_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${GRUEL_INCLUDE_DIRS}
${QWT_INCLUDE_DIRS}
@@ -47,10 +49,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..4e1d1969e2 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,51 @@
* Boston, MA 02110-1301, USA.
*/
+#define QTGUI_API
+#define FILTER_API
+
%include "gnuradio.i"
//load generated python docstrings
%include "qtgui_swig_doc.i"
+// So we understand the firdes window types
+%include "filter/firdes.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/sink_c.h"
+#include "qtgui/sink_f.h"
+#include "qtgui/time_sink_c.h"
+#include "qtgui/time_sink_f.h"
+#include "qtgui/time_raster_sink_b.h"
+#include "qtgui/time_raster_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/time_raster_sink_b.h"
+%include "qtgui/time_raster_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, time_raster_sink_b);
+GR_SWIG_BLOCK_MAGIC2(qtgui, time_raster_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);
-};