Can now control SDRThread freq. via thread task

Basic left/right keys bound for shifting frequency test.
This commit is contained in:
Charles J. Cliffe 2014-11-04 19:52:11 -05:00
parent 9896808b22
commit a8f1a87505
11 changed files with 145 additions and 85 deletions

View File

@ -79,6 +79,7 @@ SET (cubicsdr_sources
src/PrimaryGLContext.cpp src/PrimaryGLContext.cpp
src/AppFrame.cpp src/AppFrame.cpp
src/SDRThreadQueue.cpp src/SDRThreadQueue.cpp
src/SDRThreadTask.cpp
) )
SET (cubicsdr_headers SET (cubicsdr_headers
@ -89,6 +90,7 @@ SET (cubicsdr_headers
src/AppFrame.h src/AppFrame.h
src/CubicSDRDefs.h src/CubicSDRDefs.h
src/SDRThreadQueue.h src/SDRThreadQueue.h
src/SDRThreadTask.h
) )
#configure_files(${PROJECT_SOURCE_DIR}/shaders ${PROJECT_BINARY_DIR}/shaders COPYONLY) #configure_files(${PROJECT_SOURCE_DIR}/shaders ${PROJECT_BINARY_DIR}/shaders COPYONLY)
#configure_files(${PROJECT_SOURCE_DIR}/png ${PROJECT_BINARY_DIR}/png COPYONLY) #configure_files(${PROJECT_SOURCE_DIR}/png ${PROJECT_BINARY_DIR}/png COPYONLY)

View File

@ -21,7 +21,7 @@ EVT_IDLE(AppFrame::OnIdle)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
AppFrame::AppFrame() : AppFrame::AppFrame() :
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) { wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), frequency(DEFAULT_FREQ) {
canvas = new TestGLCanvas(this, NULL); canvas = new TestGLCanvas(this, NULL);
@ -116,3 +116,14 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
event.Skip(); 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;
}

View File

@ -11,6 +11,9 @@ public:
~AppFrame(); ~AppFrame();
void OnEventInput(wxThreadEvent& event); void OnEventInput(wxThreadEvent& event);
void setFrequency(unsigned int freq);
int getFrequency();
private: private:
void OnClose(wxCommandEvent& event); void OnClose(wxCommandEvent& event);
void OnNewWindow(wxCommandEvent& event); void OnNewWindow(wxCommandEvent& event);
@ -21,6 +24,7 @@ private:
IQBufferThread *t_IQBuffer; IQBufferThread *t_IQBuffer;
wxCriticalSection m_pThreadCS; wxCriticalSection m_pThreadCS;
SDRThreadQueue* m_pQueue; SDRThreadQueue* m_pQueue;
unsigned int frequency;
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();
}; };

View File

@ -4,3 +4,5 @@
#define SRATE 2500000 #define SRATE 2500000
#define FFT_SIZE 8192 #define FFT_SIZE 8192
#define DEFAULT_FREQ 105700000

View File

