/* -*- c++ -*- */ /* * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef SPECTRUM_GUI_CLASS_CPP #define SPECTRUM_GUI_CLASS_CPP #include //Added by qt3to4: #include #include const long SpectrumGUIClass::MAX_FFT_SIZE = 32768; const long SpectrumGUIClass::MIN_FFT_SIZE = 1024; SpectrumGUIClass::SpectrumGUIClass(const uint64_t maxDataSize, const uint64_t fftSize, const double newCenterFrequency, const double newStartFrequency, const double newStopFrequency) { _dataPoints = maxDataSize; if(_dataPoints < 2){ _dataPoints = 2; } _lastDataPointCount = _dataPoints; _fftSize = fftSize; _pendingGUIUpdateEventsCount = 0; _droppedEntriesCount = 0; _centerFrequency = newCenterFrequency; _startFrequency = newStartFrequency; _stopFrequency = newStopFrequency; _windowType = 5; _lastGUIUpdateTime = 0; _windowOpennedFlag = false; _fftBuffersCreatedFlag = false; _powerValue = 1; } SpectrumGUIClass::~SpectrumGUIClass() { // We don't need to delete this since as a QWidget, it is supposed to be destroyed // with it's parent. Deleting it causes a segmentation fault, and not deleting it // does not leave any extra memory. //if(GetWindowOpenFlag()){ //delete _spectrumDisplayForm; //} if(_fftBuffersCreatedFlag){ delete[] _fftPoints; delete[] _realTimeDomainPoints; delete[] _imagTimeDomainPoints; } } void SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, const bool frequency, const bool waterfall, const bool time, const bool constellation) { d_mutex.lock(); if(!_windowOpennedFlag){ if(!_fftBuffersCreatedFlag){ _fftPoints = new std::complex[_dataPoints]; _realTimeDomainPoints = new double[_dataPoints]; _imagTimeDomainPoints = new double[_dataPoints]; _fftBuffersCreatedFlag = true; memset(_fftPoints, 0x0, _dataPoints*sizeof(std::complex)); memset(_realTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); memset(_imagTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); } // Called from the Event Thread _spectrumDisplayForm = new SpectrumDisplayForm(parent); // Toggle Windows on/off _spectrumDisplayForm->ToggleTabFrequency(frequency); _spectrumDisplayForm->ToggleTabWaterfall(waterfall); _spectrumDisplayForm->ToggleTabTime(time); _spectrumDisplayForm->ToggleTabConstellation(constellation); _windowOpennedFlag = true; _spectrumDisplayForm->setSystem(this, _dataPoints, _fftSize); qApp->processEvents(); } d_mutex.unlock(); SetDisplayTitle(_title); Reset(); qApp->postEvent(_spectrumDisplayForm, new QEvent(QEvent::Type(QEvent::User+3))); _lastGUIUpdateTime = 0; // Draw Blank Display UpdateWindow(false, NULL, 0, NULL, 0, NULL, 0, get_highres_clock(), true); // Set up the initial frequency axis settings SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); // GUI Thread only qApp->processEvents(); } void SpectrumGUIClass::Reset() { if(GetWindowOpenFlag()) { qApp->postEvent(_spectrumDisplayForm, new SpectrumFrequencyRangeEvent(_centerFrequency, _startFrequency, _stopFrequency)); qApp->postEvent(_spectrumDisplayForm, new SpectrumWindowResetEvent()); } _droppedEntriesCount = 0; // Call the following function the the Spectrum Window Reset Event window // ResetPendingGUIUpdateEvents(); } void SpectrumGUIClass::SetDisplayTitle(const std::string newString) { _title.assign(newString); if(GetWindowOpenFlag()){ qApp->postEvent(_spectrumDisplayForm, new SpectrumWindowCaptionEvent(_title.c_str())); } } bool SpectrumGUIClass::GetWindowOpenFlag() { gruel::scoped_lock lock(d_mutex); bool returnFlag = false; returnFlag = _windowOpennedFlag; return returnFlag; } void SpectrumGUIClass::SetWindowOpenFlag(const bool newFlag) { gruel::scoped_lock lock(d_mutex); _windowOpennedFlag = newFlag; } void SpectrumGUIClass::SetFrequencyRange(const double centerFreq, const double startFreq, const double stopFreq) { gruel::scoped_lock lock(d_mutex); _centerFrequency = centerFreq; _startFrequency = startFreq; _stopFrequency = stopFreq; _spectrumDisplayForm->SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency); } double SpectrumGUIClass::GetStartFrequency() { gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; returnValue = _startFrequency; return returnValue; } double SpectrumGUIClass::GetStopFrequency() { gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; returnValue = _stopFrequency; return returnValue; } double SpectrumGUIClass::GetCenterFrequency() { gruel::scoped_lock lock(d_mutex); double returnValue = 0.0; returnValue = _centerFrequency; return returnValue; } void SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, const std::complex* fftBuffer, const uint64_t inputBufferSize, const float* realTimeDomainData, const uint64_t realTimeDomainDataSize, const float* complexTimeDomainData, const uint64_t complexTimeDomainDataSize, const highres_timespec timestamp, const bool lastOfMultipleFFTUpdateFlag) { //gruel::scoped_lock lock(d_mutex); int64_t bufferSize = inputBufferSize; bool repeatDataFlag = false; if(bufferSize > _dataPoints){ bufferSize = _dataPoints; } int64_t timeDomainBufferSize = 0; if(updateDisplayFlag){ if((fftBuffer != NULL) && (bufferSize > 0)){ memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex)); } // Can't do a memcpy since ths is going from float to double data type if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){ const float* realTimeDomainDataPtr = realTimeDomainData; double* realTimeDomainPointsPtr = _realTimeDomainPoints; timeDomainBufferSize = realTimeDomainDataSize; memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double)); for( uint64_t number = 0; number < realTimeDomainDataSize; number++){ *realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++; } } // Can't do a memcpy since ths is going from float to double data type if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){ const float* complexTimeDomainDataPtr = complexTimeDomainData; double* realTimeDomainPointsPtr = _realTimeDomainPoints; double* imagTimeDomainPointsPtr = _imagTimeDomainPoints; timeDomainBufferSize = complexTimeDomainDataSize; for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){ *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; } } } // If bufferSize is zero, then just update the display by sending over the old data if(bufferSize < 1){ bufferSize = _lastDataPointCount; repeatDataFlag = true; } else{ // Since there is data this time, update the count _lastDataPointCount = bufferSize; } const highres_timespec currentTime = get_highres_clock(); const highres_timespec lastUpdateGUITime = GetLastGUIUpdateTime(); if((currentTime - lastUpdateGUITime > (4*_updateTime)*gruel::high_res_timer_tps()) && (GetPendingGUIUpdateEvents() > 0) && lastUpdateGUITime != 0) { // Do not update the display if too much data is pending to be displayed _droppedEntriesCount++; } else{ // Draw the Data IncrementPendingGUIUpdateEvents(); qApp->postEvent(_spectrumDisplayForm, new SpectrumUpdateEvent(_fftPoints, bufferSize, _realTimeDomainPoints, _imagTimeDomainPoints, timeDomainBufferSize, timestamp, repeatDataFlag, lastOfMultipleFFTUpdateFlag, currentTime, _droppedEntriesCount)); // Only reset the dropped entries counter if this is not // repeat data since repeat data is dropped by the display systems if(!repeatDataFlag){ _droppedEntriesCount = 0; } } } float SpectrumGUIClass::GetPowerValue() { gruel::scoped_lock lock(d_mutex); float returnValue = 0; returnValue = _powerValue; return returnValue; } void SpectrumGUIClass::SetPowerValue(const float value) { gruel::scoped_lock lock(d_mutex); _powerValue = value; } int SpectrumGUIClass::GetWindowType() { gruel::scoped_lock lock(d_mutex); int returnValue = 0; returnValue = _windowType; return returnValue; } void SpectrumGUIClass::SetWindowType(const int newType) { gruel::scoped_lock lock(d_mutex); _windowType = newType; } int SpectrumGUIClass::GetFFTSize() { int returnValue = 0; returnValue = _fftSize; return returnValue; } int SpectrumGUIClass::GetFFTSizeIndex() { gruel::scoped_lock lock(d_mutex); int fftsize = GetFFTSize(); switch(fftsize) { case(1024): return 0; break; case(2048): return 1; break; case(4096): return 2; break; case(8192): return 3; break; case(16384): return 3; break; case(32768): return 3; break; default: return 0; } } void SpectrumGUIClass::SetFFTSize(const int newSize) { gruel::scoped_lock lock(d_mutex); _fftSize = newSize; } highres_timespec SpectrumGUIClass::GetLastGUIUpdateTime() { gruel::scoped_lock lock(d_mutex); highres_timespec returnValue; returnValue = _lastGUIUpdateTime; return returnValue; } void SpectrumGUIClass::SetLastGUIUpdateTime(const highres_timespec newTime) { gruel::scoped_lock lock(d_mutex); _lastGUIUpdateTime = newTime; } unsigned int SpectrumGUIClass::GetPendingGUIUpdateEvents() { gruel::scoped_lock lock(d_mutex); unsigned int returnValue = 0; returnValue = _pendingGUIUpdateEventsCount; return returnValue; } void SpectrumGUIClass::IncrementPendingGUIUpdateEvents() { gruel::scoped_lock lock(d_mutex); _pendingGUIUpdateEventsCount++; } void SpectrumGUIClass::DecrementPendingGUIUpdateEvents() { gruel::scoped_lock lock(d_mutex); if(_pendingGUIUpdateEventsCount > 0){ _pendingGUIUpdateEventsCount--; } } void SpectrumGUIClass::ResetPendingGUIUpdateEvents() { gruel::scoped_lock lock(d_mutex); _pendingGUIUpdateEventsCount = 0; } QWidget* SpectrumGUIClass::qwidget() { gruel::scoped_lock lock(d_mutex); return (QWidget*)_spectrumDisplayForm; } void SpectrumGUIClass::SetTimeDomainAxis(double min, double max) { gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetTimeDomainAxis(min, max); } void SpectrumGUIClass::SetConstellationAxis(double xmin, double xmax, double ymin, double ymax) { gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetConstellationAxis(xmin, xmax, ymin, ymax); } void SpectrumGUIClass::SetConstellationPenSize(int size) { gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetConstellationPenSize(size); } void SpectrumGUIClass::SetFrequencyAxis(double min, double max) { gruel::scoped_lock lock(d_mutex); _spectrumDisplayForm->SetFrequencyAxis(min, max); } void SpectrumGUIClass::SetUpdateTime(double t) { gruel::scoped_lock lock(d_mutex); _updateTime = t; _spectrumDisplayForm->SetUpdateTime(_updateTime); } #endif /* SPECTRUM_GUI_CLASS_CPP */