Now adding y-axis controls for frequency domain plot.
[debian/gnuradio] / gr-qtgui / src / lib / SpectrumGUIClass.cc
1 #ifndef SPECTRUM_GUI_CLASS_CPP
2 #define SPECTRUM_GUI_CLASS_CPP
3
4 #include <SpectrumGUIClass.h>
5 //Added by qt3to4:
6 #include <QEvent>
7 #include <QCustomEvent>
8
9 const long SpectrumGUIClass::MAX_FFT_SIZE;
10 const long SpectrumGUIClass::MIN_FFT_SIZE;
11
12 SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize,
13                                    const uint64_t fftSize, 
14                                    const double newStartFrequency,
15                                    const double newStopFrequency)
16 {
17   _dataPoints = maxDataSize;
18   if(_dataPoints < 2){
19     _dataPoints = 2;
20   }
21   _lastDataPointCount = _dataPoints;
22
23   _fftSize = fftSize;
24
25   _pendingGUIUpdateEventsCount = 0;
26   _droppedEntriesCount = 0;
27
28   _centerFrequency = 0;
29   _startFrequency = newStartFrequency;
30   _stopFrequency = newStopFrequency;
31
32 #warning SPECIFY THIS LATER...
33   _windowType = 5;
34
35   timespec_reset(&_lastGUIUpdateTime);
36
37   _windowOpennedFlag = false;
38   _fftBuffersCreatedFlag = false;
39
40   // Create Mutex Lock
41   //_windowStateLock = new MutexClass("_windowStateLock");
42
43   _powerValue = 1;
44 }
45
46 SpectrumGUIClass::~SpectrumGUIClass()
47 {
48   if(GetWindowOpenFlag()){
49     delete _spectrumDisplayForm;
50   }
51
52   if(_fftBuffersCreatedFlag){
53     delete[] _fftPoints;
54     delete[] _realTimeDomainPoints;
55     delete[] _imagTimeDomainPoints;
56   }
57
58   //delete _windowStateLock;
59 }
60
61 void
62 SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent,
63                                      const bool frequency, const bool waterfall,
64                                      const bool waterfall3d, const bool time,
65                                      const bool constellation)
66 {
67   //_windowStateLock->Lock();
68
69   if(!_windowOpennedFlag){
70
71     if(!_fftBuffersCreatedFlag){
72       _fftPoints = new std::complex<float>[_dataPoints];
73       _realTimeDomainPoints = new double[_dataPoints];
74       _imagTimeDomainPoints = new double[_dataPoints];
75       _fftBuffersCreatedFlag = true;
76       
77       
78       memset(_fftPoints, 0x0, _dataPoints*sizeof(std::complex<float>));
79       memset(_realTimeDomainPoints, 0x0, _dataPoints*sizeof(double));
80       memset(_imagTimeDomainPoints, 0x0, _dataPoints*sizeof(double));
81     }
82     
83     // Called from the Event Thread
84     _spectrumDisplayForm = new SpectrumDisplayForm(parent);
85     
86     // Toggle Windows on/off
87     _spectrumDisplayForm->ToggleTabFrequency(frequency);
88     _spectrumDisplayForm->ToggleTabWaterfall(waterfall);
89     _spectrumDisplayForm->ToggleTabWaterfall3D(waterfall3d);
90     _spectrumDisplayForm->ToggleTabTime(time);
91     _spectrumDisplayForm->ToggleTabConstellation(constellation);
92
93     _windowOpennedFlag = true;
94
95     _spectrumDisplayForm->setSystem(this, _dataPoints, _fftSize);
96
97     qApp->processEvents();
98   }
99
100   //_windowStateLock->Unlock();
101
102   SetDisplayTitle(_title);
103   Reset();
104
105   qApp->postEvent(_spectrumDisplayForm,
106                   new QEvent(QEvent::Type(QEvent::User+3)));
107
108   qApp->processEvents();
109
110   timespec_reset(&_lastGUIUpdateTime);
111
112   // Draw Blank Display
113   UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, 1.0, get_highres_clock(), true);
114
115   // GUI Thread only
116   qApp->processEvents();
117 }
118
119 void
120 SpectrumGUIClass::Reset()
121 {
122   if(GetWindowOpenFlag()) {
123     qApp->postEvent(_spectrumDisplayForm,
124                     new SpectrumFrequencyRangeEvent(_centerFrequency, 
125                                                     _startFrequency, 
126                                                     _stopFrequency));
127     qApp->postEvent(_spectrumDisplayForm, new SpectrumWindowResetEvent());
128   }
129   _droppedEntriesCount = 0;
130   // Call the following function the the Spectrum Window Reset Event window
131   // ResetPendingGUIUpdateEvents();
132 }
133
134 void
135 SpectrumGUIClass::SetDisplayTitle(const std::string newString)
136 {
137   _title.assign(newString);
138
139   if(GetWindowOpenFlag()){
140     qApp->postEvent(_spectrumDisplayForm,
141                     new SpectrumWindowCaptionEvent(_title.c_str()));
142   }
143 }
144
145 bool
146 SpectrumGUIClass::GetWindowOpenFlag()
147 {
148   bool returnFlag = false;
149   //_windowStateLock->Lock();
150   returnFlag =  _windowOpennedFlag;
151   //_windowStateLock->Unlock();
152   return returnFlag;
153 }
154
155
156 void
157 SpectrumGUIClass::SetWindowOpenFlag(const bool newFlag)
158 {
159   //_windowStateLock->Lock();
160   _windowOpennedFlag = newFlag;
161   //_windowStateLock->Unlock();
162 }
163
164 void
165 SpectrumGUIClass::SetFrequencyRange(const double centerFreq,
166                                     const double startFreq,
167                                     const double stopFreq)
168 {
169   //_windowStateLock->Lock();
170   _centerFrequency = centerFreq;
171   _startFrequency = startFreq;
172   _stopFrequency = stopFreq;
173
174   _spectrumDisplayForm->SetFrequencyRange(_centerFrequency,
175                                           _startFrequency,
176                                           _stopFrequency);
177   //_windowStateLock->Unlock();
178 }
179
180 double
181 SpectrumGUIClass::GetStartFrequency() const 
182 {
183   double returnValue = 0.0;
184   //_windowStateLock->Lock();
185   returnValue =  _startFrequency;
186   //_windowStateLock->Unlock();
187   return returnValue;
188 }
189
190 double
191 SpectrumGUIClass::GetStopFrequency() const
192 {
193   double returnValue = 0.0;
194   //_windowStateLock->Lock();
195   returnValue =  _stopFrequency;
196   //_windowStateLock->Unlock();
197   return returnValue;
198 }
199
200 double
201 SpectrumGUIClass::GetCenterFrequency() const
202 {
203   double returnValue = 0.0;
204   //_windowStateLock->Lock();
205   returnValue =  _centerFrequency;
206   //_windowStateLock->Unlock();
207   return returnValue;
208 }
209
210
211 void
212 SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag,
213                                const std::complex<float>* fftBuffer,
214                                const uint64_t inputBufferSize,
215                                const float* realTimeDomainData,
216                                const uint64_t realTimeDomainDataSize,
217                                const float* complexTimeDomainData,
218                                const uint64_t complexTimeDomainDataSize,
219                                const double timePerFFT,
220                                const timespec timestamp,
221                                const bool lastOfMultipleFFTUpdateFlag)
222 {
223   int64_t bufferSize = inputBufferSize;
224   bool repeatDataFlag = false;
225   if(bufferSize > _dataPoints){
226     bufferSize = _dataPoints;
227   }
228   int64_t timeDomainBufferSize = 0;
229
230   if(updateDisplayFlag){
231     if((fftBuffer != NULL) && (bufferSize > 0)){
232       memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex<float>));
233     }
234
235     // Can't do a memcpy since ths is going from float to double data type
236     if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){
237       const float* realTimeDomainDataPtr = realTimeDomainData;
238
239       double* realTimeDomainPointsPtr = _realTimeDomainPoints;
240       timeDomainBufferSize = realTimeDomainDataSize;
241
242       memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double));
243       for( uint64_t number = 0; number < realTimeDomainDataSize; number++){
244         *realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++;
245       }
246     }
247
248     // Can't do a memcpy since ths is going from float to double data type
249     if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){
250       const float* complexTimeDomainDataPtr = complexTimeDomainData;
251
252       double* realTimeDomainPointsPtr = _realTimeDomainPoints;
253       double* imagTimeDomainPointsPtr = _imagTimeDomainPoints;
254
255       timeDomainBufferSize = complexTimeDomainDataSize;
256       for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){
257         *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
258         *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
259       }
260     }
261   }
262
263   // If bufferSize is zero, then just update the display by sending over the old data
264   if(bufferSize < 1){
265     bufferSize = _lastDataPointCount;
266     repeatDataFlag = true;
267   }
268   else{
269     // Since there is data this time, update the count
270     _lastDataPointCount = bufferSize;
271   }
272
273   const timespec currentTime = get_highres_clock();
274   const timespec lastUpdateGUITime = GetLastGUIUpdateTime();
275
276   if((diff_timespec(currentTime, lastUpdateGUITime) > (4*timePerFFT)) &&
277      (GetPendingGUIUpdateEvents() > 0) && !timespec_empty(&lastUpdateGUITime)) {
278     // Do not update the display if too much data is pending to be displayed
279     _droppedEntriesCount++;
280   }
281   else{
282     // Draw the Data
283     IncrementPendingGUIUpdateEvents();
284     qApp->postEvent(_spectrumDisplayForm,
285                     new SpectrumUpdateEvent(_fftPoints, bufferSize,
286                                             _realTimeDomainPoints,
287                                             _imagTimeDomainPoints,
288                                             timeDomainBufferSize,
289                                             timePerFFT, timestamp,
290                                             repeatDataFlag,
291                                             lastOfMultipleFFTUpdateFlag,
292                                             currentTime,
293                                             _droppedEntriesCount));
294     
295     // Only reset the dropped entries counter if this is not
296     // repeat data since repeat data is dropped by the display systems
297     if(!repeatDataFlag){
298       _droppedEntriesCount = 0;
299     }
300   }
301 }
302
303 float
304 SpectrumGUIClass::GetPowerValue() const
305 {
306   float returnValue = 0;
307   //_windowStateLock->Lock();
308   returnValue = _powerValue;
309   //_windowStateLock->Unlock();
310   return returnValue;
311 }
312
313 void
314 SpectrumGUIClass::SetPowerValue(const float value)
315 {
316   //_windowStateLock->Lock();
317   _powerValue = value;
318   //_windowStateLock->Unlock();
319 }
320
321 int
322 SpectrumGUIClass::GetWindowType() const
323 {
324   int returnValue = 0;
325   //_windowStateLock->Lock();
326   returnValue = _windowType;
327   //_windowStateLock->Unlock();
328   return returnValue;
329 }
330
331 void
332 SpectrumGUIClass::SetWindowType(const int newType)
333 {
334   //_windowStateLock->Lock();
335   _windowType = newType;
336   //_windowStateLock->Unlock();
337 }
338
339 int
340 SpectrumGUIClass::GetFFTSize() const
341 {
342   int returnValue = 0;
343   //_windowStateLock->Lock();
344   returnValue = _fftSize;
345   //_windowStateLock->Unlock();
346   return returnValue;
347 }
348
349 int
350 SpectrumGUIClass::GetFFTSizeIndex() const
351 {
352   int fftsize = GetFFTSize();
353   switch(fftsize) {
354   case(1024): return 0; break;
355   case(2048): return 1; break;
356   case(4096): return 2; break;
357   case(8192): return 3; break;
358   case(16384): return 3; break;
359   case(32768): return 3; break;
360   default: return 0;
361   }
362 }
363
364 void
365 SpectrumGUIClass::SetFFTSize(const int newSize)
366 {
367   //_windowStateLock->Lock();
368   _fftSize = newSize;
369   //_windowStateLock->Unlock();
370 }
371
372 timespec
373 SpectrumGUIClass::GetLastGUIUpdateTime() const
374 {
375   timespec returnValue;
376   //_windowStateLock->Lock();
377   returnValue = _lastGUIUpdateTime;
378   //_windowStateLock->Unlock();
379   return returnValue;
380 }
381
382 void
383 SpectrumGUIClass::SetLastGUIUpdateTime(const timespec newTime)
384 {
385   //_windowStateLock->Lock();
386   _lastGUIUpdateTime = newTime;
387   //_windowStateLock->Unlock();
388 }
389
390 unsigned int
391 SpectrumGUIClass::GetPendingGUIUpdateEvents() const
392 {
393   unsigned int returnValue = 0;
394   //_windowStateLock->Lock();
395   returnValue = _pendingGUIUpdateEventsCount;
396   //_windowStateLock->Unlock();
397   return returnValue;
398 }
399
400 void
401 SpectrumGUIClass::IncrementPendingGUIUpdateEvents()
402 {
403   //_windowStateLock->Lock();
404   _pendingGUIUpdateEventsCount++;
405   //_windowStateLock->Unlock();
406 }
407
408 void
409 SpectrumGUIClass::DecrementPendingGUIUpdateEvents()
410 {
411   //_windowStateLock->Lock();
412   if(_pendingGUIUpdateEventsCount > 0){
413     _pendingGUIUpdateEventsCount--;
414   }
415   //_windowStateLock->Unlock();
416 }
417
418 void
419 SpectrumGUIClass::ResetPendingGUIUpdateEvents()
420 {
421   //_windowStateLock->Lock();
422   _pendingGUIUpdateEventsCount = 0;
423   //_windowStateLock->Unlock();
424 }
425
426
427 QWidget*
428 SpectrumGUIClass::qwidget()
429 {
430   return (QWidget*)_spectrumDisplayForm;
431 }
432
433 void
434 SpectrumGUIClass::SetTimeDomainAxis(double min, double max)
435 {
436   _spectrumDisplayForm->SetTimeDomainAxis(min, max);
437 }
438
439 void
440 SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax,
441                                        double ymin, double ymax)
442 {
443   _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax);
444
445 }
446
447 void
448 SpectrumGUIClass::SetFrequencyAxis(double min, double max)
449 {
450   _spectrumDisplayForm->SetFrequencyAxis(min, max);
451 }
452
453 #endif /* SPECTRUM_GUI_CLASS_CPP */