diff options
author | Josh Blum | 2011-09-05 22:35:52 -0700 |
---|---|---|
committer | Josh Blum | 2011-09-05 22:35:52 -0700 |
commit | 7628cff158a4bddaef5f38dc649ea9047008ed48 (patch) | |
tree | 18d32766d5dc97be3f24a5cedf38d018194d1f1c /gr-digital/lib | |
parent | f535cd0f1fbc7cfc753f5abbe99251a50cd32acb (diff) | |
parent | 65fbbb8f752ebf522ac2628f850445e66a278e2f (diff) | |
download | gnuradio-7628cff158a4bddaef5f38dc649ea9047008ed48.tar.gz gnuradio-7628cff158a4bddaef5f38dc649ea9047008ed48.tar.bz2 gnuradio-7628cff158a4bddaef5f38dc649ea9047008ed48.zip |
Merge branch 'digital' of https://github.com/trondeau/gnuradio into digital
Conflicts:
gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h
gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h
gr-digital/lib/digital_constellation.h
gr-digital/lib/digital_constellation_receiver_cb.h
gr-digital/lib/digital_fll_band_edge_cc.h
gr-digital/lib/digital_mpsk_receiver_cc.h
Diffstat (limited to 'gr-digital/lib')
-rw-r--r-- | gr-digital/lib/Makefile.am | 3 | ||||
-rw-r--r-- | gr-digital/lib/digital_constellation.cc | 86 | ||||
-rw-r--r-- | gr-digital/lib/digital_constellation.h | 90 | ||||
-rw-r--r-- | gr-digital/lib/digital_constellation_receiver_cb.cc | 145 | ||||
-rw-r--r-- | gr-digital/lib/digital_constellation_receiver_cb.h | 147 | ||||
-rw-r--r-- | gr-digital/lib/digital_fll_band_edge_cc.cc | 139 | ||||
-rw-r--r-- | gr-digital/lib/digital_fll_band_edge_cc.h | 218 | ||||
-rw-r--r-- | gr-digital/lib/digital_mpsk_receiver_cc.cc | 36 | ||||
-rw-r--r-- | gr-digital/lib/digital_mpsk_receiver_cc.h | 169 |
9 files changed, 316 insertions, 717 deletions
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am index 4a9359fce..ce961ef2e 100644 --- a/gr-digital/lib/Makefile.am +++ b/gr-digital/lib/Makefile.am @@ -61,6 +61,7 @@ libgnuradio_digital_la_SOURCES = \ digital_mpsk_receiver_cc.cc libgnuradio_digital_la_LIBADD = \ - $(GNURADIO_CORE_LA) + $(GNURADIO_CORE_LA) \ + $(abs_top_builddir)/gr-digital/hier/libdigital_hier.la libgnuradio_digital_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS) diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index d1f218439..0c100f38e 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -411,6 +411,20 @@ digital_constellation_qpsk::digital_constellation_qpsk () d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO); d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO); d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO); + + /* + d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO); + d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO); + d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO); + d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO); + */ + + d_pre_diff_code.resize(4); + d_pre_diff_code[0] = 0x0; + d_pre_diff_code[1] = 0x2; + d_pre_diff_code[2] = 0x3; + d_pre_diff_code[3] = 0x1; + d_rotational_symmetry = 4; d_dimensionality = 1; calc_arity(); @@ -422,8 +436,80 @@ digital_constellation_qpsk::decision_maker(const gr_complex *sample) // Real component determines small bit. // Imag component determines big bit. return 2*(imag(*sample)>0) + (real(*sample)>0); + + /* + bool a = real(*sample) > 0; + bool b = imag(*sample) > 0; + if(a) { + if(b) + return 0x0; + else + return 0x1; + } + else { + if(b) + return 0x2; + else + return 0x3; + } + */ +} + + +/********************************************************************/ + + +digital_constellation_dqpsk_sptr +digital_make_constellation_dqpsk() +{ + return digital_constellation_dqpsk_sptr(new digital_constellation_dqpsk ()); } +digital_constellation_dqpsk::digital_constellation_dqpsk () +{ + // This constellation is not gray coded, which allows + // us to use differential encodings (through gr_diff_encode and + // gr_diff_decode) on the symbols. + d_constellation.resize(4); + d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO); + d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO); + d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO); + d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO); + + // Use this mapping to convert to gray code before diff enc. + d_pre_diff_code.resize(4); + d_pre_diff_code[0] = 0x0; + d_pre_diff_code[1] = 0x1; + d_pre_diff_code[2] = 0x3; + d_pre_diff_code[3] = 0x2; + d_apply_pre_diff_code = true; + + d_rotational_symmetry = 4; + d_dimensionality = 1; + calc_arity(); +} + +unsigned int +digital_constellation_dqpsk::decision_maker(const gr_complex *sample) +{ + // Slower deicison maker as we can't slice along one axis. + // Maybe there's a better way to do this, still. + + bool a = real(*sample) > 0; + bool b = imag(*sample) > 0; + if(a) { + if(b) + return 0x0; + else + return 0x3; + } + else { + if(b) + return 0x1; + else + return 0x2; + } +} digital_constellation_8psk_sptr digital_make_constellation_8psk() diff --git a/gr-digital/lib/digital_constellation.h b/gr-digital/lib/digital_constellation.h index df00f3898..9b2a58588 100644 --- a/gr-digital/lib/digital_constellation.h +++ b/gr-digital/lib/digital_constellation.h @@ -42,8 +42,10 @@ typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr; class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation> { public: - digital_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); + digital_constellation (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); digital_constellation (); //! Returns the constellation points for a symbol value @@ -74,6 +76,8 @@ public: std::vector<std::vector<gr_complex> > v_points(); //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding) bool apply_pre_diff_code() { return d_apply_pre_diff_code;} + //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding) + void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;} //! Returns the encoding to apply before differential encoding. std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;} //! Returns the order of rotational symmetry. @@ -82,7 +86,7 @@ public: unsigned int dimensionality() {return d_dimensionality;} unsigned int bits_per_symbol () { - return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0)); + return floor(log(d_constellation.size())/d_dimensionality/log(2)); } unsigned int arity () { @@ -120,17 +124,19 @@ typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_ // public constructor DIGITAL_API digital_constellation_calcdist_sptr -digital_make_constellation_calcdist (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); +digital_make_constellation_calcdist (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); class DIGITAL_API digital_constellation_calcdist : public digital_constellation { public: digital_constellation_calcdist (std::vector<gr_complex> constellation, - std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality); + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); unsigned int decision_maker (const gr_complex *sample); // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type); // void calc_euclidean_metric(gr_complex *sample, float *metric); @@ -155,10 +161,10 @@ class DIGITAL_API digital_constellation_sector : public digital_constellation public: digital_constellation_sector (std::vector<gr_complex> constellation, - std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - unsigned int n_sectors); + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + unsigned int n_sectors); unsigned int decision_maker (const gr_complex *sample); @@ -194,19 +200,25 @@ typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect // public constructor DIGITAL_API digital_constellation_rect_sptr -digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); +digital_make_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); class DIGITAL_API digital_constellation_rect : public digital_constellation_sector { public: - digital_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); + digital_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); protected: @@ -222,10 +234,13 @@ class DIGITAL_API digital_constellation_rect : public digital_constellation_sect float d_width_imag_sectors; friend DIGITAL_API digital_constellation_rect_sptr - digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); + digital_make_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); }; @@ -323,6 +338,33 @@ class DIGITAL_API digital_constellation_qpsk : public digital_constellation }; +/************************************************************/ +/* digital_constellation_dqpsk */ +/* */ +/* Works with differential encoding; slower decisions. */ +/* */ +/************************************************************/ + +//! \brief DQPSK-specific constellation and decision maker +class digital_constellation_dqpsk; +typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr; + +// public constructor +DIGITAL_API digital_constellation_dqpsk_sptr +digital_make_constellation_dqpsk (); + +class DIGITAL_API digital_constellation_dqpsk : public digital_constellation +{ + public: + + digital_constellation_dqpsk (); + unsigned int decision_maker (const gr_complex *sample); + + friend DIGITAL_API digital_constellation_dqpsk_sptr + digital_make_constellation_dqpsk (); + +}; + /************************************************************/ /* digital_constellation_8psk */ diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc index e2b6bf1d8..b9239962a 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.cc +++ b/gr-digital/lib/digital_constellation_receiver_cb.cc @@ -54,153 +54,20 @@ digital_constellation_receiver_cb::digital_constellation_receiver_cb (digital_co : gr_block ("constellation_receiver_cb", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signaturev (1, 4, iosig)), - d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0), + gri_control_loop(loop_bw, fmax, fmin), d_constellation(constellation), d_current_const_point(0) { if (d_constellation->dimensionality() != 1) throw std::runtime_error ("This receiver only works with constellations of dimension 1."); - - // Set the damping factor for a critically damped system - d_damping = sqrtf(2.0f)/2.0f; - - // Set the bandwidth, which will then call update_gains() - set_loop_bandwidth(loop_bw); -} - - -/******************************************************************* - SET FUNCTIONS -*******************************************************************/ - -void -digital_constellation_receiver_cb::set_loop_bandwidth(float bw) -{ - if(bw < 0) { - throw std::out_of_range ("digital_constellation_receiver_cb: invalid bandwidth. Must be >= 0."); - } - - d_loop_bw = bw; - update_gains(); -} - -void -digital_constellation_receiver_cb::set_damping_factor(float df) -{ - if(df < 0 || df > 1.0) { - throw std::out_of_range ("digital_constellation_receiver_cb: invalid damping factor. Must be in [0,1]."); - } - - d_damping = df; - update_gains(); -} - -void -digital_constellation_receiver_cb::set_alpha(float alpha) -{ - if(alpha < 0 || alpha > 1.0) { - throw std::out_of_range ("digital_constellation_receiver_cb: invalid alpha. Must be in [0,1]."); - } - d_alpha = alpha; -} - -void -digital_constellation_receiver_cb::set_beta(float beta) -{ - if(beta < 0 || beta > 1.0) { - throw std::out_of_range ("digital_constellation_receiver_cb: invalid beta. Must be in [0,1]."); - } - d_beta = beta; -} - -void -digital_constellation_receiver_cb::set_frequency(float freq) -{ - if(freq > d_max_freq) - d_freq = d_min_freq; - else if(freq < d_min_freq) - d_freq = d_max_freq; - else - d_freq = freq; -} - -void -digital_constellation_receiver_cb::set_phase(float phase) -{ - d_phase = phase; - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; -} - - -/******************************************************************* - GET FUNCTIONS -*******************************************************************/ - - -float -digital_constellation_receiver_cb::get_loop_bandwidth() const -{ - return d_loop_bw; -} - -float -digital_constellation_receiver_cb::get_damping_factor() const -{ - return d_damping; -} - -float -digital_constellation_receiver_cb::get_alpha() const -{ - return d_alpha; -} - -float -digital_constellation_receiver_cb::get_beta() const -{ - return d_beta; -} - -float -digital_constellation_receiver_cb::get_frequency() const -{ - return d_freq; -} - -float -digital_constellation_receiver_cb::get_phase() const -{ - return d_phase; -} - -/******************************************************************* -*******************************************************************/ - -void -digital_constellation_receiver_cb::update_gains() -{ - float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); - d_alpha = (4*d_damping*d_loop_bw) / denom; - d_beta = (4*d_loop_bw*d_loop_bw) / denom; } void digital_constellation_receiver_cb::phase_error_tracking(float phase_error) { - 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) - d_phase -= M_TWOPI; - while(d_phase < -M_TWOPI) - d_phase += M_TWOPI; - - // Limit the frequency range - d_freq = gr_branchless_clip(d_freq, d_max_freq); + advance_loop(phase_error); + phase_wrap(); + frequency_limit(); #if VERBOSE_COSTAS printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n", @@ -236,10 +103,12 @@ digital_constellation_receiver_cb::general_work (int noutput_items, sample = in[i]; nco = gr_expj(d_phase); // get the NCO value for derotating the current sample sample = nco*sample; // get the downconverted symbol + sym_value = d_constellation->decision_maker_pe(&sample, &phase_error); - // phase_error = -arg(sample*conj(d_constellation->points()[sym_value])); phase_error_tracking(phase_error); // corrects phase and frequency offsets + out[i] = sym_value; + if(output_items.size() == 4) { out_err[i] = phase_error; out_phase[i] = d_phase; diff --git a/gr-digital/lib/digital_constellation_receiver_cb.h b/gr-digital/lib/digital_constellation_receiver_cb.h index 5e414dfed..d33be8958 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.h +++ b/gr-digital/lib/digital_constellation_receiver_cb.h @@ -26,6 +26,7 @@ #include <digital_api.h> #include <gr_block.h> #include <digital_constellation.h> +#include <gri_control_loop.h> #include <gr_complex.h> #include <math.h> #include <fstream> @@ -64,134 +65,14 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation * */ -class DIGITAL_API digital_constellation_receiver_cb : public gr_block +class DIGITAL_API digital_constellation_receiver_cb : public gr_block, public gri_control_loop { - public: +public: int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - - /******************************************************************* - SET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Set the loop bandwidth - * - * Set the loop filter's bandwidth to \p bw. This should be between - * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive - * number. - * - * When a new damping factor is set, the gains, alpha and beta, of the loop - * are recalculated by a call to update_gains(). - * - * \param bw (float) new bandwidth - * - */ - void set_loop_bandwidth(float bw); - - /*! - * \brief Set the loop damping factor - * - * Set the loop filter's damping factor to \p df. The damping factor - * should be sqrt(2)/2.0 for critically damped systems. - * Set it to anything else only if you know what you are doing. It must - * be a number between 0 and 1. - * - * When a new damping factor is set, the gains, alpha and beta, of the loop - * are recalculated by a call to update_gains(). - * - * \param df (float) new damping factor - * - */ - void set_damping_factor(float df); - - /*! - * \brief Set the loop gain alpha - * - * Set's the loop filter's alpha gain parameter. - * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. - * - * \param alpha (float) new alpha gain - * - */ - void set_alpha(float alpha); - - /*! - * \brief Set the loop gain beta - * - * Set's the loop filter's beta gain parameter. - * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. - * - * \param beta (float) new beta gain - * - */ - void set_beta(float beta); - - /*! - * \brief Set the phase/freq recovery loop's frequency. - * - * Set's the phase/freq recovery loop's frequency. While this is normally - * updated by the inner loop of the algorithm, it could be useful to - * manually initialize, set, or reset this under certain circumstances. - * - * \param freq (float) new frequency - * - */ - void set_frequency(float freq); - - /*! - * \brief Set the phase/freq recovery loop's phase. - * - * Set's the phase/freq recovery loop's phase. While this is normally - * updated by the inner loop of the algorithm, it could be useful to - * manually initialize, set, or reset this under certain circumstances. - * - * \param phase (float) new phase - * - */ - void set_phase(float phase); - - /******************************************************************* - GET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Returns the loop bandwidth - */ - float get_loop_bandwidth() const; - - /*! - * \brief Returns the loop damping factor - */ - float get_damping_factor() const; - - /*! - * \brief Returns the loop gain alpha - */ - float get_alpha() const; - - /*! - * \brief Returns the loop gain beta - */ - float get_beta() const; - - /*! - * \brief Get the phase/freq recovery loop's frequency estimate - */ - float get_frequency() const; - - /*! - * \brief Get the phase/freq loop's phase estimate - */ - float get_phase() const; - protected: /*! @@ -211,18 +92,9 @@ protected: void phase_error_tracking(float phase_error); - private: +private: unsigned int d_M; - // Members related to carrier and phase tracking - float d_freq, d_max_freq, d_min_freq; - float d_phase; - - float d_loop_bw; - float d_damping; - float d_alpha; - float d_beta; - digital_constellation_sptr d_constellation; unsigned int d_current_const_point; @@ -230,20 +102,11 @@ protected: static const unsigned int DLLEN = 8; //! delay line plus some length for overflow protection - __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN]; + gr_complex d_dl[2*DLLEN] __attribute__ ((aligned(8))); //! index to delay line unsigned int d_dl_idx; - /*! \brief update the system gains from the loop bandwidth and damping factor - * - * This function updates the system gains based on the loop - * bandwidth and damping factor of the system. - * These two factors can be set separately through their own - * set functions. - */ - void update_gains(); - friend DIGITAL_API digital_constellation_receiver_cb_sptr digital_make_constellation_receiver_cb (digital_constellation_sptr constell, float loop_bw, float fmin, float fmax); diff --git a/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc index 70cb54351..05c092622 100644 --- a/gr-digital/lib/digital_fll_band_edge_cc.cc +++ b/gr-digital/lib/digital_fll_band_edge_cc.cc @@ -55,6 +55,7 @@ digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float r : gr_sync_block ("fll_band_edge_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)), gr_make_io_signaturev (1, 4, iosig)), + gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), -M_TWOPI*(2.0/samps_per_sym)), d_updated (false) { // Initialize samples per symbol @@ -75,22 +76,8 @@ digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float r } d_filter_size = filter_size; - // base this on the number of samples per symbol - d_max_freq = M_TWOPI * (2.0/samps_per_sym); - d_min_freq = -M_TWOPI * (2.0/samps_per_sym); - - // Set the damping factor for a critically damped system - d_damping = sqrtf(2.0f)/2.0f; - - // Set the bandwidth, which will then call update_gains() - set_loop_bandwidth(bandwidth); - // Build the band edge filters design_filter(d_sps, d_rolloff, d_filter_size); - - // Initialize loop values - d_freq = 0; - d_phase = 0; } digital_fll_band_edge_cc::~digital_fll_band_edge_cc () @@ -102,47 +89,6 @@ digital_fll_band_edge_cc::~digital_fll_band_edge_cc () SET FUNCTIONS *******************************************************************/ - -void -digital_fll_band_edge_cc::set_loop_bandwidth(float bw) -{ - if(bw < 0) { - throw std::out_of_range ("digital_fll_band_edge_cc: invalid bandwidth. Must be >= 0."); - } - - d_loop_bw = bw; - update_gains(); -} - -void -digital_fll_band_edge_cc::set_damping_factor(float df) -{ - if(df < 0 || df > 1.0) { - throw std::out_of_range ("digital_fll_band_edge_cc: invalid damping factor. Must be in [0,1]."); - } - - d_damping = df; - update_gains(); -} - -void -digital_fll_band_edge_cc::set_alpha(float alpha) -{ - if(alpha < 0 || alpha > 1.0) { - throw std::out_of_range ("digital_fll_band_edge_cc: invalid alpha. Must be in [0,1]."); - } - d_alpha = alpha; -} - -void -digital_fll_band_edge_cc::set_beta(float beta) -{ - if(beta < 0 || beta > 1.0) { - throw std::out_of_range ("digital_fll_band_edge_cc: invalid beta. Must be in [0,1]."); - } - d_beta = beta; -} - void digital_fll_band_edge_cc::set_samples_per_symbol(float sps) { @@ -173,57 +119,10 @@ digital_fll_band_edge_cc::set_filter_size(int filter_size) design_filter(d_sps, d_rolloff, d_filter_size); } -void -digital_fll_band_edge_cc::set_frequency(float freq) -{ - if(freq > d_max_freq) - d_freq = d_min_freq; - else if(freq < d_min_freq) - d_freq = d_max_freq; - else - d_freq = freq; -} - -void -digital_fll_band_edge_cc::set_phase(float phase) -{ - d_phase = phase; - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; -} - - /******************************************************************* GET FUNCTIONS *******************************************************************/ - -float -digital_fll_band_edge_cc::get_loop_bandwidth() const -{ - return d_loop_bw; -} - -float -digital_fll_band_edge_cc::get_damping_factor() const -{ - return d_damping; -} - -float -digital_fll_band_edge_cc::get_alpha() const -{ - return d_alpha; -} - -float -digital_fll_band_edge_cc::get_beta() const -{ - return d_beta; -} - float digital_fll_band_edge_cc::get_samples_per_symbol() const { @@ -242,31 +141,10 @@ digital_fll_band_edge_cc:: get_filter_size() const return d_filter_size; } -float -digital_fll_band_edge_cc::get_frequency() const -{ - return d_freq; -} - -float -digital_fll_band_edge_cc::get_phase() const -{ - return d_phase; -} - /******************************************************************* *******************************************************************/ - -void -digital_fll_band_edge_cc::update_gains() -{ - float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); - d_alpha = (4*d_damping*d_loop_bw) / denom; - d_beta = (4*d_loop_bw*d_loop_bw) / denom; -} - void digital_fll_band_edge_cc::design_filter(float samps_per_sym, float rolloff, int filter_size) @@ -366,18 +244,9 @@ digital_fll_band_edge_cc::work (int noutput_items, } error = norm(out_lower) - norm(out_upper); - d_freq = d_freq + d_beta * error; - d_phase = d_phase + d_freq + d_alpha * error; - - if(d_phase > M_PI) - d_phase -= M_TWOPI; - else if(d_phase < -M_PI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; + advance_loop(error); + phase_wrap(); + frequency_limit(); if(output_items.size() == 4) { frq[i] = d_freq; diff --git a/gr-digital/lib/digital_fll_band_edge_cc.h b/gr-digital/lib/digital_fll_band_edge_cc.h index c7a56a7c9..6ef8376ac 100644 --- a/gr-digital/lib/digital_fll_band_edge_cc.h +++ b/gr-digital/lib/digital_fll_band_edge_cc.h @@ -26,6 +26,7 @@ #include <digital_api.h> #include <gr_sync_block.h> +#include <gri_control_loop.h> class digital_fll_band_edge_cc; typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr; @@ -40,39 +41,51 @@ DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float s * * \ingroup general * - * The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths - * of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth - * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges - * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth. - * The size of the filters should be fairly large so as to average over a number of symbols. + * The frequency lock loop derives a band-edge filter that covers the + * upper and lower bandwidths of a digitally-modulated signal. The + * bandwidth range is determined by the excess bandwidth (e.g., + * rolloff factor) of the modulated signal. The placement in frequency + * of the band-edges is determined by the oversampling ratio (number + * of samples per symbol) and the excess bandwidth. The size of the + * filters should be fairly large so as to average over a number of + * symbols. * - * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively. - * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining - * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the complex conjugate) - * provides an error signal at the DC term that is directly proportional to the carrier frequency. - * We then make a second-order loop using the error signal that is the running average of e(t). + * The FLL works by filtering the upper and lower band edges into + * x_u(t) and x_l(t), respectively. These are combined to form cc(t) + * = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to + * form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the + * complex conjugate) provides an error signal at the DC term that is + * directly proportional to the carrier frequency. We then make a + * second-order loop using the error signal that is the running + * average of e(t). * - * In practice, the above equation can be simplified by just comparing the absolute value squared - * of the output of both filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)). + * In practice, the above equation can be simplified by just comparing + * the absolute value squared of the output of both filters: + * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)). * - * In theory, the band-edge filter is the derivative of the matched filter in frequency, - * (H_be(f) = \\frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point - * of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine). - * Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent - * in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore - * derived from this sum of sincs. The band edge filters are then just the baseband signal - * modulated to the correct place in frequency. All of these calculations are done in the + * In theory, the band-edge filter is the derivative of the matched + * filter in frequency, (H_be(f) = \\frac{H(f)}{df}. In practice, this + * comes down to a quarter sine wave at the point of the matched + * filter's rolloff (if it's a raised-cosine, the derivative of a + * cosine is a sine). Extend this sine by another quarter wave to + * make a half wave around the band-edges is equivalent in time to the + * sum of two sinc functions. The baseband filter fot the band edges + * is therefore derived from this sum of sincs. The band edge filters + * are then just the baseband signal modulated to the correct place in + * frequency. All of these calculations are done in the * 'design_filter' function. * - * Note: We use FIR filters here because the filters have to have a flat phase response over the - * entire frequency range to allow their comparisons to be valid. + * Note: We use FIR filters here because the filters have to have a + * flat phase response over the entire frequency range to allow their + * comparisons to be valid. * - * It is very important that the band edge filters be the derivatives of the pulse shaping filter, - * and that they be linear phase. Otherwise, the variance of the error will be very large. + * It is very important that the band edge filters be the derivatives + * of the pulse shaping filter, and that they be linear + * phase. Otherwise, the variance of the error will be very large. * */ -class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block +class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop { private: /*! @@ -90,21 +103,11 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block float d_sps; float d_rolloff; int d_filter_size; - float d_max_freq; - float d_min_freq; - - float d_loop_bw; - float d_damping; - float d_alpha; - float d_beta; std::vector<gr_complex> d_taps_lower; std::vector<gr_complex> d_taps_upper; bool d_updated; - float d_freq; - float d_phase; - /*! * Build the FLL * \param samps_per_sym (float) number of samples per symbol @@ -116,11 +119,6 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block int filter_size, float bandwidth); /*! - * \brief Update the gains, alpha and beta, of the loop filter. - */ - void update_gains(); - - /*! * Design the band-edge filter based on the number of samples per symbol, * filter rolloff factor, and the filter size * @@ -138,67 +136,11 @@ public: *******************************************************************/ /*! - * \brief Set the loop bandwidth - * - * Set the loop filter's bandwidth to \p bw. This should be between - * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive - * number. - * - * When a new damping factor is set, the gains, alpha and beta, of the loop - * are recalculated by a call to update_gains(). - * - * \param bw (float) new bandwidth - * - */ - void set_loop_bandwidth(float bw); - - /*! - * \brief Set the loop damping factor - * - * Set the loop filter's damping factor to \p df. The damping factor - * should be sqrt(2)/2.0 for critically damped systems. - * Set it to anything else only if you know what you are doing. It must - * be a number between 0 and 1. - * - * When a new damping factor is set, the gains, alpha and beta, of the loop - * are recalculated by a call to update_gains(). - * - * \param df (float) new damping factor - * - */ - void set_damping_factor(float df); - - /*! - * \brief Set the loop gain alpha - * - * Set's the loop filter's alpha gain parameter. - * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. - * - * \param alpha (float) new alpha gain - * - */ - void set_alpha(float alpha); - - /*! - * \brief Set the loop gain beta - * - * Set's the loop filter's beta gain parameter. - * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. - * - * \param beta (float) new beta gain - * - */ - void set_beta(float beta); - - /*! * \brief Set the number of samples per symbol * - * Set's the number of samples per symbol the system should use. This value - * is uesd to calculate the filter taps and will force a recalculation. + * Set's the number of samples per symbol the system should + * use. This value is uesd to calculate the filter taps and will + * force a recalculation. * * \param sps (float) new samples per symbol * @@ -208,13 +150,14 @@ public: /*! * \brief Set the rolloff factor of the shaping filter * - * This sets the rolloff factor that is used in the pulse shaping filter - * and is used to calculate the filter taps. Changing this will force a - * recalculation of the filter taps. + * This sets the rolloff factor that is used in the pulse shaping + * filter and is used to calculate the filter taps. Changing this + * will force a recalculation of the filter taps. * - * This should be the same value that is used in the transmitter's pulse - * shaping filter. It must be between 0 and 1 and is usually between - * 0.2 and 0.5 (where 0.22 and 0.35 are commonly used values). + * This should be the same value that is used in the transmitter's + * pulse shaping filter. It must be between 0 and 1 and is usually + * between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used + * values). * * \param rolloff (float) new shaping filter rolloff factor [0,1] * @@ -224,68 +167,25 @@ public: /*! * \brief Set the number of taps in the filter * - * This sets the number of taps in the band-edge filters. Setting this will - * force a recalculation of the filter taps. + * This sets the number of taps in the band-edge filters. Setting + * this will force a recalculation of the filter taps. * - * This should be about the same number of taps used in the transmitter's - * shaping filter and also not very large. A large number of taps will - * result in a large delay between input and frequency estimation, and - * so will not be as accurate. Between 30 and 70 taps is usual. + * This should be about the same number of taps used in the + * transmitter's shaping filter and also not very large. A large + * number of taps will result in a large delay between input and + * frequency estimation, and so will not be as accurate. Between 30 + * and 70 taps is usual. * * \param filter_size (float) number of taps in the filters * */ void set_filter_size(int filter_size); - /*! - * \brief Set the FLL's frequency. - * - * Set's the FLL's frequency. While this is normally updated by the - * inner loop of the algorithm, it could be useful to manually initialize, - * set, or reset this under certain circumstances. - * - * \param freq (float) new frequency - * - */ - void set_frequency(float freq); - - /*! - * \brief Set the FLL's phase. - * - * Set's the FLL's phase. While this is normally updated by the - * inner loop of the algorithm, it could be useful to manually initialize, - * set, or reset this under certain circumstances. - * - * \param phase (float) new phase - * - */ - void set_phase(float phase); - /******************************************************************* GET FUNCTIONS *******************************************************************/ /*! - * \brief Returns the loop bandwidth - */ - float get_loop_bandwidth() const; - - /*! - * \brief Returns the loop damping factor - */ - float get_damping_factor() const; - - /*! - * \brief Returns the loop gain alpha - */ - float get_alpha() const; - - /*! - * \brief Returns the loop gain beta - */ - float get_beta() const; - - /*! * \brief Returns the number of sampler per symbol used for the filter */ float get_samples_per_symbol() const; @@ -301,16 +201,6 @@ public: int get_filter_size() const; /*! - * \brief Get the FLL's frequency estimate - */ - float get_frequency() const; - - /*! - * \brief Get the FLL's phase estimate - */ - float get_phase() const; - - /*! * Print the taps to screen. */ void print_taps(); diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc index 3b2ea9840..363b86c9f 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.cc +++ b/gr-digital/lib/digital_mpsk_receiver_cc.cc @@ -41,28 +41,30 @@ digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc(unsigned int M, float theta, - float alpha, float beta, + float loop_bw, float fmin, float fmax, float mu, float gain_mu, float omega, float gain_omega, float omega_rel) { return gnuradio::get_initial_sptr(new digital_mpsk_receiver_cc (M, theta, - alpha, beta, - fmin, fmax, - mu, gain_mu, - omega, gain_omega, omega_rel)); + loop_bw, + fmin, fmax, + mu, gain_mu, + omega, gain_omega, + omega_rel)); } digital_mpsk_receiver_cc::digital_mpsk_receiver_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) + float loop_bw, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, + float omega_rel) : gr_block ("mpsk_receiver_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_control_loop(loop_bw, fmax, fmin), d_M(M), d_theta(theta), - d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0), d_current_const_point(0), d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega), d_omega_rel(omega_rel), d_max_omega(0), d_min_omega(0), @@ -265,18 +267,10 @@ digital_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); - - 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) - d_phase -= M_TWOPI; - while(d_phase < -M_TWOPI) - d_phase += M_TWOPI; - // Limit the frequency range - d_freq = gr_branchless_clip(d_freq, d_max_freq); + advance_loop(phase_error); + phase_wrap(); + frequency_limit(); #if VERBOSE_COSTAS printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n", diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.h b/gr-digital/lib/digital_mpsk_receiver_cc.h index 8a6352ec7..85cd81e99 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.h +++ b/gr-digital/lib/digital_mpsk_receiver_cc.h @@ -25,6 +25,7 @@ #include <digital_api.h> #include <gruel/attributes.h> +#include <gri_control_loop.h> #include <gr_block.h> #include <gr_complex.h> #include <fstream> @@ -37,41 +38,48 @@ typedef boost::shared_ptr<digital_mpsk_receiver_cc> digital_mpsk_receiver_cc_spt // public constructor DIGITAL_API digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, + float loop_bw, 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. + * \brief This block takes care of receiving M-PSK modulated signals + * through phase, frequency, and symbol synchronization. * \ingroup sync_blk * \ingroup demod_blk * - * 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. + * 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 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: + * 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. + * 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. + * 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 DIGITAL_API digital_mpsk_receiver_cc : public gr_block +class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control_loop { public: ~digital_mpsk_receiver_cc (); @@ -112,43 +120,14 @@ class DIGITAL_API digital_mpsk_receiver_cc : public gr_block //! (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_phase; } - - //! (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) - void set_beta(float beta) { d_beta = beta; } - - //! (CL) Sets the current value of the frequency of the NCO in the Costas loop - void set_freq(float freq) { d_freq = freq; } - - //! (CL) Setss the current value of the phase of the NCO in the Costal loop - void set_phase(float phase) { d_phase = 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 loop_bw Loop bandwidth to set gains of phase/freq tracking loop * \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] @@ -161,7 +140,7 @@ protected: * value of M. */ digital_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, + float loop_bw, float fmin, float fmax, float mu, float gain_mu, float omega, float gain_omega, float omega_rel); @@ -172,54 +151,61 @@ protected: void phase_error_tracking(gr_complex sample); -/*! + /*! * \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 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. + * 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 + * 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 that does a brute-force search - * for the constellation point that minimizes the error between it and the incoming signal. + * This decision maker is a generic implementation that does a + * brute-force search for the constellation point that minimizes the + * error between it and the incoming signal. * * \returns the index to d_constellation that minimizes the error/ */ @@ -231,46 +217,44 @@ protected: * * \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. + * 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 index to d_constellation that minimizes the error/ - */ + */ unsigned int 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. + * 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 index to d_constellation that minimizes the error/ - */ + */ unsigned int decision_qpsk(gr_complex sample) const; - private: +private: unsigned int d_M; float d_theta; - // Members related to carrier and phase tracking - float d_alpha; - float d_beta; - float d_freq, d_max_freq, d_min_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. + * This is a function pointer that is set in the constructor to + * point to the proper decision function for the specified + * constellation order. * * \return index into d_constellation point that is the closest to the recieved sample - */ + */ unsigned int (digital_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function @@ -283,14 +267,15 @@ protected: 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. - */ + * 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 (digital_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const; @@ -308,7 +293,7 @@ protected: friend DIGITAL_API digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, + float loop_bw, float fmin, float fmax, float mu, float gain_mu, float omega, float gain_omega, float omega_rel); |