From 4f43f65065ef0dee3c5cbb62cf45556132560b5f Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 1 Jan 2015 18:08:54 -0500 Subject: [PATCH] AM, USB and LSB somewhat working --- src/AppFrame.cpp | 88 ++++++++--------- src/AppFrame.h | 7 +- src/CubicSDRDefs.h | 3 +- src/demod/DemodDefs.h | 16 ++-- src/demod/DemodulatorInstance.cpp | 16 +++- src/demod/DemodulatorInstance.h | 6 +- src/demod/DemodulatorPreThread.cpp | 4 +- src/demod/DemodulatorThread.cpp | 131 ++++++++++++++++++-------- src/demod/DemodulatorThread.h | 13 ++- src/demod/DemodulatorWorkerThread.cpp | 1 - src/visual/SpectrumCanvas.h | 10 +- src/visual/WaterfallCanvas.cpp | 66 ++++++++----- src/visual/WaterfallCanvas.h | 12 +-- 13 files changed, 232 insertions(+), 141 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 7281b1f..9dae70d 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -38,35 +38,35 @@ AppFrame::AppFrame() : wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL); /* - demodTray->AddSpacer(5); - demodOpts->AddSpacer(5); + demodTray->AddSpacer(5); + demodOpts->AddSpacer(5); - wxStaticText *audioDeviceLabel = new wxStaticText(this, wxID_ANY, wxString("Audio Device:")); - demodOpts->Add(audioDeviceLabel, 1, wxFIXED_MINSIZE | wxALL, 0); + wxStaticText *audioDeviceLabel = new wxStaticText(this, wxID_ANY, wxString("Audio Device:")); + demodOpts->Add(audioDeviceLabel, 1, wxFIXED_MINSIZE | wxALL, 0); - wxArrayString str; - str.Add("Primary Device"); - wxChoice *wxCh = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, str); - demodOpts->Add(wxCh, 1, wxFIXED_MINSIZE | wxALL, 0); + wxArrayString str; + str.Add("Primary Device"); + wxChoice *wxCh = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, str); + demodOpts->Add(wxCh, 1, wxFIXED_MINSIZE | wxALL, 0); - demodOpts->AddSpacer(2); + demodOpts->AddSpacer(2); - wxStaticText *demodTypeLabel = new wxStaticText(this, wxID_ANY, wxString("Demodulation:")); - demodOpts->Add(demodTypeLabel, 1, wxFIXED_MINSIZE | wxALL, 0); + wxStaticText *demodTypeLabel = new wxStaticText(this, wxID_ANY, wxString("Demodulation:")); + demodOpts->Add(demodTypeLabel, 1, wxFIXED_MINSIZE | wxALL, 0); - str.Clear(); - str.Add("FM"); - str.Add("FM Stereo"); - str.Add("AM"); - str.Add("LSB"); - str.Add("USB"); - wxChoice *wxDemodChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, str); - demodOpts->Add(wxDemodChoice, 1, wxFIXED_MINSIZE | wxALL, 0); + str.Clear(); + str.Add("FM"); + str.Add("FM Stereo"); + str.Add("AM"); + str.Add("LSB"); + str.Add("USB"); + wxChoice *wxDemodChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, str); + demodOpts->Add(wxDemodChoice, 1, wxFIXED_MINSIZE | wxALL, 0); - demodOpts->AddSpacer(5); - demodTray->AddSpacer(5); + 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); @@ -123,7 +123,7 @@ AppFrame::AppFrame() : wxMenu *menu = new wxMenu; std::vector::iterator devices_i; - std::map::iterator mdevices_i; + std::map::iterator mdevices_i; AudioThread::enumerateDevices(devices); int i = 0; @@ -141,8 +141,8 @@ AppFrame::AppFrame() : i = 0; for (mdevices_i = output_devices.begin(); mdevices_i != output_devices.end(); mdevices_i++) { - wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE+mdevices_i->first,mdevices_i->second.name,wxT("Description?")); - itm->SetId(wxID_RT_AUDIO_DEVICE+mdevices_i->first); + wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE + mdevices_i->first, mdevices_i->second.name, wxT("Description?")); + itm->SetId(wxID_RT_AUDIO_DEVICE + mdevices_i->first); if (mdevices_i->second.isDefaultOutput) { itm->Check(true); } @@ -153,14 +153,13 @@ AppFrame::AppFrame() : menuBar->Append(menu, wxT("Output &Device")); wxMenu *demodMenu = new wxMenu; - demod_menuitems[DemodulatorType::DEMOD_TYPE_FM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_FM,wxT("FM"),wxT("Description?")); - demod_menuitems[DemodulatorType::DEMOD_TYPE_AM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_AM,wxT("AM"),wxT("Description?")); - demod_menuitems[DemodulatorType::DEMOD_TYPE_LSB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_LSB,wxT("LSB"),wxT("Description?")); - demod_menuitems[DemodulatorType::DEMOD_TYPE_USB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_USB,wxT("USB"),wxT("Description?")); + demod_menuitems[DEMOD_TYPE_FM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_FM, wxT("FM"), wxT("Description?")); + demod_menuitems[DEMOD_TYPE_AM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_AM, wxT("AM"), wxT("Description?")); + demod_menuitems[DEMOD_TYPE_LSB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_LSB, wxT("LSB"), wxT("Description?")); + demod_menuitems[DEMOD_TYPE_USB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_USB, wxT("USB"), wxT("Description?")); menuBar->Append(demodMenu, wxT("Demodulaton &Type")); - SetMenuBar(menuBar); CreateStatusBar(); @@ -180,25 +179,25 @@ AppFrame::~AppFrame() { } void AppFrame::OnMenu(wxCommandEvent& event) { - if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE+devices.size()) { + if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + devices.size()) { if (activeDemodulator) { - activeDemodulator->setOutputDevice(event.GetId()-wxID_RT_AUDIO_DEVICE); + activeDemodulator->setOutputDevice(event.GetId() - wxID_RT_AUDIO_DEVICE); activeDemodulator = NULL; } } if (activeDemodulator) { - if (event.GetId() == wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_FM) { - activeDemodulator->setDemodulatorType(DemodulatorType::DEMOD_TYPE_FM); + if (event.GetId() == wxID_DEMOD_TYPE_FM) { + activeDemodulator->setDemodulatorType(DEMOD_TYPE_FM); activeDemodulator = NULL; - } else if (event.GetId() == wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_AM) { - activeDemodulator->setDemodulatorType(DemodulatorType::DEMOD_TYPE_AM); + } else if (event.GetId() == wxID_DEMOD_TYPE_AM) { + activeDemodulator->setDemodulatorType(DEMOD_TYPE_AM); activeDemodulator = NULL; - } else if (event.GetId() == wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_LSB) { - activeDemodulator->setDemodulatorType(DemodulatorType::DEMOD_TYPE_LSB); + } else if (event.GetId() == wxID_DEMOD_TYPE_LSB) { + activeDemodulator->setDemodulatorType(DEMOD_TYPE_LSB); activeDemodulator = NULL; - } else if (event.GetId() == wxID_DEMOD_TYPE+DemodulatorType::DEMOD_TYPE_USB) { - activeDemodulator->setDemodulatorType(DemodulatorType::DEMOD_TYPE_USB); + } else if (event.GetId() == wxID_DEMOD_TYPE_USB) { + activeDemodulator->setDemodulatorType(DEMOD_TYPE_USB); activeDemodulator = NULL; } } @@ -232,7 +231,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { int outputDevice = demod->getOutputDevice(); scopeCanvas->setDeviceName(output_devices[outputDevice].name); output_device_menuitems[outputDevice]->Check(true); - DemodulatorType dType = demod->getDemodulatorType(); + int dType = demod->getDemodulatorType(); demod_menuitems[dType]->Check(true); } if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) { @@ -244,10 +243,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (demodBw > SRATE / 2) { demodBw = SRATE / 2; } - if (demodBw != demodWaterfallCanvas->GetBandwidth()) { - demodWaterfallCanvas->SetBandwidth(demodBw); - demodSpectrumCanvas->SetBandwidth(demodBw); + if (demodBw < 80000) { + demodBw = 80000; } + demodWaterfallCanvas->SetBandwidth(demodBw); + demodSpectrumCanvas->SetBandwidth(demodBw); } demodSignalMeter->setLevel(demod->getSignalLevel()); if (demodSignalMeter->inputChanged()) { diff --git a/src/AppFrame.h b/src/AppFrame.h index c8144da..d3ff416 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -11,7 +11,10 @@ #include #define wxID_RT_AUDIO_DEVICE 1000 -#define wxID_DEMOD_TYPE 1500 +#define wxID_DEMOD_TYPE_FM 2000 +#define wxID_DEMOD_TYPE_AM 2001 +#define wxID_DEMOD_TYPE_LSB 2002 +#define wxID_DEMOD_TYPE_USB 2003 // Define a new frame type class AppFrame: public wxFrame { @@ -42,7 +45,7 @@ private: std::map output_devices; std::map output_device_menuitems; - std::map demod_menuitems; + std::map demod_menuitems; wxDECLARE_EVENT_TABLE(); }; diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index ca0583e..1a8fa98 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -9,7 +9,8 @@ #endif #define DEFAULT_FFT_SIZE 2048 -#define DEFAULT_FREQ 98900000 +//#define DEFAULT_FREQ 98900000 +#define DEFAULT_FREQ 132000000 #define AUDIO_FREQUENCY 44100 #include diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index d938bac..af0625d 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -7,9 +7,12 @@ #include #include -enum DemodulatorType { - DEMOD_TYPE_NULL, DEMOD_TYPE_AM, DEMOD_TYPE_FM, DEMOD_TYPE_LSB, DEMOD_TYPE_USB -}; +#define DEMOD_TYPE_NULL 0 +#define DEMOD_TYPE_FM 1 +#define DEMOD_TYPE_AM 2 +#define DEMOD_TYPE_LSB 3 +#define DEMOD_TYPE_USB 4 + class DemodulatorThread; class DemodulatorThreadCommand { @@ -41,14 +44,15 @@ public: class DemodulatorThreadControlCommand { public: enum DemodulatorThreadControlCommandEnum { - DEMOD_THREAD_CMD_CTL_NULL, DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO, DEMOD_THREAD_CMD_CTL_SQUELCH_OFF + DEMOD_THREAD_CMD_CTL_NULL, DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO, DEMOD_THREAD_CMD_CTL_SQUELCH_OFF, DEMOD_THREAD_CMD_CTL_TYPE }; DemodulatorThreadControlCommand() : - cmd(DEMOD_THREAD_CMD_CTL_NULL) { + cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType(DEMOD_TYPE_NULL) { } DemodulatorThreadControlCommandEnum cmd; + int demodType; }; class DemodulatorThreadIQData: public ReferenceCounter { @@ -122,7 +126,7 @@ public: unsigned int bandwidth; // set equal to disable second stage re-sampling? unsigned int audioSampleRate; - DemodulatorType demodType; + int demodType; DemodulatorThreadParameters() : frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate( diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 3e67f56..12c2692 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -19,6 +19,8 @@ DemodulatorInstance::DemodulatorInstance() : audioThread = new AudioThread(audioInputQueue, threadQueueNotify); demodulatorThread->setAudioInputQueue(audioInputQueue); + + currentDemodType = demodulatorThread->getDemodulatorType(); } DemodulatorInstance::~DemodulatorInstance() { @@ -208,11 +210,17 @@ int DemodulatorInstance::getOutputDevice() { return audioThread->getOutputDevice(); } -void DemodulatorInstance::setDemodulatorType(DemodulatorType demod_type_in) { - demodulatorThread->setDemodulatorType(demod_type_in); +void DemodulatorInstance::setDemodulatorType(int demod_type_in) { + if (demodulatorThread && threadQueueControl) { + DemodulatorThreadControlCommand command; + command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE; + currentDemodType = demod_type_in; + command.demodType = demod_type_in; + threadQueueControl->push(command); + } } -DemodulatorType DemodulatorInstance::getDemodulatorType() { - return demodulatorThread->getDemodulatorType(); +int DemodulatorInstance::getDemodulatorType() { + return currentDemodType; } diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index cc943ba..5a440b3 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -63,8 +63,8 @@ public: void setOutputDevice(int device_id); int getOutputDevice(); - void setDemodulatorType(DemodulatorType demod_type_in); - DemodulatorType getDemodulatorType(); + void setDemodulatorType(int demod_type_in); + int getDemodulatorType(); private: std::atomic label; // @@ -75,5 +75,7 @@ private: std::atomic active; std::atomic squelch; std::atomic stereo; + + int currentDemodType; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index f9c26a3..8ee7a9f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -88,8 +88,8 @@ void DemodulatorPreThread::threadMain() { commandQueue->pop(command); switch (command.cmd) { case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH: - if (command.int_value < 3000) { - command.int_value = 3000; + if (command.int_value < 1500) { + command.int_value = 1500; } if (command.int_value > SRATE) { command.int_value = SRATE; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index f12ae2a..9a79c3e 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -9,16 +9,14 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* pQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : postInputQueue(pQueue), visOutQueue(NULL), audioInputQueue(NULL), agc(NULL), am_max(1), am_max_ma(1), am_max_maa(1), stereo(false), terminated( - false), demodulatorType(DemodulatorType::DEMOD_TYPE_FM), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelch_level( - 0), squelch_tolerance(0), signal_level(0), squelch_enabled(false) { + false), demodulatorType(DEMOD_TYPE_FM), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelch_level(0), squelch_tolerance( + 0), signal_level(0), squelch_enabled(false) { fdem = freqdem_create(0.5); - liquid_ampmodem_type type_lsb = LIQUID_AMPMODEM_LSB; - ampdem_lsb = ampmodem_create(1.0, 0.5, type_lsb, 1); - liquid_ampmodem_type type_usb = LIQUID_AMPMODEM_USB; - ampdem_usb = ampmodem_create(1.0, -0.5, type_usb, 1); - liquid_ampmodem_type type_dsb = LIQUID_AMPMODEM_DSB; - ampdem = ampmodem_create(0.5, 0.0, type_dsb, 0); + ampdem_lsb = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1); + ampdem_usb = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1); + ampdem = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0); + ampdem_active = ampdem; } DemodulatorThread::~DemodulatorThread() { @@ -66,8 +64,23 @@ void DemodulatorThread::threadMain() { firhilbf firR2C = firhilbf_create(m, slsl); firhilbf firC2R = firhilbf_create(m, slsl); - nco_crcf nco_shift = nco_crcf_create(LIQUID_NCO); - double shift_freq = 0; + nco_crcf nco_stereo_shift = nco_crcf_create(LIQUID_NCO); + double nco_stereo_shift_freq = 0; + + nco_crcf nco_ssb_shift_up = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_frequency(nco_ssb_shift_up, (2.0 * M_PI) * 0.25); + + + nco_crcf nco_ssb_shift_down = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_frequency(nco_ssb_shift_down, (2.0 * M_PI) * 0.25); + + // estimate required filter length and generate filter + h_len = estimate_req_filter_len(ft,100.0); + float h2[h_len]; + liquid_firdes_kaiser(h_len,0.25,As,0.0,h2); + + firfilt_crcf ssb_fir_filter = firfilt_crcf_create(h2, h_len); + agc = agc_crcf_create(); agc_crcf_set_bandwidth(agc, 0.9); @@ -106,7 +119,7 @@ void DemodulatorThread::threadMain() { freqdem_reset(fdem); } - int out_size = ceil((double) (bufSize) * inp->resample_ratio); + int out_size = ceil((double) (bufSize) * inp->resample_ratio) + 32; if (agc_data.size() != out_size) { if (agc_data.capacity() < out_size) { @@ -131,7 +144,7 @@ void DemodulatorThread::threadMain() { demod_output.resize(num_written); } - int audio_out_size = ceil((double) (num_written) * audio_resample_ratio); + int audio_out_size = ceil((double) (num_written) * audio_resample_ratio) + 32; agc_crcf_execute_block(agc, &resampled_data[0], num_written, &agc_data[0]); @@ -143,40 +156,51 @@ void DemodulatorThread::threadMain() { current_level = agc_crcf_get_signal_level(agc); } - switch (demodulatorType) { - case DemodulatorType::DEMOD_TYPE_FM: + if (demodulatorType == DEMOD_TYPE_FM) { freqdem_demodulate_block(fdem, &agc_data[0], num_written, &demod_output[0]); - break; - case DemodulatorType::DEMOD_TYPE_LSB: - for (int i = 0; i < num_written; i++) { - ampmodem_demodulate(ampdem_lsb, resampled_data[i], &demod_output[i]); + } else { + float p; + switch (demodulatorType) { + case DEMOD_TYPE_LSB: + for (int i = 0; i < num_written; i++) { // Reject upper band + nco_crcf_mix_up(nco_ssb_shift_up, resampled_data[i], &x); + nco_crcf_step(nco_ssb_shift_up); + firfilt_crcf_push(ssb_fir_filter, x); + firfilt_crcf_execute(ssb_fir_filter, &x); + nco_crcf_mix_down(nco_ssb_shift_down, x, &resampled_data[i]); + nco_crcf_step(nco_ssb_shift_down); + } + break; + case DEMOD_TYPE_USB: + for (int i = 0; i < num_written; i++) { // Reject lower band + nco_crcf_mix_down(nco_ssb_shift_down, resampled_data[i], &x); + nco_crcf_step(nco_ssb_shift_down); + firfilt_crcf_push(ssb_fir_filter, x); + firfilt_crcf_execute(ssb_fir_filter, &x); + nco_crcf_mix_up(nco_ssb_shift_up, x, &resampled_data[i]); + nco_crcf_step(nco_ssb_shift_up); + } + break; + case DEMOD_TYPE_AM: + break; } - break; - case DemodulatorType::DEMOD_TYPE_USB: - for (int i = 0; i < num_written; i++) { - ampmodem_demodulate(ampdem_usb, resampled_data[i], &demod_output[i]); - } - - break; - case DemodulatorType::DEMOD_TYPE_AM: am_max = 0; + for (int i = 0; i < num_written; i++) { - ampmodem_demodulate(ampdem, resampled_data[i], &demod_output[i]); + ampmodem_demodulate(ampdem_active, resampled_data[i], &demod_output[i]); if (demod_output[i] > am_max) { am_max = demod_output[i]; } } - am_max_ma = am_max_ma + (am_max - am_max_ma) * 0.03; - am_max_maa = am_max_maa + (am_max_ma - am_max_maa) * 0.03; + am_max_ma = am_max_ma + (am_max - am_max_ma) * 0.05; + am_max_maa = am_max_maa + (am_max_ma - am_max_maa) * 0.05; - float gain = 0.95/am_max_maa; + float gain = 0.95 / am_max_maa; for (int i = 0; i < num_written; i++) { demod_output[i] *= gain; } - - break; } if (audio_out_size != resampled_audio_output.size()) { @@ -199,15 +223,15 @@ void DemodulatorThread::threadMain() { double freq = (2.0 * M_PI) * (((double) abs(38000)) / ((double) inp->bandwidth)); - if (shift_freq != freq) { - nco_crcf_set_frequency(nco_shift, freq); - shift_freq = freq; + if (nco_stereo_shift_freq != freq) { + nco_crcf_set_frequency(nco_stereo_shift, freq); + nco_stereo_shift_freq = freq; } for (int i = 0; i < num_written; i++) { firhilbf_r2c_execute(firR2C, demod_output[i], &x); - nco_crcf_mix_down(nco_shift, x, &y); - nco_crcf_step(nco_shift); + nco_crcf_mix_down(nco_stereo_shift, x, &y); + nco_crcf_step(nco_stereo_shift); firhilbf_c2r_execute(firC2R, y, &demod_output_stereo[i]); } @@ -310,6 +334,8 @@ void DemodulatorThread::threadMain() { visOutQueue->push(ati_vis); } if (!threadQueueControl->empty()) { + int newDemodType = DEMOD_TYPE_NULL; + while (!threadQueueControl->empty()) { DemodulatorThreadControlCommand command; threadQueueControl->pop(command); @@ -325,10 +351,30 @@ void DemodulatorThread::threadMain() { squelch_tolerance = 1; squelch_enabled = false; break; + case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE: + newDemodType = command.demodType; + break; default: break; } } + + if (newDemodType != DEMOD_TYPE_NULL) { + switch (newDemodType) { + case DEMOD_TYPE_FM: + break; + case DEMOD_TYPE_LSB: + ampdem_active = ampdem_lsb; + break; + case DEMOD_TYPE_USB: + ampdem_active = ampdem_usb; + break; + case DEMOD_TYPE_AM: + ampdem_active = ampdem; + break; + } + demodulatorType = newDemodType; + } } inp->decRefCount(); @@ -353,7 +399,11 @@ void DemodulatorThread::threadMain() { agc_crcf_destroy(agc); firhilbf_destroy(firR2C); firhilbf_destroy(firC2R); - nco_crcf_destroy(nco_shift); +// firhilbf_destroy(firR2Cssb); +// firhilbf_destroy(firC2Rssb); + nco_crcf_destroy(nco_stereo_shift); + nco_crcf_destroy(nco_ssb_shift_up); + nco_crcf_destroy(nco_ssb_shift_down); while (!buffers.empty()) { AudioThreadInput *audioDataDel = buffers.front(); @@ -397,10 +447,11 @@ float DemodulatorThread::getSquelchLevel() { return squelch_level; } -void DemodulatorThread::setDemodulatorType(DemodulatorType demod_type_in) { +void DemodulatorThread::setDemodulatorType(int demod_type_in) { demodulatorType = demod_type_in; } -DemodulatorType DemodulatorThread::getDemodulatorType() { +int DemodulatorThread::getDemodulatorType() { return demodulatorType; } + diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 8d7f5f1..0e59333 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -34,14 +34,15 @@ public: void initialize(); void terminate(); - void setStereo(bool state);bool isStereo(); + void setStereo(bool state); + bool isStereo(); float getSignalLevel(); void setSquelchLevel(float signal_level_in); float getSquelchLevel(); - void setDemodulatorType(DemodulatorType demod_type_in); - DemodulatorType getDemodulatorType(); + void setDemodulatorType(int demod_type_in); + int getDemodulatorType(); #ifdef __APPLE__ static void *pthread_helper(void *context) { @@ -66,6 +67,7 @@ protected: AudioThreadInputQueue *audioInputQueue; freqdem fdem; + ampmodem ampdem_active; ampmodem ampdem; ampmodem ampdem_usb; ampmodem ampdem_lsb; @@ -78,11 +80,12 @@ protected: std::atomic stereo; std::atomic terminated; - std::atomic demodulatorType; + std::atomic demodulatorType; DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadControlCommandQueue *threadQueueControl; std::atomic squelch_level; float squelch_tolerance; - std::atomic signal_level;bool squelch_enabled; + std::atomic signal_level; + bool squelch_enabled; }; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index 44c584a..a57f18f 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -47,7 +47,6 @@ void DemodulatorWorkerThread::threadMain() { result.bandwidth = filterCommand.bandwidth; result.inputRate = filterCommand.inputRate; resultQueue->push(result); - std::this_thread::sleep_for(std::chrono::milliseconds(30)); } } diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index 1d68c6c..41b1a48 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -48,12 +48,12 @@ private: fftw_complex *in, *out; fftw_plan plan; - float fft_ceil_ma, fft_ceil_maa; - float fft_floor_ma, fft_floor_maa; + double fft_ceil_ma, fft_ceil_maa; + double fft_floor_ma, fft_floor_maa; - std::vector fft_result; - std::vector fft_result_ma; - std::vector fft_result_maa; + std::vector fft_result; + std::vector fft_result_ma; + std::vector fft_result_maa; SpectrumContext *glContext; int fft_size; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 4c56c59..19078c2 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -17,9 +17,7 @@ #include -#define MIN_FM_BANDWIDTH 2000 -#define MIN_AM_BANDWIDTH 2000 - +#define MIN_BANDWIDTH 1500 wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) EVT_PAINT(WaterfallCanvas::OnPaint) EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown) @@ -36,7 +34,7 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE), parent(parent), spectrumCanvas(NULL), 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( + NULL), in(NULL), out(NULL), center_freq(0), bandwidth(0), isView(false), resampler(NULL), resample_ratio(0), last_bandwidth(0), last_input_bandwidth( 0) { glContext = new WaterfallContext(this, &wxGetApp().GetContext(this)); @@ -84,7 +82,7 @@ void WaterfallCanvas::Setup(int fft_size_in, int waterfall_lines_in) { if (plan) { fftw_destroy_plan(plan); } - plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE); + plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_ESTIMATE); glContext->Setup(fft_size, waterfall_lines); } @@ -133,7 +131,6 @@ void WaterfallCanvas::attachSpectrumCanvas(SpectrumCanvas *canvas_in) { spectrumCanvas = canvas_in; } - void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); const wxSize ClientSize = GetClientSize(); @@ -346,7 +343,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) { } if (!resampler || bandwidth != last_bandwidth || last_input_bandwidth != input->bandwidth) { - resample_ratio = (float) (bandwidth) / (float) input->bandwidth; + resample_ratio = (double) (bandwidth) / (double) input->bandwidth; float As = 60.0f; @@ -359,7 +356,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) { last_input_bandwidth = input->bandwidth; } - int out_size = ceil((float) (input->data.size()) * resample_ratio); + int out_size = ceil((double) (input->data.size()) * resample_ratio) + 32; if (resampler_buffer.size() != out_size) { if (resampler_buffer.capacity() < out_size) { @@ -373,14 +370,37 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) { resampler_buffer.resize(fft_size); - for (int i = 0; i < fft_size; i++) { - in[i][0] = resampler_buffer[i].real; - in[i][1] = resampler_buffer[i].imag; + if (num_written < fft_size) { + for (int i = 0; i < num_written; i++) { + in[i][0] = resampler_buffer[i].real; + in[i][1] = resampler_buffer[i].imag; + } + for (int i = num_written; i < fft_size; i++) { + in[i][0] = 0; + in[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + in[i][0] = resampler_buffer[i].real; + in[i][1] = resampler_buffer[i].imag; + } } } else { - for (int i = 0; i < fft_size; i++) { - in[i][0] = (*data)[i].real; - in[i][1] = (*data)[i].imag; + + if (data->size() < fft_size) { + for (int i = 0, iMax = data->size(); i < iMax; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; + } + for (int i = data->size(); i < fft_size; i++) { + in[i][0] = 0; + in[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; + } } } @@ -430,19 +450,19 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) { fft_floor -= 1; fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + double v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); 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()); + spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); } } } @@ -482,8 +502,8 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) { if (activeDemodulatorBandwidth > SRATE) { activeDemodulatorBandwidth = SRATE; } - if (activeDemodulatorBandwidth < MIN_FM_BANDWIDTH) { - activeDemodulatorBandwidth = MIN_FM_BANDWIDTH; + if (activeDemodulatorBandwidth < MIN_BANDWIDTH) { + activeDemodulatorBandwidth = MIN_BANDWIDTH; } command.int_value = activeDemodulatorBandwidth; @@ -673,8 +693,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 < MIN_FM_BANDWIDTH) { - bw = MIN_FM_BANDWIDTH; + if (bw < MIN_BANDWIDTH) { + bw = MIN_BANDWIDTH; } if (!bw) { diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 9656e32..556d50c 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -60,12 +60,12 @@ private: fftw_complex *in, *out; fftw_plan plan; - float fft_ceil_ma, fft_ceil_maa; - float fft_floor_ma, fft_floor_maa; + double fft_ceil_ma, fft_ceil_maa; + double fft_floor_ma, fft_floor_maa; - std::vector fft_result; - std::vector fft_result_ma; - std::vector fft_result_maa; + std::vector fft_result; + std::vector fft_result_ma; + std::vector fft_result_maa; WaterfallContext *glContext; MouseTracker mTracker; @@ -88,7 +88,7 @@ private: bool isView; msresamp_crcf resampler; - float resample_ratio; + double resample_ratio; nco_crcf nco_shift; int shift_freq;