summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgr-qtgui/examples/pyqt_time_raster_b.py85
-rwxr-xr-xgr-qtgui/examples/pyqt_time_raster_f.py85
-rw-r--r--gr-qtgui/grc/qtgui_time_raster_x.xml106
-rw-r--r--gr-qtgui/include/qtgui/CMakeLists.txt2
-rw-r--r--gr-qtgui/include/qtgui/time_raster_sink_b.h100
-rw-r--r--gr-qtgui/include/qtgui/time_raster_sink_f.h97
-rw-r--r--gr-qtgui/lib/CMakeLists.txt12
-rw-r--r--gr-qtgui/lib/TimeRasterDisplayPlot.cc503
-rw-r--r--gr-qtgui/lib/TimeRasterDisplayPlot.h98
-rw-r--r--gr-qtgui/lib/plot_raster.cc334
-rw-r--r--gr-qtgui/lib/plot_raster.h90
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.cc44
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.h27
-rw-r--r--gr-qtgui/lib/timeRasterGlobalData.cc252
-rw-r--r--gr-qtgui/lib/timeRasterGlobalData.h81
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.cc332
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.h104
-rw-r--r--gr-qtgui/lib/time_raster_sink_c_impl.cc219
-rw-r--r--gr-qtgui/lib/time_raster_sink_c_impl.h87
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.cc326
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.h103
-rw-r--r--gr-qtgui/lib/timerasterdisplayform.cc199
-rw-r--r--gr-qtgui/lib/timerasterdisplayform.h81
-rw-r--r--gr-qtgui/swig/qtgui_swig.i6
24 files changed, 3373 insertions, 0 deletions
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..b9db6e1e8e
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_time_raster_b.py
@@ -0,0 +1,85 @@
+#!/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 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 = gr.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..0b343e6a6e
--- /dev/null
+++ b/gr-qtgui/examples/pyqt_time_raster_f.py
@@ -0,0 +1,85 @@
+#!/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 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 = gr.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/grc/qtgui_time_raster_x.xml b/gr-qtgui/grc/qtgui_time_raster_x.xml
new file mode 100644
index 0000000000..e50810f29a
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_time_raster_x.xml
@@ -0,0 +1,106 @@
+<?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)_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($t)</callback>
+ <callback>set_title($which, $title)</callback>
+ <callback>set_color($which, $color)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>complex</value>
+ <type>enum</type>
+ <option><name>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>1</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 Rate</name>
+ <key>rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$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/qtgui/CMakeLists.txt b/gr-qtgui/include/qtgui/CMakeLists.txt
index d0d3d13fb5..f3ef6808e8 100644
--- a/gr-qtgui/include/qtgui/CMakeLists.txt
+++ b/gr-qtgui/include/qtgui/CMakeLists.txt
@@ -24,6 +24,8 @@ install(FILES
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
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..6d76c00dd8
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_raster_sink_b.h
@@ -0,0 +1,100 @@
+/* -*- 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,
+ 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(const std::string &lable) = 0;
+ virtual void set_line_color(const std::string &color) = 0;
+ virtual void set_line_width(int width) = 0;
+ virtual void set_line_style(Qt::PenStyle style) = 0;
+ virtual void set_line_marker(QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void set_num_rows(double rows) = 0;
+ virtual void set_num_cols(double 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;
+
+ 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..23a8912869
--- /dev/null
+++ b/gr-qtgui/include/qtgui/time_raster_sink_f.h
@@ -0,0 +1,97 @@
+/* -*- 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,
+ 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(const std::string &lable) = 0;
+ virtual void set_line_color(const std::string &color) = 0;
+ virtual void set_line_width(int width) = 0;
+ virtual void set_line_style(Qt::PenStyle style) = 0;
+ virtual void set_line_marker(QwtSymbol::Style marker) = 0;
+
+ virtual void set_size(int width, int height) = 0;
+
+ virtual void set_num_rows(double rows) = 0;
+ virtual void set_num_cols(double 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;
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_TIME_RASTER_SINK_F_H */
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index 9f1b1d69bb..d7a517c013 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -24,6 +24,7 @@ set(qtgui_moc_hdrs
spectrumdisplayform.h
displayform.h
timedisplayform.h
+ timerasterdisplayform.h
freqdisplayform.h
constellationdisplayform.h
waterfalldisplayform.h
@@ -31,6 +32,7 @@ set(qtgui_moc_hdrs
DisplayPlot.h
FrequencyDisplayPlot.h
TimeDomainDisplayPlot.h
+ TimeRasterDisplayPlot.h
WaterfallDisplayPlot.h
ConstellationDisplayPlot.h
)
@@ -50,22 +52,28 @@ set(qtgui_srcs
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
+ 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
@@ -125,13 +133,17 @@ 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
diff --git a/gr-qtgui/lib/TimeRasterDisplayPlot.cc b/gr-qtgui/lib/TimeRasterDisplayPlot.cc
new file mode 100644
index 0000000000..84ec31f6ef
--- /dev/null
+++ b/gr-qtgui/lib/TimeRasterDisplayPlot.cc
@@ -0,0 +1,503 @@
+/* -*- 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;
+};
+
+
+/***********************************************************************
+ * Widget to provide mouse pointer coordinate text
+ **********************************************************************/
+class TimeRasterZoomer: public QwtPlotZoomer, public TimeScaleData
+{
+public:
+ TimeRasterZoomer(QwtPlotCanvas* canvas, double rows, double cols)
+ : QwtPlotZoomer(canvas), 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 s, %2")
+ .arg(x, 0, 'f', 2)
+ .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());
+
+ double sec_per_samp = 1.0/d_samp_rate;
+ QwtYScaleDraw* yScale = (QwtYScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
+ yScale->setRows(d_rows);
+
+ QwtXScaleDraw* xScale = (QwtXScaleDraw*)axisScaleDraw(QwtPlot::xBottom);
+ xScale->setSecondsPerLine(sec_per_samp);
+
+ 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);
+#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();
+ }
+
+ setAxisScale(QwtPlot::xBottom, 0, d_rows);
+ setAxisScale(QwtPlot::yLeft, 0, d_cols);
+
+ double sec_per_samp = 1.0/d_samp_rate;
+ QwtYScaleDraw* yScale = (QwtYScaleDraw*)axisScaleDraw(QwtPlot::yLeft);
+ yScale->setRows(d_rows);
+
+ QwtXScaleDraw* xScale = (QwtXScaleDraw*)axisScaleDraw(QwtPlot::xBottom);
+ xScale->setSecondsPerLine(sec_per_samp);
+
+ // Load up the new base zoom settings
+ if(_zoomer) {
+ ((TimeRasterZoomer*)_zoomer)->setColumns(d_cols);
+ ((TimeRasterZoomer*)_zoomer)->setRows(d_rows);
+ ((TimeRasterZoomer*)_zoomer)->setSecondsPerLine(sec_per_samp);
+ //((TimeRasterZoomer*)_zoomer)-sSetUnitType(strunits);
+
+ 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);
+}
+
+double
+TimeRasterDisplayPlot::numRows() const
+{
+ return d_rows;
+}
+
+double
+TimeRasterDisplayPlot::numCols() const
+{
+ return d_cols;
+}
+
+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();
+ }
+}
+
+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..3e0ac1cfdb
--- /dev/null
+++ b/gr-qtgui/lib/TimeRasterDisplayPlot.h
@@ -0,0 +1,98 @@
+/* -*- 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);
+
+ double numRows() const;
+ double numCols() const;
+
+ 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;
+
+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/plot_raster.cc b/gr-qtgui/lib/plot_raster.cc
new file mode 100644
index 0000000000..688ce6597e
--- /dev/null
+++ b/gr-qtgui/lib/plot_raster.cc
@@ -0,0 +1,334 @@
+/* -*- 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 <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;
+}
+
+/*!
+ \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..40763e4b00
--- /dev/null
+++ b/gr-qtgui/lib/plot_raster.h
@@ -0,0 +1,90 @@
+/* -*- 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 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;
+#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/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc
index 92dd807147..5e03de685b 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.cc
+++ b/gr-qtgui/lib/spectrumUpdateEvents.cc
@@ -373,4 +373,48 @@ 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 e663980bc6..78cc275178 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.h
+++ b/gr-qtgui/lib/spectrumUpdateEvents.h
@@ -212,4 +212,31 @@ private:
};
+/********************************************************************/
+
+
+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/timeRasterGlobalData.cc b/gr-qtgui/lib/timeRasterGlobalData.cc
new file mode 100644
index 0000000000..27cb41d403
--- /dev/null
+++ b/gr-qtgui/lib/timeRasterGlobalData.cc
@@ -0,0 +1,252 @@
+/* -*- 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;
+ memset(d_data, 0x0, d_totalitems*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;
+ _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();
+ setDataBuffer(rhs->getDataBuffer());
+
+#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 {
+ memmove(d_data, &d_data[cols], d_totalitems*sizeof(double));
+ memcpy(&d_data[d_nitems], data, cols*sizeof(double));
+ }
+ }
+}
+
+double*
+TimeRasterData::getDataBuffer() const
+{
+ return d_data;
+}
+
+void
+TimeRasterData::setDataBuffer(const double* newData)
+{
+ memcpy(d_data, newData, 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..7b450c033b
--- /dev/null
+++ b/gr-qtgui/lib/timeRasterGlobalData.h
@@ -0,0 +1,81 @@
+/* -*- 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);
+
+ virtual double* getDataBuffer()const;
+ virtual void setDataBuffer(const double*);
+
+ 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..46d60ba3f5
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.cc
@@ -0,0 +1,332 @@
+/* -*- 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()
+ {
+ 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);
+ d_last_time = 0;
+ }
+
+ 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);
+ }
+
+ 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(const std::string &label)
+ {
+ d_main_gui->setLineLabel(0, label.c_str());
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_color(const std::string &color)
+ {
+ d_main_gui->setLineColor(0, color.c_str());
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_width(int width)
+ {
+ d_main_gui->setLineWidth(0, width);
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_style(Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(0, style);
+ }
+
+ void
+ time_raster_sink_b_impl::set_line_marker(QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(0, marker);
+ }
+
+ 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_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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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..248eb8dd67
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.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 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(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);
+
+ void set_num_rows(double rows);
+ void set_num_cols(double 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);
+
+ 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..ca739961fe
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_c_impl.cc
@@ -0,0 +1,219 @@
+/* -*- 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 "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()
+ {
+ 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..3e2a732940
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_c_impl.h
@@ -0,0 +1,87 @@
+/* -*- 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_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..be1e66da12
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.cc
@@ -0,0 +1,326 @@
+/* -*- 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()
+ {
+ 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);
+ d_last_time = 0;
+ }
+
+ 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);
+ }
+
+ 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(const std::string &label)
+ {
+ d_main_gui->setLineLabel(0, label.c_str());
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_color(const std::string &color)
+ {
+ d_main_gui->setLineColor(0, color.c_str());
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_width(int width)
+ {
+ d_main_gui->setLineWidth(0, width);
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_style(Qt::PenStyle style)
+ {
+ d_main_gui->setLineStyle(0, style);
+ }
+
+ void
+ time_raster_sink_f_impl::set_line_marker(QwtSymbol::Style marker)
+ {
+ d_main_gui->setLineMarker(0, marker);
+ }
+
+ 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_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);
+ }
+
+ 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);
+ }
+
+ 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];
+
+ 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 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);
+ }
+
+ 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..c14a5c1147
--- /dev/null
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.h
@@ -0,0 +1,103 @@
+/* -*- 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(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);
+
+ void set_num_rows(double rows);
+ void set_num_cols(double 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);
+
+ 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/timerasterdisplayform.cc b/gr-qtgui/lib/timerasterdisplayform.cc
new file mode 100644
index 0000000000..b7f1dba2f6
--- /dev/null
+++ b/gr-qtgui/lib/timerasterdisplayform.cc
@@ -0,0 +1,199 @@
+/* -*- 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)
+{
+ _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]);
+ }
+
+ QAction *autoscale_act = new QAction("Auto Scale", this);
+ autoscale_act->setStatusTip(tr("Autoscale intensity range"));
+ connect(autoscale_act, SIGNAL(triggered()), this, SLOT(autoScale()));
+ _menu->addAction(autoscale_act);
+
+ 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();
+}
+
+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);
+}
+
+void
+TimeRasterDisplayForm::setNumRows(QString rows)
+{
+ getPlot()->setNumRows(rows.toDouble());
+}
+
+void
+TimeRasterDisplayForm::setNumCols(double cols)
+{
+ getPlot()->setNumCols(cols);
+}
+
+void
+TimeRasterDisplayForm::setNumCols(QString cols)
+{
+ getPlot()->setNumCols(cols.toDouble());
+}
+
+void
+TimeRasterDisplayForm::setColorMap(int which,
+ const int newType,
+ const QColor lowColor,
+ const QColor highColor)
+{
+ getPlot()->setIntensityColorMapType(which, newType,
+ lowColor, highColor);
+}
+
+void
+TimeRasterDisplayForm::setAlpha(int which, int alpha)
+{
+ getPlot()->setAlpha(which, alpha);
+}
+
+void
+TimeRasterDisplayForm::setIntensityRange(const double minIntensity,
+ const double maxIntensity)
+{
+ getPlot()->setIntensityRange(minIntensity, maxIntensity);
+}
+
+void
+TimeRasterDisplayForm::autoScale()
+{
+ double min_int = _min_val;
+ double max_int = _max_val;
+
+ getPlot()->setIntensityRange(min_int, max_int);
+}
diff --git a/gr-qtgui/lib/timerasterdisplayform.h b/gr-qtgui/lib/timerasterdisplayform.h
new file mode 100644
index 0000000000..e136f5faf8
--- /dev/null
+++ b/gr-qtgui/lib/timerasterdisplayform.h
@@ -0,0 +1,81 @@
+/* -*- 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();
+
+public slots:
+ void customEvent(QEvent *e);
+
+ void setNumRows(double rows);
+ void setNumCols(double cols);
+
+ void setNumRows(QString rows);
+ void setNumCols(QString cols);
+
+ void setIntensityRange(const double minIntensity,
+ const double maxIntensity);
+
+ void setColorMap(int which,
+ const int newType,
+ const QColor lowColor,
+ const QColor highColor);
+
+ void setAlpha(int which, int alpha);
+
+ void autoScale();
+
+private slots:
+ void newData(const QEvent *updateEvent);
+
+private:
+ double _min_val;
+ double _max_val;
+};
+
+#endif /* TIMERASTER_DISPLAY_FORM_H */
diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i
index 20675503e2..4e1d1969e2 100644
--- a/gr-qtgui/swig/qtgui_swig.i
+++ b/gr-qtgui/swig/qtgui_swig.i
@@ -36,6 +36,8 @@
#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"
@@ -47,6 +49,8 @@
%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"
@@ -57,6 +61,8 @@ 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);