summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-digital/CMakeLists.txt2
-rw-r--r--gr-digital/include/digital/CMakeLists.txt4
-rw-r--r--gr-digital/include/digital/clock_recovery_mm_cc.h72
-rw-r--r--gr-digital/include/digital/clock_recovery_mm_ff.h69
-rw-r--r--gr-digital/include/digital_clock_recovery_mm_cc.h117
-rw-r--r--gr-digital/include/digital_clock_recovery_mm_ff.h100
-rw-r--r--gr-digital/lib/CMakeLists.txt7
-rw-r--r--gr-digital/lib/clock_recovery_mm_cc_impl.cc213
-rw-r--r--gr-digital/lib/clock_recovery_mm_cc_impl.h87
-rw-r--r--gr-digital/lib/clock_recovery_mm_ff_impl.cc120
-rw-r--r--gr-digital/lib/clock_recovery_mm_ff_impl.h81
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_cc.cc217
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_ff.cc139
-rw-r--r--gr-digital/swig/digital_clock_recovery_mm_cc.i51
-rw-r--r--gr-digital/swig/digital_clock_recovery_mm_ff.i47
-rw-r--r--gr-digital/swig/digital_swig.i7
16 files changed, 656 insertions, 677 deletions
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt
index 05a9bc6874..df755b4290 100644
--- a/gr-digital/CMakeLists.txt
+++ b/gr-digital/CMakeLists.txt
@@ -29,6 +29,8 @@ include(GrComponent)
GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL
Boost_FOUND
ENABLE_GR_CORE
+ ENABLE_GR_FFT
+ ENABLE_GR_FILTER
)
GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS
diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt
index 8eb5eef883..4dadbcc8cc 100644
--- a/gr-digital/include/digital/CMakeLists.txt
+++ b/gr-digital/include/digital/CMakeLists.txt
@@ -80,8 +80,8 @@ install(FILES
# impl_mpsk_snr_est.h
additive_scrambler_bb.h
binary_slicer_fb.h
-# clock_recovery_mm_cc.h
-# clock_recovery_mm_ff.h
+ clock_recovery_mm_cc.h
+ clock_recovery_mm_ff.h
# cma_equalizer_cc.h
# cpmmod_bc.h
# constellation.h
diff --git a/gr-digital/include/digital/clock_recovery_mm_cc.h b/gr-digital/include/digital/clock_recovery_mm_cc.h
new file mode 100644
index 0000000000..783e7e6ad9
--- /dev/null
+++ b/gr-digital/include/digital/clock_recovery_mm_cc.h
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H
+
+#include <digital/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * This implements the Mueller and Müller (M&M) discrete-time
+ * error-tracking synchronizer.
+ *
+ * The complex version here is based on: Modified Mueller and
+ * Muller clock recovery circuit:
+ *
+ * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
+ * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
+ * June 1995, pp. 1032 - 1033.
+ */
+ class DIGITAL_API clock_recovery_mm_cc : virtual public gr_block
+ {
+ public:
+ // gr::digital::clock_recovery_mm_cc::sptr
+ typedef boost::shared_ptr<clock_recovery_mm_cc> sptr;
+
+ sptr make(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limi);
+
+ virtual float mu() const = 0;
+ virtual float omega() const = 0;
+ virtual float gain_mu() const = 0;
+ virtual float gain_omega() const = 0;
+
+ virtual void set_verbose(bool verbose) = 0;
+ virtual void set_gain_mu (float gain_mu) = 0;
+ virtual void set_gain_omega (float gain_omega) = 0;
+ virtual void set_mu (float mu) = 0;
+ virtual void set_omega (float omega) = 0;
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H */
diff --git a/gr-digital/include/digital/clock_recovery_mm_ff.h b/gr-digital/include/digital/clock_recovery_mm_ff.h
new file mode 100644
index 0000000000..3ef9590e60
--- /dev/null
+++ b/gr-digital/include/digital/clock_recovery_mm_ff.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H
+
+#include <digital/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * This implements the Mueller and Müller (M&M) discrete-time
+ * error-tracking synchronizer.
+ *
+ * See "Digital Communication Receivers: Synchronization, Channel
+ * Estimation and Signal Processing" by Heinrich Meyr, Marc
+ * Moeneclaey, & Stefan Fechtel. ISBN 0-471-50275-8.
+ */
+ class DIGITAL_API clock_recovery_mm_ff : virtual public gr_block
+ {
+ public:
+ // gr::digital::clock_recovery_mm_ff::sptr
+ typedef boost::shared_ptr<clock_recovery_mm_ff> sptr;
+
+ sptr make(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit);
+
+ virtual float mu() const = 0;
+ virtual float omega() const = 0;
+ virtual float gain_mu() const = 0;
+ virtual float gain_omega() const = 0;
+
+ virtual void set_verbose(bool verbose) = 0;
+ virtual void set_gain_mu (float gain_mu) = 0;
+ virtual void set_gain_omega (float gain_omega) = 0;
+ virtual void set_mu (float mu) = 0;
+ virtual void set_omega (float omega) = 0;
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H */
diff --git a/gr-digital/include/digital_clock_recovery_mm_cc.h b/gr-digital/include/digital_clock_recovery_mm_cc.h
deleted file mode 100644
index a2577d5378..0000000000
--- a/gr-digital/include/digital_clock_recovery_mm_cc.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H
-#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H
-
-#include <digital_api.h>
-#include <gr_block.h>
-#include <gr_complex.h>
-#include <gr_math.h>
-
-class gri_mmse_fir_interpolator_cc;
-
-class digital_clock_recovery_mm_cc;
-typedef boost::shared_ptr<digital_clock_recovery_mm_cc> digital_clock_recovery_mm_cc_sptr;
-
-// public constructor
-DIGITAL_API digital_clock_recovery_mm_cc_sptr
-digital_make_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit=0.001);
-
-/*!
- * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output.
- * \ingroup sync_blk
- * \ingroup digital
- *
- * This implements the Mueller and Müller (M&M) discrete-time
- * error-tracking synchronizer.
- *
- * The complex version here is based on:
- * Modified Mueller and Muller clock recovery circuit
- * Based:
- * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
- * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
- * June 1995, pp. 1032 - 1033.
- */
-class DIGITAL_API digital_clock_recovery_mm_cc : public gr_block
-{
- public:
- ~digital_clock_recovery_mm_cc ();
- void forecast(int noutput_items, gr_vector_int &ninput_items_required);
- int general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- float mu() const { return d_mu;}
- float omega() const { return d_omega;}
- float gain_mu() const { return d_gain_mu;}
- float gain_omega() const { return d_gain_omega;}
- void set_verbose (bool verbose) { d_verbose = verbose; }
-
- void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
- void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
- void set_mu (float mu) { d_mu = mu; }
- void set_omega (float omega) {
- d_omega = omega;
- d_min_omega = omega*(1.0 - d_omega_relative_limit);
- d_max_omega = omega*(1.0 + d_omega_relative_limit);
- d_omega_mid = 0.5*(d_min_omega+d_max_omega);
- }
-
-protected:
- digital_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limi);
-
- private:
- float d_mu;
- float d_omega;
- float d_gain_omega;
- float d_min_omega; // minimum allowed omega
- float d_max_omega; // maximum allowed omeg
- float d_omega_relative_limit; // used to compute min and max omega
- float d_omega_mid;
- float d_gain_mu;
- gr_complex d_last_sample;
- gri_mmse_fir_interpolator_cc *d_interp;
- bool d_verbose;
-
- gr_complex d_p_2T;
- gr_complex d_p_1T;
- gr_complex d_p_0T;
-
- gr_complex d_c_2T;
- gr_complex d_c_1T;
- gr_complex d_c_0T;
-
- gr_complex slicer_0deg (gr_complex sample);
- gr_complex slicer_45deg (gr_complex sample);
-
- friend DIGITAL_API digital_clock_recovery_mm_cc_sptr
- digital_make_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit);
-};
-
-#endif
diff --git a/gr-digital/include/digital_clock_recovery_mm_ff.h b/gr-digital/include/digital_clock_recovery_mm_ff.h
deleted file mode 100644
index 36749553fb..0000000000
--- a/gr-digital/include/digital_clock_recovery_mm_ff.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H
-#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H
-
-#include <digital_api.h>
-#include <gr_block.h>
-#include <gr_math.h>
-#include <stdio.h>
-
-class gri_mmse_fir_interpolator;
-
-class digital_clock_recovery_mm_ff;
-typedef boost::shared_ptr<digital_clock_recovery_mm_ff> digital_clock_recovery_mm_ff_sptr;
-
-// public constructor
-DIGITAL_API digital_clock_recovery_mm_ff_sptr
-digital_make_clock_recovery_mm_ff (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit=0.001);
-
-/*!
- * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output.
- * \ingroup sync_blk
- * \ingroup digital
- *
- * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer.
- *
- * See "Digital Communication Receivers: Synchronization, Channel
- * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel.
- * ISBN 0-471-50275-8.
- */
-class DIGITAL_API digital_clock_recovery_mm_ff : public gr_block
-{
- public:
- ~digital_clock_recovery_mm_ff ();
- void forecast(int noutput_items, gr_vector_int &ninput_items_required);
- int general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- float mu() const { return d_mu;}
- float omega() const { return d_omega;}
- float gain_mu() const { return d_gain_mu;}
- float gain_omega() const { return d_gain_omega;}
-
- void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
- void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
- void set_mu (float mu) { d_mu = mu; }
- void set_omega (float omega){
- d_omega = omega;
- d_min_omega = omega*(1.0 - d_omega_relative_limit);
- d_max_omega = omega*(1.0 + d_omega_relative_limit);
- d_omega_mid = 0.5*(d_min_omega+d_max_omega);
- }
-
-protected:
- digital_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu,
- float omega_relative_limit);
-
- private:
- float d_mu; // fractional sample position [0.0, 1.0]
- float d_omega; // nominal frequency
- float d_min_omega; // minimum allowed omega
- float d_omega_mid; // average omega
- float d_max_omega; // maximum allowed omega
- float d_gain_omega; // gain for adjusting omega
- float d_gain_mu; // gain for adjusting mu
- float d_last_sample;
- gri_mmse_fir_interpolator *d_interp;
- FILE *d_logfile;
- float d_omega_relative_limit; // used to compute min and max omega
-
- friend DIGITAL_API digital_clock_recovery_mm_ff_sptr
- digital_make_clock_recovery_mm_ff (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit);
-};
-
-#endif
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index d016570158..56bc1335a8 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -23,13 +23,14 @@
include_directories(
${GNURADIO_CORE_INCLUDE_DIRS}
${GR_DIGITAL_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR}/../include
)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
-
########################################################################
# generate helper scripts to expand templated files
########################################################################
@@ -95,8 +96,8 @@ list(APPEND gr_digital_sources
#impl_mpsk_snr_est.cc
additive_scrambler_bb_impl.cc
binary_slicer_fb_impl.cc
- #clock_recovery_mm_cc_impl.cc
- #clock_recovery_mm_ff_impl.cc
+ clock_recovery_mm_cc_impl.cc
+ clock_recovery_mm_ff_impl.cc
#cma_equalizer_cc_impl.cc
#constellation_impl.cc
#constellation_receiver_cb_impl.cc
diff --git a/gr-digital/lib/clock_recovery_mm_cc_impl.cc b/gr-digital/lib/clock_recovery_mm_cc_impl.cc
new file mode 100644
index 0000000000..28376f8e5f
--- /dev/null
+++ b/gr-digital/lib/clock_recovery_mm_cc_impl.cc
@@ -0,0 +1,213 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2006,2010-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clock_recovery_mm_cc_impl.h"
+#include <gr_io_signature.h>
+#include <gr_prefs.h>
+#include <gr_math.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace digital {
+
+ static const int FUDGE = 16;
+
+ clock_recovery_mm_cc::sptr
+ clock_recovery_mm_cc::make(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit)
+ {
+ return gnuradio::get_initial_sptr
+ (new clock_recovery_mm_cc_impl(omega, gain_omega,
+ mu, gain_mu,
+ omega_relative_limit));
+ }
+
+ clock_recovery_mm_cc_impl::clock_recovery_mm_cc_impl(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit)
+ : gr_block("clock_recovery_mm_cc",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature2(1, 2, sizeof(gr_complex), sizeof(float))),
+ d_mu(mu), d_omega(omega), d_gain_omega(gain_omega),
+ d_omega_relative_limit(omega_relative_limit),
+ d_gain_mu(gain_mu), d_last_sample(0), d_interp(new filter::mmse_fir_interpolator_cc()),
+ d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)),
+ d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0)
+ {
+ if(omega <= 0.0)
+ throw std::out_of_range("clock rate must be > 0");
+ if(gain_mu < 0 || gain_omega < 0)
+ throw std::out_of_range("Gains must be non-negative");
+
+ set_omega(omega); // also sets min and max omega
+ set_relative_rate(1.0 / omega);
+ set_history(3); // ensure 2 extra input samples are available
+ }
+
+ clock_recovery_mm_cc_impl::~clock_recovery_mm_cc_impl()
+ {
+ delete d_interp;
+ }
+
+ void
+ clock_recovery_mm_cc_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i=0; i < ninputs; i++)
+ ninput_items_required[i] =
+ (int)ceil((noutput_items * d_omega) + d_interp->ntaps()) + FUDGE;
+ }
+
+ gr_complex
+ clock_recovery_mm_cc_impl::slicer_0deg(gr_complex sample)
+ {
+ float real=0, imag=0;
+
+ if(sample.real() > 0)
+ real = 1;
+ if(sample.imag() > 0)
+ imag = 1;
+ return gr_complex(real,imag);
+ }
+
+ gr_complex
+ clock_recovery_mm_cc_impl::slicer_45deg(gr_complex sample)
+ {
+ float real= -1, imag = -1;
+ if(sample.real() > 0)
+ real=1;
+ if(sample.imag() > 0)
+ imag = 1;
+ return gr_complex(real,imag);
+ }
+
+ int
+ clock_recovery_mm_cc_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 gr_complex *in = (const gr_complex *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
+ float *foptr = (float *)output_items[1];
+
+ bool write_foptr = output_items.size() >= 2;
+
+ int ii = 0; // input index
+ int oo = 0; // output index
+ int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this
+
+ assert(d_mu >= 0.0);
+ assert(d_mu <= 1.0);
+
+ float mm_val = 0;
+ gr_complex u, x, y;
+
+ // This loop writes the error to the second output, if it exists
+ if(write_foptr) {
+ while(oo < noutput_items && ii < ni) {
+ d_p_2T = d_p_1T;
+ d_p_1T = d_p_0T;
+ d_p_0T = d_interp->interpolate(&in[ii], d_mu);
+
+ d_c_2T = d_c_1T;
+ d_c_1T = d_c_0T;
+ d_c_0T = slicer_0deg(d_p_0T);
+
+ x = (d_c_0T - d_c_2T) * conj(d_p_1T);
+ y = (d_p_0T - d_p_2T) * conj(d_c_1T);
+ u = y - x;
+ mm_val = u.real();
+ out[oo++] = d_p_0T;
+
+ // limit mm_val
+ mm_val = gr_branchless_clip(mm_val,4.0);
+ d_omega = d_omega + d_gain_omega * mm_val;
+ d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit);
+
+ d_mu = d_mu + d_omega + d_gain_mu * mm_val;
+ ii += (int)floor(d_mu);
+ d_mu -= floor(d_mu);
+
+ // write the error signal to the second output
+ foptr[oo-1] = mm_val;
+
+ if(ii < 0) // clamp it. This should only happen with bogus input
+ ii = 0;
+ }
+ }
+ // This loop does not write to the second output (ugly, but faster)
+ else {
+ while(oo < noutput_items && ii < ni) {
+ d_p_2T = d_p_1T;
+ d_p_1T = d_p_0T;
+ d_p_0T = d_interp->interpolate(&in[ii], d_mu);
+
+ d_c_2T = d_c_1T;
+ d_c_1T = d_c_0T;
+ d_c_0T = slicer_0deg(d_p_0T);
+
+ x = (d_c_0T - d_c_2T) * conj(d_p_1T);
+ y = (d_p_0T - d_p_2T) * conj(d_c_1T);
+ u = y - x;
+ mm_val = u.real();
+ out[oo++] = d_p_0T;
+
+ // limit mm_val
+ mm_val = gr_branchless_clip(mm_val,1.0);
+
+ d_omega = d_omega + d_gain_omega * mm_val;
+ d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit);
+
+ d_mu = d_mu + d_omega + d_gain_mu * mm_val;
+ ii += (int)floor(d_mu);
+ d_mu -= floor(d_mu);
+
+ if(d_verbose) {
+ std::cout << d_omega << "\t" << d_mu << std::endl;
+ }
+
+ if(ii < 0) // clamp it. This should only happen with bogus input
+ ii = 0;
+ }
+ }
+
+ if(ii > 0) {
+ if(ii > ninput_items[0]) {
+ std::cerr << "clock_recovery_mm_cc: ii > ninput_items[0] ("
+ << ii << " > " << ninput_items[0] << std::endl;
+ assert(0);
+ }
+ consume_each(ii);
+ }
+
+ return oo;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/clock_recovery_mm_cc_impl.h b/gr-digital/lib/clock_recovery_mm_cc_impl.h
new file mode 100644
index 0000000000..fa62bd127f
--- /dev/null
+++ b/gr-digital/lib/clock_recovery_mm_cc_impl.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_IMPL_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_IMPL_H
+
+#include <digital/clock_recovery_mm_cc.h>
+#include <filter/mmse_fir_interpolator_cc.h>
+
+namespace gr {
+ namespace digital {
+
+ class clock_recovery_mm_cc_impl : public clock_recovery_mm_cc
+ {
+ public:
+ clock_recovery_mm_cc_impl(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limi);
+ ~clock_recovery_mm_cc_impl();
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ float mu() const { return d_mu;}
+ float omega() const { return d_omega;}
+ float gain_mu() const { return d_gain_mu;}
+ float gain_omega() const { return d_gain_omega;}
+
+ void set_verbose (bool verbose) { d_verbose = verbose; }
+ void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
+ void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
+ void set_mu (float mu) { d_mu = mu; }
+ void set_omega (float omega) {
+ d_omega = omega;
+ d_min_omega = omega*(1.0 - d_omega_relative_limit);
+ d_max_omega = omega*(1.0 + d_omega_relative_limit);
+ d_omega_mid = 0.5*(d_min_omega+d_max_omega);
+ }
+
+ private:
+ float d_mu; // fractional sample position [0.0, 1.0]
+ float d_omega; // nominal frequency
+ float d_gain_omega; // gain for adjusting omega
+ float d_min_omega; // minimum allowed omega
+ float d_max_omega; // maximum allowed omeg
+ float d_omega_relative_limit; // used to compute min and max omega
+ float d_omega_mid; // average omega
+ float d_gain_mu; // gain for adjusting mu
+
+ gr_complex d_last_sample;
+ filter::mmse_fir_interpolator_cc *d_interp;
+
+ bool d_verbose;
+
+ gr_complex d_p_2T, d_p_1T, d_p_0T;
+ gr_complex d_c_2T, d_c_1T, d_c_0T;
+
+ gr_complex slicer_0deg(gr_complex sample);
+ gr_complex slicer_45deg(gr_complex sample);
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_IMPL_H */
diff --git a/gr-digital/lib/clock_recovery_mm_ff_impl.cc b/gr-digital/lib/clock_recovery_mm_ff_impl.cc
new file mode 100644
index 0000000000..4ac3e40c5d
--- /dev/null
+++ b/gr-digital/lib/clock_recovery_mm_ff_impl.cc
@@ -0,0 +1,120 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clock_recovery_mm_ff_impl.h"
+#include <gr_io_signature.h>
+#include <gr_math.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace digital {
+
+ clock_recovery_mm_ff::sptr
+ clock_recovery_mm_ff::make(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit)
+ {
+ return gnuradio::get_initial_sptr
+ (new clock_recovery_mm_ff_impl(omega, gain_omega,
+ mu, gain_mu,
+ omega_relative_limit));
+ }
+
+ clock_recovery_mm_ff_impl::clock_recovery_mm_ff_impl(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit)
+ : gr_block("clock_recovery_mm_ff",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(float))),
+ d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega),
+ d_omega_relative_limit(omega_relative_limit),
+ d_last_sample(0), d_interp(new filter::mmse_fir_interpolator_ff())
+ {
+ if(omega < 1)
+ throw std::out_of_range("clock rate must be > 0");
+ if(gain_mu < 0 || gain_omega < 0)
+ throw std::out_of_range("Gains must be non-negative");
+
+ set_omega(omega); // also sets min and max omega
+ set_relative_rate (1.0 / omega);
+ }
+
+ clock_recovery_mm_ff_impl::~clock_recovery_mm_ff_impl()
+ {
+ delete d_interp;
+ }
+
+ void
+ clock_recovery_mm_ff_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i=0; i < ninputs; i++)
+ ninput_items_required[i] =
+ (int) ceil((noutput_items * d_omega) + d_interp->ntaps());
+ }
+
+ static inline float
+ slice(float x)
+ {
+ return x < 0 ? -1.0F : 1.0F;
+ }
+
+ int
+ clock_recovery_mm_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 ii = 0; // input index
+ int oo = 0; // output index
+ int ni = ninput_items[0] - d_interp->ntaps(); // don't use more input than this
+ float mm_val;
+
+ while(oo < noutput_items && ii < ni ) {
+ // produce output sample
+ out[oo] = d_interp->interpolate(&in[ii], d_mu);
+ mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample;
+ d_last_sample = out[oo];
+
+ d_omega = d_omega + d_gain_omega * mm_val;
+ d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit);
+ d_mu = d_mu + d_omega + d_gain_mu * mm_val;
+
+ ii += (int)floor(d_mu);
+ d_mu = d_mu - floor(d_mu);
+ oo++;
+ }
+
+ consume_each(ii);
+ return oo;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/clock_recovery_mm_ff_impl.h b/gr-digital/lib/clock_recovery_mm_ff_impl.h
new file mode 100644
index 0000000000..920a05a496
--- /dev/null
+++ b/gr-digital/lib/clock_recovery_mm_ff_impl.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_IMPL_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_IMPL_H
+
+#include <digital/clock_recovery_mm_ff.h>
+#include <filter/mmse_fir_interpolator_ff.h>
+
+namespace gr {
+ namespace digital {
+
+ class clock_recovery_mm_ff_impl : public clock_recovery_mm_ff
+ {
+ public:
+ clock_recovery_mm_ff_impl(float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limi);
+ ~clock_recovery_mm_ff_impl();
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ float mu() const { return d_mu;}
+ float omega() const { return d_omega;}
+ float gain_mu() const { return d_gain_mu;}
+ float gain_omega() const { return d_gain_omega;}
+
+ void set_verbose (bool verbose) { d_verbose = verbose; }
+ void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
+ void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
+ void set_mu (float mu) { d_mu = mu; }
+ void set_omega (float omega){
+ d_omega = omega;
+ d_min_omega = omega*(1.0 - d_omega_relative_limit);
+ d_max_omega = omega*(1.0 + d_omega_relative_limit);
+ d_omega_mid = 0.5*(d_min_omega+d_max_omega);
+ }
+
+ private:
+ float d_mu; // fractional sample position [0.0, 1.0]
+ float d_gain_mu; // gain for adjusting mu
+ float d_omega; // nominal frequency
+ float d_gain_omega; // gain for adjusting omega
+ float d_min_omega; // minimum allowed omega
+ float d_max_omega; // maximum allowed omeg
+ float d_omega_relative_limit; // used to compute min and max omega
+ float d_omega_mid; // average omega
+
+ float d_last_sample;
+ filter::mmse_fir_interpolator_ff *d_interp;
+
+ bool d_verbose;
+ };
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_IMPL_H */
diff --git a/gr-digital/lib/digital_clock_recovery_mm_cc.cc b/gr-digital/lib/digital_clock_recovery_mm_cc.cc
deleted file mode 100644
index 198eb4b890..0000000000
--- a/gr-digital/lib/digital_clock_recovery_mm_cc.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2005,2006,2010,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_io_signature.h>
-#include <gr_prefs.h>
-#include <digital_clock_recovery_mm_cc.h>
-#include <gri_mmse_fir_interpolator_cc.h>
-#include <stdexcept>
-#include <cstdio>
-
-
-// Public constructor
-static const int FUDGE = 16;
-
-digital_clock_recovery_mm_cc_sptr
-digital_make_clock_recovery_mm_cc(float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit)
-{
- return gnuradio::get_initial_sptr(new digital_clock_recovery_mm_cc (omega,
- gain_omega,
- mu,
- gain_mu,
- omega_relative_limit));
-}
-
-digital_clock_recovery_mm_cc::digital_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit)
- : gr_block ("clock_recovery_mm_cc",
- gr_make_io_signature (1, 1, sizeof (gr_complex)),
- gr_make_io_signature2 (1, 2, sizeof (gr_complex), sizeof(float))),
- d_mu (mu), d_omega(omega), d_gain_omega(gain_omega),
- d_omega_relative_limit(omega_relative_limit),
- d_gain_mu(gain_mu), d_last_sample(0), d_interp(new gri_mmse_fir_interpolator_cc()),
- d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)),
- d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0)
-{
- if (omega <= 0.0)
- throw std::out_of_range ("clock rate must be > 0");
- if (gain_mu < 0 || gain_omega < 0)
- throw std::out_of_range ("Gains must be non-negative");
-
- set_omega(omega); // also sets min and max omega
- set_relative_rate (1.0 / omega);
- set_history(3); // ensure 2 extra input sample is available
-}
-
-digital_clock_recovery_mm_cc::~digital_clock_recovery_mm_cc ()
-{
- delete d_interp;
-}
-
-void
-digital_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required)
-{
- unsigned ninputs = ninput_items_required.size();
- for (unsigned i=0; i < ninputs; i++)
- ninput_items_required[i] =
- (int) ceil((noutput_items * d_omega) + d_interp->ntaps()) + FUDGE;
-}
-
-gr_complex
-digital_clock_recovery_mm_cc::slicer_0deg (gr_complex sample)
-{
- float real=0, imag=0;
-
- if(sample.real() > 0)
- real = 1;
- if(sample.imag() > 0)
- imag = 1;
- return gr_complex(real,imag);
-}
-
-gr_complex
-digital_clock_recovery_mm_cc::slicer_45deg (gr_complex sample)
-{
- float real= -1, imag = -1;
- if(sample.real() > 0)
- real=1;
- if(sample.imag() > 0)
- imag = 1;
- return gr_complex(real,imag);
-}
-
-/*
- Modified Mueller and Muller clock recovery circuit
- Based:
- G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller
- algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033.
-*/
-
-int
-digital_clock_recovery_mm_cc::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- const gr_complex *in = (const gr_complex *) input_items[0];
- gr_complex *out = (gr_complex *) output_items[0];
- float *foptr = (float *) output_items[1];
-
- bool write_foptr = output_items.size() >= 2;
-
- int ii = 0; // input index
- int oo = 0; // output index
- int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this
-
- assert(d_mu >= 0.0);
- assert(d_mu <= 1.0);
-
- float mm_val=0;
- gr_complex u, x, y;
-
- // This loop writes the error to the second output, if it exists
- if (write_foptr) {
- while(oo < noutput_items && ii < ni) {
- d_p_2T = d_p_1T;
- d_p_1T = d_p_0T;
- d_p_0T = d_interp->interpolate (&in[ii], d_mu);
-
- d_c_2T = d_c_1T;
- d_c_1T = d_c_0T;
- d_c_0T = slicer_0deg(d_p_0T);
-
- x = (d_c_0T - d_c_2T) * conj(d_p_1T);
- y = (d_p_0T - d_p_2T) * conj(d_c_1T);
- u = y - x;
- mm_val = u.real();
- out[oo++] = d_p_0T;
-
- // limit mm_val
- mm_val = gr_branchless_clip(mm_val,4.0);
- d_omega = d_omega + d_gain_omega * mm_val;
- d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit); // make sure we don't walk away
-
- d_mu = d_mu + d_omega + d_gain_mu * mm_val;
- ii += (int)floor(d_mu);
- d_mu -= floor(d_mu);
-
- // write the error signal to the second output
- foptr[oo-1] = mm_val;
-
- if (ii < 0) // clamp it. This should only happen with bogus input
- ii = 0;
- }
- }
- // This loop does not write to the second output (ugly, but faster)
- else {
- while(oo < noutput_items && ii < ni) {
- d_p_2T = d_p_1T;
- d_p_1T = d_p_0T;
- d_p_0T = d_interp->interpolate (&in[ii], d_mu);
-
- d_c_2T = d_c_1T;
- d_c_1T = d_c_0T;
- d_c_0T = slicer_0deg(d_p_0T);
-
- x = (d_c_0T - d_c_2T) * conj(d_p_1T);
- y = (d_p_0T - d_p_2T) * conj(d_c_1T);
- u = y - x;
- mm_val = u.real();
- out[oo++] = d_p_0T;
-
- // limit mm_val
- mm_val = gr_branchless_clip(mm_val,1.0);
-
- d_omega = d_omega + d_gain_omega * mm_val;
- d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit); // make sure we don't walk away
-
- d_mu = d_mu + d_omega + d_gain_mu * mm_val;
- ii += (int)floor(d_mu);
- d_mu -= floor(d_mu);
-
- if(d_verbose) {
- printf("%f\t%f\n", d_omega, d_mu);
- }
-
- if (ii < 0) // clamp it. This should only happen with bogus input
- ii = 0;
- }
- }
-
- if (ii > 0){
- if (ii > ninput_items[0]){
- fprintf(stderr, "gr_clock_recovery_mm_cc: ii > ninput_items[0] (%d > %d)\n",
- ii, ninput_items[0]);
- assert(0);
- }
- consume_each (ii);
- }
-
- return oo;
-}
diff --git a/gr-digital/lib/digital_clock_recovery_mm_ff.cc b/gr-digital/lib/digital_clock_recovery_mm_ff.cc
deleted file mode 100644
index 04057f0e94..0000000000
--- a/gr-digital/lib/digital_clock_recovery_mm_ff.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2010,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_io_signature.h>
-#include <digital_clock_recovery_mm_ff.h>
-#include <gri_mmse_fir_interpolator.h>
-#include <stdexcept>
-
-#define DEBUG_CR_MM_FF 0 // must be defined as 0 or 1
-
-// Public constructor
-
-digital_clock_recovery_mm_ff_sptr
-digital_make_clock_recovery_mm_ff(float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit)
-{
- return gnuradio::get_initial_sptr(new digital_clock_recovery_mm_ff (omega,
- gain_omega,
- mu,
- gain_mu,
- omega_relative_limit));
-}
-
-digital_clock_recovery_mm_ff::digital_clock_recovery_mm_ff (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit)
- : gr_block ("clock_recovery_mm_ff",
- gr_make_io_signature (1, 1, sizeof (float)),
- gr_make_io_signature (1, 1, sizeof (float))),
- d_mu (mu), d_gain_omega(gain_omega), d_gain_mu(gain_mu),
- d_last_sample(0), d_interp(new gri_mmse_fir_interpolator()),
- d_logfile(0), d_omega_relative_limit(omega_relative_limit)
-{
- if (omega < 1)
- throw std::out_of_range ("clock rate must be > 0");
- if (gain_mu < 0 || gain_omega < 0)
- throw std::out_of_range ("Gains must be non-negative");
-
- set_omega(omega); // also sets min and max omega
- set_relative_rate (1.0 / omega);
-
- if (DEBUG_CR_MM_FF)
- d_logfile = fopen("cr_mm_ff.dat", "wb");
-}
-
-digital_clock_recovery_mm_ff::~digital_clock_recovery_mm_ff ()
-{
- delete d_interp;
-
- if (DEBUG_CR_MM_FF && d_logfile){
- fclose(d_logfile);
- d_logfile = 0;
- }
-}
-
-void
-digital_clock_recovery_mm_ff::forecast(int noutput_items, gr_vector_int &ninput_items_required)
-{
- unsigned ninputs = ninput_items_required.size();
- for (unsigned i=0; i < ninputs; i++)
- ninput_items_required[i] =
- (int) ceil((noutput_items * d_omega) + d_interp->ntaps());
-}
-
-static inline float
-slice(float x)
-{
- return x < 0 ? -1.0F : 1.0F;
-}
-
-/*
- * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer.
- *
- * See "Digital Communication Receivers: Synchronization, Channel
- * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel.
- * ISBN 0-471-50275-8.
- */
-int
-digital_clock_recovery_mm_ff::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 ii = 0; // input index
- int oo = 0; // output index
- int ni = ninput_items[0] - d_interp->ntaps(); // don't use more input than this
- float mm_val;
-
- while (oo < noutput_items && ii < ni ){
-
- // produce output sample
- out[oo] = d_interp->interpolate (&in[ii], d_mu);
- mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample;
- d_last_sample = out[oo];
-
- d_omega = d_omega + d_gain_omega * mm_val;
- d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit); // make sure we don't walk away
- d_mu = d_mu + d_omega + d_gain_mu * mm_val;
-
- ii += (int) floor(d_mu);
- d_mu = d_mu - floor(d_mu);
- oo++;
-
- if (DEBUG_CR_MM_FF && d_logfile){
- fwrite(&d_omega, sizeof(d_omega), 1, d_logfile);
- }
- }
-
- consume_each (ii);
-
- return oo;
-}
diff --git a/gr-digital/swig/digital_clock_recovery_mm_cc.i b/gr-digital/swig/digital_clock_recovery_mm_cc.i
deleted file mode 100644
index 4ce9a9725d..0000000000
--- a/gr-digital/swig/digital_clock_recovery_mm_cc.i
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-GR_SWIG_BLOCK_MAGIC(digital,clock_recovery_mm_cc);
-
-digital_clock_recovery_mm_cc_sptr
-digital_make_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit) throw(std::exception);
-
-class digital_clock_recovery_mm_cc : public gr_sync_block
-{
- private:
- digital_clock_recovery_mm_cc (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit);
-
-public:
- float mu() const { return d_mu;}
- float omega() const { return d_omega;}
- float gain_mu() const { return d_gain_mu;}
- float gain_omega() const { return d_gain_omega;}
-
- void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
- void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
- void set_mu (float omega) { d_mu = mu; }
- void set_omega (float omega) { d_omega = omega;
- d_min_omega = omega*(1.0 - d_omega_relative_limit);
- d_max_omega = omega*(1.0 + d_omega_relative_limit);
- }
- void set_verbose (bool verbose) { d_verbose = verbose; }
-};
diff --git a/gr-digital/swig/digital_clock_recovery_mm_ff.i b/gr-digital/swig/digital_clock_recovery_mm_ff.i
deleted file mode 100644
index 054ef9ebfe..0000000000
--- a/gr-digital/swig/digital_clock_recovery_mm_ff.i
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2011 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-GR_SWIG_BLOCK_MAGIC(digital,clock_recovery_mm_ff);
-
-digital_clock_recovery_mm_ff_sptr
-digital_make_clock_recovery_mm_ff (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit=0.001) throw(std::exception);
-
-class digital_clock_recovery_mm_ff : public gr_sync_block
-{
- private:
- digital_clock_recovery_mm_ff (float omega, float gain_omega,
- float mu, float gain_mu,
- float omega_relative_limit);
-
-public:
- float mu() const;
- float omega() const;
- float gain_mu() const;
- float gain_omega() const;
-
- void set_gain_mu (float gain_mu);
- void set_gain_omega (float gain_omega);
- void set_mu (float omega);
- void set_omega (float omega);
-};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index cb6e1c7be6..0e1b79fb27 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -40,11 +40,16 @@
%{
#include "digital/additive_scrambler_bb.h"
#include "digital/binary_slicer_fb.h"
+#include "digital/clock_recovery_mm_cc.h"
+#include "digital/clock_recovery_mm_ff.h"
%}
%include "digital/additive_scrambler_bb.h"
%include "digital/binary_slicer_fb.h"
+%include "digital/clock_recovery_mm_cc.h"
+%include "digital/clock_recovery_mm_ff.h"
GR_SWIG_BLOCK_MAGIC2(digital, additive_scrambler_bb);
GR_SWIG_BLOCK_MAGIC2(digital, binary_slicer_fb);
-
+GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_cc);
+GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_ff);