diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 62f19cd..f419420 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -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 { diff --git a/src/AppFrame.h b/src/AppFrame.h index 3c87d95..b8589fa 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -23,6 +23,7 @@ private: ScopeCanvas *scopeCanvas; SpectrumCanvas *spectrumCanvas; WaterfallCanvas *waterfallCanvas; + SpectrumCanvas *demodSpectrumCanvas; WaterfallCanvas *demodWaterfallCanvas; // event table diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index ac899ba..d938bac 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -71,10 +71,10 @@ class DemodulatorThreadPostIQData: public ReferenceCounter { public: std::vector 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() : diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 9223e84..f9c26a3 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -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; } diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 7bd0b23..962b3f9 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -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; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 3f10217..b3e9640 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -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); diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 444c037..0501b59 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -58,5 +58,6 @@ protected: DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadControlCommandQueue *threadQueueControl; float squelch_level; - float squelch_tolerance;bool squelch_enabled; + float squelch_tolerance; + bool squelch_enabled; }; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index 1d79c9f..44c584a 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -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)); } } diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index a51e88d..a45336c 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -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; diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 9322410..b269d42 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -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; diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 76071ed..80ad241 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -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 &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(); diff --git a/src/visual/ScopeCanvas.h b/src/visual/ScopeCanvas.h index 26ace11..29d1cd4 100644 --- a/src/visual/ScopeCanvas.h +++ b/src/visual/ScopeCanvas.h @@ -19,7 +19,7 @@ public: ~ScopeCanvas(); void setWaveformPoints(std::vector &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(); }; diff --git a/src/visual/ScopeContext.cpp b/src/visual/ScopeContext.cpp index 5c1badd..1a12298 100644 --- a/src/visual/ScopeContext.cpp +++ b/src/visual/ScopeContext.cpp @@ -20,18 +20,57 @@ void ScopeContext::DrawBegin() { glDisable (GL_TEXTURE_2D); } -void ScopeContext::Plot(std::vector &points) { +void ScopeContext::Plot(std::vector &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(); + } } diff --git a/src/visual/ScopeContext.h b/src/visual/ScopeContext.h index 6f001b0..321f14e 100644 --- a/src/visual/ScopeContext.h +++ b/src/visual/ScopeContext.h @@ -12,7 +12,7 @@ public: ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext); void DrawBegin(); - void Plot(std::vector &points); + void Plot(std::vector &points, bool stereo=false); void DrawDivider(); void DrawEnd(); diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 4dc669c..1c73431 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -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 &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(); diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index d5ddc2b..dea6b74 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -14,11 +14,23 @@ class SpectrumCanvas: public wxGLCanvas { public: + std::vector 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 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(); diff --git a/src/visual/SpectrumContext.cpp b/src/visual/SpectrumContext.cpp index 8d4993e..2a5207a 100644 --- a/src/visual/SpectrumContext.cpp +++ b/src/visual/SpectrumContext.cpp @@ -6,7 +6,7 @@ #include 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 &points) { +void SpectrumContext::Draw(std::vector &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 &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; diff --git a/src/visual/SpectrumContext.h b/src/visual/SpectrumContext.h index 3167e65..91c900c 100644 --- a/src/visual/SpectrumContext.h +++ b/src/visual/SpectrumContext.h @@ -11,7 +11,7 @@ class SpectrumContext: public PrimaryGLContext { public: SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext); - void Draw(std::vector &points); + void Draw(std::vector &points, int freq, int bandwidth); private: int fft_size; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 49a3481..589b966 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -17,6 +17,8 @@ #include +#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) { diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index a04aca2..fb8196c 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -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 spectrum_points; fftw_complex *in, *out;