mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2026-06-02 06:04:39 -04:00
Now plotting IQ spectrum
seems to only be showing half the bandwidth..
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define BUF_SIZE (16 * 32 * 512)
|
||||
#define SRATE 2500000
|
||||
#define FFT_SIZE BUF_SIZE/2
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE (16 * 32 * 512)
|
||||
#include "CubicSDRDefs.h"
|
||||
|
||||
IQBufferThread::IQBufferThread(wxApp *app) :
|
||||
wxThread(wxTHREAD_DETACHED) {
|
||||
|
||||
+58
-12
@@ -11,6 +11,8 @@
|
||||
#endif
|
||||
|
||||
#include "CubicSDR.h"
|
||||
#include "CubicSDRDefs.h"
|
||||
#include <algorithm>
|
||||
|
||||
wxString glGetwxString(GLenum name) {
|
||||
const GLubyte *v = glGetString(name);
|
||||
@@ -68,7 +70,7 @@ void PrimaryGLContext::PlotIQ(std::vector<float> &i_points, std::vector<float> &
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0f, 0.5f, 0.0f);
|
||||
if (q_points.size()) {
|
||||
glScalef(10.0f, 1.0f, 1.0f);
|
||||
// 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);
|
||||
@@ -85,7 +87,7 @@ void PrimaryGLContext::PlotIQ(std::vector<float> &i_points, std::vector<float> &
|
||||
glPushMatrix();
|
||||
glTranslatef(0.0f, -0.5f, 0.0f);
|
||||
if (i_points.size()) {
|
||||
glScalef(10.0f, 1.0f, 1.0f);
|
||||
// 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);
|
||||
@@ -113,6 +115,13 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
|
||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE) {
|
||||
|
||||
int in_block_size = BUF_SIZE/2;
|
||||
int out_block_size = FFT_SIZE;
|
||||
|
||||
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * in_block_size);
|
||||
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * out_block_size);
|
||||
plan = fftw_plan_dft_1d(out_block_size, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
|
||||
}
|
||||
|
||||
void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
@@ -148,23 +157,60 @@ 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());
|
||||
|
||||
if (i_points.size() < FFT_SIZE*2) {
|
||||
i_points.resize(FFT_SIZE*2);
|
||||
}
|
||||
|
||||
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;
|
||||
for (int i = 0; i < BUF_SIZE / 2; i++) {
|
||||
in[i][0] = (float) (*data)[i * 2] / 127.0f;
|
||||
in[i][1] = (float) (*data)[i * 2 + 1] / 127.0f;
|
||||
}
|
||||
|
||||
// for (int i = 0; i < BUF_SIZE / 2; i++) {
|
||||
// double ang = (M_PI / (float) BUF_SIZE) * (float) i;
|
||||
// double w = 0.5 * (1.0 - cos(ang));
|
||||
//
|
||||
// in[i][0] *= w;
|
||||
// in[i][1] *= w;
|
||||
// }
|
||||
|
||||
fftw_execute(plan);
|
||||
|
||||
float result[FFT_SIZE];
|
||||
float fft_floor, fft_ceil;
|
||||
|
||||
for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) {
|
||||
double a = out[i][0];
|
||||
double b = out[i][1];
|
||||
|
||||
double c = sqrt(a*a+b*b);
|
||||
if (i==1) {
|
||||
fft_floor=fft_ceil=c;
|
||||
} else {
|
||||
if (c<fft_floor) {
|
||||
fft_floor = c;
|
||||
}
|
||||
if (c>fft_ceil) {
|
||||
fft_ceil = c;
|
||||
}
|
||||
}
|
||||
|
||||
result[i] = c;
|
||||
}
|
||||
|
||||
for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) {
|
||||
i_points[i * 2 + 1] = (result[i]-fft_floor)/(fft_ceil-fft_floor);
|
||||
i_points[i * 2] = 2.0f * ((float) i / (float) iMax) - 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TestGLCanvas::OnIdle(wxIdleEvent &event) {
|
||||
Refresh(false);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "wx/timer.h"
|
||||
|
||||
#include <vector>
|
||||
#include "CubicSDRDefs.h"
|
||||
#include "fftw3.h"
|
||||
|
||||
class PrimaryGLContext : public wxGLContext
|
||||
{
|
||||
@@ -27,6 +29,9 @@ public:
|
||||
std::vector<float> i_points;
|
||||
std::vector<float> q_points;
|
||||
|
||||
fftw_complex *in, *out;
|
||||
fftw_plan plan;
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
||||
+20
-7
@@ -1,7 +1,7 @@
|
||||
#include "SDRThread.h"
|
||||
#include "CubicSDRDefs.h"
|
||||
#include <vector>
|
||||
|
||||
#define BUF_SIZE (16 * 32 * 512)
|
||||
|
||||
//wxDEFINE_EVENT(wxEVT_COMMAND_SDRThread_INPUT, wxThreadEvent);
|
||||
|
||||
@@ -87,14 +87,19 @@ wxThread::ExitCode SDRThread::Entry() {
|
||||
|
||||
enumerate_rtl();
|
||||
|
||||
rtlsdr_open(&dev, 0);
|
||||
rtlsdr_set_sample_rate(dev, 2500000);
|
||||
rtlsdr_set_center_freq(dev, 105700000);
|
||||
rtlsdr_open(&dev, 3);
|
||||
rtlsdr_set_sample_rate(dev, SRATE);
|
||||
rtlsdr_set_center_freq(dev, 105700000-(SRATE/2));
|
||||
rtlsdr_set_agc_mode(dev, 1);
|
||||
rtlsdr_set_offset_tuning(dev, 1);
|
||||
rtlsdr_reset_buffer(dev);
|
||||
|
||||
sample_rate = rtlsdr_get_sample_rate(dev);
|
||||
|
||||
std::cout << "Sample Rate is: " << sample_rate << std::endl;
|
||||
|
||||
int n_read;
|
||||
double seconds = 0.0;
|
||||
|
||||
std::cout << "Sampling..";
|
||||
while (!TestDestroy()) {
|
||||
@@ -107,9 +112,17 @@ wxThread::ExitCode SDRThread::Entry() {
|
||||
new_buffer->push_back(buf[i] - 127);
|
||||
}
|
||||
|
||||
wxThreadEvent event(wxEVT_THREAD, EVENT_SDR_INPUT);
|
||||
event.SetPayload(new_buffer);
|
||||
wxQueueEvent(frame, event.Clone());
|
||||
double time_slice = (double)n_read/(double)sample_rate;
|
||||
seconds += time_slice;
|
||||
|
||||
std::cout << "Time Slice: " << time_slice << std::endl;
|
||||
if (!TestDestroy()) {
|
||||
wxThreadEvent event(wxEVT_THREAD, EVENT_SDR_INPUT);
|
||||
event.SetPayload(new_buffer);
|
||||
wxQueueEvent(frame, event.Clone());
|
||||
} else {
|
||||
delete new_buffer;
|
||||
}
|
||||
}
|
||||
this->Sleep(1);
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ public:
|
||||
protected:
|
||||
virtual ExitCode Entry();
|
||||
AppFrame *frame;
|
||||
uint32_t sample_rate;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user