Imported Upstream version 3.2.2
[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 newCenterFrequency,
477                                        const double newStartFrequency, 
478                                        const double newStopFrequency)
479 {
480   double fdiff;
481   if(UseRFFrequenciesCheckBox->isChecked()) {
482     fdiff = newCenterFrequency;
483   }
484   else {
485     fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
486   }
487
488   if(fdiff > 0) {
489     std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
490     double units10 = floor(log10(fdiff));
491     double units3  = std::max(floor(units10 / 3.0), 0.0);
492     double units = pow(10, (units10-fmod(units10, 3.0)));
493     int iunit = static_cast<int>(units3);
494     
495     _startFrequency = newStartFrequency;
496     _stopFrequency = newStopFrequency;
497     _centerFrequency = newCenterFrequency;
498
499     _frequencyDisplayPlot->SetFrequencyRange(newStartFrequency,
500                                              newStopFrequency,
501                                              newCenterFrequency,
502                                              UseRFFrequenciesCheckBox->isChecked(),
503                                              units, strunits[iunit]);
504     _waterfallDisplayPlot->SetFrequencyRange(newStartFrequency,
505                                              newStopFrequency,
506                                              newCenterFrequency,
507                                              UseRFFrequenciesCheckBox->isChecked(),
508                                              units, strunits[iunit]);
509     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
510       _waterfall3DDisplayPlot->SetFrequencyRange(newStartFrequency,
511                                                  newStopFrequency,
512                                                  newCenterFrequency,
513                                                  UseRFFrequenciesCheckBox->isChecked(),
514                                                  units, strunits[iunit]);
515     }
516   }
517 }
518
519 int
520 SpectrumDisplayForm::GetAverageCount()
521 {
522   return _historyVector->size();
523 }
524
525 void
526 SpectrumDisplayForm::SetAverageCount(const int newCount)
527 {
528   if(newCount > -1){
529     if(newCount != static_cast<int>(_historyVector->size())){
530       std::vector<double*>::iterator pos;
531       while(newCount < static_cast<int>(_historyVector->size())){
532         pos = _historyVector->begin();
533         delete[] (*pos);
534         _historyVector->erase(pos);
535       }
536
537       while(newCount > static_cast<int>(_historyVector->size())){
538         _historyVector->push_back(new double[_numRealDataPoints]);
539       }
540       AverageDataReset();
541     }
542   }
543 }
544
545 void
546 SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
547 {
548   if(_numRealDataPoints > 0){
549     if(_historyVector->size() > 0){
550       memcpy(_historyVector->operator[](_historyEntry), newBuffer,
551              _numRealDataPoints*sizeof(double));
552
553       // Increment the next location to store data
554       _historyEntryCount++;
555       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
556         _historyEntryCount = _historyVector->size();
557       }
558       _historyEntry = (++_historyEntry)%_historyVector->size();
559
560       // Total up and then average the values
561       double sum;
562       for(uint64_t location = 0; location < _numRealDataPoints; location++){
563         sum = 0;
564         for(int number = 0; number < _historyEntryCount; number++){
565           sum += _historyVector->operator[](number)[location];
566         }
567         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
568       }
569     }
570     else{
571       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
572     }
573   }
574 }
575
576 void
577 SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
578                                     const uint64_t /*numTimeDomainDataPoints*/ )
579 {
580   // Convert from Complex to Real for certain Displays
581   if(_numRealDataPoints != numFFTDataPoints){
582     _numRealDataPoints = numFFTDataPoints;
583     delete[] _realFFTDataPoints;
584     delete[] _averagedValues;
585     
586     _realFFTDataPoints = new double[_numRealDataPoints];
587     _averagedValues = new double[_numRealDataPoints];
588     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
589     
590     const int historySize = _historyVector->size();
591     SetAverageCount(0); // Clear the existing history
592     SetAverageCount(historySize);
593     
594     Reset();
595   }
596 }
597
598 void
599 SpectrumDisplayForm::Reset()
600 {
601   AverageDataReset();
602
603   _waterfallDisplayPlot->Reset();
604   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
605     _waterfall3DDisplayPlot->Reset();
606   }
607 }
608
609
610 void
611 SpectrumDisplayForm::AverageDataReset()
612 {
613   _historyEntry = 0;
614   _historyEntryCount = 0;
615
616   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
617
618   MaxHoldResetBtn_clicked();
619   MinHoldResetBtn_clicked();
620 }
621
622
623 void
624 SpectrumDisplayForm::closeEvent( QCloseEvent *e )
625 {
626   if(_systemSpecifiedFlag){
627     _system->SetWindowOpenFlag(false);
628   }
629
630   qApp->processEvents();
631
632   QWidget::closeEvent(e);
633 }
634
635
636 void
637 SpectrumDisplayForm::WindowTypeChanged( int newItem )
638 {
639   if(_systemSpecifiedFlag){
640    _system->SetWindowType(newItem);
641   }
642 }
643
644
645 void
646 SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
647 {
648   SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
649 }
650
651
652 void
653 SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
654 {
655   if(newValue > WaterfallMinimumIntensityWheel->value()){
656     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
657   }
658   else{
659     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
660   }
661
662   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
663                                            WaterfallMaximumIntensityWheel->value());
664 }
665
666
667 void
668 SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
669 {
670   if(newValue < WaterfallMaximumIntensityWheel->value()){
671     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
672   }
673   else{
674     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
675   }
676
677   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
678                                            WaterfallMaximumIntensityWheel->value());
679 }
680
681 void
682 SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
683 {
684   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
685     if(newValue > Waterfall3DMinimumIntensityWheel->value()){
686       Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
687     }
688     else{
689       Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
690     }
691     
692     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
693                                                Waterfall3DMaximumIntensityWheel->value());
694   }
695 }
696
697
698 void
699 SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
700 {
701   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
702     if(newValue < Waterfall3DMaximumIntensityWheel->value()){
703       Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
704     }
705     else{
706       Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
707     }
708     
709     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
710                                                Waterfall3DMaximumIntensityWheel->value());
711   }
712 }
713
714
715 void
716 SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
717 {
718   if(_systemSpecifiedFlag){
719     _system->SetFFTSize(fftSizeString.toLong());
720   }
721 }
722
723
724 void
725 SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
726 {
727   double minimumIntensity = _noiseFloorAmplitude - 5;
728   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
729     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
730   }
731   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
732   double maximumIntensity = _peakAmplitude + 10;
733   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
734     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
735   }
736   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
737   waterfallMaximumIntensityChangedCB(maximumIntensity);
738 }
739
740 void
741 SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
742 {
743   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
744     double minimumIntensity = _noiseFloorAmplitude - 5;
745     if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
746       minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
747     }
748     Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
749     double maximumIntensity = _peakAmplitude + 10;
750     if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
751       maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
752     }
753     Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
754     waterfallMaximumIntensityChangedCB(maximumIntensity);
755   }
756 }
757
758 void
759 SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
760 {
761   QColor lowIntensityColor;
762   QColor highIntensityColor;
763   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
764     // Select the Low Intensity Color
765     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
766     if(!lowIntensityColor.isValid()){
767       lowIntensityColor = Qt::black;
768     }
769     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
770     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
771     
772     // Select the High Intensity Color
773     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
774     if(!highIntensityColor.isValid()){
775       highIntensityColor = Qt::white;
776     }
777     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
778     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
779   }
780   
781   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
782 }
783
784 void
785 SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
786 {
787   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
788     QColor lowIntensityColor;
789     QColor highIntensityColor;
790     if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
791       // Select the Low Intensity Color
792       lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
793       if(!lowIntensityColor.isValid()){
794         lowIntensityColor = Qt::black;
795       }
796       QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
797       lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
798       
799       // Select the High Intensity Color
800       highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
801       if(!highIntensityColor.isValid()){
802         highIntensityColor = Qt::white;
803       }
804       QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
805       highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
806     }
807     _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor,
808                                                       highIntensityColor);
809   }
810 }
811
812
813 void
814 SpectrumDisplayForm::ToggleTabFrequency(const bool state)
815 {
816   if(state == true) {
817     if(d_plot_fft == -1) {
818       SpectrumTypeTab->addTab(FrequencyPage, "Frequency Display");
819       d_plot_fft = SpectrumTypeTab->count()-1;
820     }
821   }
822   else {
823     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(FrequencyPage));
824     d_plot_fft = -1;
825   }
826 }
827
828 void
829 SpectrumDisplayForm::ToggleTabWaterfall(const bool state)
830 {
831   if(state == true) {
832     if(d_plot_waterfall == -1) {
833       SpectrumTypeTab->addTab(WaterfallPage, "Waterfall Display");
834       d_plot_waterfall = SpectrumTypeTab->count()-1;
835     }
836   }
837   else {
838     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(WaterfallPage));
839     d_plot_waterfall = -1;
840   }
841 }
842
843 void
844 SpectrumDisplayForm::ToggleTabWaterfall3D(const bool state)
845 {
846   if(state == true) {
847     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
848       if(d_plot_waterfall3d == -1) {
849         SpectrumTypeTab->addTab(Waterfall3DPage, "3D Waterfall Display");
850         d_plot_waterfall3d = SpectrumTypeTab->count()-1;
851       }
852     }
853   }
854   else {
855     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
856     d_plot_waterfall3d = -1;
857   }
858 }
859
860 void
861 SpectrumDisplayForm::ToggleTabTime(const bool state)
862 {
863   if(state == true) {
864     if(d_plot_time == -1) {
865       SpectrumTypeTab->addTab(TimeDomainPage, "Time Domain Display");
866       d_plot_time = SpectrumTypeTab->count()-1;
867     }
868   }
869   else {
870     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(TimeDomainPage));
871     d_plot_time = -1;
872   }
873 }
874
875 void
876 SpectrumDisplayForm::ToggleTabConstellation(const bool state)
877 {
878   if(state == true) {
879     if(d_plot_constellation == -1) {
880       SpectrumTypeTab->addTab(ConstellationPage, "Constellation Display");
881       d_plot_constellation = SpectrumTypeTab->count()-1;
882     }
883   }
884   else {
885     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(ConstellationPage));
886     d_plot_constellation = -1;
887   }
888 }
889
890
891 void
892 SpectrumDisplayForm::SetTimeDomainAxis(double min, double max)
893 {
894   _timeDomainDisplayPlot->set_yaxis(min, max);
895 }
896
897 void
898 SpectrumDisplayForm::SetConstellationAxis(double xmin, double xmax,
899                                                 double ymin, double ymax)
900 {
901   _constellationDisplayPlot->set_axis(xmin, xmax, ymin, ymax);
902 }
903
904 void
905 SpectrumDisplayForm::SetFrequencyAxis(double min, double max)
906 {
907   _frequencyDisplayPlot->set_yaxis(min, max);
908 }