From 0d5b2959694bdcd4875fbafd79526c76678f0bb8 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Sat, 13 Jan 2018 23:40:06 +0200 Subject: [PATCH] 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. --- grc/CMakeLists.txt | 2 +- grc/satnogs_block_tree.xml | 1 + grc/satnogs_quad_demod_filter_ff.xml | 34 ++++++ include/satnogs/CMakeLists.txt | 2 +- include/satnogs/quad_demod_filter_ff.h | 82 +++++++++++++++ lib/CMakeLists.txt | 3 +- lib/quad_demod_filter_ff_impl.cc | 140 +++++++++++++++++++++++++ lib/quad_demod_filter_ff_impl.h | 54 ++++++++++ swig/satnogs_swig0.i | 3 + 9 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 grc/satnogs_quad_demod_filter_ff.xml create mode 100644 include/satnogs/quad_demod_filter_ff.h create mode 100644 lib/quad_demod_filter_ff_impl.cc create mode 100644 lib/quad_demod_filter_ff_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 22ff453..122b647 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -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 ) diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml index c052cee..17f5742 100644 --- a/grc/satnogs_block_tree.xml +++ b/grc/satnogs_block_tree.xml @@ -29,4 +29,5 @@ satnogs_ax25_encoder_mb satnogs_ax25_decoder_bm satnogs_waterfall_sink + satnogs_quad_demod_filter_ff \ No newline at end of file diff --git a/grc/satnogs_quad_demod_filter_ff.xml b/grc/satnogs_quad_demod_filter_ff.xml new file mode 100644 index 0000000..f1be4c8 --- /dev/null +++ b/grc/satnogs_quad_demod_filter_ff.xml @@ -0,0 +1,34 @@ + + + Quadrature Demod Filter + satnogs_quad_demod_filter_ff + import satnogs + satnogs.quad_demod_filter_ff($thresh) + + + Threshold + thresh + math.pi + real + + + + + in + float + + + + + out + float + + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index 2e38fed..ea2a968 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -67,5 +67,5 @@ endif() install(FILES ${HEADER_FILES} - DESTINATION include/satnogs + quad_demod_filter_ff.h DESTINATION include/satnogs ) \ No newline at end of file diff --git a/include/satnogs/quad_demod_filter_ff.h b/include/satnogs/quad_demod_filter_ff.h new file mode 100644 index 0000000..d34d42d --- /dev/null +++ b/include/satnogs/quad_demod_filter_ff.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2018, Libre Space Foundation + * + * 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 . + */ + + +#ifndef INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_H +#define INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_H + +#include +#include + +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 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 */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 40f44e2..5fd37e5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -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}) diff --git a/lib/quad_demod_filter_ff_impl.cc b/lib/quad_demod_filter_ff_impl.cc new file mode 100644 index 0000000..f039123 --- /dev/null +++ b/lib/quad_demod_filter_ff_impl.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2018, Libre Space Foundation + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#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 */ + diff --git a/lib/quad_demod_filter_ff_impl.h b/lib/quad_demod_filter_ff_impl.h new file mode 100644 index 0000000..06fa2a7 --- /dev/null +++ b/lib/quad_demod_filter_ff_impl.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2018, Libre Space Foundation + * + * 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 . + */ + +#ifndef INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_IMPL_H +#define INCLUDED_SATNOGS_QUAD_DEMOD_FILTER_FF_IMPL_H + +#include + +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 */ + diff --git a/swig/satnogs_swig0.i b/swig/satnogs_swig0.i index 6f4c040..e73340a 100644 --- a/swig/satnogs_swig0.i +++ b/swig/satnogs_swig0.i @@ -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);