4cb71a31a055e5f7c227d6eba79be8993a026a41
[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, 1.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 double timePerFFT,
224                                const timespec timestamp,
225                                const bool lastOfMultipleFFTUpdateFlag)
226 {
227   int64_t bufferSize = inputBufferSize;
228   bool repeatDataFlag = false;
229   if(bufferSize > _dataPoints){
230     bufferSize = _dataPoints;
231   }
232   int64_t timeDomainBufferSize = 0;
233
234   if(updateDisplayFlag){
235     if((fftBuffer != NULL) && (bufferSize > 0)){
236       memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex<float>));
237     }
238
239     // Can't do a memcpy since ths is going from float to double data type
240     if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){
241       const float* realTimeDomainDataPtr = realTimeDomainData;
242
243       double* realTimeDomainPointsPtr = _realTimeDomainPoints;
244       timeDomainBufferSize = realTimeDomainDataSize;
245
246       memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double));
247       for( uint64_t number = 0; number < realTimeDomainDataSize; number++){
248         *realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++;
249       }
250     }
251
252     // Can't do a memcpy since ths is going from float to double data type
253     if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){
254       const float* complexTimeDomainDataPtr = complexTimeDomainData;
255
256       double* realTimeDomainPointsPtr = _realTimeDomainPoints;
257       double* imagTimeDomainPointsPtr = _imagTimeDomainPoints;
258
259       timeDomainBufferSize = complexTimeDomainDataSize;
260       for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){
261         *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
262         *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++;
263       }
264     }
265   }
266
267   // If bufferSize is zero, then just update the display by sending over the old data
268   if(bufferSize < 1){
269     bufferSize = _lastDataPointCount;
270     repeatDataFlag = true;
271   }
272   else{
273     // Since there is data this time, update the count
274     _lastDataPointCount = bufferSize;
275   }
276
277   const timespec currentTime = get_highres_clock();
278   const timespec lastUpdateGUITime = GetLastGUIUpdateTime();
279
280   if((diff_timespec(currentTime, lastUpdateGUITime) > (4*timePerFFT)) &&
281      (GetPendingGUIUpdateEvents() > 0) && !timespec_empty(&lastUpdateGUITime)) {
282     // Do not update the display if too much data is pending to be displayed
283     _droppedEntriesCount++;
284   }
285   else{
286     // Draw the Data
287     IncrementPendingGUIUpdateEvents();
288     qApp->postEvent(_spectrumDisplayForm,
289                     new SpectrumUpdateEvent(_fftPoints, bufferSize,
290                                             _realTimeDomainPoints,
291                                             _imagTimeDomainPoints,
292                                             timeDomainBufferSize,
293                                             timePerFFT, timestamp,
294                                             repeatDataFlag,
295                                             lastOfMultipleFFTUpdateFlag,
296                                             currentTime,
297                                             _droppedEntriesCount));
298     
299     // Only reset the dropped entries counter if this is not
300     // repeat data since repeat data is dropped by the display systems
301     if(!repeatDataFlag){
302       _droppedEntriesCount = 0;
303     }
304   }
305 }
306
307 float
308 SpectrumGUIClass::GetPowerValue() const
309 {
310   float returnValue = 0;
311   //_windowStateLock->Lock();
312   returnValue = _powerValue;
313   //_windowStateLock->Unlock();
314   return returnValue;
315 }
316
317 void
318 SpectrumGUIClass::SetPowerValue(const float value)
319 {
320   //_windowStateLock->Lock();
321   _powerValue = value;
322   //_windowStateLock->Unlock();
323 }
324
325 int
326 SpectrumGUIClass::GetWindowType() const
327 {
328   int returnValue = 0;
329   //_windowStateLock->Lock();
330   returnValue = _windowType;
331   //_windowStateLock->Unlock();
332   return returnValue;
333 }
334
335 void
336 SpectrumGUIClass::SetWindowType(const int newType)
337 {
338   //_windowStateLock->Lock();
339   _windowType = newType;
340   //_windowStateLock->Unlock();
341 }
342
343 int
344 SpectrumGUIClass::GetFFTSize() const
345 {
346   int returnValue = 0;
347   //_windowStateLock->Lock();
348   returnValue = _fftSize;
349   //_windowStateLock->Unlock();
350   return returnValue;
351 }
352
353 int
354 SpectrumGUIClass::GetFFTSizeIndex() const
355 {
356   int fftsize = GetFFTSize();
357   switch(fftsize) {
358   case(1024): return 0; break;
359   case(2048): return 1; break;
360   case(4096): return 2; break;
361   case(8192): return 3; break;
362   case(16384): return 3; break;
363   case(32768): return 3; break;
364   default: return 0;
365   }
366 }
367
368 void
369 SpectrumGUIClass::SetFFTSize(const int newSize)
370 {
371   //_windowStateLock->Lock();
372   _fftSize = newSize;
373   //_windowStateLock->Unlock();
374 }
375
376 timespec
377 SpectrumGUIClass::GetLastGUIUpdateTime() const
378 {
379   timespec returnValue;
380   //_windowStateLock->Lock();
381   returnValue = _lastGUIUpdateTime;
382   //_windowStateLock->Unlock();
383   return returnValue;
384 }
385
386 void
387 SpectrumGUIClass::SetLastGUIUpdateTime(const timespec newTime)
388 {
389   //_windowStateLock->Lock();
390   _lastGUIUpdateTime = newTime;
391   //_windowStateLock->Unlock();
392 }
393
394 unsigned int
395 SpectrumGUIClass::GetPendingGUIUpdateEvents() const
396 {
397   unsigned int returnValue = 0;
398   //_windowStateLock->Lock();
399   returnValue = _pendingGUIUpdateEventsCount;
400   //_windowStateLock->Unlock();
401   return returnValue;
402 }
403
404 void
405 SpectrumGUIClass::IncrementPendingGUIUpdateEvents()
406 {
407   //_windowStateLock->Lock();
408   _pendingGUIUpdateEventsCount++;
409   //_windowStateLock->Unlock();
410 }
411
412 void
413 SpectrumGUIClass::DecrementPendingGUIUpdateEvents()
414 {
415   //_windowStateLock->Lock();
416   if(_pendingGUIUpdateEventsCount > 0){
417     _pendingGUIUpdateEventsCount--;
418   }
419   //_windowStateLock->Unlock();
420 }
421
422 void
423 SpectrumGUIClass::ResetPendingGUIUpdateEvents()
424 {
425   //_windowStateLock->Lock();
426   _pendingGUIUpdateEventsCount = 0;
427   //_windowStateLock->Unlock();
428 }
429
430
431 QWidget*
432 SpectrumGUIClass::qwidget()
433 {
434   return (QWidget*)_spectrumDisplayForm;
435 }
436
437 void
438 SpectrumGUIClass::SetTimeDomainAxis(double min, double max)
439 {
440   _spectrumDisplayForm->SetTimeDomainAxis(min, max);
441 }
442
443 void
444 SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax,
445                                        double ymin, double ymax)
446 {
447   _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax);
448
449 }
450
451 void
452 SpectrumGUIClass::SetConstellationPenSize(int size){
453   _spectrumDisplayForm->SetConstellationPenSize(size);
454 }
455
456
457 void
458 SpectrumGUIClass::SetFrequencyAxis(double min, double max)
459 {
460   _spectrumDisplayForm->SetFrequencyAxis(min, max);
461 }
462
463 #endif /* SPECTRUM_GUI_CLASS_CPP */