commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r4207 - gnuradio/branches/developers/trondeau/digital-


From: trondeau
Subject: [Commit-gnuradio] r4207 - gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general
Date: Mon, 1 Jan 2007 12:41:54 -0700 (MST)

Author: trondeau
Date: 2007-01-01 12:41:54 -0700 (Mon, 01 Jan 2007)
New Revision: 4207

Added:
   
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
   
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h
   
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i
Modified:
   
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/Makefile.am
   
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/general.i
Log:
adding new M-PSK receiver that does symbol, phase, and frequency 
synchronization together. This has been tested in a loopback setting 
(non-over-the-air) for BPSK, QPSK, and 8PSK.

Modified: 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/Makefile.am
        2006-12-30 15:45:46 UTC (rev 4206)
+++ 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/Makefile.am
        2007-01-01 19:41:54 UTC (rev 4207)
@@ -158,6 +158,7 @@
        gr_map_bb.cc                    \
        gr_math.cc                      \
        gr_misc.cc                      \
+       gr_mpsk_receiver_cc.cc          \
        gr_nlog10_ff.cc                 \
        gr_nop.cc                       \
        gr_null_sink.cc                 \
@@ -284,6 +285,7 @@
        gr_map_bb.h                     \
        gr_math.h                       \
        gr_misc.h                       \
+       gr_mpsk_receiver_cc.h           \
        gr_nco.h                        \
        gr_nlog10_ff.h                  \
        gr_noise_type.h                 \
@@ -416,6 +418,7 @@
        gr_lms_dfe_cc.i                 \
        gr_lms_dfe_ff.i                 \
        gr_map_bb.i                     \
+       gr_mpsk_receiver_cc.i           \
        gr_nlog10_ff.i                  \
        gr_nop.i                        \
        gr_null_sink.i                  \

Modified: 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/general.i
===================================================================
--- 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/general.i
  2006-12-30 15:45:46 UTC (rev 4206)
+++ 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/general.i
  2007-01-01 19:41:54 UTC (rev 4207)
@@ -71,6 +71,7 @@
 #include <gr_nlog10_ff.h>
 #include <gr_fake_channel_coder_pp.h>
 #include <gr_throttle.h>
+#include <gr_mpsk_receiver_cc.h>
 #include <gr_stream_to_streams.h>
 #include <gr_streams_to_stream.h>
 #include <gr_streams_to_vector.h>
@@ -165,6 +166,7 @@
 %include "gr_nlog10_ff.i"
 %include "gr_fake_channel_coder_pp.i"
 %include "gr_throttle.i"
+%include "gr_mpsk_receiver_cc.i"
 %include "gr_stream_to_streams.i"
 %include "gr_streams_to_stream.i"
 %include "gr_streams_to_vector.i"

Added: 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
===================================================================
--- 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
                             (rev 0)
+++ 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
     2007-01-01 19:41:54 UTC (rev 4207)
