3 * Copyright 2005,2006 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
27 #include <gr_io_signature.h>
29 #include <gr_clock_recovery_mm_cc.h>
30 #include <gri_mmse_fir_interpolator_cc.h>
36 gr_clock_recovery_mm_cc_sptr
37 gr_make_clock_recovery_mm_cc(float omega, float gain_omega, float mu, float gain_mu,
38 float omega_relative_limit)
40 return gr_clock_recovery_mm_cc_sptr (new gr_clock_recovery_mm_cc (omega,
44 omega_relative_limit));
47 gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu,
48 float gain_mu, float omega_relative_limit)
49 : gr_block ("clock_recovery_mm_cc",
50 gr_make_io_signature (1, 1, sizeof (gr_complex)),
51 gr_make_io_signature (1, 2, sizeof (gr_complex))),
52 d_mu (mu), d_omega(omega), d_gain_omega(gain_omega),
53 d_omega_relative_limit(omega_relative_limit),
54 d_gain_mu(gain_mu), d_last_sample(0), d_interp(new gri_mmse_fir_interpolator_cc()),
55 d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)),
56 d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0)
59 throw std::out_of_range ("clock rate must be > 0");
60 if (gain_mu < 0 || gain_omega < 0)
61 throw std::out_of_range ("Gains must be non-negative");
63 set_omega(omega); // also sets min and max omega
64 set_relative_rate (1.0 / omega);
65 set_history(3); // ensure 2 extra input sample is available
68 gr_clock_recovery_mm_cc::~gr_clock_recovery_mm_cc ()
74 gr_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required)
76 unsigned ninputs = ninput_items_required.size();
77 for (unsigned i=0; i < ninputs; i++)
78 ninput_items_required[i] =
79 (int) ceil((noutput_items * d_omega) + d_interp->ntaps());
83 gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample)
91 return gr_complex(real,imag);
95 gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample)
97 float real= -1, imag = -1;
100 if(sample.imag() > 0)
102 return gr_complex(real,imag);
106 Modified Mueller and Muller clock recovery circuit
108 G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller
109 algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033.
112 static const int FUDGE = 16;
115 gr_clock_recovery_mm_cc::general_work (int noutput_items,
116 gr_vector_int &ninput_items,
117 gr_vector_const_void_star &input_items,
118 gr_vector_void_star &output_items)
120 const gr_complex *in = (const gr_complex *) input_items[0];
121 gr_complex *out = (gr_complex *) output_items[0];
122 gr_complex *foptr = (gr_complex *) output_items[1];
124 bool write_foptr = output_items.size() >= 2;
126 int ii = 0; // input index
127 int oo = 0; // output index
128 int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this
136 while(oo < noutput_items && ii < ni) {
139 d_p_0T = d_interp->interpolate (&in[ii], d_mu);
143 d_c_0T = slicer_0deg(d_p_0T);
145 x = (d_c_0T - d_c_2T) * conj(d_p_1T);
146 y = (d_p_0T - d_p_2T) * conj(d_c_1T);
154 else if (mm_val < -1.0)
157 d_omega = d_omega + d_gain_omega * mm_val;
158 if (d_omega > d_max_omega)
159 d_omega = d_max_omega;
160 else if (d_omega < d_min_omega)
161 d_omega = d_min_omega;
163 d_mu = d_mu + d_omega + d_gain_mu * mm_val;
164 ii += (int)floor(d_mu);
168 printf("%f\t%f\n", d_omega, d_mu);
171 // write the error signal to the second output
173 foptr[oo-1] = gr_complex(d_mu,0);
175 if (ii < 0) // clamp it. This should only happen with bogus input
180 if (ii > ninput_items[0]){
181 fprintf(stderr, "gr_clock_recovery_mm_cc: ii > ninput_items[0] (%d > %d)\n",
182 ii, ninput_items[0]);