Add a quadrature demod filter

This is an attempt to cut the signal free period after the quadrature
demodulation block. The idea seems that works, but there still an issue
with the samples not passing correctly from the valve.
This commit is contained in:
Manolis Surligas 2018-01-13 23:40:06 +02:00
parent 0074fe7c10
commit 0d5b295969
9 changed files with 318 additions and 3 deletions

View File

@ -52,5 +52,5 @@ if(${INCLUDE_DEBUG_BLOCKS})
endif()
install(FILES
${enabled_blocks}
DESTINATION share/gnuradio/grc/blocks
satnogs_quad_demod_filter_ff.xml DESTINATION share/gnuradio/grc/blocks
)

View File

@ -29,4 +29,5 @@
<block>satnogs_ax25_encoder_mb</block>
<block>satnogs_ax25_decoder_bm</block>
<block>satnogs_waterfall_sink</block>
<block>satnogs_quad_demod_filter_ff</block>
</cat>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<block>
<name>Quadrature Demod Filter</name>
<key>satnogs_quad_demod_filter_ff</key>
<import>import satnogs</import>
<make>satnogs.quad_demod_filter_ff($thresh)</make>
<param>
<name>Threshold</name>
<key>thresh</key>
<value>math.pi</value>
<type>real</type>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out</name>
<type>float</type>
</source>
</block>

View File

@ -67,5 +67,5 @@ endif()
install(FILES
${HEADER_FILES}
DESTINATION include/satnogs
quad_demod_filter_ff.h DESTINATION include/satnogs
)

View File

@ -0,0 +1,82 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_H
#define INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_H
#include <satnogs/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace satnogs {
/*!
* \brief The goal of this block is to act as a valve for a signal
* commonly originating from a clock recovered quadrature demodulated stream.
*
* A very common problem in such cases, is that after the quadrature
* demodulation the signal is on the phase domain and the detection
* of signal presence or absence cannot be performed with energy detection.
* Why do we need to identify signal presence? Most of the amateur satellites
* uses quite poor and short training sequences, especially in the AX.25
* AFSK1200 mode. Thus, the decoders have too many false alarms and due to
* this, they miss frames.
*
* Some may argue that you can perform energy detection before the quadrature
* demodulation, but this implies a 'magic' threshold should be set.
* In the SatNOGS case, this is not possible. Every ground station is unique
* in terms of performance and RF characteristics. On the other hand the
* phase domain has the nice property that the signal level is known. This
* level can be +-pi. This block tries to find an SNR-like metric based
* on the variance and the mean of the signal.
* \ingroup satnogs
*
*/
class SATNOGS_API quad_demod_filter_ff : virtual public gr::block
{
public:
typedef boost::shared_ptr<quad_demod_filter_ff> sptr;
/**
* Creates a Quadrature Demodulate filter. The block will output samples
* only in signal presence acting as a valve to reduce false alarms of
* the FSK decoders.
*
* @param gain this MUST be the gain set on the quadrature demodulate
* gain or an appropriate value if the amplitude of the quadrature
* demodulated signal somehow is scaled. By default if the signal is
* on the +-pi region, the gain should be one. If it is on the +-2pi, the
* gain should be set to 2.0 etc.
*
* @param window the window size to calculate the moving average and
* variance.
*
* @return shared pointer of the block
*/
static sptr make(float gain, int window = 80);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_H */

View File

@ -64,7 +64,8 @@ list(APPEND satnogs_sources
ogg_source_impl.cc
noaa_apt_sink_impl.cc
frame_file_sink_impl.cc
iq_sink_impl.cc)
iq_sink_impl.cc
quad_demod_filter_ff_impl.cc)
if(${INCLUDE_DEBUG_BLOCKS})
list(APPEND satnogs_sources ${satnogs_debug_sources})

View File

@ -0,0 +1,140 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "quad_demod_filter_ff_impl.h"
namespace gr {
namespace satnogs {
quad_demod_filter_ff::sptr
quad_demod_filter_ff::make(float gain, int window)
{
return gnuradio::get_initial_sptr
(new quad_demod_filter_ff_impl(gain, window));
}
/*
* The private constructor
*/
quad_demod_filter_ff_impl::quad_demod_filter_ff_impl (float gain,
int window) :
gr::block ("quad_demod_filter_ff",
gr::io_signature::make (1, 1, sizeof(float)),
gr::io_signature::make (1, 1, sizeof(float))),
d_gain (gain),
d_norm (1.0f / window),
d_win (window),
d_sum (0.0f),
d_sum_sq (0.0f),
d_remaining (0)
{
if(window < 1) {
throw std::invalid_argument ("Window must be a positive");
}
set_history (2 * window);
}
/*
* Our virtual destructor.
*/
quad_demod_filter_ff_impl::~quad_demod_filter_ff_impl()
{
}
/**
* Fast approximation of the inverse of the square root.
* Thank you OpenArena!
* @param number the number to be computed
* @return the inverse of the square root of the number
*/
static inline float
inv_sqrt (float number)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = *(long *) &y;
i = 0x5f3759df - (i >> 1); /* what the fuck? */
y = *(float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
int
quad_demod_filter_ff_impl::general_work (
int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
int available = std::min(ninput_items[0], noutput_items);
int produced = 0;
float m;
float m_sq;
float snr;
float in_old;
float in_new;
float diff;
for(int i = 0; i < available; i++) {
in_old = std::abs(in[i + d_win]);
in_new = std::abs(in[i + 2*d_win - 1]);
d_sum -= in_old;
d_sum += in_new;
d_sum_sq -= (in_old * in_old);
d_sum_sq += (in_new * in_new);
m = (d_sum * d_norm);
m_sq = (d_sum_sq * d_norm);
snr = m * inv_sqrt(m_sq - m*m);
/*
* If the SNR is high enough start passing the data to the output.
* In order not to loose any samples due to the settling period, start
* from the buffered and let a window of samples to pass after the
* trigger is off
*/
if(snr > d_gain * 1.8) {
d_remaining = 2*d_win;
}
if(d_remaining) {
out[produced++] = in[i];
d_remaining--;
}
}
// Tell runtime system how many output items we produced.
consume_each(available);
return produced;
}
} /* namespace satnogs */
} /* namespace gr */

View File

@ -0,0 +1,54 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_IMPL_H
#define INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_IMPL_H
#include <satnogs/quad_demod_filter_ff.h>
namespace gr {
namespace satnogs {
class quad_demod_filter_ff_impl : public quad_demod_filter_ff
{
private:
const float d_gain;
const float d_norm;
const int d_win;
float d_sum;
float d_sum_sq;
int d_remaining;
public:
quad_demod_filter_ff_impl(float gain, int window);
~quad_demod_filter_ff_impl();
// Where all the action really happens
int
general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_IMPL_H */

View File

@ -31,6 +31,7 @@
#include "satnogs/noaa_apt_sink.h"
#include "satnogs/frame_file_sink.h"
#include "satnogs/iq_sink.h"
#include "satnogs/quad_demod_filter_ff.h"
%}
@ -97,3 +98,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, frame_file_sink);
%include "satnogs/iq_sink.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, iq_sink);
%include "satnogs/quad_demod_filter_ff.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, quad_demod_filter_ff);