summaryrefslogtreecommitdiff
path: root/gr-digital
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2011-07-19 22:07:27 -0400
committerTom Rondeau <trondeau@vt.edu>2011-07-19 22:07:27 -0400
commit7b54b63c58dd4474a3f8192b43f0799447f79ee8 (patch)
tree5ce70b4f58a8fe69b3c02263f048af37aa810851 /gr-digital
parent3f94d49bae62301349f31959c34c690b5c47fc2b (diff)
digital: moved clock_recovery_ff/cc to gr-digital.
Diffstat (limited to 'gr-digital')
-rw-r--r--gr-digital/lib/Makefile.am4
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_cc.cc217
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_cc.h112
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_ff.cc139
-rw-r--r--gr-digital/lib/digital_clock_recovery_mm_ff.h98
-rw-r--r--gr-digital/swig/Makefile.am2
-rw-r--r--gr-digital/swig/digital_clock_recovery_mm_cc.i51
-rw-r--r--gr-digital/swig/digital_clock_recovery_mm_ff.i47
8 files changed, 670 insertions, 0 deletions
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am
index 493daab8b5..3d39d15dac 100644
--- a/gr-digital/lib/Makefile.am
+++ b/gr-digital/lib/Makefile.am
@@ -26,6 +26,8 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES)
# These headers get installed in ${prefix}/include/gnuradio
grinclude_HEADERS = \
digital_binary_slicer_fb.h \
+ digital_clock_recovery_mm_cc.h \
+ digital_clock_recovery_mm_ff.h \
digital_constellation.h \
digital_constellation_receiver_cb.h \
digital_constellation_decoder_cb.h \
@@ -39,6 +41,8 @@ lib_LTLIBRARIES = libgnuradio-digital.la
libgnuradio_digital_la_SOURCES = \
digital_binary_slicer_fb.cc \
+ digital_clock_recovery_mm_cc.cc \
+ digital_clock_recovery_mm_ff.cc \
digital_constellation.cc \
digital_constellation_receiver_cb.cc \
digital_constellation_decoder_cb.cc \
diff --git a/gr-digital/lib/digital_clock_recovery_mm_cc.cc b/gr-digital/lib/digital_clock_recovery_mm_cc.cc
new file mode 100644
index 0000000000..2984afd6cb
--- /dev/null
+++ b/gr-digital/lib/digital_clock_recovery_mm_cc.cc
@@ -0,0 +1,217 @@
+/* -*- 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_signature (1, 2, sizeof (gr_complex))),
+ 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];
+ gr_complex *foptr = (gr_complex *) 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,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);
+
+ // write the error signal to the second output
+ foptr[oo-1] = gr_complex(d_mu,0);
+
+ 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_cc.h b/gr-digital/lib/digital_clock_recovery_mm_cc.h
new file mode 100644
index 0000000000..422bf811cb
--- /dev/null
+++ b/gr-digital/lib/digital_clock_recovery_mm_cc.h
@@ -0,0 +1,112 @@
+/* -*- 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 <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_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
+ *
+ * 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_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_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/lib/digital_clock_recovery_mm_ff.cc b/gr-digital/lib/digital_clock_recovery_mm_ff.cc
new file mode 100644
index 0000000000..04057f0e94
--- /dev/null
+++ b/gr-digital/lib/digital_clock_recovery_mm_ff.cc
@@ -0,0 +1,139 @@
+/* -*- 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/lib/digital_clock_recovery_mm_ff.h b/gr-digital/lib/digital_clock_recovery_mm_ff.h
new file mode 100644
index 0000000000..6fc5ac2616
--- /dev/null
+++ b/gr-digital/lib/digital_clock_recovery_mm_ff.h
@@ -0,0 +1,98 @@
+/* -*- 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 <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_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
+ *
+ * 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_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_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/swig/Makefile.am b/gr-digital/swig/Makefile.am
index f1041ab69d..aad63ee449 100644
--- a/gr-digital/swig/Makefile.am
+++ b/gr-digital/swig/Makefile.am
@@ -59,6 +59,8 @@ digital_swig_la_swig_libadd = \
# additional SWIG files to be installed
digital_swig_swiginclude_headers = \
digital_binary_slicer_fb.i \
+ digital_clock_recovery_mm_cc.i \
+ digital_clock_recovery_mm_ff.i \
digital_constellation.i \
digital_constellation_receiver_cb.i \
digital_constellation_decoder_cb.i \
diff --git a/gr-digital/swig/digital_clock_recovery_mm_cc.i b/gr-digital/swig/digital_clock_recovery_mm_cc.i
new file mode 100644
index 0000000000..4ce9a9725d
--- /dev/null
+++ b/gr-digital/swig/digital_clock_recovery_mm_cc.i
@@ -0,0 +1,51 @@
+/* -*- 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
new file mode 100644
index 0000000000..054ef9ebfe
--- /dev/null
+++ b/gr-digital/swig/digital_clock_recovery_mm_ff.i
@@ -0,0 +1,47 @@
+/* -*- 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);
+};