@@ -0,0 +1,295 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2006 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 2, 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 <gr_timing_recovery_simple_cc.h>
+#include <stdexcept>
+#include <gr_math.h>
+#include <gr_expj.h>
+#include <gri_mmse_fir_interpolator_cc.h>
+
+
+#define M_TWOPI (2*M_PI)
+
+
+// Public constructor
+
+gr_timing_recovery_simple_cc_sptr 
+gr_make_timing_recovery_simple_cc(unsigned int M, float theta,
+                                 float alpha, float beta,
+                                 float fmin, float fmax,
+                                 float mu, float gain_mu, 
+                                 float omega, float gain_omega, float 
omega_rel)
+{
+  return gr_timing_recovery_simple_cc_sptr (new gr_timing_recovery_simple_cc 
(M, theta, 
+                                                                             
alpha, beta,
+                                                                             
fmin, fmax,
+                                                                             
mu, gain_mu, 
+                                                                             
omega, gain_omega, omega_rel));
+}
+
+gr_timing_recovery_simple_cc::gr_timing_recovery_simple_cc (unsigned int M, 
float theta, 
+                                                           float alpha, float 
beta,
+                                                           float fmin, float 
fmax,
+                                                           float mu, float 
gain_mu, 
+                                                           float omega, float 
gain_omega, float omega_rel)
+  : gr_block ("timing_recovery_simple_cc",
+             gr_make_io_signature (1, 1, sizeof (gr_complex)),
+             gr_make_io_signature (1, 1, sizeof (gr_complex))),
+    d_M(M), d_theta(theta), 
+    d_alpha(alpha), d_beta(beta), d_freq(0), d_phase(0),
+    d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega), 
+    d_max_omega(omega+omega_rel), d_min_omega(omega-omega_rel),
+    d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0)
+{
+  d_interp = new gri_mmse_fir_interpolator_cc();
+  d_dl_idx = 0;
+
+  set_omega(omega);
+
+  // 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_timing_recovery_simple_cc::phase_error_detector_bpsk;
+    d_decision = &gr_timing_recovery_simple_cc::decision_bpsk;
+    break;
+
+  case 4: // optimized algorithms for QPSK
+    d_phase_error_detector = 
&gr_timing_recovery_simple_cc::phase_error_detector_qpsk;
+    d_decision = &gr_timing_recovery_simple_cc::decision_qpsk;
+    break;
+
+  default: // generic algorithms for any M (power of 2?) but not pretty
+    d_phase_error_detector = 
&gr_timing_recovery_simple_cc::phase_error_detector_generic;
+    d_decision = &gr_timing_recovery_simple_cc::decision_generic;
+    break;
+  }
+  
+  // FIXME: remove when we've got everything working
+  fout.open("timing_recovery.txt");
+}
+
+gr_timing_recovery_simple_cc::~gr_timing_recovery_simple_cc ()
+{
+  // FIXME: remove when we've got everything working
+  fout.close();
+  delete d_interp;
+}
+
+void
+gr_timing_recovery_simple_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] = d_samples_per_symbol+d_offset;
+}
+
+float
+gr_timing_recovery_simple_cc::phase_error_detector_qpsk(gr_complex sample) 
const
+{
+  return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() -
+         (sample.imag()>0 ? 1.0 : -1.0) * sample.real());
+}
+
+float
+gr_timing_recovery_simple_cc::phase_error_detector_bpsk(gr_complex sample) 
const
+{
+  return (sample.real()*sample.imag());
+}
+
+float gr_timing_recovery_simple_cc::phase_error_detector_generic(gr_complex 
sample) const
+{
+  unsigned int min_m = 0;
+  gr_complex constpoint;
+  float min_s = 65535;
+  float error = 0;
+
+  // Develop all possible constellation points and find the one that minimizes
+  // the Euclidean distance (error) with the sample
+  for(unsigned int m=0; m < d_M; m++) {
+    constpoint = gr_expj((M_TWOPI/d_M)*m + d_theta);
+    gr_complex diff = (constpoint - sample)*(constpoint - sample);
+    
+    if(fabs(diff.real()) < min_s) {
+      min_s = fabs(diff.real());
+      min_m = m;
+    }
+  }
+  // Use this constellation point to derotate the sample
+  constpoint = gr_expj(-((M_TWOPI/d_M)*min_m + d_theta));
+  // get the error in the sample as the phase difference from the real axis
+  error = gr_fast_atan2f(sample*constpoint);
+
+  return error;
+}
+
+gr_complex
+gr_timing_recovery_simple_cc::decision_bpsk(gr_complex sample) const
+{
+  float real=-0.5, imag=0.0;
+
+  // Implements a 1-demensional slicer
+  if(sample.real() > 0)
+    real = 0.5;
+  return gr_complex(real,imag);
+}
+
+gr_complex
+gr_timing_recovery_simple_cc::decision_qpsk(gr_complex sample) const
+{
+  float real=-0.5, imag=-0.5;
+
+  // Implements a simple slicer function
+  if(sample.real() > 0)
+    real = 0.5;
+  if(sample.imag() > 0)
+    imag = 0.5;
+  return gr_complex(real,imag);
+}
+
+gr_complex
+gr_timing_recovery_simple_cc::decision_generic(gr_complex sample) const
+{
+  unsigned int min_m = 0;
+  gr_complex constpoint;
+  float min_s = 65535;
+  
+  // Develop all possible constellation points and find the one that minimizes
+  // the Euclidean distance (error) with the sample
+  for(unsigned int m=0; m < d_M; m++) {
+    constpoint = gr_expj((M_TWOPI/d_M)*m + d_theta);
+    gr_complex diff = (constpoint - sample)*(constpoint - sample);
+    
+    if(fabs(diff.real()) < min_s) {
+      min_s = fabs(diff.real());
+      min_m = m;
+    }
+  }
+  // Return the constellation point that minimizes the error
+  constpoint = gr_expj(((M_TWOPI/d_M)*min_m + d_theta));
+  return constpoint;
+}
+
+int
+gr_timing_recovery_simple_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 phase_error = 0, mm_error = 0;
+  gr_complex sample, nco, u, x, y;
+  
+  int i=0, o=0;
+
+  while(i < ninput_items[0]) {    
+   
+    while((d_mu > 1) && (i < ninput_items[0]))  {
+      d_mu--;             // skip a number of symbols between sampling
+      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)
+       d_phase -= M_TWOPI;
+      while(d_phase<-M_TWOPI)
+       d_phase += M_TWOPI;
+
+      nco = gr_expj(-d_phase); // get the NCO value for derotating the current 
sample
+      sample = nco*in[i];      // get the downconverted symbol
+
+      // Fill up the delay line for the interpolator
+      d_dl[d_dl_idx] = sample;
+      d_dl[(d_dl_idx + DLLEN)] = sample;  // put this in the second half of 
the buffer for overflows
+      d_dl_idx = (d_dl_idx+1) % DLLEN;    // Keep the delay line index in 
bounds
+
+      #if 0
+      // FIXME: remove when we've got everything working
+      fout << d_mu << "\t" << sample.real() << " " << sample.imag();
+      if(d_mu < 1)
+       fout << "\t" << sample.real() << " " << sample.imag() << std::endl;
+      else
+       fout << "0 0" << std::endl;
+      #endif
+
+      i++;
+    }
+    
+    if(i < ninput_items[0]) {
+      d_offset = d_samples_per_symbol;
+      gr_complex interp_sample = d_interp->interpolate(&d_dl[d_dl_idx], d_mu);
+      
+      // Make sample timing corrections
+      d_p_2T = d_p_1T;
+      d_p_1T = d_p_0T;
+      d_p_0T = interp_sample;
+
+      d_c_2T = d_c_1T;
+      d_c_1T = d_c_0T;
+      d_c_0T = (*this.*d_decision)(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_error = u.real();
+      
+      // limit mm_val
+      if (mm_error > 1.0)
+       mm_error = 1.0;
+      else if (mm_error < -1.0)
+       mm_error = -1.0;
+      
+      d_omega = d_omega + d_gain_omega * mm_error;
+      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_omega + d_gain_mu * mm_error;
+      
+      #if 0
+      printf("samples: %f+j%f   mu: %f   omega: %f  mm_error: %f\n", 
+            interp_sample.real(), interp_sample.imag(), d_mu, d_omega, 
mm_error);
+      #endif
+
+      // Make phase and frequency corrections based on sampled value
+      phase_error = (*this.*d_phase_error_detector)(interp_sample);
+      d_freq += d_beta*phase_error;
+      d_phase += d_alpha*phase_error;
+
+      // FIXME: Add frequency clamping
+
+      out[o++] = d_p_0T; //interp_sample;
+    }
+
+    //printf("\t interpolated sample: %f+j*%f\n\n",  interp_sample.real(), 
interp_sample.imag());
+  }
+
+  consume_each(i);
+  return o;
+}

