Merge remote branch 'bitshark/burx_support' into wip/burx_support
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_mpsk_receiver_cc.cc
index 6b8cc320a9af02992ce6d44edc7706436073a2bd..1efa827035da7848338c24a982a46db2dcd61987 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,
@@ -90,13 +90,13 @@ gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta,
   // Select a phase detector and a decision maker for the modulation order
   switch(d_M) {
   case 2:  // optimized algorithms for BPSK
-    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_generic; //bpsk;
-    d_decision = &gr_mpsk_receiver_cc::decision_generic; //bpsk;
+    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_bpsk; //bpsk;
+    d_decision = &gr_mpsk_receiver_cc::decision_bpsk;
     break;
 
   case 4: // optimized algorithms for QPSK
-    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_generic; //qpsk;
-    d_decision = &gr_mpsk_receiver_cc::decision_generic; //qpsk;
+    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_qpsk; //qpsk;
+    d_decision = &gr_mpsk_receiver_cc::decision_qpsk;
     break;
 
   default: // generic algorithms for any M (power of 2?) but not pretty
@@ -104,8 +104,6 @@ gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta,
     d_decision = &gr_mpsk_receiver_cc::decision_generic;
     break;
   }
-
-  set_history(3);                      // ensure 2 extra input sample is available
 }
 
 gr_mpsk_receiver_cc::~gr_mpsk_receiver_cc ()
@@ -119,24 +117,33 @@ gr_mpsk_receiver_cc::forecast(int noutput_items, gr_vector_int &ninput_items_req
   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());
-  //ninput_items_required[i] = (int)(d_omega);
-
 }
 
 // FIXME add these back in an test difference in performance
 float
 gr_mpsk_receiver_cc::phase_error_detector_qpsk(gr_complex sample) const
 {
-  float phase_error = ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() -
-                      (sample.imag()>0 ? 1.0 : -1.0) * sample.real());
-  return -phase_error;
+  float phase_error = 0;
+  if(fabsf(sample.real()) > fabsf(sample.imag())) {
+    if(sample.real() > 0)
+      phase_error = -sample.imag();
+    else
+      phase_error = sample.imag();
+  }
+  else {
+    if(sample.imag() > 0)
+      phase_error = sample.real();
+    else
+      phase_error = -sample.real();
+  }
+  
+  return phase_error;
 }
 
-// FIXME add these back in an test difference in performance
 float
 gr_mpsk_receiver_cc::phase_error_detector_bpsk(gr_complex sample) const
 {
-  return (sample.real()*sample.imag());
+  return -(sample.real()*sample.imag());
 }
 
 float gr_mpsk_receiver_cc::phase_error_detector_generic(gr_complex sample) const
@@ -145,31 +152,20 @@ float gr_mpsk_receiver_cc::phase_error_detector_generic(gr_complex sample) const
   return -arg(sample*conj(d_constellation[d_current_const_point]));
 }
 
-// FIXME add these back in an test difference in performance
 unsigned int
 gr_mpsk_receiver_cc::decision_bpsk(gr_complex sample) const
 {
-  unsigned int index = 0;
-
-  // Implements a 1-demensional slicer
-  if(sample.real() > 0)
-    index = 1;
-  return index;
+  return (gr_branchless_binary_slicer(sample.real()) ^ 1);
+  //return gr_binary_slicer(sample.real()) ^ 1;
 }
 
-// FIXME add these back in an test difference in performance
 unsigned int
 gr_mpsk_receiver_cc::decision_qpsk(gr_complex sample) const
 {
-  unsigned int index = 0;
-
-  // Implements a simple slicer function
-  if((sample.real() < 0) && (sample.imag() > 0))
-    index = 1;
-  else if((sample.real() < 0) && (sample.imag() < 0))
-    index = 2;
-  else
-    index = 3;
+  unsigned int index;
+
+  //index = gr_branchless_quad_0deg_slicer(sample);
+  index = gr_quad_0deg_slicer(sample);
   return index;
 }
 
@@ -211,11 +207,11 @@ gr_mpsk_receiver_cc::mm_sampler(const gr_complex symbol)
   d_phase += d_freq;  // increment the phase based on the frequency of the rotation
 
   // Keep phase clamped and not walk to infinity
-  while(d_phase>M_TWOPI)
+  while(d_phase > M_TWOPI)
     d_phase -= M_TWOPI;
-  while(d_phase<-M_TWOPI)
+  while(d_phase < -M_TWOPI)
     d_phase += M_TWOPI;
-
+  
   nco = gr_expj(d_phase+d_theta);   // get the NCO value for derotating the current sample
   sample = nco*symbol;      // get the downconverted symbol
   
@@ -247,20 +243,10 @@ gr_mpsk_receiver_cc::mm_error_tracking(gr_complex sample)
   y = (d_p_0T - d_p_2T) * conj(d_c_1T);
   u = y - x;
   mm_error = u.real();   // the error signal is in the real part
-  
-  // limit mm_val
-  if (mm_error > 1.0)
-    mm_error = 1.0;
-  else if (mm_error < -1.0)
-    mm_error = -1.0;
-  
+  mm_error = gr_branchless_clip(mm_error, 1.0); // limit mm_val
+    
   d_omega = d_omega + d_gain_omega * mm_error;  // update omega based on loop error
-
-  // make sure we don't walk away
-  if (d_omega > d_max_omega)
-    d_omega = d_max_omega;
-  else if (d_omega < d_min_omega)
-    d_omega = d_min_omega;
+  d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_rel);   // make sure we don't walk away
   
   d_mu += d_omega + d_gain_mu * mm_error;   // update mu based on loop error
   
@@ -279,27 +265,19 @@ gr_mpsk_receiver_cc::phase_error_tracking(gr_complex sample)
 
   // Make phase and frequency corrections based on sampled value
   phase_error = (*this.*d_phase_error_detector)(sample);
-
-  if (phase_error > 1)
-    phase_error = 1;
-  else if (phase_error < -1)
-    phase_error = -1;  
-
+    
   d_freq += d_beta*phase_error;             // adjust frequency based on error
   d_phase += d_freq + d_alpha*phase_error;  // adjust phase based on error
-  
+
   // Make sure we stay within +-2pi
-  while(d_phase>M_TWOPI)
+  while(d_phase > M_TWOPI)
     d_phase -= M_TWOPI;
-  while(d_phase<-M_TWOPI)
+  while(d_phase < -M_TWOPI)
     d_phase += M_TWOPI;
   
   // Limit the frequency range
-  if (d_freq > d_max_freq)
-    d_freq = d_max_freq;
-  else if (d_freq < d_min_freq)
-    d_freq = d_min_freq;
-
+  d_freq = gr_branchless_clip(d_freq, d_max_freq);
+  
 #if VERBOSE_COSTAS
   printf("cl: phase_error: %f  phase: %f  freq: %f  sample: %f+j%f  constellation: %f+j%f\n",
         phase_error, d_phase, d_freq, sample.real(), sample.imag(), 
@@ -318,7 +296,6 @@ gr_mpsk_receiver_cc::general_work (int noutput_items,
 
   int i=0, o=0;
 
-  //while(i < ninput_items[0]) {    
   while((o < noutput_items) && (i < ninput_items[0])) {
     while((d_mu > 1) && (i < ninput_items[0]))  {
       mm_sampler(in[i]);   // puts symbols into a buffer and adjusts d_mu