From 8dc2e6cacc6f9508d63936667c56cf688d4e23ab Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 19:17:43 -0400 Subject: [PATCH 01/14] Move waterfall FFT processing to it's own thread. --- CMakeLists.txt | 2 + src/AppFrame.cpp | 45 +++++------------- src/AppFrame.h | 8 ++-- src/CubicSDR.cpp | 4 -- src/CubicSDR.h | 2 - src/process/FFTVisualDataThread.cpp | 68 +++++++++++++++++++++++++++ src/process/FFTVisualDataThread.h | 24 ++++++++++ src/process/SpectrumVisualProcessor.h | 5 +- src/visual/WaterfallCanvas.cpp | 14 ++---- src/visual/WaterfallCanvas.h | 1 - 10 files changed, 121 insertions(+), 52 deletions(-) create mode 100644 src/process/FFTVisualDataThread.cpp create mode 100644 src/process/FFTVisualDataThread.h 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); From 8c7d2576ad9af728c05f087dad455312f593f13c Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 20:19:37 -0400 Subject: [PATCH 02/14] Update frequency dialog to support bandwidth entry --- src/CubicSDR.cpp | 22 ++++++++++++++++--- src/CubicSDR.h | 3 ++- src/FrequencyDialog.cpp | 42 +++++++++++++++++++++++++------------ src/FrequencyDialog.h | 6 ++++-- src/visual/TuningCanvas.cpp | 8 +++++-- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index b8cb515..f9bff43 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -13,7 +13,6 @@ #endif #include "CubicSDR.h" -#include "FrequencyDialog.h" #ifdef _OSX_APP_ #include "CoreFoundation/CoreFoundation.h" @@ -389,8 +388,25 @@ int CubicSDR::getPPM() { } -void CubicSDR::showFrequencyInput() { - FrequencyDialog fdialog(appframe, -1, demodMgr.getActiveDemodulator()?_("Set Demodulator Frequency"):_("Set Center Frequency"), demodMgr.getActiveDemodulator(), wxPoint(-100,-100), wxSize(320, 75 )); +void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode) { + const wxString demodTitle("Set Demodulator Frequency"); + const wxString freqTitle("Set Center Frequency"); + const wxString bwTitle("Set Demodulator Bandwidth"); + + wxString title; + + switch (targetMode) { + case FrequencyDialog::FDIALOG_TARGET_DEFAULT: + title = demodMgr.getActiveDemodulator()?demodTitle:freqTitle; + break; + case FrequencyDialog::FDIALOG_TARGET_BANDWIDTH: + title = bwTitle; + break; + default: + break; + } + + FrequencyDialog fdialog(appframe, -1, title, demodMgr.getActiveDemodulator(), wxPoint(-100,-100), wxSize(320, 75 ), wxDEFAULT_DIALOG_STYLE, targetMode); fdialog.ShowModal(); } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 9aaded6..015b629 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -16,6 +16,7 @@ #include "DemodulatorMgr.h" #include "AppConfig.h" #include "AppFrame.h" +#include "FrequencyDialog.h" #include "ScopeVisualProcessor.h" #include "SpectrumVisualProcessor.h" @@ -77,7 +78,7 @@ public: void setPPM(int ppm_in); int getPPM(); - void showFrequencyInput(); + void showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetMode = FrequencyDialog::FDIALOG_TARGET_DEFAULT); private: AppFrame *appframe; diff --git a/src/FrequencyDialog.cpp b/src/FrequencyDialog.cpp index 712739e..bed49cd 100644 --- a/src/FrequencyDialog.cpp +++ b/src/FrequencyDialog.cpp @@ -10,15 +10,22 @@ EVT_CHAR_HOOK(FrequencyDialog::OnChar) wxEND_EVENT_TABLE() FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstance *demod, const wxPoint & position, - const wxSize & size, long style) : + const wxSize & size, long style, FrequencyDialogTarget targetMode) : wxDialog(parent, id, title, position, size, style) { wxString freqStr; activeDemod = demod; + this->targetMode = targetMode; - if (activeDemod) { - freqStr = frequencyToStr(activeDemod->getFrequency()); - } else { - freqStr = frequencyToStr(wxGetApp().getFrequency()); + if (targetMode == FDIALOG_TARGET_DEFAULT) { + if (activeDemod) { + freqStr = frequencyToStr(activeDemod->getFrequency()); + } else { + freqStr = frequencyToStr(wxGetApp().getFrequency()); + } + } + + if (targetMode == FDIALOG_TARGET_BANDWIDTH) { + freqStr = frequencyToStr(wxGetApp().getDemodMgr().getLastBandwidth()); } dialogText = new wxTextCtrl(this, wxID_FREQ_INPUT, freqStr, wxPoint(6, 1), wxSize(size.GetWidth() - 20, size.GetHeight() - 70), @@ -109,14 +116,23 @@ void FrequencyDialog::OnChar(wxKeyEvent& event) { case WXK_NUMPAD_ENTER: // Do Stuff freq = strToFrequency(dialogText->GetValue().ToStdString()); - if (activeDemod) { - activeDemod->setTracking(true); - activeDemod->setFollow(true); - activeDemod->setFrequency(freq); - activeDemod->updateLabel(freq); - } else { - wxGetApp().setFrequency(freq); - } + if (targetMode == FDIALOG_TARGET_DEFAULT) { + if (activeDemod) { + activeDemod->setTracking(true); + activeDemod->setFollow(true); + activeDemod->setFrequency(freq); + activeDemod->updateLabel(freq); + } else { + wxGetApp().setFrequency(freq); + } + } + if (targetMode == FDIALOG_TARGET_BANDWIDTH) { + if (activeDemod) { + activeDemod->setBandwidth(freq); + } else { + wxGetApp().getDemodMgr().setLastBandwidth(freq); + } + } Close(); break; case WXK_ESCAPE: diff --git a/src/FrequencyDialog.h b/src/FrequencyDialog.h index 42ad7b0..4f2b931 100644 --- a/src/FrequencyDialog.h +++ b/src/FrequencyDialog.h @@ -11,12 +11,13 @@ class FrequencyDialog: public wxDialog { public: - + typedef enum FrequencyDialogTarget { FDIALOG_TARGET_DEFAULT, FDIALOG_TARGET_CENTERFREQ, FDIALOG_TARGET_FREQ, FDIALOG_TARGET_BANDWIDTH } FrequencyDialogTarget; FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstance *demod = NULL, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, - long style = wxDEFAULT_DIALOG_STYLE ); + long style = wxDEFAULT_DIALOG_STYLE, + FrequencyDialogTarget targetMode = FDIALOG_TARGET_DEFAULT); wxTextCtrl * dialogText; @@ -28,5 +29,6 @@ private: void OnEnter ( wxCommandEvent &event ); void OnChar ( wxKeyEvent &event ); std::string& filterChars(std::string& s, const std::string& allowed); + FrequencyDialogTarget targetMode; DECLARE_EVENT_TABLE() }; diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 8a85ac4..6ac2e9b 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -407,8 +407,12 @@ void TuningCanvas::setHelpTip(std::string tip) { void TuningCanvas::OnKeyDown(wxKeyEvent& event) { InteractiveCanvas::OnKeyDown(event); - if (event.GetKeyCode() == WXK_SPACE && (hoverState == TUNING_HOVER_CENTER || hoverState == TUNING_HOVER_FREQ)) { - wxGetApp().showFrequencyInput(); + if (event.GetKeyCode() == WXK_SPACE) { + if (hoverState == TUNING_HOVER_CENTER || hoverState == TUNING_HOVER_FREQ) { + wxGetApp().showFrequencyInput(FrequencyDialog::FDIALOG_TARGET_DEFAULT); + } else if (hoverState == TUNING_HOVER_BW) { + wxGetApp().showFrequencyInput(FrequencyDialog::FDIALOG_TARGET_BANDWIDTH); + } } } From 9c1d9f57980a0257be95b944e0f99b77c3fc5fed Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 20:41:52 -0400 Subject: [PATCH 03/14] IsVisible is *not* for app visibility; Hello there, IsActive() --- src/AppFrame.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 56ad675..7799cfd 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -782,15 +782,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) { waterfallCanvas->processInputQueue(); demodWaterfallCanvas->processInputQueue(); - if (this->IsVisible()) { -#ifdef __APPLE__ - usleep(5000); -#endif - } else { + if (!this->IsActive()) { #ifndef _WIN32 - usleep(15000); + usleep(50000); #else - Sleep(15); + Sleep(50); #endif } From 89332d03b8dea3fbce3af0c6393fd59104d65de1 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 20:54:18 -0400 Subject: [PATCH 04/14] too much delay.. --- src/AppFrame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 7799cfd..d737ca0 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -784,9 +784,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (!this->IsActive()) { #ifndef _WIN32 - usleep(50000); + usleep(25000); #else - Sleep(50); + Sleep(25); #endif } From 22ed3d3b275f481abb66f2fe98ee2f8985d4c4f0 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:20:07 -0400 Subject: [PATCH 05/14] Unify sleepy code to std::thread sleep --- src/AppFrame.cpp | 6 +----- src/process/FFTVisualDataThread.cpp | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index d737ca0..af93aae 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -783,11 +783,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodWaterfallCanvas->processInputQueue(); if (!this->IsActive()) { -#ifndef _WIN32 - usleep(25000); -#else - Sleep(25); -#endif + std::this_thread::sleep_for(std::chrono::milliseconds(25)); } event.RequestMore(); diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index 67f4549..df5a9bf 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -36,11 +36,7 @@ void FFTVisualDataThread::run() { while(!terminated) { -#ifndef _WIN32 - usleep(15000); -#else - Sleep(15); -#endif + std::this_thread::sleep_for(std::chrono::milliseconds(15)); int fftSize = wproc.getDesiredInputSize(); From e98088159c7ee32175cfb15dd6f3a03ee7bef80a Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:23:58 -0400 Subject: [PATCH 06/14] FFTVisualDataThread sleep adjustment --- src/process/FFTVisualDataThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index df5a9bf..f4eabfb 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -36,7 +36,7 @@ void FFTVisualDataThread::run() { while(!terminated) { - std::this_thread::sleep_for(std::chrono::milliseconds(15)); + std::this_thread::sleep_for(std::chrono::milliseconds(12)); int fftSize = wproc.getDesiredInputSize(); From 4cc4c151fab8eb7a7e5c6749385e25cb1ea0cc80 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:28:43 -0400 Subject: [PATCH 07/14] Reduce log noise, run an old version to show if need be.. --- src/util/GLExt.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/util/GLExt.cpp b/src/util/GLExt.cpp index eb1e7d6..88785a9 100644 --- a/src/util/GLExt.cpp +++ b/src/util/GLExt.cpp @@ -32,9 +32,8 @@ void initGLExtensions() { return; } - const GLubyte *extensions = glGetString(GL_EXTENSIONS); - - std::cout << std::endl << "Supported GL Extensions: " << std::endl << extensions << std::endl << std::endl; +// const GLubyte *extensions = glGetString(GL_EXTENSIONS); +// std::cout << std::endl << "Supported GL Extensions: " << std::endl << extensions << std::endl << std::endl; #ifdef __linux__ const GLint interval = 2; From b41d0a361314f1f05571466f2af717e889238eba Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:32:58 -0400 Subject: [PATCH 08/14] Update tuner bandwidth help tip --- src/visual/TuningCanvas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 6ac2e9b..b6fa267 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -297,7 +297,7 @@ void TuningCanvas::OnMouseMoved(wxMouseEvent& event) { setStatusText("Click, wheel or drag a digit to change frequency; SPACE for direct input. Right click to set/clear snap. Hold ALT to change PPM. Hold SHIFT to disable carry."); break; case TUNING_HOVER_BW: - setStatusText("Click, wheel or drag a digit to change bandwidth. Hold SHIFT to disable carry."); + setStatusText("Click, wheel or drag a digit to change bandwidth; SPACE for direct input. Hold SHIFT to disable carry."); break; case TUNING_HOVER_CENTER: setStatusText("Click, wheel or drag a digit to change center frequency; SPACE for direct input. Hold SHIFT to disable carry."); From 91a6e45ed38d3ed093dc0d7cb0738920d92f441c Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:36:31 -0400 Subject: [PATCH 09/14] Fix spectrum visual failure below 1% averaging speed --- src/AppFrame.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index af93aae..8c05eeb 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -746,6 +746,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (spectrumAvgMeter->inputChanged()) { float val = spectrumAvgMeter->getInputValue(); + if (val < 0.01) { + val = 0.01; + } spectrumAvgMeter->setLevel(val); proc->setFFTAverageRate(val); From 52cde1e0f7788246efe22d59d6040bcd04210bde Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 14 Aug 2015 21:50:44 -0400 Subject: [PATCH 10/14] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 79a923b..cba51ff 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Features and Status: - [ ] Undo / Redo action - I/Q Recording and playback - [ ] Recording + - [ ] Record waterfall output to PNG file chunks of desired height - [ ] Record I/Q input data - [ ] Simultaneously record demod decimated I/Q and audio - [ ] Playback From 3e2570a26cc75777b64bd551b8e752a8894feda1 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 15 Aug 2015 04:47:01 -0400 Subject: [PATCH 11/14] Waterfall keyboard control updates --- src/visual/WaterfallCanvas.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 8ec1c2d..6bbd6d2 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -252,10 +252,14 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { ctrlDown = event.ControlDown(); switch (event.GetKeyCode()) { case 'A': - zoom = 1.0; + case WXK_UP: + case WXK_NUMPAD_UP: + zoom = 1.0; break; case 'Z': - zoom = 1.0; + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + zoom = 1.0; break; } } @@ -269,16 +273,21 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { long long originalFreq; switch (event.GetKeyCode()) { case 'A': - zoom = 0.95; + case WXK_UP: + case WXK_NUMPAD_UP: + zoom = 0.95; break; case 'Z': - zoom = 1.05; + case WXK_DOWN: + case WXK_NUMPAD_DOWN: + zoom = 1.05; break; case WXK_RIGHT: - freq = wxGetApp().getFrequency(); + case WXK_NUMPAD_RIGHT: + freq = getCenterFrequency(); originalFreq = freq; if (shiftDown) { - freq += wxGetApp().getSampleRate() * 10; + freq += getBandwidth() * 10; if (isView) { setView(centerFreq + (freq - originalFreq), getBandwidth()); if (spectrumCanvas) { @@ -286,7 +295,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } } } else { - freq += wxGetApp().getSampleRate() / 2; + freq += getBandwidth() / 2; if (isView) { setView(centerFreq + (freq - originalFreq), getBandwidth()); if (spectrumCanvas) { @@ -298,13 +307,14 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { setStatusText("Set center frequency: %s", freq); break; case WXK_LEFT: - freq = wxGetApp().getFrequency(); + case WXK_NUMPAD_LEFT: + freq = getCenterFrequency(); originalFreq = freq; if (shiftDown) { - if ((freq - wxGetApp().getSampleRate() * 10) < wxGetApp().getSampleRate() / 2) { + if ((freq - getBandwidth() * 10) < wxGetApp().getSampleRate() / 2) { freq = wxGetApp().getSampleRate() / 2; } else { - freq -= wxGetApp().getSampleRate() * 10; + freq -= getBandwidth() * 10; } if (isView) { setView(centerFreq + (freq - originalFreq), getBandwidth()); @@ -313,10 +323,10 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } } } else { - if ((freq - wxGetApp().getSampleRate() / 2) < wxGetApp().getSampleRate() / 2) { + if ((freq - getBandwidth() / 2) < wxGetApp().getSampleRate() / 2) { freq = wxGetApp().getSampleRate() / 2; } else { - freq -= wxGetApp().getSampleRate() / 2; + freq -= getBandwidth() / 2; } if (isView) { setView(centerFreq + (freq - originalFreq), getBandwidth()); From cd129e0726927edcfcc8750f81253d852636861b Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 16 Aug 2015 16:43:19 -0400 Subject: [PATCH 12/14] fix keyboard control code --- src/visual/WaterfallCanvas.cpp | 79 +++++++++++++++------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 6bbd6d2..17566b2 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -269,8 +269,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); - long long freq; - long long originalFreq; + long long originalFreq = getCenterFrequency(); + long long freq = originalFreq; + switch (event.GetKeyCode()) { case 'A': case WXK_UP: @@ -284,59 +285,19 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { break; case WXK_RIGHT: case WXK_NUMPAD_RIGHT: - freq = getCenterFrequency(); - originalFreq = freq; if (shiftDown) { freq += getBandwidth() * 10; - if (isView) { - setView(centerFreq + (freq - originalFreq), getBandwidth()); - if (spectrumCanvas) { - spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); - } - } } else { freq += getBandwidth() / 2; - if (isView) { - setView(centerFreq + (freq - originalFreq), getBandwidth()); - if (spectrumCanvas) { - spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); - } - } } - wxGetApp().setFrequency(freq); - setStatusText("Set center frequency: %s", freq); break; case WXK_LEFT: case WXK_NUMPAD_LEFT: - freq = getCenterFrequency(); - originalFreq = freq; if (shiftDown) { - if ((freq - getBandwidth() * 10) < wxGetApp().getSampleRate() / 2) { - freq = wxGetApp().getSampleRate() / 2; - } else { - freq -= getBandwidth() * 10; - } - if (isView) { - setView(centerFreq + (freq - originalFreq), getBandwidth()); - if (spectrumCanvas) { - spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); - } - } + freq -= getBandwidth() * 10; } else { - if ((freq - getBandwidth() / 2) < wxGetApp().getSampleRate() / 2) { - freq = wxGetApp().getSampleRate() / 2; - } else { - freq -= getBandwidth() / 2; - } - if (isView) { - setView(centerFreq + (freq - originalFreq), getBandwidth()); - if (spectrumCanvas) { - spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); - } - } + freq -= getBandwidth() / 2; } - wxGetApp().setFrequency(freq); - setStatusText("Set center frequency: %s", freq); break; case 'D': case WXK_DELETE: @@ -363,6 +324,36 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { event.Skip(); return; } + + long long minFreq = wxGetApp().getSampleRate()/2; + if (freq < minFreq) { + freq = minFreq; + } + + if (freq != originalFreq) { + if (isView) { + setView(freq, getBandwidth()); + if (spectrumCanvas) { + spectrumCanvas->setView(freq, getBandwidth()); + } + + long long minFreq = wxGetApp().getFrequency()-(wxGetApp().getSampleRate()/2); + long long maxFreq = wxGetApp().getFrequency()+(wxGetApp().getSampleRate()/2); + + if (freq < minFreq) { + wxGetApp().setFrequency(freq+(wxGetApp().getSampleRate()/2)); + setStatusText("Set center frequency: %s", freq); + } + if (freq > maxFreq) { + wxGetApp().setFrequency(freq-(wxGetApp().getSampleRate()/2)); + setStatusText("Set center frequency: %s", freq); + } + } else { + wxGetApp().setFrequency(freq); + setStatusText("Set center frequency: %s", freq); + } + } + } void WaterfallCanvas::OnIdle(wxIdleEvent &event) { Refresh(); From d1ed603ff06b1f2aa2ef8406196a7f48b73a5a38 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 16 Aug 2015 18:12:12 -0400 Subject: [PATCH 13/14] Move demodulator and main spectrum visual processors to threads --- CMakeLists.txt | 2 ++ src/AppFrame.cpp | 28 ++++++++++---------- src/CubicSDR.cpp | 33 ++++++++++++++++++------ src/CubicSDR.h | 13 ++++++---- src/process/FFTVisualDataThread.cpp | 2 +- src/process/SpectrumVisualDataThread.cpp | 25 ++++++++++++++++++ src/process/SpectrumVisualDataThread.h | 16 ++++++++++++ 7 files changed, 91 insertions(+), 28 deletions(-) create mode 100644 src/process/SpectrumVisualDataThread.cpp create mode 100644 src/process/SpectrumVisualDataThread.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f7fa48b..9ddee92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,7 @@ SET (cubicsdr_sources src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp src/process/FFTVisualDataThread.cpp + src/process/SpectrumVisualDataThread.cpp src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp @@ -318,6 +319,7 @@ SET (cubicsdr_headers src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h src/process/FFTVisualDataThread.h + src/process/SpectrumVisualDataThread.h src/ui/GLPanel.h src/ui/UITestCanvas.cpp src/ui/UITestCanvas.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 8c05eeb..608400b 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -62,11 +62,11 @@ AppFrame::AppFrame() : demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band."); demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); - wxGetApp().getDemodSpectrumProcesor()->setup(1024); + wxGetApp().getDemodSpectrumProcessor()->setup(1024); demodSpectrumCanvas = new SpectrumCanvas(this, attribList); demodSpectrumCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000); demodVisuals->Add(demodSpectrumCanvas, 3, wxEXPAND | wxALL, 0); - wxGetApp().getDemodSpectrumProcesor()->attachOutput(demodSpectrumCanvas->getVisualDataQueue()); + wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodSpectrumCanvas->getVisualDataQueue()); demodVisuals->AddSpacer(1); @@ -76,7 +76,7 @@ AppFrame::AppFrame() : demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas); demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas); demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0); - wxGetApp().getDemodSpectrumProcesor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue()); + wxGetApp().getDemodSpectrumProcessor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue()); demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0); @@ -113,9 +113,9 @@ AppFrame::AppFrame() : vbox->AddSpacer(1); wxBoxSizer *spectrumSizer = new wxBoxSizer(wxHORIZONTAL); - wxGetApp().getSpectrumProcesor()->setup(2048); + wxGetApp().getSpectrumProcessor()->setup(2048); spectrumCanvas = new SpectrumCanvas(this, attribList); - wxGetApp().getSpectrumProcesor()->attachOutput(spectrumCanvas->getVisualDataQueue()); + wxGetApp().getSpectrumProcessor()->attachOutput(spectrumCanvas->getVisualDataQueue()); spectrumAvgMeter = new MeterCanvas(this, attribList); spectrumAvgMeter->setHelpTip("Spectrum averaging speed, click or drag to adjust."); @@ -370,7 +370,7 @@ AppFrame::AppFrame() : float spectrumAvg = wxGetApp().getConfig()->getSpectrumAvgSpeed(); spectrumAvgMeter->setLevel(spectrumAvg); - wxGetApp().getSpectrumProcesor()->setFFTAverageRate(spectrumAvg); + wxGetApp().getSpectrumProcessor()->setFFTAverageRate(spectrumAvg); int wflps =wxGetApp().getConfig()->getWaterfallLinesPerSec(); @@ -488,7 +488,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) { spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS); waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS)); - wxGetApp().getSpectrumProcesor()->setFFTAverageRate(0.65); + wxGetApp().getSpectrumProcessor()->setFFTAverageRate(0.65); spectrumAvgMeter->setLevel(0.65); demodModeSelector->Refresh(); demodTuner->Refresh(); @@ -607,12 +607,16 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } void AppFrame::OnClose(wxCloseEvent& event) { + wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodSpectrumCanvas->getVisualDataQueue()); + wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodWaterfallCanvas->getVisualDataQueue()); + wxGetApp().getSpectrumProcessor()->removeOutput(spectrumCanvas->getVisualDataQueue()); + wxGetApp().getConfig()->setWindow(this->GetPosition(), this->GetClientSize()); wxGetApp().getConfig()->setWindowMaximized(this->IsMaximized()); wxGetApp().getConfig()->setTheme(ThemeMgr::mgr.getTheme()); wxGetApp().getConfig()->setSnap(wxGetApp().getFrequencySnap()); wxGetApp().getConfig()->setCenterFreq(wxGetApp().getFrequency()); - wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcesor()->getFFTAverageRate()); + wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcessor()->getFFTAverageRate()); wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond()); wxGetApp().getConfig()->save(); event.Skip(); @@ -742,7 +746,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wxGetApp().getScopeProcessor()->run(); wxGetApp().getSpectrumDistributor()->run(); - SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcesor(); + SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor(); if (spectrumAvgMeter->inputChanged()) { float val = spectrumAvgMeter->getInputValue(); @@ -759,15 +763,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) { proc->setBandwidth(spectrumCanvas->getBandwidth()); proc->setCenterFrequency(spectrumCanvas->getCenterFrequency()); - proc->run(); - - SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcesor(); + SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcessor(); dproc->setView(demodWaterfallCanvas->getViewState()); dproc->setBandwidth(demodWaterfallCanvas->getBandwidth()); dproc->setCenterFrequency(demodWaterfallCanvas->getCenterFrequency()); - - dproc->run(); SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor(); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index f9bff43..769f9c5 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -21,7 +21,7 @@ IMPLEMENT_APP(CubicSDR) CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0), - sdrThread(NULL), sdrPostThread(NULL), pipeSDRCommand(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) { + sdrThread(NULL), sdrPostThread(NULL), spectrumVisualThread(NULL), demodVisualThread(NULL), pipeSDRCommand(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) { } @@ -51,6 +51,9 @@ bool CubicSDR::OnInit() { directSamplingMode = 0; // Visual Data + spectrumVisualThread = new SpectrumVisualDataThread(); + demodVisualThread = new SpectrumVisualDataThread(); + pipeIQVisualData = new DemodulatorThreadInputQueue(); pipeIQVisualData->set_max_num_items(1); @@ -68,8 +71,8 @@ bool CubicSDR::OnInit() { spectrumDistributor.attachOutput(pipeDemodIQVisualData); spectrumDistributor.attachOutput(pipeSpectrumIQVisualData); - demodSpectrumProcessor.setInput(pipeDemodIQVisualData); - spectrumProcessor.setInput(pipeSpectrumIQVisualData); + getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData); + getSpectrumProcessor()->setInput(pipeSpectrumIQVisualData); pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData->set_max_num_items(1); @@ -80,7 +83,7 @@ bool CubicSDR::OnInit() { pipeSDRIQData = new SDRThreadIQDataQueue(); pipeSDRCommand = new SDRThreadCommandQueue(); - pipeSDRIQData->set_max_num_items(1); + pipeSDRIQData->set_max_num_items(100); sdrThread = new SDRThread(); sdrThread->setInputQueue("SDRCommandQueue",pipeSDRCommand); @@ -134,6 +137,8 @@ bool CubicSDR::OnInit() { t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); + t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread); + t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread); appframe = new AppFrame(); if (dev != NULL) { @@ -167,6 +172,13 @@ int CubicSDR::OnExit() { std::cout << "Terminating SDR post-processing thread.." << std::endl; sdrPostThread->terminate(); t_PostSDR->join(); + + std::cout << "Terminating Visual Processor threads.." << std::endl; + spectrumVisualThread->terminate(); + t_SpectrumVisual->join(); + + demodVisualThread->terminate(); + t_DemodVisual->join(); delete sdrThread; delete t_SDR; @@ -174,6 +186,11 @@ int CubicSDR::OnExit() { delete sdrPostThread; delete t_PostSDR; + delete t_SpectrumVisual; + delete spectrumVisualThread; + delete t_DemodVisual; + delete demodVisualThread; + delete pipeSDRCommand; delete pipeIQVisualData; @@ -273,12 +290,12 @@ ScopeVisualProcessor *CubicSDR::getScopeProcessor() { return &scopeProcessor; } -SpectrumVisualProcessor *CubicSDR::getSpectrumProcesor() { - return &spectrumProcessor; +SpectrumVisualProcessor *CubicSDR::getSpectrumProcessor() { + return spectrumVisualThread->getProcessor(); } -SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcesor() { - return &demodSpectrumProcessor; +SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() { + return demodVisualThread->getProcessor(); } VisualDataDistributor *CubicSDR::getSpectrumDistributor() { diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 015b629..a1d4aec 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -20,6 +20,7 @@ #include "ScopeVisualProcessor.h" #include "SpectrumVisualProcessor.h" +#include "SpectrumVisualDataThread.h" #include @@ -57,8 +58,8 @@ public: int getDevice(); ScopeVisualProcessor *getScopeProcessor(); - SpectrumVisualProcessor *getSpectrumProcesor(); - SpectrumVisualProcessor *getDemodSpectrumProcesor(); + SpectrumVisualProcessor *getSpectrumProcessor(); + SpectrumVisualProcessor *getDemodSpectrumProcessor(); VisualDataDistributor *getSpectrumDistributor(); DemodulatorThreadOutputQueue* getAudioVisualQueue(); @@ -96,6 +97,8 @@ private: SDRThread *sdrThread; SDRPostThread *sdrPostThread; + SpectrumVisualDataThread *spectrumVisualThread; + SpectrumVisualDataThread *demodVisualThread; SDRThreadCommandQueue* pipeSDRCommand; SDRThreadIQDataQueue* pipeSDRIQData; @@ -106,13 +109,13 @@ private: DemodulatorThreadInputQueue* pipeWaterfallIQVisualData; ScopeVisualProcessor scopeProcessor; - SpectrumVisualProcessor spectrumProcessor; - SpectrumVisualProcessor demodSpectrumProcessor; VisualDataDistributor spectrumDistributor; - + std::thread *t_SDR; std::thread *t_PostSDR; + std::thread *t_SpectrumVisual; + std::thread *t_DemodVisual; }; static const wxCmdLineEntryDesc commandLineInfo [] = diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index f4eabfb..0e92dbb 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -59,6 +59,6 @@ void FFTVisualDataThread::run() { } } - std::cout << "FFT visual data thread terminated." << std::endl; + std::cout << "FFT visual data thread done." << std::endl; } diff --git a/src/process/SpectrumVisualDataThread.cpp b/src/process/SpectrumVisualDataThread.cpp new file mode 100644 index 0000000..cd737f4 --- /dev/null +++ b/src/process/SpectrumVisualDataThread.cpp @@ -0,0 +1,25 @@ +#include "SpectrumVisualDataThread.h" +#include "CubicSDR.h" + +SpectrumVisualDataThread::SpectrumVisualDataThread() { +} + +SpectrumVisualDataThread::~SpectrumVisualDataThread() { + +} + +SpectrumVisualProcessor *SpectrumVisualDataThread::getProcessor() { + return &sproc; +} + +void SpectrumVisualDataThread::run() { + std::cout << "Spectrum visual data thread started." << std::endl; + + while(!terminated) { + std::this_thread::sleep_for(std::chrono::milliseconds(12)); + sproc.run(); + } + + std::cout << "Spectrum visual data thread done." << std::endl; +} + diff --git a/src/process/SpectrumVisualDataThread.h b/src/process/SpectrumVisualDataThread.h new file mode 100644 index 0000000..017b519 --- /dev/null +++ b/src/process/SpectrumVisualDataThread.h @@ -0,0 +1,16 @@ +#pragma once + +#include "IOThread.h" +#include "SpectrumVisualProcessor.h" + +class SpectrumVisualDataThread : public IOThread { +public: + SpectrumVisualDataThread(); + ~SpectrumVisualDataThread(); + SpectrumVisualProcessor *getProcessor(); + + void run(); + +protected: + SpectrumVisualProcessor sproc; +}; From 5de181cf670287f6c5f48ea0eabe07d970994ef5 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 16 Aug 2015 19:47:49 -0400 Subject: [PATCH 14/14] keyboard waterfall zoom input tweaks --- src/AppFrame.cpp | 8 ++--- src/sdr/SDRPostThread.cpp | 4 +-- src/sdr/SDRThread.cpp | 2 +- src/visual/SpectrumCanvas.cpp | 8 ++++- src/visual/SpectrumCanvas.h | 1 + src/visual/WaterfallCanvas.cpp | 54 ++++++++++++++++++++++------------ 6 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 608400b..df7e79f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -759,9 +759,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { GetStatusBar()->SetStatusText(wxString::Format(wxT("Spectrum averaging speed changed to %0.2f%%."),val*100.0)); } - proc->setView(spectrumCanvas->getViewState()); - proc->setBandwidth(spectrumCanvas->getBandwidth()); - proc->setCenterFrequency(spectrumCanvas->getCenterFrequency()); + proc->setView(waterfallCanvas->getViewState()); + proc->setBandwidth(waterfallCanvas->getBandwidth()); + proc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcessor(); @@ -784,7 +784,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { waterfallCanvas->processInputQueue(); demodWaterfallCanvas->processInputQueue(); - + if (!this->IsActive()) { std::this_thread::sleep_for(std::chrono::milliseconds(25)); } diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index e4a9d2b..e19cc51 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -221,14 +221,14 @@ void SDRPostThread::run() { data_in->decRefCount(); } - buffers.purge(); +// buffers.purge(); if (iqVisualQueue && !iqVisualQueue->empty()) { DemodulatorThreadIQData *visualDataDummy; iqVisualQueue->pop(visualDataDummy); } - visualDataBuffers.purge(); +// visualDataBuffers.purge(); std::cout << "SDR post-processing thread done." << std::endl; } diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index a9a0d43..81f4cc0 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -295,7 +295,7 @@ void SDRThread::run() { } } - buffers.purge(); +// buffers.purge(); std::cout << "SDR thread done." << std::endl; } diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index f21a6a8..a35aca5 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -22,6 +22,7 @@ EVT_IDLE(SpectrumCanvas::OnIdle) EVT_MOTION(SpectrumCanvas::OnMouseMoved) EVT_LEFT_DOWN(SpectrumCanvas::OnMouseDown) EVT_LEFT_UP(SpectrumCanvas::OnMouseReleased) +EVT_ENTER_WINDOW(SpectrumCanvas::OnMouseEnterWindow) EVT_LEAVE_WINDOW(SpectrumCanvas::OnMouseLeftWindow) EVT_MOUSEWHEEL(SpectrumCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() @@ -152,6 +153,11 @@ void SpectrumCanvas::OnMouseReleased(wxMouseEvent& event) { SetCursor(wxCURSOR_SIZEWE); } +void SpectrumCanvas::OnMouseEnterWindow(wxMouseEvent& event) { + InteractiveCanvas::OnMouseEnterWindow(event); + SetCursor(wxCURSOR_SIZEWE); +} + void SpectrumCanvas::OnMouseLeftWindow(wxMouseEvent& event) { InteractiveCanvas::OnMouseLeftWindow(event); SetCursor(wxCURSOR_SIZEWE); @@ -163,4 +169,4 @@ void SpectrumCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) { SpectrumVisualDataQueue *SpectrumCanvas::getVisualDataQueue() { return &visualDataQueue; -} \ No newline at end of file +} diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index 6c891ae..af07f6c 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -30,6 +30,7 @@ private: void OnMouseDown(wxMouseEvent& event); void OnMouseWheelMoved(wxMouseEvent& event); void OnMouseReleased(wxMouseEvent& event); + void OnMouseEnterWindow(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event); PrimaryGLContext *glContext; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 17566b2..f2d2578 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -105,45 +105,49 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { long long bw; if (currentZoom != 1) { long long freq = wxGetApp().getFrequency(); - + bw = getBandwidth(); + + double mpos = 0; + float mouseInView = false; + + if (mouseTracker.mouseInView()) { + mpos = mouseTracker.getMouseX(); + mouseInView = true; + } else if (spectrumCanvas && spectrumCanvas->getMouseTracker()->mouseInView()) { + mpos = spectrumCanvas->getMouseTracker()->getMouseX(); + mouseInView = true; + } + if (currentZoom < 1) { - centerFreq = getCenterFrequency(); - bw = getBandwidth(); bw = (long long) ceil((long double) bw * currentZoom); if (bw < 30000) { bw = 30000; } - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + if (mouseInView) { + long long mfreqA = getFrequencyAt(mpos); setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + long long mfreqB = getFrequencyAt(mpos); centerFreq += mfreqA - mfreqB; } setView(centerFreq, bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } } else { if (isView) { - bw = getBandwidth(); bw = (long long) ceil((long double) bw * currentZoom); + if (bw >= wxGetApp().getSampleRate()) { disableView(); if (spectrumCanvas) { spectrumCanvas->disableView(); } } else { - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + if (mouseInView) { + long long mfreqA = getFrequencyAt(mpos); setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + long long mfreqB = getFrequencyAt(mpos); centerFreq += mfreqA - mfreqB; - } - - setView(getCenterFrequency(), bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); + } else { + setBandwidth(bw); } } } @@ -154,8 +158,15 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; } + + if (spectrumCanvas) { + if ((spectrumCanvas->getCenterFrequency() != centerFreq) || (spectrumCanvas->getBandwidth() != bw)) { + spectrumCanvas->setView(centerFreq,bw); + } + } } + glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); @@ -255,11 +266,13 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { case WXK_UP: case WXK_NUMPAD_UP: zoom = 1.0; + mouseZoom = 0.95; break; case 'Z': case WXK_DOWN: case WXK_NUMPAD_DOWN: zoom = 1.0; + mouseZoom = 1.05; break; } } @@ -276,11 +289,13 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { case 'A': case WXK_UP: case WXK_NUMPAD_UP: + mouseZoom = 1.0; zoom = 0.95; break; case 'Z': case WXK_DOWN: case WXK_NUMPAD_DOWN: + mouseZoom = 1.0; zoom = 1.05; break; case WXK_RIGHT: @@ -349,6 +364,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { setStatusText("Set center frequency: %s", freq); } } else { + if (spectrumCanvas) { + spectrumCanvas->setCenterFrequency(freq); + } wxGetApp().setFrequency(freq); setStatusText("Set center frequency: %s", freq); }