Demodulator can now tune offset!

Demodulator will up-convert / down-convert by mixing VCO with incoming
IQ to shift frequency -- No longer limited to center freq. can listen
anywhere on the waterfall.
This commit is contained in:
Charles J. Cliffe 2014-11-27 22:13:21 -05:00
parent df853bfd65
commit 1554348f55
4 changed files with 54 additions and 13 deletions

View File

@ -88,7 +88,7 @@ PrimaryGLContext& CubicSDR::GetContext(wxGLCanvas *canvas) {
void CubicSDR::setFrequency(unsigned int freq) {
frequency = freq;
demodulatorTest->getParams().frequency = freq;
// demodulatorTest->getParams().frequency = freq;
SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE);
command.int_value = freq;
threadCmdQueueSDR->push(command);

View File

@ -3,12 +3,16 @@
#include <vector>
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) :
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) {
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) {
float kf = 0.75; // modulation factor
fdem = freqdem_create(kf);
// freqdem_print(fdem);
nco_shift = nco_crcf_create(LIQUID_VCO);
shift_freq = 0;
}
void DemodulatorThread::initialize() {
@ -55,7 +59,6 @@ void DemodulatorThread::initialize() {
audio_resampler = msresamp_crcf_create(audio_resample_ratio, As);
// msresamp_crcf_print(audio_resampler);
initialized = true;
// std::cout << "inputResampleRate " << params.bandwidth << std::endl;
@ -82,7 +85,7 @@ void DemodulatorThread::threadMain() {
DemodulatorThreadCommand command;
commandQueue->pop(command);
switch (command.cmd) {
case DemodulatorThreadCommand::SDR_THREAD_CMD_SETBANDWIDTH:
case DemodulatorThreadCommand::SDR_THREAD_CMD_SET_BANDWIDTH:
if (command.int_value < 3000) {
command.int_value = 3000;
}
@ -92,6 +95,9 @@ void DemodulatorThread::threadMain() {
params.bandwidth = command.int_value;
paramsChanged = true;
break;
case DemodulatorThreadCommand::SDR_THREAD_CMD_SET_FREQUENCY:
params.frequency = command.int_value;
break;
}
}
@ -107,17 +113,42 @@ void DemodulatorThread::threadMain() {
continue;
}
// Requested frequency is not center, shift it into the center!
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)((float)(SRATE/2) * 1.5)) {
continue;
}
std::vector<signed char> *data = &inp.data;
if (data->size()) {
liquid_float_complex filtered_input[BUF_SIZE / 2];
liquid_float_complex x, y, z;
for (int i = 0; i < BUF_SIZE / 2; i++) {
if (shift_freq != 0) {
nco_crcf_step(nco_shift);
liquid_float_complex x;
liquid_float_complex y;
z.real = (float) (*data)[i * 2] / 127.0f;
z.imag = (float) (*data)[i * 2 + 1] / 127.0f;
x.real = (float) (*data)[i * 2] / 127.0f;
x.imag = (float) (*data)[i * 2 + 1] / 127.0f;
if (shift_freq < 0) {
nco_crcf_mix_up(nco_shift, z, &x);
} else {
nco_crcf_mix_down(nco_shift, z, &x);
}
} else {
x.real = (float) (*data)[i * 2] / 127.0f;
x.imag = (float) (*data)[i * 2 + 1] / 127.0f;
}
firfilt_crcf_push(fir_filter, x); // push input sample
firfilt_crcf_execute(fir_filter, &y); // compute output

View File

@ -23,7 +23,8 @@ class DemodulatorThreadCommand {
public:
enum DemodulatorThreadCommandEnum {
SDR_THREAD_CMD_NULL,
SDR_THREAD_CMD_SETBANDWIDTH
SDR_THREAD_CMD_SET_BANDWIDTH,
SDR_THREAD_CMD_SET_FREQUENCY
};
DemodulatorThreadCommand() : cmd(cmd), int_value(SDR_THREAD_CMD_NULL) {
@ -149,6 +150,9 @@ protected:
DemodulatorThreadParameters last_params;
freqdem fdem;
nco_crcf nco_shift;
int shift_freq;
std::atomic<bool> terminated;
std::atomic<bool> initialized;

View File

@ -199,7 +199,7 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
}
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SETBANDWIDTH;
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SET_BANDWIDTH;
demodBW = demodBW - bwDiff;
if (demodBW < 1000) {
demodBW = 1000;
@ -245,11 +245,17 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
float pos = mTracker.getMouseX();
int freq = wxGetApp().getFrequency();
int center_freq = wxGetApp().getFrequency();
freq += (pos - 0.5) * SRATE;
DemodulatorInstance *demod = wxGetApp().getDemodTest();
wxGetApp().setFrequency(freq);
int freq = center_freq - (int)(0.5 * (float)SRATE) + (int)((float)pos * (float)SRATE);
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::SDR_THREAD_CMD_SET_FREQUENCY;
command.int_value = freq;
demod->getCommandQueue()->push(command);
((wxFrame*) parent)->GetStatusBar()->SetStatusText(
wxString::Format(wxT("Set center frequency: %s"),