Rendering rtl-sdr I/Q data to the GL canvas

This commit is contained in:
Charles J. Cliffe 2014-10-28 22:59:17 -04:00
parent 23f8c6a197
commit 2ef8010438
7 changed files with 85 additions and 28 deletions

View File

@ -23,7 +23,7 @@ wxEND_EVENT_TABLE()
AppFrame::AppFrame() :
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
new TestGLCanvas(this, NULL);
canvas = new TestGLCanvas(this, NULL);
// SetIcon(wxICON(sample));
@ -57,9 +57,11 @@ void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
}
void AppFrame::OnEventInput(wxThreadEvent& event) {
std::vector<unsigned char> *new_buffer = event.GetPayload<std::vector<unsigned char> *>();
std::vector<signed char> *new_buffer = event.GetPayload<std::vector<signed char> *>();
std::cout << "Got IQ buffer, length: " << new_buffer->size() << std::endl;
// std::cout << "Got IQ buffer, length: " << new_buffer->size() << std::endl;
canvas->setData(new_buffer);
delete new_buffer;
}

View File

@ -14,5 +14,7 @@ private:
void OnNewWindow(wxCommandEvent& event);
void OnIdle(wxIdleEvent& event);
TestGLCanvas *canvas;
wxDECLARE_EVENT_TABLE();
};

View File

@ -1,7 +1,6 @@
#include "IQBufferThread.h"
#include <cstring>
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
@ -12,8 +11,6 @@
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
#endif
#define BUF_SIZE (16 * 32 * 512)
IQBufferThread::IQBufferThread(wxApp *app) :
@ -24,7 +21,7 @@ IQBufferThread::~IQBufferThread() {
}
wxThread::ExitCode IQBufferThread::Entry() {
unsigned char *buf = (unsigned char*) malloc(BUF_SIZE);
signed char *buf = (signed char*) malloc(BUF_SIZE);
int n_read;
int i = 0;
@ -40,7 +37,7 @@ wxThread::ExitCode IQBufferThread::Entry() {
// iq_buffer.pop();
// delete old_buffer;
// }
std::cout << "#";
// std::cout << "#";
// }
this->Sleep(100);
}

View File

@ -10,19 +10,17 @@
#include "SDRThread.h"
#include <queue>
class IQBufferThread: public wxThread {
public:
IQBufferThread(wxApp *app);
~IQBufferThread();
void OnEventInput(wxEvent& event)
{
void OnEventInput(wxEvent& event) {
std::cout << "event !" << std::endl;
}
protected:
virtual ExitCode Entry();
wxApp *handler;
std::queue<std::vector<unsigned char> *> iq_buffer;
std::queue<std::vector<signed char> *> iq_buffer;
};

View File

@ -59,23 +59,45 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas) :
CheckGLError();
}
void PrimaryGLContext::PlotIQ() {
void PrimaryGLContext::PlotIQ(std::vector<float> &i_points, std::vector<float> &q_points) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.0f, 0.5f, 0.0f);
if (q_points.size()) {
glScalef(10.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &q_points[0]);
glDrawArrays(GL_LINE_STRIP, 0, q_points.size() / 2);
glDisableClientState(GL_VERTEX_ARRAY);
} else {
glBegin(GL_LINE_STRIP);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -0.5f, 0.0f);
glVertex3f(1.0f, -0.5f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glEnd();
}
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f, -0.5f, 0.0f);
if (i_points.size()) {
glScalef(10.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &i_points[0]);
glDrawArrays(GL_LINE_STRIP, 0, i_points.size() / 2);
glDisableClientState(GL_VERTEX_ARRAY);
} else {
glBegin(GL_LINE_STRIP);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 0.5f, 0.0f);
glVertex3f(1.0f, 0.5f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glEnd();
}
glPopMatrix();
glFlush();
@ -84,6 +106,7 @@ void PrimaryGLContext::PlotIQ() {
wxBEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) EVT_PAINT(TestGLCanvas::OnPaint)
EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
EVT_IDLE(TestGLCanvas::OnIdle)
wxEND_EVENT_TABLE()
TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
@ -99,7 +122,7 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
PrimaryGLContext& canvas = wxGetApp().GetContext(this);
glViewport(0, 0, ClientSize.x, ClientSize.y);
canvas.PlotIQ();
canvas.PlotIQ(i_points, q_points);
SwapBuffers();
}
@ -124,3 +147,24 @@ void TestGLCanvas::OnKeyDown(wxKeyEvent& event) {
}
}
void TestGLCanvas::setData(std::vector<signed char> *data) {
if (data && data->size()) {
if (i_points.size() < data->size()) {
i_points.resize(data->size());
}
if (q_points.size() < data->size()) {
q_points.resize(data->size());
}
for (int i = 0, iMax = data->size() / 2; i < iMax; i++) {
i_points[i * 2 + 1] = (float) (*data)[i * 2] / 127.0f;
q_points[i * 2 + 1] = (float) (*data)[i * 2 + 1] / 127.0f;
i_points[i * 2] = q_points[i * 2] = 2.0f * ((float) i / (float) iMax) - 1.0f;
}
}
}
void TestGLCanvas::OnIdle(wxIdleEvent &event) {
Refresh(false);
}
;

View File

@ -3,12 +3,14 @@
#include "wx/glcanvas.h"
#include "wx/timer.h"
#include <vector>
class PrimaryGLContext : public wxGLContext
{
public:
PrimaryGLContext(wxGLCanvas *canvas);
void PlotIQ();
void PlotIQ(std::vector<float> &i_points, std::vector<float> &q_points);
private:
// textures for the cube faces
@ -20,9 +22,16 @@ class TestGLCanvas : public wxGLCanvas
public:
TestGLCanvas(wxWindow *parent, int *attribList = NULL);
void setData(std::vector<signed char> *data);
std::vector<float> i_points;
std::vector<float> q_points;
private:
void OnPaint(wxPaintEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnIdle(wxIdleEvent &event);
wxDECLARE_EVENT_TABLE();
};

View File

@ -3,7 +3,6 @@
#define BUF_SIZE (16 * 32 * 512)
//wxDEFINE_EVENT(wxEVT_COMMAND_SDRThread_INPUT, wxThreadEvent);
SDRThread::SDRThread(AppFrame *frame) :
@ -91,6 +90,8 @@ wxThread::ExitCode SDRThread::Entry() {
rtlsdr_open(&dev, 0);
rtlsdr_set_sample_rate(dev, 2500000);
rtlsdr_set_center_freq(dev, 105700000);
rtlsdr_set_agc_mode(dev, 1);
rtlsdr_set_offset_tuning(dev, 1);
rtlsdr_reset_buffer(dev);
int n_read;
@ -100,7 +101,11 @@ wxThread::ExitCode SDRThread::Entry() {
rtlsdr_read_sync(dev, buf, BUF_SIZE, &n_read);
if (!TestDestroy()) {
std::vector<unsigned char> *new_buffer = new std::vector<unsigned char>(buf, buf + n_read);
std::vector<signed char> *new_buffer = new std::vector<signed char>();
for (int i = 0; i < n_read; i++) {
new_buffer->push_back(buf[i] - 127);
}
wxThreadEvent event(wxEVT_THREAD, EVENT_SDR_INPUT);
event.SetPayload(new_buffer);