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_mbsatnogs_ax25_decoder_bmsatnogs_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);