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