summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-qtgui/src/lib/ConstellationDisplayPlot.cc167
-rw-r--r--gr-qtgui/src/lib/ConstellationDisplayPlot.h49
-rw-r--r--gr-qtgui/src/lib/Makefile.am3
-rw-r--r--gr-qtgui/src/lib/spectrumdisplayform.cc34
-rw-r--r--gr-qtgui/src/lib/spectrumdisplayform.h2
-rw-r--r--gr-qtgui/src/lib/spectrumdisplayform.ui61
-rwxr-xr-xgr-qtgui/src/python/qt_digital.py40
7 files changed, 324 insertions, 32 deletions
diff --git a/gr-qtgui/src/lib/ConstellationDisplayPlot.cc b/gr-qtgui/src/lib/ConstellationDisplayPlot.cc
new file mode 100644
index 000000000..c422c8f52
--- /dev/null
+++ b/gr-qtgui/src/lib/ConstellationDisplayPlot.cc
@@ -0,0 +1,167 @@
+#ifndef CONSTELLATION_DISPLAY_PLOT_C
+#define CONSTELLATION_DISPLAY_PLOT_C
+
+#include <ConstellationDisplayPlot.h>
+
+#include <qwt_scale_draw.h>
+#include <qwt_legend.h>
+
+
+class ConstellationDisplayZoomer: public QwtPlotZoomer
+{
+public:
+ ConstellationDisplayZoomer(QwtPlotCanvas* canvas):QwtPlotZoomer(canvas)
+ {
+ setTrackerMode(QwtPicker::AlwaysOn);
+ }
+
+ virtual ~ConstellationDisplayZoomer(){
+
+ }
+
+ virtual void updateTrackerText(){
+ updateDisplay();
+ }
+
+protected:
+ virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ {
+ QwtText t(QString("Sample %1, %2 V").arg(p.x(), 0, 'f', 0).arg(p.y(), 0, 'f', 4));
+
+ return t;
+ }
+};
+
+ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent):QwtPlot(parent){
+ timespec_reset(&_lastReplot);
+
+ resize(parent->width(), parent->height());
+
+ _displayIntervalTime = (1.0/10.0); // 1/10 of a second between updates
+
+ _numPoints = 1024;
+ _realDataPoints = new double[_numPoints];
+ _imagDataPoints = new double[_numPoints];
+
+ // Disable polygon clipping
+ QwtPainter::setDeviceClipping(false);
+
+ // We don't need the cache here
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
+
+ QPalette palette;
+ palette.setColor(canvas()->backgroundRole(), QColor("white"));
+ canvas()->setPalette(palette);
+
+ setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
+ setAxisScale(QwtPlot::xBottom, -1.0, 1.0);
+ setAxisTitle(QwtPlot::xBottom, "In-phase");
+
+ setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
+ setAxisScale(QwtPlot::yLeft, -1.0, 1.0);
+ setAxisTitle(QwtPlot::yLeft, "Quadrature");
+
+ // Automatically deleted when parent is deleted
+ _plot_curve = new QwtPlotCurve("Constellation Points");
+ _plot_curve->attach(this);
+ _plot_curve->setPen(QPen(Qt::blue, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ _plot_curve->setStyle(QwtPlotCurve::Dots);
+ _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints);
+
+ memset(_realDataPoints, 0x0, _numPoints*sizeof(double));
+ memset(_imagDataPoints, 0x0, _numPoints*sizeof(double));
+
+ replot();
+
+ _zoomer = new ConstellationDisplayZoomer(canvas());
+#if QT_VERSION < 0x040000
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+#else
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+#endif
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
+ Qt::RightButton);
+
+ _panner = new QwtPlotPanner(canvas());
+ _panner->setAxisEnabled(QwtPlot::yRight, false);
+ _panner->setMouseButton(Qt::MidButton);
+
+ // Avoid jumping when labels with more/less digits
+ // appear/disappear when scrolling vertically
+
+ const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
+ QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
+ sd->setMinimumExtent( fm.width("100.00") );
+
+ const QColor c(Qt::darkRed);
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
+
+ QwtLegend* legendDisplay = new QwtLegend(this);
+ legendDisplay->setItemMode(QwtLegend::CheckableItem);
+ insertLegend(legendDisplay);
+
+ connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
+}
+
+ConstellationDisplayPlot::~ConstellationDisplayPlot(){
+ delete[] _realDataPoints;
+ delete[] _imagDataPoints;
+
+ // _fft_plot_curves deleted when parent deleted
+ // _zoomer and _panner deleted when parent deleted
+}
+
+
+
+void ConstellationDisplayPlot::replot(){
+
+ const timespec startTime = get_highres_clock();
+
+ QwtPlot::replot();
+
+ double differenceTime = (diff_timespec(get_highres_clock(), startTime));
+
+ differenceTime *= 99.0;
+ // Require at least a 10% duty cycle
+ if(differenceTime > (1.0/10.0)){
+ _displayIntervalTime = differenceTime;
+ }
+}
+
+void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, const double* imagDataPoints, const int64_t numDataPoints){
+ if(numDataPoints > 0){
+
+ if(numDataPoints != _numPoints){
+ _numPoints = numDataPoints;
+
+ delete[] _realDataPoints;
+ delete[] _imagDataPoints;
+ _realDataPoints = new double[_numPoints];
+ _imagDataPoints = new double[_numPoints];
+
+ _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints);
+ }
+ memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double));
+ memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double));
+
+ }
+
+ // Allow at least a 50% duty cycle
+ if(diff_timespec(get_highres_clock(), _lastReplot) > _displayIntervalTime){
+ // Only replot the screen if it is visible
+ if(isVisible()){
+ replot();
+ }
+ _lastReplot = get_highres_clock();
+ }
+}
+
+void ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on){
+ plotItem->setVisible(!on);
+}
+
+#endif /* CONSTELLATION_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/src/lib/ConstellationDisplayPlot.h b/gr-qtgui/src/lib/ConstellationDisplayPlot.h
new file mode 100644
index 000000000..d7604ea84
--- /dev/null
+++ b/gr-qtgui/src/lib/ConstellationDisplayPlot.h
@@ -0,0 +1,49 @@
+#ifndef CONSTELLATION_DISPLAY_PLOT_HPP
+#define CONSTELLATION_DISPLAY_PLOT_HPP
+
+#include <qwt_plot.h>
+#include <qwt_painter.h>
+#include <qwt_plot_canvas.h>
+#include <qwt_plot_curve.h>
+#include <qwt_scale_engine.h>
+#include <qwt_scale_widget.h>
+#include <qwt_plot_zoomer.h>
+#include <qwt_plot_panner.h>
+#include <qwt_plot_marker.h>
+#include <highResTimeFunctions.h>
+#include <qwt_symbol.h>
+
+class ConstellationDisplayPlot:public QwtPlot{
+ Q_OBJECT
+
+public:
+ ConstellationDisplayPlot(QWidget*);
+ virtual ~ConstellationDisplayPlot();
+
+ void PlotNewData(const double* realDataPoints, const double* imagDataPoints,
+ const int64_t numDataPoints);
+
+ virtual void replot();
+
+protected slots:
+ void LegendEntryChecked(QwtPlotItem *plotItem, bool on);
+
+protected:
+
+private:
+ QwtPlotCurve* _plot_curve;
+
+ QwtPlotPanner* _panner;
+ QwtPlotZoomer* _zoomer;
+
+ double* _realDataPoints;
+ double* _imagDataPoints;
+
+ timespec _lastReplot;
+
+ int64_t _numPoints;
+
+ double _displayIntervalTime;
+};
+
+#endif /* CONSTELLATION_DISPLAY_PLOT_HPP */
diff --git a/gr-qtgui/src/lib/Makefile.am b/gr-qtgui/src/lib/Makefile.am
index 41281e687..034eff053 100644
--- a/gr-qtgui/src/lib/Makefile.am
+++ b/gr-qtgui/src/lib/Makefile.am
@@ -54,6 +54,7 @@ QMAKE_SOURCES = \
TimeDomainDisplayPlot_moc.cc \
WaterfallDisplayPlot_moc.cc \
Waterfall3DDisplayPlot_moc.cc \
+ ConstellationDisplayPlot_moc.cc \
spectrumdisplayform_ui.h
endif
@@ -81,6 +82,7 @@ libqtgui_la_SOURCES = \
WaterfallDisplayPlot.cc \
Waterfall3DDisplayPlot.cc \
waterfallGlobalData.cc \
+ ConstellationDisplayPlot.cc \
spectrumdisplayform.cc \
SpectrumGUIClass.cc \
spectrumUpdateEvents.cc \
@@ -100,6 +102,7 @@ grinclude_HEADERS = \
WaterfallDisplayPlot.h \
Waterfall3DDisplayPlot.h \
waterfallGlobalData.h \
+ ConstellationDisplayPlot.h \
highResTimeFunctions.h \
plot_waterfall.h \
spectrumdisplayform.h \
diff --git a/gr-qtgui/src/lib/spectrumdisplayform.cc b/gr-qtgui/src/lib/spectrumdisplayform.cc
index e0b43ae30..a898015be 100644
--- a/gr-qtgui/src/lib/spectrumdisplayform.cc
+++ b/gr-qtgui/src/lib/spectrumdisplayform.cc
@@ -15,6 +15,7 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QDialog(parent){
_waterfallDisplayPlot = new WaterfallDisplayPlot(Tab2PlotDisplayFrame);
_waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
_timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
+ _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame);
_numRealDataPoints = 1024;
_realFFTDataPoints = new double[_numRealDataPoints];
_averagedValues = new double[_numRealDataPoints];
@@ -42,8 +43,10 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QDialog(parent){
_noiseFloorAmplitude = -HUGE_VAL;
- connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
- connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
+ connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)),
+ _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
+ connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)),
+ _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
_frequencyDisplayPlot->SetLowerIntensityLevel(-200);
_frequencyDisplayPlot->SetUpperIntensityLevel(-200);
@@ -72,7 +75,9 @@ SpectrumDisplayForm::~SpectrumDisplayForm(){
delete _historyVector;
}
-void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, const uint64_t numTimeDomainDataPoints )
+void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem,
+ const uint64_t numFFTDataPoints,
+ const uint64_t numTimeDomainDataPoints )
{
ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
@@ -168,6 +173,9 @@ void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumU
_timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints,
imagTimeDomainDataPoints,
numTimeDomainDataPoints);
+ _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints,
+ imagTimeDomainDataPoints,
+ numTimeDomainDataPoints);
}
// Don't update the repeated data for the waterfall
if(!repeatDataFlag){
@@ -199,27 +207,29 @@ void SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
SpectrumTypeTab->resize( e->size().width(), SpectrumTypeTab->height());
// Tell the TabXFreqDisplay to resize
- Tab1PlotDisplayFrame->resize(e->size().width()-4,
+ Tab1PlotDisplayFrame->resize(e->size().width()-4,
Tab1PlotDisplayFrame->height());
Tab2PlotDisplayFrame->resize(e->size().width()-4,
Tab2PlotDisplayFrame->height());
- Waterfall3DPlotDisplayFrame->resize(e->size().width()-4,
+ Waterfall3DPlotDisplayFrame->resize(e->size().width()-4,
Waterfall3DPlotDisplayFrame->height());
- TimeDomainDisplayFrame->resize(e->size().width()-4,
+ TimeDomainDisplayFrame->resize(e->size().width()-4,
TimeDomainDisplayFrame->height());
- _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4,
+ _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4,
Tab1PlotDisplayFrame->height());
- _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4,
+ _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4,
Tab2PlotDisplayFrame->height());
- _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4,
+ _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4,
Waterfall3DPlotDisplayFrame->height());
- _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4,
+ _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4,
TimeDomainDisplayFrame->height());
// Move the IntensityWheels and Labels
- WaterfallMaximumIntensityLabel->move(width() - 5 - WaterfallMaximumIntensityLabel->width(),
+ WaterfallMaximumIntensityLabel->move(width() - 5 -
+ WaterfallMaximumIntensityLabel->width(),
WaterfallMaximumIntensityLabel->y());
- WaterfallMinimumIntensityLabel->move(width() - 5 - WaterfallMinimumIntensityLabel->width(),
+ WaterfallMinimumIntensityLabel->move(width() - 5 -
+ WaterfallMinimumIntensityLabel->width(),
WaterfallMinimumIntensityLabel->y());
WaterfallMaximumIntensityWheel->resize(WaterfallMaximumIntensityLabel->x() - 5 -
WaterfallMaximumIntensityWheel->x(),
diff --git a/gr-qtgui/src/lib/spectrumdisplayform.h b/gr-qtgui/src/lib/spectrumdisplayform.h
index 97b14a6c9..6e57e2cec 100644
--- a/gr-qtgui/src/lib/spectrumdisplayform.h
+++ b/gr-qtgui/src/lib/spectrumdisplayform.h
@@ -11,6 +11,7 @@ class SpectrumGUIClass;
#include <WaterfallDisplayPlot.h>
#include <Waterfall3DDisplayPlot.h>
#include <TimeDomainDisplayPlot.h>
+#include <ConstellationDisplayPlot.h>
#include <QValidator>
#include <vector>
@@ -73,6 +74,7 @@ private:
WaterfallDisplayPlot* _waterfallDisplayPlot;
Waterfall3DDisplayPlot* _waterfall3DDisplayPlot;
TimeDomainDisplayPlot* _timeDomainDisplayPlot;
+ ConstellationDisplayPlot* _constellationDisplayPlot;
SpectrumGUIClass* _system;
bool _systemSpecifiedFlag;
double _centerFrequency;
diff --git a/gr-qtgui/src/lib/spectrumdisplayform.ui b/gr-qtgui/src/lib/spectrumdisplayform.ui
index aac323dac..561be64cb 100644
--- a/gr-qtgui/src/lib/spectrumdisplayform.ui
+++ b/gr-qtgui/src/lib/spectrumdisplayform.ui
@@ -358,7 +358,7 @@
</property>
</item>
</widget>
- <widget class="QwtWheel" native="1" name="WaterfallMaximumIntensityWheel" >
+ <widget class="QwtWheel" name="WaterfallMaximumIntensityWheel" >
<property name="geometry" >
<rect>
<x>215</x>
@@ -373,16 +373,16 @@
<property name="focusPolicy" >
<enum>Qt::WheelFocus</enum>
</property>
- <property name="valid" stdset="0" >
+ <property name="valid" >
<bool>true</bool>
</property>
- <property name="totalAngle" stdset="0" >
+ <property name="totalAngle" >
<double>200.000000000000000</double>
</property>
- <property name="viewAngle" stdset="0" >
+ <property name="viewAngle" >
<double>20.000000000000000</double>
</property>
- <property name="mass" stdset="0" >
+ <property name="mass" >
<double>0.000000000000000</double>
</property>
</widget>
@@ -418,7 +418,7 @@
<enum>QFrame::Plain</enum>
</property>
</widget>
- <widget class="QwtWheel" native="1" name="WaterfallMinimumIntensityWheel" >
+ <widget class="QwtWheel" name="WaterfallMinimumIntensityWheel" >
<property name="geometry" >
<rect>
<x>215</x>
@@ -427,16 +427,16 @@
<height>24</height>
</rect>
</property>
- <property name="valid" stdset="0" >
+ <property name="valid" >
<bool>true</bool>
</property>
- <property name="totalAngle" stdset="0" >
+ <property name="totalAngle" >
<double>200.000000000000000</double>
</property>
- <property name="viewAngle" stdset="0" >
+ <property name="viewAngle" >
<double>20.000000000000000</double>
</property>
- <property name="mass" stdset="0" >
+ <property name="mass" >
<double>0.000000000000000</double>
</property>
</widget>
@@ -525,7 +525,7 @@
<string>Auto Scale</string>
</property>
</widget>
- <widget class="QwtWheel" native="1" name="Waterfall3DMinimumIntensityWheel" >
+ <widget class="QwtWheel" name="Waterfall3DMinimumIntensityWheel" >
<property name="geometry" >
<rect>
<x>215</x>
@@ -534,16 +534,16 @@
<height>24</height>
</rect>
</property>
- <property name="valid" stdset="0" >
+ <property name="valid" >
<bool>true</bool>
</property>
- <property name="totalAngle" stdset="0" >
+ <property name="totalAngle" >
<double>200.000000000000000</double>
</property>
- <property name="viewAngle" stdset="0" >
+ <property name="viewAngle" >
<double>20.000000000000000</double>
</property>
- <property name="mass" stdset="0" >
+ <property name="mass" >
<double>0.000000000000000</double>
</property>
</widget>
@@ -614,7 +614,7 @@
</property>
</item>
</widget>
- <widget class="QwtWheel" native="1" name="Waterfall3DMaximumIntensityWheel" >
+ <widget class="QwtWheel" name="Waterfall3DMaximumIntensityWheel" >
<property name="geometry" >
<rect>
<x>215</x>
@@ -629,16 +629,16 @@
<property name="focusPolicy" >
<enum>Qt::WheelFocus</enum>
</property>
- <property name="valid" stdset="0" >
+ <property name="valid" >
<bool>true</bool>
</property>
- <property name="totalAngle" stdset="0" >
+ <property name="totalAngle" >
<double>200.000000000000000</double>
</property>
- <property name="viewAngle" stdset="0" >
+ <property name="viewAngle" >
<double>20.000000000000000</double>
</property>
- <property name="mass" stdset="0" >
+ <property name="mass" >
<double>0.000000000000000</double>
</property>
</widget>
@@ -664,6 +664,27 @@
</property>
</widget>
</widget>
+ <widget class="QWidget" name="ConstellationPage" >
+ <attribute name="title" >
+ <string>Constellation Display</string>
+ </attribute>
+ <widget class="QFrame" name="ConstellationDisplayFrame" >
+ <property name="geometry" >
+ <rect>
+ <x>5</x>
+ <y>5</y>
+ <width>620</width>
+ <height>340</height>
+ </rect>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11" />
diff --git a/gr-qtgui/src/python/qt_digital.py b/gr-qtgui/src/python/qt_digital.py
new file mode 100755
index 000000000..f7635b4a5
--- /dev/null
+++ b/gr-qtgui/src/python/qt_digital.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, blks2
+from gnuradio.qtgui import qtgui
+import scipy
+
+class my_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ sps = 2
+ excess_bw = 0.35
+ gray_code = True
+
+ fftsize = 2048
+
+ data = scipy.random.randint(0, 255, 1000)
+ src = gr.vector_source_b(data, True)
+ mod = blks2.dqpsk_mod(sps, excess_bw, gray_code, False, False)
+
+ rrctaps = gr.firdes.root_raised_cosine(1, sps, 1, excess_bw, 21)
+ rx_rrc = gr.fir_filter_ccf(sps, rrctaps)
+
+ thr = gr.throttle(gr.sizeof_gr_complex, 10*fftsize)
+ self.snk_tx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -1/2, 1/2)
+ self.snk_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -1/2, 1/2)
+
+ self.connect(src, mod, self.snk_tx)
+ self.connect(mod, rx_rrc, thr, self.snk_rx)
+
+ self.snk_tx.initialize()
+ qapp = self.snk_tx.get_qapplication()
+ self.snk_rx.initialize(qapp)
+
+if __name__ == "__main__":
+ tb = my_top_block();
+ tb.start()
+ tb.snk_tx.start_app();
+ #tb.wait();
+