Removing Waterfall3DPlot. The qwt_plot3d is too much of a hassle to deal with and...
[debian/gnuradio] / gr-qtgui / src / lib / spectrumdisplayform.cc
index 481a55264be21d601c0354bff1c4489e2372c84f..e0509a294853715b0f44966a1106b9ffe01c3a06 100644 (file)
@@ -5,23 +5,26 @@
 
 int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1;
 
-SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QDialog(parent){
+SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent)
+  : QWidget(parent)
+{
   setupUi(this);
-  
+
+  _useOpenGL = useOpenGL;
   _systemSpecifiedFlag = false;
   _intValidator = new QIntValidator(this);
   _intValidator->setBottom(0);
-  _frequencyDisplayPlot = new FrequencyDisplayPlot(Tab1PlotDisplayFrame);
-  _waterfallDisplayPlot = new WaterfallDisplayPlot(Tab2PlotDisplayFrame);
-  _waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
+  _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<double*>;
   
-  AvgLineEdit->setValidator(_intValidator);
-  PowerLineEdit->setValidator(_intValidator);
+  AvgLineEdit->setRange(0, 500);                 // Set range of Average box value from 0 to 500
   MinHoldCheckBox_toggled( false );
   MaxHoldCheckBox_toggled( false );
   
@@ -31,36 +34,42 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QDialog(parent){
   WaterfallMinimumIntensityWheel->setTickCnt(50);
   WaterfallMinimumIntensityWheel->setValue(-200);
   
-  Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
-  Waterfall3DMaximumIntensityWheel->setTickCnt(50);
-  Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
-  Waterfall3DMinimumIntensityWheel->setTickCnt(50);
-  Waterfall3DMinimumIntensityWheel->setValue(-200);
-  
   _peakFrequency = 0;
   _peakAmplitude = -HUGE_VAL;
   
   _noiseFloorAmplitude = -HUGE_VAL;
-  
-  connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
-  connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
+
+  connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), 
+         _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
+  connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), 
+         _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
   
   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
-  
+
   // 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(){
+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 _intValidator;
 
   delete[] _realFFTDataPoints;
   delete[] _averagedValues;
@@ -70,9 +79,15 @@ SpectrumDisplayForm::~SpectrumDisplayForm(){
   }
 
   delete _historyVector;
+
+  displayTimer->stop();
+  delete displayTimer;
 }
 
-void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, const uint64_t numTimeDomainDataPoints )
+void
+SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, 
+                               const uint64_t numFFTDataPoints, 
+                               const uint64_t numTimeDomainDataPoints )
 {
   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
   
@@ -85,15 +100,16 @@ void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, const uint64_
   }
 }
 
