Merged branch 'msgq' from http://gnuradio.org/git/jblum.git
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_clock_recovery_mm_cc.cc
index 0d8c7f38d1a5cce582cc9453c4ae950a6ca56783..60e3dd13d59659b9f6623834e1d4f4fef03fd4b6 100644 (file)
@@ -6,7 +6,7 @@
  *
  * 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 2, or (at your option)
+ * 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,
@@ -16,8 +16,8 @@
  *
  * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -29,6 +29,8 @@
 #include <gr_clock_recovery_mm_cc.h>
 #include <gri_mmse_fir_interpolator_cc.h>
 #include <stdexcept>
+#include <cstdio>
+
 
 // Public constructor
 
@@ -48,7 +50,7 @@ gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega,
                                                  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, 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()),
@@ -119,6 +121,9 @@ gr_clock_recovery_mm_cc::general_work (int noutput_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
@@ -130,43 +135,73 @@ gr_clock_recovery_mm_cc::general_work (int noutput_items,
   float mm_val=0;
   gr_complex u, x, y;
 
-  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
-    if (mm_val > 1.0)
-      mm_val = 1.0;
-    else if (mm_val < -1.0)
-      mm_val = -1.0;
-
-    d_omega = d_omega + d_gain_omega * mm_val;
-    if (d_omega > d_max_omega)
-      d_omega = d_max_omega;
-    else if (d_omega < d_min_omega)
-      d_omega = d_min_omega;
-
-    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);
+  // 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)        // clamp it.  This should only happen with bogus input
-      ii = 0;
   }
 
   if (ii > 0){