Add input decimator to receiver.

This commit is contained in:
Alexandru Csete 2015-11-15 13:46:53 +01:00
parent fa0c49445c
commit 9c06cb58b8
3 changed files with 211 additions and 32 deletions

View File

@ -87,7 +87,7 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
d_filter_shape = receiver::FILTER_SHAPE_NORMAL;
/* create receiver object */
rx = new receiver("", "");
rx = new receiver("", "", 1);
rx->set_rf_freq(144500000.0f);
// remote controller
@ -367,7 +367,9 @@ MainWindow::~MainWindow()
*/
bool MainWindow::loadConfig(const QString cfgfile, bool check_crash)
{
double actual_rate;
qint64 int64_val;
int int_val;
bool bool_val;
bool conf_ok = false;
bool conv_ok;
@ -453,10 +455,10 @@ bool MainWindow::loadConfig(const QString cfgfile, bool check_crash)
QString outdev = m_settings->value("output/device", "").toString();
rx->set_output_device(outdev.toStdString());
int sr = m_settings->value("input/sample_rate", 0).toInt(&conv_ok);
if (conv_ok && (sr > 0))
int_val = m_settings->value("input/sample_rate", 0).toInt(&conv_ok);
if (conv_ok && (int_val > 0))
{
double actual_rate = rx->set_input_rate(sr);
actual_rate = rx->set_input_rate(int_val);
if (actual_rate == 0)
{
@ -472,19 +474,40 @@ bool MainWindow::loadConfig(const QString cfgfile, bool check_crash)
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
actual_rate = sr;
actual_rate = int_val;
}
qDebug() << "Requested sample rate:" << sr;
qDebug() << "Requested sample rate:" << int_val;
qDebug() << "Actual sample rate :" << QString("%1").arg(actual_rate, 0, 'f', 6);
uiDockRxOpt->setFilterOffsetRange((qint64)(0.9*actual_rate));
ui->plotter->setSampleRate(actual_rate);
ui->plotter->setSpanFreq((quint32)actual_rate);
remote->setBandwidth(sr);
iq_tool->setSampleRate(sr);
}
int_val = m_settings->value("input/decimation", 1).toInt(&conv_ok);
if (conv_ok && int_val >= 2)
{
if (rx->set_input_decim(int_val) != int_val)
{
qDebug() << "Failed to set decimation" << int_val;
qDebug() << " actual decimation:" << rx->get_input_decim();
}
else
{
// update actual rate
actual_rate /= (double)int_val;
qDebug() << "Input decimation:" << int_val;
qDebug() << "Quadrature rate:" << QString("%1").arg(actual_rate, 0, 'f', 6);
}
}
else
{
rx->set_input_decim(1);
}
// update various widget that need a sample rate
uiDockRxOpt->setFilterOffsetRange((qint64)(0.9*actual_rate));
ui->plotter->setSampleRate(actual_rate);
ui->plotter->setSpanFreq((quint32)actual_rate);
remote->setBandwidth((qint64)actual_rate);
iq_tool->setSampleRate((qint64)actual_rate);
int64_val = m_settings->value("input/bandwidth", 0).toInt(&conv_ok);
if (conv_ok)
{

View File

@ -32,6 +32,7 @@
#include "applications/gqrx/receiver.h"
#include "dsp/correct_iq_cc.h"
#include "dsp/hbf_decim.h"
#include "dsp/rx_fft.h"
#include "receivers/nbrx.h"
#include "receivers/wfmrx.h"
@ -49,10 +50,13 @@
* @param audio_device Audio output device specifier,
* e.g. hw:0 when using ALSA or Portaudio.
*/
receiver::receiver(const std::string input_device, const std::string audio_device)
receiver::receiver(const std::string input_device,
const std::string audio_device,
unsigned int decimation)
: d_running(false),
d_input_rate(96000.0),
d_audio_rate(48000),
d_decim(decimation),
d_rf_freq(144800000.0),
d_filter_offset(0.0),
d_recording_iq(false),
@ -77,21 +81,44 @@ receiver::receiver(const std::string input_device, const std::string audio_devic
src = osmosdr::source::make(input_device);
}
// input decimator
if (d_decim >= 2)
{
try
{
input_decim = make_hbf_decim(d_decim);
}
catch (std::range_error &e)
{
std::cout << "Error opening creating input decimator " << d_decim
<< ": " << e.what() << std::endl
<< "Using decimation 1." << std::endl;
d_decim = 1;
}
d_quad_rate = d_input_rate / (double)d_decim;
}
else
{
d_quad_rate = d_input_rate;
}
// create I/Q sink and close it
iq_sink = gr::blocks::file_sink::make(sizeof(gr_complex), "/dev/null", false);
iq_sink->set_unbuffered(true);
iq_sink->close();
rx = make_nbrx(d_input_rate, d_audio_rate);
lo = gr::analog::sig_source_c::make(d_input_rate, gr::analog::GR_SIN_WAVE,
rx = make_nbrx(d_quad_rate, d_audio_rate);
lo = gr::analog::sig_source_c::make(d_quad_rate, gr::analog::GR_SIN_WAVE,
0.0, 1.0);
mixer = gr::blocks::multiply_cc::make();
iq_swap = make_iq_swap_cc(false);
dc_corr = make_dc_corr_cc(d_input_rate, 1.0);
iq_fft = make_rx_fft_c(4096u, 0);
dc_corr = make_dc_corr_cc(d_quad_rate, 1.0);
iq_fft = make_rx_fft_c(8192u, 0);
audio_fft = make_rx_fft_f(4096u);
audio_fft = make_rx_fft_f(8192u);
audio_gain0 = gr::blocks::multiply_const_ff::make(0.1);
audio_gain1 = gr::blocks::multiply_const_ff::make(0.1);
@ -183,11 +210,28 @@ void receiver::set_input_device(const std::string device)
tb->wait();
}
tb->disconnect(src, 0, iq_swap, 0);
if (d_decim >= 2)
{
tb->disconnect(src, 0, input_decim, 0);
tb->disconnect(input_decim, 0, iq_swap, 0);
}
else
{
tb->disconnect(src, 0, iq_swap, 0);
}
src.reset();
src = osmosdr::source::make(device);
tb->connect(src, 0, iq_swap, 0);
if (d_decim >= 2)
{
tb->connect(src, 0, input_decim, 0);
tb->connect(input_decim, 0, iq_swap, 0);
}
else
{
tb->connect(src, 0, iq_swap, 0);
}
if (d_running)
tb->start();
@ -273,9 +317,10 @@ double receiver::set_input_rate(double rate)
d_input_rate = rate;
}
dc_corr->set_sample_rate(d_input_rate);
rx->set_quad_rate(d_input_rate);
lo->set_sampling_freq(d_input_rate);
d_quad_rate = d_input_rate / (double)d_decim;
dc_corr->set_sample_rate(d_quad_rate);
rx->set_quad_rate(d_quad_rate);
lo->set_sampling_freq(d_quad_rate);
tb->unlock();
return d_input_rate;
@ -288,6 +333,72 @@ double receiver::get_input_rate(void) const
return d_input_rate;
}
/** Set input decimation */
unsigned int receiver::set_input_decim(unsigned int decim)
{
if (decim == d_decim)
return d_decim;
if (d_running)
{
tb->stop();
tb->wait();
}
if (d_decim >= 2)
{
tb->disconnect(src, 0, input_decim, 0);
tb->disconnect(input_decim, 0, iq_swap, 0);
}
else
{
tb->disconnect(src, 0, iq_swap, 0);
}
input_decim.reset();
d_decim = decim;
if (d_decim >= 2)
{
try
{
input_decim = make_hbf_decim(d_decim);
}
catch (std::range_error &e)
{
std::cout << "Error opening creating input decimator " << d_decim
<< ": " << e.what() << std::endl
<< "Using decimation 1." << std::endl;
d_decim = 1;
}
d_quad_rate = d_input_rate / (double)d_decim;
}
else
{
d_quad_rate = d_input_rate;
}
// update quadrature rate
dc_corr->set_sample_rate(d_quad_rate);
rx->set_quad_rate(d_quad_rate);
lo->set_sampling_freq(d_quad_rate);
if (d_decim >= 2)
{
tb->connect(src, 0, input_decim, 0);
tb->connect(input_decim, 0, iq_swap, 0);
}
else
{
tb->connect(src, 0, iq_swap, 0);
}
if (d_running)
tb->start();
return d_decim;
}
/**
* @brief Set new analog bandwidth.
* @param bw The new bandwidth.
@ -991,7 +1102,11 @@ receiver::status receiver::start_iq_recording(const std::string filename)
}
else
{
tb->connect(src, 0, iq_sink, 0);
if (d_decim >= 2)
tb->connect(input_decim, 0, iq_sink, 0);
else
tb->connect(src, 0, iq_sink, 0);
d_recording_iq = true;
}
tb->unlock();
@ -1014,7 +1129,12 @@ receiver::status receiver::stop_iq_recording()
tb->lock();
iq_sink->close();
tb->disconnect(src, 0, iq_sink, 0);
if (d_decim >= 2)
tb->disconnect(input_decim, 0, iq_sink, 0);
else
tb->disconnect(src, 0, iq_sink, 0);
tb->unlock();
d_recording_iq = false;
@ -1102,7 +1222,15 @@ void receiver::connect_all(rx_chain type)
switch (type)
{
case RX_CHAIN_NONE:
tb->connect(src, 0, iq_swap, 0);
if (d_decim >= 2)
{
tb->connect(src, 0, input_decim, 0);
tb->connect(input_decim, 0, iq_swap, 0);
}
else
{
tb->connect(src, 0, iq_swap, 0);
}
if (d_dc_cancel)
{
tb->connect(iq_swap, 0, dc_corr, 0);
@ -1118,9 +1246,17 @@ void receiver::connect_all(rx_chain type)
if (rx->name() != "NBRX")
{
rx.reset();
rx = make_nbrx(d_input_rate, d_audio_rate);
rx = make_nbrx(d_quad_rate, d_audio_rate);
}
if (d_decim >= 2)
{
tb->connect(src, 0, input_decim, 0);
tb->connect(input_decim, 0, iq_swap, 0);
}
else
{
tb->connect(src, 0, iq_swap, 0);
}
tb->connect(src, 0, iq_swap, 0);
if (d_dc_cancel)
{
tb->connect(iq_swap, 0, dc_corr, 0);
@ -1146,9 +1282,17 @@ void receiver::connect_all(rx_chain type)
if (rx->name() != "WFMRX")
{
rx.reset();
rx = make_wfmrx(d_input_rate, d_audio_rate);
rx = make_wfmrx(d_quad_rate, d_audio_rate);
}
if (d_decim >= 2)
{
tb->connect(src, 0, input_decim, 0);
tb->connect(input_decim, 0, iq_swap, 0);
}
else
{
tb->connect(src, 0, iq_swap, 0);
}
tb->connect(src, 0, iq_swap, 0);
if (d_dc_cancel)
{
tb->connect(iq_swap, 0, dc_corr, 0);
@ -1177,7 +1321,10 @@ void receiver::connect_all(rx_chain type)
// reconnect recorders and sniffers
if (d_recording_iq)
{
tb->connect(src, 0, iq_sink, 0);
if (d_decim >= 2)
tb->connect(input_decim, 0, iq_sink, 0);
else
tb->connect(src, 0, iq_sink, 0);
}
if (d_recording_wav)

View File

@ -35,6 +35,7 @@
#include <string>
#include "dsp/correct_iq_cc.h"
#include "dsp/hbf_decim.h"
#include "dsp/rx_noise_blanker_cc.h"
#include "dsp/rx_filter.h"
#include "dsp/rx_meter.h"
@ -103,7 +104,9 @@ public:
FILTER_SHAPE_SHARP = 2 /*!< Sharp: Transition band is TBD of width. */
};
receiver(const std::string input_device="", const std::string audio_device="");
receiver(const std::string input_device="",
const std::string audio_device="",
unsigned int decimation=1);
~receiver();
void start();
@ -117,6 +120,9 @@ public:
double set_input_rate(double rate);
double get_input_rate(void) const;
unsigned int set_input_decim(unsigned int decim);
unsigned int get_input_decim(void) const { return d_decim; }
double set_analog_bandwidth(double bw);
double get_analog_bandwidth(void) const;
@ -212,7 +218,9 @@ private:
private:
bool d_running; /*!< Whether receiver is running or not. */
double d_input_rate; /*!< Input sample rate. */
double d_quad_rate; /*!< Quadrature rate (input_rate / decim) */
double d_audio_rate; /*!< Audio output rate. */
unsigned int d_decim; /*!< input decimation. */
double d_rf_freq; /*!< Current RF frequency. */
double d_filter_offset; /*!< Current filter offset */
bool d_recording_iq; /*!< Whether we are recording I/Q file. */
@ -230,6 +238,7 @@ private:
gr::top_block_sptr tb; /*!< The GNU Radio top block. */
osmosdr::source::sptr src; /*!< Real time I/Q source. */
hbf_decim_sptr input_decim; /*!< Input decimator. */
receiver_base_cf_sptr rx; /*!< receiver. */
dc_corr_cc_sptr dc_corr; /*!< DC corrector block. */