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