mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-05-31 06:32:25 -04:00
Demodulator can now be initialized with parameters
This commit is contained in:
parent
7f5031b6e5
commit
dd42d112c9
@ -91,6 +91,7 @@ SET (cubicsdr_sources
|
|||||||
src/demod/DemodulatorThread.cpp
|
src/demod/DemodulatorThread.cpp
|
||||||
src/demod/DemodulatorThreadQueue.cpp
|
src/demod/DemodulatorThreadQueue.cpp
|
||||||
src/demod/DemodulatorThreadTask.cpp
|
src/demod/DemodulatorThreadTask.cpp
|
||||||
|
src/demod/DemodulatorMgr.cpp
|
||||||
src/audio/AudioThread.cpp
|
src/audio/AudioThread.cpp
|
||||||
src/audio/AudioThreadQueue.cpp
|
src/audio/AudioThreadQueue.cpp
|
||||||
src/audio/AudioThreadTask.cpp
|
src/audio/AudioThreadTask.cpp
|
||||||
@ -115,6 +116,7 @@ SET (cubicsdr_headers
|
|||||||
src/demod/DemodulatorThread.h
|
src/demod/DemodulatorThread.h
|
||||||
src/demod/DemodulatorThreadQueue.h
|
src/demod/DemodulatorThreadQueue.h
|
||||||
src/demod/DemodulatorThreadTask.h
|
src/demod/DemodulatorThreadTask.h
|
||||||
|
src/demod/DemodulatorMgr.h
|
||||||
src/audio/AudioThread.h
|
src/audio/AudioThread.h
|
||||||
src/audio/AudioThreadQueue.h
|
src/audio/AudioThreadQueue.h
|
||||||
src/audio/AudioThreadTask.h
|
src/audio/AudioThreadTask.h
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "SDRThread.h"
|
#include "SDRThread.h"
|
||||||
#include "DemodulatorThread.h"
|
#include "DemodulatorMgr.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
@ -65,14 +65,9 @@ AppFrame::AppFrame() :
|
|||||||
t_SDR = NULL;
|
t_SDR = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
threadQueueDemod = new DemodulatorThreadQueue(this);
|
demodulatorTest = demodMgr.newThread(this);
|
||||||
t_Demod = new DemodulatorThread(threadQueueDemod);
|
demodulatorTest->params.inputResampleRate=170000;
|
||||||
if (t_Demod->Run() != wxTHREAD_NO_ERROR) {
|
demodulatorTest->run();
|
||||||
wxLogError
|
|
||||||
("Can't create the Demodulator thread!");
|
|
||||||
delete t_Demod;
|
|
||||||
t_Demod = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
threadQueueAudio = new AudioThreadQueue(this);
|
threadQueueAudio = new AudioThreadQueue(this);
|
||||||
t_Audio = new AudioThread(threadQueueAudio);
|
t_Audio = new AudioThread(threadQueueAudio);
|
||||||
@ -102,7 +97,6 @@ AppFrame::~AppFrame() {
|
|||||||
|
|
||||||
// delete t_SDR;
|
// delete t_SDR;
|
||||||
delete threadQueueAudio;
|
delete threadQueueAudio;
|
||||||
delete threadQueueDemod;
|
|
||||||
delete threadQueueSDR;
|
delete threadQueueSDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +126,7 @@ void AppFrame::OnThread(wxCommandEvent& event) {
|
|||||||
if (new_uc_buffer->size()) {
|
if (new_uc_buffer->size()) {
|
||||||
DemodulatorThreadTask task = DemodulatorThreadTask(DemodulatorThreadTask::DEMOD_THREAD_DATA);
|
DemodulatorThreadTask task = DemodulatorThreadTask(DemodulatorThreadTask::DEMOD_THREAD_DATA);
|
||||||
task.data = new DemodulatorThreadIQData(iqData->bandwidth, iqData->frequency, iqData->data);
|
task.data = new DemodulatorThreadIQData(iqData->bandwidth, iqData->frequency, iqData->data);
|
||||||
threadQueueDemod->addTask(task, DemodulatorThreadQueue::DEMOD_PRIORITY_HIGHEST);
|
demodulatorTest->addTask(task, DemodulatorThreadQueue::DEMOD_PRIORITY_HIGHEST);
|
||||||
|
|
||||||
spectrumCanvas->setData(new_uc_buffer);
|
spectrumCanvas->setData(new_uc_buffer);
|
||||||
waterfallCanvas->setData(new_uc_buffer);
|
waterfallCanvas->setData(new_uc_buffer);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "PrimaryGLContext.h"
|
#include "PrimaryGLContext.h"
|
||||||
#include "SDRThread.h"
|
#include "SDRThread.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "DemodulatorThread.h"
|
#include "DemodulatorMgr.h"
|
||||||
|
|
||||||
#include "ScopeCanvas.h"
|
#include "ScopeCanvas.h"
|
||||||
#include "SpectrumCanvas.h"
|
#include "SpectrumCanvas.h"
|
||||||
@ -35,12 +35,13 @@ private:
|
|||||||
SDRThreadQueue* threadQueueSDR;
|
SDRThreadQueue* threadQueueSDR;
|
||||||
AudioThread *t_Audio;
|
AudioThread *t_Audio;
|
||||||
AudioThreadQueue* threadQueueAudio;
|
AudioThreadQueue* threadQueueAudio;
|
||||||
DemodulatorThread *t_Demod;
|
DemodulatorMgr demodMgr;
|
||||||
DemodulatorThreadQueue* threadQueueDemod;
|
|
||||||
|
|
||||||
wxCriticalSection m_pThreadCS;
|
wxCriticalSection m_pThreadCS;
|
||||||
unsigned int frequency;
|
unsigned int frequency;
|
||||||
|
|
||||||
|
DemodulatorInstance *demodulatorTest;
|
||||||
|
|
||||||
// event table
|
// event table
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
0
src/demod/DemodulatorMgr.cpp
Normal file
0
src/demod/DemodulatorMgr.cpp
Normal file
65
src/demod/DemodulatorMgr.h
Normal file
65
src/demod/DemodulatorMgr.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "DemodulatorThread.h"
|
||||||
|
#include "DemodulatorThreadQueue.h"
|
||||||
|
#include "DemodulatorThreadTask.h"
|
||||||
|
|
||||||
|
class DemodulatorInstance {
|
||||||
|
public:
|
||||||
|
DemodulatorThread *t_Demod;
|
||||||
|
DemodulatorThreadQueue* threadQueueDemod;
|
||||||
|
DemodulatorThreadParameters params;
|
||||||
|
wxEvtHandler* parent;
|
||||||
|
|
||||||
|
DemodulatorInstance(wxEvtHandler* pParent) :
|
||||||
|
t_Demod(NULL), threadQueueDemod(NULL), parent(pParent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
threadQueueDemod = new DemodulatorThreadQueue(parent);
|
||||||
|
t_Demod = new DemodulatorThread(threadQueueDemod, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTask(const DemodulatorThreadTask& task, const DemodulatorThreadQueue::DEMOD_PRIORITY& priority) {
|
||||||
|
threadQueueDemod->addTask(task, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run() {
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (t_Demod->Run() != wxTHREAD_NO_ERROR) {
|
||||||
|
wxLogError
|
||||||
|
("Can't create the Demodulator thread!");
|
||||||
|
delete t_Demod;
|
||||||
|
delete threadQueueDemod;
|
||||||
|
t_Demod = NULL;
|
||||||
|
threadQueueDemod = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DemodulatorMgr {
|
||||||
|
public:
|
||||||
|
DemodulatorMgr() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~DemodulatorMgr() {
|
||||||
|
while (demods.size()) {
|
||||||
|
DemodulatorInstance *d = demods.back();
|
||||||
|
demods.pop_back();
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DemodulatorInstance *newThread(wxEvtHandler* pParent) {
|
||||||
|
DemodulatorInstance *newDemod = new DemodulatorInstance(pParent);
|
||||||
|
demods.push_back(newDemod);
|
||||||
|
return newDemod;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DemodulatorInstance *> demods;
|
||||||
|
};
|
@ -3,17 +3,21 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorThreadQueue* pQueue, int id) :
|
DemodulatorThread::DemodulatorThread(DemodulatorThreadQueue* pQueue, DemodulatorThreadParameters *params_in, int id) :
|
||||||
wxThread(wxTHREAD_DETACHED), m_pQueue(pQueue), m_ID(id) {
|
wxThread(wxTHREAD_DETACHED), m_pQueue(pQueue), m_ID(id) {
|
||||||
|
|
||||||
bandwidth = 200000;
|
DemodulatorThreadParameters defaultParams;
|
||||||
resample_ratio = (float) (bandwidth) / (float) SRATE;
|
if (!params_in) {
|
||||||
wbfm_frequency = 100000;
|
params = defaultParams;
|
||||||
wbfm_resample_ratio = (float) (wbfm_frequency) / (float) bandwidth;
|
} else {
|
||||||
audio_frequency = AUDIO_FREQUENCY;
|
params = *params_in;
|
||||||
audio_resample_ratio = (float) (audio_frequency) / (float) wbfm_frequency;
|
}
|
||||||
|
|
||||||
float fc = 0.5f * ((float) bandwidth / (float) SRATE) * 0.75; // filter cutoff frequency
|
resample_ratio = (float) (params.inputResampleRate) / (float) params.inputRate;
|
||||||
|
second_resampler_ratio = (float) (params.demodResampleRate) / (float) params.inputResampleRate;
|
||||||
|
audio_resample_ratio = (float) (params.audioSampleRate) / (float) params.demodResampleRate;
|
||||||
|
|
||||||
|
float fc = 0.5f * ((float) params.inputResampleRate / (float) params.inputRate) * 0.75; // filter cutoff frequency
|
||||||
float ft = 0.05f; // filter transition
|
float ft = 0.05f; // filter transition
|
||||||
float As = 60.0f; // stop-band attenuation [dB]
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
float mu = 0.0f; // fractional timing offset
|
float mu = 0.0f; // fractional timing offset
|
||||||
@ -26,7 +30,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadQueue* pQueue, int id) :
|
|||||||
fir_filter = firfilt_crcf_create(h, h_len);
|
fir_filter = firfilt_crcf_create(h, h_len);
|
||||||
|
|
||||||
h_len = estimate_req_filter_len(ft, As);
|
h_len = estimate_req_filter_len(ft, As);
|
||||||
liquid_firdes_kaiser(h_len, 32000.0 / (float) wbfm_frequency, As, mu, h);
|
liquid_firdes_kaiser(h_len, (float)params.filterFrequency / (float) params.demodResampleRate, As, mu, h);
|
||||||
|
|
||||||
fir_audio_filter = firfilt_crcf_create(h, h_len);
|
fir_audio_filter = firfilt_crcf_create(h, h_len);
|
||||||
|
|
||||||
@ -34,8 +38,8 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadQueue* pQueue, int id) :
|
|||||||
resampler = msresamp_crcf_create(resample_ratio, As);
|
resampler = msresamp_crcf_create(resample_ratio, As);
|
||||||
msresamp_crcf_print(resampler);
|
msresamp_crcf_print(resampler);
|
||||||
|
|
||||||
wbfm_resampler = msresamp_crcf_create(wbfm_resample_ratio, As);
|
second_resampler = msresamp_crcf_create(second_resampler_ratio, As);
|
||||||
msresamp_crcf_print(wbfm_resampler);
|
msresamp_crcf_print(second_resampler);
|
||||||
|
|
||||||
audio_resampler = msresamp_crcf_create(audio_resample_ratio, As);
|
audio_resampler = msresamp_crcf_create(audio_resample_ratio, As);
|
||||||
msresamp_crcf_print(audio_resampler);
|
msresamp_crcf_print(audio_resampler);
|
||||||
@ -104,11 +108,11 @@ wxThread::ExitCode DemodulatorThread::Entry() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int wbfm_out_size = ceil((float) (num_written) * wbfm_resample_ratio);
|
int wbfm_out_size = ceil((float) (num_written) * second_resampler_ratio);
|
||||||
liquid_float_complex resampled_wbfm_output[wbfm_out_size];
|
liquid_float_complex resampled_wbfm_output[wbfm_out_size];
|
||||||
|
|
||||||
unsigned int num_wbfm_written;
|
unsigned int num_wbfm_written;
|
||||||
msresamp_crcf_execute(wbfm_resampler, resampled_output, num_written, resampled_wbfm_output, &num_wbfm_written);
|
msresamp_crcf_execute(second_resampler, resampled_output, num_written, resampled_wbfm_output, &num_wbfm_written);
|
||||||
|
|
||||||
for (int i = 0; i < num_wbfm_written; i++) {
|
for (int i = 0; i < num_wbfm_written; i++) {
|
||||||
firfilt_crcf_push(fir_audio_filter, resampled_wbfm_output[i]);
|
firfilt_crcf_push(fir_audio_filter, resampled_wbfm_output[i]);
|
||||||
@ -132,7 +136,7 @@ wxThread::ExitCode DemodulatorThread::Entry() {
|
|||||||
|
|
||||||
|
|
||||||
if (!TestDestroy()) {
|
if (!TestDestroy()) {
|
||||||
DemodulatorThreadAudioData *audioOut = new DemodulatorThreadAudioData(task.data->frequency,audio_frequency,newBuffer);
|
DemodulatorThreadAudioData *audioOut = new DemodulatorThreadAudioData(task.data->frequency,params.audioSampleRate,newBuffer);
|
||||||
|
|
||||||
m_pQueue->sendAudioData(DemodulatorThreadTask::DEMOD_THREAD_AUDIO_DATA,audioOut);
|
m_pQueue->sendAudioData(DemodulatorThreadTask::DEMOD_THREAD_AUDIO_DATA,audioOut);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
class DemodulatorThread: public wxThread {
|
class DemodulatorThread: public wxThread {
|
||||||
public:
|
public:
|
||||||
DemodulatorThread(DemodulatorThreadQueue* pQueue, int id = 0);
|
|
||||||
|
DemodulatorThread(DemodulatorThreadQueue* pQueue, DemodulatorThreadParameters *params, int id = 0);
|
||||||
~DemodulatorThread();
|
~DemodulatorThread();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -27,17 +28,15 @@ protected:
|
|||||||
firfilt_crcf fir_filter;
|
firfilt_crcf fir_filter;
|
||||||
firfilt_crcf fir_audio_filter;
|
firfilt_crcf fir_audio_filter;
|
||||||
|
|
||||||
unsigned int bandwidth;
|
|
||||||
msresamp_crcf resampler;
|
msresamp_crcf resampler;
|
||||||
float resample_ratio;
|
float resample_ratio;
|
||||||
|
|
||||||
unsigned int wbfm_frequency;
|
msresamp_crcf second_resampler;
|
||||||
msresamp_crcf wbfm_resampler;
|
float second_resampler_ratio;
|
||||||
float wbfm_resample_ratio;
|
|
||||||
|
|
||||||
unsigned int audio_frequency;
|
|
||||||
msresamp_crcf audio_resampler;
|
msresamp_crcf audio_resampler;
|
||||||
float audio_resample_ratio;
|
float audio_resample_ratio;
|
||||||
|
|
||||||
|
DemodulatorThreadParameters params;
|
||||||
freqdem fdem;
|
freqdem fdem;
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
#include "wx/defs.h"
|
#include "wx/defs.h"
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
#include "wx/object.h"
|
#include "wx/object.h"
|
||||||
|
#include "CubicSDRDefs.h"
|
||||||
|
|
||||||
|
enum DemodulatorType {
|
||||||
|
DEMOD_TYPE_NULL, DEMOD_TYPE_AM, DEMOD_TYPE_FM, DEMOD_TYPE_LSB, DEMOD_TYPE_USB, DEMOD_TYPE_WFM
|
||||||
|
};
|
||||||
|
|
||||||
class DemodulatorThreadIQData: public wxObject {
|
class DemodulatorThreadIQData: public wxObject {
|
||||||
public:
|
public:
|
||||||
@ -39,6 +44,25 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DemodulatorThreadParameters: public wxObject {
|
||||||
|
public:
|
||||||
|
unsigned int inputRate;
|
||||||
|
unsigned int inputResampleRate; // set equal to disable second stage re-sampling?
|
||||||
|
unsigned int demodResampleRate;
|
||||||
|
unsigned int filterFrequency;
|
||||||
|
unsigned int audioSampleRate;
|
||||||
|
DemodulatorType demodType;
|
||||||
|
|
||||||
|
DemodulatorThreadParameters() :
|
||||||
|
inputRate(SRATE), inputResampleRate(200000), demodResampleRate(100000), audioSampleRate(48000), filterFrequency(32000), demodType(DEMOD_TYPE_WFM) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~DemodulatorThreadParameters() {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class DemodulatorThreadTask {
|
class DemodulatorThreadTask {
|
||||||
public:
|
public:
|
||||||
enum DEMOD_THREAD_COMMAND {
|
enum DEMOD_THREAD_COMMAND {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user