91abbd36ff6e0d4f95620f529985a63c9c82b76a
[debian/gnuradio] / gr-qtgui / src / lib / spectrumdisplayform.cc
1 #include <cmath>
2 #include <QColorDialog>
3 #include <QMessageBox>
4 #include <spectrumdisplayform.h>
5
6 int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1;
7
8 SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent)
9   : QWidget(parent)
10 {
11   setupUi(this);
12
13   _useOpenGL = useOpenGL;
14   _systemSpecifiedFlag = false;
15   _intValidator = new QIntValidator(this);
16   _intValidator->setBottom(0);
17   _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame);
18   _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame);
19
20   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
21     //_waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
22   }
23
24   _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
25   _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame);
26   _numRealDataPoints = 1024;
27   _realFFTDataPoints = new double[_numRealDataPoints];
28   _averagedValues = new double[_numRealDataPoints];
29   _historyVector = new std::vector<double*>;
30   
31   AvgLineEdit->setRange(0, 500);                 // Set range of Average box value from 0 to 500
32   MinHoldCheckBox_toggled( false );
33   MaxHoldCheckBox_toggled( false );
34   
35   WaterfallMaximumIntensityWheel->setRange(-200, 0);
36   WaterfallMaximumIntensityWheel->setTickCnt(50);
37   WaterfallMinimumIntensityWheel->setRange(-200, 0);
38   WaterfallMinimumIntensityWheel->setTickCnt(50);
39   WaterfallMinimumIntensityWheel->setValue(-200);
40   
41   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
42     Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
43     Waterfall3DMaximumIntensityWheel->setTickCnt(50);
44     Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
45     Waterfall3DMinimumIntensityWheel->setTickCnt(50);
46     Waterfall3DMinimumIntensityWheel->setValue(-200);
47   }
48
49   _peakFrequency = 0;
50   _peakAmplitude = -HUGE_VAL;
51   
52   _noiseFloorAmplitude = -HUGE_VAL;
53
54   connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), 
55           _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
56   connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), 
57           _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
58   
59   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
60   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
61
62   // Load up the acceptable FFT sizes...
63   FFTSizeComboBox->clear();
64   for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
65     FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
66   }
67   Reset();
68
69   ToggleTabFrequency(false);
70   ToggleTabWaterfall(false);
71   ToggleTabWaterfall3D(false);
72   ToggleTabTime(false);
73   ToggleTabConstellation(false);
74
75   // Create a timer to update plots at the specified rate
76   displayTimer = new QTimer(this);
77   connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer()));
78 }
79
80 SpectrumDisplayForm::~SpectrumDisplayForm()
81 {
82   // Qt deletes children when parent is deleted
83
84   // Don't worry about deleting Display Plots - they are deleted when parents are deleted
85   delete _intValidator;
86
87   delete[] _realFFTDataPoints;
88   delete[] _averagedValues;
89
90   for(unsigned int count = 0; count < _historyVector->size(); count++){
91     delete[] _historyVector->operator[](count);
92   }
93
94   delete _historyVector;
95
96   displayTimer->stop();
97   delete displayTimer;
98 }
99
100 void
101 SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, 
102                                 const uint64_t numFFTDataPoints, 
103                                 const uint64_t numTimeDomainDataPoints )
104 {
105   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
106   
107   if(newSystem != NULL){
108     _system = newSystem;
109     _systemSpecifiedFlag = true;
110   }
111   else{
112     _systemSpecifiedFlag = false;
113   }
114 }
115
116 void
117 SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
118 {
119   //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent);
120   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
121   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
122   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
123   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
124   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
125   const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();
126   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
127   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
128   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
129
130   // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
131   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
132
133   // Calculate the Magnitude of the complex point
134   const std::complex<float>* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2;
135   double* realFFTDataPointsPtr = _realFFTDataPoints;
136
137   // Run this twice to perform the fftshift operation on the data here as well
138   for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
139     std::complex<float> pt = (*complexDataPointsPtr) / (float)numFFTDataPoints;
140     *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
141
142     complexDataPointsPtr++;
143     realFFTDataPointsPtr++;
144   }
145   
146   // This loop takes the first half of the input data and puts it in the 
147   // second half of the plotted data
148   complexDataPointsPtr = complexDataPoints;
149   for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
150     std::complex<float> pt = (*complexDataPointsPtr) / (float)numFFTDataPoints;
151     *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
152
153     complexDataPointsPtr++;
154     realFFTDataPointsPtr++;
155   }
156
157   // Don't update the averaging history if this is repeated data
158   if(!repeatDataFlag){
159     _AverageHistory(_realFFTDataPoints);
160
161     double sumMean;
162     const double fft_bin_size = (_stopFrequency-_startFrequency) /
163       static_cast<double>(numFFTDataPoints);
164
165     // find the peak, sum (for mean), etc
166     _peakAmplitude = -HUGE_VAL;
167     sumMean = 0.0;
168     for(uint64_t number = 0; number < numFFTDataPoints; number++){
169       // find peak
170       if(_realFFTDataPoints[number] > _peakAmplitude){
171         // Calculate the frequency relative to the local bw, adjust for _startFrequency later
172         _peakFrequency = (static_cast<float>(number) * fft_bin_size);
173         _peakAmplitude = _realFFTDataPoints[number];
174       }
175       sumMean += _realFFTDataPoints[number];
176     }
177
178     // calculate the spectral mean
179     // +20 because for the comparison below we only want to throw out bins
180     // that are significantly higher (and would, thus, affect the mean more)
181     const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
182
183     // now throw out any bins higher than the mean
184     sumMean = 0.0;
185     uint64_t newNumDataPoints = numFFTDataPoints;
186     for(uint64_t number = 0; number < numFFTDataPoints; number++){
187       if (_realFFTDataPoints[number] <= meanAmplitude)
188         sumMean += _realFFTDataPoints[number];
189       else
190         newNumDataPoints--;
191     }
192
193     if (newNumDataPoints == 0)             // in the odd case that all
194       _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
195     else
196       _noiseFloorAmplitude = sumMean / newNumDataPoints;
197   }
198
199   if(lastOfMultipleUpdatesFlag){
200     int tabindex = SpectrumTypeTab->currentIndex();
201     if(tabindex == d_plot_fft) {
202       _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, 
203                                          _noiseFloorAmplitude, _peakFrequency, 
204                                          _peakAmplitude, d_update_time);
205     }
206     if(tabindex == d_plot_time) {
207       _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
208                                           imagTimeDomainDataPoints, 
209                                           numTimeDomainDataPoints,
210                                           d_update_time);
211     }
212     if(tabindex == d_plot_constellation) {
213       _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
214                                              imagTimeDomainDataPoints, 
215                                              numTimeDomainDataPoints,
216                                              d_update_time);
217     }
218
219     // Don't update the repeated data for the waterfall
220     if(!repeatDataFlag){
221       if(tabindex == d_plot_waterfall) {
222         _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
223                                            d_update_time, dataTimestamp, 
224                                            spectrumUpdateEvent->getDroppedFFTFrames());
225       }
226       /*
227       if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
228         if( _openGLWaterfall3DFlag == 1 && (tabindex == d_plot_waterfall3d)) {
229           _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
230                                                d_update_time, dataTimestamp, 
231                                                spectrumUpdateEvent->getDroppedFFTFrames());
232         }
233       }
234       */
235     }
236
237     
238     // Tell the system the GUI has been updated
239     if(_systemSpecifiedFlag){
240       _system->SetLastGUIUpdateTime(generatedTimestamp);
241       _system->DecrementPendingGUIUpdateEvents();
242     }
243   }
244 }
245
246 void
247 SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
248 {
249   QSize s;
250   s.setWidth(FrequencyPlotDisplayFrame->width());
251   s.setHeight(FrequencyPlotDisplayFrame->height());
252   emit _frequencyDisplayPlot->resizeSlot(&s);
253
254   s.setWidth(TimeDomainDisplayFrame->width());
255   s.setHeight(TimeDomainDisplayFrame->height());
256   emit _timeDomainDisplayPlot->resizeSlot(&s);
257
258   s.setWidth(WaterfallPlotDisplayFrame->width());
259   s.setHeight(WaterfallPlotDisplayFrame->height());
260   emit _waterfallDisplayPlot->resizeSlot(&s);
261
262   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
263     s.setWidth(Waterfall3DPlotDisplayFrame->width());
264     s.setHeight(Waterfall3DPlotDisplayFrame->height());
265     //emit _waterfall3DDisplayPlot->resizeSlot(&s);
266   }
267
268   s.setWidth(ConstellationDisplayFrame->width());
269   s.setHeight(ConstellationDisplayFrame->height());
270   emit _constellationDisplayPlot->resizeSlot(&s);
271 }
272
273 void
274 SpectrumDisplayForm::customEvent( QEvent * e)
275 {
276   if(e->type() == QEvent::User+3){
277     if(_systemSpecifiedFlag){
278       WindowComboBox->setCurrentIndex(_system->GetWindowType());
279       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
280       //FFTSizeComboBox->setCurrentIndex(1);
281     }
282
283     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
284     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
285
286     // If the video card doesn't support OpenGL then don't display the 3D Waterfall
287     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
288       waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
289       waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
290       
291       // Check for Hardware Acceleration of the OpenGL
292       /*
293       if(!_waterfall3DDisplayPlot->format().directRendering()){
294         // Only ask this once while the program is running...
295         if(_openGLWaterfall3DFlag == -1){
296           _openGLWaterfall3DFlag = 0;
297           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){
298             _openGLWaterfall3DFlag = 1;
299           }
300         }
301       }
302       else{
303         _openGLWaterfall3DFlag = 1;
304       }
305       */
306     }
307     
308     if(_openGLWaterfall3DFlag != 1){
309       ToggleTabWaterfall3D(false);
310     }
311
312     // Clear any previous display
313     Reset();
314   }
315   else if(e->type() == 10005){
316     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
317     newFrequencyData(spectrumUpdateEvent);
318   }
319   else if(e->type() == 10008){
320     setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
321   }
322   else if(e->type() == 10009){
323     Reset();
324     if(_systemSpecifiedFlag){
325       _system->ResetPendingGUIUpdateEvents();
326     }
327   }
328   else if(e->type() == 10010){
329     _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
330     _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
331     _centerFrequency  = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
332
333     UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
334   }
335 }
336
337 void
338 SpectrumDisplayForm::UpdateGuiTimer()
339 {
340   // This is called by the displayTimer and redraws the canvases of
341   // all of the plots.
342   _frequencyDisplayPlot->canvas()->update();
343   _waterfallDisplayPlot->canvas()->update();
344   //if((QGLFormat::hasOpenGL()) && (_useOpenGL))
345   //_waterfall3DDisplayPlot->canvas()->update();
346   _timeDomainDisplayPlot->canvas()->update();
347   _constellationDisplayPlot->canvas()->update();
348 }
349
350
351 void
352 SpectrumDisplayForm::AvgLineEdit_valueChanged( int value )
353 {
354   SetAverageCount(value);
355 }
356
357
358 void
359 SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
360 {
361   MaxHoldResetBtn->setEnabled(newState);
362   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
363   MaxHoldResetBtn_clicked();
364 }
365
366
367 void
368 SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
369 {
370   MinHoldResetBtn->setEnabled(newState);
371   _frequencyDisplayPlot->SetMinFFTVisible(newState);
372   MinHoldResetBtn_clicked();
373 }
374
375
376 void
377 SpectrumDisplayForm::MinHoldResetBtn_clicked()
378 {
379   _frequencyDisplayPlot->ClearMinData();
380   _frequencyDisplayPlot->replot();
381 }
382
383
384 void
385 SpectrumDisplayForm::MaxHoldResetBtn_clicked()
386 {
387   _frequencyDisplayPlot->ClearMaxData();
388   _frequencyDisplayPlot->replot();
389 }
390
391
392 void
393 SpectrumDisplayForm::TabChanged(int index)
394 {
395   // This might be dangerous to call this with NULL
396   resizeEvent(NULL);  
397 }
398
399 void
400 SpectrumDisplayForm::SetFrequencyRange(const double newCenterFrequency,
401                                        const double newStartFrequency, 
402                                        const double newStopFrequency)
403 {
404   double fdiff;
405   if(UseRFFrequenciesCheckBox->isChecked()) {
406     fdiff = newCenterFrequency;
407   }
408   else {
409     fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
410   }
411
412   if(fdiff > 0) {
413     std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
414     std::string strtime[4] = {"sec", "ms", "us", "ns"};
415     double units10 = floor(log10(fdiff));
416     double units3  = std::max(floor(units10 / 3.0), 0.0);
417     double units = pow(10, (units10-fmod(units10, 3.0)));
418     int iunit = static_cast<int>(units3);
419     
420     _startFrequency = newStartFrequency;
421     _stopFrequency = newStopFrequency;
422     _centerFrequency = newCenterFrequency;
423
424     _frequencyDisplayPlot->SetFrequencyRange(_startFrequency,
425                                              _stopFrequency,
426                                              _centerFrequency,
427                                              UseRFFrequenciesCheckBox->isChecked(),
428                                              units, strunits[iunit]);
429     _waterfallDisplayPlot->SetFrequencyRange(_startFrequency,
430                                              _stopFrequency,
431                                              _centerFrequency,
432                                              UseRFFrequenciesCheckBox->isChecked(),
433                                              units, strunits[iunit]);
434     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
435       /*
436       _waterfall3DDisplayPlot->SetFrequencyRange(_startFrequency,
437                                                  _stopFrequency,
438                                                  _centerFrequency,
439                                                  UseRFFrequenciesCheckBox->isChecked(),
440                                                  units, strunits[iunit]);
441       */
442     }
443     _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency,
444                                           units, strtime[iunit]);
445   }
446 }
447
448 int
449 SpectrumDisplayForm::GetAverageCount()
450 {
451   return _historyVector->size();
452 }
453
454 void
455 SpectrumDisplayForm::SetAverageCount(const int newCount)
456 {
457   if(newCount > -1){
458     if(newCount != static_cast<int>(_historyVector->size())){
459       std::vector<double*>::iterator pos;
460       while(newCount < static_cast<int>(_historyVector->size())){
461         pos = _historyVector->begin();
462         delete[] (*pos);
463         _historyVector->erase(pos);
464       }
465
466       while(newCount > static_cast<int>(_historyVector->size())){
467         _historyVector->push_back(new double[_numRealDataPoints]);
468       }
469       AverageDataReset();
470     }
471   }
472 }
473
474 void
475 SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
476 {
477   if(_numRealDataPoints > 0){
478     if(_historyVector->size() > 0){
479       memcpy(_historyVector->operator[](_historyEntry), newBuffer,
480              _numRealDataPoints*sizeof(double));
481
482       // Increment the next location to store data
483       _historyEntryCount++;
484       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
485         _historyEntryCount = _historyVector->size();
486       }
487       _historyEntry = (++_historyEntry)%_historyVector->size();
488
489       // Total up and then average the values
490       double sum;
491       for(uint64_t location = 0; location < _numRealDataPoints; location++){
492         sum = 0;
493         for(int number = 0; number < _historyEntryCount; number++){
494           sum += _historyVector->operator[](number)[location];
495         }
496         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
497       }
498     }
499     else{
500       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
501     }
502   }
503 }
504
505 void
506 SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
507                                     const uint64_t /*numTimeDomainDataPoints*/ )
508 {
509   // Convert from Complex to Real for certain Displays
510   if(_numRealDataPoints != numFFTDataPoints){
511     _numRealDataPoints = numFFTDataPoints;
512     delete[] _realFFTDataPoints;
513     delete[] _averagedValues;
514     
515     _realFFTDataPoints = new double[_numRealDataPoints];
516     _averagedValues = new double[_numRealDataPoints];
517     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
518     
519     const int historySize = _historyVector->size();
520     SetAverageCount(0); // Clear the existing history
521     SetAverageCount(historySize);
522     
523     Reset();
524   }
525 }
526
527 void
528 SpectrumDisplayForm::Reset()
529 {
530   AverageDataReset();
531
532   _waterfallDisplayPlot->Reset();
533   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
534     //_waterfall3DDisplayPlot->Reset();
535   }
536 }
537
538
539 void
540 SpectrumDisplayForm::AverageDataReset()
541 {
542   _historyEntry = 0;
543   _historyEntryCount = 0;
544
545   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
546
547   MaxHoldResetBtn_clicked();
548   MinHoldResetBtn_clicked();
549 }
550
551
552 void
553 SpectrumDisplayForm::closeEvent( QCloseEvent *e )
554 {
555   if(_systemSpecifiedFlag){
556     _system->SetWindowOpenFlag(false);
557   }
558
559   qApp->processEvents();
560
561   QWidget::closeEvent(e);
562 }
563
564
565 void
566 SpectrumDisplayForm::WindowTypeChanged( int newItem )
567 {
568   if(_systemSpecifiedFlag){
569    _system->SetWindowType(newItem);
570   }
571 }
572
573
574 void
575 SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
576 {
577   SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
578 }
579
580
581 void
582 SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
583 {
584   if(newValue > WaterfallMinimumIntensityWheel->value()){
585     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
586   }
587   else{
588     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
589   }
590
591   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
592                                            WaterfallMaximumIntensityWheel->value());
593 }
594
595
596 void
597 SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
598 {
599   if(newValue < WaterfallMaximumIntensityWheel->value()){
600     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
601   }
602   else{
603     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
604   }
605
606   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
607                                            WaterfallMaximumIntensityWheel->value());
608 }
609
610 void
611 SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
612 {
613   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
614     if(newValue > Waterfall3DMinimumIntensityWheel->value()){
615       Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
616     }
617     else{
618       Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
619     }
620
621     /*
622     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
623                                                Waterfall3DMaximumIntensityWheel->value());
624     */
625   }
626 }
627
628
629 void
630 SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
631 {
632   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
633     if(newValue < Waterfall3DMaximumIntensityWheel->value()){
634       Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
635     }
636     else{
637       Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
638     }
639
640     /*
641     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
642                                                Waterfall3DMaximumIntensityWheel->value());
643     */
644   }
645 }
646
647
648 void
649 SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
650 {
651   if(_systemSpecifiedFlag){
652     _system->SetFFTSize(fftSizeString.toLong());
653   }
654 }
655
656
657 void
658 SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
659 {
660   double minimumIntensity = _noiseFloorAmplitude - 5;
661   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
662     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
663   }
664   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
665   double maximumIntensity = _peakAmplitude + 10;
666   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
667     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
668   }
669   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
670   waterfallMaximumIntensityChangedCB(maximumIntensity);
671 }
672
673 void
674 SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
675 {
676   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
677     double minimumIntensity = _noiseFloorAmplitude - 5;
678     if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
679       minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
680     }
681     Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
682     double maximumIntensity = _peakAmplitude + 10;
683     if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
684       maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
685     }
686     Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
687     waterfallMaximumIntensityChangedCB(maximumIntensity);
688   }
689 }
690
691 void
692 SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
693 {
694   QColor lowIntensityColor;
695   QColor highIntensityColor;
696   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
697     // Select the Low Intensity Color
698     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
699     if(!lowIntensityColor.isValid()){
700       lowIntensityColor = Qt::black;
701     }
702     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
703     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
704     
705     // Select the High Intensity Color
706     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
707     if(!highIntensityColor.isValid()){
708       highIntensityColor = Qt::white;
709     }
710     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
711     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
712   }
713   
714   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
715 }
716
717 void
718 SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
719 {
720   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
721     QColor lowIntensityColor;
722     QColor highIntensityColor;
723     if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
724       // Select the Low Intensity Color
725       lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
726       if(!lowIntensityColor.isValid()){
727         lowIntensityColor = Qt::black;
728       }
729       QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
730       lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
731       
732       // Select the High Intensity Color
733       highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
734       if(!highIntensityColor.isValid()){
735         highIntensityColor = Qt::white;
736       }
737       QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
738       highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
739     }
740     /*
741     _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor,
742                                                       highIntensityColor);
743     */
744   }
745 }
746
747
748 void
749 SpectrumDisplayForm::ToggleTabFrequency(const bool state)
750 {
751   if(state == true) {
752     if(d_plot_fft == -1) {
753       SpectrumTypeTab->addTab(FrequencyPage, "Frequency Display");
754       d_plot_fft = SpectrumTypeTab->count()-1;
755     }
756   }
757   else {
758     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(FrequencyPage));
759     d_plot_fft = -1;
760   }
761 }
762
763 void
764 SpectrumDisplayForm::ToggleTabWaterfall(const bool state)
765 {
766   if(state == true) {
767     if(d_plot_waterfall == -1) {
768       SpectrumTypeTab->addTab(WaterfallPage, "Waterfall Display");
769       d_plot_waterfall = SpectrumTypeTab->count()-1;
770     }
771   }
772   else {
773     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(WaterfallPage));
774     d_plot_waterfall = -1;
775   }
776 }
777
778 void
779 SpectrumDisplayForm::ToggleTabWaterfall3D(const bool state)
780 {
781   if(state == true) {
782     /*
783     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
784       if(d_plot_waterfall3d == -1) {
785         SpectrumTypeTab->addTab(Waterfall3DPage, "3D Waterfall Display");
786         d_plot_waterfall3d = SpectrumTypeTab->count()-1;
787       }
788     }
789     */
790     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
791     d_plot_waterfall3d = -1;
792     fprintf(stderr, "\nWARNING: The Waterfall3D plot has been disabled until we get it working.\n\n");
793   }
794   else {
795     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
796     d_plot_waterfall3d = -1;
797   }
798 }
799
800 void
801 SpectrumDisplayForm::ToggleTabTime(const bool state)
802 {
803   if(state == true) {
804     if(d_plot_time == -1) {
805       SpectrumTypeTab->addTab(TimeDomainPage, "Time Domain Display");
806       d_plot_time = SpectrumTypeTab->count()-1;
807     }
808   }
809   else {
810     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(TimeDomainPage));
811     d_plot_time = -1;
812   }
813 }
814
815 void
816 SpectrumDisplayForm::ToggleTabConstellation(const bool state)
817 {
818   if(state == true) {
819     if(d_plot_constellation == -1) {
820       SpectrumTypeTab->addTab(ConstellationPage, "Constellation Display");
821       d_plot_constellation = SpectrumTypeTab->count()-1;
822     }
823   }
824   else {
825     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(ConstellationPage));
826     d_plot_constellation = -1;
827   }
828 }
829
830
831 void
832 SpectrumDisplayForm::SetTimeDomainAxis(double min, double max)
833 {
834   _timeDomainDisplayPlot->set_yaxis(min, max);
835 }
836
837 void
838 SpectrumDisplayForm::SetConstellationAxis(double xmin, double xmax,
839                                                 double ymin, double ymax)
840 {
841   _constellationDisplayPlot->set_axis(xmin, xmax, ymin, ymax);
842 }
843
844 void
845 SpectrumDisplayForm::SetConstellationPenSize(int size)
846 {
847   _constellationDisplayPlot->set_pen_size( size );
848 }
849
850 void
851 SpectrumDisplayForm::SetFrequencyAxis(double min, double max)
852 {
853   _frequencyDisplayPlot->set_yaxis(min, max);
854 }
855
856 void
857 SpectrumDisplayForm::SetUpdateTime(double t)
858 {
859   d_update_time = t;
860   // QTimer class takes millisecond input
861   displayTimer->start(d_update_time*1000);
862 }