diff --git a/CMakeLists.txt b/CMakeLists.txt index e7e1d17..89164eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ SET (cubicsdr_sources src/PrimaryGLContext.cpp src/AppFrame.cpp src/SDRThreadQueue.cpp + src/SDRThreadTask.cpp ) SET (cubicsdr_headers @@ -89,6 +90,7 @@ SET (cubicsdr_headers src/AppFrame.h src/CubicSDRDefs.h src/SDRThreadQueue.h + src/SDRThreadTask.h ) #configure_files(${PROJECT_SOURCE_DIR}/shaders ${PROJECT_BINARY_DIR}/shaders COPYONLY) #configure_files(${PROJECT_SOURCE_DIR}/png ${PROJECT_BINARY_DIR}/png COPYONLY) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 52724a1..eb1046f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -21,7 +21,7 @@ EVT_IDLE(AppFrame::OnIdle) wxEND_EVENT_TABLE() AppFrame::AppFrame() : - wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) { + wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), frequency(DEFAULT_FREQ) { canvas = new TestGLCanvas(this, NULL); @@ -57,7 +57,7 @@ AppFrame::AppFrame() : // wxLogError // ("Can't create the thread!"); // delete t_IQBuffer; - t_IQBuffer = NULL; + t_IQBuffer = NULL; // } // static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 }; @@ -116,3 +116,14 @@ void AppFrame::OnIdle(wxIdleEvent& event) { event.Skip(); } + +void AppFrame::setFrequency(unsigned int freq) { + frequency = freq; + SDRThreadTask task = SDRThreadTask(SDRThreadTask::SDR_THREAD_TUNING); + task.setUInt(freq); + m_pQueue->addTask(task, SDRThreadQueue::SDR_PRIORITY_HIGHEST); +} + +int AppFrame::getFrequency() { + return frequency; +} diff --git a/src/AppFrame.h b/src/AppFrame.h index 928b313..50cfe8b 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -11,6 +11,9 @@ public: ~AppFrame(); void OnEventInput(wxThreadEvent& event); + void setFrequency(unsigned int freq); + int getFrequency(); + private: void OnClose(wxCommandEvent& event); void OnNewWindow(wxCommandEvent& event); @@ -21,6 +24,7 @@ private: IQBufferThread *t_IQBuffer; wxCriticalSection m_pThreadCS; SDRThreadQueue* m_pQueue; + unsigned int frequency; wxDECLARE_EVENT_TABLE(); }; diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index 57e90cc..94a2a04 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -4,3 +4,5 @@ #define SRATE 2500000 #define FFT_SIZE 8192 +#define DEFAULT_FREQ 105700000 + diff --git a/src/PrimaryGLContext.cpp b/src/PrimaryGLContext.cpp index 59b8c28..fde55e7 100644 --- a/src/PrimaryGLContext.cpp +++ b/src/PrimaryGLContext.cpp @@ -12,6 +12,7 @@ #include "CubicSDR.h" #include "CubicSDRDefs.h" +#include "AppFrame.h" #include wxString glGetwxString(GLenum name) { @@ -98,7 +99,7 @@ wxEND_EVENT_TABLE() TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, - wxFULL_REPAINT_ON_RESIZE) { + wxFULL_REPAINT_ON_RESIZE), parent(parent) { int in_block_size = BUF_SIZE / 2; int out_block_size = FFT_SIZE; @@ -109,7 +110,7 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : plan[0] = fftw_plan_dft_1d(out_block_size, in, out[0], FFTW_BACKWARD, FFTW_MEASURE); plan[1] = fftw_plan_dft_1d(out_block_size, in, out[1], FFTW_FORWARD, FFTW_MEASURE); - fft_ceil_ma=fft_ceil_maa=1.0; + fft_ceil_ma = fft_ceil_maa = 1.0; } void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { @@ -127,10 +128,17 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { void TestGLCanvas::OnKeyDown(wxKeyEvent& event) { float angle = 5.0; + unsigned int freq; switch (event.GetKeyCode()) { case WXK_RIGHT: + freq = ((AppFrame*) parent)->getFrequency(); + freq += 100000; + ((AppFrame*) parent)->setFrequency(freq); break; case WXK_LEFT: + freq = ((AppFrame*) parent)->getFrequency(); + freq -= 100000; + ((AppFrame*) parent)->setFrequency(freq); break; case WXK_DOWN: break; @@ -200,8 +208,8 @@ void TestGLCanvas::setData(std::vector *data) { } } - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma)*0.05; - fft_ceil_maa = fft_ceil_maa + (fft_ceil - fft_ceil_maa)*0.05; + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; + fft_ceil_maa = fft_ceil_maa + (fft_ceil - fft_ceil_maa) * 0.05; for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) { points[i * 2 + 1] = fft_result_maa[i] / fft_ceil_maa; diff --git a/src/PrimaryGLContext.h b/src/PrimaryGLContext.h index d87957e..e9c973a 100644 --- a/src/PrimaryGLContext.h +++ b/src/PrimaryGLContext.h @@ -7,8 +7,7 @@ #include "CubicSDRDefs.h" #include "fftw3.h" -class PrimaryGLContext : public wxGLContext -{ +class PrimaryGLContext: public wxGLContext { public: PrimaryGLContext(wxGLCanvas *canvas); @@ -19,13 +18,19 @@ private: GLuint m_textures[6]; }; -class TestGLCanvas : public wxGLCanvas -{ +class TestGLCanvas: public wxGLCanvas { public: TestGLCanvas(wxWindow *parent, int *attribList = NULL); void setData(std::vector *data); +private: + void OnPaint(wxPaintEvent& event); + void OnKeyDown(wxKeyEvent& event); + + void OnIdle(wxIdleEvent &event); + + wxWindow *parent; std::vector points; fftw_complex *in, *out[2]; @@ -36,13 +41,6 @@ public: std::vector fft_result; std::vector fft_result_ma; std::vector fft_result_maa; - -private: - void OnPaint(wxPaintEvent& event); - void OnKeyDown(wxKeyEvent& event); - - void OnIdle(wxIdleEvent &event); - - wxDECLARE_EVENT_TABLE(); +wxDECLARE_EVENT_TABLE(); }; diff --git a/src/SDRThread.cpp b/src/SDRThread.cpp index 0b44b54..9be5591 100644 --- a/src/SDRThread.cpp +++ b/src/SDRThread.cpp @@ -95,7 +95,7 @@ wxThread::ExitCode SDRThread::Entry() { rtlsdr_open(&dev, use_my_dev); rtlsdr_set_sample_rate(dev, SRATE); - rtlsdr_set_center_freq(dev, 105700000); + rtlsdr_set_center_freq(dev, DEFAULT_FREQ); rtlsdr_set_agc_mode(dev, 1); rtlsdr_set_offset_tuning(dev, 1); rtlsdr_reset_buffer(dev); @@ -110,33 +110,27 @@ wxThread::ExitCode SDRThread::Entry() { std::cout << "Sampling.."; while (!TestDestroy()) { - if (m_pQueue->Stacksize()) { - while (m_pQueue->Stacksize()) { - SDRThreadTask task = m_pQueue->Pop(); // pop a task from the queue. this will block the worker thread if queue is empty + if (m_pQueue->stackSize()) { + bool freq_changed = false; + float new_freq; + + while (m_pQueue->stackSize()) { + SDRThreadTask task = m_pQueue->pop(); // pop a task from the queue. this will block the worker thread if queue is empty switch (task.m_cmd) { -// case SDRThreadTask::SDR_THREAD_EXIT: // thread should exit -// Sleep(1000); // wait a while -// throw SDRThreadTask::SDR_THREAD_EXIT; // confirm exit command -// case SDRThreadTask::SDR_THREAD_TASK: // process a standard task -// Sleep(2000); -// m_pQueue->Report(SDRThreadTask::SDR_THREAD_TASK, wxString::Format(wxT("Task #%s done."), task.m_Arg.c_str()), m_ID); // report successful completion -// break; -// case SDRThreadTask::SDR_THREAD_JOBERR: // process a task that terminates with an error -// m_pQueue->Report(SDRThreadTask::SDR_THREAD_TASK, wxString::Format(wxT("Task #%s errorneous."), task.m_Arg.c_str()), m_ID); -// Sleep(1000); -// throw SDRThreadTask::SDR_THREAD_EXIT; // report exit of worker thread -// break; -// case SDRThreadTask::SDR_THREAD_NULL: // dummy command -// default: break; // default + case SDRThreadTask::SDR_THREAD_TUNING: + std::cout << "Set frequency: " << task.getUInt() << std::endl; + freq_changed = true; + new_freq = task.getUInt(); + break; } } + + if (freq_changed) { + rtlsdr_set_center_freq(dev, new_freq); + } } rtlsdr_read_sync(dev, buf, BUF_SIZE, &n_read); - // move around - // long freq = 98000000+(20000000)*sin(seconds/50.0); - // rtlsdr_set_center_freq(dev, freq); - // std::cout << "Frequency: " << freq << std::endl; if (!TestDestroy()) { std::vector *new_buffer = new std::vector(); diff --git a/src/SDRThreadQueue.cpp b/src/SDRThreadQueue.cpp index e69de29..6f75c42 100644 --- a/src/SDRThreadQueue.cpp +++ b/src/SDRThreadQueue.cpp @@ -0,0 +1,43 @@ +#include "SDRThreadQueue.h" + +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +SDRThreadQueue::SDRThreadQueue(wxEvtHandler* pParent) : + m_pParent(pParent) { +} + +void SDRThreadQueue::addTask(const SDRThreadTask& task, const SDR_PRIORITY& priority) { + wxMutexLocker lock(m_MutexQueue); + m_Tasks.insert(std::make_pair(priority, task)); + m_QueueCount.Post(); +} + +SDRThreadTask SDRThreadQueue::pop() { + SDRThreadTask element; + m_QueueCount.Wait(); + m_MutexQueue.Lock(); + element = (m_Tasks.begin())->second; + m_Tasks.erase(m_Tasks.begin()); + m_MutexQueue.Unlock(); + return element; +} + +void SDRThreadQueue::report(const SDRThreadTask::SDR_COMMAND& cmd, const wxString& sArg, int iArg) { + wxCommandEvent evt(wxEVT_THREAD, cmd); + evt.SetString(sArg); + evt.SetInt(iArg); + m_pParent->AddPendingEvent(evt); +} + +size_t SDRThreadQueue::stackSize() { + wxMutexLocker lock(m_MutexQueue); + return m_Tasks.size(); +} + +wxEvtHandler* SDRThreadQueue::getHandler() { + return m_pParent; +} diff --git a/src/SDRThreadQueue.h b/src/SDRThreadQueue.h index 7f7e09a..dc9cc3e 100644 --- a/src/SDRThreadQueue.h +++ b/src/SDRThreadQueue.h @@ -1,59 +1,24 @@ #pragma once #include +#include "SDRThreadTask.h" -class SDRThreadTask { -public: - enum SDR_COMMAND { - SDR_THREAD_EXIT = wxID_EXIT, SDR_THREAD_NULL = wxID_HIGHEST + 1, SDR_THREAD_STARTED, SDR_THREAD_PROCESS, SDR_THREAD_ERROR, - }; - - SDRThreadTask() : - m_cmd(SDR_THREAD_NULL) { - } - SDRThreadTask(SDR_COMMAND cmd, const wxString& arg) : - m_cmd(cmd), m_Arg(arg) { - } - SDR_COMMAND m_cmd; - wxString m_Arg; -}; +#include "wx/event.h" class SDRThreadQueue { public: enum SDR_PRIORITY { SDR_PRIORITY_HIGHEST, SDR_PRIORITY_HIGHER, SDR_PRIORITY_NORMAL, SDR_PRIORITY_BELOW_NORMAL, SDR_PRIORITY_LOW, SDR_PRIORITY_IDLE }; - SDRThreadQueue(wxEvtHandler* pParent) : - m_pParent(pParent) { - } - void AddTask(const SDRThreadTask& task, const SDR_PRIORITY& priority = SDR_PRIORITY_NORMAL) { - wxMutexLocker lock(m_MutexQueue); - m_Tasks.insert(std::make_pair(priority, task)); - m_QueueCount.Post(); - } - SDRThreadTask Pop() { - SDRThreadTask element; - m_QueueCount.Wait(); - m_MutexQueue.Lock(); - element = (m_Tasks.begin())->second; - m_Tasks.erase(m_Tasks.begin()); - m_MutexQueue.Unlock(); - return element; - } - void Report(const SDRThreadTask::SDR_COMMAND& cmd, const wxString& sArg = wxEmptyString, int iArg = 0) { - wxCommandEvent evt(wxEVT_THREAD, cmd); - evt.SetString(sArg); - evt.SetInt(iArg); - m_pParent->AddPendingEvent(evt); - } - size_t Stacksize() { - wxMutexLocker lock(m_MutexQueue); - return m_Tasks.size(); - } + SDRThreadQueue(wxEvtHandler* pParent); - wxEvtHandler* getHandler() { - return m_pParent; - } + void addTask(const SDRThreadTask& task, const SDR_PRIORITY& priority = SDR_PRIORITY_NORMAL); + void report(const SDRThreadTask::SDR_COMMAND& cmd, const wxString& sArg = wxEmptyString, int iArg = 0); + + SDRThreadTask pop(); + size_t stackSize(); + + wxEvtHandler* getHandler(); private: wxEvtHandler* m_pParent; diff --git a/src/SDRThreadTask.cpp b/src/SDRThreadTask.cpp new file mode 100644 index 0000000..f0de701 --- /dev/null +++ b/src/SDRThreadTask.cpp @@ -0,0 +1,9 @@ +#include "SDRThreadTask.h" + +void SDRThreadTask::setUInt(unsigned int i) { + arg_int = i; +} + +unsigned int SDRThreadTask::getUInt() { + return arg_int; +} diff --git a/src/SDRThreadTask.h b/src/SDRThreadTask.h new file mode 100644 index 0000000..93336c1 --- /dev/null +++ b/src/SDRThreadTask.h @@ -0,0 +1,24 @@ +#pragma once + +#include "wx/defs.h" +#include "wx/string.h" + +class SDRThreadTask { +public: + enum SDR_COMMAND { + SDR_THREAD_EXIT = wxID_EXIT, SDR_THREAD_NULL = wxID_HIGHEST + 1, SDR_THREAD_STARTED, SDR_THREAD_PROCESS, SDR_THREAD_ERROR, SDR_THREAD_TUNING + }; + + SDRThreadTask() : + m_cmd(SDR_THREAD_NULL) { + } + SDRThreadTask(SDR_COMMAND cmd) : + m_cmd(cmd) { + } + + void setUInt(unsigned int i); + unsigned int getUInt(); + + SDR_COMMAND m_cmd; + unsigned int arg_int; +};