-void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
+void
+SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
 {
+  //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent);
   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
-  const double timePerFFT = spectrumUpdateEvent->getTimePerFFT();
-  const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();;
+  const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();
   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
@@ -102,42 +118,55 @@ void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumU
   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
 
   // Calculate the Magnitude of the complex point
-  const std::complex<float>* complexDataPointsPtr = complexDataPoints;
+  const std::complex<float>* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2;
   double* realFFTDataPointsPtr = _realFFTDataPoints;
-  for(uint64_t point = 0; point < numFFTDataPoints; point++){
-    // Calculate dBm
-    // 50 ohm load assumption
-    // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
-    // 75 ohm load assumption
-    // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
+
+  double sumMean = 0.0;
+  double localPeakAmplitude = -HUGE_VAL;
+  double localPeakFrequency = 0.0;
+  const double fftBinSize = (_stopFrequency-_startFrequency) /
+    static_cast<double>(numFFTDataPoints);
+
+  // Run this twice to perform the fftshift operation on the data here as well
+  std::complex<float> scaleFactor = std::complex<float>((float)numFFTDataPoints);
+  for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
+    std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor;
+    *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
+
+    if(*realFFTDataPointsPtr > localPeakAmplitude) {
+      localPeakFrequency = static_cast<float>(point) * fftBinSize;
+      localPeakAmplitude = *realFFTDataPointsPtr;
+    }
+    sumMean += *realFFTDataPointsPtr;
     
-    *realFFTDataPointsPtr = 10.0*log10((((*complexDataPointsPtr).real() * (*complexDataPointsPtr).real()) + ((*complexDataPointsPtr).imag()*(*complexDataPointsPtr).imag())) + 1e-20);
+    complexDataPointsPtr++;
+    realFFTDataPointsPtr++;
+  }
+  
+  // This loop takes the first half of the input data and puts it in the 
+  // second half of the plotted data
+  complexDataPointsPtr = complexDataPoints;
+  for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
+    std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor;
+    *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
+
+    if(*realFFTDataPointsPtr > localPeakAmplitude) {
+      localPeakFrequency = static_cast<float>(point) * fftBinSize;
+      localPeakAmplitude = *realFFTDataPointsPtr;
+    }
+    sumMean += *realFFTDataPointsPtr;
 
     complexDataPointsPtr++;
     realFFTDataPointsPtr++;
   }
 
   // Don't update the averaging history if this is repeated data
   if(!repeatDataFlag){
     _AverageHistory(_realFFTDataPoints);
 
-    double sumMean;
-    const double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(numFFTDataPoints);
-
-    // find the peak, sum (for mean), etc
-    _peakAmplitude = -HUGE_VAL;
-    sumMean = 0.0;
-    for(uint64_t number = 0; number < numFFTDataPoints; number++){
-      // find peak
-      if(_realFFTDataPoints[number] > _peakAmplitude){
-        _peakFrequency = (static_cast<float>(number) * fft_bin_size);  // Calculate the frequency relative to the local bw, adjust for _startFrequency later
-        _peakAmplitude = _realFFTDataPoints[number];
-        // _peakBin = number;
-      }
-      // sum (for mean)
-      sumMean += _realFFTDataPoints[number];
-    }
+    // 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
@@ -161,115 +190,79 @@ void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumU
   }
 
   if(lastOfMultipleUpdatesFlag){
-    _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, _noiseFloorAmplitude, _peakFrequency, _peakAmplitude);
-    _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, imagTimeDomainDataPoints, numTimeDomainDataPoints);
-  }
-  // Don't update the repeated data for the waterfall
-  if(!repeatDataFlag){
-    _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, timePerFFT, dataTimestamp, spectrumUpdateEvent->getDroppedFFTFrames());
-    if( _openGLWaterfall3DFlag == 1 ){
-      _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, timePerFFT, dataTimestamp, spectrumUpdateEvent->getDroppedFFTFrames());
+    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();
     }
-  }
-  
-  // Tell the system the GUI has been updated
-  if(_systemSpecifiedFlag){
-    _system->SetLastGUIUpdateTime(generatedTimestamp);
-    _system->DecrementPendingGUIUpdateEvents();
   }
 }
 
