Demodulator now has it's own spectrum view
This commit is contained in:
parent
d642cc63fd
commit
4403824e3b
|
@ -28,13 +28,14 @@ EVT_IDLE(AppFrame::OnIdle)
|
|||
wxEND_EVENT_TABLE()
|
||||
|
||||
AppFrame::AppFrame() :
|
||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
||||
|
||||
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
/*
|
||||
demodTray->AddSpacer(5);
|
||||
demodOpts->AddSpacer(5);
|
||||
|
||||
|
@ -63,12 +64,19 @@ wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
|||
demodOpts->AddSpacer(5);
|
||||
demodTray->AddSpacer(5);
|
||||
|
||||
demodTray->Add(demodOpts, 1, wxEXPAND | wxALL, 0);
|
||||
demodTray->Add(demodOpts, 1, wxEXPAND | wxALL, 0); */
|
||||
|
||||
demodSpectrumCanvas = new SpectrumCanvas(this, NULL);
|
||||
demodSpectrumCanvas->Setup(1024);
|
||||
demodSpectrumCanvas->SetView(DEFAULT_FREQ, 300000);
|
||||
demodVisuals->Add(demodSpectrumCanvas, 1, wxEXPAND | wxALL, 0);
|
||||
|
||||
demodVisuals->AddSpacer(1);
|
||||
|
||||
demodWaterfallCanvas = new WaterfallCanvas(this, NULL);
|
||||
demodWaterfallCanvas->Setup(1024,128);
|
||||
demodWaterfallCanvas->SetView(DEFAULT_FREQ,300000);
|
||||
demodWaterfallCanvas->Setup(1024, 256);
|
||||
demodWaterfallCanvas->SetView(DEFAULT_FREQ, 300000);
|
||||
demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas);
|
||||
demodVisuals->Add(demodWaterfallCanvas, 3, wxEXPAND | wxALL, 0);
|
||||
|
||||
demodTray->Add(demodVisuals, 7, wxEXPAND | wxALL, 0);
|
||||
|
@ -85,7 +93,8 @@ wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
|||
vbox->Add(spectrumCanvas, 1, wxEXPAND | wxALL, 0);
|
||||
vbox->AddSpacer(2);
|
||||
waterfallCanvas = new WaterfallCanvas(this, NULL);
|
||||
waterfallCanvas->Setup(2048,512);
|
||||
waterfallCanvas->Setup(2048, 512);
|
||||
waterfallCanvas->attachSpectrumCanvas(spectrumCanvas);
|
||||
vbox->Add(waterfallCanvas, 4, wxEXPAND | wxALL, 0);
|
||||
|
||||
this->SetSizer(vbox);
|
||||
|
@ -149,13 +158,15 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
|
||||
if (demod->getParams().frequency != demodWaterfallCanvas->GetCenterFrequency()) {
|
||||
demodWaterfallCanvas->SetCenterFrequency(demod->getParams().frequency);
|
||||
demodSpectrumCanvas->SetCenterFrequency(demod->getParams().frequency);
|
||||
}
|
||||
unsigned int demodBw = (unsigned int) ceil((float) demod->getParams().bandwidth * 2.5);
|
||||
if (demodBw > SRATE/2) {
|
||||
demodBw = SRATE/2;
|
||||
if (demodBw > SRATE / 2) {
|
||||
demodBw = SRATE / 2;
|
||||
}
|
||||
if (demodBw != demodWaterfallCanvas->GetBandwidth()) {
|
||||
demodWaterfallCanvas->SetBandwidth(demodBw);
|
||||
demodSpectrumCanvas->SetBandwidth(demodBw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +176,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||
wxGetApp().getIQVisualQueue()->pop(iqData);
|
||||
|
||||
if (iqData && iqData->data.size()) {
|
||||
spectrumCanvas->setData(iqData);
|
||||
// spectrumCanvas->setData(iqData);
|
||||
waterfallCanvas->setData(iqData);
|
||||
demodWaterfallCanvas->setData(iqData);
|
||||
delete iqData;
|
||||
|
@ -188,7 +199,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||
scopeCanvas->waveform_points[i * 2] = ((double) i / (double) iMax);
|
||||
}
|
||||
|
||||
scopeCanvas->setDivider(demodAudioData->channels == 2);
|
||||
scopeCanvas->setStereo(demodAudioData->channels == 2);
|
||||
|
||||
delete demodAudioData;
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,7 @@ private:
|
|||
ScopeCanvas *scopeCanvas;
|
||||
SpectrumCanvas *spectrumCanvas;
|
||||
WaterfallCanvas *waterfallCanvas;
|
||||
SpectrumCanvas *demodSpectrumCanvas;
|
||||
WaterfallCanvas *demodWaterfallCanvas;
|
||||
|
||||
// event table
|
||||
|
|
|
@ -71,10 +71,10 @@ class DemodulatorThreadPostIQData: public ReferenceCounter {
|
|||
public:
|
||||
std::vector<liquid_float_complex> data;
|
||||
int bandwidth;
|
||||
float audio_resample_ratio;
|
||||
double audio_resample_ratio;
|
||||
msresamp_rrrf audio_resampler;
|
||||
msresamp_rrrf stereo_resampler;
|
||||
float resample_ratio;
|
||||
double resample_ratio;
|
||||
msresamp_crcf resampler;
|
||||
|
||||
DemodulatorThreadPostIQData() :
|
||||
|
|
|
@ -30,32 +30,17 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* pQueueIn
|
|||
void DemodulatorPreThread::initialize() {
|
||||
initialized = false;
|
||||
|
||||
resample_ratio = (float) (params.bandwidth) / (float) params.inputRate;
|
||||
audio_resample_ratio = (float) (params.audioSampleRate) / (float) params.bandwidth;
|
||||
resample_ratio = (double) (params.bandwidth) / (double) params.inputRate;
|
||||
audio_resample_ratio = (double) (params.audioSampleRate) / (double) params.bandwidth;
|
||||
|
||||
float As = 60.0f; // stop-band attenuation [dB]
|
||||
|
||||
// create multi-stage arbitrary resampler object
|
||||
if (resampler) {
|
||||
msresamp_crcf_destroy(resampler);
|
||||
}
|
||||
resampler = msresamp_crcf_create(resample_ratio, As);
|
||||
// msresamp_crcf_print(resampler);
|
||||
|
||||
if (audio_resampler) {
|
||||
msresamp_rrrf_destroy(audio_resampler);
|
||||
}
|
||||
audio_resampler = msresamp_rrrf_create(audio_resample_ratio, As);
|
||||
// msresamp_crcf_print(audio_resampler);
|
||||
|
||||
if (stereo_resampler) {
|
||||
msresamp_rrrf_destroy(stereo_resampler);
|
||||
}
|
||||
stereo_resampler = msresamp_rrrf_create(audio_resample_ratio, As);
|
||||
|
||||
initialized = true;
|
||||
// std::cout << "inputResampleRate " << params.bandwidth << std::endl;
|
||||
|
||||
last_params = params;
|
||||
}
|
||||
|
||||
|
@ -68,12 +53,12 @@ DemodulatorPreThread::~DemodulatorPreThread() {
|
|||
#ifdef __APPLE__
|
||||
void *DemodulatorPreThread::threadMain() {
|
||||
#else
|
||||
void DemodulatorPreThread::threadMain() {
|
||||
void DemodulatorPreThread::threadMain() {
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
pthread_t tID = pthread_self(); // ID of this thread
|
||||
int priority = sched_get_priority_max( SCHED_FIFO) - 1;
|
||||
sched_param prio = { priority }; // scheduling priority of thread
|
||||
sched_param prio = {priority}; // scheduling priority of thread
|
||||
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
||||
#endif
|
||||
|
||||
|
@ -137,13 +122,13 @@ void *DemodulatorPreThread::threadMain() {
|
|||
if (inp->frequency != params.frequency) {
|
||||
if ((params.frequency - inp->frequency) != shift_freq) {
|
||||
shift_freq = params.frequency - inp->frequency;
|
||||
if (abs(shift_freq) <= (int) ((float) (SRATE / 2) * 1.5)) {
|
||||
nco_crcf_set_frequency(nco_shift, (2.0 * M_PI) * (((float) abs(shift_freq)) / ((float) SRATE)));
|
||||
if (abs(shift_freq) <= (int) ((double) (SRATE / 2) * 1.5)) {
|
||||
nco_crcf_set_frequency(nco_shift, (2.0 * M_PI) * (((double) abs(shift_freq)) / ((double) SRATE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(shift_freq) > (int) ((float) (SRATE / 2) * 1.5)) {
|
||||
if (abs(shift_freq) > (int) ((double) (SRATE / 2) * 1.5)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ protected:
|
|||
AudioThreadInputQueue *audioInputQueue;
|
||||
|
||||
msresamp_crcf resampler;
|
||||
float resample_ratio;
|
||||
double resample_ratio;
|
||||
|
||||
msresamp_rrrf audio_resampler;
|
||||
msresamp_rrrf stereo_resampler;
|
||||
float audio_resample_ratio;
|
||||
double audio_resample_ratio;
|
||||
|
||||
DemodulatorThreadParameters params;
|
||||
DemodulatorThreadParameters last_params;
|
||||
|
|
|
@ -36,7 +36,7 @@ void DemodulatorThread::threadMain() {
|
|||
firfilt_rrrf fir_filter2 = NULL;
|
||||
msresamp_crcf resampler = NULL;
|
||||
|
||||
float fc = 0.5 * ((double) 36000 / (double) AUDIO_FREQUENCY); // filter cutoff frequency
|
||||
double fc = 0.5 * ((double) 36000 / (double) AUDIO_FREQUENCY); // filter cutoff frequency
|
||||
if (fc <= 0) {
|
||||
fc = 0;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void DemodulatorThread::threadMain() {
|
|||
firhilbf firC2R = firhilbf_create(m, slsl);
|
||||
|
||||
nco_crcf nco_shift = nco_crcf_create(LIQUID_NCO);
|
||||
float shift_freq = 0;
|
||||
double shift_freq = 0;
|
||||
|
||||
agc = agc_crcf_create();
|
||||
agc_crcf_set_bandwidth(agc, 1e-3f);
|
||||
|
@ -105,7 +105,7 @@ void DemodulatorThread::threadMain() {
|
|||
stereo_resampler = inp->stereo_resampler;
|
||||
}
|
||||
|
||||
int out_size = ceil((float) (bufSize) * inp->resample_ratio);
|
||||
int out_size = ceil((double) (bufSize) * inp->resample_ratio);
|
||||
|
||||
if (agc_data.size() != out_size) {
|
||||
if (agc_data.capacity() < out_size) {
|
||||
|
@ -121,7 +121,7 @@ void DemodulatorThread::threadMain() {
|
|||
|
||||
agc_crcf_execute_block(agc, &resampled_data[0], num_written, &agc_data[0]);
|
||||
|
||||
float audio_resample_ratio = inp->audio_resample_ratio;
|
||||
double audio_resample_ratio = inp->audio_resample_ratio;
|
||||
|
||||
if (demod_output.size() != num_written) {
|
||||
if (demod_output.capacity() < num_written) {
|
||||
|
@ -130,7 +130,7 @@ void DemodulatorThread::threadMain() {
|
|||
demod_output.resize(num_written);
|
||||
}
|
||||
|
||||
int audio_out_size = ceil((float) (num_written) * audio_resample_ratio);
|
||||
int audio_out_size = ceil((double) (num_written) * audio_resample_ratio);
|
||||
|
||||
freqdem_demodulate_block(fdem, &agc_data[0], num_written, &demod_output[0]);
|
||||
|
||||
|
@ -152,7 +152,7 @@ void DemodulatorThread::threadMain() {
|
|||
demod_output_stereo.resize(num_written);
|
||||
}
|
||||
|
||||
double freq = (2.0 * M_PI) * (((float) abs(38000)) / ((float) inp->bandwidth));
|
||||
double freq = (2.0 * M_PI) * (((double) abs(38000)) / ((double) inp->bandwidth));
|
||||
|
||||
if (shift_freq != freq) {
|
||||
nco_crcf_set_frequency(nco_shift, freq);
|
||||
|
|
|
@ -58,5 +58,6 @@ protected:
|
|||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
||||
DemodulatorThreadControlCommandQueue *threadQueueControl;
|
||||
float squelch_level;
|
||||
float squelch_tolerance;bool squelch_enabled;
|
||||
float squelch_tolerance;
|
||||
bool squelch_enabled;
|
||||
};
|
||||
|
|
|
@ -34,8 +34,8 @@ void DemodulatorWorkerThread::threadMain() {
|
|||
if (filterChanged) {
|
||||
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
|
||||
|
||||
result.resample_ratio = (float) (filterCommand.bandwidth) / (float) filterCommand.inputRate;
|
||||
result.audio_resample_ratio = (float) (filterCommand.audioSampleRate) / (float) filterCommand.bandwidth;
|
||||
result.resample_ratio = (double) (filterCommand.bandwidth) / (double) filterCommand.inputRate;
|
||||
result.audio_resample_ratio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth;
|
||||
|
||||
float As = 60.0f; // stop-band attenuation [dB]
|
||||
|
||||
|
@ -46,8 +46,8 @@ void DemodulatorWorkerThread::threadMain() {
|
|||
result.audioSampleRate = filterCommand.audioSampleRate;
|
||||
result.bandwidth = filterCommand.bandwidth;
|
||||
result.inputRate = filterCommand.inputRate;
|
||||
|
||||
resultQueue->push(result);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(30));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ public:
|
|||
DemodulatorThreadResultEnum cmd;
|
||||
|
||||
msresamp_crcf resampler;
|
||||
float resample_ratio;
|
||||
double resample_ratio;
|
||||
msresamp_rrrf audio_resampler;
|
||||
msresamp_rrrf stereo_resampler;
|
||||
float audio_resample_ratio;
|
||||
double audio_resample_ratio;
|
||||
|
||||
unsigned int inputRate;
|
||||
unsigned int bandwidth;
|
||||
|
|
|
@ -132,7 +132,7 @@ void SDRPostThread::threadMain() {
|
|||
DemodulatorInstance *demod = *i;
|
||||
|
||||
if (demod->getParams().frequency != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0))) {
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (int) ((double) ((double) SRATE / 2.0))) {
|
||||
continue;
|
||||
}
|
||||
activeDemods++;
|
||||
|
@ -166,7 +166,7 @@ void SDRPostThread::threadMain() {
|
|||
DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod;
|
||||
|
||||
if (demod->getParams().frequency != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0))) {
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (int) ((double) ((double) SRATE / 2.0))) {
|
||||
if (demod->isActive()) {
|
||||
demod->setActive(false);
|
||||
DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData;
|
||||
|
|
|
@ -21,7 +21,7 @@ wxEND_EVENT_TABLE()
|
|||
|
||||
ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) :
|
||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), divider(false) {
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), stereo(false) {
|
||||
|
||||
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
|
||||
timer.start();
|
||||
|
@ -35,8 +35,8 @@ void ScopeCanvas::setWaveformPoints(std::vector<float> &waveform_points_in) {
|
|||
waveform_points = waveform_points_in;
|
||||
}
|
||||
|
||||
void ScopeCanvas::setDivider(bool state) {
|
||||
divider = state;
|
||||
void ScopeCanvas::setStereo(bool state) {
|
||||
stereo = state;
|
||||
}
|
||||
|
||||
void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
|
@ -47,10 +47,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||
|
||||
glContext->DrawBegin();
|
||||
glContext->Plot(waveform_points);
|
||||
if (divider) {
|
||||
glContext->DrawDivider();
|
||||
}
|
||||
glContext->Plot(waveform_points, stereo);
|
||||
glContext->DrawEnd();
|
||||
|
||||
SwapBuffers();
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
~ScopeCanvas();
|
||||
|
||||
void setWaveformPoints(std::vector<float> &waveform_points_in);
|
||||
void setDivider(bool state);
|
||||
void setStereo(bool state);
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
|
||||
|
@ -30,7 +30,7 @@ private:
|
|||
ScopeContext *glContext;
|
||||
Timer timer;
|
||||
float frameTimer;
|
||||
bool divider;
|
||||
bool stereo;
|
||||
// event table
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
|
|
@ -20,18 +20,57 @@ void ScopeContext::DrawBegin() {
|
|||
glDisable (GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void ScopeContext::Plot(std::vector<float> &points) {
|
||||
void ScopeContext::Plot(std::vector<float> &points, bool stereo) {
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
if (stereo) {
|
||||
glColor3f(0.7, 0.7, 0.7);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-1.0,0.0);
|
||||
glVertex2f(1.0,0.0);
|
||||
glEnd();
|
||||
glColor3f(0.3, 0.3, 0.3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-1.0,0.5);
|
||||
glVertex2f(1.0,0.5);
|
||||
glVertex2f(-1.0,-0.5);
|
||||
glVertex2f(1.0,-0.5);
|
||||
glEnd();
|
||||
} else {
|
||||
glColor3f(0.3, 0.3, 0.3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-1.0,0.0);
|
||||
glVertex2f(1.0,0.0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glColor3f(0.9, 0.9, 0.9);
|
||||
if (points.size()) {
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.0f, 0.0f);
|
||||
glScalef(2.0f, 2.0f, 1.0f);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2);
|
||||
if (stereo) {
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.5f, 0.0f);
|
||||
glScalef(4.0f, 0.92f, 1.0f);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, points.size() / 4);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0f, -0.5f, 0.0f);
|
||||
glPushMatrix();
|
||||
glScalef(4.0f, 0.92f, 1.0f);
|
||||
glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4);
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
} else {
|
||||
glPushMatrix();
|
||||
glTranslatef(-1.0f, 0.0f, 0.0f);
|
||||
glScalef(2.0f, 2.0f, 1.0f);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2);
|
||||
glPopMatrix();
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glPopMatrix();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext);
|
||||
|
||||
void DrawBegin();
|
||||
void Plot(std::vector<float> &points);
|
||||
void Plot(std::vector<float> &points, bool stereo=false);
|
||||
void DrawDivider();
|
||||
void DrawEnd();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ wxEND_EVENT_TABLE()
|
|||
|
||||
SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) :
|
||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), fft_size(0), in(NULL), out(NULL), plan(NULL) {
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), fft_size(0), in(NULL), out(NULL), plan(NULL), center_freq(0), bandwidth(0), isView(0) {
|
||||
|
||||
glContext = new SpectrumContext(this, &wxGetApp().GetContext(this));
|
||||
|
||||
|
@ -74,12 +74,12 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||
|
||||
glContext->BeginDraw();
|
||||
glContext->Draw(spectrum_points);
|
||||
glContext->Draw(spectrum_points, GetCenterFrequency(), GetBandwidth());
|
||||
|
||||
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
|
||||
|
||||
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
||||
glContext->DrawDemodInfo(demods[i]);
|
||||
glContext->DrawDemodInfo(demods[i], 1, 1, 1, GetCenterFrequency(), GetBandwidth());
|
||||
}
|
||||
|
||||
glContext->EndDraw();
|
||||
|
@ -171,6 +171,41 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpectrumCanvas::SetView(int center_freq_in, int bandwidth_in) {
|
||||
isView = true;
|
||||
center_freq = center_freq_in;
|
||||
bandwidth = bandwidth_in;
|
||||
}
|
||||
|
||||
void SpectrumCanvas::DisableView() {
|
||||
isView = false;
|
||||
}
|
||||
void SpectrumCanvas::SetCenterFrequency(unsigned int center_freq_in) {
|
||||
center_freq = center_freq_in;
|
||||
}
|
||||
|
||||
unsigned int SpectrumCanvas::GetCenterFrequency() {
|
||||
if (isView) {
|
||||
return center_freq;
|
||||
} else {
|
||||
return (unsigned int) wxGetApp().getFrequency();
|
||||
}
|
||||
}
|
||||
|
||||
void SpectrumCanvas::SetBandwidth(unsigned int bandwidth_in) {
|
||||
bandwidth = bandwidth_in;
|
||||
}
|
||||
|
||||
unsigned int SpectrumCanvas::GetBandwidth() {
|
||||
if (isView) {
|
||||
return bandwidth;
|
||||
} else {
|
||||
return SRATE;
|
||||
}
|
||||
}
|
||||
|
||||
void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
|
||||
// timer.update();
|
||||
// frameTimer += timer.lastUpdateSeconds();
|
||||
|
@ -183,7 +218,7 @@ void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
|
|||
void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
|
||||
mTracker.OnMouseMoved(event);
|
||||
if (mTracker.mouseDown()) {
|
||||
int freqChange = mTracker.getDeltaMouseX() * SRATE;
|
||||
int freqChange = mTracker.getDeltaMouseX() * GetBandwidth();
|
||||
|
||||
if (freqChange != 0) {
|
||||
int freq = wxGetApp().getFrequency();
|
||||
|
|
|
@ -14,11 +14,23 @@
|
|||
|
||||
class SpectrumCanvas: public wxGLCanvas {
|
||||
public:
|
||||
std::vector<float> spectrum_points;
|
||||
|
||||
SpectrumCanvas(wxWindow *parent, int *attribList = NULL);
|
||||
void Setup(int fft_size_in);
|
||||
~SpectrumCanvas();
|
||||
|
||||
void setData(DemodulatorThreadIQData *input);
|
||||
|
||||
void SetView(int center_freq_in, int bandwidth_in);
|
||||
void DisableView();
|
||||
|
||||
void SetCenterFrequency(unsigned int center_freq_in);
|
||||
unsigned int GetCenterFrequency();
|
||||
|
||||
void SetBandwidth(unsigned int bandwidth_in);
|
||||
unsigned int GetBandwidth();
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
|
||||
|
@ -33,7 +45,6 @@ private:
|
|||
void mouseLeftWindow(wxMouseEvent& event);
|
||||
|
||||
wxWindow *parent;
|
||||
std::vector<float> spectrum_points;
|
||||
|
||||
fftw_complex *in, *out;
|
||||
fftw_plan plan;
|
||||
|
@ -48,6 +59,11 @@ private:
|
|||
SpectrumContext *glContext;
|
||||
int fft_size;
|
||||
|
||||
unsigned int center_freq;
|
||||
unsigned int bandwidth;
|
||||
|
||||
bool isView;
|
||||
|
||||
MouseTracker mTracker;
|
||||
// event table
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <iostream>
|
||||
|
||||
SpectrumContext::SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext) :
|
||||
PrimaryGLContext(canvas, sharedContext) {
|
||||
PrimaryGLContext(canvas, sharedContext), fft_size(0) {
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
@ -15,7 +15,7 @@ SpectrumContext::SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedCont
|
|||
|
||||
}
|
||||
|
||||
void SpectrumContext::Draw(std::vector<float> &points) {
|
||||
void SpectrumContext::Draw(std::vector<float> &points, int freq, int bandwidth) {
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
@ -35,9 +35,10 @@ void SpectrumContext::Draw(std::vector<float> &points) {
|
|||
glGetIntegerv( GL_VIEWPORT, vp);
|
||||
|
||||
float viewHeight = (float) vp[3];
|
||||
float viewWidth = (float) vp[2];
|
||||
|
||||
float leftFreq = (float) wxGetApp().getFrequency() - ((float) SRATE / 2.0);
|
||||
float rightFreq = leftFreq + (float) SRATE;
|
||||
float leftFreq = (float) freq - ((float) bandwidth / 2.0);
|
||||
float rightFreq = leftFreq + (float) bandwidth;
|
||||
|
||||
float firstMhz = floor(leftFreq / 1000000.0) * 1000000.0;
|
||||
float mhzStart = ((firstMhz - leftFreq) / (rightFreq - leftFreq)) * 2.0;
|
||||
|
|
|
@ -11,7 +11,7 @@ class SpectrumContext: public PrimaryGLContext {
|
|||
public:
|
||||
SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext);
|
||||
|
||||
void Draw(std::vector<float> &points);
|
||||
void Draw(std::vector<float> &points, int freq, int bandwidth);
|
||||
|
||||
private:
|
||||
int fft_size;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include <wx/numformatter.h>
|
||||
|
||||
#define MIN_FM_BANDWIDTH 10000
|
||||
|
||||
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) EVT_PAINT(WaterfallCanvas::OnPaint)
|
||||
EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown)
|
||||
EVT_KEY_UP(WaterfallCanvas::OnKeyUp)
|
||||
|
@ -30,7 +32,7 @@ wxEND_EVENT_TABLE()
|
|||
|
||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), spectrumCanvas(NULL), frameTimer(0), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
|
||||
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown(false), altDown(false), ctrlDown(false), fft_size(0), waterfall_lines(0), plan(
|
||||
NULL), in(NULL), out(NULL), center_freq(0), bandwidth(0), isView(false), resampler(NULL), resample_ratio(0), last_bandwidth(0), last_input_bandwidth(
|
||||
0) {
|
||||
|
@ -126,6 +128,11 @@ WaterfallCanvas::DragState WaterfallCanvas::getNextDragState() {
|
|||
return nextDragState;
|
||||
}
|
||||
|
||||
void WaterfallCanvas::attachSpectrumCanvas(SpectrumCanvas *canvas_in) {
|
||||
spectrumCanvas = canvas_in;
|
||||
}
|
||||
|
||||
|
||||
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
wxPaintDC dc(this);
|
||||
const wxSize ClientSize = GetClientSize();
|
||||
|
@ -427,6 +434,10 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
|||
spectrum_points[i * 2] = ((float) i / (float) iMax);
|
||||
spectrum_points[i * 2 + 1] = v;
|
||||
}
|
||||
|
||||
if (spectrumCanvas) {
|
||||
spectrumCanvas->spectrum_points.assign(spectrum_points.begin(),spectrum_points.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,11 +478,11 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
|||
DemodulatorThreadCommand command;
|
||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
||||
activeDemodulatorBandwidth = activeDemodulatorBandwidth + bwDiff;
|
||||
if (activeDemodulatorBandwidth < 2000) {
|
||||
activeDemodulatorBandwidth = 2000;
|
||||
if (activeDemodulatorBandwidth > SRATE) {
|
||||
activeDemodulatorBandwidth = SRATE;
|
||||
}
|
||||
if (activeDemodulatorBandwidth > GetBandwidth()) {
|
||||
activeDemodulatorBandwidth = GetBandwidth();
|
||||
if (activeDemodulatorBandwidth < MIN_FM_BANDWIDTH) {
|
||||
activeDemodulatorBandwidth = MIN_FM_BANDWIDTH;
|
||||
}
|
||||
|
||||
command.int_value = activeDemodulatorBandwidth;
|
||||
|
@ -661,8 +672,8 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
|
|||
unsigned int freq = input_center_freq - (int) (0.5 * (float) GetBandwidth()) + (int) ((float) pos * (float) GetBandwidth());
|
||||
unsigned int bw = (unsigned int) (fabs(width) * (float) GetBandwidth());
|
||||
|
||||
if (bw < 2000) {
|
||||
bw = 2000;
|
||||
if (bw < MIN_FM_BANDWIDTH) {
|
||||
bw = MIN_FM_BANDWIDTH;
|
||||
}
|
||||
|
||||
if (!bw) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "WaterfallContext.h"
|
||||
#include "MouseTracker.h"
|
||||
#include "SpectrumCanvas.h"
|
||||
|
||||
#include "fftw3.h"
|
||||
#include "Timer.h"
|
||||
|
@ -37,6 +38,8 @@ public:
|
|||
DragState getDragState();
|
||||
DragState getNextDragState();
|
||||
|
||||
void attachSpectrumCanvas(SpectrumCanvas *canvas_in);
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
@ -52,6 +55,7 @@ private:
|
|||
void mouseLeftWindow(wxMouseEvent& event);
|
||||
|
||||
wxWindow *parent;
|
||||
SpectrumCanvas *spectrumCanvas;
|
||||
std::vector<float> spectrum_points;
|
||||
|
||||
fftw_complex *in, *out;
|
||||
|
|
Loading…
Reference in New Issue