diff options
Diffstat (limited to 'gr-qtgui/lib')
29 files changed, 1413 insertions, 455 deletions
diff --git a/gr-qtgui/lib/.gitignore b/gr-qtgui/lib/.gitignore index fc4f8cdfe..7754ad227 100644 --- a/gr-qtgui/lib/.gitignore +++ b/gr-qtgui/lib/.gitignore @@ -10,6 +10,7 @@ /spectrumdisplayform.ui.h /FrequencyDisplayPlot.moc.cc /ConstellationDisplayPlot.moc.cc +/timedisplayform.moc.cc /gnuradio /guile /python diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc index 75dbe9c37..dda7cfea2 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.cc +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef CONSTELLATION_DISPLAY_PLOT_C #define CONSTELLATION_DISPLAY_PLOT_C @@ -36,7 +58,7 @@ protected: ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) : QwtPlot(parent) { - timespec_reset(&_lastReplot); + _lastReplot = 0; resize(parent->width(), parent->height()); @@ -161,8 +183,8 @@ void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, const double timeInterval) { if((numDataPoints > 0) && - (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { - + (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) { + if(numDataPoints != _numPoints){ _numPoints = numDataPoints; @@ -177,7 +199,7 @@ void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); - _lastReplot = get_highres_clock(); + _lastReplot = gruel::high_res_timer_now(); } } diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h index bf4531e0a..23004f86c 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.h +++ b/gr-qtgui/lib/ConstellationDisplayPlot.h @@ -1,6 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef CONSTELLATION_DISPLAY_PLOT_HPP #define CONSTELLATION_DISPLAY_PLOT_HPP +#include <stdint.h> #include <cstdio> #include <qwt_plot.h> #include <qwt_painter.h> @@ -11,7 +34,7 @@ #include <qwt_plot_zoomer.h> #include <qwt_plot_panner.h> #include <qwt_plot_marker.h> -#include <highResTimeFunctions.h> +#include <gruel/high_res_timer.h> #include <qwt_symbol.h> #include <qtgui_util.h> @@ -60,7 +83,7 @@ private: double* _realDataPoints; double* _imagDataPoints; - timespec _lastReplot; + gruel::high_res_timer_type _lastReplot; int64_t _numPoints; int64_t _penSize; diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index 30b318184..f57edd8f6 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef FREQUENCY_DISPLAY_PLOT_C #define FREQUENCY_DISPLAY_PLOT_C @@ -98,7 +120,7 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _startFrequency = 0; _stopFrequency = 4000; - timespec_reset(&_lastReplot); + _lastReplot = 0; resize(parent->width(), parent->height()); @@ -340,7 +362,7 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat { // Only update plot if there is data and if the time interval has elapsed if((numDataPoints > 0) && - (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { + (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) { if(numDataPoints != _numPoints) { _numPoints = numDataPoints; @@ -379,7 +401,7 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat SetUpperIntensityLevel(_peakAmplitude); - _lastReplot = get_highres_clock(); + _lastReplot = gruel::high_res_timer_now(); } } diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h index 7a207ab8d..a263fec2f 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.h +++ b/gr-qtgui/lib/FrequencyDisplayPlot.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef FREQUENCY_DISPLAY_PLOT_HPP #define FREQUENCY_DISPLAY_PLOT_HPP @@ -13,7 +35,7 @@ #include <qwt_plot_panner.h> #include <qwt_plot_marker.h> #include <qwt_plot_magnifier.h> -#include <highResTimeFunctions.h> +#include <gruel/high_res_timer.h> #include <qwt_symbol.h> #include <qtgui_util.h> @@ -100,7 +122,7 @@ private: double _noiseFloorAmplitude; - timespec _lastReplot; + gruel::high_res_timer_type _lastReplot; bool _useCenterFrequencyFlag; }; diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index 7dee39eb4..849ee8360 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -24,12 +24,14 @@ include $(top_srcdir)/Makefile.common EXTRA_DIST += spectrumdisplayform.ui AM_CPPFLAGS = -I. $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \ - $(QT_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES) + $(QT_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES) \ + -Dlibgnuradio_qtgui_EXPORTS # Only include these files in the build if qtgui passes configure checks # This is mostly to help make distcheck pass QMAKE_SOURCES = \ spectrumdisplayform.moc.cc \ + timedisplayform.moc.cc \ FrequencyDisplayPlot.moc.cc \ TimeDomainDisplayPlot.moc.cc \ WaterfallDisplayPlot.moc.cc \ @@ -49,11 +51,14 @@ libgnuradio_qtgui_la_SOURCES = \ waterfallGlobalData.cc \ ConstellationDisplayPlot.cc \ spectrumdisplayform.cc \ + timedisplayform.cc \ SpectrumGUIClass.cc \ spectrumUpdateEvents.cc \ plot_waterfall.cc \ qtgui_sink_c.cc \ qtgui_sink_f.cc \ + qtgui_time_sink_c.cc \ + qtgui_time_sink_f.cc \ qtgui_util.cc nodist_libgnuradio_qtgui_la_SOURCES=$(QMAKE_SOURCES) @@ -65,13 +70,16 @@ grinclude_HEADERS = \ WaterfallDisplayPlot.h \ waterfallGlobalData.h \ ConstellationDisplayPlot.h \ - highResTimeFunctions.h \ plot_waterfall.h \ spectrumdisplayform.h \ + timedisplayform.h \ SpectrumGUIClass.h \ spectrumUpdateEvents.h \ + gr_qtgui_api.h \ qtgui_sink_c.h \ qtgui_sink_f.h \ + qtgui_time_sink_c.h \ + qtgui_time_sink_f.h \ qtgui_util.h #QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc index 1a519591d..af95e2bb2 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.cc +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef SPECTRUM_GUI_CLASS_CPP #define SPECTRUM_GUI_CLASS_CPP @@ -32,7 +54,7 @@ SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize, _windowType = 5; - timespec_reset(&_lastGUIUpdateTime); + _lastGUIUpdateTime = 0; _windowOpennedFlag = false; _fftBuffersCreatedFlag = false; @@ -101,10 +123,10 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, qApp->postEvent(_spectrumDisplayForm, new QEvent(QEvent::Type(QEvent::User+3))); - timespec_reset(&_lastGUIUpdateTime); + _lastGUIUpdateTime = 0; // Draw Blank Display - UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, get_highres_clock(), true); + UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, gruel::high_res_timer_now(), true); // Set up the initial frequency axis settings SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); @@ -207,7 +229,7 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, const uint64_t realTimeDomainDataSize, const float* complexTimeDomainData, const uint64_t complexTimeDomainDataSize, - const timespec timestamp, + const gruel::high_res_timer_type timestamp, const bool lastOfMultipleFFTUpdateFlag) { //gruel::scoped_lock lock(d_mutex); @@ -261,11 +283,11 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, _lastDataPointCount = bufferSize; } - const timespec currentTime = get_highres_clock(); - const timespec lastUpdateGUITime = GetLastGUIUpdateTime(); + const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); + const gruel::high_res_timer_type lastUpdateGUITime = GetLastGUIUpdateTime(); - if((diff_timespec(currentTime, lastUpdateGUITime) > (4*_updateTime)) && - (GetPendingGUIUpdateEvents() > 0) && !timespec_empty(&lastUpdateGUITime)) { + if((currentTime - lastUpdateGUITime > (4*_updateTime)*gruel::high_res_timer_tps()) && + (GetPendingGUIUpdateEvents() > 0) && lastUpdateGUITime != 0) { // Do not update the display if too much data is pending to be displayed _droppedEntriesCount++; } @@ -354,17 +376,17 @@ SpectrumGUIClass::SetFFTSize(const int newSize) _fftSize = newSize; } -timespec +gruel::high_res_timer_type SpectrumGUIClass::GetLastGUIUpdateTime() { gruel::scoped_lock lock(d_mutex); - timespec returnValue; + gruel::high_res_timer_type returnValue; returnValue = _lastGUIUpdateTime; return returnValue; } void -SpectrumGUIClass::SetLastGUIUpdateTime(const timespec newTime) +SpectrumGUIClass::SetLastGUIUpdateTime(const gruel::high_res_timer_type newTime) { gruel::scoped_lock lock(d_mutex); _lastGUIUpdateTime = newTime; diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h index 48f45a0f5..857c2515f 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.h +++ b/gr-qtgui/lib/SpectrumGUIClass.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef SPECTRUM_GUI_CLASS_HPP #define SPECTRUM_GUI_CLASS_HPP @@ -44,7 +66,7 @@ public: const uint64_t, const float*, const uint64_t, const float*, const uint64_t, - const timespec, const bool); + const gruel::high_res_timer_type, const bool); float GetPowerValue(); void SetPowerValue(const float); @@ -56,8 +78,8 @@ public: int GetFFTSizeIndex(); void SetFFTSize(const int); - timespec GetLastGUIUpdateTime(); - void SetLastGUIUpdateTime(const timespec); + gruel::high_res_timer_type GetLastGUIUpdateTime(); + void SetLastGUIUpdateTime(const gruel::high_res_timer_type); unsigned int GetPendingGUIUpdateEvents(); void IncrementPendingGUIUpdateEvents(); @@ -92,7 +114,7 @@ private: int _windowType; int64_t _lastDataPointCount; int _fftSize; - timespec _lastGUIUpdateTime; + gruel::high_res_timer_type _lastGUIUpdateTime; unsigned int _pendingGUIUpdateEventsCount; int _droppedEntriesCount; bool _fftBuffersCreatedFlag; diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index be25a6cde..f635a2b0c 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef TIME_DOMAIN_DISPLAY_PLOT_C #define TIME_DOMAIN_DISPLAY_PLOT_C @@ -5,7 +27,8 @@ #include <qwt_scale_draw.h> #include <qwt_legend.h> - +#include <QColor> +#include <iostream> class TimePrecisionClass { @@ -70,16 +93,14 @@ private: std::string _unitType; }; -TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) +TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) + : QwtPlot(parent), _nplots(nplots) { - timespec_reset(&_lastReplot); - resize(parent->width(), parent->height()); _numPoints = 1024; - _realDataPoints = new double[_numPoints]; - _imagDataPoints = new double[_numPoints]; _xAxisPoints = new double[_numPoints]; + memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); _zoomer = new TimeDomainDisplayZoomer(canvas(), 0); _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); @@ -96,41 +117,40 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) canvas()->setPalette(palette); setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); - set_xaxis(0, _numPoints); + setXaxis(0, _numPoints); setAxisTitle(QwtPlot::xBottom, "Time (sec)"); setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); - set_yaxis(-2.0, 2.0); - setAxisTitle(QwtPlot::yLeft, "Normalized Voltage"); + setYaxis(-2.0, 2.0); + setAxisTitle(QwtPlot::yLeft, "Amplitude"); + QList<QColor> colors; + colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green) + << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta) + << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed) + << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray); + + int ncolors = colors.size(); + + // Setup dataPoints and plot vectors // Automatically deleted when parent is deleted - _real_plot_curve = new QwtPlotCurve("Real Data"); - _real_plot_curve->attach(this); - _real_plot_curve->setPen(QPen(Qt::blue)); - _real_plot_curve->setRawData(_xAxisPoints, _realDataPoints, _numPoints); - - _imag_plot_curve = new QwtPlotCurve("Imaginary Data"); - _imag_plot_curve->attach(this); - _imag_plot_curve->setPen(QPen(Qt::magenta)); - _imag_plot_curve->setRawData(_xAxisPoints, _imagDataPoints, _numPoints); - // _imag_plot_curve->setVisible(false); - - memset(_realDataPoints, 0x0, _numPoints*sizeof(double)); - memset(_imagDataPoints, 0x0, _numPoints*sizeof(double)); - memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); + for(int i = 0; i < _nplots; i++) { + _dataPoints.push_back(new double[_numPoints]); + memset(_dataPoints[i], 0x0, _numPoints*sizeof(double)); + + _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); + _plot_curve[i]->attach(this); + _plot_curve[i]->setPen(QPen(colors[i])); + _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); + } _sampleRate = 1; _resetXAxisPoints(); -#if QT_VERSION < 0x040000 - _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); -#else _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); -#endif + Qt::RightButton, Qt::ControlModifier); _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, - Qt::RightButton); + Qt::RightButton); _panner = new QwtPlotPanner(canvas()); _panner->setAxisEnabled(QwtPlot::yRight, false); @@ -164,29 +184,40 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) )); } -TimeDomainDisplayPlot::~TimeDomainDisplayPlot(){ - delete[] _realDataPoints; - delete[] _imagDataPoints; +TimeDomainDisplayPlot::~TimeDomainDisplayPlot() +{ + for(int i = 0; i < _nplots; i++) + delete [] _dataPoints[i]; delete[] _xAxisPoints; - // _fft_plot_curves deleted when parent deleted // _zoomer and _panner deleted when parent deleted } void -TimeDomainDisplayPlot::set_yaxis(double min, double max) +TimeDomainDisplayPlot::setYaxis(double min, double max) { setAxisScale(QwtPlot::yLeft, min, max); _zoomer->setZoomBase(); } void -TimeDomainDisplayPlot::set_xaxis(double min, double max) +TimeDomainDisplayPlot::setXaxis(double min, double max) { setAxisScale(QwtPlot::xBottom, min, max); _zoomer->setZoomBase(); } +void +TimeDomainDisplayPlot::setTitle(int which, QString title) +{ + _plot_curve[which]->setTitle(title); +} + +void +TimeDomainDisplayPlot::setColor(int which, QString color) +{ + _plot_curve[which]->setPen(QPen(color)); +} void TimeDomainDisplayPlot::replot() { @@ -196,47 +227,37 @@ void TimeDomainDisplayPlot::replot() void TimeDomainDisplayPlot::resizeSlot( QSize *s ) { - resize(s->width(), s->height()); + // -10 is to spare some room for the legend and x-axis label + resize(s->width()-10, s->height()-10); } -void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints, - const double* imagDataPoints, +void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, const int64_t numDataPoints, const double timeInterval) { - if((numDataPoints > 0) && - (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { - + if((numDataPoints > 0)) { if(numDataPoints != _numPoints){ _numPoints = numDataPoints; - delete[] _realDataPoints; - delete[] _imagDataPoints; delete[] _xAxisPoints; - _realDataPoints = new double[_numPoints]; - _imagDataPoints = new double[_numPoints]; _xAxisPoints = new double[_numPoints]; - - _real_plot_curve->setRawData(_xAxisPoints, _realDataPoints, _numPoints); - _imag_plot_curve->setRawData(_xAxisPoints, _imagDataPoints, _numPoints); - - set_xaxis(0, numDataPoints); + for(int i = 0; i < _nplots; i++) { + delete[] _dataPoints[i]; + _dataPoints[i] = new double[_numPoints]; + _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); + } + + setXaxis(0, numDataPoints); _resetXAxisPoints(); } - memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); - memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); - - _lastReplot = get_highres_clock(); + for(int i = 0; i < _nplots; i++) { + memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); + } } } -void TimeDomainDisplayPlot::SetImaginaryDataVisible(const bool visibleFlag) -{ - _imag_plot_curve->setVisible(visibleFlag); -} - void TimeDomainDisplayPlot::_resetXAxisPoints() { double delt = 1.0/_sampleRate; diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h index 01338300c..af87e1b14 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.h +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -1,8 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef TIME_DOMAIN_DISPLAY_PLOT_HPP #define TIME_DOMAIN_DISPLAY_PLOT_HPP #include <stdint.h> #include <cstdio> +#include <vector> #include <qwt_plot.h> #include <qwt_painter.h> #include <qwt_plot_canvas.h> @@ -13,7 +36,6 @@ #include <qwt_plot_panner.h> #include <qwt_plot_magnifier.h> #include <qwt_plot_marker.h> -#include <highResTimeFunctions.h> #include <qwt_symbol.h> #include <qtgui_util.h> @@ -21,20 +43,20 @@ class TimeDomainDisplayPlot:public QwtPlot{ Q_OBJECT public: - TimeDomainDisplayPlot(QWidget*); + TimeDomainDisplayPlot(int nplots, QWidget*); virtual ~TimeDomainDisplayPlot(); - void PlotNewData(const double* realDataPoints, const double* imagDataPoints, + void PlotNewData(const std::vector<double*> dataPoints, const int64_t numDataPoints, const double timeInterval); - void SetImaginaryDataVisible(const bool); - virtual void replot(); - void set_yaxis(double min, double max); - void set_xaxis(double min, double max); - public slots: + void setYaxis(double min, double max); + void setXaxis(double min, double max); + void setTitle(int which, QString title); + void setColor(int which, QString color); + void resizeSlot( QSize *s ); void SetSampleRate(double sr, double units, const std::string &strunits); @@ -52,8 +74,8 @@ protected: private: void _resetXAxisPoints(); - QwtPlotCurve* _real_plot_curve; - QwtPlotCurve* _imag_plot_curve; + int _nplots; + std::vector<QwtPlotCurve*> _plot_curve; QwtPlotPanner* _panner; QwtPlotZoomer* _zoomer; @@ -61,14 +83,11 @@ private: QwtDblClickPlotPicker *_picker; QwtPlotMagnifier *_magnifier; - double* _realDataPoints; - double* _imagDataPoints; + std::vector<double*> _dataPoints; double* _xAxisPoints; double _sampleRate; - timespec _lastReplot; - int64_t _numPoints; }; diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index 2234f4238..1476be2bd 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef WATERFALL_DISPLAY_PLOT_C #define WATERFALL_DISPLAY_PLOT_C @@ -88,7 +110,7 @@ class TimeScaleData public: TimeScaleData() { - timespec_reset(&_zeroTime); + _zeroTime = 0; _secondsPerLine = 1.0; } @@ -96,14 +118,14 @@ public: { } - virtual timespec GetZeroTime() const + virtual gruel::high_res_timer_type GetZeroTime() const { return _zeroTime; } - virtual void SetZeroTime(const timespec newTime) + virtual void SetZeroTime(const gruel::high_res_timer_type newTime) { - _zeroTime = newTime; + _zeroTime = newTime - gruel::high_res_timer_epoch(); } virtual void SetSecondsPerLine(const double newTime) @@ -118,13 +140,26 @@ public: protected: - timespec _zeroTime; + gruel::high_res_timer_type _zeroTime; double _secondsPerLine; private: }; +static QString +make_time_label(double secs) +{ + std::string time_str = pt::to_simple_string(pt::from_time_t(time_t(secs))); + + // lops off the YYYY-mmm-DD part of the string + size_t ind = time_str.find(" "); + if(ind != std::string::npos) + time_str = time_str.substr(ind); + + return QString("").sprintf("%s.%03ld", time_str.c_str(), long(std::fmod(secs*1000, 1000))); +} + class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData { public: @@ -138,14 +173,8 @@ public: virtual QwtText label(double value) const { - timespec lineTime = timespec_add(GetZeroTime(), (-value) * GetSecondsPerLine()); - std::string time_str = pt::to_simple_string(pt::from_time_t(lineTime.tv_sec)); - - // lops off the YYYY-mmm-DD part of the string - size_t ind = time_str.find(" "); - if(ind != std::string::npos) - time_str = time_str.substr(ind); - return QwtText(QString("").sprintf("%s.%03ld", time_str.c_str(), lineTime.tv_nsec/1000000)); + double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (value * GetSecondsPerLine()); + return QwtText(make_time_label(secs)); } virtual void initiateUpdate() @@ -190,18 +219,10 @@ protected: using QwtPlotZoomer::trackerText; virtual QwtText trackerText( const QwtDoublePoint& p ) const { - timespec lineTime = timespec_add(GetZeroTime(), (-p.y()) * GetSecondsPerLine()); - std::string time_str = pt::to_simple_string(pt::from_time_t(lineTime.tv_sec)); - - // lops off the YYYY-mmm-DD part of the string - size_t ind = time_str.find(" "); - if(ind != std::string::npos) - time_str = time_str.substr(ind); - QString yLabel(QString("").sprintf("%s.%03ld", time_str.c_str(), lineTime.tv_nsec/1000000)); - + double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (p.y() * GetSecondsPerLine()); QwtText t(QString("%1 %2, %3"). - arg(p.x(), 0, 'f', GetFrequencyPrecision()). - arg(_unitType.c_str()).arg(yLabel)); + arg(p.x(), 0, 'f', GetFrequencyPrecision()). + arg(_unitType.c_str()).arg(make_time_label(secs))); return t; } @@ -232,7 +253,7 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) setAxisTitle(QwtPlot::yLeft, "Time"); setAxisScaleDraw(QwtPlot::yLeft, new QwtTimeScaleDraw()); - timespec_reset(&_lastReplot); + _lastReplot = 0; d_spectrogram = new PlotWaterfall(_waterfallData, "Waterfall Display"); @@ -367,7 +388,7 @@ void WaterfallDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints, const double timePerFFT, - const timespec timestamp, + const gruel::high_res_timer_type timestamp, const int droppedFrames) { if(numDataPoints > 0){ @@ -383,10 +404,10 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, replot(); } - _lastReplot = get_highres_clock(); + _lastReplot = gruel::high_res_timer_now(); } - if(diff_timespec(get_highres_clock(), _lastReplot) > timePerFFT) { + if(gruel::high_res_timer_now() - _lastReplot > timePerFFT*gruel::high_res_timer_tps()) { //FIXME: We may want to average the data between these updates to smooth display _waterfallData->addFFTData(dataPoints, numDataPoints, droppedFrames); _waterfallData->IncrementNumLinesToUpdate(); @@ -403,7 +424,7 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, replot(); - _lastReplot = get_highres_clock(); + _lastReplot = gruel::high_res_timer_now(); } } } @@ -546,7 +567,7 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() replot(); // Update the last replot timer - _lastReplot = get_highres_clock(); + _lastReplot = gruel::high_res_timer_now(); } void diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h index faa48d6aa..0c6a521b1 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.h +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef WATERFALL_DISPLAY_PLOT_HPP #define WATERFALL_DISPLAY_PLOT_HPP @@ -10,7 +32,7 @@ #include <qtgui_util.h> #include <plot_waterfall.h> -#include <highResTimeFunctions.h> +#include <gruel/high_res_timer.h> class WaterfallDisplayPlot:public QwtPlot{ Q_OBJECT @@ -29,7 +51,7 @@ public: double GetStopFrequency()const; void PlotNewData(const double* dataPoints, const int64_t numDataPoints, - const double timePerFFT, const timespec timestamp, + const double timePerFFT, const gruel::high_res_timer_type timestamp, const int droppedFrames); void SetIntensityRange(const double minIntensity, const double maxIntensity); @@ -76,7 +98,7 @@ private: WaterfallData* _waterfallData; - timespec _lastReplot; + gruel::high_res_timer_type _lastReplot; bool _useCenterFrequencyFlag; diff --git a/gr-qtgui/lib/gr_qtgui_api.h b/gr-qtgui/lib/gr_qtgui_api.h new file mode 100644 index 000000000..65033a093 --- /dev/null +++ b/gr-qtgui/lib/gr_qtgui_api.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 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_GR_QTGUI_API_H +#define INCLUDED_GR_QTGUI_API_H + +#include <gruel/attributes.h> + +#ifdef libgnuradio_qtgui_EXPORTS +# define GR_QTGUI_API __GR_ATTR_EXPORT +#else +# define GR_QTGUI_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_GR_QTGUI_API_H */ diff --git a/gr-qtgui/lib/highResTimeFunctions.h b/gr-qtgui/lib/highResTimeFunctions.h index 251bbad8b..6b3844901 100644 --- a/gr-qtgui/lib/highResTimeFunctions.h +++ b/gr-qtgui/lib/highResTimeFunctions.h @@ -1,299 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef HIGH_RES_TIME_FUNCTIONS_H #define HIGH_RES_TIME_FUNCTIONS_H -#include <ctime> -#include <sys/time.h> -#include <cmath> -/* Requires the librt and libm libraries */ - -static const long NSEC_PER_SEC = 1000000000L; - -static inline bool -timespec_greater(const struct timespec* t1, - const struct timespec* t0) -{ - return ((t1->tv_sec > t0->tv_sec) || - ((t1->tv_sec == t0->tv_sec) && - (t1->tv_nsec > t0->tv_nsec))); -} - -static inline bool -timespec_greater(const struct timespec t1, - const struct timespec t0) -{ - return ((t1.tv_sec > t0.tv_sec) || - ((t1.tv_sec == t0.tv_sec) && - (t1.tv_nsec > t0.tv_nsec))); -} - -static inline bool -timespec_less(const struct timespec* t1, - const struct timespec* t0) -{ - return ((t1->tv_sec < t0->tv_sec) || - ((t1->tv_sec == t0->tv_sec) && - (t1->tv_nsec < t0->tv_nsec))); -} - -static inline bool -timespec_less(const struct timespec t1, - const struct timespec t0) -{ - return ((t1.tv_sec < t0.tv_sec) || - ((t1.tv_sec == t0.tv_sec) && - (t1.tv_nsec < t0.tv_nsec))); -} - -static inline bool -timespec_equal(const struct timespec* t1, - const struct timespec* t0) -{ - return ((t1->tv_sec == t0->tv_sec) && - (t1->tv_nsec == t0->tv_nsec)); -} - -static inline bool -timespec_equal(const struct timespec t1, - const struct timespec t0) -{ - return ((t1.tv_sec == t0.tv_sec) && - (t1.tv_nsec == t0.tv_nsec)); -} - -static inline void -timespec_reset(struct timespec* ret) -{ - ret->tv_sec = 0; - ret->tv_nsec = 0; -} - -static inline void -set_normalized_timespec(struct timespec *ts, - time_t sec, long nsec) -{ - while (nsec > NSEC_PER_SEC) { - nsec -= NSEC_PER_SEC; - ++sec; - } - while(nsec < 0) { - nsec += NSEC_PER_SEC; - --sec; - } - ts->tv_sec = sec; - ts->tv_nsec = nsec; -} - -static inline struct timespec -convert_to_timespec(const double timeValue) -{ - struct timespec ret; - double seconds = 0; - long nsec = static_cast<long>(modf(timeValue, &seconds) * - static_cast<double>(NSEC_PER_SEC)); - time_t sec = static_cast<time_t>(seconds); - - set_normalized_timespec(&ret, sec, nsec); - - return ret; -} - -static inline double -convert_from_timespec(const timespec actual) -{ - return (static_cast<double>(actual.tv_sec) + - (static_cast<double>(actual.tv_nsec) / - static_cast<double>(NSEC_PER_SEC))); -} - -static inline void -timespec_add(struct timespec *ret, - const struct timespec* t1, - const struct timespec* t0) -{ - time_t sec = t1->tv_sec + t0->tv_sec; - long nsec = t1->tv_nsec + t0->tv_nsec; +#include <gruel/high_res_timer.h> - set_normalized_timespec(ret, sec, nsec); -} - -static inline void -timespec_add(struct timespec *ret, - const struct timespec t1, - const struct timespec t0) -{ - return timespec_add(ret, &t1, &t0); -} - -static inline struct timespec -timespec_add(const struct timespec t1, - const struct timespec t0) -{ - struct timespec ret; - timespec_add(&ret, &t1, &t0); - return ret; -} - -static inline struct timespec -timespec_add(const struct timespec t1, - const double time0) -{ - struct timespec ret; - struct timespec t0; - t0 = convert_to_timespec(time0); - - timespec_add(&ret, &t1, &t0); - - return ret; -} +typedef gruel::high_res_timer_type highres_timespec; -static inline void -timespec_subtract(struct timespec *ret, - const struct timespec* t1, - const struct timespec* t0) -{ - time_t sec = t1->tv_sec - t0->tv_sec; - long nsec = t1->tv_nsec - t0->tv_nsec; - - set_normalized_timespec(ret, sec, nsec); -} - -static inline void -timespec_subtract(struct timespec *ret, - const struct timespec t1, - const struct timespec t0) -{ - return timespec_subtract(ret, &t1, &t0); -} - -static inline struct timespec -timespec_subtract(const struct timespec t1, - const struct timespec t0) -{ - struct timespec ret; - timespec_subtract(&ret, &t1, &t0); - return ret; -} - -static inline struct timespec -timespec_subtract(const struct timespec t1, - const double time0) -{ - struct timespec ret; - struct timespec t0; - t0 = convert_to_timespec(time0); - - timespec_subtract(&ret, &t1, &t0); - - return ret; -} - -static inline double -diff_timespec(struct timespec* ret, - const struct timespec *t1, - const struct timespec* t0) -{ - struct timespec actual; - time_t sec = 0; - long nsec = 0; - - if(timespec_greater(t1, t0)){ - sec = t1->tv_sec - t0->tv_sec; - nsec = t1->tv_nsec - t0->tv_nsec; - - set_normalized_timespec(&actual, sec, nsec); - - if(ret != NULL){ - ret->tv_sec = actual.tv_sec; - ret->tv_nsec = actual.tv_nsec; - } - - return convert_from_timespec(actual); - } - else{ - sec = t0->tv_sec - t1->tv_sec; - nsec = t0->tv_nsec - t1->tv_nsec; - - // Do nothing with the ret value as the ret value - // would have to store a negative, which it can't. - - set_normalized_timespec(&actual, sec, nsec); - - return (-convert_from_timespec(actual)); - } -} - -static inline double -diff_timespec(struct timespec* ret, - const struct timespec t1, - const struct timespec t0) -{ - return diff_timespec(ret, &t1, &t0); -} - -static inline double -diff_timespec(const struct timespec t1, - const struct timespec t0) -{ - return diff_timespec(NULL, &t1, &t0); -} - - -static inline double -diff_timespec(const struct timespec* t1, - const struct timespec* t0) -{ - return diff_timespec(NULL, t1, t0); -} - - -#ifdef CLOCK_REALTIME -// If we can use clock_gettime, use it; -// otherwise, use gettimeofday -static inline void -get_highres_clock(struct timespec* ret) -{ - if(clock_gettime(CLOCK_REALTIME, ret) != 0){ - // Unable to get high resolution time - - // fail over to low resolution time - timeval lowResTime; - gettimeofday(&lowResTime, NULL); - ret->tv_sec = lowResTime.tv_sec; - ret->tv_nsec = lowResTime.tv_usec*1000; - } -} - -#else - -// Trick timer functions into thinking it has an nsec timer -// but only use the low resolution (usec) timer. -static inline void -get_highres_clock(struct timespec* ret) -{ - timeval lowResTime; - gettimeofday(&lowResTime, NULL); - ret->tv_sec = lowResTime.tv_sec; - ret->tv_nsec = lowResTime.tv_usec*1000; -} -#endif - -static inline struct timespec +static inline highres_timespec get_highres_clock() { - struct timespec ret; - get_highres_clock(&ret); - return ret; -} - -static inline bool -timespec_empty(const struct timespec* ret) -{ - return ( (ret->tv_sec == 0 ) && (ret->tv_nsec == 0) ); -} - -static inline bool -timespec_empty(const struct timespec ret) -{ - return timespec_empty(&ret); + return gruel::high_res_timer_now(); } #endif /* HIGH_RES_TIME_FUNCTIONS_H */ diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index 7b40dd01d..965be0773 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -272,7 +272,7 @@ qtgui_sink_c::general_work (int noutput_items, // If we have enough input for one full FFT, do it if(datasize >= resid) { - const timespec currentTime = get_highres_clock(); + const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); // Fill up residbuf with d_fftsize number of items memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid); diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index fb0cb6c5f..b0946885c 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -24,6 +24,7 @@ #define INCLUDED_QTGUI_SINK_C_H #include <Python.h> +#include <gr_qtgui_api.h> #include <gr_block.h> #include <gr_firdes.h> #include <gri_fft.h> @@ -33,17 +34,17 @@ class qtgui_sink_c; typedef boost::shared_ptr<qtgui_sink_c> qtgui_sink_c_sptr; -qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, +GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, double fc=0, double bandwidth=1.0, const std::string &name="Spectrum Display", bool plotfreq=true, bool plotwaterfall=true, bool plottime=true, bool plotconst=true, QWidget *parent=NULL); -class qtgui_sink_c : public gr_block +class GR_QTGUI_API qtgui_sink_c : public gr_block { private: - friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, + friend GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc index 3312b9006..a435064c0 100644 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -268,7 +268,7 @@ qtgui_sink_f::general_work (int noutput_items, // If we have enough input for one full FFT, do it if(datasize >= resid) { - const timespec currentTime = get_highres_clock(); + const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); // Fill up residbuf with d_fftsize number of items memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid); diff --git a/gr-qtgui/lib/qtgui_sink_f.h b/gr-qtgui/lib/qtgui_sink_f.h index 518aa3846..30db05eea 100644 --- a/gr-qtgui/lib/qtgui_sink_f.h +++ b/gr-qtgui/lib/qtgui_sink_f.h @@ -24,6 +24,7 @@ #define INCLUDED_QTGUI_SINK_F_H #include <Python.h> +#include <gr_qtgui_api.h> #include <gr_block.h> #include <gr_firdes.h> #include <gri_fft.h> @@ -34,17 +35,17 @@ class qtgui_sink_f; typedef boost::shared_ptr<qtgui_sink_f> qtgui_sink_f_sptr; -qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, +GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, double fc=0, double bw=1.0, const std::string &name="Spectrum Display", bool plotfreq=true, bool plotwaterfall=true, bool plottime=true, bool plotconst=true, QWidget *parent=NULL); -class qtgui_sink_f : public gr_block +class GR_QTGUI_API qtgui_sink_f : public gr_block { private: - friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, + friend GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, diff --git a/gr-qtgui/lib/qtgui_time_sink_c.cc b/gr-qtgui/lib/qtgui_time_sink_c.cc new file mode 100644 index 000000000..3d38419b2 --- /dev/null +++ b/gr-qtgui/lib/qtgui_time_sink_c.cc @@ -0,0 +1,199 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qtgui_time_sink_c.h> +#include <gr_io_signature.h> +#include <string.h> + +#include <QTimer> + +qtgui_time_sink_c_sptr +qtgui_make_time_sink_c (int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) +{ + return gnuradio::get_initial_sptr(new qtgui_time_sink_c (size, bw, name, + nconnections, parent)); +} + +qtgui_time_sink_c::qtgui_time_sink_c (int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_block ("time_sink_c", + gr_make_io_signature (nconnections, nconnections, sizeof(gr_complex)), + gr_make_io_signature (0, 0, 0)), + d_size(size), d_bandwidth(bw), d_name(name), + d_nconnections(2*nconnections), d_parent(parent) +{ + d_main_gui = NULL; + + d_index = 0; + + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(new double[d_size]); + } + + initialize(); +} + +qtgui_time_sink_c::~qtgui_time_sink_c() +{ + // d_main_gui is a qwidget destroyed with its parent + for(int i = 0; i < d_nconnections; i++) { + delete [] d_residbufs[i]; + } +} + +void +qtgui_time_sink_c::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_size, 8191); + } +} + +void +qtgui_time_sink_c::initialize() +{ + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; +} + + +void +qtgui_time_sink_c::exec_() +{ + d_qApplication->exec(); +} + +QWidget* +qtgui_time_sink_c::qwidget() +{ + return d_main_gui; +} + +PyObject* +qtgui_time_sink_c::pyqwidget() +{ + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; +} + +void +qtgui_time_sink_c::set_time_domain_axis(double min, double max) +{ + d_main_gui->setTimeDomainAxis(min, max); +} + +void +qtgui_time_sink_c::set_update_time(double t) +{ + d_update_time = t; + d_main_gui->setUpdateTime(d_update_time); +} + +void +qtgui_time_sink_c::set_title(int which, const std::string &title) +{ + d_main_gui->setTitle(which, title.c_str()); +} + +void +qtgui_time_sink_c::set_color(int which, const std::string &color) +{ + d_main_gui->setColor(which, color.c_str()); +} + +int +qtgui_time_sink_c::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int n=0, j=0, idx=0; + const gr_complex *in = (const gr_complex*)input_items[idx]; + + for(int i=0; i < noutput_items; i+=d_size) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_size-d_index; + idx = 0; + + // If we have enough input for one full plot, do it + if(datasize >= resid) { + d_current_time = gruel::high_res_timer_now(); + + // Fill up residbufs with d_size number of items + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx++]; + for(unsigned int k = 0; k < resid; k++) { + d_residbufs[n][d_index+k] = in[j+k].real(); + d_residbufs[n+1][d_index+k] = in[j+k].imag(); + } + } + + // Update the plot if its time + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = d_current_time; + d_qApplication->postEvent(d_main_gui, + new TimeUpdateEvent(d_residbufs, d_size)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx++]; + for(unsigned int k = 0; k < resid; k++) { + d_residbufs[n][d_index+k] = in[j+k].real(); + d_residbufs[n+1][d_index+k] = in[j+k].imag(); + } + } + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; +} diff --git a/gr-qtgui/lib/qtgui_time_sink_c.h b/gr-qtgui/lib/qtgui_time_sink_c.h new file mode 100644 index 000000000..459423c40 --- /dev/null +++ b/gr-qtgui/lib/qtgui_time_sink_c.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_C_H +#define INCLUDED_QTGUI_TIME_SINK_C_H + +#include <Python.h> +#include <gr_qtgui_api.h> +#include <gr_block.h> +#include <gr_firdes.h> +#include <gri_fft.h> +#include <qapplication.h> +#include <timedisplayform.h> + +class qtgui_time_sink_c; +typedef boost::shared_ptr<qtgui_time_sink_c> qtgui_time_sink_c_sptr; + +GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, + const std::string &name, + int nconnectons=1, + QWidget *parent=NULL); + +class GR_QTGUI_API qtgui_time_sink_c : public gr_block +{ +private: + friend GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent); + qtgui_time_sink_c(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_size; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + int d_index; + std::vector<double*> d_residbufs; + + double d_update_time; + + QWidget *d_parent; + TimeDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_current_time; + gruel::high_res_timer_type d_last_time; + +public: + ~qtgui_time_sink_c(); + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_time_domain_axis(double min, double max); + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + + QApplication *d_qApplication; + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_QTGUI_TIME_SINK_C_H */ diff --git a/gr-qtgui/lib/qtgui_time_sink_f.cc b/gr-qtgui/lib/qtgui_time_sink_f.cc new file mode 100644 index 000000000..58cc7a38a --- /dev/null +++ b/gr-qtgui/lib/qtgui_time_sink_f.cc @@ -0,0 +1,197 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qtgui_time_sink_f.h> +#include <gr_io_signature.h> +#include <string.h> + +#include <QTimer> + +qtgui_time_sink_f_sptr +qtgui_make_time_sink_f (int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) +{ + return gnuradio::get_initial_sptr(new qtgui_time_sink_f (size, bw, name, + nconnections, parent)); +} + +qtgui_time_sink_f::qtgui_time_sink_f (int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_block ("time_sink_f", + gr_make_io_signature (nconnections, nconnections, sizeof(float)), + gr_make_io_signature (0, 0, 0)), + d_size(size), d_bandwidth(bw), d_name(name), + d_nconnections(nconnections), d_parent(parent) +{ + d_main_gui = NULL; + + d_index = 0; + + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(new double[d_size]); + } + + initialize(); +} + +qtgui_time_sink_f::~qtgui_time_sink_f() +{ + // d_main_gui is a qwidget destroyed with its parent + for(int i = 0; i < d_nconnections; i++) { + delete [] d_residbufs[i]; + } +} + +void +qtgui_time_sink_f::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_size, 8191); + } +} + +void +qtgui_time_sink_f::initialize() +{ + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; +} + + +void +qtgui_time_sink_f::exec_() +{ + d_qApplication->exec(); +} + +QWidget* +qtgui_time_sink_f::qwidget() +{ + return d_main_gui; +} + +PyObject* +qtgui_time_sink_f::pyqwidget() +{ + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; +} + +void +qtgui_time_sink_f::set_time_domain_axis(double min, double max) +{ + d_main_gui->setTimeDomainAxis(min, max); +} + +void +qtgui_time_sink_f::set_update_time(double t) +{ + d_update_time = t; + d_main_gui->setUpdateTime(d_update_time); +} + +void +qtgui_time_sink_f::set_title(int which, const std::string &title) +{ + d_main_gui->setTitle(which, title.c_str()); +} + +void +qtgui_time_sink_f::set_color(int which, const std::string &color) +{ + d_main_gui->setColor(which, color.c_str()); +} + +int +qtgui_time_sink_f::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int n=0, j=0, idx=0; + const float *in = (const float*)input_items[idx]; + + for(int i=0; i < noutput_items; i+=d_size) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_size-d_index; + idx = 0; + + // If we have enough input for one full plot, do it + if(datasize >= resid) { + d_current_time = gruel::high_res_timer_now(); + + // Fill up residbufs with d_size number of items + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx++]; + for(unsigned int k = 0; k < resid; k++) { + d_residbufs[n][d_index+k] = in[j+k]; + } + } + + // Update the plot if its time + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = d_current_time; + d_qApplication->postEvent(d_main_gui, + new TimeUpdateEvent(d_residbufs, d_size)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx++]; + for(unsigned int k = 0; k < resid; k++) { + d_residbufs[n][d_index+k] = in[j+k]; + } + } + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; +} diff --git a/gr-qtgui/lib/qtgui_time_sink_f.h b/gr-qtgui/lib/qtgui_time_sink_f.h new file mode 100644 index 000000000..632246c6e --- /dev/null +++ b/gr-qtgui/lib/qtgui_time_sink_f.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_F_H +#define INCLUDED_QTGUI_TIME_SINK_F_H + +#include <Python.h> +#include <gr_qtgui_api.h> +#include <gr_block.h> +#include <gr_firdes.h> +#include <gri_fft.h> +#include <qapplication.h> +#include <timedisplayform.h> + +class qtgui_time_sink_f; +typedef boost::shared_ptr<qtgui_time_sink_f> qtgui_time_sink_f_sptr; + +GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, + const std::string &name, + int nconnectons=1, + QWidget *parent=NULL); + +class GR_QTGUI_API qtgui_time_sink_f : public gr_block +{ +private: + friend GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent); + qtgui_time_sink_f(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_size; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + int d_index; + std::vector<double*> d_residbufs; + + double d_update_time; + + QWidget *d_parent; + TimeDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_current_time; + gruel::high_res_timer_type d_last_time; + +public: + ~qtgui_time_sink_f(); + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_time_domain_axis(double min, double max); + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + + QApplication *d_qApplication; + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_QTGUI_TIME_SINK_F_H */ diff --git a/gr-qtgui/lib/qtgui_util.h b/gr-qtgui/lib/qtgui_util.h index a519c66a2..5b129c7b5 100644 --- a/gr-qtgui/lib/qtgui_util.h +++ b/gr-qtgui/lib/qtgui_util.h @@ -24,12 +24,12 @@ #define INCLUDED_QTGUI_UTIL_H #include <qevent.h> - +#include <gr_qtgui_api.h> #include <qwt_plot_picker.h> #include <qwt_picker_machine.h> -class QwtDblClickPlotPicker: public QwtPlotPicker +class GR_QTGUI_API QwtDblClickPlotPicker: public QwtPlotPicker { public: QwtDblClickPlotPicker(QwtPlotCanvas *); @@ -38,7 +38,7 @@ public: virtual QwtPickerMachine * stateMachine(int) const; }; -class QwtPickerDblClickPointMachine: public QwtPickerMachine +class GR_QTGUI_API QwtPickerDblClickPointMachine: public QwtPickerMachine { public: QwtPickerDblClickPointMachine(); diff --git a/gr-qtgui/lib/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc index 53a205fb7..9be2f5357 100644 --- a/gr-qtgui/lib/spectrumUpdateEvents.cc +++ b/gr-qtgui/lib/spectrumUpdateEvents.cc @@ -8,10 +8,10 @@ SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints, const double* realTimeDomainPoints, const double* imagTimeDomainPoints, const uint64_t numTimeDomainDataPoints, - const timespec dataTimestamp, + const gruel::high_res_timer_type dataTimestamp, const bool repeatDataFlag, const bool lastOfMultipleUpdateFlag, - const timespec generatedTimestamp, + const gruel::high_res_timer_type generatedTimestamp, const int droppedFFTFrames) : QEvent(QEvent::Type(10005)) { @@ -90,7 +90,7 @@ SpectrumUpdateEvent::getNumTimeDomainDataPoints() const return _numTimeDomainDataPoints; } -timespec +gruel::high_res_timer_type SpectrumUpdateEvent::getDataTimestamp() const { return _dataTimestamp; @@ -108,7 +108,7 @@ SpectrumUpdateEvent::getLastOfMultipleUpdateFlag() const return _lastOfMultipleUpdateFlag; } -timespec +gruel::high_res_timer_type SpectrumUpdateEvent::getEventGeneratedTimestamp() const { return _eventGeneratedTimestamp; @@ -177,4 +177,47 @@ SpectrumFrequencyRangeEvent::GetStopFrequency() const return _stopFrequency; } + +/***************************************************************************/ +#include <iostream> +TimeUpdateEvent::TimeUpdateEvent(const std::vector<double*> timeDomainPoints, + const uint64_t numTimeDomainDataPoints) + : QEvent(QEvent::Type(10005)) +{ + if(numTimeDomainDataPoints < 1) { + _numTimeDomainDataPoints = 1; + } + else { + _numTimeDomainDataPoints = numTimeDomainDataPoints; + } + + _nplots = timeDomainPoints.size(); + for(size_t i = 0; i < _nplots; i++) { + _dataTimeDomainPoints.push_back(new double[_numTimeDomainDataPoints]); + if(numTimeDomainDataPoints > 0) { + memcpy(_dataTimeDomainPoints[i], timeDomainPoints[i], + _numTimeDomainDataPoints*sizeof(double)); + } + } +} + +TimeUpdateEvent::~TimeUpdateEvent() +{ + for(size_t i = 0; i < _nplots; i++) { + delete[] _dataTimeDomainPoints[i]; + } +} + +const std::vector<double*> +TimeUpdateEvent::getTimeDomainPoints() const +{ + return _dataTimeDomainPoints; +} + +uint64_t +TimeUpdateEvent::getNumTimeDomainDataPoints() const +{ + return _numTimeDomainDataPoints; +} + #endif /* SPECTRUM_UPDATE_EVENTS_C */ diff --git a/gr-qtgui/lib/spectrumUpdateEvents.h b/gr-qtgui/lib/spectrumUpdateEvents.h index ccc072c3e..5a17657b7 100644 --- a/gr-qtgui/lib/spectrumUpdateEvents.h +++ b/gr-qtgui/lib/spectrumUpdateEvents.h @@ -5,7 +5,8 @@ #include <QEvent> #include <QString> #include <complex> -#include <highResTimeFunctions.h> +#include <vector> +#include <gruel/high_res_timer.h> class SpectrumUpdateEvent:public QEvent{ @@ -15,10 +16,10 @@ public: const double* realTimeDomainPoints, const double* imagTimeDomainPoints, const uint64_t numTimeDomainDataPoints, - const timespec dataTimestamp, + const gruel::high_res_timer_type dataTimestamp, const bool repeatDataFlag, const bool lastOfMultipleUpdateFlag, - const timespec generatedTimestamp, + const gruel::high_res_timer_type generatedTimestamp, const int droppedFFTFrames); ~SpectrumUpdateEvent(); @@ -28,10 +29,10 @@ public: const double* getImagTimeDomainPoints() const; uint64_t getNumFFTDataPoints() const; uint64_t getNumTimeDomainDataPoints() const; - timespec getDataTimestamp() const; + gruel::high_res_timer_type getDataTimestamp() const; bool getRepeatDataFlag() const; bool getLastOfMultipleUpdateFlag() const; - timespec getEventGeneratedTimestamp() const; + gruel::high_res_timer_type getEventGeneratedTimestamp() const; int getDroppedFFTFrames() const; protected: @@ -42,10 +43,10 @@ private: double* _imagDataTimeDomainPoints; uint64_t _numFFTDataPoints; uint64_t _numTimeDomainDataPoints; - timespec _dataTimestamp; + gruel::high_res_timer_type _dataTimestamp; bool _repeatDataFlag; bool _lastOfMultipleUpdateFlag; - timespec _eventGeneratedTimestamp; + gruel::high_res_timer_type _eventGeneratedTimestamp; int _droppedFFTFrames; }; @@ -89,4 +90,27 @@ private: }; +class TimeUpdateEvent: public QEvent +{ +public: + TimeUpdateEvent(const std::vector<double*> timeDomainPoints, + const uint64_t numTimeDomainDataPoints); + + ~TimeUpdateEvent(); + + int which() const; + const std::vector<double*> getTimeDomainPoints() const; + uint64_t getNumTimeDomainDataPoints() const; + timespec getDataTimestamp() const; + bool getRepeatDataFlag() const; + +protected: + +private: + size_t _nplots; + std::vector<double*> _dataTimeDomainPoints; + uint64_t _numTimeDomainDataPoints; +}; + + #endif /* SPECTRUM_UPDATE_EVENTS_H */ diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index 238c9889f..0e8594029 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #include <cmath> #include <QColorDialog> #include <QMessageBox> @@ -14,13 +36,16 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame); _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame); - _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame); + _timeDomainDisplayPlot = new TimeDomainDisplayPlot(2, TimeDomainDisplayFrame); _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame); _numRealDataPoints = 1024; _realFFTDataPoints = new double[_numRealDataPoints]; _averagedValues = new double[_numRealDataPoints]; _historyVector = new std::vector<double*>; + _timeDomainDisplayPlot->setTitle(0, "real"); + _timeDomainDisplayPlot->setTitle(1, "imag"); + AvgLineEdit->setRange(0, 500); // Set range of Average box value from 0 to 500 MinHoldCheckBox_toggled( false ); MaxHoldCheckBox_toggled( false ); @@ -119,13 +144,17 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent); const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints(); const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints(); - const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints(); - const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints(); const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints(); - const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp(); + const gruel::high_res_timer_type dataTimestamp = spectrumUpdateEvent->getDataTimestamp(); const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag(); const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag(); - const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp(); + const gruel::high_res_timer_type generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp(); + double* realTimeDomainDataPoints = (double*)spectrumUpdateEvent->getRealTimeDomainPoints(); + double* imagTimeDomainDataPoints = (double*)spectrumUpdateEvent->getImagTimeDomainPoints(); + + std::vector<double*> timeDomainDataPoints; + timeDomainDataPoints.push_back(realTimeDomainDataPoints); + timeDomainDataPoints.push_back(imagTimeDomainDataPoints); // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true... ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints); @@ -210,11 +239,10 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate _peakAmplitude, d_update_time); } if(tabindex == d_plot_time) { - _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, - imagTimeDomainDataPoints, + _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints, numTimeDomainDataPoints, d_update_time); - } + } if(tabindex == d_plot_constellation) { _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, imagTimeDomainDataPoints, @@ -673,7 +701,7 @@ SpectrumDisplayForm::ToggleTabConstellation(const bool state) void SpectrumDisplayForm::SetTimeDomainAxis(double min, double max) { - _timeDomainDisplayPlot->set_yaxis(min, max); + _timeDomainDisplayPlot->setYaxis(min, max); } void diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h index 860edf2d1..30303a36f 100644 --- a/gr-qtgui/lib/spectrumdisplayform.h +++ b/gr-qtgui/lib/spectrumdisplayform.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef SPECTRUM_DISPLAY_FORM_H #define SPECTRUM_DISPLAY_FORM_H diff --git a/gr-qtgui/lib/timedisplayform.cc b/gr-qtgui/lib/timedisplayform.cc new file mode 100644 index 000000000..cc4ac9951 --- /dev/null +++ b/gr-qtgui/lib/timedisplayform.cc @@ -0,0 +1,177 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cmath> +#include <QColorDialog> +#include <QMessageBox> +#include <timedisplayform.h> +#include <iostream> + +TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) + : QWidget(parent) +{ + _systemSpecifiedFlag = false; + _intValidator = new QIntValidator(this); + _intValidator->setBottom(0); + + _layout = new QGridLayout(this); + _timeDomainDisplayPlot = new TimeDomainDisplayPlot(nplots, this); + _layout->addWidget(_timeDomainDisplayPlot, 0, 0); + + _numRealDataPoints = 1024; + + setLayout(_layout); + + Reset(); + + // Create a timer to update plots at the specified rate + displayTimer = new QTimer(this); + connect(displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer())); + + connect(_timeDomainDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onTimePlotPointSelected(const QPointF))); +} + +TimeDisplayForm::~TimeDisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + delete _intValidator; + + displayTimer->stop(); + delete displayTimer; +} + +void +TimeDisplayForm::newData( const TimeUpdateEvent* spectrumUpdateEvent) +{ + const std::vector<double*> timeDomainDataPoints = spectrumUpdateEvent->getTimeDomainPoints(); + const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints(); + + _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints, + numTimeDomainDataPoints, + d_update_time); +} + +void +TimeDisplayForm::resizeEvent( QResizeEvent *e ) +{ + QSize s = size(); + emit _timeDomainDisplayPlot->resizeSlot(&s); +} + +void +TimeDisplayForm::customEvent( QEvent * e) +{ + if(e->type() == 10005) { + TimeUpdateEvent* timeUpdateEvent = (TimeUpdateEvent*)e; + newData(timeUpdateEvent); + } + //else if(e->type() == 10008){ + //setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel()); + //} + //else if(e->type() == 10009){ + //Reset(); + //if(_systemSpecifiedFlag){ + // _system->ResetPendingGUIUpdateEvents(); + //} + //} +} + +void +TimeDisplayForm::updateGuiTimer() +{ + _timeDomainDisplayPlot->canvas()->update(); +} + +void +TimeDisplayForm::onTimePlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 3); +} + +void +TimeDisplayForm::setFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency) +{ + double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency)); + + if(fdiff > 0) { + std::string strtime[4] = {"sec", "ms", "us", "ns"}; + double units10 = floor(log10(fdiff)); + double units3 = std::max(floor(units10 / 3.0), 0.0); + double units = pow(10, (units10-fmod(units10, 3.0))); + int iunit = static_cast<int>(units3); + + _startFrequency = newStartFrequency; + _stopFrequency = newStopFrequency; + + _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency, + units, strtime[iunit]); + } +} + +void +TimeDisplayForm::Reset() +{ +} + + +void +TimeDisplayForm::closeEvent( QCloseEvent *e ) +{ + //if(_systemSpecifiedFlag){ + // _system->SetWindowOpenFlag(false); + //} + + qApp->processEvents(); + + QWidget::closeEvent(e); +} + +void +TimeDisplayForm::setTimeDomainAxis(double min, double max) +{ + _timeDomainDisplayPlot->setYaxis(min, max); +} + +void +TimeDisplayForm::setUpdateTime(double t) +{ + d_update_time = t; + // QTimer class takes millisecond input + displayTimer->start(d_update_time*1000); +} + +void +TimeDisplayForm::setTitle(int which, QString title) +{ + _timeDomainDisplayPlot->setTitle(which, title); +} + +void +TimeDisplayForm::setColor(int which, QString color) +{ + _timeDomainDisplayPlot->setColor(which, color); +} diff --git a/gr-qtgui/lib/timedisplayform.h b/gr-qtgui/lib/timedisplayform.h new file mode 100644 index 000000000..1216a1ef5 --- /dev/null +++ b/gr-qtgui/lib/timedisplayform.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef TIME_DISPLAY_FORM_H +#define TIME_DISPLAY_FORM_H + +#include <spectrumUpdateEvents.h> +#include <FrequencyDisplayPlot.h> +#include <WaterfallDisplayPlot.h> +#include <TimeDomainDisplayPlot.h> +#include <ConstellationDisplayPlot.h> +#include <QtGui/QApplication> +#include <QtGui/QGridLayout> +#include <QValidator> +#include <QTimer> +#include <vector> + +class TimeDisplayForm : public QWidget +{ + Q_OBJECT + + public: + TimeDisplayForm(int nplots=1, QWidget* parent = 0); + ~TimeDisplayForm(); + + void Reset(); + +public slots: + void resizeEvent( QResizeEvent * e ); + void customEvent( QEvent * e ); + void setFrequencyRange( const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency ); + void closeEvent( QCloseEvent * e ); + + void setTimeDomainAxis(double min, double max); + + void setUpdateTime(double t); + + void setTitle(int which, QString title); + void setColor(int which, QString color); + +private slots: + void newData( const TimeUpdateEvent* ); + void updateGuiTimer(); + + void onTimePlotPointSelected(const QPointF p); + +signals: + void plotPointSelected(const QPointF p, int type); + +private: + uint64_t _numRealDataPoints; + QIntValidator* _intValidator; + + QGridLayout *_layout; + TimeDomainDisplayPlot* _timeDomainDisplayPlot; + bool _systemSpecifiedFlag; + double _startFrequency; + double _stopFrequency; + + QTimer *displayTimer; + double d_update_time; +}; + +#endif /* TIME_DISPLAY_FORM_H */ |