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