Adding a constellation plot and an example for viewing constellations of digital...
[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(QWidget* parent) : QDialog(parent){
9   setupUi(this);
10   
11   _systemSpecifiedFlag = false;
12   _intValidator = new QIntValidator(this);
13   _intValidator->setBottom(0);
14   _frequencyDisplayPlot = new FrequencyDisplayPlot(Tab1PlotDisplayFrame);
15   _waterfallDisplayPlot = new WaterfallDisplayPlot(Tab2PlotDisplayFrame);
16   _waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
17   _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
18   _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame);
19   _numRealDataPoints = 1024;
20   _realFFTDataPoints = new double[_numRealDataPoints];
21   _averagedValues = new double[_numRealDataPoints];
22   _historyVector = new std::vector<double*>;
23   
24   AvgLineEdit->setValidator(_intValidator);
25   PowerLineEdit->setValidator(_intValidator);
26   MinHoldCheckBox_toggled( false );
27   MaxHoldCheckBox_toggled( false );
28   
29   WaterfallMaximumIntensityWheel->setRange(-200, 0);
30   WaterfallMaximumIntensityWheel->setTickCnt(50);
31   WaterfallMinimumIntensityWheel->setRange(-200, 0);
32   WaterfallMinimumIntensityWheel->setTickCnt(50);
33   WaterfallMinimumIntensityWheel->setValue(-200);
34   
35   Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
36   Waterfall3DMaximumIntensityWheel->setTickCnt(50);
37   Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
38   Waterfall3DMinimumIntensityWheel->setTickCnt(50);
39   Waterfall3DMinimumIntensityWheel->setValue(-200);
40   
41   _peakFrequency = 0;
42   _peakAmplitude = -HUGE_VAL;
43   
44   _noiseFloorAmplitude = -HUGE_VAL;
45   
46   connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), 
47           _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
48   connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), 
49           _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
50   
51   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
52   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
53   
54   // Load up the acceptable FFT sizes...
55   FFTSizeComboBox->clear();
56   for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
57     FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
58   }
59   Reset();
60 }
61
62 SpectrumDisplayForm::~SpectrumDisplayForm(){
63   // Qt deletes children when parent is deleted
64
65   // Don't worry about deleting Display Plots - they are deleted when parents are deleted
66   /*   delete _intValidator; */
67
68   delete[] _realFFTDataPoints;
69   delete[] _averagedValues;
70
71   for(unsigned int count = 0; count < _historyVector->size(); count++){
72     delete[] _historyVector->operator[](count);
73   }
74
75   delete _historyVector;
76 }
77
78 void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, 
79                                      const uint64_t numFFTDataPoints, 
80                                      const uint64_t numTimeDomainDataPoints )
81 {
82   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
83   
84   if(newSystem != NULL){
85     _system = newSystem;
86     _systemSpecifiedFlag = true;
87   }
88   else{
89     _systemSpecifiedFlag = false;
90   }
91 }
92
93 void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
94 {
95   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
96   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
97   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
98   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
99   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
100   const double timePerFFT = spectrumUpdateEvent->getTimePerFFT();
101   const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();;
102   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
103   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
104   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
105
106   // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
107   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
108
109   // Calculate the Magnitude of the complex point
110   const std::complex<float>* complexDataPointsPtr = complexDataPoints;
111   double* realFFTDataPointsPtr = _realFFTDataPoints;
112   for(uint64_t point = 0; point < numFFTDataPoints; point++){
113     // Calculate dBm
114     // 50 ohm load assumption
115     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
116     // 75 ohm load assumption
117     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
118     
119     *realFFTDataPointsPtr = 10.0*log10((((*complexDataPointsPtr).real() * (*complexDataPointsPtr).real()) + ((*complexDataPointsPtr).imag()*(*complexDataPointsPtr).imag())) + 1e-20);
120
121     complexDataPointsPtr++;
122     realFFTDataPointsPtr++;
123   }
124  
125
126   // Don't update the averaging history if this is repeated data
127   if(!repeatDataFlag){
128     _AverageHistory(_realFFTDataPoints);
129
130     double sumMean;
131     const double fft_bin_size = (_stopFrequency-_startFrequency) /
132       static_cast<double>(numFFTDataPoints);
133
134     // find the peak, sum (for mean), etc
135     _peakAmplitude = -HUGE_VAL;
136     sumMean = 0.0;
137     for(uint64_t number = 0; number < numFFTDataPoints; number++){
138       // find peak
139       if(_realFFTDataPoints[number] > _peakAmplitude){
140         _peakFrequency = (static_cast<float>(number) * fft_bin_size);  // Calculate the frequency relative to the local bw, adjust for _startFrequency later
141         _peakAmplitude = _realFFTDataPoints[number];
142         // _peakBin = number;
143       }
144       // sum (for mean)
145       sumMean += _realFFTDataPoints[number];
146     }
147
148     // calculate the spectral mean
149     // +20 because for the comparison below we only want to throw out bins
150     // that are significantly higher (and would, thus, affect the mean more)
151     const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
152
153     // now throw out any bins higher than the mean
154     sumMean = 0.0;
155     uint64_t newNumDataPoints = numFFTDataPoints;
156     for(uint64_t number = 0; number < numFFTDataPoints; number++){
157       if (_realFFTDataPoints[number] <= meanAmplitude)
158         sumMean += _realFFTDataPoints[number];
159       else
160         newNumDataPoints--;
161     }
162
163     if (newNumDataPoints == 0)             // in the odd case that all
164       _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
165     else
166       _noiseFloorAmplitude = sumMean / newNumDataPoints;
167   }
168
169   if(lastOfMultipleUpdatesFlag){
170     _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, 
171                                        _noiseFloorAmplitude, _peakFrequency, 
172                                        _peakAmplitude);
173     _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
174                                         imagTimeDomainDataPoints, 
175                                         numTimeDomainDataPoints);
176     _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
177                                            imagTimeDomainDataPoints, 
178                                            numTimeDomainDataPoints);
179   }
180   // Don't update the repeated data for the waterfall
181   if(!repeatDataFlag){
182     _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
183                                        timePerFFT, dataTimestamp, 
184                                        spectrumUpdateEvent->getDroppedFFTFrames());
185     if( _openGLWaterfall3DFlag == 1 ){
186       _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
187                                            timePerFFT, dataTimestamp, 
188                                            spectrumUpdateEvent->getDroppedFFTFrames());
189     }
190   }
191   
192   // Tell the system the GUI has been updated
193   if(_systemSpecifiedFlag){
194     _system->SetLastGUIUpdateTime(generatedTimestamp);
195     _system->DecrementPendingGUIUpdateEvents();
196   }
197 }
198
199 void SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
200 {
201   // Let the actual window resize its width, but not its height
202   QSize newSize(e->size().width(), e->oldSize().height());
203   QResizeEvent et(newSize, e->oldSize());
204   QWidget::resizeEvent(&et);
205
206   // Tell the Tab Window to Resize
207   SpectrumTypeTab->resize( e->size().width(), SpectrumTypeTab->height());
208
209   // Tell the TabXFreqDisplay to resize
210   Tab1PlotDisplayFrame->resize(e->size().width()-4,
211                                Tab1PlotDisplayFrame->height());
212   Tab2PlotDisplayFrame->resize(e->size().width()-4,
213                                Tab2PlotDisplayFrame->height());
214   Waterfall3DPlotDisplayFrame->resize(e->size().width()-4,
215                                       Waterfall3DPlotDisplayFrame->height());
216   TimeDomainDisplayFrame->resize(e->size().width()-4,
217                                  TimeDomainDisplayFrame->height());
218   _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4,
219                                  Tab1PlotDisplayFrame->height());
220   _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4,
221                                  Tab2PlotDisplayFrame->height());
222   _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4,
223                                    Waterfall3DPlotDisplayFrame->height());
224   _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4,
225                                   TimeDomainDisplayFrame->height());
226
227   // Move the IntensityWheels and Labels
228   WaterfallMaximumIntensityLabel->move(width() - 5 -
229                                        WaterfallMaximumIntensityLabel->width(),
230                                        WaterfallMaximumIntensityLabel->y());
231   WaterfallMinimumIntensityLabel->move(width() - 5 -
232                                        WaterfallMinimumIntensityLabel->width(),
233                                        WaterfallMinimumIntensityLabel->y());
234   WaterfallMaximumIntensityWheel->resize(WaterfallMaximumIntensityLabel->x() - 5 -
235                                          WaterfallMaximumIntensityWheel->x(),
236                                          WaterfallMaximumIntensityWheel->height());
237   WaterfallMinimumIntensityWheel->resize(WaterfallMinimumIntensityLabel->x() - 5 -
238                                          WaterfallMinimumIntensityWheel->x(),
239                                          WaterfallMinimumIntensityWheel->height());
240
241   Waterfall3DMaximumIntensityLabel->move(width() - 5 -
242                                          Waterfall3DMaximumIntensityLabel->width(),
243                                          Waterfall3DMaximumIntensityLabel->y());
244   Waterfall3DMinimumIntensityLabel->move(width() - 5 -
245                                          Waterfall3DMinimumIntensityLabel->width(),
246                                          Waterfall3DMinimumIntensityLabel->y());
247   Waterfall3DMaximumIntensityWheel->resize(Waterfall3DMaximumIntensityLabel->x() - 5 -
248                                            Waterfall3DMaximumIntensityWheel->x(),
249                                            Waterfall3DMaximumIntensityWheel->height());
250   Waterfall3DMinimumIntensityWheel->resize(Waterfall3DMinimumIntensityLabel->x() - 5 -
251                                            Waterfall3DMinimumIntensityWheel->x(),
252                                            Waterfall3DMinimumIntensityWheel->height());
253
254
255   // Move the Power Lbl
256   PowerLabel->move(e->size().width()-(415-324) - PowerLabel->width(),
257                    PowerLabel->y());
258
259   // Move the Power Line Edit
260   PowerLineEdit->move(e->size().width()-(415-318) - PowerLineEdit->width(),
261                       PowerLineEdit->y());
262
263   // Move the Avg Lbl
264   AvgLabel->move(e->size().width()-(415-406) - AvgLabel->width(),
265                  AvgLabel->y());
266
267   // Move the Avg Line Edit
268   AvgLineEdit->move(e->size().width()-(415-400) - AvgLineEdit->width(),
269                     AvgLineEdit->y());
270   
271   // Move the FFT Size Combobox and label
272   FFTSizeComboBox->move(width() - 5 - FFTSizeComboBox->width(),
273                         FFTSizeComboBox->y());
274   FFTSizeLabel->move(width() - 10 - FFTSizeComboBox->width() - FFTSizeLabel->width(),
275                      FFTSizeLabel->y());
276 }
277
278
279 void SpectrumDisplayForm::customEvent( QEvent * e)
280 {
281   if(e->type() == QEvent::User+3){
282     if(_systemSpecifiedFlag){
283       WindowComboBox->setCurrentIndex(_system->GetWindowType());
284       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
285       //FFTSizeComboBox->setCurrentIndex(1);
286       PowerLineEdit_textChanged(PowerLineEdit->text());
287     }
288
289     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
290     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
291
292     waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
293     waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
294
295     // If the video card doesn't support OpenGL then don't display the 3D Waterfall
296     if(QGLFormat::hasOpenGL()){
297       // Check for Hardware Acceleration of the OpenGL
298       if(!_waterfall3DDisplayPlot->format().directRendering()){
299         // Only ask this once while the program is running...
300         if(_openGLWaterfall3DFlag == -1){
301           _openGLWaterfall3DFlag = 0;
302           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){
303             _openGLWaterfall3DFlag = 1;
304           }
305         }
306       }
307       else{
308         _openGLWaterfall3DFlag = 1;
309       }
310     }
311
312     if(_openGLWaterfall3DFlag != 1){
313       SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
314     }
315
316     // Clear any previous display
317     Reset();
318
319     show();
320   }
321   else if(e->type() == 10005){
322     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
323     newFrequencyData(spectrumUpdateEvent);
324   }
325   else if(e->type() == 10008){
326     setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
327   }
328   else if(e->type() == 10009){
329     Reset();
330     if(_systemSpecifiedFlag){
331       _system->ResetPendingGUIUpdateEvents();
332     }
333   }
334   else if(e->type() == 10010){
335     _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
336     _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
337     _centerFrequency  = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
338
339     UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
340   }
341 }
342
343 void SpectrumDisplayForm::AvgLineEdit_textChanged( const QString &valueString )
344 {
345   if(!valueString.isEmpty()){
346     int value = valueString.toInt();
347     if(value > 500){
348       value = 500;
349       AvgLineEdit->setText("500");
350     }
351     SetAverageCount(value);
352   }
353 }
354
355
356 void SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
357 {
358   MaxHoldResetBtn->setEnabled(newState);
359   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
360   MaxHoldResetBtn_clicked();
361 }
362
363
364 void SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
365 {
366   MinHoldResetBtn->setEnabled(newState);
367   _frequencyDisplayPlot->SetMinFFTVisible(newState);
368   MinHoldResetBtn_clicked();
369 }
370
371
372 void SpectrumDisplayForm::MinHoldResetBtn_clicked()
373 {
374   _frequencyDisplayPlot->ClearMinData();
375   _frequencyDisplayPlot->replot();
376 }
377
378
379 void SpectrumDisplayForm::MaxHoldResetBtn_clicked()
380 {
381   _frequencyDisplayPlot->ClearMaxData();
382   _frequencyDisplayPlot->replot();
383 }
384
385
386 void SpectrumDisplayForm::PowerLineEdit_textChanged( const QString &valueString )
387 {
388   if(_systemSpecifiedFlag){
389     if(!valueString.isEmpty()){
390       double value = valueString.toDouble();
391       if(value < 1.0){
392         value = 1.0;
393         PowerLineEdit->setText("1");
394       }
395       _system->SetPowerValue(value);
396     }
397
398     if(_system->GetPowerValue() > 1){
399       UseRFFrequenciesCheckBox->setChecked(false);
400       UseRFFrequenciesCheckBox->setEnabled(false);
401       UseRFFrequenciesCB(false);
402     }
403     else{
404       UseRFFrequenciesCheckBox->setEnabled(true);
405     }
406   }
407 }
408
409 void SpectrumDisplayForm::SetFrequencyRange(const double newStartFrequency, const double newStopFrequency, const double newCenterFrequency){
410   _frequencyDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
411   _waterfallDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
412   _waterfall3DDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
413
414 }
415
416 int SpectrumDisplayForm::GetAverageCount(){
417   return _historyVector->size();
418 }
419
420 void SpectrumDisplayForm::SetAverageCount(const int newCount){
421   if(newCount > -1){
422     if(newCount != static_cast<int>(_historyVector->size())){
423       std::vector<double*>::iterator pos;
424       while(newCount < static_cast<int>(_historyVector->size())){
425         pos = _historyVector->begin();
426         delete[] (*pos);
427         _historyVector->erase(pos);
428       }
429
430       while(newCount > static_cast<int>(_historyVector->size())){
431         _historyVector->push_back(new double[_numRealDataPoints]);
432       }
433       AverageDataReset();
434     }
435   }
436 }
437
438 void SpectrumDisplayForm::_AverageHistory(const double* newBuffer){
439   if(_numRealDataPoints > 0){
440     if(_historyVector->size() > 0){
441       memcpy(_historyVector->operator[](_historyEntry), newBuffer, _numRealDataPoints*sizeof(double));
442
443       // Increment the next location to store data
444       _historyEntryCount++;
445       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
446         _historyEntryCount = _historyVector->size();
447       }
448       _historyEntry = (++_historyEntry)%_historyVector->size();
449
450       // Total up and then average the values
451       double sum;
452       for(uint64_t location = 0; location < _numRealDataPoints; location++){
453         sum = 0;
454         for(int number = 0; number < _historyEntryCount; number++){
455           sum += _historyVector->operator[](number)[location];
456         }
457         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
458       }
459     }
460     else{
461       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
462     }
463   }
464 }
465
466 void SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, const uint64_t /*numTimeDomainDataPoints*/ ){
467   // Convert from Complex to Real for certain Displays
468   if(_numRealDataPoints != numFFTDataPoints){
469     _numRealDataPoints = numFFTDataPoints;
470     delete[] _realFFTDataPoints;
471     delete[] _averagedValues;
472     
473     _realFFTDataPoints = new double[_numRealDataPoints];
474     _averagedValues = new double[_numRealDataPoints];
475     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
476     
477     const int historySize = _historyVector->size();
478     SetAverageCount(0); // Clear the existing history
479     SetAverageCount(historySize);
480     
481     Reset();
482   }
483 }
484
485 void SpectrumDisplayForm::Reset(){
486   AverageDataReset();
487
488   _waterfallDisplayPlot->Reset();
489   _waterfall3DDisplayPlot->Reset();
490 }
491
492
493 void SpectrumDisplayForm::AverageDataReset(){
494   _historyEntry = 0;
495   _historyEntryCount = 0;
496
497   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
498
499   MaxHoldResetBtn_clicked();
500   MinHoldResetBtn_clicked();
501 }
502
503
504 void SpectrumDisplayForm::closeEvent( QCloseEvent *e )
505 {
506   if(_systemSpecifiedFlag){
507     _system->SetWindowOpenFlag(false);
508   }
509
510   qApp->processEvents();
511
512   QWidget::closeEvent(e);
513 }
514
515
516 void SpectrumDisplayForm::WindowTypeChanged( int newItem )
517 {
518   if(_systemSpecifiedFlag){
519    _system->SetWindowType(newItem);
520   }
521 }
522
523
524 void SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
525 {
526   if(useRFFlag){
527     SetFrequencyRange(_startFrequency, _stopFrequency, _centerFrequency);
528   }
529   else{
530     SetFrequencyRange(_startFrequency, _stopFrequency, 0.0 );
531   }
532 }
533
534
535 void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
536 {
537   if(newValue > WaterfallMinimumIntensityWheel->value()){
538     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
539   }
540   else{
541     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
542   }
543   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
544 }
545
546
547 void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
548 {
549   if(newValue < WaterfallMaximumIntensityWheel->value()){
550     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
551   }
552   else{
553     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
554   }
555   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
556 }
557
558 void SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
559 {
560   if(newValue > Waterfall3DMinimumIntensityWheel->value()){
561     Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
562   }
563   else{
564     Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
565   }
566   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
567 }
568
569
570 void SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
571 {
572   if(newValue < Waterfall3DMaximumIntensityWheel->value()){
573     Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
574   }
575   else{
576     Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
577   }
578   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
579 }
580
581
582 void SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
583 {
584   if(_systemSpecifiedFlag){
585     _system->SetFFTSize(fftSizeString.toLong());
586   }
587 }
588
589
590 void SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
591 {
592   double minimumIntensity = _noiseFloorAmplitude - 5;
593   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
594     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
595   }
596   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
597   double maximumIntensity = _peakAmplitude + 10;
598   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
599     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
600   }
601   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
602   waterfallMaximumIntensityChangedCB(maximumIntensity);
603 }
604
605 void SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
606 {
607   double minimumIntensity = _noiseFloorAmplitude - 5;
608   if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
609     minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
610   }
611   Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
612   double maximumIntensity = _peakAmplitude + 10;
613   if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
614     maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
615   }
616   Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
617   waterfallMaximumIntensityChangedCB(maximumIntensity);
618 }
619
620 void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
621 {
622   QColor lowIntensityColor;
623   QColor highIntensityColor;
624   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
625     // Select the Low Intensity Color
626     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
627     if(!lowIntensityColor.isValid()){
628       lowIntensityColor = Qt::black;
629     }
630     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
631     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
632
633     // Select the High Intensity Color
634     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
635     if(!highIntensityColor.isValid()){
636       highIntensityColor = Qt::white;
637     }
638     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
639     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
640   }
641   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
642 }
643
644 void SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
645 {
646   QColor lowIntensityColor;
647   QColor highIntensityColor;
648   if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
649     // Select the Low Intensity Color
650     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
651     if(!lowIntensityColor.isValid()){
652       lowIntensityColor = Qt::black;
653     }
654     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
655     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
656
657     // Select the High Intensity Color
658     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
659     if(!highIntensityColor.isValid()){
660       highIntensityColor = Qt::white;
661     }
662     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
663     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
664   }
665   _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
666 }