mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 13:48:38 -05:00
Demodulator worker thread test
This commit is contained in:
parent
023002f009
commit
5fc5e4269c
@ -92,6 +92,7 @@ SET (cubicsdr_sources
|
|||||||
src/sdr/SDRThread.cpp
|
src/sdr/SDRThread.cpp
|
||||||
src/sdr/SDRPostThread.cpp
|
src/sdr/SDRPostThread.cpp
|
||||||
src/demod/DemodulatorThread.cpp
|
src/demod/DemodulatorThread.cpp
|
||||||
|
src/demod/DemodulatorWorkerThread.cpp
|
||||||
src/demod/DemodulatorMgr.cpp
|
src/demod/DemodulatorMgr.cpp
|
||||||
src/audio/AudioThread.cpp
|
src/audio/AudioThread.cpp
|
||||||
src/util/Gradient.cpp
|
src/util/Gradient.cpp
|
||||||
@ -113,6 +114,7 @@ SET (cubicsdr_headers
|
|||||||
src/sdr/SDRThread.h
|
src/sdr/SDRThread.h
|
||||||
src/sdr/SDRPostThread.h
|
src/sdr/SDRPostThread.h
|
||||||
src/demod/DemodulatorThread.h
|
src/demod/DemodulatorThread.h
|
||||||
|
src/demod/DemodulatorWorkerThread.h
|
||||||
src/demod/DemodulatorMgr.h
|
src/demod/DemodulatorMgr.h
|
||||||
src/audio/AudioThread.h
|
src/audio/AudioThread.h
|
||||||
src/util/Gradient.h
|
src/util/Gradient.h
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) :
|
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) :
|
||||||
inputQueue(pQueue), visOutQueue(NULL), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio(
|
inputQueue(pQueue), visOutQueue(NULL), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio(
|
||||||
1), resampler(NULL), commandQueue(NULL), fir_filter(NULL) {
|
1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL) {
|
||||||
|
|
||||||
float kf = 0.5; // modulation factor
|
float kf = 0.5; // modulation factor
|
||||||
fdem = freqdem_create(kf);
|
fdem = freqdem_create(kf);
|
||||||
@ -13,6 +13,11 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) :
|
|||||||
nco_shift = nco_crcf_create(LIQUID_VCO);
|
nco_shift = nco_crcf_create(LIQUID_VCO);
|
||||||
shift_freq = 0;
|
shift_freq = 0;
|
||||||
|
|
||||||
|
workerQueue = new DemodulatorThreadWorkerCommandQueue;
|
||||||
|
workerResults = new DemodulatorThreadWorkerResultQueue;
|
||||||
|
workerThread = new DemodulatorWorkerThread(workerQueue,workerResults);
|
||||||
|
|
||||||
|
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain,workerThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::initialize() {
|
void DemodulatorThread::initialize() {
|
||||||
@ -66,6 +71,9 @@ void DemodulatorThread::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThread::~DemodulatorThread() {
|
DemodulatorThread::~DemodulatorThread() {
|
||||||
|
delete workerThread;
|
||||||
|
delete workerQueue;
|
||||||
|
delete workerResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::threadMain() {
|
void DemodulatorThread::threadMain() {
|
||||||
@ -79,29 +87,40 @@ void DemodulatorThread::threadMain() {
|
|||||||
DemodulatorThreadIQData inp;
|
DemodulatorThreadIQData inp;
|
||||||
inputQueue->pop(inp);
|
inputQueue->pop(inp);
|
||||||
|
|
||||||
|
bool bandwidthChanged = false;
|
||||||
|
DemodulatorThreadParameters bandwidthParams = params;
|
||||||
|
|
||||||
if (!commandQueue->empty()) {
|
if (!commandQueue->empty()) {
|
||||||
bool paramsChanged = false;
|
bool paramsChanged = false;
|
||||||
while (!commandQueue->empty()) {
|
while (!commandQueue->empty()) {
|
||||||
DemodulatorThreadCommand command;
|
DemodulatorThreadCommand command;
|
||||||
commandQueue->pop(command);
|
commandQueue->pop(command);
|
||||||
switch (command.cmd) {
|
switch (command.cmd) {
|
||||||
case DemodulatorThreadCommand::SDR_THREAD_CMD_SET_BANDWIDTH:
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH:
|
||||||
if (command.int_value < 3000) {
|
if (command.int_value < 3000) {
|
||||||
command.int_value = 3000;
|
command.int_value = 3000;
|
||||||
}
|
}
|
||||||
if (command.int_value > SRATE) {
|
if (command.int_value > SRATE) {
|
||||||
command.int_value = SRATE;
|
command.int_value = SRATE;
|
||||||
}
|
}
|
||||||
params.bandwidth = command.int_value;
|
bandwidthParams.bandwidth = command.int_value;
|
||||||
paramsChanged = true;
|
bandwidthChanged = true;
|
||||||
break;
|
break;
|
||||||
case DemodulatorThreadCommand::SDR_THREAD_CMD_SET_FREQUENCY:
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY:
|
||||||
params.frequency = command.int_value;
|
params.frequency = command.int_value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paramsChanged) {
|
if (bandwidthChanged) {
|
||||||
|
// DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS);
|
||||||
|
// command.audioSampleRate = bandwidthParams.audioSampleRate;
|
||||||
|
// command.bandwidth = bandwidthParams.bandwidth;
|
||||||
|
// command.frequency = bandwidthParams.frequency;
|
||||||
|
// command.inputRate = bandwidthParams.inputRate;
|
||||||
|
//
|
||||||
|
// workerQueue->push(command);
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
while (!inputQueue->empty()) { // catch up
|
while (!inputQueue->empty()) { // catch up
|
||||||
inputQueue->pop(inp);
|
inputQueue->pop(inp);
|
||||||
@ -206,4 +225,7 @@ void DemodulatorThread::terminate() {
|
|||||||
terminated = true;
|
terminated = true;
|
||||||
DemodulatorThreadIQData inp; // push dummy to nudge queue
|
DemodulatorThreadIQData inp; // push dummy to nudge queue
|
||||||
inputQueue->push(inp);
|
inputQueue->push(inp);
|
||||||
|
|
||||||
|
workerThread->terminate();
|
||||||
|
t_Worker->join();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "ThreadQueue.h"
|
#include "ThreadQueue.h"
|
||||||
#include "CubicSDRDefs.h"
|
#include "CubicSDRDefs.h"
|
||||||
|
#include "DemodulatorWorkerThread.h"
|
||||||
|
|
||||||
enum DemodulatorType {
|
enum DemodulatorType {
|
||||||
DEMOD_TYPE_NULL, DEMOD_TYPE_AM, DEMOD_TYPE_FM, DEMOD_TYPE_LSB, DEMOD_TYPE_USB
|
DEMOD_TYPE_NULL, DEMOD_TYPE_AM, DEMOD_TYPE_FM, DEMOD_TYPE_LSB, DEMOD_TYPE_USB
|
||||||
@ -22,11 +23,11 @@ enum DemodulatorType {
|
|||||||
class DemodulatorThreadCommand {
|
class DemodulatorThreadCommand {
|
||||||
public:
|
public:
|
||||||
enum DemodulatorThreadCommandEnum {
|
enum DemodulatorThreadCommandEnum {
|
||||||
SDR_THREAD_CMD_NULL, SDR_THREAD_CMD_SET_BANDWIDTH, SDR_THREAD_CMD_SET_FREQUENCY
|
DEMOD_THREAD_CMD_NULL, DEMOD_THREAD_CMD_SET_BANDWIDTH, DEMOD_THREAD_CMD_SET_FREQUENCY
|
||||||
};
|
};
|
||||||
|
|
||||||
DemodulatorThreadCommand() :
|
DemodulatorThreadCommand() :
|
||||||
cmd(cmd), int_value(SDR_THREAD_CMD_NULL) {
|
cmd(DEMOD_THREAD_CMD_NULL), int_value(0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +107,7 @@ typedef ThreadQueue<DemodulatorThreadIQData> DemodulatorThreadInputQueue;
|
|||||||
typedef ThreadQueue<AudioThreadInput> DemodulatorThreadOutputQueue;
|
typedef ThreadQueue<AudioThreadInput> DemodulatorThreadOutputQueue;
|
||||||
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
|
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
|
||||||
|
|
||||||
|
|
||||||
class DemodulatorThread {
|
class DemodulatorThread {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -158,4 +160,10 @@ protected:
|
|||||||
|
|
||||||
std::atomic<bool> terminated;
|
std::atomic<bool> terminated;
|
||||||
std::atomic<bool> initialized;
|
std::atomic<bool> initialized;
|
||||||
|
|
||||||
|
DemodulatorWorkerThread *workerThread;
|
||||||
|
std::thread *t_Worker;
|
||||||
|
|
||||||
|
DemodulatorThreadWorkerCommandQueue *workerQueue;
|
||||||
|
DemodulatorThreadWorkerResultQueue *workerResults;
|
||||||
};
|
};
|
||||||
|
78
src/demod/DemodulatorWorkerThread.cpp
Normal file
78
src/demod/DemodulatorWorkerThread.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "DemodulatorWorkerThread.h"
|
||||||
|
#include "CubicSDRDefs.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
DemodulatorWorkerThread::DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out) :
|
||||||
|
terminated(false), commandQueue(in), resultQueue(out) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorWorkerThread::threadMain() {
|
||||||
|
|
||||||
|
std::cout << "Demodulator worker thread started.." << std::endl;
|
||||||
|
|
||||||
|
while (!terminated) {
|
||||||
|
bool filterChanged = false;
|
||||||
|
DemodulatorWorkerThreadCommand filterCommand;
|
||||||
|
DemodulatorWorkerThreadCommand command;
|
||||||
|
DemodulatorWorkerThreadResult result;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
while (!done) {
|
||||||
|
commandQueue->pop(command);
|
||||||
|
switch (command.cmd) {
|
||||||
|
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS:
|
||||||
|
filterChanged = true;
|
||||||
|
filterCommand = command;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
done = commandQueue->empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterChanged) {
|
||||||
|
result.cmd = 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;
|
||||||
|
|
||||||
|
float fc = 0.5 * ((double) filterCommand.bandwidth / (double) filterCommand.inputRate); // filter cutoff frequency
|
||||||
|
|
||||||
|
if (fc <= 0) {
|
||||||
|
fc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fc >= 0.5) {
|
||||||
|
fc = 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ft = 0.05f; // filter transition
|
||||||
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
|
float mu = 0.0f; // fractional timing offset
|
||||||
|
|
||||||
|
// estimate required filter length and generate filter
|
||||||
|
unsigned int h_len = estimate_req_filter_len(ft, As);
|
||||||
|
float h[h_len];
|
||||||
|
liquid_firdes_kaiser(h_len, fc, As, mu, h);
|
||||||
|
|
||||||
|
result.fir_filter = firfilt_crcf_create(h, h_len);
|
||||||
|
|
||||||
|
result.resampler = msresamp_crcf_create(result.resample_ratio, As);
|
||||||
|
result.audio_resampler = msresamp_crcf_create(result.audio_resample_ratio, As);
|
||||||
|
// msresamp_crcf_print(audio_resampler);
|
||||||
|
|
||||||
|
resultQueue->push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Demodulator worker thread done." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemodulatorWorkerThread::terminate() {
|
||||||
|
terminated = true;
|
||||||
|
DemodulatorWorkerThreadCommand inp; // push dummy to nudge queue
|
||||||
|
commandQueue->push(inp);
|
||||||
|
}
|
100
src/demod/DemodulatorWorkerThread.h
Normal file
100
src/demod/DemodulatorWorkerThread.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/wx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wx/thread.h"
|
||||||
|
|
||||||
|
#include "liquid/liquid.h"
|
||||||
|
#include "AudioThread.h"
|
||||||
|
#include "ThreadQueue.h"
|
||||||
|
#include "CubicSDRDefs.h"
|
||||||
|
|
||||||
|
class DemodulatorWorkerThreadResult {
|
||||||
|
public:
|
||||||
|
enum DemodulatorThreadResultEnum {
|
||||||
|
DEMOD_WORKER_THREAD_RESULT_NULL, DEMOD_WORKER_THREAD_RESULT_FILTERS
|
||||||
|
};
|
||||||
|
|
||||||
|
DemodulatorWorkerThreadResult() :
|
||||||
|
cmd(DEMOD_WORKER_THREAD_RESULT_NULL), audioSampleRate(0), bandwidth(0), inputRate(0), fir_filter(NULL), resampler(NULL), resample_ratio(
|
||||||
|
0), audio_resampler(NULL), audio_resample_ratio(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DemodulatorWorkerThreadResult(DemodulatorThreadResultEnum cmd) :
|
||||||
|
cmd(cmd), audioSampleRate(0), bandwidth(0), inputRate(0), fir_filter(NULL), resampler(NULL), resample_ratio(0), audio_resampler(NULL), audio_resample_ratio(
|
||||||
|
0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
firfilt_crcf fir_filter;
|
||||||
|
msresamp_crcf resampler;
|
||||||
|
float resample_ratio;
|
||||||
|
msresamp_crcf audio_resampler;
|
||||||
|
float audio_resample_ratio;
|
||||||
|
|
||||||
|
unsigned int inputRate;
|
||||||
|
unsigned int bandwidth;
|
||||||
|
unsigned int audioSampleRate;
|
||||||
|
|
||||||
|
DemodulatorThreadResultEnum cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DemodulatorWorkerThreadCommand {
|
||||||
|
public:
|
||||||
|
enum DemodulatorThreadCommandEnum {
|
||||||
|
DEMOD_WORKER_THREAD_CMD_NULL, DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS
|
||||||
|
};
|
||||||
|
|
||||||
|
DemodulatorWorkerThreadCommand() :
|
||||||
|
cmd(DEMOD_WORKER_THREAD_CMD_NULL), frequency(0), inputRate(0), bandwidth(0), audioSampleRate(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DemodulatorWorkerThreadCommand(DemodulatorThreadCommandEnum cmd) :
|
||||||
|
cmd(cmd), frequency(0), inputRate(0), bandwidth(0), audioSampleRate(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int frequency;
|
||||||
|
unsigned int inputRate;
|
||||||
|
unsigned int bandwidth;
|
||||||
|
unsigned int audioSampleRate;
|
||||||
|
|
||||||
|
DemodulatorThreadCommandEnum cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
|
||||||
|
typedef ThreadQueue<DemodulatorWorkerThreadResult> DemodulatorThreadWorkerResultQueue;
|
||||||
|
|
||||||
|
class DemodulatorWorkerThread {
|
||||||
|
public:
|
||||||
|
|
||||||
|
DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out);
|
||||||
|
~DemodulatorWorkerThread();
|
||||||
|
|
||||||
|
void threadMain();
|
||||||
|
|
||||||
|
void setCommandQueue(DemodulatorThreadWorkerCommandQueue *tQueue) {
|
||||||
|
commandQueue = tQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setResultQueue(DemodulatorThreadWorkerResultQueue *tQueue) {
|
||||||
|
resultQueue = tQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
DemodulatorThreadWorkerCommandQueue *commandQueue;
|
||||||
|
DemodulatorThreadWorkerResultQueue *resultQueue;
|
||||||
|
|
||||||
|
std::atomic<bool> terminated;
|
||||||
|
};
|
@ -21,7 +21,7 @@ public:
|
|||||||
SDR_THREAD_CMD_TUNE
|
SDR_THREAD_CMD_TUNE
|
||||||
};
|
};
|
||||||
|
|
||||||
SDRThreadCommand() : cmd(cmd), int_value(SDR_THREAD_CMD_NULL) {
|
SDRThreadCommand() : cmd(SDR_THREAD_CMD_NULL), int_value(0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThreadCommand command;
|
DemodulatorThreadCommand command;
|
||||||
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SET_BANDWIDTH;
|
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
||||||
activeDemodulatorBandwidth = activeDemodulatorBandwidth + bwDiff;
|
activeDemodulatorBandwidth = activeDemodulatorBandwidth + bwDiff;
|
||||||
if (activeDemodulatorBandwidth < 1000) {
|
if (activeDemodulatorBandwidth < 1000) {
|
||||||
activeDemodulatorBandwidth = 1000;
|
activeDemodulatorBandwidth = 1000;
|
||||||
@ -242,7 +242,7 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThreadCommand command;
|
DemodulatorThreadCommand command;
|
||||||
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SET_FREQUENCY;
|
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
||||||
activeDemodulatorFrequency = activeDemodulatorFrequency + bwDiff;
|
activeDemodulatorFrequency = activeDemodulatorFrequency + bwDiff;
|
||||||
|
|
||||||
command.int_value = activeDemodulatorFrequency;
|
command.int_value = activeDemodulatorFrequency;
|
||||||
@ -327,7 +327,7 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
|
|||||||
int freq = center_freq - (int) (0.5 * (float) SRATE) + (int) ((float) pos * (float) SRATE);
|
int freq = center_freq - (int) (0.5 * (float) SRATE) + (int) ((float) pos * (float) SRATE);
|
||||||
|
|
||||||
DemodulatorThreadCommand command;
|
DemodulatorThreadCommand command;
|
||||||
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SET_FREQUENCY;
|
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
||||||
command.int_value = freq;
|
command.int_value = freq;
|
||||||
|
|
||||||
demod->getCommandQueue()->push(command);
|
demod->getCommandQueue()->push(command);
|
||||||
|
Loading…
Reference in New Issue
Block a user