From befadabc2f18b483c71250adfd7dbf42f66b16f0 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 12:55:16 -0400 Subject: gr-qtgui: restructuring qtgui directory to new layout. --- gr-qtgui/lib/ConstellationDisplayPlot.cc | 193 ++++++++ gr-qtgui/lib/ConstellationDisplayPlot.h | 61 +++ gr-qtgui/lib/FrequencyDisplayPlot.cc | 439 +++++++++++++++++ gr-qtgui/lib/FrequencyDisplayPlot.h | 92 ++++ gr-qtgui/lib/Makefile.am | 110 +++++ gr-qtgui/lib/Makefile.swig.gen | 145 ++++++ gr-qtgui/lib/SpectrumGUIClass.cc | 468 ++++++++++++++++++ gr-qtgui/lib/SpectrumGUIClass.h | 111 +++++ gr-qtgui/lib/TimeDomainDisplayPlot.cc | 276 +++++++++++ gr-qtgui/lib/TimeDomainDisplayPlot.h | 65 +++ gr-qtgui/lib/WaterfallDisplayPlot.cc | 547 +++++++++++++++++++++ gr-qtgui/lib/WaterfallDisplayPlot.h | 84 ++++ gr-qtgui/lib/highResTimeFunctions.h | 299 ++++++++++++ gr-qtgui/lib/plot_waterfall.cc | 325 +++++++++++++ gr-qtgui/lib/plot_waterfall.h | 52 ++ gr-qtgui/lib/qtgui.h | 71 +++ gr-qtgui/lib/qtgui.i | 131 +++++ gr-qtgui/lib/qtgui_sink_c.cc | 326 +++++++++++++ gr-qtgui/lib/qtgui_sink_c.h | 127 +++++ gr-qtgui/lib/qtgui_sink_f.cc | 321 +++++++++++++ gr-qtgui/lib/qtgui_sink_f.h | 125 +++++ gr-qtgui/lib/spectrumUpdateEvents.cc | 180 +++++++ gr-qtgui/lib/spectrumUpdateEvents.h | 92 ++++ gr-qtgui/lib/spectrumdisplayform.cc | 691 +++++++++++++++++++++++++++ gr-qtgui/lib/spectrumdisplayform.h | 114 +++++ gr-qtgui/lib/spectrumdisplayform.ui | 788 +++++++++++++++++++++++++++++++ gr-qtgui/lib/waterfallGlobalData.cc | 164 +++++++ gr-qtgui/lib/waterfallGlobalData.h | 47 ++ 28 files changed, 6444 insertions(+) create mode 100644 gr-qtgui/lib/ConstellationDisplayPlot.cc create mode 100644 gr-qtgui/lib/ConstellationDisplayPlot.h create mode 100644 gr-qtgui/lib/FrequencyDisplayPlot.cc create mode 100644 gr-qtgui/lib/FrequencyDisplayPlot.h create mode 100644 gr-qtgui/lib/Makefile.am create mode 100644 gr-qtgui/lib/Makefile.swig.gen create mode 100644 gr-qtgui/lib/SpectrumGUIClass.cc create mode 100644 gr-qtgui/lib/SpectrumGUIClass.h create mode 100644 gr-qtgui/lib/TimeDomainDisplayPlot.cc create mode 100644 gr-qtgui/lib/TimeDomainDisplayPlot.h create mode 100644 gr-qtgui/lib/WaterfallDisplayPlot.cc create mode 100644 gr-qtgui/lib/WaterfallDisplayPlot.h create mode 100644 gr-qtgui/lib/highResTimeFunctions.h create mode 100644 gr-qtgui/lib/plot_waterfall.cc create mode 100644 gr-qtgui/lib/plot_waterfall.h create mode 100644 gr-qtgui/lib/qtgui.h create mode 100644 gr-qtgui/lib/qtgui.i create mode 100644 gr-qtgui/lib/qtgui_sink_c.cc create mode 100644 gr-qtgui/lib/qtgui_sink_c.h create mode 100644 gr-qtgui/lib/qtgui_sink_f.cc create mode 100644 gr-qtgui/lib/qtgui_sink_f.h create mode 100644 gr-qtgui/lib/spectrumUpdateEvents.cc create mode 100644 gr-qtgui/lib/spectrumUpdateEvents.h create mode 100644 gr-qtgui/lib/spectrumdisplayform.cc create mode 100644 gr-qtgui/lib/spectrumdisplayform.h create mode 100644 gr-qtgui/lib/spectrumdisplayform.ui create mode 100644 gr-qtgui/lib/waterfallGlobalData.cc create mode 100644 gr-qtgui/lib/waterfallGlobalData.h (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc new file mode 100644 index 000000000..9ad5bdd3c --- /dev/null +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -0,0 +1,193 @@ +#ifndef CONSTELLATION_DISPLAY_PLOT_C +#define CONSTELLATION_DISPLAY_PLOT_C + +#include + +#include +#include + + +class ConstellationDisplayZoomer: public QwtPlotZoomer +{ +public: + ConstellationDisplayZoomer(QwtPlotCanvas* canvas):QwtPlotZoomer(canvas) + { + setTrackerMode(QwtPicker::AlwaysOn); + } + + virtual ~ConstellationDisplayZoomer(){ + + } + + virtual void updateTrackerText(){ + updateDisplay(); + } + +protected: + using QwtPlotZoomer::trackerText; + virtual QwtText trackerText( const QwtDoublePoint& p ) const + { + QwtText t(QString("(%1, %2)").arg(p.x(), 0, 'f', 4). + arg(p.y(), 0, 'f', 4)); + return t; + } +}; + +ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) + : QwtPlot(parent) +{ + timespec_reset(&_lastReplot); + + resize(parent->width(), parent->height()); + + _numPoints = 1024; + _penSize = 5; + _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); + set_xaxis(-2.0, 2.0); + setAxisTitle(QwtPlot::xBottom, "In-phase"); + + setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); + set_yaxis(-2.0, 2.0); + setAxisTitle(QwtPlot::yLeft, "Quadrature"); + + // Automatically deleted when parent is deleted + _plot_curve = new QwtPlotCurve("Constellation Points"); + _plot_curve->attach(this); + _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + _plot_curve->setStyle(QwtPlotCurve::Dots); + _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); + + 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::set_pen_size(int size) +{ + if(size > 0 && size < 30){ + _penSize = size; + _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + } +} + + +void +ConstellationDisplayPlot::set_xaxis(double min, double max) +{ + setAxisScale(QwtPlot::xBottom, min, max); +} + +void +ConstellationDisplayPlot::set_yaxis(double min, double max) +{ + setAxisScale(QwtPlot::yLeft, min, max); +} + +void +ConstellationDisplayPlot::set_axis(double xmin, double xmax, + double ymin, double ymax) +{ + set_xaxis(xmin, xmax); + set_yaxis(ymin, ymax); +} + +void ConstellationDisplayPlot::replot() +{ + QwtPlot::replot(); +} + +void +ConstellationDisplayPlot::resizeSlot( QSize *s ) +{ + resize(s->width(), s->height()); +} + +void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, + const double* imagDataPoints, + const int64_t numDataPoints, + const double timeInterval) +{ + if((numDataPoints > 0) && + (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { + + 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)); + + 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/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h new file mode 100644 index 000000000..a441a8bfe --- /dev/null +++ b/gr-qtgui/lib/ConstellationDisplayPlot.h @@ -0,0 +1,61 @@ +#ifndef CONSTELLATION_DISPLAY_PLOT_HPP +#define CONSTELLATION_DISPLAY_PLOT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ConstellationDisplayPlot : public QwtPlot +{ + Q_OBJECT + +public: + ConstellationDisplayPlot(QWidget*); + virtual ~ConstellationDisplayPlot(); + + void PlotNewData(const double* realDataPoints, + const double* imagDataPoints, + const int64_t numDataPoints, + const double timeInterval); + + virtual void replot(); + + void set_xaxis(double min, double max); + void set_yaxis(double min, double max); + void set_axis(double xmin, double xmax, + double ymin, double ymax); + void set_pen_size(int size); + +public slots: + void resizeSlot( QSize *s ); + +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; + int64_t _penSize; +}; + +#endif /* CONSTELLATION_DISPLAY_PLOT_HPP */ diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc new file mode 100644 index 000000000..d150e2e4c --- /dev/null +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -0,0 +1,439 @@ +#ifndef FREQUENCY_DISPLAY_PLOT_C +#define FREQUENCY_DISPLAY_PLOT_C + +#include + +#include + +class FreqPrecisionClass +{ +public: + FreqPrecisionClass(const int freqPrecision) + { + _frequencyPrecision = freqPrecision; + } + + virtual ~FreqPrecisionClass() + { + } + + virtual unsigned int GetFrequencyPrecision() const + { + return _frequencyPrecision; + } + + virtual void SetFrequencyPrecision(const unsigned int newPrecision) + { + _frequencyPrecision = newPrecision; + } +protected: + unsigned int _frequencyPrecision; + +private: + +}; + +class FreqDisplayScaleDraw: public QwtScaleDraw, public FreqPrecisionClass +{ +public: + FreqDisplayScaleDraw(const unsigned int precision) + : QwtScaleDraw(), FreqPrecisionClass(precision) + { + } + + virtual ~FreqDisplayScaleDraw() + { + } + + virtual QwtText label(double value) const + { + return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision()); + } + +protected: + +private: + +}; + +class FreqDisplayZoomer: public QwtPlotZoomer, public FreqPrecisionClass +{ +public: + FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision) + : QwtPlotZoomer(canvas),FreqPrecisionClass(freqPrecision) + { + setTrackerMode(QwtPicker::AlwaysOn); + } + + virtual ~FreqDisplayZoomer(){ + + } + + virtual void updateTrackerText(){ + updateDisplay(); + } + + void SetUnitType(const std::string &type) + { + _unitType = type; + } + +protected: + using QwtPlotZoomer::trackerText; + virtual QwtText trackerText( const QwtDoublePoint& p ) const + { + QwtText t(QString("%1 %2, %3 dB"). + arg(p.x(), 0, 'f', GetFrequencyPrecision()). + arg(_unitType.c_str()).arg(p.y(), 0, 'f', 2)); + return t; + } + +private: + std::string _unitType; +}; + +FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) + : QwtPlot(parent) +{ + _startFrequency = 0; + _stopFrequency = 4000; + + timespec_reset(&_lastReplot); + + resize(parent->width(), parent->height()); + + _useCenterFrequencyFlag = false; + + _numPoints = 1024; + _dataPoints = new double[_numPoints]; + _minFFTPoints = new double[_numPoints]; + _maxFFTPoints = new double[_numPoints]; + _xAxisPoints = new double[_numPoints]; + + // Disable polygon clipping + 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); + + setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); + setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); + + _minYAxis = -120; + _maxYAxis = 10; + setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); + setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis); + setAxisTitle(QwtPlot::yLeft, "Power (dB)"); + + // Automatically deleted when parent is deleted + _fft_plot_curve = new QwtPlotCurve("Power Spectrum"); + _fft_plot_curve->attach(this); + _fft_plot_curve->setPen(QPen(Qt::blue)); + _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints); + + _min_fft_plot_curve = new QwtPlotCurve("Minimum Power"); + _min_fft_plot_curve->attach(this); + _min_fft_plot_curve->setPen(QPen(Qt::magenta)); + _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); + _min_fft_plot_curve->setVisible(false); + + _max_fft_plot_curve = new QwtPlotCurve("Maximum Power"); + _max_fft_plot_curve->attach(this); + _max_fft_plot_curve->setPen(QPen(Qt::darkYellow)); + _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); + _max_fft_plot_curve->setVisible(false); + + _lower_intensity_marker = new QwtPlotMarker(); + _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + _lower_intensity_marker->setLinePen(QPen(Qt::cyan)); + _lower_intensity_marker->attach(this); + + _upper_intensity_marker = new QwtPlotMarker(); + _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + _upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine)); + _upper_intensity_marker->attach(this); + + memset(_dataPoints, 0x0, _numPoints*sizeof(double)); + memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); + + for(int64_t number = 0; number < _numPoints; number++){ + _minFFTPoints[number] = 200.0; + _maxFFTPoints[number] = -280.0; + } + + // set up peak marker + QwtSymbol symbol; + + _markerPeakAmplitude = new QwtPlotMarker(); + _markerPeakAmplitude->setLinePen(QPen(Qt::yellow)); + symbol.setStyle(QwtSymbol::Diamond); + symbol.setSize(8); + symbol.setPen(QPen(Qt::yellow)); + symbol.setBrush(QBrush(Qt::yellow)); + _markerPeakAmplitude->setSymbol(symbol); + _markerPeakAmplitude->attach(this); + + _markerNoiseFloorAmplitude = new QwtPlotMarker(); + _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine); + _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine)); + _markerNoiseFloorAmplitude->attach(this); + + _peakFrequency = 0; + _peakAmplitude = -HUGE_VAL; + + _noiseFloorAmplitude = -HUGE_VAL; + + replot(); + + _zoomer = new FreqDisplayZoomer(canvas(), 0); +#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); + + // Do this after the zoomer has been built + _resetXAxisPoints(); +} + +FrequencyDisplayPlot::~FrequencyDisplayPlot() +{ + delete[] _dataPoints; + delete[] _maxFFTPoints; + delete[] _minFFTPoints; + delete[] _xAxisPoints; + + // _fft_plot_curves deleted when parent deleted + // _zoomer and _panner deleted when parent deleted +} + +void +FrequencyDisplayPlot::set_yaxis(double min, double max) +{ + // Get the new max/min values for the plot + _minYAxis = min; + _maxYAxis = max; + + // Set the axis max/min to the new values + setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis); + + // Reset the base zoom level to the new axis scale set here + _zoomer->setZoomBase(); +} + +void +FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq, + const double constStopFreq, + const double constCenterFreq, + const bool useCenterFrequencyFlag, + const double units, const std::string &strunits) +{ + double startFreq = constStartFreq / units; + double stopFreq = constStopFreq / units; + double centerFreq = constCenterFreq / units; + + _useCenterFrequencyFlag = useCenterFrequencyFlag; + + if(_useCenterFrequencyFlag){ + startFreq = (startFreq + centerFreq); + stopFreq = (stopFreq + centerFreq); + } + + bool reset = false; + if((startFreq != _startFrequency) || (stopFreq != _stopFrequency)) + reset = true; + + if(stopFreq > startFreq) { + _startFrequency = startFreq; + _stopFrequency = stopFreq; + + if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){ + double display_units = ceil(log10(units)/2.0); + setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units)); + setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str())); + + if(reset) + _resetXAxisPoints(); + + ((FreqDisplayZoomer*)_zoomer)->SetFrequencyPrecision(display_units); + ((FreqDisplayZoomer*)_zoomer)->SetUnitType(strunits); + } + } +} + + +double +FrequencyDisplayPlot::GetStartFrequency() const +{ + return _startFrequency; +} + +double +FrequencyDisplayPlot::GetStopFrequency() const +{ + return _stopFrequency; +} + +void +FrequencyDisplayPlot::replot() +{ + _markerNoiseFloorAmplitude->setYValue(_noiseFloorAmplitude); + + // Make sure to take into account the start frequency + if(_useCenterFrequencyFlag){ + _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency); + } + else{ + _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency); + } + _markerPeakAmplitude->setYValue(_peakAmplitude); + + QwtPlot::replot(); +} + +void +FrequencyDisplayPlot::resizeSlot( QSize *s ) +{ + resize(s->width(), s->height()); +} + +void +FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints, + const double noiseFloorAmplitude, const double peakFrequency, + const double peakAmplitude, const double timeInterval) +{ + // Only update plot if there is data and if the time interval has elapsed + if((numDataPoints > 0) && + (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { + + if(numDataPoints != _numPoints) { + _numPoints = numDataPoints; + + delete[] _dataPoints; + delete[] _minFFTPoints; + delete[] _maxFFTPoints; + delete[] _xAxisPoints; + _dataPoints = new double[_numPoints]; + _xAxisPoints = new double[_numPoints]; + _minFFTPoints = new double[_numPoints]; + _maxFFTPoints = new double[_numPoints]; + + _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints); + _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); + _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); + + _resetXAxisPoints(); + ClearMaxData(); + ClearMinData(); + } + + memcpy(_dataPoints, dataPoints, numDataPoints*sizeof(double)); + for(int64_t point = 0; point < numDataPoints; point++){ + if(dataPoints[point] < _minFFTPoints[point]){ + _minFFTPoints[point] = dataPoints[point]; + } + if(dataPoints[point] > _maxFFTPoints[point]){ + _maxFFTPoints[point] = dataPoints[point]; + } + } + + _noiseFloorAmplitude = noiseFloorAmplitude; + _peakFrequency = peakFrequency; + _peakAmplitude = peakAmplitude; + + SetUpperIntensityLevel(_peakAmplitude); + + replot(); + + _lastReplot = get_highres_clock(); + } +} + +void +FrequencyDisplayPlot::ClearMaxData() +{ + for(int64_t number = 0; number < _numPoints; number++){ + _maxFFTPoints[number] = _minYAxis; + } +} + +void +FrequencyDisplayPlot::ClearMinData() +{ + for(int64_t number = 0; number < _numPoints; number++){ + _minFFTPoints[number] = _maxYAxis; + } +} + +void +FrequencyDisplayPlot::SetMaxFFTVisible(const bool visibleFlag) +{ + _max_fft_plot_curve->setVisible(visibleFlag); +} + +void +FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag) +{ + _min_fft_plot_curve->setVisible(visibleFlag); +} + +void +FrequencyDisplayPlot::_resetXAxisPoints() +{ + double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast(_numPoints); + double freqValue = _startFrequency; + for(int64_t loc = 0; loc < _numPoints; loc++){ + _xAxisPoints[loc] = freqValue; + freqValue += fft_bin_size; + } + + setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency); + + // Set up zoomer base for maximum unzoom x-axis + // and reset to maximum unzoom level + QwtDoubleRect zbase = _zoomer->zoomBase(); + zbase.setLeft(_startFrequency); + zbase.setRight(_stopFrequency); + _zoomer->zoom(zbase); + _zoomer->setZoomBase(zbase); + _zoomer->zoom(0); +} + +void +FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel) +{ + _lower_intensity_marker->setYValue( lowerIntensityLevel ); +} + +void +FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel) +{ + _upper_intensity_marker->setYValue( upperIntensityLevel ); +} + + +#endif /* FREQUENCY_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h new file mode 100644 index 000000000..3c22c1397 --- /dev/null +++ b/gr-qtgui/lib/FrequencyDisplayPlot.h @@ -0,0 +1,92 @@ +#ifndef FREQUENCY_DISPLAY_PLOT_HPP +#define FREQUENCY_DISPLAY_PLOT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class FrequencyDisplayPlot:public QwtPlot{ + Q_OBJECT + +public: + FrequencyDisplayPlot(QWidget*); + virtual ~FrequencyDisplayPlot(); + + void SetFrequencyRange(const double, const double, + const double, const bool, + const double units=1000.0, + const std::string &strunits = "kHz"); + double GetStartFrequency()const; + double GetStopFrequency()const; + + void PlotNewData(const double* dataPoints, const int64_t numDataPoints, + const double noiseFloorAmplitude, const double peakFrequency, + const double peakAmplitude, const double timeInterval); + + void ClearMaxData(); + void ClearMinData(); + + void SetMaxFFTVisible(const bool); + void SetMinFFTVisible(const bool); + + virtual void replot(); + + void set_yaxis(double min, double max); + +public slots: + void resizeSlot( QSize *e ); + void SetLowerIntensityLevel(const double); + void SetUpperIntensityLevel(const double); + +protected: + +private: + + void _resetXAxisPoints(); + + double _startFrequency; + double _stopFrequency; + double _maxYAxis; + double _minYAxis; + + QwtPlotCurve* _fft_plot_curve; + QwtPlotCurve* _min_fft_plot_curve; + QwtPlotCurve* _max_fft_plot_curve; + + QwtPlotMarker* _lower_intensity_marker; + QwtPlotMarker* _upper_intensity_marker; + + QwtPlotPanner* _panner; + QwtPlotZoomer* _zoomer; + + QwtPlotMarker *_markerPeakAmplitude; + QwtPlotMarker *_markerNoiseFloorAmplitude; + + double* _dataPoints; + double* _xAxisPoints; + + double* _minFFTPoints; + double* _maxFFTPoints; + int64_t _numPoints; + + double _peakFrequency; + double _peakAmplitude; + + double _noiseFloorAmplitude; + + timespec _lastReplot; + + bool _useCenterFrequencyFlag; +}; + +#endif /* FREQUENCY_DISPLAY_PLOT_HPP */ diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am new file mode 100644 index 000000000..446a07fd0 --- /dev/null +++ b/gr-qtgui/lib/Makefile.am @@ -0,0 +1,110 @@ +# +# Copyright 2008,2009,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. +# + +include $(top_srcdir)/Makefile.common +include $(top_srcdir)/Makefile.swig + +EXTRA_DIST += spectrumdisplayform.ui + +AM_CPPFLAGS = -I. $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \ + $(QT_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES) + +# 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 \ + FrequencyDisplayPlot.moc.cc \ + TimeDomainDisplayPlot.moc.cc \ + WaterfallDisplayPlot.moc.cc \ + ConstellationDisplayPlot.moc.cc \ + spectrumdisplayform.ui.h + +BUILT_SOURCES += $(QMAKE_SOURCES) + +# Build the normal library for C++ apps to link against +lib_LTLIBRARIES = libgnuradio-qtgui.la + +# These are the source files that go into the shared library +libgnuradio_qtgui_la_SOURCES = \ + FrequencyDisplayPlot.cc \ + TimeDomainDisplayPlot.cc \ + WaterfallDisplayPlot.cc \ + waterfallGlobalData.cc \ + ConstellationDisplayPlot.cc \ + spectrumdisplayform.cc \ + SpectrumGUIClass.cc \ + spectrumUpdateEvents.cc \ + plot_waterfall.cc \ + qtgui_sink_c.cc \ + qtgui_sink_f.cc + +nodist_libgnuradio_qtgui_la_SOURCES=$(QMAKE_SOURCES) + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + FrequencyDisplayPlot.h \ + TimeDomainDisplayPlot.h \ + WaterfallDisplayPlot.h \ + waterfallGlobalData.h \ + ConstellationDisplayPlot.h \ + highResTimeFunctions.h \ + plot_waterfall.h \ + spectrumdisplayform.h \ + SpectrumGUIClass.h \ + spectrumUpdateEvents.h \ + qtgui.h \ + qtgui_sink_c.h \ + qtgui_sink_f.h + +QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB +%.moc.cc : %.h + $(QT_MOC_EXEC) $(QT_MOC_FLAGS) -p $(srcdir) $< -o $@ + +%.ui.h : %.ui + $(QT_UIC_EXEC) $< -o $@ + +# magic flags +libgnuradio_qtgui_la_LDFLAGS = $(NO_UNDEFINED) $(BOOST_LDFLAGS) $(LTVERSIONFLAGS) + +libgnuradio_qtgui_la_LIBADD = \ + $(GNURADIO_CORE_LA) \ + $(BOOST_THREAD_LIB) \ + $(BOOST_DATE_TIME_LIB) \ + -lstdc++ \ + $(QT_LIBS) + + +############################## +# SWIG interfaces and libraries + +TOP_SWIG_IFILES = \ + qtgui.i + +# Install so that they end up available as: +# import gnuradio.qtgui +# This ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio +qtgui_pythondir_category = \ + gnuradio/qtgui + +# additional libraries for linking with the SWIG-generated library +qtgui_la_swig_libadd = \ + libgnuradio-qtgui.la diff --git a/gr-qtgui/lib/Makefile.swig.gen b/gr-qtgui/lib/Makefile.swig.gen new file mode 100644 index 000000000..9c4c0b58c --- /dev/null +++ b/gr-qtgui/lib/Makefile.swig.gen @@ -0,0 +1,145 @@ +# -*- Makefile -*- +# +# Copyright 2009 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. +# + +# Makefile.swig.gen for qtgui.i + +## Default install locations for these files: +## +## Default location for the Python directory is: +## ${prefix}/lib/python${python_version}/site-packages/[category]/qtgui +## Default location for the Python exec directory is: +## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/qtgui +## +## The following can be overloaded to change the install location, but +## this has to be done in the including Makefile.am -before- +## Makefile.swig is included. + +qtgui_pythondir_category ?= gnuradio/qtgui +qtgui_pylibdir_category ?= $(qtgui_pythondir_category) +qtgui_pythondir = $(pythondir)/$(qtgui_pythondir_category) +qtgui_pylibdir = $(pyexecdir)/$(qtgui_pylibdir_category) + +# The .so libraries for the guile modules get installed whereever guile +# is installed, usually /usr/lib/guile/gnuradio/ +# FIXME: determince whether these should be installed with gnuradio. +qtgui_scmlibdir = $(libdir) + +# The scm files for the guile modules get installed where ever guile +# is installed, usually /usr/share/guile/site/qtgui +# FIXME: determince whether these should be installed with gnuradio. +qtgui_scmdir = $(guiledir) + +## SWIG headers are always installed into the same directory. + +qtgui_swigincludedir = $(swigincludedir) + +## This is a template file for a "generated" Makefile addition (in +## this case, "Makefile.swig.gen"). By including the top-level +## Makefile.swig, this file will be used to generate the SWIG +## dependencies. Assign the variable TOP_SWIG_FILES to be the list of +## SWIG .i files to generated wrappings for; there can be more than 1 +## so long as the names are unique (no sorting is done on the +## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i +## file will generate .cc, .py, and possibly .h files -- meaning that +## all of these files will have the same base name (that provided for +## the SWIG .i file). +## +## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the +## right thing. For more info, see < +## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > + +## Other cleaned files: dependency files generated by SWIG or this Makefile + +MOSTLYCLEANFILES += $(DEPDIR)/*.S* + +## Various SWIG variables. These can be overloaded in the including +## Makefile.am by setting the variable value there, then including +## Makefile.swig . + +qtgui_swiginclude_HEADERS = \ + qtgui.i \ + $(qtgui_swiginclude_headers) + +if PYTHON +qtgui_pylib_LTLIBRARIES = \ + _qtgui.la + +_qtgui_la_SOURCES = \ + python/qtgui.cc \ + $(qtgui_la_swig_sources) + +qtgui_python_PYTHON = \ + qtgui.py \ + $(qtgui_python) + +_qtgui_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(qtgui_la_swig_libadd) + +_qtgui_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(qtgui_la_swig_ldflags) + +_qtgui_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(qtgui_la_swig_cxxflags) + +python/qtgui.cc: qtgui.py +qtgui.py: qtgui.i + +# Include the python dependencies for this file +-include python/qtgui.d + +endif # end of if python + +if GUILE + +qtgui_scmlib_LTLIBRARIES = \ + libguile-gnuradio-qtgui.la +libguile_gnuradio_qtgui_la_SOURCES = \ + guile/qtgui.cc \ + $(qtgui_la_swig_sources) +nobase_qtgui_scm_DATA = \ + gnuradio/qtgui.scm \ + gnuradio/qtgui-primitive.scm +libguile_gnuradio_qtgui_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(qtgui_la_swig_libadd) +libguile_gnuradio_qtgui_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(qtgui_la_swig_ldflags) +libguile_gnuradio_qtgui_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(qtgui_la_swig_cxxflags) + +guile/qtgui.cc: gnuradio/qtgui.scm +gnuradio/qtgui.scm: qtgui.i +gnuradio/qtgui-primitive.scm: gnuradio/qtgui.scm + +# Include the guile dependencies for this file +-include guile/qtgui.d + +endif # end of GUILE + + diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc new file mode 100644 index 000000000..052730fc2 --- /dev/null +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -0,0 +1,468 @@ +#ifndef SPECTRUM_GUI_CLASS_CPP +#define SPECTRUM_GUI_CLASS_CPP + +#include +//Added by qt3to4: +#include +#include + +const long SpectrumGUIClass::MAX_FFT_SIZE = 32768; +const long SpectrumGUIClass::MIN_FFT_SIZE = 1024; + +SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize, + const uint64_t fftSize, + const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency) +{ + _dataPoints = maxDataSize; + if(_dataPoints < 2){ + _dataPoints = 2; + } + _lastDataPointCount = _dataPoints; + + _fftSize = fftSize; + + _pendingGUIUpdateEventsCount = 0; + _droppedEntriesCount = 0; + + _centerFrequency = newCenterFrequency; + _startFrequency = newStartFrequency; + _stopFrequency = newStopFrequency; + + _windowType = 5; + + timespec_reset(&_lastGUIUpdateTime); + + _windowOpennedFlag = false; + _fftBuffersCreatedFlag = false; + + // Create Mutex Lock + //_windowStateLock = new MutexClass("_windowStateLock"); + + _powerValue = 1; +} + +SpectrumGUIClass::~SpectrumGUIClass() +{ + if(GetWindowOpenFlag()){ + delete _spectrumDisplayForm; + } + + if(_fftBuffersCreatedFlag){ + delete[] _fftPoints; + delete[] _realTimeDomainPoints; + delete[] _imagTimeDomainPoints; + } + + //delete _windowStateLock; +} + +void +SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, + const bool frequency, const bool waterfall, + const bool time, const bool constellation, + const bool use_openGL) +{ + //_windowStateLock->Lock(); + + if(!_windowOpennedFlag){ + + if(!_fftBuffersCreatedFlag){ + _fftPoints = new std::complex[_dataPoints]; + _realTimeDomainPoints = new double[_dataPoints]; + _imagTimeDomainPoints = new double[_dataPoints]; + _fftBuffersCreatedFlag = true; + + + memset(_fftPoints, 0x0, _dataPoints*sizeof(std::complex)); + memset(_realTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); + memset(_imagTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); + } + + // Called from the Event Thread + _spectrumDisplayForm = new SpectrumDisplayForm(use_openGL, parent); + + // Toggle Windows on/off + _spectrumDisplayForm->ToggleTabFrequency(frequency); + _spectrumDisplayForm->ToggleTabWaterfall(waterfall); + _spectrumDisplayForm->ToggleTabTime(time); + _spectrumDisplayForm->ToggleTabConstellation(constellation); + + _windowOpennedFlag = true; + + _spectrumDisplayForm->setSystem(this, _dataPoints, _fftSize); + + qApp->processEvents(); + } + + //_windowStateLock->Unlock(); + + SetDisplayTitle(_title); + Reset(); + + qApp->postEvent(_spectrumDisplayForm, + new QEvent(QEvent::Type(QEvent::User+3))); + + qApp->processEvents(); + + timespec_reset(&_lastGUIUpdateTime); + + // Draw Blank Display + UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, get_highres_clock(), true); + + // Set up the initial frequency axis settings + SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); + + // GUI Thread only + qApp->processEvents(); +} + +void +SpectrumGUIClass::Reset() +{ + if(GetWindowOpenFlag()) { + qApp->postEvent(_spectrumDisplayForm, + new SpectrumFrequencyRangeEvent(_centerFrequency, + _startFrequency, + _stopFrequency)); + qApp->postEvent(_spectrumDisplayForm, new SpectrumWindowResetEvent()); + } + _droppedEntriesCount = 0; + // Call the following function the the Spectrum Window Reset Event window + // ResetPendingGUIUpdateEvents(); +} + +void +SpectrumGUIClass::SetDisplayTitle(const std::string newString) +{ + _title.assign(newString); + + if(GetWindowOpenFlag()){ + qApp->postEvent(_spectrumDisplayForm, + new SpectrumWindowCaptionEvent(_title.c_str())); + } +} + +bool +SpectrumGUIClass::GetWindowOpenFlag() +{ + bool returnFlag = false; + //_windowStateLock->Lock(); + returnFlag = _windowOpennedFlag; + //_windowStateLock->Unlock(); + return returnFlag; +} + + +void +SpectrumGUIClass::SetWindowOpenFlag(const bool newFlag) +{ + //_windowStateLock->Lock(); + _windowOpennedFlag = newFlag; + //_windowStateLock->Unlock(); +} + +void +SpectrumGUIClass::SetFrequencyRange(const double centerFreq, + const double startFreq, + const double stopFreq) +{ + //_windowStateLock->Lock(); + _centerFrequency = centerFreq; + _startFrequency = startFreq; + _stopFrequency = stopFreq; + + _spectrumDisplayForm->SetFrequencyRange(_centerFrequency, + _startFrequency, + _stopFrequency); + //_windowStateLock->Unlock(); +} + +double +SpectrumGUIClass::GetStartFrequency() const +{ + double returnValue = 0.0; + //_windowStateLock->Lock(); + returnValue = _startFrequency; + //_windowStateLock->Unlock(); + return returnValue; +} + +double +SpectrumGUIClass::GetStopFrequency() const +{ + double returnValue = 0.0; + //_windowStateLock->Lock(); + returnValue = _stopFrequency; + //_windowStateLock->Unlock(); + return returnValue; +} + +double +SpectrumGUIClass::GetCenterFrequency() const +{ + double returnValue = 0.0; + //_windowStateLock->Lock(); + returnValue = _centerFrequency; + //_windowStateLock->Unlock(); + return returnValue; +} + + +void +SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, + const std::complex* fftBuffer, + const uint64_t inputBufferSize, + const float* realTimeDomainData, + const uint64_t realTimeDomainDataSize, + const float* complexTimeDomainData, + const uint64_t complexTimeDomainDataSize, + const timespec timestamp, + const bool lastOfMultipleFFTUpdateFlag) +{ + int64_t bufferSize = inputBufferSize; + bool repeatDataFlag = false; + if(bufferSize > _dataPoints){ + bufferSize = _dataPoints; + } + int64_t timeDomainBufferSize = 0; + + if(updateDisplayFlag){ + if((fftBuffer != NULL) && (bufferSize > 0)){ + memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex)); + } + + // Can't do a memcpy since ths is going from float to double data type + if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){ + const float* realTimeDomainDataPtr = realTimeDomainData; + + double* realTimeDomainPointsPtr = _realTimeDomainPoints; + timeDomainBufferSize = realTimeDomainDataSize; + + memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double)); + for( uint64_t number = 0; number < realTimeDomainDataSize; number++){ + *realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++; + } + } + + // Can't do a memcpy since ths is going from float to double data type + if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){ + const float* complexTimeDomainDataPtr = complexTimeDomainData; + + double* realTimeDomainPointsPtr = _realTimeDomainPoints; + double* imagTimeDomainPointsPtr = _imagTimeDomainPoints; + + timeDomainBufferSize = complexTimeDomainDataSize; + for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){ + *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; + *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; + } + } + } + + // If bufferSize is zero, then just update the display by sending over the old data + if(bufferSize < 1){ + bufferSize = _lastDataPointCount; + repeatDataFlag = true; + } + else{ + // Since there is data this time, update the count + _lastDataPointCount = bufferSize; + } + + const timespec currentTime = get_highres_clock(); + const timespec lastUpdateGUITime = GetLastGUIUpdateTime(); + + if((diff_timespec(currentTime, lastUpdateGUITime) > (4*_updateTime)) && + (GetPendingGUIUpdateEvents() > 0) && !timespec_empty(&lastUpdateGUITime)) { + // Do not update the display if too much data is pending to be displayed + _droppedEntriesCount++; + } + else{ + // Draw the Data + IncrementPendingGUIUpdateEvents(); + qApp->postEvent(_spectrumDisplayForm, + new SpectrumUpdateEvent(_fftPoints, bufferSize, + _realTimeDomainPoints, + _imagTimeDomainPoints, + timeDomainBufferSize, + timestamp, + repeatDataFlag, + lastOfMultipleFFTUpdateFlag, + currentTime, + _droppedEntriesCount)); + + // Only reset the dropped entries counter if this is not + // repeat data since repeat data is dropped by the display systems + if(!repeatDataFlag){ + _droppedEntriesCount = 0; + } + } +} + +float +SpectrumGUIClass::GetPowerValue() const +{ + float returnValue = 0; + //_windowStateLock->Lock(); + returnValue = _powerValue; + //_windowStateLock->Unlock(); + return returnValue; +} + +void +SpectrumGUIClass::SetPowerValue(const float value) +{ + //_windowStateLock->Lock(); + _powerValue = value; + //_windowStateLock->Unlock(); +} + +int +SpectrumGUIClass::GetWindowType() const +{ + int returnValue = 0; + //_windowStateLock->Lock(); + returnValue = _windowType; + //_windowStateLock->Unlock(); + return returnValue; +} + +void +SpectrumGUIClass::SetWindowType(const int newType) +{ + //_windowStateLock->Lock(); + _windowType = newType; + //_windowStateLock->Unlock(); +} + +int +SpectrumGUIClass::GetFFTSize() const +{ + int returnValue = 0; + //_windowStateLock->Lock(); + returnValue = _fftSize; + //_windowStateLock->Unlock(); + return returnValue; +} + +int +SpectrumGUIClass::GetFFTSizeIndex() const +{ + int fftsize = GetFFTSize(); + switch(fftsize) { + case(1024): return 0; break; + case(2048): return 1; break; + case(4096): return 2; break; + case(8192): return 3; break; + case(16384): return 3; break; + case(32768): return 3; break; + default: return 0; + } +} + +void +SpectrumGUIClass::SetFFTSize(const int newSize) +{ + //_windowStateLock->Lock(); + _fftSize = newSize; + //_windowStateLock->Unlock(); +} + +timespec +SpectrumGUIClass::GetLastGUIUpdateTime() const +{ + timespec returnValue; + //_windowStateLock->Lock(); + returnValue = _lastGUIUpdateTime; + //_windowStateLock->Unlock(); + return returnValue; +} + +void +SpectrumGUIClass::SetLastGUIUpdateTime(const timespec newTime) +{ + //_windowStateLock->Lock(); + _lastGUIUpdateTime = newTime; + //_windowStateLock->Unlock(); +} + +unsigned int +SpectrumGUIClass::GetPendingGUIUpdateEvents() const +{ + unsigned int returnValue = 0; + //_windowStateLock->Lock(); + returnValue = _pendingGUIUpdateEventsCount; + //_windowStateLock->Unlock(); + return returnValue; +} + +void +SpectrumGUIClass::IncrementPendingGUIUpdateEvents() +{ + //_windowStateLock->Lock(); + _pendingGUIUpdateEventsCount++; + //_windowStateLock->Unlock(); +} + +void +SpectrumGUIClass::DecrementPendingGUIUpdateEvents() +{ + //_windowStateLock->Lock(); + if(_pendingGUIUpdateEventsCount > 0){ + _pendingGUIUpdateEventsCount--; + } + //_windowStateLock->Unlock(); +} + +void +SpectrumGUIClass::ResetPendingGUIUpdateEvents() +{ + //_windowStateLock->Lock(); + _pendingGUIUpdateEventsCount = 0; + //_windowStateLock->Unlock(); +} + + +QWidget* +SpectrumGUIClass::qwidget() +{ + return (QWidget*)_spectrumDisplayForm; +} + +void +SpectrumGUIClass::SetTimeDomainAxis(double min, double max) +{ + _spectrumDisplayForm->SetTimeDomainAxis(min, max); +} + +void +SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax, + double ymin, double ymax) +{ + _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax); + +} + +void +SpectrumGUIClass::SetConstellationPenSize(int size){ + _spectrumDisplayForm->SetConstellationPenSize(size); +} + + +void +SpectrumGUIClass::SetFrequencyAxis(double min, double max) +{ + _spectrumDisplayForm->SetFrequencyAxis(min, max); +} + +void +SpectrumGUIClass::SetUpdateTime(double t) +{ + _updateTime = t; + _spectrumDisplayForm->SetUpdateTime(_updateTime); +} + + +#endif /* SPECTRUM_GUI_CLASS_CPP */ diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h new file mode 100644 index 000000000..57a749a6a --- /dev/null +++ b/gr-qtgui/lib/SpectrumGUIClass.h @@ -0,0 +1,111 @@ +#ifndef SPECTRUM_GUI_CLASS_HPP +#define SPECTRUM_GUI_CLASS_HPP + +//#include +#include +#include +#include +#include +#include + +//#include + +class SpectrumDisplayForm; +#include + +#include + +#include +#include +#include + +class SpectrumGUIClass +{ +public: + SpectrumGUIClass(const uint64_t maxDataSize, const uint64_t fftSize, + const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency); + ~SpectrumGUIClass(); + void Reset(); + + void OpenSpectrumWindow(QWidget*, + const bool frequency=true, const bool waterfall=true, + const bool time=true, const bool constellation=true, + const bool use_openGL=true); + void SetDisplayTitle(const std::string); + + bool GetWindowOpenFlag(); + void SetWindowOpenFlag(const bool); + + void SetFrequencyRange(const double, const double, const double); + double GetStartFrequency()const; + double GetStopFrequency()const; + double GetCenterFrequency()const; + + void UpdateWindow(const bool, const std::complex*, + const uint64_t, const float*, + const uint64_t, const float*, + const uint64_t, + const timespec, const bool); + + float GetPowerValue()const; + void SetPowerValue(const float); + + int GetWindowType()const; + void SetWindowType(const int); + + int GetFFTSize()const; + int GetFFTSizeIndex()const; + void SetFFTSize(const int); + + timespec GetLastGUIUpdateTime()const; + void SetLastGUIUpdateTime(const timespec); + + unsigned int GetPendingGUIUpdateEvents()const; + void IncrementPendingGUIUpdateEvents(); + void DecrementPendingGUIUpdateEvents(); + void ResetPendingGUIUpdateEvents(); + + static const long MAX_FFT_SIZE; + static const long MIN_FFT_SIZE; + + QWidget* qwidget(); + + void SetTimeDomainAxis(double min, double max); + void SetConstellationAxis(double xmin, double xmax, + double ymin, double ymax); + void SetConstellationPenSize(int size); + void SetFrequencyAxis(double min, double max); + + void SetUpdateTime(double t); + +protected: + +private: + + //MutexClass* _windowStateLock; + int64_t _dataPoints; + std::string _title; + double _centerFrequency; + double _startFrequency; + double _stopFrequency; + float _powerValue; + bool _windowOpennedFlag; + int _windowType; + int64_t _lastDataPointCount; + int _fftSize; + timespec _lastGUIUpdateTime; + unsigned int _pendingGUIUpdateEventsCount; + int _droppedEntriesCount; + bool _fftBuffersCreatedFlag; + double _updateTime; + + SpectrumDisplayForm* _spectrumDisplayForm; + + std::complex* _fftPoints; + double* _realTimeDomainPoints; + double* _imagTimeDomainPoints; +}; + +#endif /* SPECTRUM_GUI_CLASS_HPP */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc new file mode 100644 index 000000000..9c98cec5b --- /dev/null +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -0,0 +1,276 @@ +#ifndef TIME_DOMAIN_DISPLAY_PLOT_C +#define TIME_DOMAIN_DISPLAY_PLOT_C + +#include + +#include +#include + + +class TimePrecisionClass +{ +public: + TimePrecisionClass(const int timePrecision) + { + _timePrecision = timePrecision; + } + + virtual ~TimePrecisionClass() + { + } + + virtual unsigned int GetTimePrecision() const + { + return _timePrecision; + } + + virtual void SetTimePrecision(const unsigned int newPrecision) + { + _timePrecision = newPrecision; + } +protected: + unsigned int _timePrecision; +}; + + +class TimeDomainDisplayZoomer: public QwtPlotZoomer, public TimePrecisionClass +{ +public: + TimeDomainDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int timePrecision) + : QwtPlotZoomer(canvas),TimePrecisionClass(timePrecision) + { + setTrackerMode(QwtPicker::AlwaysOn); + } + + virtual ~TimeDomainDisplayZoomer(){ + + } + + virtual void updateTrackerText(){ + updateDisplay(); + } + + void SetUnitType(const std::string &type) + { + _unitType = type; + } + +protected: + using QwtPlotZoomer::trackerText; + virtual QwtText trackerText( const QwtDoublePoint& p ) const + { + QwtText t(QString("%1 %2, %3 V").arg(p.x(), 0, 'f', GetTimePrecision()). + arg(_unitType.c_str()). + arg(p.y(), 0, 'f', 4)); + + return t; + } + +private: + std::string _unitType; +}; + +TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) +{ + timespec_reset(&_lastReplot); + + resize(parent->width(), parent->height()); + + _numPoints = 1024; + _realDataPoints = new double[_numPoints]; + _imagDataPoints = new double[_numPoints]; + _xAxisPoints = new double[_numPoints]; + + _zoomer = new TimeDomainDisplayZoomer(canvas(), 0); + + // 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); + set_xaxis(0, _numPoints); + setAxisTitle(QwtPlot::xBottom, "Time (sec)"); + + setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); + set_yaxis(-2.0, 2.0); + setAxisTitle(QwtPlot::yLeft, "Normalized Voltage"); + + // 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)); + + _sampleRate = 1; + _resetXAxisPoints(); + + replot(); + +#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 ) )); +} + +TimeDomainDisplayPlot::~TimeDomainDisplayPlot(){ + delete[] _realDataPoints; + delete[] _imagDataPoints; + delete[] _xAxisPoints; + + // _fft_plot_curves deleted when parent deleted + // _zoomer and _panner deleted when parent deleted +} + +void +TimeDomainDisplayPlot::set_yaxis(double min, double max) +{ + setAxisScale(QwtPlot::yLeft, min, max); + _zoomer->setZoomBase(); +} + +void +TimeDomainDisplayPlot::set_xaxis(double min, double max) +{ + setAxisScale(QwtPlot::xBottom, min, max); + _zoomer->setZoomBase(); +} + + +void TimeDomainDisplayPlot::replot() +{ + QwtPlot::replot(); +} + +void +TimeDomainDisplayPlot::resizeSlot( QSize *s ) +{ + resize(s->width(), s->height()); +} + +void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints, + const double* imagDataPoints, + const int64_t numDataPoints, + const double timeInterval) +{ + if((numDataPoints > 0) && + (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) { + + 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); + + _resetXAxisPoints(); + } + + memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); + memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); + + replot(); + + _lastReplot = get_highres_clock(); + } +} + +void TimeDomainDisplayPlot::SetImaginaryDataVisible(const bool visibleFlag) +{ + _imag_plot_curve->setVisible(visibleFlag); +} + +void TimeDomainDisplayPlot::_resetXAxisPoints() +{ + double delt = 1.0/_sampleRate; + for(long loc = 0; loc < _numPoints; loc++){ + _xAxisPoints[loc] = loc*delt; + } + setAxisScale(QwtPlot::xBottom, 0, _numPoints*delt); + + // Set up zoomer base for maximum unzoom x-axis + // and reset to maximum unzoom level + QwtDoubleRect zbase = _zoomer->zoomBase(); + zbase.setLeft(0); + zbase.setRight(_numPoints*delt); + _zoomer->zoom(zbase); + _zoomer->setZoomBase(zbase); + _zoomer->zoom(0); +} + +void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) +{ + plotItem->setVisible(!on); +} + +void +TimeDomainDisplayPlot::SetSampleRate(double sr, double units, + const std::string &strunits) +{ + double newsr = sr/units; + if(newsr != _sampleRate) { + _sampleRate = sr/units; + _resetXAxisPoints(); + + // While we could change the displayed sigfigs based on the unit being + // displayed, I think it looks better by just setting it to 4 regardless. + //double display_units = ceil(log10(units)/2.0); + double display_units = 4; + setAxisTitle(QwtPlot::xBottom, QString("Time (%1)").arg(strunits.c_str())); + ((TimeDomainDisplayZoomer*)_zoomer)->SetTimePrecision(display_units); + ((TimeDomainDisplayZoomer*)_zoomer)->SetUnitType(strunits); + } +} + +#endif /* TIME_DOMAIN_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h new file mode 100644 index 000000000..952b5c8cf --- /dev/null +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -0,0 +1,65 @@ +#ifndef TIME_DOMAIN_DISPLAY_PLOT_HPP +#define TIME_DOMAIN_DISPLAY_PLOT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class TimeDomainDisplayPlot:public QwtPlot{ + Q_OBJECT + +public: + TimeDomainDisplayPlot(QWidget*); + virtual ~TimeDomainDisplayPlot(); + + void PlotNewData(const double* realDataPoints, const double* imagDataPoints, + 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 resizeSlot( QSize *s ); + void SetSampleRate(double sr, double units, + const std::string &strunits); + +protected slots: + void LegendEntryChecked(QwtPlotItem *plotItem, bool on); + +protected: + +private: + void _resetXAxisPoints(); + + QwtPlotCurve* _real_plot_curve; + QwtPlotCurve* _imag_plot_curve; + + QwtPlotPanner* _panner; + QwtPlotZoomer* _zoomer; + + double* _realDataPoints; + double* _imagDataPoints; + double* _xAxisPoints; + + double _sampleRate; + + timespec _lastReplot; + + int64_t _numPoints; +}; + +#endif /* TIME_DOMAIN_DISPLAY_PLOT_HPP */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc new file mode 100644 index 000000000..a8e5361e7 --- /dev/null +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -0,0 +1,547 @@ +#ifndef WATERFALL_DISPLAY_PLOT_C +#define WATERFALL_DISPLAY_PLOT_C + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +namespace pt = boost::posix_time; + +class FreqOffsetAndPrecisionClass +{ +public: + FreqOffsetAndPrecisionClass(const int freqPrecision) + { + _frequencyPrecision = freqPrecision; + _centerFrequency = 0; + } + + virtual ~FreqOffsetAndPrecisionClass() + { + } + + virtual unsigned int GetFrequencyPrecision() const + { + return _frequencyPrecision; + } + + virtual void SetFrequencyPrecision(const unsigned int newPrecision) + { + _frequencyPrecision = newPrecision; + } + + virtual double GetCenterFrequency() const + { + return _centerFrequency; + } + + virtual void SetCenterFrequency(const double newFreq) + { + _centerFrequency = newFreq; + } + +protected: + unsigned int _frequencyPrecision; + double _centerFrequency; + +private: + +}; + +class WaterfallFreqDisplayScaleDraw: public QwtScaleDraw, public FreqOffsetAndPrecisionClass{ +public: + WaterfallFreqDisplayScaleDraw(const unsigned int precision) + : QwtScaleDraw(), FreqOffsetAndPrecisionClass(precision) + { + } + + virtual ~WaterfallFreqDisplayScaleDraw() + { + } + + QwtText label(double value) const + { + return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision()); + } + + virtual void initiateUpdate() + { + invalidateCache(); + } + +protected: + +private: + +}; + +class TimeScaleData +{ +public: + TimeScaleData() + { + timespec_reset(&_zeroTime); + _secondsPerLine = 1.0; + } + + virtual ~TimeScaleData() + { + } + + virtual timespec GetZeroTime() const + { + return _zeroTime; + } + + virtual void SetZeroTime(const timespec newTime) + { + _zeroTime = newTime; + } + + virtual void SetSecondsPerLine(const double newTime) + { + _secondsPerLine = newTime; + } + + virtual double GetSecondsPerLine() const + { + return _secondsPerLine; + } + + +protected: + timespec _zeroTime; + double _secondsPerLine; + +private: + +}; + +class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData +{ +public: + QwtTimeScaleDraw():QwtScaleDraw(),TimeScaleData() + { + } + + virtual ~QwtTimeScaleDraw() + { + } + + 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 + int 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)); + } + + virtual void initiateUpdate() + { + // Do this in one call rather than when zeroTime and secondsPerLine + // updates is to prevent the display from being updated too often... + invalidateCache(); + } + +protected: + +private: + +}; + +class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData, + public FreqOffsetAndPrecisionClass +{ +public: + WaterfallZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision) + : QwtPlotZoomer(canvas), TimeScaleData(), + FreqOffsetAndPrecisionClass(freqPrecision) + { + setTrackerMode(QwtPicker::AlwaysOn); + } + + virtual ~WaterfallZoomer() + { + } + + virtual void updateTrackerText() + { + updateDisplay(); + } + + void SetUnitType(const std::string &type) + { + _unitType = type; + } + +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 + int 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)); + + QwtText t(QString("%1 %2, %3"). + arg(p.x(), 0, 'f', GetFrequencyPrecision()). + arg(_unitType.c_str()).arg(yLabel)); + return t; + } + +private: + std::string _unitType; +}; + + +WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) + : QwtPlot(parent) +{ + _zoomer = NULL; + _startFrequency = 0; + _stopFrequency = 4000; + + resize(parent->width(), parent->height()); + _numPoints = 1024; + + _waterfallData = new WaterfallData(_startFrequency, _stopFrequency, _numPoints, 200); + + QPalette palette; + palette.setColor(canvas()->backgroundRole(), QColor("white")); + canvas()->setPalette(palette); + + setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); + setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(0)); + + setAxisTitle(QwtPlot::yLeft, "Time"); + setAxisScaleDraw(QwtPlot::yLeft, new QwtTimeScaleDraw()); + + timespec_reset(&_lastReplot); + + d_spectrogram = new PlotWaterfall(_waterfallData, "Waterfall Display"); + + _intensityColorMapType = INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR; + + QwtLinearColorMap colorMap(Qt::darkCyan, Qt::white); + colorMap.addColorStop(0.25, Qt::cyan); + colorMap.addColorStop(0.5, Qt::yellow); + colorMap.addColorStop(0.75, Qt::red); + + d_spectrogram->setColorMap(colorMap); + + d_spectrogram->attach(this); + + // LeftButton for the zooming + // MidButton for the panning + // RightButton: zoom out by 1 + // Ctrl+RighButton: zoom out to full size + + _zoomer = new WaterfallZoomer(canvas(), 0); +#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::white); + _zoomer->setRubberBandPen(c); + _zoomer->setTrackerPen(c); + + _UpdateIntensityRangeDisplay(); +} + +WaterfallDisplayPlot::~WaterfallDisplayPlot() +{ + delete _waterfallData; + delete d_spectrogram; +} + +void +WaterfallDisplayPlot::Reset() +{ + _waterfallData->ResizeData(_startFrequency, _stopFrequency, _numPoints); + _waterfallData->Reset(); + + setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency); + + // Load up the new base zoom settings + QwtDoubleRect newSize = _zoomer->zoomBase(); + newSize.setLeft(_startFrequency); + newSize.setWidth(_stopFrequency-_startFrequency); + _zoomer->zoom(newSize); + _zoomer->setZoomBase(newSize); + _zoomer->zoom(0); +} + +void +WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq, + const double constStopFreq, + const double constCenterFreq, + const bool useCenterFrequencyFlag, + const double units, const std::string &strunits) +{ + double startFreq = constStartFreq / units; + double stopFreq = constStopFreq / units; + double centerFreq = constCenterFreq / units; + + _useCenterFrequencyFlag = useCenterFrequencyFlag; + + if(_useCenterFrequencyFlag){ + startFreq = (startFreq + centerFreq); + stopFreq = (stopFreq + centerFreq); + } + + bool reset = false; + if((startFreq != _startFrequency) || (stopFreq != _stopFrequency)) + reset = true; + + if(stopFreq > startFreq) { + _startFrequency = startFreq; + _stopFrequency = stopFreq; + + if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){ + double display_units = ceil(log10(units)/2.0); + setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(display_units)); + setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str())); + + if(reset) { + Reset(); + } + + ((WaterfallZoomer*)_zoomer)->SetFrequencyPrecision(display_units); + ((WaterfallZoomer*)_zoomer)->SetUnitType(strunits); + } + } +} + + +double +WaterfallDisplayPlot::GetStartFrequency() const +{ + return _startFrequency; +} + +double +WaterfallDisplayPlot::GetStopFrequency() const +{ + return _stopFrequency; +} + +void +WaterfallDisplayPlot::PlotNewData(const double* dataPoints, + const int64_t numDataPoints, + const double timePerFFT, + const timespec timestamp, + const int droppedFrames) +{ + if(numDataPoints > 0){ + if(numDataPoints != _numPoints){ + _numPoints = numDataPoints; + + Reset(); + + d_spectrogram->invalidateCache(); + d_spectrogram->itemChanged(); + + if(isVisible()){ + replot(); + } + + _lastReplot = get_highres_clock(); + } + + if(diff_timespec(get_highres_clock(), _lastReplot) > timePerFFT) { + //FIXME: We may want to average the data between these updates to smooth display + _waterfallData->addFFTData(dataPoints, numDataPoints, droppedFrames); + _waterfallData->IncrementNumLinesToUpdate(); + + QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); + timeScale->SetSecondsPerLine(timePerFFT); + timeScale->SetZeroTime(timestamp); + + ((WaterfallZoomer*)_zoomer)->SetSecondsPerLine(timePerFFT); + ((WaterfallZoomer*)_zoomer)->SetZeroTime(timestamp); + + d_spectrogram->invalidateCache(); + d_spectrogram->itemChanged(); + + replot(); + + _lastReplot = get_highres_clock(); + } + } +} + +void +WaterfallDisplayPlot::SetIntensityRange(const double minIntensity, + const double maxIntensity) +{ + _waterfallData->setRange(QwtDoubleInterval(minIntensity, maxIntensity)); + + emit UpdatedLowerIntensityLevel(minIntensity); + emit UpdatedUpperIntensityLevel(maxIntensity); + + _UpdateIntensityRangeDisplay(); +} + +void +WaterfallDisplayPlot::replot() +{ + QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); + timeScale->initiateUpdate(); + + WaterfallFreqDisplayScaleDraw* freqScale = (WaterfallFreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom); + freqScale->initiateUpdate(); + + // Update the time axis display + if(axisWidget(QwtPlot::yLeft) != NULL){ + axisWidget(QwtPlot::yLeft)->update(); + } + + // Update the Frequency Offset Display + if(axisWidget(QwtPlot::xBottom) != NULL){ + axisWidget(QwtPlot::xBottom)->update(); + } + + if(_zoomer != NULL){ + ((WaterfallZoomer*)_zoomer)->updateTrackerText(); + } + + QwtPlot::replot(); +} + +void +WaterfallDisplayPlot::resizeSlot( QSize *s ) +{ + resize(s->width(), s->height()); +} + +int +WaterfallDisplayPlot::GetIntensityColorMapType() const +{ + return _intensityColorMapType; +} + +void +WaterfallDisplayPlot::SetIntensityColorMapType(const int newType, + const QColor lowColor, + const QColor highColor) +{ + if((_intensityColorMapType != newType) || + ((newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED) && + (lowColor.isValid() && highColor.isValid()))){ + switch(newType){ + case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:{ + _intensityColorMapType = newType; + QwtLinearColorMap colorMap(Qt::darkCyan, Qt::white); + colorMap.addColorStop(0.25, Qt::cyan); + colorMap.addColorStop(0.5, Qt::yellow); + colorMap.addColorStop(0.75, Qt::red); + d_spectrogram->setColorMap(colorMap); + break; + } + case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:{ + _intensityColorMapType = newType; + QwtLinearColorMap colorMap(Qt::black, Qt::white); + d_spectrogram->setColorMap(colorMap); + break; + } + case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:{ + _intensityColorMapType = newType; + QwtLinearColorMap colorMap(Qt::white, Qt::black); + d_spectrogram->setColorMap(colorMap); + break; + } + case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:{ + _intensityColorMapType = newType; + QwtLinearColorMap colorMap(Qt::black, Qt::white); + colorMap.addColorStop(0.5, Qt::darkRed); + d_spectrogram->setColorMap(colorMap); + break; + } + case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:{ + _userDefinedLowIntensityColor = lowColor; + _userDefinedHighIntensityColor = highColor; + _intensityColorMapType = newType; + QwtLinearColorMap colorMap(_userDefinedLowIntensityColor, _userDefinedHighIntensityColor); + d_spectrogram->setColorMap(colorMap); + break; + } + default: break; + } + + _UpdateIntensityRangeDisplay(); + } +} + +const QColor +WaterfallDisplayPlot::GetUserDefinedLowIntensityColor() const +{ + return _userDefinedLowIntensityColor; +} + +const QColor +WaterfallDisplayPlot::GetUserDefinedHighIntensityColor() const +{ + return _userDefinedHighIntensityColor; +} + +void +WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() +{ + QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight); + rightAxis->setTitle("Intensity (dB)"); + rightAxis->setColorBarEnabled(true); + rightAxis->setColorMap(d_spectrogram->data()->range(), + d_spectrogram->colorMap()); + + setAxisScale(QwtPlot::yRight, + d_spectrogram->data()->range().minValue(), + d_spectrogram->data()->range().maxValue() ); + enableAxis(QwtPlot::yRight); + + plotLayout()->setAlignCanvasToScales(true); + + // Tell the display to redraw everything + d_spectrogram->invalidateCache(); + d_spectrogram->itemChanged(); + + // Draw again + replot(); + + // Update the last replot timer + _lastReplot = get_highres_clock(); +} + +#endif /* WATERFALL_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h new file mode 100644 index 000000000..6b4e978bb --- /dev/null +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -0,0 +1,84 @@ +#ifndef WATERFALL_DISPLAY_PLOT_HPP +#define WATERFALL_DISPLAY_PLOT_HPP + +#include +#include +#include +#include +#include + +#include + +#include + +class WaterfallDisplayPlot:public QwtPlot{ + Q_OBJECT + +public: + WaterfallDisplayPlot(QWidget*); + virtual ~WaterfallDisplayPlot(); + + void Reset(); + + void SetFrequencyRange(const double, const double, + const double, const bool, + const double units=1000.0, + const std::string &strunits = "kHz"); + double GetStartFrequency()const; + double GetStopFrequency()const; + + void PlotNewData(const double* dataPoints, const int64_t numDataPoints, + const double timePerFFT, const timespec timestamp, + const int droppedFrames); + + void SetIntensityRange(const double minIntensity, const double maxIntensity); + + virtual void replot(void); + + int GetIntensityColorMapType()const; + void SetIntensityColorMapType( const int, const QColor, const QColor ); + const QColor GetUserDefinedLowIntensityColor()const; + const QColor GetUserDefinedHighIntensityColor()const; + + enum{ + INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR = 0, + INTENSITY_COLOR_MAP_TYPE_WHITE_HOT = 1, + INTENSITY_COLOR_MAP_TYPE_BLACK_HOT = 2, + INTENSITY_COLOR_MAP_TYPE_INCANDESCENT = 3, + INTENSITY_COLOR_MAP_TYPE_USER_DEFINED = 4 + }; + +public slots: + void resizeSlot( QSize *s ); + +signals: + void UpdatedLowerIntensityLevel(const double); + void UpdatedUpperIntensityLevel(const double); + +protected: + +private: + void _UpdateIntensityRangeDisplay(); + + double _startFrequency; + double _stopFrequency; + + PlotWaterfall *d_spectrogram; + + QwtPlotPanner* _panner; + QwtPlotZoomer* _zoomer; + + WaterfallData* _waterfallData; + + timespec _lastReplot; + + bool _useCenterFrequencyFlag; + + int64_t _numPoints; + + int _intensityColorMapType; + QColor _userDefinedLowIntensityColor; + QColor _userDefinedHighIntensityColor; +}; + +#endif /* WATERFALL_DISPLAY_PLOT_HPP */ diff --git a/gr-qtgui/lib/highResTimeFunctions.h b/gr-qtgui/lib/highResTimeFunctions.h new file mode 100644 index 000000000..251bbad8b --- /dev/null +++ b/gr-qtgui/lib/highResTimeFunctions.h @@ -0,0 +1,299 @@ +#ifndef HIGH_RES_TIME_FUNCTIONS_H +#define HIGH_RES_TIME_FUNCTIONS_H + +#include +#include +#include +/* 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(modf(timeValue, &seconds) * + static_cast(NSEC_PER_SEC)); + time_t sec = static_cast(seconds); + + set_normalized_timespec(&ret, sec, nsec); + + return ret; +} + +static inline double +convert_from_timespec(const timespec actual) +{ + return (static_cast(actual.tv_sec) + + (static_cast(actual.tv_nsec) / + static_cast(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; + + 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; +} + +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 +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); +} + +#endif /* HIGH_RES_TIME_FUNCTIONS_H */ diff --git a/gr-qtgui/lib/plot_waterfall.cc b/gr-qtgui/lib/plot_waterfall.cc new file mode 100644 index 000000000..2b1447e03 --- /dev/null +++ b/gr-qtgui/lib/plot_waterfall.cc @@ -0,0 +1,325 @@ +#include +#include +#include +#include "qwt_painter.h" +#include "qwt_double_interval.h" +#include "qwt_scale_map.h" +#include "qwt_color_map.h" +#include "plot_waterfall.h" + +#if QT_VERSION < 0x040000 +typedef Q3ValueVector QwtColorTable; +#else +typedef QVector QwtColorTable; +#endif + + +class PlotWaterfallImage: public QImage +{ + // This class hides some Qt3/Qt4 API differences +public: + PlotWaterfallImage(const QSize &size, QwtColorMap::Format format): +#if QT_VERSION < 0x040000 + QImage(size, format == QwtColorMap::RGB ? 32 : 8) +#else + QImage(size, format == QwtColorMap::RGB + ? QImage::Format_ARGB32 : QImage::Format_Indexed8 ) +#endif + { + } + + PlotWaterfallImage(const QImage &other): + QImage(other) + { + } + + void initColorTable(const QImage& other) + { +#if QT_VERSION < 0x040000 + const unsigned int numColors = other.numColors(); + + setNumColors(numColors); + for ( unsigned int i = 0; i < numColors; i++ ) + setColor(i, other.color(i)); +#else + setColorTable(other.colorTable()); +#endif + } + +#if QT_VERSION < 0x040000 + + void setColorTable(const QwtColorTable &colorTable) + { + setNumColors(colorTable.size()); + for ( unsigned int i = 0; i < colorTable.size(); i++ ) + setColor(i, colorTable[i]); + } + + QwtColorTable colorTable() const + { + QwtColorTable table(numColors()); + for ( int i = 0; i < numColors(); i++ ) + table[i] = color(i); + + return table; + } +#endif +}; + +class PlotWaterfall::PrivateData +{ +public: + PrivateData() + { + data = NULL; + colorMap = new QwtLinearColorMap(); + } + ~PrivateData() + { + delete colorMap; + } + + WaterfallData *data; + QwtColorMap *colorMap; +}; + +/*! + Sets the following item attributes: + - QwtPlotItem::AutoScale: true + - QwtPlotItem::Legend: false + + The z value is initialized by 8.0. + + \param title Title + + \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ() +*/ +PlotWaterfall::PlotWaterfall(WaterfallData* data, const QString &title): + QwtPlotRasterItem(title) +{ + d_data = new PrivateData(); + d_data->data = data; + +// setCachePolicy(QwtPlotRasterItem::PaintCache); + + setItemAttribute(QwtPlotItem::AutoScale, true); + setItemAttribute(QwtPlotItem::Legend, false); + + setZ(8.0); +} + +//! Destructor +PlotWaterfall::~PlotWaterfall() +{ + delete d_data; +} + +const WaterfallData* PlotWaterfall::data()const{ + return d_data->data; +} + +//! \return QwtPlotItem::Rtti_PlotSpectrogram +int PlotWaterfall::rtti() const +{ + return QwtPlotItem::Rtti_PlotSpectrogram; +} + +/*! + Change the color map + + Often it is useful to display the mapping between intensities and + colors as an additional plot axis, showing a color bar. + + \param colorMap Color Map + + \sa colorMap(), QwtScaleWidget::setColorBarEnabled(), + QwtScaleWidget::setColorMap() +*/ +void PlotWaterfall::setColorMap(const QwtColorMap &colorMap) +{ + delete d_data->colorMap; + d_data->colorMap = colorMap.copy(); + + invalidateCache(); + itemChanged(); +} + +/*! + \return Color Map used for mapping the intensity values to colors + \sa setColorMap() +*/ +const QwtColorMap &PlotWaterfall::colorMap() const +{ + return *d_data->colorMap; +} +/*! + \return Bounding rect of the data + \sa QwtRasterData::boundingRect +*/ +QwtDoubleRect PlotWaterfall::boundingRect() const +{ + return d_data->data->boundingRect(); +} + +/*! + \brief Returns the recommended raster for a given rect. + + F.e the raster hint is used to limit the resolution of + the image that is rendered. + + \param rect Rect for the raster hint + \return data().rasterHint(rect) +*/ +QSize PlotWaterfall::rasterHint(const QwtDoubleRect &rect) const +{ + return d_data->data->rasterHint(rect); +} + +/*! + \brief Render an image from the data and color map. + + The area is translated into a rect of the paint device. + For each pixel of this rect the intensity is mapped + into a color. + + \param xMap X-Scale Map + \param yMap Y-Scale Map + \param area Area that should be rendered in scale coordinates. + + \return A QImage::Format_Indexed8 or QImage::Format_ARGB32 depending + on the color map. + + \sa QwtRasterData::intensity(), QwtColorMap::rgb(), + QwtColorMap::colorIndex() +*/ +QImage PlotWaterfall::renderImage( + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QwtDoubleRect &area) const +{ + if ( area.isEmpty() ) + return QImage(); + + QRect rect = transform(xMap, yMap, area); + + QwtScaleMap xxMap = xMap; + QwtScaleMap yyMap = yMap; + + const QSize res = d_data->data->rasterHint(area); + if ( res.isValid() ) + { + /* + It is useless to render an image with a higher resolution + than the data offers. Of course someone will have to + scale this image later into the size of the given rect, but f.e. + in case of postscript this will done on the printer. + */ + rect.setSize(rect.size().boundedTo(res)); + + int px1 = rect.x(); + int px2 = rect.x() + rect.width(); + if ( xMap.p1() > xMap.p2() ) + qSwap(px1, px2); + + double sx1 = area.x(); + double sx2 = area.x() + area.width(); + if ( xMap.s1() > xMap.s2() ) + qSwap(sx1, sx2); + + int py1 = rect.y(); + int py2 = rect.y() + rect.height(); + if ( yMap.p1() > yMap.p2() ) + qSwap(py1, py2); + + double sy1 = area.y(); + double sy2 = area.y() + area.height(); + if ( yMap.s1() > yMap.s2() ) + qSwap(sy1, sy2); + + xxMap.setPaintInterval(px1, px2); + xxMap.setScaleInterval(sx1, sx2); + yyMap.setPaintInterval(py1, py2); + yyMap.setScaleInterval(sy1, sy2); + } + + PlotWaterfallImage image(rect.size(), d_data->colorMap->format()); + + const QwtDoubleInterval intensityRange = d_data->data->range(); + if ( !intensityRange.isValid() ) + return image; + + d_data->data->initRaster(area, rect.size()); + + if ( d_data->colorMap->format() == QwtColorMap::RGB ) + { + for ( int y = rect.top(); y <= rect.bottom(); y++ ) + { + const double ty = yyMap.invTransform(y); + + QRgb *line = (QRgb *)image.scanLine(y - rect.top()); + for ( int x = rect.left(); x <= rect.right(); x++ ) + { + const double tx = xxMap.invTransform(x); + + *line++ = d_data->colorMap->rgb(intensityRange, + d_data->data->value(tx, ty)); + } + } + } + else if ( d_data->colorMap->format() == QwtColorMap::Indexed ) + { + image.setColorTable(d_data->colorMap->colorTable(intensityRange)); + + for ( int y = rect.top(); y <= rect.bottom(); y++ ) + { + const double ty = yyMap.invTransform(y); + + unsigned char *line = image.scanLine(y - rect.top()); + for ( int x = rect.left(); x <= rect.right(); x++ ) + { + const double tx = xxMap.invTransform(x); + + *line++ = d_data->colorMap->colorIndex(intensityRange, + d_data->data->value(tx, ty)); + } + } + } + + d_data->data->discardRaster(); + + // Mirror the image in case of inverted maps + + const bool hInvert = xxMap.p1() > xxMap.p2(); + const bool vInvert = yyMap.p1() < yyMap.p2(); + if ( hInvert || vInvert ) + { +#ifdef __GNUC__ +#endif +#if QT_VERSION < 0x040000 + image = image.mirror(hInvert, vInvert); +#else + image = image.mirrored(hInvert, vInvert); +#endif + } + + return image; +} + +/*! + \brief Draw the spectrogram + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas in painter coordinates + + \sa setDisplayMode, renderImage, + QwtPlotRasterItem::draw, drawContourLines +*/ + +void PlotWaterfall::draw(QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRect &canvasRect) const +{ + QwtPlotRasterItem::draw(painter, xMap, yMap, canvasRect); +} + diff --git a/gr-qtgui/lib/plot_waterfall.h b/gr-qtgui/lib/plot_waterfall.h new file mode 100644 index 000000000..a11461611 --- /dev/null +++ b/gr-qtgui/lib/plot_waterfall.h @@ -0,0 +1,52 @@ +#ifndef PLOT_WATERFALL_H +#define PLOT_WATERFALL_H + +#include +#include + +#include "qwt_valuelist.h" +#include "qwt_plot_rasteritem.h" + +class QwtColorMap; + +/*! + \brief A plot item, which displays a waterfall spectrogram + + A waterfall displays threedimenional data, where the 3rd dimension + ( the intensity ) is displayed using colors. The colors are calculated + from the values using a color map. + + \sa QwtRasterData, QwtColorMap +*/ + +class PlotWaterfall: public QwtPlotRasterItem +{ +public: + explicit PlotWaterfall(WaterfallData* data, const QString &title = QString::null); + virtual ~PlotWaterfall(); + + const WaterfallData* data()const; + + void setColorMap(const QwtColorMap &); + const QwtColorMap &colorMap() const; + + virtual QwtDoubleRect boundingRect() const; + virtual QSize rasterHint(const QwtDoubleRect &) const; + + virtual int rtti() const; + + virtual void draw(QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRect &rect) const; + +protected: + virtual QImage renderImage( + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QwtDoubleRect &rect) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/gr-qtgui/lib/qtgui.h b/gr-qtgui/lib/qtgui.h new file mode 100644 index 000000000..9831697ac --- /dev/null +++ b/gr-qtgui/lib/qtgui.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,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_H +#define INCLUDED_QTGUI_H + +#include +#include +#include "SpectrumGUIClass.h" + +class qtgui_event : public QEvent +{ +private: + gruel::mutex &d_mutex; + +public: + qtgui_event(gruel::mutex &mutex) + : QEvent((QEvent::Type)(QEvent::User+101)), + d_mutex(mutex) + { + //nop + } + + void lock() + { + d_mutex.lock(); + } + + void unlock() + { + d_mutex.unlock(); + } +}; + +class qtgui_obj : public QObject +{ +public: + qtgui_obj(QObject *p) + : QObject(p) + { + } + + void customEvent(QEvent *e) + { + if(e->type() == (QEvent::Type)(QEvent::User+101)) { + qtgui_event *qt = (qtgui_event*)e; + qt->unlock(); + } + } +}; + +#endif /* INCLUDED_QTGUI_H */ diff --git a/gr-qtgui/lib/qtgui.i b/gr-qtgui/lib/qtgui.i new file mode 100644 index 000000000..bb64c6ae2 --- /dev/null +++ b/gr-qtgui/lib/qtgui.i @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%include "gnuradio.i" + +%{ +#include "qtgui_sink_c.h" +#include "qtgui_sink_f.h" +%} + +GR_SWIG_BLOCK_MAGIC(qtgui,sink_c) + + qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, + double fc=0, double bw=1.0, + const std::string &name="Display", + bool plotfreq=true, bool plotwaterfall=true, + bool plotwaterfall3d=true, bool plottime=true, + bool plotconst=true, + bool use_openGL=true, + QWidget *parent=NULL); + +class qtgui_sink_c : public gr_block +{ +private: + friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + qtgui_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + +public: + void exec_(); + PyObject* pyqwidget(); + + void set_frequency_range(const double centerfreq, + const double bandwidth); + void set_time_domain_axis(double min, double max); + void set_constellation_axis(double xmin, double xmax, + double ymin, double ymax); + void set_frequency_axis(double min, double max); + void set_constellation_pen_size(int size); +}; + + + +/*********************************************************************/ + + +GR_SWIG_BLOCK_MAGIC(qtgui,sink_f) + +qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, + double fc=0, double bw=0.0, + const std::string &name="Display", + bool plotfreq=true, bool plotwaterfall=true, + bool plotwaterfall3d=true, bool plottime=true, + bool plotconst=true, + bool use_openGL=true, + QWidget *parent=NULL); + +class qtgui_sink_f : public gr_block +{ +private: + friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + qtgui_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + +public: + void exec_(); + PyObject* pyqwidget(); + + void set_frequency_range(const double centerfreq, + const double bandwidth); + void set_time_domain_axis(double min, double max); + void set_constellation_axis(double xmin, double xmax, + double ymin, double ymax); + void set_frequency_axis(double min, double max); + void set_constellation_pen_size(int size); +}; + +#if SWIGGUILE +%scheme %{ +(load-extension-global "libguile-gnuradio-qtgui" "scm_init_gnuradio_qtgui_module") +%} + +%goops %{ +(use-modules (gnuradio gnuradio_core_runtime)) +%} +#endif diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc new file mode 100644 index 000000000..05c7b28d5 --- /dev/null +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -0,0 +1,326 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +qtgui_sink_c_sptr +qtgui_make_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent) +{ + return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype, + fc, bw, name, + plotfreq, plotwaterfall, + plotwaterfall3d, plottime, + plotconst, + use_openGL, + parent)); +} + +qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent) + : gr_block ("sink_c", + gr_make_io_signature (1, -1, sizeof(gr_complex)), + gr_make_io_signature (0, 0, 0)), + d_fftsize(fftsize), + d_wintype((gr_firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), + d_plottime(plottime), d_plotconst(plotconst), + d_parent(parent) +{ + if(plotwaterfall3d == true) { + fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); + } + + d_main_gui = NULL; + lock(); + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new gri_fft_complex (d_fftsize, true); + + d_index = 0; + d_residbuf = new gr_complex[d_fftsize]; + + buildwindow(); + + initialize(use_openGL); +} + +qtgui_sink_c::~qtgui_sink_c() +{ + delete d_main_gui; + delete [] d_residbuf; + delete d_fft; +} + +void +qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } +} + +void qtgui_sink_c::lock() +{ + d_mutex.lock(); +} + +void qtgui_sink_c::unlock() +{ + d_mutex.unlock(); +} + + +void +qtgui_sink_c::initialize(const bool opengl) +{ + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + if(d_center_freq < 0) { + throw std::runtime_error("qtgui_sink_c: Received bad center frequency.\n"); + } + + uint64_t maxBufferSize = 32768; + d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, + d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + + d_main_gui->SetDisplayTitle(d_name); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetWindowType((int)d_wintype); + + d_main_gui->OpenSpectrumWindow(d_parent, + d_plotfreq, d_plotwaterfall, + d_plottime, d_plotconst, + opengl); + + // initialize update time to 10 times a second + set_update_time(0.1); + + d_object = new qtgui_obj(d_qApplication); + qApp->postEvent(d_object, new qtgui_event(d_mutex)); +} + + +void +qtgui_sink_c::exec_() +{ + d_qApplication->exec(); +} + +QWidget* +qtgui_sink_c::qwidget() +{ + return d_main_gui->qwidget(); +} + +PyObject* +qtgui_sink_c::pyqwidget() +{ + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; +} + +void +qtgui_sink_c::set_frequency_range(const double centerfreq, + const double bandwidth) +{ + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); +} + +void +qtgui_sink_c::set_time_domain_axis(double min, double max) +{ + d_main_gui->SetTimeDomainAxis(min, max); +} + +void +qtgui_sink_c::set_constellation_axis(double xmin, double xmax, + double ymin, double ymax) +{ + d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); +} + +void +qtgui_sink_c::set_constellation_pen_size(int size) +{ + d_main_gui->SetConstellationPenSize(size); +} + + +void +qtgui_sink_c::set_frequency_axis(double min, double max) +{ + d_main_gui->SetFrequencyAxis(min, max); +} + +void +qtgui_sink_c::set_update_time(double t) +{ + d_update_time = t; + d_main_gui->SetUpdateTime(d_update_time); +} + +void +qtgui_sink_c::fft(const gr_complex *data_in, int size) +{ + if (d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + int i; + for (i = 0; i < size; i++) // apply window + dst[i] = data_in[i] * d_window[i]; + } + else { + memcpy (d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size); + } + + d_fft->execute (); // compute the fft +} + +void +qtgui_sink_c::windowreset() +{ + gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } +} + +void +qtgui_sink_c::buildwindow() +{ + d_window.clear(); + if(d_wintype != 0) { + d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76); + } +} + +void +qtgui_sink_c::fftresize() +{ + int newfftsize = d_main_gui->GetFFTSize(); + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + delete [] d_residbuf; + d_residbuf = new gr_complex[newfftsize]; + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new gri_fft_complex (d_fftsize, true); + } +} + + +int +qtgui_sink_c::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int j=0; + const gr_complex *in = (const gr_complex*)input_items[0]; + + gruel::scoped_lock lock(d_mutex); + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + const timespec currentTime = get_highres_clock(); + + // Fill up residbuf with d_fftsize number of items + memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid); + d_index = 0; + + j += resid; + fft(d_residbuf, d_fftsize); + + d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize, + NULL, 0, (float*)d_residbuf, d_fftsize, + currentTime, true); + } + // Otherwise, copy what we received into the residbuf for next time + else { + memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*datasize); + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; +} diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h new file mode 100644 index 000000000..bbf9983b0 --- /dev/null +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -0,0 +1,127 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_C_H +#define INCLUDED_QTGUI_SINK_C_H + +#include +#include +#include +#include +#include +#include +#include "SpectrumGUIClass.h" + +class qtgui_sink_c; +typedef boost::shared_ptr qtgui_sink_c_sptr; + +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 plotwaterfall3d=true, bool plottime=true, + bool plotconst=true, + bool use_openGL=true, + QWidget *parent=NULL); + +class qtgui_sink_c : public gr_block +{ +private: + friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + qtgui_sink_c (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + // use opengl to force OpenGL on or off + // this might be necessary for sessions over SSH + void initialize(const bool opengl=true); + + int d_fftsize; + gr_firdes::win_type d_wintype; + std::vector d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + + gruel::mutex d_mutex; + + bool d_shift; + gri_fft_complex *d_fft; + + int d_index; + gr_complex *d_residbuf; + + bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; + + double d_update_time; + + QWidget *d_parent; + SpectrumGUIClass *d_main_gui; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(const gr_complex *data_in, int size); + +public: + ~qtgui_sink_c(); + void exec_(); + void lock(); + void unlock(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_frequency_range(const double centerfreq, + const double bandwidth); + + void set_time_domain_axis(double min, double max); + void set_constellation_axis(double xmin, double xmax, + double ymin, double ymax); + void set_constellation_pen_size(int size); + void set_frequency_axis(double min, double max); + + void set_update_time(double t); + + QApplication *d_qApplication; + qtgui_obj *d_object; + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_QTGUI_SINK_C_H */ diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc new file mode 100644 index 000000000..984c2803c --- /dev/null +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -0,0 +1,321 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +qtgui_sink_f_sptr +qtgui_make_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent) +{ + return gnuradio::get_initial_sptr(new qtgui_sink_f (fftsize, wintype, + fc, bw, name, + plotfreq, plotwaterfall, + plotwaterfall3d, plottime, + plotconst, + use_openGL, + parent)); +} + +qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent) + : gr_block ("sink_f", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (0, 0, 0)), + d_fftsize(fftsize), + d_wintype((gr_firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), + d_plottime(plottime), d_plotconst(plotconst), + d_parent(parent) +{ + if(plotwaterfall3d == true) { + fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); + } + + d_main_gui = NULL; + lock(); + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new gri_fft_complex (d_fftsize, true); + + d_index = 0; + d_residbuf = new float[d_fftsize]; + + buildwindow(); + + initialize(use_openGL); +} + +qtgui_sink_f::~qtgui_sink_f() +{ + delete d_main_gui; + delete [] d_residbuf; + delete d_fft; +} + +void +qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } +} + +void qtgui_sink_f::lock() +{ + d_mutex.lock(); +} + +void qtgui_sink_f::unlock() +{ + d_mutex.unlock(); +} + +void +qtgui_sink_f::initialize(const bool opengl) +{ + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + + uint64_t maxBufferSize = 32768; + d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, + d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + d_main_gui->SetDisplayTitle(d_name); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetWindowType((int)d_wintype); + + d_main_gui->OpenSpectrumWindow(d_parent, + d_plotfreq, d_plotwaterfall, + d_plottime, d_plotconst, + opengl); + + // initialize update time to 10 times a second + set_update_time(0.1); + + d_object = new qtgui_obj(d_qApplication); + qApp->postEvent(d_object, new qtgui_event(d_mutex)); +} + +void +qtgui_sink_f::exec_() +{ + d_qApplication->exec(); +} + +QWidget* +qtgui_sink_f::qwidget() +{ + return d_main_gui->qwidget(); +} + +PyObject* +qtgui_sink_f::pyqwidget() +{ + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; +} + +void +qtgui_sink_f::set_frequency_range(const double centerfreq, + const double bandwidth) +{ + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); +} + +void +qtgui_sink_f::set_time_domain_axis(double min, double max) +{ + d_main_gui->SetTimeDomainAxis(min, max); +} + +void +qtgui_sink_f::set_constellation_axis(double xmin, double xmax, + double ymin, double ymax) +{ + d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); +} + +void +qtgui_sink_f::set_constellation_pen_size(int size) +{ + d_main_gui->SetConstellationPenSize(size); +} + + +void +qtgui_sink_f::set_frequency_axis(double min, double max) +{ + d_main_gui->SetFrequencyAxis(min, max); +} + +void +qtgui_sink_f::set_update_time(double t) +{ + d_update_time = t; + d_main_gui->SetUpdateTime(d_update_time); +} + +void +qtgui_sink_f::fft(const float *data_in, int size) +{ + if (d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) // apply window + dst[i] = data_in[i] * d_window[i]; + } + else { + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) // float to complex conversion + dst[i] = data_in[i]; + } + + d_fft->execute (); // compute the fft +} + +void +qtgui_sink_f::windowreset() +{ + gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } +} + +void +qtgui_sink_f::buildwindow() +{ + d_window.clear(); + if(d_wintype != 0) { + d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76); + } +} + +void +qtgui_sink_f::fftresize() +{ + int newfftsize = d_main_gui->GetFFTSize(); + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + delete [] d_residbuf; + d_residbuf = new float[newfftsize]; + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new gri_fft_complex (d_fftsize, true); + } +} + + +int +qtgui_sink_f::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int j=0; + const float *in = (const float*)input_items[0]; + + gruel::scoped_lock lock(d_mutex); + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + const timespec currentTime = get_highres_clock(); + + // Fill up residbuf with d_fftsize number of items + memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid); + d_index = 0; + + j += resid; + fft(d_residbuf, d_fftsize); + + d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize, + (float*)d_residbuf, d_fftsize, NULL, 0, + currentTime, true); + } + // Otherwise, copy what we received into the residbuf for next time + else { + memcpy(d_residbuf+d_index, &in[j], sizeof(float)*datasize); + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; +} diff --git a/gr-qtgui/lib/qtgui_sink_f.h b/gr-qtgui/lib/qtgui_sink_f.h new file mode 100644 index 000000000..d80a6a198 --- /dev/null +++ b/gr-qtgui/lib/qtgui_sink_f.h @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_F_H +#define INCLUDED_QTGUI_SINK_F_H + +#include +#include +#include +#include +#include +#include +#include "SpectrumGUIClass.h" + +class qtgui_sink_f; +typedef boost::shared_ptr qtgui_sink_f_sptr; + +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 plotwaterfall3d=true, bool plottime=true, + bool plotconst=true, + bool use_openGL=true, + QWidget *parent=NULL); + +class qtgui_sink_f : public gr_block +{ +private: + friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + qtgui_sink_f (int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plotwaterfall3d, bool plottime, + bool plotconst, + bool use_openGL, + QWidget *parent); + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(const bool opengl=true); + + int d_fftsize; + gr_firdes::win_type d_wintype; + std::vector d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + + gruel::mutex d_mutex; + + bool d_shift; + gri_fft_complex *d_fft; + + int d_index; + float *d_residbuf; + + bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; + + double d_update_time; + + QWidget *d_parent; + SpectrumGUIClass *d_main_gui; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(const float *data_in, int size); + +public: + ~qtgui_sink_f(); + void exec_(); + void lock(); + void unlock(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_frequency_range(const double centerfreq, + const double bandwidth); + + void set_time_domain_axis(double min, double max); + void set_constellation_axis(double xmin, double xmax, + double ymin, double ymax); + void set_constellation_pen_size(int size); + void set_frequency_axis(double min, double max); + + void set_update_time(double t); + + QApplication *d_qApplication; + qtgui_obj *d_object; + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_QTGUI_SINK_F_H */ diff --git a/gr-qtgui/lib/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc new file mode 100644 index 000000000..53a205fb7 --- /dev/null +++ b/gr-qtgui/lib/spectrumUpdateEvents.cc @@ -0,0 +1,180 @@ +#ifndef SPECTRUM_UPDATE_EVENTS_C +#define SPECTRUM_UPDATE_EVENTS_C + +#include + +SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex* fftPoints, + const uint64_t numFFTDataPoints, + const double* realTimeDomainPoints, + const double* imagTimeDomainPoints, + const uint64_t numTimeDomainDataPoints, + const timespec dataTimestamp, + const bool repeatDataFlag, + const bool lastOfMultipleUpdateFlag, + const timespec generatedTimestamp, + const int droppedFFTFrames) + : QEvent(QEvent::Type(10005)) +{ + if(numFFTDataPoints < 1) { + _numFFTDataPoints = 1; + } + else { + _numFFTDataPoints = numFFTDataPoints; + } + + if(numTimeDomainDataPoints < 1) { + _numTimeDomainDataPoints = 1; + } + else { + _numTimeDomainDataPoints = numTimeDomainDataPoints; + } + + _fftPoints = new std::complex[_numFFTDataPoints]; + _fftPoints[0] = std::complex(0,0); + memcpy(_fftPoints, fftPoints, numFFTDataPoints*sizeof(std::complex)); + + _realDataTimeDomainPoints = new double[_numTimeDomainDataPoints]; + memset(_realDataTimeDomainPoints, 0x0, _numTimeDomainDataPoints*sizeof(double)); + if(numTimeDomainDataPoints > 0) { + memcpy(_realDataTimeDomainPoints, realTimeDomainPoints, + numTimeDomainDataPoints*sizeof(double)); + } + + _imagDataTimeDomainPoints = new double[_numTimeDomainDataPoints]; + memset(_imagDataTimeDomainPoints, 0x0, _numTimeDomainDataPoints*sizeof(double)); + if(numTimeDomainDataPoints > 0) { + memcpy(_imagDataTimeDomainPoints, imagTimeDomainPoints, + numTimeDomainDataPoints*sizeof(double)); + } + _dataTimestamp = dataTimestamp; + _repeatDataFlag = repeatDataFlag; + _lastOfMultipleUpdateFlag = lastOfMultipleUpdateFlag; + _eventGeneratedTimestamp = generatedTimestamp; + _droppedFFTFrames = droppedFFTFrames; +} + +SpectrumUpdateEvent::~SpectrumUpdateEvent() +{ + delete[] _fftPoints; + delete[] _realDataTimeDomainPoints; + delete[] _imagDataTimeDomainPoints; +} + +const std::complex* +SpectrumUpdateEvent::getFFTPoints() const +{ + return _fftPoints; +} + +const double* +SpectrumUpdateEvent::getRealTimeDomainPoints() const +{ + return _realDataTimeDomainPoints; +} + +const double* +SpectrumUpdateEvent::getImagTimeDomainPoints() const +{ + return _imagDataTimeDomainPoints; +} + +uint64_t +SpectrumUpdateEvent::getNumFFTDataPoints() const +{ + return _numFFTDataPoints; +} + +uint64_t +SpectrumUpdateEvent::getNumTimeDomainDataPoints() const +{ + return _numTimeDomainDataPoints; +} + +timespec +SpectrumUpdateEvent::getDataTimestamp() const +{ + return _dataTimestamp; +} + +bool +SpectrumUpdateEvent::getRepeatDataFlag() const +{ + return _repeatDataFlag; +} + +bool +SpectrumUpdateEvent::getLastOfMultipleUpdateFlag() const +{ + return _lastOfMultipleUpdateFlag; +} + +timespec +SpectrumUpdateEvent::getEventGeneratedTimestamp() const +{ + return _eventGeneratedTimestamp; +} + +int +SpectrumUpdateEvent::getDroppedFFTFrames() const +{ + return _droppedFFTFrames; +} + +SpectrumWindowCaptionEvent::SpectrumWindowCaptionEvent(const QString& newLbl) + : QEvent(QEvent::Type(10008)) +{ + _labelString = newLbl; +} + +SpectrumWindowCaptionEvent::~SpectrumWindowCaptionEvent() +{ +} + +QString +SpectrumWindowCaptionEvent::getLabel() +{ + return _labelString; +} + +SpectrumWindowResetEvent::SpectrumWindowResetEvent() + : QEvent(QEvent::Type(10009)) +{ +} + +SpectrumWindowResetEvent::~SpectrumWindowResetEvent() +{ +} + +SpectrumFrequencyRangeEvent::SpectrumFrequencyRangeEvent(const double centerFreq, + const double startFreq, + const double stopFreq) + : QEvent(QEvent::Type(10010)) +{ + _centerFrequency = centerFreq; + _startFrequency = startFreq; + _stopFrequency = stopFreq; +} + +SpectrumFrequencyRangeEvent::~SpectrumFrequencyRangeEvent() +{ +} + +double +SpectrumFrequencyRangeEvent::GetCenterFrequency() const +{ + return _centerFrequency; +} + +double +SpectrumFrequencyRangeEvent::GetStartFrequency() const +{ + return _startFrequency; +} + +double +SpectrumFrequencyRangeEvent::GetStopFrequency() const +{ + return _stopFrequency; +} + +#endif /* SPECTRUM_UPDATE_EVENTS_C */ diff --git a/gr-qtgui/lib/spectrumUpdateEvents.h b/gr-qtgui/lib/spectrumUpdateEvents.h new file mode 100644 index 000000000..ccc072c3e --- /dev/null +++ b/gr-qtgui/lib/spectrumUpdateEvents.h @@ -0,0 +1,92 @@ +#ifndef SPECTRUM_UPDATE_EVENTS_H +#define SPECTRUM_UPDATE_EVENTS_H + +#include +#include +#include +#include +#include + +class SpectrumUpdateEvent:public QEvent{ + +public: + SpectrumUpdateEvent(const std::complex* fftPoints, + const uint64_t numFFTDataPoints, + const double* realTimeDomainPoints, + const double* imagTimeDomainPoints, + const uint64_t numTimeDomainDataPoints, + const timespec dataTimestamp, + const bool repeatDataFlag, + const bool lastOfMultipleUpdateFlag, + const timespec generatedTimestamp, + const int droppedFFTFrames); + + ~SpectrumUpdateEvent(); + + const std::complex* getFFTPoints() const; + const double* getRealTimeDomainPoints() const; + const double* getImagTimeDomainPoints() const; + uint64_t getNumFFTDataPoints() const; + uint64_t getNumTimeDomainDataPoints() const; + timespec getDataTimestamp() const; + bool getRepeatDataFlag() const; + bool getLastOfMultipleUpdateFlag() const; + timespec getEventGeneratedTimestamp() const; + int getDroppedFFTFrames() const; + +protected: + +private: + std::complex* _fftPoints; + double* _realDataTimeDomainPoints; + double* _imagDataTimeDomainPoints; + uint64_t _numFFTDataPoints; + uint64_t _numTimeDomainDataPoints; + timespec _dataTimestamp; + bool _repeatDataFlag; + bool _lastOfMultipleUpdateFlag; + timespec _eventGeneratedTimestamp; + int _droppedFFTFrames; +}; + +class SpectrumWindowCaptionEvent:public QEvent{ +public: + SpectrumWindowCaptionEvent(const QString&); + ~SpectrumWindowCaptionEvent(); + QString getLabel(); + +protected: + +private: + QString _labelString; +}; + +class SpectrumWindowResetEvent:public QEvent{ +public: + SpectrumWindowResetEvent(); + ~SpectrumWindowResetEvent(); + +protected: + +private: + +}; + +class SpectrumFrequencyRangeEvent:public QEvent{ +public: + SpectrumFrequencyRangeEvent(const double, const double, const double); + ~SpectrumFrequencyRangeEvent(); + double GetCenterFrequency()const; + double GetStartFrequency()const; + double GetStopFrequency()const; + +protected: + +private: + double _centerFrequency; + double _startFrequency; + double _stopFrequency; +}; + + +#endif /* SPECTRUM_UPDATE_EVENTS_H */ diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc new file mode 100644 index 000000000..e0509a294 --- /dev/null +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -0,0 +1,691 @@ +#include +#include +#include +#include + +int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1; + +SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent) + : QWidget(parent) +{ + setupUi(this); + + _useOpenGL = useOpenGL; + _systemSpecifiedFlag = false; + _intValidator = new QIntValidator(this); + _intValidator->setBottom(0); + _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame); + _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame); + + _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame); + _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame); + _numRealDataPoints = 1024; + _realFFTDataPoints = new double[_numRealDataPoints]; + _averagedValues = new double[_numRealDataPoints]; + _historyVector = new std::vector; + + AvgLineEdit->setRange(0, 500); // Set range of Average box value from 0 to 500 + MinHoldCheckBox_toggled( false ); + MaxHoldCheckBox_toggled( false ); + + WaterfallMaximumIntensityWheel->setRange(-200, 0); + WaterfallMaximumIntensityWheel->setTickCnt(50); + WaterfallMinimumIntensityWheel->setRange(-200, 0); + WaterfallMinimumIntensityWheel->setTickCnt(50); + WaterfallMinimumIntensityWheel->setValue(-200); + + _peakFrequency = 0; + _peakAmplitude = -HUGE_VAL; + + _noiseFloorAmplitude = -HUGE_VAL; + + connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), + _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double))); + connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), + _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double))); + + _frequencyDisplayPlot->SetLowerIntensityLevel(-200); + _frequencyDisplayPlot->SetUpperIntensityLevel(-200); + + // Load up the acceptable FFT sizes... + FFTSizeComboBox->clear(); + for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){ + FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize)); + } + Reset(); + + ToggleTabFrequency(false); + ToggleTabWaterfall(false); + ToggleTabTime(false); + ToggleTabConstellation(false); + + // Create a timer to update plots at the specified rate + displayTimer = new QTimer(this); + connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer())); +} + +SpectrumDisplayForm::~SpectrumDisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + delete _intValidator; + + delete[] _realFFTDataPoints; + delete[] _averagedValues; + + for(unsigned int count = 0; count < _historyVector->size(); count++){ + delete[] _historyVector->operator[](count); + } + + delete _historyVector; + + displayTimer->stop(); + delete displayTimer; +} + +void +SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, + const uint64_t numFFTDataPoints, + const uint64_t numTimeDomainDataPoints ) +{ + ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints); + + if(newSystem != NULL){ + _system = newSystem; + _systemSpecifiedFlag = true; + } + else{ + _systemSpecifiedFlag = false; + } +} + +void +SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent) +{ + //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent); + const std::complex* 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 bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag(); + const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag(); + const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp(); + + // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true... + ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints); + + // Calculate the Magnitude of the complex point + const std::complex* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2; + double* realFFTDataPointsPtr = _realFFTDataPoints; + + double sumMean = 0.0; + double localPeakAmplitude = -HUGE_VAL; + double localPeakFrequency = 0.0; + const double fftBinSize = (_stopFrequency-_startFrequency) / + static_cast(numFFTDataPoints); + + // Run this twice to perform the fftshift operation on the data here as well + std::complex scaleFactor = std::complex((float)numFFTDataPoints); + for(uint64_t point = 0; point < numFFTDataPoints/2; point++){ + std::complex pt = (*complexDataPointsPtr) / scaleFactor; + *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20); + + if(*realFFTDataPointsPtr > localPeakAmplitude) { + localPeakFrequency = static_cast(point) * fftBinSize; + localPeakAmplitude = *realFFTDataPointsPtr; + } + sumMean += *realFFTDataPointsPtr; + + complexDataPointsPtr++; + realFFTDataPointsPtr++; + } + + // This loop takes the first half of the input data and puts it in the + // second half of the plotted data + complexDataPointsPtr = complexDataPoints; + for(uint64_t point = 0; point < numFFTDataPoints/2; point++){ + std::complex pt = (*complexDataPointsPtr) / scaleFactor; + *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20); + + if(*realFFTDataPointsPtr > localPeakAmplitude) { + localPeakFrequency = static_cast(point) * fftBinSize; + localPeakAmplitude = *realFFTDataPointsPtr; + } + sumMean += *realFFTDataPointsPtr; + + complexDataPointsPtr++; + realFFTDataPointsPtr++; + } + + // Don't update the averaging history if this is repeated data + if(!repeatDataFlag){ + _AverageHistory(_realFFTDataPoints); + + // Only use the local info if we are not repeating data + _peakAmplitude = localPeakAmplitude; + _peakFrequency = localPeakFrequency; + + // calculate the spectral mean + // +20 because for the comparison below we only want to throw out bins + // that are significantly higher (and would, thus, affect the mean more) + const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0; + + // now throw out any bins higher than the mean + sumMean = 0.0; + uint64_t newNumDataPoints = numFFTDataPoints; + for(uint64_t number = 0; number < numFFTDataPoints; number++){ + if (_realFFTDataPoints[number] <= meanAmplitude) + sumMean += _realFFTDataPoints[number]; + else + newNumDataPoints--; + } + + if (newNumDataPoints == 0) // in the odd case that all + _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal! + else + _noiseFloorAmplitude = sumMean / newNumDataPoints; + } + + if(lastOfMultipleUpdatesFlag){ + int tabindex = SpectrumTypeTab->currentIndex(); + if(tabindex == d_plot_fft) { + _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, + _noiseFloorAmplitude, _peakFrequency, + _peakAmplitude, d_update_time); + } + if(tabindex == d_plot_time) { + _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, + imagTimeDomainDataPoints, + numTimeDomainDataPoints, + d_update_time); + } + if(tabindex == d_plot_constellation) { + _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, + imagTimeDomainDataPoints, + numTimeDomainDataPoints, + d_update_time); + } + + // Don't update the repeated data for the waterfall + if(!repeatDataFlag){ + if(tabindex == d_plot_waterfall) { + _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, + d_update_time, dataTimestamp, + spectrumUpdateEvent->getDroppedFFTFrames()); + } + } + + + // Tell the system the GUI has been updated + if(_systemSpecifiedFlag){ + _system->SetLastGUIUpdateTime(generatedTimestamp); + _system->DecrementPendingGUIUpdateEvents(); + } + } +} + +void +SpectrumDisplayForm::resizeEvent( QResizeEvent *e ) +{ + QSize s; + s.setWidth(FrequencyPlotDisplayFrame->width()); + s.setHeight(FrequencyPlotDisplayFrame->height()); + emit _frequencyDisplayPlot->resizeSlot(&s); + + s.setWidth(TimeDomainDisplayFrame->width()); + s.setHeight(TimeDomainDisplayFrame->height()); + emit _timeDomainDisplayPlot->resizeSlot(&s); + + s.setWidth(WaterfallPlotDisplayFrame->width()); + s.setHeight(WaterfallPlotDisplayFrame->height()); + emit _waterfallDisplayPlot->resizeSlot(&s); + + s.setWidth(ConstellationDisplayFrame->width()); + s.setHeight(ConstellationDisplayFrame->height()); + emit _constellationDisplayPlot->resizeSlot(&s); +} + +void +SpectrumDisplayForm::customEvent( QEvent * e) +{ + if(e->type() == QEvent::User+3){ + if(_systemSpecifiedFlag){ + WindowComboBox->setCurrentIndex(_system->GetWindowType()); + FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex()); + //FFTSizeComboBox->setCurrentIndex(1); + } + + waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value()); + waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value()); + + // Clear any previous display + Reset(); + } + else if(e->type() == 10005){ + SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e; + newFrequencyData(spectrumUpdateEvent); + } + else if(e->type() == 10008){ + setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel()); + } + else if(e->type() == 10009){ + Reset(); + if(_systemSpecifiedFlag){ + _system->ResetPendingGUIUpdateEvents(); + } + } + else if(e->type() == 10010){ + _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency(); + _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency(); + _centerFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency(); + + UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked()); + } +} + +void +SpectrumDisplayForm::UpdateGuiTimer() +{ + // This is called by the displayTimer and redraws the canvases of + // all of the plots. + _frequencyDisplayPlot->canvas()->update(); + _waterfallDisplayPlot->canvas()->update(); + _timeDomainDisplayPlot->canvas()->update(); + _constellationDisplayPlot->canvas()->update(); +} + + +void +SpectrumDisplayForm::AvgLineEdit_valueChanged( int value ) +{ + SetAverageCount(value); +} + + +void +SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState ) +{ + MaxHoldResetBtn->setEnabled(newState); + _frequencyDisplayPlot->SetMaxFFTVisible(newState); + MaxHoldResetBtn_clicked(); +} + + +void +SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState ) +{ + MinHoldResetBtn->setEnabled(newState); + _frequencyDisplayPlot->SetMinFFTVisible(newState); + MinHoldResetBtn_clicked(); +} + + +void +SpectrumDisplayForm::MinHoldResetBtn_clicked() +{ + _frequencyDisplayPlot->ClearMinData(); + _frequencyDisplayPlot->replot(); +} + + +void +SpectrumDisplayForm::MaxHoldResetBtn_clicked() +{ + _frequencyDisplayPlot->ClearMaxData(); + _frequencyDisplayPlot->replot(); +} + + +void +SpectrumDisplayForm::TabChanged(int index) +{ + // This might be dangerous to call this with NULL + resizeEvent(NULL); +} + +void +SpectrumDisplayForm::SetFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency) +{ + double fdiff; + if(UseRFFrequenciesCheckBox->isChecked()) { + fdiff = newCenterFrequency; + } + else { + fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency)); + } + + if(fdiff > 0) { + std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"}; + 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(units3); + + _startFrequency = newStartFrequency; + _stopFrequency = newStopFrequency; + _centerFrequency = newCenterFrequency; + + _frequencyDisplayPlot->SetFrequencyRange(_startFrequency, + _stopFrequency, + _centerFrequency, + UseRFFrequenciesCheckBox->isChecked(), + units, strunits[iunit]); + _waterfallDisplayPlot->SetFrequencyRange(_startFrequency, + _stopFrequency, + _centerFrequency, + UseRFFrequenciesCheckBox->isChecked(), + units, strunits[iunit]); + _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency, + units, strtime[iunit]); + } +} + +int +SpectrumDisplayForm::GetAverageCount() +{ + return _historyVector->size(); +} + +void +SpectrumDisplayForm::SetAverageCount(const int newCount) +{ + if(newCount > -1){ + if(newCount != static_cast(_historyVector->size())){ + std::vector::iterator pos; + while(newCount < static_cast(_historyVector->size())){ + pos = _historyVector->begin(); + delete[] (*pos); + _historyVector->erase(pos); + } + + while(newCount > static_cast(_historyVector->size())){ + _historyVector->push_back(new double[_numRealDataPoints]); + } + AverageDataReset(); + } + } +} + +void +SpectrumDisplayForm::_AverageHistory(const double* newBuffer) +{ + if(_numRealDataPoints > 0){ + if(_historyVector->size() > 0){ + memcpy(_historyVector->operator[](_historyEntry), newBuffer, + _numRealDataPoints*sizeof(double)); + + // Increment the next location to store data + _historyEntryCount++; + if(_historyEntryCount > static_cast(_historyVector->size())){ + _historyEntryCount = _historyVector->size(); + } + _historyEntry = (++_historyEntry)%_historyVector->size(); + + // Total up and then average the values + double sum; + for(uint64_t location = 0; location < _numRealDataPoints; location++){ + sum = 0; + for(int number = 0; number < _historyEntryCount; number++){ + sum += _historyVector->operator[](number)[location]; + } + _averagedValues[location] = sum/static_cast(_historyEntryCount); + } + } + else{ + memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double)); + } + } +} + +void +SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, + const uint64_t /*numTimeDomainDataPoints*/ ) +{ + // Convert from Complex to Real for certain Displays + if(_numRealDataPoints != numFFTDataPoints){ + _numRealDataPoints = numFFTDataPoints; + delete[] _realFFTDataPoints; + delete[] _averagedValues; + + _realFFTDataPoints = new double[_numRealDataPoints]; + _averagedValues = new double[_numRealDataPoints]; + memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double)); + + const int historySize = _historyVector->size(); + SetAverageCount(0); // Clear the existing history + SetAverageCount(historySize); + + Reset(); + } +} + +void +SpectrumDisplayForm::Reset() +{ + AverageDataReset(); + + _waterfallDisplayPlot->Reset(); +} + + +void +SpectrumDisplayForm::AverageDataReset() +{ + _historyEntry = 0; + _historyEntryCount = 0; + + memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double)); + + MaxHoldResetBtn_clicked(); + MinHoldResetBtn_clicked(); +} + + +void +SpectrumDisplayForm::closeEvent( QCloseEvent *e ) +{ + if(_systemSpecifiedFlag){ + _system->SetWindowOpenFlag(false); + } + + qApp->processEvents(); + + QWidget::closeEvent(e); +} + + +void +SpectrumDisplayForm::WindowTypeChanged( int newItem ) +{ + if(_systemSpecifiedFlag){ + _system->SetWindowType(newItem); + } +} + + +void +SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag ) +{ + SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); +} + + +void +SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue ) +{ + if(newValue > WaterfallMinimumIntensityWheel->value()){ + WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0)); + } + else{ + WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value()); + } + + _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), + WaterfallMaximumIntensityWheel->value()); +} + + +void +SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue ) +{ + if(newValue < WaterfallMaximumIntensityWheel->value()){ + WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0)); + } + else{ + WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value()); + } + + _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), + WaterfallMaximumIntensityWheel->value()); +} + +void +SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString ) +{ + if(_systemSpecifiedFlag){ + _system->SetFFTSize(fftSizeString.toLong()); + } +} + + +void +SpectrumDisplayForm::WaterfallAutoScaleBtnCB() +{ + double minimumIntensity = _noiseFloorAmplitude - 5; + if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){ + minimumIntensity = WaterfallMinimumIntensityWheel->minValue(); + } + WaterfallMinimumIntensityWheel->setValue(minimumIntensity); + double maximumIntensity = _peakAmplitude + 10; + if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){ + maximumIntensity = WaterfallMaximumIntensityWheel->maxValue(); + } + WaterfallMaximumIntensityWheel->setValue(maximumIntensity); + waterfallMaximumIntensityChangedCB(maximumIntensity); +} + +void +SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType ) +{ + QColor lowIntensityColor; + QColor highIntensityColor; + if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){ + // Select the Low Intensity Color + lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor(); + if(!lowIntensityColor.isValid()){ + lowIntensityColor = Qt::black; + } + QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display", QMessageBox::Ok); + lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this); + + // Select the High Intensity Color + highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor(); + if(!highIntensityColor.isValid()){ + highIntensityColor = Qt::white; + } + QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display", QMessageBox::Ok); + highIntensityColor = QColorDialog::getColor(highIntensityColor, this); + } + + _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor); +} + +void +SpectrumDisplayForm::ToggleTabFrequency(const bool state) +{ + if(state == true) { + if(d_plot_fft == -1) { + SpectrumTypeTab->addTab(FrequencyPage, "Frequency Display"); + d_plot_fft = SpectrumTypeTab->count()-1; + } + } + else { + SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(FrequencyPage)); + d_plot_fft = -1; + } +} + +void +SpectrumDisplayForm::ToggleTabWaterfall(const bool state) +{ + if(state == true) { + if(d_plot_waterfall == -1) { + SpectrumTypeTab->addTab(WaterfallPage, "Waterfall Display"); + d_plot_waterfall = SpectrumTypeTab->count()-1; + } + } + else { + SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(WaterfallPage)); + d_plot_waterfall = -1; + } +} + +void +SpectrumDisplayForm::ToggleTabTime(const bool state) +{ + if(state == true) { + if(d_plot_time == -1) { + SpectrumTypeTab->addTab(TimeDomainPage, "Time Domain Display"); + d_plot_time = SpectrumTypeTab->count()-1; + } + } + else { + SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(TimeDomainPage)); + d_plot_time = -1; + } +} + +void +SpectrumDisplayForm::ToggleTabConstellation(const bool state) +{ + if(state == true) { + if(d_plot_constellation == -1) { + SpectrumTypeTab->addTab(ConstellationPage, "Constellation Display"); + d_plot_constellation = SpectrumTypeTab->count()-1; + } + } + else { + SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(ConstellationPage)); + d_plot_constellation = -1; + } +} + + +void +SpectrumDisplayForm::SetTimeDomainAxis(double min, double max) +{ + _timeDomainDisplayPlot->set_yaxis(min, max); +} + +void +SpectrumDisplayForm::SetConstellationAxis(double xmin, double xmax, + double ymin, double ymax) +{ + _constellationDisplayPlot->set_axis(xmin, xmax, ymin, ymax); +} + +void +SpectrumDisplayForm::SetConstellationPenSize(int size) +{ + _constellationDisplayPlot->set_pen_size( size ); +} + +void +SpectrumDisplayForm::SetFrequencyAxis(double min, double max) +{ + _frequencyDisplayPlot->set_yaxis(min, max); +} + +void +SpectrumDisplayForm::SetUpdateTime(double t) +{ + d_update_time = t; + // QTimer class takes millisecond input + displayTimer->start(d_update_time*1000); +} diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h new file mode 100644 index 000000000..fbd08349b --- /dev/null +++ b/gr-qtgui/lib/spectrumdisplayform.h @@ -0,0 +1,114 @@ +#ifndef SPECTRUM_DISPLAY_FORM_H +#define SPECTRUM_DISPLAY_FORM_H + +#include "spectrumdisplayform.ui.h" + +class SpectrumGUIClass; +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class SpectrumDisplayForm : public QWidget, public Ui::SpectrumDisplayForm +{ + Q_OBJECT + + public: + SpectrumDisplayForm(bool useOpenGL = true, QWidget* parent = 0); + ~SpectrumDisplayForm(); + + void setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, + const uint64_t numTimeDomainDataPoints ); + + int GetAverageCount(); + void SetAverageCount( const int newCount ); + void Reset(); + void AverageDataReset(); + void ResizeBuffers( const uint64_t numFFTDataPoints, + const uint64_t numTimeDomainDataPoints ); + +public slots: + void resizeEvent( QResizeEvent * e ); + void customEvent( QEvent * e ); + void AvgLineEdit_valueChanged( int valueString ); + void MaxHoldCheckBox_toggled( bool newState ); + void MinHoldCheckBox_toggled( bool newState ); + void MinHoldResetBtn_clicked(); + void MaxHoldResetBtn_clicked(); + void TabChanged(int index); + + void SetFrequencyRange( const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency ); + void closeEvent( QCloseEvent * e ); + void WindowTypeChanged( int newItem ); + void UseRFFrequenciesCB( bool useRFFlag ); + void waterfallMaximumIntensityChangedCB(double); + void waterfallMinimumIntensityChangedCB(double); + void WaterfallIntensityColorTypeChanged(int); + void WaterfallAutoScaleBtnCB(); + void FFTComboBoxSelectedCB(const QString&); + + void ToggleTabFrequency(const bool state); + void ToggleTabWaterfall(const bool state); + void ToggleTabTime(const bool state); + void ToggleTabConstellation(const bool state); + + void SetTimeDomainAxis(double min, double max); + void SetConstellationAxis(double xmin, double xmax, + double ymin, double ymax); + void SetConstellationPenSize(int size); + void SetFrequencyAxis(double min, double max); + void SetUpdateTime(double t); + +private slots: + void newFrequencyData( const SpectrumUpdateEvent* ); + void UpdateGuiTimer(); + +protected: + +private: + void _AverageHistory( const double * newBuffer ); + + bool _useOpenGL; + int _historyEntryCount; + int _historyEntry; + std::vector* _historyVector; + double* _averagedValues; + uint64_t _numRealDataPoints; + double* _realFFTDataPoints; + QIntValidator* _intValidator; + FrequencyDisplayPlot* _frequencyDisplayPlot; + WaterfallDisplayPlot* _waterfallDisplayPlot; + TimeDomainDisplayPlot* _timeDomainDisplayPlot; + ConstellationDisplayPlot* _constellationDisplayPlot; + SpectrumGUIClass* _system; + bool _systemSpecifiedFlag; + double _centerFrequency; + double _startFrequency; + double _noiseFloorAmplitude; + double _peakFrequency; + double _peakAmplitude; + static int _openGLWaterfall3DFlag; + double _stopFrequency; + + //SpectrumUpdateEvent _lastSpectrumEvent; + + // whether or not to use a particular display + int d_plot_fft; + int d_plot_waterfall; + int d_plot_waterfall3d; + int d_plot_time; + int d_plot_constellation; + + QTimer *displayTimer; + double d_update_time; +}; + +#endif /* SPECTRUM_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui new file mode 100644 index 000000000..5a23bc8a9 --- /dev/null +++ b/gr-qtgui/lib/spectrumdisplayform.ui @@ -0,0 +1,788 @@ + + + SpectrumDisplayForm + + + + 0 + 0 + 712 + 543 + + + + Spectrum Display + + + + + + + 0 + 0 + + + + + 120 + 16777215 + + + + + 1024 + + + + + 2048 + + + + + 4096 + + + + + 8192 + + + + + 16384 + + + + + 32768 + + + + + + + + FFT Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + Display RF Frequencies + + + + + + + + + + 0 + 0 + + + + Window: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 120 + 0 + + + + + 120 + 16777215 + + + + + 9 + + + + + Hamming + + + + + Hann + + + + + Blackman + + + + + Rectangular + + + + + Kaiser + + + + + Blackman-harris + + + + + + + + + + 0 + + + + Frequency Display + + + + + + + + + 0 + 0 + + + + + 400 + 350 + + + + + 1 + 1 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + + + Max Hold + + + false + + + + + + + Min Hold + + + false + + + + + + + + 0 + 0 + + + + + 25 + 0 + + + + Reset + + + + + + + + 0 + 0 + + + + + 62 + 0 + + + + Average + + + Qt::AlignCenter + + + false + + + + + + + Reset + + + + + + + + + + Qt::Horizontal + + + + 200 + 20 + + + + + + + + + + + + + Waterfall Display + + + + + + + 100 + 16777215 + + + + Intensity Display: + + + false + + + + + + + + 200 + 0 + + + + true + + + Qt::WheelFocus + + + true + + + 200.000000000000000 + + + 20.000000000000000 + + + 0.000000000000000 + + + + + + + + 100 + 16777215 + + + + 100 dB + + + false + + + + + + + + 617 + 338 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + + 200 + 0 + + + + true + + + 200.000000000000000 + + + 20.000000000000000 + + + 0.000000000000000 + + + + + + + + 100 + 16777215 + + + + -100 dB + + + false + + + + + + + + 80 + 16777215 + + + + Scales the Intensity to the current data extremes. + + + Auto Scale + + + + + + + + 100 + 16777215 + + + + + Color + + + + + White Hot + + + + + Black Hot + + + + + Incandescent + + + + + User Defined + + + + + + + + + Time Domain Display + + + + + + + 617 + 404 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + + Constellation Display + + + + + + + 617 + 406 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + qPixmapFromMimeSource + + + QwtWheel + QWidget +
qwt_wheel.h
+
+
+ + SpectrumTypeTab + UseRFFrequenciesCheckBox + FFTSizeComboBox + WaterfallMaximumIntensityWheel + WaterfallMinimumIntensityWheel + + + SpectrumGUIClass.h + FrequencyDisplayPlot.h + WaterfallDisplayPlot.h + TimeDomainDisplayPlot.h + qvalidator.h + vector + qwt_wheel.h + + + + + MaxHoldCheckBox + toggled(bool) + SpectrumDisplayForm + MaxHoldCheckBox_toggled(bool) + + + 22 + 324 + + + 20 + 20 + + + + + MaxHoldResetBtn + clicked() + SpectrumDisplayForm + MaxHoldResetBtn_clicked() + + + 107 + 324 + + + 20 + 20 + + + + + MinHoldCheckBox + toggled(bool) + SpectrumDisplayForm + MinHoldCheckBox_toggled(bool) + + + 22 + 349 + + + 20 + 20 + + + + + MinHoldResetBtn + clicked() + SpectrumDisplayForm + MinHoldResetBtn_clicked() + + + 107 + 349 + + + 20 + 20 + + + + + WindowComboBox + activated(int) + SpectrumDisplayForm + WindowTypeChanged(int) + + + 20 + 20 + + + 20 + 20 + + + + + UseRFFrequenciesCheckBox + toggled(bool) + SpectrumDisplayForm + UseRFFrequenciesCB(bool) + + + 20 + 20 + + + 20 + 20 + + + + + WaterfallMaximumIntensityWheel + valueChanged(double) + SpectrumDisplayForm + waterfallMaximumIntensityChangedCB(double) + + + 217 + 44 + + + 20 + 20 + + + + + WaterfallMinimumIntensityWheel + valueChanged(double) + SpectrumDisplayForm + waterfallMinimumIntensityChangedCB(double) + + + 217 + 349 + + + 20 + 20 + + + + + FFTSizeComboBox + activated(QString) + SpectrumDisplayForm + FFTComboBoxSelectedCB(QString) + + + 20 + 20 + + + 20 + 20 + + + + + WaterfallAutoScaleBtn + clicked() + SpectrumDisplayForm + WaterfallAutoScaleBtnCB() + + + 22 + 349 + + + 20 + 20 + + + + + Waterfall3DAutoScaleBtn + clicked() + SpectrumDisplayForm + Waterfall3DAutoScaleBtnCB() + + + 22 + 349 + + + 20 + 20 + + + + + WaterfallIntensityComboBox + activated(int) + SpectrumDisplayForm + WaterfallIntensityColorTypeChanged(int) + + + 92 + 44 + + + 20 + 20 + + + + + Waterfall3DIntensityComboBox + activated(int) + SpectrumDisplayForm + Waterfall3DIntensityColorTypeChanged(int) + + + 92 + 44 + + + 20 + 20 + + + + + SpectrumTypeTab + currentChanged(int) + SpectrumDisplayForm + TabChanged(int) + + + 314 + 189 + + + 316 + 217 + + + + + AvgLineEdit + valueChanged(int) + SpectrumDisplayForm + AvgLineEdit_valueChanged(int) + + + 604 + 421 + + + 328 + 260 + + + + +
diff --git a/gr-qtgui/lib/waterfallGlobalData.cc b/gr-qtgui/lib/waterfallGlobalData.cc new file mode 100644 index 000000000..1ba153f0d --- /dev/null +++ b/gr-qtgui/lib/waterfallGlobalData.cc @@ -0,0 +1,164 @@ +#ifndef WATERFALL_GLOBAL_DATA_CPP +#define WATERFALL_GLOBAL_DATA_CPP + +#include + +WaterfallData::WaterfallData(const double minimumFrequency, + const double maximumFrequency, + const uint64_t fftPoints, + const unsigned int historyExtent) + : QwtRasterData(QwtDoubleRect(minimumFrequency /* X START */, 0 /* Y START */, + maximumFrequency - minimumFrequency /* WIDTH */, + static_cast(historyExtent)/* HEIGHT */)) +{ + _intensityRange = QwtDoubleInterval(-200.0, 0.0); + + _fftPoints = fftPoints; + _historyLength = historyExtent; + + _spectrumData = new double[_fftPoints * _historyLength]; + + Reset(); +} + +WaterfallData::~WaterfallData() +{ + delete[] _spectrumData; +} + +void WaterfallData::Reset() +{ + memset(_spectrumData, 0x0, _fftPoints*_historyLength*sizeof(double)); + + _numLinesToUpdate = -1; +} + +void WaterfallData::Copy(const WaterfallData* rhs) +{ + if((_fftPoints != rhs->GetNumFFTPoints()) || + (boundingRect() != rhs->boundingRect()) ){ + _fftPoints = rhs->GetNumFFTPoints(); + setBoundingRect(rhs->boundingRect()); + delete[] _spectrumData; + _spectrumData = new double[_fftPoints * _historyLength]; + } + Reset(); + SetSpectrumDataBuffer(rhs->GetSpectrumDataBuffer()); + SetNumLinesToUpdate(rhs->GetNumLinesToUpdate()); + setRange(rhs->range()); +} + +void WaterfallData::ResizeData(const double startFreq, + const double stopFreq, + const uint64_t fftPoints) +{ + if((fftPoints != GetNumFFTPoints()) || + (boundingRect().width() != (stopFreq - startFreq)) || + (boundingRect().left() != startFreq)){ + + setBoundingRect(QwtDoubleRect(startFreq, 0, stopFreq-startFreq, boundingRect().height())); + _fftPoints = fftPoints; + delete[] _spectrumData; + _spectrumData = new double[_fftPoints * _historyLength]; + } + + Reset(); +} + +QwtRasterData *WaterfallData::copy() const +{ + WaterfallData* returnData = new WaterfallData(boundingRect().left(), + boundingRect().right(), + _fftPoints, _historyLength); + returnData->Copy(this); + return returnData; +} + +QwtDoubleInterval WaterfallData::range() const +{ + return _intensityRange; +} + +void WaterfallData::setRange(const QwtDoubleInterval& newRange) +{ + _intensityRange = newRange; +} + +double WaterfallData::value(double x, double y) const +{ + double returnValue = 0.0; + + const unsigned int intY = static_cast((1.0 - (y/boundingRect().height())) * + static_cast(_historyLength - 1)); + const unsigned int intX = static_cast((((x - boundingRect().left()) / boundingRect().width()) * + static_cast(_fftPoints-1)) + 0.5); + + const int location = (intY * _fftPoints) + intX; + if((location > -1) && (location < static_cast(_fftPoints * _historyLength))){ + returnValue = _spectrumData[location]; + } + + return returnValue; +} + +uint64_t WaterfallData::GetNumFFTPoints() const +{ + return _fftPoints; +} + +void WaterfallData::addFFTData(const double* fftData, + const uint64_t fftDataSize, + const int droppedFrames){ + if(fftDataSize == _fftPoints){ + int64_t heightOffset = _historyLength - 1 - droppedFrames; + uint64_t drawingDroppedFrames = droppedFrames; + + // Any valid data rolled off the display so just fill in zeros and write new data + if(heightOffset < 0){ + heightOffset = 0; + drawingDroppedFrames = static_cast(_historyLength-1); + } + + // Copy the old data over if any available + if(heightOffset > 0){ + memmove( _spectrumData, &_spectrumData[(drawingDroppedFrames+1) * _fftPoints], + heightOffset * _fftPoints * sizeof(double)) ; + } + + if(drawingDroppedFrames > 0){ + // Fill in zeros data for dropped data + memset(&_spectrumData[heightOffset * _fftPoints], 0x00, + static_cast(drawingDroppedFrames) * _fftPoints * sizeof(double)); + } + + // add the new buffer + memcpy(&_spectrumData[(_historyLength - 1) * _fftPoints], fftData, _fftPoints*sizeof(double)); + } +} + +double* WaterfallData::GetSpectrumDataBuffer() const +{ + return _spectrumData; +} + +void WaterfallData::SetSpectrumDataBuffer(const double* newData) +{ + memcpy(_spectrumData, newData, _fftPoints * _historyLength * sizeof(double)); +} + +int WaterfallData::GetNumLinesToUpdate() const +{ + return _numLinesToUpdate; +} + +void WaterfallData::SetNumLinesToUpdate(const int newNum) +{ + _numLinesToUpdate = newNum; +} + +void WaterfallData::IncrementNumLinesToUpdate() +{ + _numLinesToUpdate++; +} + +#endif /* WATERFALL_GLOBAL_DATA_CPP */ diff --git a/gr-qtgui/lib/waterfallGlobalData.h b/gr-qtgui/lib/waterfallGlobalData.h new file mode 100644 index 000000000..51f65064c --- /dev/null +++ b/gr-qtgui/lib/waterfallGlobalData.h @@ -0,0 +1,47 @@ +#ifndef WATERFALL_GLOBAL_DATA_HPP +#define WATERFALL_GLOBAL_DATA_HPP + +#include +#include + + +class WaterfallData: public QwtRasterData +{ +public: + WaterfallData(const double, const double, const uint64_t, const unsigned int); + virtual ~WaterfallData(); + + virtual void Reset(); + virtual void Copy(const WaterfallData*); + + virtual void ResizeData(const double, const double, const uint64_t); + + virtual QwtRasterData *copy() const; + virtual QwtDoubleInterval range() const; + virtual void setRange(const QwtDoubleInterval&); + + virtual double value(double x, double y) const; + + virtual uint64_t GetNumFFTPoints()const; + virtual void addFFTData(const double*, const uint64_t, const int); + + virtual double* GetSpectrumDataBuffer()const; + virtual void SetSpectrumDataBuffer(const double*); + + virtual int GetNumLinesToUpdate()const; + virtual void SetNumLinesToUpdate(const int); + virtual void IncrementNumLinesToUpdate(); + +protected: + + double* _spectrumData; + uint64_t _fftPoints; + uint64_t _historyLength; + int _numLinesToUpdate; + QwtDoubleInterval _intensityRange; + +private: + +}; + +#endif /* WATERFALL_GLOBAL_DATA_HPP */ -- cgit From c102d4f510339f78184d292c8126e5d3721bb0b9 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 12:56:22 -0400 Subject: gr-qtgui: moving gitignore to new location. --- gr-qtgui/lib/.gitignore | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 gr-qtgui/lib/.gitignore (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/.gitignore b/gr-qtgui/lib/.gitignore new file mode 100644 index 000000000..61b9ca8c1 --- /dev/null +++ b/gr-qtgui/lib/.gitignore @@ -0,0 +1,16 @@ +/Makefile +/Makefile.in +/.libs +/.deps +/qtgui.cc +/qtgui.py +/WaterfallDisplayPlot.moc.cc +/Waterfall3DDisplayPlot.moc.cc +/TimeDomainDisplayPlot.moc.cc +/spectrumdisplayform.moc.cc +/spectrumdisplayform.ui.h +/FrequencyDisplayPlot.moc.cc +/ConstellationDisplayPlot.moc.cc +/gnuradio +/guile +/python -- cgit From 43b9359fabe5c153a02081ae56047b9e121dce02 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 12:59:52 -0400 Subject: gr-qtgui: moving Python files to new structure; get rid of src directory. --- gr-qtgui/lib/Makefile.swig.gen | 145 ----------------------------------------- gr-qtgui/lib/qtgui.i | 131 ------------------------------------- 2 files changed, 276 deletions(-) delete mode 100644 gr-qtgui/lib/Makefile.swig.gen delete mode 100644 gr-qtgui/lib/qtgui.i (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/Makefile.swig.gen b/gr-qtgui/lib/Makefile.swig.gen deleted file mode 100644 index 9c4c0b58c..000000000 --- a/gr-qtgui/lib/Makefile.swig.gen +++ /dev/null @@ -1,145 +0,0 @@ -# -*- Makefile -*- -# -# Copyright 2009 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. -# - -# Makefile.swig.gen for qtgui.i - -## Default install locations for these files: -## -## Default location for the Python directory is: -## ${prefix}/lib/python${python_version}/site-packages/[category]/qtgui -## Default location for the Python exec directory is: -## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/qtgui -## -## The following can be overloaded to change the install location, but -## this has to be done in the including Makefile.am -before- -## Makefile.swig is included. - -qtgui_pythondir_category ?= gnuradio/qtgui -qtgui_pylibdir_category ?= $(qtgui_pythondir_category) -qtgui_pythondir = $(pythondir)/$(qtgui_pythondir_category) -qtgui_pylibdir = $(pyexecdir)/$(qtgui_pylibdir_category) - -# The .so libraries for the guile modules get installed whereever guile -# is installed, usually /usr/lib/guile/gnuradio/ -# FIXME: determince whether these should be installed with gnuradio. -qtgui_scmlibdir = $(libdir) - -# The scm files for the guile modules get installed where ever guile -# is installed, usually /usr/share/guile/site/qtgui -# FIXME: determince whether these should be installed with gnuradio. -qtgui_scmdir = $(guiledir) - -## SWIG headers are always installed into the same directory. - -qtgui_swigincludedir = $(swigincludedir) - -## This is a template file for a "generated" Makefile addition (in -## this case, "Makefile.swig.gen"). By including the top-level -## Makefile.swig, this file will be used to generate the SWIG -## dependencies. Assign the variable TOP_SWIG_FILES to be the list of -## SWIG .i files to generated wrappings for; there can be more than 1 -## so long as the names are unique (no sorting is done on the -## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i -## file will generate .cc, .py, and possibly .h files -- meaning that -## all of these files will have the same base name (that provided for -## the SWIG .i file). -## -## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the -## right thing. For more info, see < -## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > - -## Other cleaned files: dependency files generated by SWIG or this Makefile - -MOSTLYCLEANFILES += $(DEPDIR)/*.S* - -## Various SWIG variables. These can be overloaded in the including -## Makefile.am by setting the variable value there, then including -## Makefile.swig . - -qtgui_swiginclude_HEADERS = \ - qtgui.i \ - $(qtgui_swiginclude_headers) - -if PYTHON -qtgui_pylib_LTLIBRARIES = \ - _qtgui.la - -_qtgui_la_SOURCES = \ - python/qtgui.cc \ - $(qtgui_la_swig_sources) - -qtgui_python_PYTHON = \ - qtgui.py \ - $(qtgui_python) - -_qtgui_la_LIBADD = \ - $(STD_SWIG_LA_LIB_ADD) \ - $(qtgui_la_swig_libadd) - -_qtgui_la_LDFLAGS = \ - $(STD_SWIG_LA_LD_FLAGS) \ - $(qtgui_la_swig_ldflags) - -_qtgui_la_CXXFLAGS = \ - $(STD_SWIG_CXX_FLAGS) \ - -I$(top_builddir) \ - $(qtgui_la_swig_cxxflags) - -python/qtgui.cc: qtgui.py -qtgui.py: qtgui.i - -# Include the python dependencies for this file --include python/qtgui.d - -endif # end of if python - -if GUILE - -qtgui_scmlib_LTLIBRARIES = \ - libguile-gnuradio-qtgui.la -libguile_gnuradio_qtgui_la_SOURCES = \ - guile/qtgui.cc \ - $(qtgui_la_swig_sources) -nobase_qtgui_scm_DATA = \ - gnuradio/qtgui.scm \ - gnuradio/qtgui-primitive.scm -libguile_gnuradio_qtgui_la_LIBADD = \ - $(STD_SWIG_LA_LIB_ADD) \ - $(qtgui_la_swig_libadd) -libguile_gnuradio_qtgui_la_LDFLAGS = \ - $(STD_SWIG_LA_LD_FLAGS) \ - $(qtgui_la_swig_ldflags) -libguile_gnuradio_qtgui_la_CXXFLAGS = \ - $(STD_SWIG_CXX_FLAGS) \ - -I$(top_builddir) \ - $(qtgui_la_swig_cxxflags) - -guile/qtgui.cc: gnuradio/qtgui.scm -gnuradio/qtgui.scm: qtgui.i -gnuradio/qtgui-primitive.scm: gnuradio/qtgui.scm - -# Include the guile dependencies for this file --include guile/qtgui.d - -endif # end of GUILE - - diff --git a/gr-qtgui/lib/qtgui.i b/gr-qtgui/lib/qtgui.i deleted file mode 100644 index bb64c6ae2..000000000 --- a/gr-qtgui/lib/qtgui.i +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include "gnuradio.i" - -%{ -#include "qtgui_sink_c.h" -#include "qtgui_sink_f.h" -%} - -GR_SWIG_BLOCK_MAGIC(qtgui,sink_c) - - qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc=0, double bw=1.0, - const std::string &name="Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plotwaterfall3d=true, bool plottime=true, - bool plotconst=true, - bool use_openGL=true, - QWidget *parent=NULL); - -class qtgui_sink_c : public gr_block -{ -private: - friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, - bool use_openGL, - QWidget *parent); - qtgui_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, - bool use_openGL, - QWidget *parent); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_frequency_axis(double min, double max); - void set_constellation_pen_size(int size); -}; - - - -/*********************************************************************/ - - -GR_SWIG_BLOCK_MAGIC(qtgui,sink_f) - -qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc=0, double bw=0.0, - const std::string &name="Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plotwaterfall3d=true, bool plottime=true, - bool plotconst=true, - bool use_openGL=true, - QWidget *parent=NULL); - -class qtgui_sink_f : public gr_block -{ -private: - friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, - bool use_openGL, - QWidget *parent); - qtgui_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, - bool use_openGL, - QWidget *parent); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_frequency_axis(double min, double max); - void set_constellation_pen_size(int size); -}; - -#if SWIGGUILE -%scheme %{ -(load-extension-global "libguile-gnuradio-qtgui" "scm_init_gnuradio_qtgui_module") -%} - -%goops %{ -(use-modules (gnuradio gnuradio_core_runtime)) -%} -#endif -- cgit From 4a1dfe6b13a6ea839e1e6f4792d5f8992c495594 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 13:10:40 -0400 Subject: gr-qtgui: wip: moving and renaming files for new structure. --- gr-qtgui/lib/Makefile.am | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index 446a07fd0..687a4f966 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008,2009,2010 Free Software Foundation, Inc. +# Copyright 2008-2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,6 @@ # include $(top_srcdir)/Makefile.common -include $(top_srcdir)/Makefile.swig EXTRA_DIST += spectrumdisplayform.ui @@ -91,7 +90,6 @@ libgnuradio_qtgui_la_LIBADD = \ -lstdc++ \ $(QT_LIBS) - ############################## # SWIG interfaces and libraries -- cgit From b7f96d543b35b8d5a401ced3afbc0aff2d7043db Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 13:41:32 -0400 Subject: gr-qtgui: fixed some signed/unsigned comparison warnings. --- gr-qtgui/lib/WaterfallDisplayPlot.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index a8e5361e7..08a71c023 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -142,7 +142,7 @@ public: 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 - int ind = time_str.find(" "); + 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)); @@ -194,7 +194,7 @@ protected: 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 - int ind = time_str.find(" "); + 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)); -- cgit From 79fa80423ab962e550b57c1bde49673394d8e0db Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 18:17:17 -0400 Subject: gr-qtgui: cleaning up handling of mutex --- gr-qtgui/lib/qtgui_sink_c.cc | 13 +------------ gr-qtgui/lib/qtgui_sink_c.h | 2 -- 2 files changed, 1 insertion(+), 14 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index 05c7b28d5..dee7c2f43 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -71,8 +71,8 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); } + gruel::scoped_lock lock(d_mutex); d_main_gui = NULL; - lock(); // Perform fftshift operation; // this is usually desired when plotting @@ -104,17 +104,6 @@ qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required) } } -void qtgui_sink_c::lock() -{ - d_mutex.lock(); -} - -void qtgui_sink_c::unlock() -{ - d_mutex.unlock(); -} - - void qtgui_sink_c::initialize(const bool opengl) { diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index bbf9983b0..bcdcf65ae 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -99,8 +99,6 @@ private: public: ~qtgui_sink_c(); void exec_(); - void lock(); - void unlock(); QWidget* qwidget(); PyObject* pyqwidget(); -- cgit From 7563ab82b34600219daf45555a00de79dd254fdb Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 27 Mar 2011 19:21:58 -0400 Subject: gr-qtgui: tightening up and cleaning up some memory leaks. --- gr-qtgui/lib/qtgui.h | 6 +++++- gr-qtgui/lib/qtgui_sink_c.cc | 3 ++- gr-qtgui/lib/spectrumdisplayform.cc | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/qtgui.h b/gr-qtgui/lib/qtgui.h index 9831697ac..27279e5cd 100644 --- a/gr-qtgui/lib/qtgui.h +++ b/gr-qtgui/lib/qtgui.h @@ -40,6 +40,8 @@ public: //nop } + ~qtgui_event() {} + void lock() { d_mutex.lock(); @@ -58,7 +60,9 @@ public: : QObject(p) { } - + + ~qtgui_obj() {} + void customEvent(QEvent *e) { if(e->type() == (QEvent::Type)(QEvent::User+101)) { diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index dee7c2f43..405971aa0 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -93,6 +93,7 @@ qtgui_sink_c::~qtgui_sink_c() delete d_main_gui; delete [] d_residbuf; delete d_fft; + delete d_object; } void @@ -111,7 +112,7 @@ qtgui_sink_c::initialize(const bool opengl) d_qApplication = qApp; } else { - int argc; + int argc=0; char **argv = NULL; d_qApplication = new QApplication(argc, argv); } diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index e0509a294..b5d4bf4d7 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -74,6 +74,11 @@ SpectrumDisplayForm::~SpectrumDisplayForm() delete[] _realFFTDataPoints; delete[] _averagedValues; + delete _frequencyDisplayPlot; + delete _waterfallDisplayPlot; + delete _timeDomainDisplayPlot; + delete _constellationDisplayPlot; + for(unsigned int count = 0; count < _historyVector->size(); count++){ delete[] _historyVector->operator[](count); } -- cgit From 2653d20527b9c8b431b9bfcd396bc2a03a8a950b Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Fri, 1 Apr 2011 10:59:33 -0400 Subject: gr-qtgui: wip trying to figure out segfaults. --- gr-qtgui/lib/SpectrumGUIClass.cc | 96 ++++++++++++++++--------------------- gr-qtgui/lib/SpectrumGUIClass.h | 24 +++++----- gr-qtgui/lib/spectrumdisplayform.cc | 8 ++-- 3 files changed, 56 insertions(+), 72 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc index 052730fc2..c62f34290 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.cc +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -37,15 +37,13 @@ SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize, _windowOpennedFlag = false; _fftBuffersCreatedFlag = false; - // Create Mutex Lock - //_windowStateLock = new MutexClass("_windowStateLock"); - _powerValue = 1; } SpectrumGUIClass::~SpectrumGUIClass() { if(GetWindowOpenFlag()){ + printf("spectrumDisplayForm: %p\n", _spectrumDisplayForm); delete _spectrumDisplayForm; } @@ -54,8 +52,6 @@ SpectrumGUIClass::~SpectrumGUIClass() delete[] _realTimeDomainPoints; delete[] _imagTimeDomainPoints; } - - //delete _windowStateLock; } void @@ -64,7 +60,7 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, const bool time, const bool constellation, const bool use_openGL) { - //_windowStateLock->Lock(); + d_mutex.lock(); if(!_windowOpennedFlag){ @@ -82,6 +78,7 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, // Called from the Event Thread _spectrumDisplayForm = new SpectrumDisplayForm(use_openGL, parent); + printf("spectrumDisplayForm: %p\n", _spectrumDisplayForm); // Toggle Windows on/off _spectrumDisplayForm->ToggleTabFrequency(frequency); @@ -95,8 +92,8 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, qApp->processEvents(); } + d_mutex.unlock(); - //_windowStateLock->Unlock(); SetDisplayTitle(_title); Reset(); @@ -104,7 +101,7 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, qApp->postEvent(_spectrumDisplayForm, new QEvent(QEvent::Type(QEvent::User+3))); - qApp->processEvents(); + //qApp->processEvents(); timespec_reset(&_lastGUIUpdateTime); @@ -147,10 +144,9 @@ SpectrumGUIClass::SetDisplayTitle(const std::string newString) bool SpectrumGUIClass::GetWindowOpenFlag() { + gruel::scoped_lock lock(d_mutex); bool returnFlag = false; - //_windowStateLock->Lock(); returnFlag = _windowOpennedFlag; - //_windowStateLock->Unlock(); return returnFlag; } @@ -158,9 +154,8 @@ SpectrumGUIClass::GetWindowOpenFlag() void SpectrumGUIClass::SetWindowOpenFlag(const bool newFlag) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _windowOpennedFlag = newFlag; - //_windowStateLock->Unlock(); } void @@ -168,7 +163,7 @@ SpectrumGUIClass::SetFrequencyRange(const double centerFreq, const double startFreq, const double stopFreq) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _centerFrequency = centerFreq; _startFrequency = startFreq; _stopFrequency = stopFreq; @@ -176,36 +171,32 @@ SpectrumGUIClass::SetFrequencyRange(const double centerFreq, _spectrumDisplayForm->SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); - //_windowStateLock->Unlock(); } double -SpectrumGUIClass::GetStartFrequency() const +SpectrumGUIClass::GetStartFrequency() { + gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; - //_windowStateLock->Lock(); returnValue = _startFrequency; - //_windowStateLock->Unlock(); return returnValue; } double -SpectrumGUIClass::GetStopFrequency() const +SpectrumGUIClass::GetStopFrequency() { + gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; - //_windowStateLock->Lock(); returnValue = _stopFrequency; - //_windowStateLock->Unlock(); return returnValue; } double -SpectrumGUIClass::GetCenterFrequency() const +SpectrumGUIClass::GetCenterFrequency() { + gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; - //_windowStateLock->Lock(); returnValue = _centerFrequency; - //_windowStateLock->Unlock(); return returnValue; } @@ -221,6 +212,7 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, const timespec timestamp, const bool lastOfMultipleFFTUpdateFlag) { + //gruel::scoped_lock lock(d_mutex); int64_t bufferSize = inputBufferSize; bool repeatDataFlag = false; if(bufferSize > _dataPoints){ @@ -302,54 +294,49 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, } float -SpectrumGUIClass::GetPowerValue() const +SpectrumGUIClass::GetPowerValue() { + gruel::scoped_lock lock(d_mutex); float returnValue = 0; - //_windowStateLock->Lock(); returnValue = _powerValue; - //_windowStateLock->Unlock(); return returnValue; } void SpectrumGUIClass::SetPowerValue(const float value) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _powerValue = value; - //_windowStateLock->Unlock(); } int -SpectrumGUIClass::GetWindowType() const +SpectrumGUIClass::GetWindowType() { + gruel::scoped_lock lock(d_mutex); int returnValue = 0; - //_windowStateLock->Lock(); returnValue = _windowType; - //_windowStateLock->Unlock(); return returnValue; } void SpectrumGUIClass::SetWindowType(const int newType) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _windowType = newType; - //_windowStateLock->Unlock(); } int -SpectrumGUIClass::GetFFTSize() const +SpectrumGUIClass::GetFFTSize() { int returnValue = 0; - //_windowStateLock->Lock(); returnValue = _fftSize; - //_windowStateLock->Unlock(); return returnValue; } int -SpectrumGUIClass::GetFFTSizeIndex() const +SpectrumGUIClass::GetFFTSizeIndex() { + gruel::scoped_lock lock(d_mutex); int fftsize = GetFFTSize(); switch(fftsize) { case(1024): return 0; break; @@ -365,75 +352,70 @@ SpectrumGUIClass::GetFFTSizeIndex() const void SpectrumGUIClass::SetFFTSize(const int newSize) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _fftSize = newSize; - //_windowStateLock->Unlock(); } timespec -SpectrumGUIClass::GetLastGUIUpdateTime() const +SpectrumGUIClass::GetLastGUIUpdateTime() { + gruel::scoped_lock lock(d_mutex); timespec returnValue; - //_windowStateLock->Lock(); returnValue = _lastGUIUpdateTime; - //_windowStateLock->Unlock(); return returnValue; } void SpectrumGUIClass::SetLastGUIUpdateTime(const timespec newTime) { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _lastGUIUpdateTime = newTime; - //_windowStateLock->Unlock(); } unsigned int -SpectrumGUIClass::GetPendingGUIUpdateEvents() const +SpectrumGUIClass::GetPendingGUIUpdateEvents() { + gruel::scoped_lock lock(d_mutex); unsigned int returnValue = 0; - //_windowStateLock->Lock(); returnValue = _pendingGUIUpdateEventsCount; - //_windowStateLock->Unlock(); return returnValue; } void SpectrumGUIClass::IncrementPendingGUIUpdateEvents() { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _pendingGUIUpdateEventsCount++; - //_windowStateLock->Unlock(); } void SpectrumGUIClass::DecrementPendingGUIUpdateEvents() { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); if(_pendingGUIUpdateEventsCount > 0){ _pendingGUIUpdateEventsCount--; } - //_windowStateLock->Unlock(); } void SpectrumGUIClass::ResetPendingGUIUpdateEvents() { - //_windowStateLock->Lock(); + gruel::scoped_lock lock(d_mutex); _pendingGUIUpdateEventsCount = 0; - //_windowStateLock->Unlock(); } QWidget* SpectrumGUIClass::qwidget() { + gruel::scoped_lock lock(d_mutex); return (QWidget*)_spectrumDisplayForm; } void SpectrumGUIClass::SetTimeDomainAxis(double min, double max) { + gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetTimeDomainAxis(min, max); } @@ -441,12 +423,14 @@ void SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax, double ymin, double ymax) { + gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax); - } void -SpectrumGUIClass::SetConstellationPenSize(int size){ +SpectrumGUIClass::SetConstellationPenSize(int size) +{ + gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetConstellationPenSize(size); } @@ -454,12 +438,14 @@ SpectrumGUIClass::SetConstellationPenSize(int size){ void SpectrumGUIClass::SetFrequencyAxis(double min, double max) { + gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetFrequencyAxis(min, max); } void SpectrumGUIClass::SetUpdateTime(double t) { + gruel::scoped_lock lock(d_mutex); _updateTime = t; _spectrumDisplayForm->SetUpdateTime(_updateTime); } diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h index 57a749a6a..8ffb411b8 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.h +++ b/gr-qtgui/lib/SpectrumGUIClass.h @@ -1,15 +1,13 @@ #ifndef SPECTRUM_GUI_CLASS_HPP #define SPECTRUM_GUI_CLASS_HPP -//#include +#include #include #include #include #include #include -//#include - class SpectrumDisplayForm; #include @@ -39,9 +37,9 @@ public: void SetWindowOpenFlag(const bool); void SetFrequencyRange(const double, const double, const double); - double GetStartFrequency()const; - double GetStopFrequency()const; - double GetCenterFrequency()const; + double GetStartFrequency(); + double GetStopFrequency(); + double GetCenterFrequency(); void UpdateWindow(const bool, const std::complex*, const uint64_t, const float*, @@ -49,20 +47,20 @@ public: const uint64_t, const timespec, const bool); - float GetPowerValue()const; + float GetPowerValue(); void SetPowerValue(const float); - int GetWindowType()const; + int GetWindowType(); void SetWindowType(const int); - int GetFFTSize()const; - int GetFFTSizeIndex()const; + int GetFFTSize(); + int GetFFTSizeIndex(); void SetFFTSize(const int); - timespec GetLastGUIUpdateTime()const; + timespec GetLastGUIUpdateTime(); void SetLastGUIUpdateTime(const timespec); - unsigned int GetPendingGUIUpdateEvents()const; + unsigned int GetPendingGUIUpdateEvents(); void IncrementPendingGUIUpdateEvents(); void DecrementPendingGUIUpdateEvents(); void ResetPendingGUIUpdateEvents(); @@ -84,7 +82,7 @@ protected: private: - //MutexClass* _windowStateLock; + gruel::mutex d_mutex; int64_t _dataPoints; std::string _title; double _centerFrequency; diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index b5d4bf4d7..d85637a67 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -74,10 +74,10 @@ SpectrumDisplayForm::~SpectrumDisplayForm() delete[] _realFFTDataPoints; delete[] _averagedValues; - delete _frequencyDisplayPlot; - delete _waterfallDisplayPlot; - delete _timeDomainDisplayPlot; - delete _constellationDisplayPlot; + //delete _frequencyDisplayPlot; + //delete _waterfallDisplayPlot; + //delete _timeDomainDisplayPlot; + //delete _constellationDisplayPlot; for(unsigned int count = 0; count < _historyVector->size(); count++){ delete[] _historyVector->operator[](count); -- cgit From 414ff0e69704f8c75edfc2ad3284a9c1bba5e50c Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 4 Apr 2011 23:37:58 -0400 Subject: gr-qtgui: removing unnecessary mutex and qtevent objects. --- gr-qtgui/lib/qtgui_sink_c.cc | 7 ------- gr-qtgui/lib/qtgui_sink_c.h | 6 +++--- gr-qtgui/lib/qtgui_sink_f.cc | 15 --------------- gr-qtgui/lib/qtgui_sink_f.h | 7 +------ 4 files changed, 4 insertions(+), 31 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index 405971aa0..bdd941fe1 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -71,7 +71,6 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); } - gruel::scoped_lock lock(d_mutex); d_main_gui = NULL; // Perform fftshift operation; @@ -93,7 +92,6 @@ qtgui_sink_c::~qtgui_sink_c() delete d_main_gui; delete [] d_residbuf; delete d_fft; - delete d_object; } void @@ -138,9 +136,6 @@ qtgui_sink_c::initialize(const bool opengl) // initialize update time to 10 times a second set_update_time(0.1); - - d_object = new qtgui_obj(d_qApplication); - qApp->postEvent(d_object, new qtgui_event(d_mutex)); } @@ -278,8 +273,6 @@ qtgui_sink_c::general_work (int noutput_items, int j=0; const gr_complex *in = (const gr_complex*)input_items[0]; - gruel::scoped_lock lock(d_mutex); - // Update the FFT size from the application fftresize(); windowreset(); diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index bcdcf65ae..59b5acfe5 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -28,7 +28,7 @@ #include #include #include -#include +//#include #include "SpectrumGUIClass.h" class qtgui_sink_c; @@ -76,7 +76,7 @@ private: double d_bandwidth; std::string d_name; - gruel::mutex d_mutex; + //gruel::mutex d_mutex; bool d_shift; gri_fft_complex *d_fft; @@ -114,7 +114,7 @@ public: void set_update_time(double t); QApplication *d_qApplication; - qtgui_obj *d_object; + //qtgui_obj *d_object; int general_work (int noutput_items, gr_vector_int &ninput_items, diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc index 984c2803c..3b3140b5e 100644 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -104,16 +104,6 @@ qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required) } } -void qtgui_sink_f::lock() -{ - d_mutex.lock(); -} - -void qtgui_sink_f::unlock() -{ - d_mutex.unlock(); -} - void qtgui_sink_f::initialize(const bool opengl) { @@ -143,9 +133,6 @@ qtgui_sink_f::initialize(const bool opengl) // initialize update time to 10 times a second set_update_time(0.1); - - d_object = new qtgui_obj(d_qApplication); - qApp->postEvent(d_object, new qtgui_event(d_mutex)); } void @@ -283,8 +270,6 @@ qtgui_sink_f::general_work (int noutput_items, int j=0; const float *in = (const float*)input_items[0]; - gruel::scoped_lock lock(d_mutex); - // Update the FFT size from the application fftresize(); windowreset(); diff --git a/gr-qtgui/lib/qtgui_sink_f.h b/gr-qtgui/lib/qtgui_sink_f.h index d80a6a198..a798a41bb 100644 --- a/gr-qtgui/lib/qtgui_sink_f.h +++ b/gr-qtgui/lib/qtgui_sink_f.h @@ -28,7 +28,7 @@ #include #include #include -#include +//#include #include "SpectrumGUIClass.h" class qtgui_sink_f; @@ -74,8 +74,6 @@ private: double d_bandwidth; std::string d_name; - gruel::mutex d_mutex; - bool d_shift; gri_fft_complex *d_fft; @@ -97,8 +95,6 @@ private: public: ~qtgui_sink_f(); void exec_(); - void lock(); - void unlock(); QWidget* qwidget(); PyObject* pyqwidget(); @@ -114,7 +110,6 @@ public: void set_update_time(double t); QApplication *d_qApplication; - qtgui_obj *d_object; int general_work (int noutput_items, gr_vector_int &ninput_items, -- cgit From fb89b81971ecb6859936ee484d31f5bd3e665f62 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 4 Apr 2011 23:38:37 -0400 Subject: gr-qtgui: removing uncessary file of qtevents and objects. --- gr-qtgui/lib/Makefile.am | 1 - gr-qtgui/lib/qtgui.h | 75 ------------------------------------------------ 2 files changed, 76 deletions(-) delete mode 100644 gr-qtgui/lib/qtgui.h (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index 687a4f966..7c21bfc14 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -69,7 +69,6 @@ grinclude_HEADERS = \ spectrumdisplayform.h \ SpectrumGUIClass.h \ spectrumUpdateEvents.h \ - qtgui.h \ qtgui_sink_c.h \ qtgui_sink_f.h diff --git a/gr-qtgui/lib/qtgui.h b/gr-qtgui/lib/qtgui.h deleted file mode 100644 index 27279e5cd..000000000 --- a/gr-qtgui/lib/qtgui.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,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_H -#define INCLUDED_QTGUI_H - -#include -#include -#include "SpectrumGUIClass.h" - -class qtgui_event : public QEvent -{ -private: - gruel::mutex &d_mutex; - -public: - qtgui_event(gruel::mutex &mutex) - : QEvent((QEvent::Type)(QEvent::User+101)), - d_mutex(mutex) - { - //nop - } - - ~qtgui_event() {} - - void lock() - { - d_mutex.lock(); - } - - void unlock() - { - d_mutex.unlock(); - } -}; - -class qtgui_obj : public QObject -{ -public: - qtgui_obj(QObject *p) - : QObject(p) - { - } - - ~qtgui_obj() {} - - void customEvent(QEvent *e) - { - if(e->type() == (QEvent::Type)(QEvent::User+101)) { - qtgui_event *qt = (qtgui_event*)e; - qt->unlock(); - } - } -}; - -#endif /* INCLUDED_QTGUI_H */ -- cgit From c5fd71cf8e03617a902291e85c589f3ff37e3fd8 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 4 Apr 2011 23:41:09 -0400 Subject: gr-qtgui: missed lock call that was just deleted. --- gr-qtgui/lib/qtgui_sink_f.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc index 3b3140b5e..e27ff3ac1 100644 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -72,7 +72,6 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, } d_main_gui = NULL; - lock(); // Perform fftshift operation; // this is usually desired when plotting -- cgit From 484b6a0715f2ed6e4f460ee05887e1e5c98c1e2f Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 6 Apr 2011 00:05:05 -0400 Subject: gr-qtgui: don't delete the SpectrumDisplayWindow; as a QWidget, it takes care of itself when the parent is deleted. --- gr-qtgui/lib/SpectrumGUIClass.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc index c62f34290..3342c0cb3 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.cc +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -42,10 +42,12 @@ SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize, SpectrumGUIClass::~SpectrumGUIClass() { - if(GetWindowOpenFlag()){ - printf("spectrumDisplayForm: %p\n", _spectrumDisplayForm); - delete _spectrumDisplayForm; - } + // We don't need to delete this since as a QWidget, it is supposed to be destroyed + // with it's parent. Deleting it causes a segmentation fault, and not deleting it + // does not leave any extra memory. + //if(GetWindowOpenFlag()){ + //delete _spectrumDisplayForm; + //} if(_fftBuffersCreatedFlag){ delete[] _fftPoints; @@ -78,7 +80,6 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, // Called from the Event Thread _spectrumDisplayForm = new SpectrumDisplayForm(use_openGL, parent); - printf("spectrumDisplayForm: %p\n", _spectrumDisplayForm); // Toggle Windows on/off _spectrumDisplayForm->ToggleTabFrequency(frequency); @@ -101,8 +102,6 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, qApp->postEvent(_spectrumDisplayForm, new QEvent(QEvent::Type(QEvent::User+3))); - //qApp->processEvents(); - timespec_reset(&_lastGUIUpdateTime); // Draw Blank Display -- cgit From b0f876b55549db96920c2b3bfee32de6748096af Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 6 Apr 2011 00:07:00 -0400 Subject: gr-qtgui: cleaning up unnecessary plotting calls. --- gr-qtgui/lib/ConstellationDisplayPlot.cc | 4 ---- gr-qtgui/lib/FrequencyDisplayPlot.cc | 2 -- gr-qtgui/lib/TimeDomainDisplayPlot.cc | 4 ---- gr-qtgui/lib/spectrumdisplayform.cc | 8 +++----- 4 files changed, 3 insertions(+), 15 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc index 9ad5bdd3c..71933cece 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.cc +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -74,8 +74,6 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) 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, @@ -178,8 +176,6 @@ void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); - replot(); - _lastReplot = get_highres_clock(); } } diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index d150e2e4c..45e2e6c16 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -367,8 +367,6 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat SetUpperIntensityLevel(_peakAmplitude); - replot(); - _lastReplot = get_highres_clock(); } } diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index 9c98cec5b..da28d0304 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -121,8 +121,6 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) _sampleRate = 1; _resetXAxisPoints(); - replot(); - #if QT_VERSION < 0x040000 _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); @@ -220,8 +218,6 @@ void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints, memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); - replot(); - _lastReplot = get_highres_clock(); } } diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index d85637a67..d4fc03781 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -59,6 +59,9 @@ SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent) ToggleTabTime(false); ToggleTabConstellation(false); + _historyEntry = 0; + _historyEntryCount = 0; + // Create a timer to update plots at the specified rate displayTimer = new QTimer(this); connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer())); @@ -74,11 +77,6 @@ SpectrumDisplayForm::~SpectrumDisplayForm() delete[] _realFFTDataPoints; delete[] _averagedValues; - //delete _frequencyDisplayPlot; - //delete _waterfallDisplayPlot; - //delete _timeDomainDisplayPlot; - //delete _constellationDisplayPlot; - for(unsigned int count = 0; count < _historyVector->size(); count++){ delete[] _historyVector->operator[](count); } -- cgit From 8f53f5a782a6500d191ba557b37e7e3785cf6e02 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 6 Apr 2011 00:22:29 -0400 Subject: gr-qtgui: removing references to 3D waterfall plot and changning QtGui API to remove bool that turns it on/off. --- gr-qtgui/lib/.gitignore | 1 - gr-qtgui/lib/qtgui_sink_c.cc | 13 +++---------- gr-qtgui/lib/qtgui_sink_c.h | 10 +++------- gr-qtgui/lib/qtgui_sink_f.cc | 13 +++---------- gr-qtgui/lib/qtgui_sink_f.h | 9 +++------ gr-qtgui/lib/spectrumdisplayform.cc | 2 -- gr-qtgui/lib/spectrumdisplayform.h | 2 -- 7 files changed, 12 insertions(+), 38 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/.gitignore b/gr-qtgui/lib/.gitignore index 61b9ca8c1..fc4f8cdfe 100644 --- a/gr-qtgui/lib/.gitignore +++ b/gr-qtgui/lib/.gitignore @@ -5,7 +5,6 @@ /qtgui.cc /qtgui.py /WaterfallDisplayPlot.moc.cc -/Waterfall3DDisplayPlot.moc.cc /TimeDomainDisplayPlot.moc.cc /spectrumdisplayform.moc.cc /spectrumdisplayform.ui.h diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index bdd941fe1..4cbd47c55 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -35,16 +35,14 @@ qtgui_make_sink_c (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent) { return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype, fc, bw, name, plotfreq, plotwaterfall, - plotwaterfall3d, plottime, - plotconst, + plottime, plotconst, use_openGL, parent)); } @@ -53,8 +51,7 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent) : gr_block ("sink_c", @@ -67,10 +64,6 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, d_plottime(plottime), d_plotconst(plotconst), d_parent(parent) { - if(plotwaterfall3d == true) { - fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); - } - d_main_gui = NULL; // Perform fftshift operation; diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index 59b5acfe5..22ca07f77 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -28,7 +28,6 @@ #include #include #include -//#include #include "SpectrumGUIClass.h" class qtgui_sink_c; @@ -38,8 +37,7 @@ 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 plotwaterfall3d=true, bool plottime=true, - bool plotconst=true, + bool plottime=true, bool plotconst=true, bool use_openGL=true, QWidget *parent=NULL); @@ -50,16 +48,14 @@ private: double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent); qtgui_sink_c (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent); diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc index e27ff3ac1..90d4d7a70 100644 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -35,16 +35,14 @@ qtgui_make_sink_f (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent) { return gnuradio::get_initial_sptr(new qtgui_sink_f (fftsize, wintype, fc, bw, name, plotfreq, plotwaterfall, - plotwaterfall3d, plottime, - plotconst, + plottime, plotconst, use_openGL, parent)); } @@ -53,8 +51,7 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent) : gr_block ("sink_f", @@ -67,10 +64,6 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, d_plottime(plottime), d_plotconst(plotconst), d_parent(parent) { - if(plotwaterfall3d == true) { - fprintf(stderr, "Warning: plotting Waterfall3D has been removed; enabling plotwaterfall3d has no effect.\n"); - } - d_main_gui = NULL; // Perform fftshift operation; diff --git a/gr-qtgui/lib/qtgui_sink_f.h b/gr-qtgui/lib/qtgui_sink_f.h index a798a41bb..8f27d120a 100644 --- a/gr-qtgui/lib/qtgui_sink_f.h +++ b/gr-qtgui/lib/qtgui_sink_f.h @@ -38,8 +38,7 @@ 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 plotwaterfall3d=true, bool plottime=true, - bool plotconst=true, + bool plottime=true, bool plotconst=true, bool use_openGL=true, QWidget *parent=NULL); @@ -50,16 +49,14 @@ private: double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent); qtgui_sink_f (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, - bool plotwaterfall3d, bool plottime, - bool plotconst, + bool plottime, bool plotconst, bool use_openGL, QWidget *parent); diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index d4fc03781..101bbc52b 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -3,8 +3,6 @@ #include #include -int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1; - SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent) : QWidget(parent) { diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h index fbd08349b..e760ccc13 100644 --- a/gr-qtgui/lib/spectrumdisplayform.h +++ b/gr-qtgui/lib/spectrumdisplayform.h @@ -95,7 +95,6 @@ private: double _noiseFloorAmplitude; double _peakFrequency; double _peakAmplitude; - static int _openGLWaterfall3DFlag; double _stopFrequency; //SpectrumUpdateEvent _lastSpectrumEvent; @@ -103,7 +102,6 @@ private: // whether or not to use a particular display int d_plot_fft; int d_plot_waterfall; - int d_plot_waterfall3d; int d_plot_time; int d_plot_constellation; -- cgit From 997e8dd482eb88bcf34a0014aab7da5986548d8e Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 6 Apr 2011 00:27:52 -0400 Subject: gr-qtgui: finishing off removing references to 3D plotting in UI file. --- gr-qtgui/lib/spectrumdisplayform.ui | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui index 5a23bc8a9..856f59153 100644 --- a/gr-qtgui/lib/spectrumdisplayform.ui +++ b/gr-qtgui/lib/spectrumdisplayform.ui @@ -704,22 +704,6 @@ - - Waterfall3DAutoScaleBtn - clicked() - SpectrumDisplayForm - Waterfall3DAutoScaleBtnCB() - - - 22 - 349 - - - 20 - 20 - - - WaterfallIntensityComboBox activated(int) @@ -736,22 +720,6 @@ - - Waterfall3DIntensityComboBox - activated(int) - SpectrumDisplayForm - Waterfall3DIntensityColorTypeChanged(int) - - - 92 - 44 - - - 20 - 20 - - - SpectrumTypeTab currentChanged(int) -- cgit From c4050c5bdb55ce14565d0ade84bd518cc8c27ec5 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 10 Apr 2011 17:13:15 -0400 Subject: gr-qtgui: removed OpenGL calls; we still link against the QTOPENGL_LIBS because of some dependencies in Qwt. --- gr-qtgui/lib/Makefile.am | 3 ++- gr-qtgui/lib/SpectrumGUIClass.cc | 5 ++--- gr-qtgui/lib/SpectrumGUIClass.h | 3 +-- gr-qtgui/lib/qtgui_sink_c.cc | 10 +++------- gr-qtgui/lib/qtgui_sink_c.h | 7 +------ gr-qtgui/lib/qtgui_sink_f.cc | 10 +++------- gr-qtgui/lib/qtgui_sink_f.h | 5 +---- gr-qtgui/lib/spectrumdisplayform.cc | 3 +-- gr-qtgui/lib/spectrumdisplayform.h | 3 +-- 9 files changed, 15 insertions(+), 34 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index 7c21bfc14..f9b5dd03e 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -72,7 +72,8 @@ grinclude_HEADERS = \ qtgui_sink_c.h \ qtgui_sink_f.h -QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB +#QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB +QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB %.moc.cc : %.h $(QT_MOC_EXEC) $(QT_MOC_FLAGS) -p $(srcdir) $< -o $@ diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc index 3342c0cb3..1a519591d 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.cc +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -59,8 +59,7 @@ SpectrumGUIClass::~SpectrumGUIClass() void SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, const bool frequency, const bool waterfall, - const bool time, const bool constellation, - const bool use_openGL) + const bool time, const bool constellation) { d_mutex.lock(); @@ -79,7 +78,7 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, } // Called from the Event Thread - _spectrumDisplayForm = new SpectrumDisplayForm(use_openGL, parent); + _spectrumDisplayForm = new SpectrumDisplayForm(parent); // Toggle Windows on/off _spectrumDisplayForm->ToggleTabFrequency(frequency); diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h index 8ffb411b8..48f45a0f5 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.h +++ b/gr-qtgui/lib/SpectrumGUIClass.h @@ -29,8 +29,7 @@ public: void OpenSpectrumWindow(QWidget*, const bool frequency=true, const bool waterfall=true, - const bool time=true, const bool constellation=true, - const bool use_openGL=true); + const bool time=true, const bool constellation=true); void SetDisplayTitle(const std::string); bool GetWindowOpenFlag(); diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index 4cbd47c55..2cfa67d75 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -36,14 +36,12 @@ qtgui_make_sink_c (int fftsize, int wintype, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent) { return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype, fc, bw, name, plotfreq, plotwaterfall, plottime, plotconst, - use_openGL, parent)); } @@ -52,7 +50,6 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent) : gr_block ("sink_c", gr_make_io_signature (1, -1, sizeof(gr_complex)), @@ -77,7 +74,7 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, buildwindow(); - initialize(use_openGL); + initialize(); } qtgui_sink_c::~qtgui_sink_c() @@ -97,7 +94,7 @@ qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required) } void -qtgui_sink_c::initialize(const bool opengl) +qtgui_sink_c::initialize() { if(qApp != NULL) { d_qApplication = qApp; @@ -124,8 +121,7 @@ qtgui_sink_c::initialize(const bool opengl) d_main_gui->OpenSpectrumWindow(d_parent, d_plotfreq, d_plotwaterfall, - d_plottime, d_plotconst, - opengl); + d_plottime, d_plotconst); // initialize update time to 10 times a second set_update_time(0.1); diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index 22ca07f77..1c9561704 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -38,7 +38,6 @@ qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, const std::string &name="Spectrum Display", bool plotfreq=true, bool plotwaterfall=true, bool plottime=true, bool plotconst=true, - bool use_openGL=true, QWidget *parent=NULL); class qtgui_sink_c : public gr_block @@ -49,21 +48,17 @@ private: const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent); qtgui_sink_c (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent); void forecast(int noutput_items, gr_vector_int &ninput_items_required); - // use opengl to force OpenGL on or off - // this might be necessary for sessions over SSH - void initialize(const bool opengl=true); + void initialize(); int d_fftsize; gr_firdes::win_type d_wintype; diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc index 90d4d7a70..3312b9006 100644 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ b/gr-qtgui/lib/qtgui_sink_f.cc @@ -36,14 +36,12 @@ qtgui_make_sink_f (int fftsize, int wintype, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent) { return gnuradio::get_initial_sptr(new qtgui_sink_f (fftsize, wintype, fc, bw, name, plotfreq, plotwaterfall, plottime, plotconst, - use_openGL, parent)); } @@ -52,7 +50,6 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent) : gr_block ("sink_f", gr_make_io_signature (1, 1, sizeof(float)), @@ -77,7 +74,7 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, buildwindow(); - initialize(use_openGL); + initialize(); } qtgui_sink_f::~qtgui_sink_f() @@ -97,7 +94,7 @@ qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required) } void -qtgui_sink_f::initialize(const bool opengl) +qtgui_sink_f::initialize() { if(qApp != NULL) { d_qApplication = qApp; @@ -120,8 +117,7 @@ qtgui_sink_f::initialize(const bool opengl) d_main_gui->OpenSpectrumWindow(d_parent, d_plotfreq, d_plotwaterfall, - d_plottime, d_plotconst, - opengl); + d_plottime, d_plotconst); // initialize update time to 10 times a second set_update_time(0.1); diff --git a/gr-qtgui/lib/qtgui_sink_f.h b/gr-qtgui/lib/qtgui_sink_f.h index 8f27d120a..518aa3846 100644 --- a/gr-qtgui/lib/qtgui_sink_f.h +++ b/gr-qtgui/lib/qtgui_sink_f.h @@ -39,7 +39,6 @@ qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, const std::string &name="Spectrum Display", bool plotfreq=true, bool plotwaterfall=true, bool plottime=true, bool plotconst=true, - bool use_openGL=true, QWidget *parent=NULL); class qtgui_sink_f : public gr_block @@ -50,19 +49,17 @@ private: const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent); qtgui_sink_f (int fftsize, int wintype, double fc, double bw, const std::string &name, bool plotfreq, bool plotwaterfall, bool plottime, bool plotconst, - bool use_openGL, QWidget *parent); void forecast(int noutput_items, gr_vector_int &ninput_items_required); - void initialize(const bool opengl=true); + void initialize(); int d_fftsize; gr_firdes::win_type d_wintype; diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index 101bbc52b..804dbdd62 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -3,12 +3,11 @@ #include #include -SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent) +SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QWidget(parent) { setupUi(this); - _useOpenGL = useOpenGL; _systemSpecifiedFlag = false; _intValidator = new QIntValidator(this); _intValidator->setBottom(0); diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h index e760ccc13..794a8c58e 100644 --- a/gr-qtgui/lib/spectrumdisplayform.h +++ b/gr-qtgui/lib/spectrumdisplayform.h @@ -20,7 +20,7 @@ class SpectrumDisplayForm : public QWidget, public Ui::SpectrumDisplayForm Q_OBJECT public: - SpectrumDisplayForm(bool useOpenGL = true, QWidget* parent = 0); + SpectrumDisplayForm(QWidget* parent = 0); ~SpectrumDisplayForm(); void setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, @@ -76,7 +76,6 @@ protected: private: void _AverageHistory( const double * newBuffer ); - bool _useOpenGL; int _historyEntryCount; int _historyEntry; std::vector* _historyVector; -- cgit From 16ec5a3bf5a22cc72423d975666878eeadd2cf3c Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 10 Apr 2011 17:21:38 -0400 Subject: gr-qtgui: exposing set_update_time to Python. --- gr-qtgui/lib/qtgui_sink_c.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc index 2cfa67d75..7b40dd01d 100644 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ b/gr-qtgui/lib/qtgui_sink_c.cc @@ -39,10 +39,10 @@ qtgui_make_sink_c (int fftsize, int wintype, QWidget *parent) { return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype, - fc, bw, name, - plotfreq, plotwaterfall, - plottime, plotconst, - parent)); + fc, bw, name, + plotfreq, plotwaterfall, + plottime, plotconst, + parent)); } qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, -- cgit From 65dd7abbe7310d6e064712ac2507312c50304345 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 10 Apr 2011 17:53:08 -0400 Subject: gr-qtgui: fixes problem with initial axes not showing up properly. --- gr-qtgui/lib/spectrumdisplayform.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui index 856f59153..049d4ffeb 100644 --- a/gr-qtgui/lib/spectrumdisplayform.ui +++ b/gr-qtgui/lib/spectrumdisplayform.ui @@ -7,7 +7,7 @@ 0 0 712 - 543 + 560 @@ -182,8 +182,8 @@ - 400 - 350 + 617 + 400 -- cgit From 043ebada1dc7b258ed4558adaa037ac7e3dc97ca Mon Sep 17 00:00:00 2001 From: Mike Cornelius Date: Sun, 10 Apr 2011 22:10:42 -0400 Subject: gr-qtgui: adding new qtgui_util.h to handle plot picker machinery. --- gr-qtgui/lib/Makefile.am | 6 ++-- gr-qtgui/lib/qtgui_util.cc | 71 ++++++++++++++++++++++++++++++++++++++++++++++ gr-qtgui/lib/qtgui_util.h | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 gr-qtgui/lib/qtgui_util.cc create mode 100644 gr-qtgui/lib/qtgui_util.h (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index f9b5dd03e..26c9e64aa 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -53,7 +53,8 @@ libgnuradio_qtgui_la_SOURCES = \ spectrumUpdateEvents.cc \ plot_waterfall.cc \ qtgui_sink_c.cc \ - qtgui_sink_f.cc + qtgui_sink_f.cc \ + qtgui_util.cc nodist_libgnuradio_qtgui_la_SOURCES=$(QMAKE_SOURCES) @@ -70,7 +71,8 @@ grinclude_HEADERS = \ SpectrumGUIClass.h \ spectrumUpdateEvents.h \ qtgui_sink_c.h \ - qtgui_sink_f.h + qtgui_sink_f.h \ + qtgui_util.h #QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB diff --git a/gr-qtgui/lib/qtgui_util.cc b/gr-qtgui/lib/qtgui_util.cc new file mode 100644 index 000000000..87b90997a --- /dev/null +++ b/gr-qtgui/lib/qtgui_util.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 + +QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine() + : QwtPickerMachine () +{ + +} + +QwtPickerDblClickPointMachine::~QwtPickerDblClickPointMachine() +{ + +} + +QwtPickerMachine::CommandList +QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, + const QEvent *e) +{ + QwtPickerMachine::CommandList cmdList; + switch(e->type()) { + case QEvent::MouseButtonDblClick: + if ( eventPattern.mouseMatch(QwtEventPattern::MouseSelect1, + (const QMouseEvent *)e) ) { + cmdList += QwtPickerMachine::Begin; + cmdList += QwtPickerMachine::Append; + cmdList += QwtPickerMachine::End; + } + break; + default: + break; + } + return cmdList; +} + +QwtDblClickPlotPicker::QwtDblClickPlotPicker(QwtPlotCanvas* canvas) + : QwtPlotPicker(canvas) +{ + setSelectionFlags(QwtPicker::PointSelection); +} + +QwtDblClickPlotPicker::~QwtDblClickPlotPicker() +{ +} + +QwtPickerMachine* +QwtDblClickPlotPicker::stateMachine(int n) const +{ + return new QwtPickerDblClickPointMachine; +} + diff --git a/gr-qtgui/lib/qtgui_util.h b/gr-qtgui/lib/qtgui_util.h new file mode 100644 index 000000000..a519c66a2 --- /dev/null +++ b/gr-qtgui/lib/qtgui_util.h @@ -0,0 +1,50 @@ +/* -*- 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_UTIL_H +#define INCLUDED_QTGUI_UTIL_H + +#include + +#include +#include + + +class QwtDblClickPlotPicker: public QwtPlotPicker +{ +public: + QwtDblClickPlotPicker(QwtPlotCanvas *); + ~QwtDblClickPlotPicker(); + + virtual QwtPickerMachine * stateMachine(int) const; +}; + +class QwtPickerDblClickPointMachine: public QwtPickerMachine +{ +public: + QwtPickerDblClickPointMachine(); + ~QwtPickerDblClickPointMachine(); + + virtual CommandList transition( const QwtEventPattern &eventPattern, const QEvent *e); +}; + +#endif /* INCLUDED_QTGUI_UTIL_H */ -- cgit From 41ad09b4f22228dd555ea73f2078cb9ff056b979 Mon Sep 17 00:00:00 2001 From: Mike Cornelius Date: Mon, 11 Apr 2011 00:48:29 -0400 Subject: gr-qtgui: adding double-click point selector to main gui widgets. --- gr-qtgui/lib/ConstellationDisplayPlot.cc | 29 +++++++++++------ gr-qtgui/lib/ConstellationDisplayPlot.h | 8 +++++ gr-qtgui/lib/FrequencyDisplayPlot.cc | 55 ++++++++++++++++++++++++++++---- gr-qtgui/lib/FrequencyDisplayPlot.h | 16 ++++++++++ gr-qtgui/lib/Makefile.am | 25 +++------------ gr-qtgui/lib/TimeDomainDisplayPlot.cc | 18 +++++++++++ gr-qtgui/lib/TimeDomainDisplayPlot.h | 10 ++++++ gr-qtgui/lib/WaterfallDisplayPlot.cc | 24 +++++++++++--- gr-qtgui/lib/WaterfallDisplayPlot.h | 8 ++++- gr-qtgui/lib/qtgui_sink_c.h | 3 -- 10 files changed, 150 insertions(+), 46 deletions(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc index 71933cece..75dbe9c37 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.cc +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -5,7 +5,7 @@ #include #include - +#include class ConstellationDisplayZoomer: public QwtPlotZoomer { @@ -75,15 +75,11 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) memset(_imagDataPoints, 0x0, _numPoints*sizeof(double)); _zoomer = new ConstellationDisplayZoomer(canvas()); -#if QT_VERSION < 0x040000 - _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); -#else + _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); _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); @@ -100,8 +96,13 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) _zoomer->setRubberBandPen(c); _zoomer->setTrackerPen(c); - connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), - this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) )); + // emit the position of clicks on widget + _picker = new QwtDblClickPlotPicker(canvas()); + connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), + this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + + connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool ) ), + this, SLOT(LegendEntryChecked(QwtPlotItem *, bool ) )); } ConstellationDisplayPlot::~ConstellationDisplayPlot() @@ -186,4 +187,12 @@ ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) plotItem->setVisible(!on); } +void +ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} + #endif /* CONSTELLATION_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h index a441a8bfe..bf4531e0a 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.h +++ b/gr-qtgui/lib/ConstellationDisplayPlot.h @@ -13,6 +13,7 @@ #include #include #include +#include class ConstellationDisplayPlot : public QwtPlot { @@ -38,6 +39,11 @@ public: public slots: void resizeSlot( QSize *s ); + void OnPickerPointSelected(const QwtDoublePoint & p); + +signals: + void plotPointSelected(const QPointF p); + protected slots: void LegendEntryChecked(QwtPlotItem *plotItem, bool on); @@ -49,6 +55,8 @@ private: QwtPlotPanner* _panner; QwtPlotZoomer* _zoomer; + QwtDblClickPlotPicker *_picker; + double* _realDataPoints; double* _imagDataPoints; diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index 45e2e6c16..30b318184 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -148,7 +148,7 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); _max_fft_plot_curve->setVisible(false); - _lower_intensity_marker = new QwtPlotMarker(); + _lower_intensity_marker= new QwtPlotMarker(); _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); _lower_intensity_marker->setLinePen(QPen(Qt::cyan)); _lower_intensity_marker->attach(this); @@ -183,6 +183,12 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine)); _markerNoiseFloorAmplitude->attach(this); + _markerCF= new QwtPlotMarker(); + _markerCF->setLineStyle(QwtPlotMarker::VLine); + _markerCF->setLinePen(QPen(Qt::lightGray, 0, Qt::DotLine)); + _markerCF->attach(this); + _markerCF->hide(); + _peakFrequency = 0; _peakAmplitude = -HUGE_VAL; @@ -190,14 +196,19 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) replot(); + // emit the position of clicks on widget + _picker = new QwtDblClickPlotPicker(canvas()); + connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), + this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + + // Configure magnify on mouse wheel + _magnifier = new QwtPlotMagnifier(canvas()); + _magnifier->setAxisEnabled(QwtPlot::xBottom, false); + _zoomer = new FreqDisplayZoomer(canvas(), 0); -#if QT_VERSION < 0x040000 + _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); -#else - _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); -#endif _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); @@ -256,6 +267,7 @@ FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq, double stopFreq = constStopFreq / units; double centerFreq = constCenterFreq / units; + _xAxisMultiplier = units; _useCenterFrequencyFlag = useCenterFrequencyFlag; if(_useCenterFrequencyFlag){ @@ -433,5 +445,36 @@ FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel) _upper_intensity_marker->setYValue( upperIntensityLevel ); } +void +FrequencyDisplayPlot::SetTraceColour (QColor c) +{ + _fft_plot_curve->setPen(QPen(c)); +} + +void +FrequencyDisplayPlot::SetBGColour (QColor c) +{ + QPalette palette; + palette.setColor(canvas()->backgroundRole(), c); + canvas()->setPalette(palette); +} + +void +FrequencyDisplayPlot::ShowCFMarker (const bool show) +{ + if (show) + _markerCF->show(); + else + _markerCF->hide(); +} + +void +FrequencyDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); + point.setX(point.x() * _xAxisMultiplier); + emit plotPointSelected(point); +} #endif /* FREQUENCY_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h index 3c22c1397..7a207ab8d 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.h +++ b/gr-qtgui/lib/FrequencyDisplayPlot.h @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include class FrequencyDisplayPlot:public QwtPlot{ Q_OBJECT @@ -43,11 +45,20 @@ public: void set_yaxis(double min, double max); + void SetTraceColour (QColor); + void SetBGColour (QColor c); + void ShowCFMarker (const bool); + public slots: void resizeSlot( QSize *e ); void SetLowerIntensityLevel(const double); void SetUpperIntensityLevel(const double); + void OnPickerPointSelected(const QwtDoublePoint & p); + +signals: + void plotPointSelected(const QPointF p); + protected: private: @@ -71,9 +82,14 @@ private: QwtPlotMarker *_markerPeakAmplitude; QwtPlotMarker *_markerNoiseFloorAmplitude; + QwtPlotMarker *_markerCF; + + QwtDblClickPlotPicker *_picker; + QwtPlotMagnifier *_magnifier; double* _dataPoints; double* _xAxisPoints; + int _xAxisMultiplier; double* _minFFTPoints; double* _maxFFTPoints; diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index 26c9e64aa..7dee39eb4 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -86,25 +86,8 @@ QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB libgnuradio_qtgui_la_LDFLAGS = $(NO_UNDEFINED) $(BOOST_LDFLAGS) $(LTVERSIONFLAGS) libgnuradio_qtgui_la_LIBADD = \ - $(GNURADIO_CORE_LA) \ - $(BOOST_THREAD_LIB) \ - $(BOOST_DATE_TIME_LIB) \ - -lstdc++ \ + $(GNURADIO_CORE_LA) \ + $(BOOST_THREAD_LIB) \ + $(BOOST_DATE_TIME_LIB) \ + -lstdc++ \ $(QT_LIBS) - -############################## -# SWIG interfaces and libraries - -TOP_SWIG_IFILES = \ - qtgui.i - -# Install so that they end up available as: -# import gnuradio.qtgui -# This ends up at: -# ${prefix}/lib/python${python_version}/site-packages/gnuradio -qtgui_pythondir_category = \ - gnuradio/qtgui - -# additional libraries for linking with the SWIG-generated library -qtgui_la_swig_libadd = \ - libgnuradio-qtgui.la diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index da28d0304..be25a6cde 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -82,6 +82,7 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) _xAxisPoints = new double[_numPoints]; _zoomer = new TimeDomainDisplayZoomer(canvas(), 0); + _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); // Disable polygon clipping QwtPainter::setDeviceClipping(false); @@ -135,6 +136,15 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent) _panner->setAxisEnabled(QwtPlot::yRight, false); _panner->setMouseButton(Qt::MidButton); + // emit the position of clicks on widget + _picker = new QwtDblClickPlotPicker(canvas()); + connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), + this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + + // Configure magnify on mouse wheel + _magnifier = new QwtPlotMagnifier(canvas()); + _magnifier->setAxisEnabled(QwtPlot::xBottom, false); + // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically @@ -269,4 +279,12 @@ TimeDomainDisplayPlot::SetSampleRate(double sr, double units, } } +void +TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} + #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h index 952b5c8cf..01338300c 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.h +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -11,9 +11,11 @@ #include #include #include +#include #include #include #include +#include class TimeDomainDisplayPlot:public QwtPlot{ Q_OBJECT @@ -37,6 +39,11 @@ public slots: void SetSampleRate(double sr, double units, const std::string &strunits); + void OnPickerPointSelected(const QwtDoublePoint & p); + +signals: + void plotPointSelected(const QPointF p); + protected slots: void LegendEntryChecked(QwtPlotItem *plotItem, bool on); @@ -51,6 +58,9 @@ private: QwtPlotPanner* _panner; QwtPlotZoomer* _zoomer; + QwtDblClickPlotPicker *_picker; + QwtPlotMagnifier *_magnifier; + double* _realDataPoints; double* _imagDataPoints; double* _xAxisPoints; diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index 08a71c023..2234f4238 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -253,13 +253,9 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) // Ctrl+RighButton: zoom out to full size _zoomer = new WaterfallZoomer(canvas(), 0); -#if QT_VERSION < 0x040000 + _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); -#else - _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); -#endif _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); @@ -267,6 +263,11 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) _panner->setAxisEnabled(QwtPlot::yRight, false); _panner->setMouseButton(Qt::MidButton); + // emit the position of clicks on widget + _picker = new QwtDblClickPlotPicker(canvas()); + connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), + this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically @@ -279,6 +280,8 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) _zoomer->setTrackerPen(c); _UpdateIntensityRangeDisplay(); + + _xAxisMultiplier = 1; } WaterfallDisplayPlot::~WaterfallDisplayPlot() @@ -315,6 +318,8 @@ WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq, double stopFreq = constStopFreq / units; double centerFreq = constCenterFreq / units; + _xAxisMultiplier = units; + _useCenterFrequencyFlag = useCenterFrequencyFlag; if(_useCenterFrequencyFlag){ @@ -544,4 +549,13 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() _lastReplot = get_highres_clock(); } +void +WaterfallDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); + point.setX(point.x() * _xAxisMultiplier); + emit plotPointSelected(point); +} + #endif /* WATERFALL_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h index 6b4e978bb..faa48d6aa 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.h +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -50,10 +51,12 @@ public: public slots: void resizeSlot( QSize *s ); - + void OnPickerPointSelected(const QwtDoublePoint & p); + signals: void UpdatedLowerIntensityLevel(const double); void UpdatedUpperIntensityLevel(const double); + void plotPointSelected(const QPointF p); protected: @@ -62,12 +65,15 @@ private: double _startFrequency; double _stopFrequency; + int _xAxisMultiplier; PlotWaterfall *d_spectrogram; QwtPlotPanner* _panner; QwtPlotZoomer* _zoomer; + QwtDblClickPlotPicker *_picker; + WaterfallData* _waterfallData; timespec _lastReplot; diff --git a/gr-qtgui/lib/qtgui_sink_c.h b/gr-qtgui/lib/qtgui_sink_c.h index 1c9561704..fb0cb6c5f 100644 --- a/gr-qtgui/lib/qtgui_sink_c.h +++ b/gr-qtgui/lib/qtgui_sink_c.h @@ -67,8 +67,6 @@ private: double d_bandwidth; std::string d_name; - //gruel::mutex d_mutex; - bool d_shift; gri_fft_complex *d_fft; @@ -105,7 +103,6 @@ public: void set_update_time(double t); QApplication *d_qApplication; - //qtgui_obj *d_object; int general_work (int noutput_items, gr_vector_int &ninput_items, -- cgit From 117bf31ca76a2751f7e9dfd06860211b7fc14205 Mon Sep 17 00:00:00 2001 From: Mike Cornelius Date: Tue, 12 Apr 2011 21:55:51 -0400 Subject: gr-qtgui: exposing double-click events through spectrumdisplayform and through to Python. --- gr-qtgui/lib/spectrumdisplayform.cc | 37 +++++++++++++++++++++++++++++++++++++ gr-qtgui/lib/spectrumdisplayform.h | 8 +++++++- 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'gr-qtgui/lib') diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index 804dbdd62..238c9889f 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -62,6 +62,19 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) // Create a timer to update plots at the specified rate displayTimer = new QTimer(this); connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer())); + + // Connect double click signals up + connect(_frequencyDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onFFTPlotPointSelected(const QPointF))); + + connect(_waterfallDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onWFallPlotPointSelected(const QPointF))); + + connect(_timeDomainDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onTimePlotPointSelected(const QPointF))); + + connect(_constellationDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onConstPlotPointSelected(const QPointF))); } SpectrumDisplayForm::~SpectrumDisplayForm() @@ -689,3 +702,27 @@ SpectrumDisplayForm::SetUpdateTime(double t) // QTimer class takes millisecond input displayTimer->start(d_update_time*1000); } + +void +SpectrumDisplayForm::onFFTPlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 1); +} + +void +SpectrumDisplayForm::onWFallPlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 2); +} + +void +SpectrumDisplayForm::onTimePlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 3); +} + +void +SpectrumDisplayForm::onConstPlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 4); +} diff --git a/gr-qtgui/lib/spectrumdisplayform.h b/gr-qtgui/lib/spectrumdisplayform.h index 794a8c58e..860edf2d1 100644 --- a/gr-qtgui/lib/spectrumdisplayform.h +++ b/gr-qtgui/lib/spectrumdisplayform.h @@ -71,7 +71,13 @@ private slots: void newFrequencyData( const SpectrumUpdateEvent* ); void UpdateGuiTimer(); -protected: + void onFFTPlotPointSelected(const QPointF p); + void onWFallPlotPointSelected(const QPointF p); + void onTimePlotPointSelected(const QPointF p); + void onConstPlotPointSelected(const QPointF p); + +signals: + void plotPointSelected(const QPointF p, int type); private: void _AverageHistory( const double * newBuffer ); -- cgit