Added: 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h
===================================================================
--- 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h
                              (rev 0)
+++ 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h
      2007-01-01 19:41:54 UTC (rev 4207)
@@ -0,0 +1,307 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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 2, 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_GR_TIMING_RECOVERY_SIMPLE_CC_H
+#define        INCLUDED_GR_TIMING_RECOVERY_SIMPLE_CC_H
+
+#include <gr_block.h>
+#include <gr_complex.h>
+#include <fstream>
+
+class gri_mmse_fir_interpolator_cc;
+
+class gr_timing_recovery_simple_cc;
+typedef boost::shared_ptr<gr_timing_recovery_simple_cc> 
gr_timing_recovery_simple_cc_sptr;
+
+// public constructor
+gr_timing_recovery_simple_cc_sptr 
+gr_make_timing_recovery_simple_cc (unsigned int M, float theta, 
+                                  float alpha, float beta,
+                                  float fmin, float fmax,
+                                  float mu, float gain_mu, 
+                                  float omega, float gain_omega, float 
omega_rel);
+
+/*!
+ * \brief This block takes care of receiving M-PSK modulated signals through 
phase, frequency, and symbol
+ * synchronization. 
+ * \ingroup block
+ *
+ * This block takes care of receiving M-PSK modulated signals through phase, 
frequency, and symbol
+ * synchronization. It performs carrier frequency and phase locking as well as 
symbol timing recovery. 
+ * It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should 
also work for OQPSK and 
+ * PI/4 DQPSK.
+ *
+ * The phase and frequency synchronization are based on a Costas loop that 
finds the error of the incoming
+ * signal point compared to its nearest constellation point. The frequency and 
phase of the NCO are 
+ * updated according to this error. There are optimized phase error detectors 
for BPSK and QPSK, but 8PSK
+ * is done using a brute-force computation of the constellation points to find 
the minimum.
+ *
+ * The symbol synchronization is done using a modified Mueller and Muller 
circuit from the paper:
+ * 
+ *    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.
+ *
+ * This circuit interpolates the downconverted sample (using the NCO developed 
by the Costas loop)
+ * every mu samples, then it finds the sampling error based on this and the 
past symbols and the decision
+ * made on the samples. Like the phase error detector, there are optimized 
decision algorithms for BPSK
+ * and QPKS, but 8PSK uses another brute force computation against all 
possible symbols. The modifications
+ * to the M&M used here reduce self-noise.
+ *
+ */
+
+class gr_timing_recovery_simple_cc : public gr_block
+{
+ public:
+  ~gr_timing_recovery_simple_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);
+
+
+  // Member functions related to the symbol tracking portion of the receiver
+  //! (M&M) Returns current value of mu
+  float mu() const { return d_mu;}
+
+  //! (M&M) Returns current value of omega
+  float omega() const { return d_omega;}
+
+  //! (M&M) Returns mu gain factor
+  float gain_mu() const { return d_gain_mu;}
+
+  //! (M&M) Returns omega gain factor
+  float gain_omega() const { return d_gain_omega;}
+
+  //! (M&M) Sets value of mu
+  void set_mu (float mu) { d_mu = mu; }
+  
+  //! (M&M) Sets value of omega and its min and max values 
+  void set_omega (float omega) { 
+    d_omega = omega;
+    d_min_omega = omega*(1.0 - d_omega_rel);
+    d_max_omega = omega*(1.0 + d_omega_rel);
+  }
+
+  //! (M&M) Sets value for mu gain factor
+  void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
+
+  //! (M&M) Sets value for omega gain factor
+  void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
+
+
+
+  // Member function related to the phase/frequency tracking portion of the 
receiver
+  //! (CL) Returns the value for alpha (the phase gain term)
+  float alpha() const { return d_alpha; }
+  
+  //! (CL) Returns the value of beta (the frequency gain term)
+  float beta() const { return d_beta; }
+
+  //! (CL) Returns the current value of the frequency of the NCO in the Costas 
loop
+  float freq() const { return d_freq; }
+
+  //! (CL) Returns the current value of the phase of the NCO in the Costal loop
+  float phase() const { return d_phaes; }
+
+  //! (CL) Sets the value for alpha (the phase gain term)
+  void set_alpha(float alpha) { d_alpha = alpha; }
+  
+  //! (CL) Setss the value of beta (the frequency gain term)
+  float set_beta(float beta) { d_beta = beta; }
+
+  //! (CL) Sets the current value of the frequency of the NCO in the Costas 
loop
+  float set_freq(float freq) { d_freq = freq; }
+
+  //! (CL) Setss the current value of the phase of the NCO in the Costal loop
+  float set_phase(float phase) { d_phaes = phase; }
+
+
+protected:
+
+ /*!
+   * \brief Constructor to synchronize incoming M-PSK symbols
+   *
+   * \param M          modulation order of the M-PSK modulation
+   * \param theta      any constant phase rotation from the real axis of the 
constellation
+   * \param alpha      gain parameter to adjust the phase in the Costas loop 
(~0.01)
+   * \param beta        gain parameter to adjust the frequency in the Costas 
loop (~alpha^2/4) 
+   * \param fmin        minimum normalized frequency value the loop can achieve
+   * \param fmax        maximum normalized frequency value the loop can achieve
+   * \param mu          initial parameter for the interpolator [0,1]
+   * \param gain_mu     gain parameter of the M&M error signal to adjust mu 
(~0.05)
+   * \param omega       initial value for the number of symbols between 
samples (~number of samples/symbol)
+   * \param gain_omega  gain parameter to adjust omega based on the error 
(~omega^2/4)
+   * \param omega_rel   sets the maximum (omega*(1+omega_rel)) and minimum 
(omega*(1+omega_rel)) omega (~0.005)
+   *
+   * The constructor also chooses which phase detector and decision maker to 
use in the work loop based on the
+   * value of M.
+   */
+  gr_timing_recovery_simple_cc (unsigned int M, float theta, 
+                               float alpha, float beta,
+                               float fmin, float fmax,
+                               float mu, float gain_mu, 
+                               float omega, float gain_omega, float omega_rel);
+
+/*!
+   * \brief Phase error detector for MPSK modulations.
+   *
+   * \param sample   the I&Q sample from which to determine the phase error
+   *
+   * This function determines the phase error for any MPSK signal by creating 
a set of PSK constellation points
+   * and doing a brute-force search to see which point minimizes the Euclidean 
distance. This point is then used
+   * to derotate the sample to the real-axis and a atan (using the fast 
approximation function) to determine the
+   * phase difference between the incoming sample and the real constellation 
point
+   *
+   * This should be cleaned up and made more efficient.
+   *
+   * \returns the approximated phase error.
+ */
+  float phase_error_detector_generic(gr_complex sample) const; // generic for 
M but more costly
+
+ /*!
+   * \brief Phase error detector for BPSK modulation.
+   *
+   * \param sample   the I&Q sample from which to determine the phase error
+   *
+   * This function determines the phase error using a simple BPSK phase error 
detector by multiplying the real
+   * and imaginary (the error signal) components together. As the imaginary 
part goes to 0, so does this error.
+   *
+   * \returns the approximated phase error.
+ */
+  float phase_error_detector_bpsk(gr_complex sample) const;    // optimized 
for BPSK
+
+ /*!
+   * \brief Phase error detector for QPSK modulation.
+   *
+   * \param sample   the I&Q sample from which to determine the phase error
+   *
+   * This function determines the phase error using the limiter approach in a 
standard 4th order Costas loop
+   *
+   * \returns the approximated phase error.
+ */
+  float phase_error_detector_qpsk(gr_complex sample) const;
+ 
+
+
+ /*!
+   * \brief Decision maker for a generic MPSK constellation.
+   *
+   * \param sample   the baseband I&Q sample from which to make the decision
+   *
+   * This decision maker is a generic implementation the creates a set of 
constellation point for MPSK
+   * and does a brute-force search for the constellation point that minimizes 
the error from the incoming
+   * signal.
+   *
+   * \returns the constellation point that minimizes error.
+ */
+  gr_complex decision_generic(gr_complex sample) const;
+
+
+ /*!
+   * \brief Decision maker for BPSK constellation.
+   *
+   * \param sample   the baseband I&Q sample from which to make the decision
+   *
+   * This decision maker is a simple slicer function that makes a decision on 
the symbol based on its
+   * placement on the real axis of greater than 0 or less than 0; the 
quadrature component is always 0.
+   *
+   * \returns the constellation point that minimizes error.
+ */
+  gr_complex decision_bpsk(gr_complex sample) const;
+  
+
+ /*!
+   * \brief Decision maker for QPSK constellation.
+   *
+   * \param sample   the baseband I&Q sample from which to make the decision
+   *
+   * This decision maker is a simple slicer function that makes a decision on 
the symbol based on its
+   * placement versus both axes and returns which quadrant the symbol is in.
+   *
+   * \returns the constellation point that minimizes error.
+ */
+  gr_complex decision_qpsk(gr_complex sample) const;
+
+  private:
+  unsigned int d_M;
+  float        d_theta;
+
+  // Members related to carrier and phase tracking
+  float d_alpha;
+  float d_beta;
+  float d_freq;
+  float d_phase;
+
+/*!
+   * \brief Decision maker function pointer 
+   *
+   * \param sample   the baseband I&Q sample from which to make the decision
+   *
+   * This is a function pointer that is set in the constructor to point to the 
proper decision function
+   * for the specified constellation order.
+ */
+  gr_complex (gr_timing_recovery_simple_cc::*d_decision)(gr_complex sample) 
const; // pointer to decision function
+
+
+
+  // Members related to symbol timing
+  float d_mu, d_gain_mu;
+  float d_omega, d_gain_omega, d_omega_rel, d_min_omega, d_max_omega;
+  gr_complex d_p_2T, d_p_1T, d_p_0T;
+  gr_complex d_c_2T, d_c_1T, d_c_0T;
+
+ /*!
+   * \brief Phase error detector function pointer 
+   *
+   * \param sample   the I&Q sample from which to determine the phase error
+   *
+   * This is a function pointer that is set in the constructor to point to the 
proper phase error detector
+   * function for the specified constellation order.
+ */
+  float (gr_timing_recovery_simple_cc::*d_phase_error_detector)(gr_complex 
sample) const;
+
+
+  //! get interpolated value
+  gri_mmse_fir_interpolator_cc         *d_interp;
+  
+  //! delay line length.
+  static const unsigned int DLLEN = 8;
+  
+  //! delay line plus some length for overflow protection
+  gr_complex d_dl[2*DLLEN];
+  
+  //! index to delay line
+  unsigned int d_dl_idx;
+
+  // FIXME: remove this once we're satisfied it all works
+  std::ofstream fout;
+  
+  friend gr_timing_recovery_simple_cc_sptr
+  gr_make_timing_recovery_simple_cc (unsigned int M, float theta,
+                                    float alpha, float beta,
+                                    float fmin, float fmax,
+                                    float mu, float gain_mu, 
+                                    float omega, float gain_omega, float 
omega_rel);
+};
+
+#endif

Added: 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i
===================================================================
--- 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i
                              (rev 0)
+++ 
gnuradio/branches/developers/trondeau/digital-wip2/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i
      2007-01-01 19:41:54 UTC (rev 4207)
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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 2, 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(gr,timing_recovery_simple_cc);
+
+gr_timing_recovery_simple_cc_sptr gr_make_timing_recovery_simple_cc (unsigned 
int M, float theta,
+                                                                    float 
alpha, float beta,
+                                                                    float 
fmin, float fmax,
+                                                                    float mu, 
float gain_mu, 
+                                                                    float 
omega, float gain_omega, float omega_rel);
+class gr_timing_recovery_simple_cc : public gr_block
+{
+ private:
+  gr_timing_recovery_simple_cc (unsigned int M,float theta,
+                               float alpha, float beta,
+                               float fmin, float fmax,
+                               float mu, float gain_mu, 
+                               float omega, float gain_omega, float omega_rel);
+public:
+  unsigned int samples_per_symbol() const { return d_samples_per_symbol;}
+
+  void set_samples_per_symbol (unsigned int samples_per_symbol) { 
d_samples_per_symbol = samples_per_symbol; }
+};





reply via email to

[Prev in Thread] Current Thread [Next in Thread]