-void SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
+void
+SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
 {
-  // Let the actual window resize its width, but not its height
-  QSize newSize(e->size().width(), e->oldSize().height());
-  QResizeEvent et(newSize, e->oldSize());
-  QWidget::resizeEvent(&et);
-
-  // Tell the Tab Window to Resize
-  SpectrumTypeTab->resize( e->size().width(), SpectrumTypeTab->height());
-
-  // Tell the TabXFreqDisplay to resize
-  Tab1PlotDisplayFrame->resize(e->size().width()-4, Tab1PlotDisplayFrame->height());
-  Tab2PlotDisplayFrame->resize(e->size().width()-4, Tab2PlotDisplayFrame->height());
-  Waterfall3DPlotDisplayFrame->resize(e->size().width()-4, Waterfall3DPlotDisplayFrame->height());
-  TimeDomainDisplayFrame->resize(e->size().width()-4, TimeDomainDisplayFrame->height());
-  _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4, Tab1PlotDisplayFrame->height());
-  _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4, Tab2PlotDisplayFrame->height());
-  _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4, Waterfall3DPlotDisplayFrame->height());
-  _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4, TimeDomainDisplayFrame->height());
-
-  // Move the IntensityWheels and Labels
-  WaterfallMaximumIntensityLabel->move(width() - 5 - WaterfallMaximumIntensityLabel->width(), WaterfallMaximumIntensityLabel->y());
-  WaterfallMinimumIntensityLabel->move(width() - 5 - WaterfallMinimumIntensityLabel->width(), WaterfallMinimumIntensityLabel->y());
-  WaterfallMaximumIntensityWheel->resize(WaterfallMaximumIntensityLabel->x() - 5 - WaterfallMaximumIntensityWheel->x(), WaterfallMaximumIntensityWheel->height());
-  WaterfallMinimumIntensityWheel->resize(WaterfallMinimumIntensityLabel->x() - 5 - WaterfallMinimumIntensityWheel->x(), WaterfallMinimumIntensityWheel->height());
-
-  Waterfall3DMaximumIntensityLabel->move(width() - 5 - Waterfall3DMaximumIntensityLabel->width(), Waterfall3DMaximumIntensityLabel->y());
-  Waterfall3DMinimumIntensityLabel->move(width() - 5 - Waterfall3DMinimumIntensityLabel->width(), Waterfall3DMinimumIntensityLabel->y());
-  Waterfall3DMaximumIntensityWheel->resize(Waterfall3DMaximumIntensityLabel->x() - 5 - Waterfall3DMaximumIntensityWheel->x(), Waterfall3DMaximumIntensityWheel->height());
-  Waterfall3DMinimumIntensityWheel->resize(Waterfall3DMinimumIntensityLabel->x() - 5 - Waterfall3DMinimumIntensityWheel->x(), Waterfall3DMinimumIntensityWheel->height());
-
-
-  // Move the Power Lbl
-  PowerLabel->move(e->size().width()-(415-324) - PowerLabel->width(), PowerLabel->y());
-
-  // Move the Power Line Edit
-  PowerLineEdit->move(e->size().width()-(415-318) - PowerLineEdit->width(), PowerLineEdit->y());
-
-  // Move the Avg Lbl
-  AvgLabel->move(e->size().width()-(415-406) - AvgLabel->width(), AvgLabel->y());
-
-  // Move the Avg Line Edit
-  AvgLineEdit->move(e->size().width()-(415-400) - AvgLineEdit->width(), AvgLineEdit->y());
-  
-  // Move the FFT Size Combobox and label
-  FFTSizeComboBox->move(width() - 5 - FFTSizeComboBox->width(), FFTSizeComboBox->y());
-  FFTSizeLabel->move(width() - 10 - FFTSizeComboBox->width() - FFTSizeLabel->width(), FFTSizeLabel->y());
+  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)
+void
+SpectrumDisplayForm::customEvent( QEvent * e)
 {
   if(e->type() == QEvent::User+3){
     if(_systemSpecifiedFlag){
       WindowComboBox->setCurrentIndex(_system->GetWindowType());
       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
       //FFTSizeComboBox->setCurrentIndex(1);
-      PowerLineEdit_textChanged(PowerLineEdit->text());
     }
 
     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
 
-    waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
-    waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
-
-    // If the video card doesn't support OpenGL then don't display the 3D Waterfall
-    if(QGLFormat::hasOpenGL()){
-      // Check for Hardware Acceleration of the OpenGL
-      if(!_waterfall3DDisplayPlot->format().directRendering()){
-       // Only ask this once while the program is running...
-       if(_openGLWaterfall3DFlag == -1){
-         _openGLWaterfall3DFlag = 0;
-         if(QMessageBox::warning(this, "OpenGL Direct Rendering NOT Supported", "<center>The system's video card hardware or current drivers do not support direct hardware rendering of the OpenGL modules.</center><br><center>Software rendering is VERY processor intensive.</center><br><center>Do you want to use software rendering?</center>", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes){
-           _openGLWaterfall3DFlag = 1;
-         }
-       }
-      }
-      else{
-       _openGLWaterfall3DFlag = 1;
-      }
-    }
-
-    if(_openGLWaterfall3DFlag != 1){
-      SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
-    }
-
     // Clear any previous display
     Reset();
-
-    show();
   }
   else if(e->type() == 10005){
     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
@@ -293,20 +286,27 @@ void SpectrumDisplayForm::customEvent( QEvent * e)
   }
 }
 
-void SpectrumDisplayForm::AvgLineEdit_textChanged( const QString &valueString )
+void
+SpectrumDisplayForm::UpdateGuiTimer()
 {
-  if(!valueString.isEmpty()){
-    int value = valueString.toInt();
-    if(value > 500){
-      value = 500;
-      AvgLineEdit->setText("500");
-    }
-    SetAverageCount(value);
-  }
+  // 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::MaxHoldCheckBox_toggled( bool newState )
+void
+SpectrumDisplayForm::AvgLineEdit_valueChanged( int value )
+{
+  SetAverageCount(value);
+}
+
+
+void
+SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
 {
   MaxHoldResetBtn->setEnabled(newState);
   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
@@ -314,7 +314,8 @@ void SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
 }
 
 
-void SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
+void
+SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
 {
   MinHoldResetBtn->setEnabled(newState);
   _frequencyDisplayPlot->SetMinFFTVisible(newState);
@@ -322,55 +323,78 @@ void SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
 }
 
 
-void SpectrumDisplayForm::MinHoldResetBtn_clicked()
+void
+SpectrumDisplayForm::MinHoldResetBtn_clicked()
 {
   _frequencyDisplayPlot->ClearMinData();
   _frequencyDisplayPlot->replot();
 }
 
 
-void SpectrumDisplayForm::MaxHoldResetBtn_clicked()
+void
+SpectrumDisplayForm::MaxHoldResetBtn_clicked()
 {
   _frequencyDisplayPlot->ClearMaxData();
   _frequencyDisplayPlot->replot();
 }
 
 
-void SpectrumDisplayForm::PowerLineEdit_textChanged( const QString &valueString )
+void
+SpectrumDisplayForm::TabChanged(int index)
 {
-  if(_systemSpecifiedFlag){
-    if(!valueString.isEmpty()){
-      double value = valueString.toDouble();
-      if(value < 1.0){
-       value = 1.0;
-       PowerLineEdit->setText("1");
-      }
-      _system->SetPowerValue(value);
-    }
-
-    if(_system->GetPowerValue() > 1){
-      UseRFFrequenciesCheckBox->setChecked(false);
-      UseRFFrequenciesCheckBox->setEnabled(false);
-      UseRFFrequenciesCB(false);
-    }
-    else{
-      UseRFFrequenciesCheckBox->setEnabled(true);
-    }
-  }
+  // This might be dangerous to call this with NULL
+  resizeEvent(NULL);  
 }
 
-void SpectrumDisplayForm::SetFrequencyRange(const double newStartFrequency, const double newStopFrequency, const double newCenterFrequency){
-  _frequencyDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
-  _waterfallDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
-  _waterfall3DDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
+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<int>(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(){
+int
+SpectrumDisplayForm::GetAverageCount()
+{
   return _historyVector->size();
 }
 
-void SpectrumDisplayForm::SetAverageCount(const int newCount){
+void
+SpectrumDisplayForm::SetAverageCount(const int newCount)
+{
   if(newCount > -1){
     if(newCount != static_cast<int>(_historyVector->size())){
       std::vector<double*>::iterator pos;
@@ -388,10 +412,13 @@ void SpectrumDisplayForm::SetAverageCount(const int newCount){
   }
 }
 
-void SpectrumDisplayForm::_AverageHistory(const double* newBuffer){
+void
+SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
+{
   if(_numRealDataPoints > 0){
     if(_historyVector->size() > 0){
-      memcpy(_historyVector->operator[](_historyEntry), newBuffer, _numRealDataPoints*sizeof(double));
+      memcpy(_historyVector->operator[](_historyEntry), newBuffer,
+            _numRealDataPoints*sizeof(double));
 
       // Increment the next location to store data
       _historyEntryCount++;
@@ -416,7 +443,10 @@ void SpectrumDisplayForm::_AverageHistory(const double* newBuffer){
   }
 }
 
-void SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, const uint64_t /*numTimeDomainDataPoints*/ ){
+void
+SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
+                                   const uint64_t /*numTimeDomainDataPoints*/ )
+{
   // Convert from Complex to Real for certain Displays
   if(_numRealDataPoints != numFFTDataPoints){
     _numRealDataPoints = numFFTDataPoints;
@@ -435,15 +465,18 @@ void SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, const
   }
 }
 
-void SpectrumDisplayForm::Reset(){
+void
+SpectrumDisplayForm::Reset()
+{
   AverageDataReset();
 
   _waterfallDisplayPlot->Reset();
-  _waterfall3DDisplayPlot->Reset();
 }
 
 
-void SpectrumDisplayForm::AverageDataReset(){
+void
+SpectrumDisplayForm::AverageDataReset()
+{
   _historyEntry = 0;
   _historyEntryCount = 0;
 
@@ -454,7 +487,8 @@ void SpectrumDisplayForm::AverageDataReset(){
 }
 
 
-void SpectrumDisplayForm::closeEvent( QCloseEvent *e )
+void
+SpectrumDisplayForm::closeEvent( QCloseEvent *e )
 {
   if(_systemSpecifiedFlag){
     _system->SetWindowOpenFlag(false);
@@ -466,7 +500,8 @@ void SpectrumDisplayForm::closeEvent( QCloseEvent *e )
 }
 
 
-void SpectrumDisplayForm::WindowTypeChanged( int newItem )
+void
+SpectrumDisplayForm::WindowTypeChanged( int newItem )
 {
   if(_systemSpecifiedFlag){
    _system->SetWindowType(newItem);
@@ -474,18 +509,15 @@ void SpectrumDisplayForm::WindowTypeChanged( int newItem )
 }
 
 
-void SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
+void
+SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
 {
-  if(useRFFlag){
-    SetFrequencyRange(_startFrequency, _stopFrequency, _centerFrequency);
-  }
-  else{
-    SetFrequencyRange(_startFrequency, _stopFrequency, 0.0 );
-  }
+  SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
 }
 
 
-void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
+void
+SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
 {
   if(newValue > WaterfallMinimumIntensityWheel->value()){
     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
@@ -493,11 +525,14 @@ void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
   else{
     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
   }
-  _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
+
+  _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
+                                          WaterfallMaximumIntensityWheel->value());
 }
 
 
-void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
+void
+SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
 {
   if(newValue < WaterfallMaximumIntensityWheel->value()){
     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
@@ -505,34 +540,13 @@ void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
   else{
     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
   }
-  _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
-}
-
-void SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
-{
-  if(newValue > Waterfall3DMinimumIntensityWheel->value()){
-    Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
-  }
-  else{
-    Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
-  }
-  _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
-}
 
-
-void SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
-{
-  if(newValue < Waterfall3DMaximumIntensityWheel->value()){
-    Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
-  }
-  else{
-    Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
-  }
-  _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
+  _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
+                                          WaterfallMaximumIntensityWheel->value());
 }
 
-
-void SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
+void
+SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
 {
   if(_systemSpecifiedFlag){
     _system->SetFFTSize(fftSizeString.toLong());
@@ -540,7 +554,8 @@ void SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
 }
 
 
-void SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
+void
+SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
 {
   double minimumIntensity = _noiseFloorAmplitude - 5;
   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
@@ -555,22 +570,8 @@ void SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
   waterfallMaximumIntensityChangedCB(maximumIntensity);
 }
 
-void SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
-{
-  double minimumIntensity = _noiseFloorAmplitude - 5;
-  if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
-    minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
-  }
-  Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
-  double maximumIntensity = _peakAmplitude + 10;
-  if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
-    maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
-  }
-  Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
-  waterfallMaximumIntensityChangedCB(maximumIntensity);
-}
-
-void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
+void
+SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
 {
   QColor lowIntensityColor;
   QColor highIntensityColor;
@@ -582,7 +583,7 @@ void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
     }
     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()){
@@ -591,29 +592,100 @@ void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
     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::Waterfall3DIntensityColorTypeChanged( int newType )
+void
+SpectrumDisplayForm::ToggleTabFrequency(const bool state)
 {
-  QColor lowIntensityColor;
-  QColor highIntensityColor;
-  if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
-    // Select the Low Intensity Color
-    lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
-    if(!lowIntensityColor.isValid()){
-      lowIntensityColor = Qt::black;
+  if(state == true) {
+    if(d_plot_fft == -1) {
+      SpectrumTypeTab->addTab(FrequencyPage, "Frequency Display");
+      d_plot_fft = SpectrumTypeTab->count()-1;
     }
-    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);
+  }
+  else {
+    SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(FrequencyPage));
+    d_plot_fft = -1;
+  }
+}
 
-    // Select the High Intensity Color
-    highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
-    if(!highIntensityColor.isValid()){
-      highIntensityColor = Qt::white;
+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;
     }
-    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);
   }
-  _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
+  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);
 }