@ -12,6 +12,7 @@
#include "CubicSDR.h" #include "CubicSDR.h"
#include "CubicSDRDefs.h" #include "CubicSDRDefs.h"
#include "AppFrame.h"
#include <algorithm> #include <algorithm>
wxString glGetwxString(GLenum name) { wxString glGetwxString(GLenum name) {
@ -98,7 +99,7 @@ wxEND_EVENT_TABLE()
TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, 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 in_block_size = BUF_SIZE / 2;
int out_block_size = FFT_SIZE; 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[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); 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)) { void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
@ -127,10 +128,17 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
void TestGLCanvas::OnKeyDown(wxKeyEvent& event) { void TestGLCanvas::OnKeyDown(wxKeyEvent& event) {
float angle = 5.0; float angle = 5.0;
unsigned int freq;
switch (event.GetKeyCode()) { switch (event.GetKeyCode()) {
case WXK_RIGHT: case WXK_RIGHT:
freq = ((AppFrame*) parent)->getFrequency();
freq += 100000;
((AppFrame*) parent)->setFrequency(freq);
break; break;
case WXK_LEFT: case WXK_LEFT:
freq = ((AppFrame*) parent)->getFrequency();
freq -= 100000;
((AppFrame*) parent)->setFrequency(freq);
break; break;
case WXK_DOWN: case WXK_DOWN:
break; break;
@ -200,8 +208,8 @@ void TestGLCanvas::setData(std::vector<signed char> *data) {
} }
} }
fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma)*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; fft_ceil_maa = fft_ceil_maa + (fft_ceil - fft_ceil_maa) * 0.05;
for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) { for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) {
points[i * 2 + 1] = fft_result_maa[i] / fft_ceil_maa; points[i * 2 + 1] = fft_result_maa[i] / fft_ceil_maa;

View File

@ -7,8 +7,7 @@
#include "CubicSDRDefs.h" #include "CubicSDRDefs.h"
#include "fftw3.h" #include "fftw3.h"
class PrimaryGLContext : public wxGLContext class PrimaryGLContext: public wxGLContext {
{
public: public:
PrimaryGLContext(wxGLCanvas *canvas); PrimaryGLContext(wxGLCanvas *canvas);
@ -19,13 +18,19 @@ private:
GLuint m_textures[6]; GLuint m_textures[6];
}; };
class TestGLCanvas : public wxGLCanvas class TestGLCanvas: public wxGLCanvas {
{
public: public:
TestGLCanvas(wxWindow *parent, int *attribList = NULL); TestGLCanvas(wxWindow *parent, int *attribList = NULL);
void setData(std::vector<signed char> *data); void setData(std::vector<signed char> *data);
private:
void OnPaint(wxPaintEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnIdle(wxIdleEvent &event);
wxWindow *parent;
std::vector<float> points; std::vector<float> points;
fftw_complex *in, *out[2]; fftw_complex *in, *out[2];
@ -37,12 +42,5 @@ public:
std::vector<float> fft_result_ma; std::vector<float> fft_result_ma;
std::vector<float> fft_result_maa; std::vector<float> fft_result_maa;
wxDECLARE_EVENT_TABLE();
private:
void OnPaint(wxPaintEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnIdle(wxIdleEvent &event);
wxDECLARE_EVENT_TABLE();
}; };

View File

@ -95,7 +95,7 @@ wxThread::ExitCode SDRThread::Entry() {
rtlsdr_open(&dev, use_my_dev); rtlsdr_open(&dev, use_my_dev);
rtlsdr_set_sample_rate(dev, SRATE); 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_agc_mode(dev, 1);
rtlsdr_set_offset_tuning(dev, 1); rtlsdr_set_offset_tuning(dev, 1);
rtlsdr_reset_buffer(dev); rtlsdr_reset_buffer(dev);
@ -110,33 +110,27 @@ wxThread::ExitCode SDRThread::Entry() {
std::cout << "Sampling.."; std::cout << "Sampling..";
while (!TestDestroy()) { while (!TestDestroy()) {
if (m_pQueue->Stacksize()) { if (m_pQueue->stackSize()) {
while (m_pQueue->Stacksize()) { bool freq_changed = false;
SDRThreadTask task = m_pQueue->Pop(); // pop a task from the queue. this will block the worker thread if queue is empty 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) { switch (task.m_cmd) {
// case SDRThreadTask::SDR_THREAD_EXIT: // thread should exit case SDRThreadTask::SDR_THREAD_TUNING:
// Sleep(1000); // wait a while std::cout << "Set frequency: " << task.getUInt() << std::endl;
// throw SDRThreadTask::SDR_THREAD_EXIT; // confirm exit command freq_changed = true;
// case SDRThreadTask::SDR_THREAD_TASK: // process a standard task new_freq = task.getUInt();
// Sleep(2000); break;
// 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
} }
} }
if (freq_changed) {
rtlsdr_set_center_freq(dev, new_freq);
}
} }
rtlsdr_read_sync(dev, buf, BUF_SIZE, &n_read); 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()) { if (!TestDestroy()) {
std::vector<signed char> *new_buffer = new std::vector<signed char>(); std::vector<signed char> *new_buffer = new std::vector<signed char>();

View File

@ -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;
}

View File

@ -1,59 +1,24 @@
#pragma once #pragma once
#include <map> #include <map>
#include "SDRThreadTask.h"
class SDRThreadTask { #include "wx/event.h"
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;
};
class SDRThreadQueue { class SDRThreadQueue {
public: public:
enum SDR_PRIORITY { enum SDR_PRIORITY {
SDR_PRIORITY_HIGHEST, SDR_PRIORITY_HIGHER, SDR_PRIORITY_NORMAL, SDR_PRIORITY_BELOW_NORMAL, SDR_PRIORITY_LOW, SDR_PRIORITY_IDLE SDR_PRIORITY_HIGHEST, SDR_PRIORITY_HIGHER, SDR_PRIORITY_NORMAL, SDR_PRIORITY_BELOW_NORMAL, SDR_PRIORITY_LOW, SDR_PRIORITY_IDLE
}; };
SDRThreadQueue(wxEvtHandler* pParent) : 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();
}
wxEvtHandler* getHandler() { void addTask(const SDRThreadTask& task, const SDR_PRIORITY& priority = SDR_PRIORITY_NORMAL);
return m_pParent; void report(const SDRThreadTask::SDR_COMMAND& cmd, const wxString& sArg = wxEmptyString, int iArg = 0);
}
SDRThreadTask pop();
size_t stackSize();
wxEvtHandler* getHandler();
private: private:
wxEvtHandler* m_pParent; wxEvtHandler* m_pParent;

9
src/SDRThreadTask.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "SDRThreadTask.h"
void SDRThreadTask::setUInt(unsigned int i) {
arg_int = i;
}
unsigned int SDRThreadTask::getUInt() {
return arg_int;
}

24
src/SDRThreadTask.h Normal file
View File

@ -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;
};