diff --git a/CMakeLists.txt b/CMakeLists.txt index 3697dfd..f7fa48b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,7 @@ SET (cubicsdr_sources src/process/VisualProcessor.cpp src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp + src/process/FFTVisualDataThread.cpp src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp @@ -316,6 +317,7 @@ SET (cubicsdr_headers src/process/VisualProcessor.h src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h + src/process/FFTVisualDataThread.h src/ui/GLPanel.h src/ui/UITestCanvas.cpp src/ui/UITestCanvas.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 957651e..56ad675 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -133,15 +133,14 @@ AppFrame::AppFrame() : wxBoxSizer *wfSizer = new wxBoxSizer(wxHORIZONTAL); - wxGetApp().getWaterfallProcesor()->setup(2048); waterfallCanvas = new WaterfallCanvas(this, attribList); waterfallCanvas->setup(2048, 512); - - fftDistrib.setInput(wxGetApp().getWaterfallVisualQueue()); - fftDistrib.attachOutput(&fftQueue); - - wxGetApp().getWaterfallProcesor()->setInput(&fftQueue); - wxGetApp().getWaterfallProcesor()->attachOutput(waterfallCanvas->getVisualDataQueue()); + + waterfallDataThread = new FFTVisualDataThread(); + t_FFTData = new std::thread(&FFTVisualDataThread::threadMain, waterfallDataThread); + + waterfallDataThread->setInputQueue("IQDataInput", wxGetApp().getWaterfallVisualQueue()); + waterfallDataThread->setOutputQueue("FFTDataOutput", waterfallCanvas->getVisualDataQueue()); waterfallSpeedMeter = new MeterCanvas(this, attribList); waterfallSpeedMeter->setHelpTip("Waterfall speed, click or drag to adjust (max 1024 lines per second)"); @@ -376,7 +375,7 @@ AppFrame::AppFrame() : int wflps =wxGetApp().getConfig()->getWaterfallLinesPerSec(); waterfallSpeedMeter->setLevel(sqrt(wflps)); - fftDistrib.setLinesPerSecond(wflps); + waterfallDataThread->setLinesPerSecond(wflps); ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme()); @@ -400,7 +399,8 @@ AppFrame::AppFrame() : } AppFrame::~AppFrame() { - + waterfallDataThread->terminate(); + t_FFTData->join(); } @@ -486,7 +486,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) { waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency()); spectrumCanvas->setBandwidth(wxGetApp().getSampleRate()); spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); - fftDistrib.setLinesPerSecond(DEFAULT_WATERFALL_LPS); + waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS); waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS)); wxGetApp().getSpectrumProcesor()->setFFTAverageRate(0.65); spectrumAvgMeter->setLevel(0.65); @@ -613,7 +613,7 @@ void AppFrame::OnClose(wxCloseEvent& event) { wxGetApp().getConfig()->setSnap(wxGetApp().getFrequencySnap()); wxGetApp().getConfig()->setCenterFreq(wxGetApp().getFrequency()); wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcesor()->getFFTAverageRate()); - wxGetApp().getConfig()->setWaterfallLinesPerSec(fftDistrib.getLinesPerSecond()); + wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond()); wxGetApp().getConfig()->save(); event.Skip(); } @@ -766,42 +766,23 @@ void AppFrame::OnIdle(wxIdleEvent& event) { dproc->run(); - SpectrumVisualProcessor *wproc = wxGetApp().getWaterfallProcesor(); + SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor(); - int fftSize = wproc->getDesiredInputSize(); - - if (fftSize) { - fftDistrib.setFFTSize(fftSize); - } else { - fftDistrib.setFFTSize(DEFAULT_FFT_SIZE); - } - if (waterfallSpeedMeter->inputChanged()) { float val = waterfallSpeedMeter->getInputValue(); waterfallSpeedMeter->setLevel(val); - fftDistrib.setLinesPerSecond((int)ceil(val*val)); - wxGetApp().getWaterfallVisualQueue()->set_max_num_items((int)ceil(val*val)); - + waterfallDataThread->setLinesPerSecond((int)ceil(val*val)); GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val))); } - fftDistrib.run(); - wproc->setView(waterfallCanvas->getViewState()); wproc->setBandwidth(waterfallCanvas->getBandwidth()); wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); - while (!wproc->isInputEmpty()) { - wproc->run(); - } - waterfallCanvas->processInputQueue(); demodWaterfallCanvas->processInputQueue(); - if (this->IsVisible()) { - waterfallCanvas->DoPaint(); - demodWaterfallCanvas->DoPaint(); #ifdef __APPLE__ usleep(5000); #endif diff --git a/src/AppFrame.h b/src/AppFrame.h index 3531de5..42ea5e9 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -9,7 +9,8 @@ #include "MeterCanvas.h" #include "TuningCanvas.h" #include "ModeSelectorCanvas.h" -#include "UITestCanvas.h" +#include "FFTVisualDataThread.h" +//#include "UITestCanvas.h" #include @@ -94,8 +95,9 @@ private: std::string currentSessionFile; - FFTDataDistributor fftDistrib; - DemodulatorThreadInputQueue fftQueue; + FFTVisualDataThread *waterfallDataThread; + std::thread *t_FFTData; + wxDECLARE_EVENT_TABLE(); }; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 2283d57..b8cb515 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -282,10 +282,6 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcesor() { return &demodSpectrumProcessor; } -SpectrumVisualProcessor *CubicSDR::getWaterfallProcesor() { - return &waterfallProcessor; -} - VisualDataDistributor *CubicSDR::getSpectrumDistributor() { return &spectrumDistributor; } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 77dba79..9aaded6 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -58,7 +58,6 @@ public: ScopeVisualProcessor *getScopeProcessor(); SpectrumVisualProcessor *getSpectrumProcesor(); SpectrumVisualProcessor *getDemodSpectrumProcesor(); - SpectrumVisualProcessor *getWaterfallProcesor(); VisualDataDistributor *getSpectrumDistributor(); DemodulatorThreadOutputQueue* getAudioVisualQueue(); @@ -107,7 +106,6 @@ private: ScopeVisualProcessor scopeProcessor; SpectrumVisualProcessor spectrumProcessor; - SpectrumVisualProcessor waterfallProcessor; SpectrumVisualProcessor demodSpectrumProcessor; VisualDataDistributor spectrumDistributor; diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp new file mode 100644 index 0000000..67f4549 --- /dev/null +++ b/src/process/FFTVisualDataThread.cpp @@ -0,0 +1,68 @@ +#include "FFTVisualDataThread.h" +#include "CubicSDR.h" + +FFTVisualDataThread::FFTVisualDataThread() : linesPerSecond(DEFAULT_WATERFALL_LPS) { + lpsChanged.store(true); +} + +FFTVisualDataThread::~FFTVisualDataThread() { + +} + +void FFTVisualDataThread::setLinesPerSecond(int lps) { + linesPerSecond.store(lps); + lpsChanged.store(true); +} + +int FFTVisualDataThread::getLinesPerSecond() { + return linesPerSecond.load(); +} + +SpectrumVisualProcessor *FFTVisualDataThread::getProcessor() { + return &wproc; +} + +void FFTVisualDataThread::run() { + DemodulatorThreadInputQueue *pipeIQDataIn = (DemodulatorThreadInputQueue *)getInputQueue("IQDataInput"); + SpectrumVisualDataQueue *pipeFFTDataOut = (SpectrumVisualDataQueue *)getOutputQueue("FFTDataOutput"); + + fftDistrib.setInput(pipeIQDataIn); + fftDistrib.attachOutput(&fftQueue); + wproc.setInput(&fftQueue); + wproc.attachOutput(pipeFFTDataOut); + wproc.setup(2048); + + std::cout << "FFT visual data thread started." << std::endl; + + while(!terminated) { + +#ifndef _WIN32 + usleep(15000); +#else + Sleep(15); +#endif + + int fftSize = wproc.getDesiredInputSize(); + + if (fftSize) { + fftDistrib.setFFTSize(fftSize); + } else { + fftDistrib.setFFTSize(DEFAULT_FFT_SIZE); + } + + if (lpsChanged.load()) { + fftDistrib.setLinesPerSecond(linesPerSecond.load()); + pipeIQDataIn->set_max_num_items(linesPerSecond.load()); + lpsChanged.store(false); + } + + fftDistrib.run(); + + while (!wproc.isInputEmpty()) { + wproc.run(); + } + } + + std::cout << "FFT visual data thread terminated." << std::endl; +} + diff --git a/src/process/FFTVisualDataThread.h b/src/process/FFTVisualDataThread.h new file mode 100644 index 0000000..a08cd4d --- /dev/null +++ b/src/process/FFTVisualDataThread.h @@ -0,0 +1,24 @@ +#pragma once + +#include "IOThread.h" +#include "SpectrumVisualProcessor.h" + +class FFTVisualDataThread : public IOThread { +public: + FFTVisualDataThread(); + ~FFTVisualDataThread(); + + void setLinesPerSecond(int lps); + int getLinesPerSecond(); + SpectrumVisualProcessor *getProcessor(); + + void run(); + +protected: + FFTDataDistributor fftDistrib; + DemodulatorThreadInputQueue fftQueue; + SpectrumVisualProcessor wproc; + + std::atomic_int linesPerSecond; + std::atomic_bool lpsChanged; +}; diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index fd7f013..8e1e694 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -111,7 +111,10 @@ protected: if (inp) { if (inp->data.size() >= fftSize) { - for (int i = 0, iMax = inp->data.size()-fftSize; i <= iMax; i += fftSize) { + if (lineRateAccum + (lineRateStep * floor((double)inp->data.size()/(double)fftSize)) < 1.0) { + // move along, nothing to see here.. + lineRateAccum += (lineRateStep * inp->data.size()/fftSize); + } else for (int i = 0, iMax = inp->data.size()-fftSize; i <= iMax; i += fftSize) { lineRateAccum += lineRateStep; if (lineRateAccum >= 1.0) { diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 00bc773..8ec1c2d 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -88,12 +88,8 @@ void WaterfallCanvas::processInputQueue() { } void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { -// event.Skip(); -} - -void WaterfallCanvas::DoPaint() { - wxClientDC dc(this); - // wxPaintDC dc(this); +// wxClientDC dc(this); + wxPaintDC dc(this); const wxSize ClientSize = GetClientSize(); long double currentZoom = zoom; @@ -359,9 +355,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } } void WaterfallCanvas::OnIdle(wxIdleEvent &event) { -// Refresh(); -// event.RequestMore(); - event.Skip(); + Refresh(); + event.RequestMore(); +// event.Skip(); } void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 1b59e35..2f51ec3 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -28,7 +28,6 @@ public: void attachSpectrumCanvas(SpectrumCanvas *canvas_in); void processInputQueue(); SpectrumVisualDataQueue *getVisualDataQueue(); - void DoPaint(); private: void OnPaint(wxPaintEvent& event);