summaryrefslogtreecommitdiff
path: root/gr-digital/include
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/include')
-rw-r--r--gr-digital/include/.gitignore2
-rw-r--r--gr-digital/include/Makefile.am50
-rw-r--r--gr-digital/include/digital_binary_slicer_fb.h52
-rw-r--r--gr-digital/include/digital_clock_recovery_mm_cc.h116
-rw-r--r--gr-digital/include/digital_clock_recovery_mm_ff.h99
-rw-r--r--gr-digital/include/digital_cma_equalizer_cc.h102
-rw-r--r--gr-digital/include/digital_constellation.h448
-rw-r--r--gr-digital/include/digital_constellation_decoder_cb.h65
-rw-r--r--gr-digital/include/digital_constellation_receiver_cb.h121
-rw-r--r--gr-digital/include/digital_correlate_access_code_bb.h84
-rw-r--r--gr-digital/include/digital_costas_loop_cc.h117
-rw-r--r--gr-digital/include/digital_cpmmod_bc.h96
-rw-r--r--gr-digital/include/digital_crc32.h50
-rw-r--r--gr-digital/include/digital_fll_band_edge_cc.h213
-rw-r--r--gr-digital/include/digital_gmskmod_bc.h62
-rw-r--r--gr-digital/include/digital_kurtotic_equalizer_cc.h112
-rw-r--r--gr-digital/include/digital_lms_dd_equalizer_cc.h117
-rw-r--r--gr-digital/include/digital_metric_type.h31
-rw-r--r--gr-digital/include/digital_mpsk_receiver_cc.h302
-rw-r--r--gr-digital/include/digital_ofdm_cyclic_prefixer.h58
-rw-r--r--gr-digital/include/digital_ofdm_frame_acquisition.h116
-rw-r--r--gr-digital/include/digital_ofdm_frame_sink.h126
-rw-r--r--gr-digital/include/digital_ofdm_insert_preamble.h104
-rw-r--r--gr-digital/include/digital_ofdm_mapper_bcv.h87
-rw-r--r--gr-digital/include/digital_ofdm_sampler.h67
25 files changed, 2797 insertions, 0 deletions
diff --git a/gr-digital/include/.gitignore b/gr-digital/include/.gitignore
new file mode 100644
index 000000000..b336cc7ce
--- /dev/null
+++ b/gr-digital/include/.gitignore
@@ -0,0 +1,2 @@
+/Makefile
+/Makefile.in
diff --git a/gr-digital/include/Makefile.am b/gr-digital/include/Makefile.am
new file mode 100644
index 000000000..ce9e67efb
--- /dev/null
+++ b/gr-digital/include/Makefile.am
@@ -0,0 +1,50 @@
+#
+# Copyright 2011 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 3, 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.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# These headers get installed in ${prefix}/include/gnuradio
+grinclude_HEADERS = \
+ digital_binary_slicer_fb.h \
+ digital_clock_recovery_mm_cc.h \
+ digital_clock_recovery_mm_ff.h \
+ digital_constellation.h \
+ digital_constellation_receiver_cb.h \
+ digital_constellation_decoder_cb.h \
+ digital_correlate_access_code_bb.h \
+ digital_costas_loop_cc.h \
+ digital_cma_equalizer_cc.h \
+ digital_crc32.h \
+ digital_fll_band_edge_cc.h \
+ digital_lms_dd_equalizer_cc.h \
+ digital_kurtotic_equalizer_cc.h \
+ digital_metric_type.h \
+ digital_mpsk_receiver_cc.h \
+ digital_ofdm_cyclic_prefixer.h \
+ digital_ofdm_frame_acquisition.h \
+ digital_ofdm_frame_sink.h \
+ digital_ofdm_insert_preamble.h \
+ digital_ofdm_mapper_bcv.h \
+ digital_ofdm_sampler.h \
+ digital_gmskmod_bc.h \
+ digital_cpmmod_bc.h
+
+libgnuradio_digital_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS)
diff --git a/gr-digital/include/digital_binary_slicer_fb.h b/gr-digital/include/digital_binary_slicer_fb.h
new file mode 100644
index 000000000..4e6717de6
--- /dev/null
+++ b/gr-digital/include/digital_binary_slicer_fb.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2011 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 3, 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_DIGITAL_BINARY_SLICER_FB_H
+#define INCLUDED_DIGITAL_BINARY_SLICER_FB_H
+
+#include <gr_sync_block.h>
+
+class digital_binary_slicer_fb;
+typedef boost::shared_ptr<digital_binary_slicer_fb> digital_binary_slicer_fb_sptr;
+
+digital_binary_slicer_fb_sptr digital_make_binary_slicer_fb ();
+
+/*!
+ * \brief slice float binary symbol outputting 1 bit output
+ * \ingroup converter_blk
+ * \ingroup digital
+ *
+ * x < 0 --> 0
+ * x >= 0 --> 1
+ */
+class digital_binary_slicer_fb : public gr_sync_block
+{
+ friend digital_binary_slicer_fb_sptr digital_make_binary_slicer_fb ();
+ digital_binary_slicer_fb ();
+
+ public:
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gr-digital/include/digital_clock_recovery_mm_cc.h b/gr-digital/include/digital_clock_recovery_mm_cc.h
new file mode 100644
index 000000000..5d9c8c5e5
--- /dev/null
+++ b/gr-digital/include/digital_clock_recovery_mm_cc.h
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011 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 3, 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_DIGITAL_CLOCK_RECOVERY_MM_CC_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H
+
+#include <gr_block.h>
+#include <gr_complex.h>
+#include <gr_math.h>
+
+class gri_mmse_fir_interpolator_cc;
+
+class digital_clock_recovery_mm_cc;
+typedef boost::shared_ptr<digital_clock_recovery_mm_cc> digital_clock_recovery_mm_cc_sptr;
+
+// public constructor
+digital_clock_recovery_mm_cc_sptr
+digital_make_clock_recovery_mm_cc (float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit=0.001);
+
+/*!
+ * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * This implements the Mueller and Müller (M&M) discrete-time
+ * error-tracking synchronizer.
+ *
+ * The complex version here is based on:
+ * Modified Mueller and Muller clock recovery circuit
+ * Based:
+ * 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.
+ */
+class digital_clock_recovery_mm_cc : public gr_block
+{
+ public:
+ ~digital_clock_recovery_mm_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);
+ float mu() const { return d_mu;}
+ float omega() const { return d_omega;}
+ float gain_mu() const { return d_gain_mu;}
+ float gain_omega() const { return d_gain_omega;}
+ void set_verbose (bool verbose) { d_verbose = verbose; }
+
+ void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
+ void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
+ void set_mu (float mu) { d_mu = mu; }
+ void set_omega (float omega) {
+ d_omega = omega;
+ d_min_omega = omega*(1.0 - d_omega_relative_limit);
+ d_max_omega = omega*(1.0 + d_omega_relative_limit);
+ d_omega_mid = 0.5*(d_min_omega+d_max_omega);
+ }
+
+protected:
+ digital_clock_recovery_mm_cc (float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limi);
+
+ private:
+ float d_mu;
+ float d_omega;
+ float d_gain_omega;
+ float d_min_omega; // minimum allowed omega
+ float d_max_omega; // maximum allowed omeg
+ float d_omega_relative_limit; // used to compute min and max omega
+ float d_omega_mid;
+ float d_gain_mu;
+ gr_complex d_last_sample;
+ gri_mmse_fir_interpolator_cc *d_interp;
+ bool d_verbose;
+
+ gr_complex d_p_2T;
+ gr_complex d_p_1T;
+ gr_complex d_p_0T;
+
+ gr_complex d_c_2T;
+ gr_complex d_c_1T;
+ gr_complex d_c_0T;
+
+ gr_complex slicer_0deg (gr_complex sample);
+ gr_complex slicer_45deg (gr_complex sample);
+
+ friend digital_clock_recovery_mm_cc_sptr
+ digital_make_clock_recovery_mm_cc (float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit);
+};
+
+#endif
diff --git a/gr-digital/include/digital_clock_recovery_mm_ff.h b/gr-digital/include/digital_clock_recovery_mm_ff.h
new file mode 100644
index 000000000..5a2206fb2
--- /dev/null
+++ b/gr-digital/include/digital_clock_recovery_mm_ff.h
@@ -0,0 +1,99 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2011 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 3, 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_DIGITAL_CLOCK_RECOVERY_MM_FF_H
+#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H
+
+#include <gr_block.h>
+#include <gr_math.h>
+#include <stdio.h>
+
+class gri_mmse_fir_interpolator;
+
+class digital_clock_recovery_mm_ff;
+typedef boost::shared_ptr<digital_clock_recovery_mm_ff> digital_clock_recovery_mm_ff_sptr;
+
+// public constructor
+digital_clock_recovery_mm_ff_sptr
+digital_make_clock_recovery_mm_ff (float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit=0.001);
+
+/*!
+ * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer.
+ *
+ * See "Digital Communication Receivers: Synchronization, Channel
+ * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel.
+ * ISBN 0-471-50275-8.
+ */
+class digital_clock_recovery_mm_ff : public gr_block
+{
+ public:
+ ~digital_clock_recovery_mm_ff ();
+ 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);
+ float mu() const { return d_mu;}
+ float omega() const { return d_omega;}
+ float gain_mu() const { return d_gain_mu;}
+ float gain_omega() const { return d_gain_omega;}
+
+ void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
+ void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
+ void set_mu (float mu) { d_mu = mu; }
+ void set_omega (float omega){
+ d_omega = omega;
+ d_min_omega = omega*(1.0 - d_omega_relative_limit);
+ d_max_omega = omega*(1.0 + d_omega_relative_limit);
+ d_omega_mid = 0.5*(d_min_omega+d_max_omega);
+ }
+
+protected:
+ digital_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu,
+ float omega_relative_limit);
+
+ private:
+ float d_mu; // fractional sample position [0.0, 1.0]
+ float d_omega; // nominal frequency
+ float d_min_omega; // minimum allowed omega
+ float d_omega_mid; // average omega
+ float d_max_omega; // maximum allowed omega
+ float d_gain_omega; // gain for adjusting omega
+ float d_gain_mu; // gain for adjusting mu
+ float d_last_sample;
+ gri_mmse_fir_interpolator *d_interp;
+ FILE *d_logfile;
+ float d_omega_relative_limit; // used to compute min and max omega
+
+ friend digital_clock_recovery_mm_ff_sptr
+ digital_make_clock_recovery_mm_ff (float omega, float gain_omega,
+ float mu, float gain_mu,
+ float omega_relative_limit);
+};
+
+#endif
diff --git a/gr-digital/include/digital_cma_equalizer_cc.h b/gr-digital/include/digital_cma_equalizer_cc.h
new file mode 100644
index 000000000..93771dca4
--- /dev/null
+++ b/gr-digital/include/digital_cma_equalizer_cc.h
@@ -0,0 +1,102 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 3, 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_DIGITAL_CMA_EQUALIZER_CC_H
+#define INCLUDED_DIGITAL_CMA_EQUALIZER_CC_H
+
+#include <gr_adaptive_fir_ccc.h>
+#include <gr_math.h>
+#include <iostream>
+
+class digital_cma_equalizer_cc;
+typedef boost::shared_ptr<digital_cma_equalizer_cc> digital_cma_equalizer_cc_sptr;
+
+digital_cma_equalizer_cc_sptr
+digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps);
+
+/*!
+ * \brief Implements constant modulus adaptive filter on complex stream
+ * \ingroup eq_blk
+ * \ingroup digital
+ *
+ * The error value and tap update equations (for p=2) can be found in:
+ *
+ * D. Godard, "Self-Recovering Equalization and Carrier Tracking in
+ * Two-Dimensional Data Communication Systems," IEEE Transactions on
+ * Communications, Vol. 28, No. 11, pp. 1867 - 1875, 1980,
+ */
+class digital_cma_equalizer_cc : public gr_adaptive_fir_ccc
+{
+private:
+ float d_modulus;
+ float d_mu;
+
+ friend digital_cma_equalizer_cc_sptr digital_make_cma_equalizer_cc(int num_taps,
+ float modulus,
+ float mu,
+ int sps);
+ digital_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps);
+
+protected:
+
+ virtual gr_complex error(const gr_complex &out)
+ {
+ gr_complex error = out*(norm(out) - d_modulus);
+ float re = gr_clip(error.real(), 1.0);
+ float im = gr_clip(error.imag(), 1.0);
+ return gr_complex(re, im);
+ }
+
+ virtual void update_tap(gr_complex &tap, const gr_complex &in)
+ {
+ // Hn+1 = Hn - mu*conj(Xn)*zn*(|zn|^2 - 1)
+ tap -= d_mu*conj(in)*d_error;
+ }
+
+public:
+ float get_gain()
+ {
+ return d_mu;
+ }
+
+ void set_gain(float mu)
+ {
+ if(mu < 0.0f || mu > 1.0f) {
+ throw std::out_of_range("digital_cma_equalizer::set_gain: Gain value must be in [0,1]");
+ }
+ d_mu = mu;
+ }
+
+ float get_modulus()
+ {
+ return d_modulus;
+ }
+
+ void set_modulus(float mod)
+ {
+ if(mod < 0)
+ throw std::out_of_range("digital_cma_equalizer::set_modulus: Modulus value must be >= 0");
+ d_modulus = mod;
+ }
+};
+
+#endif
diff --git a/gr-digital/include/digital_constellation.h b/gr-digital/include/digital_constellation.h
new file mode 100644
index 000000000..b6da7ff9b
--- /dev/null
+++ b/gr-digital/include/digital_constellation.h
@@ -0,0 +1,448 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010, 2011 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 3, 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_DIGITAL_CONSTELLATION_H
+#define INCLUDED_DIGITAL_CONSTELLATION_H
+
+#include <vector>
+#include <math.h>
+#include <gr_complex.h>
+#include <boost/enable_shared_from_this.hpp>
+#include <digital_metric_type.h>
+
+/************************************************************/
+/* digital_constellation */
+/* */
+/* Base class defining interface. */
+/************************************************************/
+
+class digital_constellation;
+typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
+
+/*!
+ * \brief An abstracted constellation object
+ * \ingroup digital
+ *
+ * The constellation objects hold the necessary information to pass
+ * around constellation information for modulators and
+ * demodulators. These objects contain the mapping between the bits
+ * and the constellation points used to represent them as well as
+ * methods for slicing the symbol space. Various implementations are
+ * possible for efficiency and ease of use.
+ *
+ * Standard constellations (BPSK, QPSK, QAM, etc) can be inherited
+ * from this class and overloaded to perform optimized slicing and
+ * constellation mappings.
+ */
+class 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 ();
+
+ //! Returns the constellation points for a symbol value
+ void map_to_points(unsigned int value, gr_complex *points);
+ std::vector<gr_complex> map_to_points_v(unsigned int value);
+
+ //! Returns the constellation point that matches best.
+ virtual unsigned int decision_maker (const gr_complex *sample) = 0;
+ //! Takes a vector rather than a pointer. Better for SWIG wrapping.
+ unsigned int decision_maker_v (std::vector<gr_complex> sample);
+ //! Also calculates the phase error.
+ unsigned int decision_maker_pe (const gr_complex *sample, float *phase_error);
+ //! Calculates distance.
+ unsigned int decision_maker_e (const gr_complex *sample, float *error);
+
+ //! Calculates metrics for all points in the constellation.
+ //! For use with the viterbi algorithm.
+ virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
+ virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
+ virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
+
+ //! Returns the set of points in this constellation.
+ std::vector<gr_complex> points() { return d_constellation;}
+ //! Returns the vector of points in this constellation.
+ //! Raise error if dimensionality is not one.
+ std::vector<gr_complex> s_points();
+ //! Returns a vector of vectors of points.
+ 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.
+ unsigned int rotational_symmetry() { return d_rotational_symmetry;}
+ //! Returns the number of complex numbers in a single symbol.
+ unsigned int dimensionality() {return d_dimensionality;}
+
+ unsigned int bits_per_symbol () {
+ return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
+ }
+
+ unsigned int arity () {
+ return d_arity;
+ }
+
+ digital_constellation_sptr base() {
+ return shared_from_this();
+ }
+
+ protected:
+
+ std::vector<gr_complex> d_constellation;
+ std::vector<unsigned int> d_pre_diff_code;
+ bool d_apply_pre_diff_code;
+ unsigned int d_rotational_symmetry;
+ unsigned int d_dimensionality;
+ unsigned int d_arity;
+
+ float get_distance(unsigned int index, const gr_complex *sample);
+ unsigned int get_closest_point(const gr_complex *sample);
+ void calc_arity ();
+};
+
+/************************************************************/
+/* digital_constellation_calcdist */
+/* */
+/************************************************************/
+
+class digital_constellation_calcdist;
+typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_calcdist_sptr;
+
+// public constructor
+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);
+
+
+/*! \brief Calculate Euclidian distance for any constellation
+ * \ingroup digital
+ *
+ * Constellation which calculates the distance to each point in the
+ * constellation for decision making. Inefficient for large
+ * constellations.
+ */
+class 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);
+ 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);
+ // void calc_hard_symbol_metric(gr_complex *sample, float *metric);
+
+ private:
+ friend digital_constellation_calcdist_sptr
+ digital_make_constellation_calcdist (std::vector<gr_complex> constellation);
+};
+
+
+/************************************************************/
+/*! digital_constellation_sector */
+/************************************************************/
+
+/*!
+ * \brief Sectorized digital constellation
+ * \ingroup digital
+ *
+ * Constellation space is divided into sectors. Each sector is
+ * associated with the nearest constellation point.
+ *
+ */
+class 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);
+
+ unsigned int decision_maker (const gr_complex *sample);
+
+ protected:
+
+ virtual unsigned int get_sector (const gr_complex *sample) = 0;
+ virtual unsigned int calc_sector_value (unsigned int sector) = 0;
+ void find_sector_values ();
+
+ unsigned int n_sectors;
+
+ private:
+
+ std::vector<unsigned int> sector_values;
+
+};
+
+/************************************************************/
+/* digital_constellation_rect */
+/************************************************************/
+
+/*!
+ * \brief Rectangular digital constellation
+ * \ingroup digital
+ *
+ * Only implemented for 1-(complex)dimensional constellation.
+ *
+ * Constellation space is divided into rectangular sectors. Each
+ * sector is associated with the nearest constellation point.
+ *
+ * Works well for square QAM.
+ *
+ * Works for any generic constellation provided sectors are not too
+ * large.
+ */
+
+class digital_constellation_rect;
+typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect_sptr;
+
+// public constructor
+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);
+
+class 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);
+
+ protected:
+
+ unsigned int get_sector (const gr_complex *sample);
+
+ unsigned int calc_sector_value (unsigned int sector);
+
+ private:
+
+ unsigned int n_real_sectors;
+ unsigned int n_imag_sectors;
+ float d_width_real_sectors;
+ float d_width_imag_sectors;
+
+ friend 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_constellation_psk */
+/************************************************************/
+
+class digital_constellation_psk;
+typedef boost::shared_ptr<digital_constellation_psk> digital_constellation_psk_sptr;
+
+// public constructor
+digital_constellation_psk_sptr
+digital_make_constellation_psk (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+/*!
+ * \brief digital_constellation_psk
+ * \ingroup digital
+ *
+ * Constellation space is divided into pie slices sectors.
+ *
+ * Each slice is associated with the nearest constellation point.
+ *
+ * Works well for PSK but nothing else.
+ *
+ * Assumes that there is a constellation point at 1.x
+ */
+class digital_constellation_psk : public digital_constellation_sector
+{
+ public:
+
+ digital_constellation_psk (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+ protected:
+
+ unsigned int get_sector (const gr_complex *sample);
+
+ unsigned int calc_sector_value (unsigned int sector);
+
+ private:
+
+ friend digital_constellation_psk_sptr
+ digital_make_constellation_psk (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+};
+
+
+/************************************************************/
+/* digital_constellation_bpsk */
+/* */
+/* Only works for BPSK. */
+/* */
+/************************************************************/
+
+class digital_constellation_bpsk;
+typedef boost::shared_ptr<digital_constellation_bpsk> digital_constellation_bpsk_sptr;
+
+// public constructor
+digital_constellation_bpsk_sptr
+digital_make_constellation_bpsk ();
+
+/*!
+ * \brief Digital constellation for BPSK
+ * \ingroup digital
+ */
+class digital_constellation_bpsk : public digital_constellation
+{
+ public:
+
+ digital_constellation_bpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend digital_constellation_bpsk_sptr
+ digital_make_constellation_bpsk ();
+
+};
+
+
+/************************************************************/
+/* digital_constellation_qpsk */
+/* */
+/* Only works for QPSK. */
+/* */
+/************************************************************/
+
+class digital_constellation_qpsk;
+typedef boost::shared_ptr<digital_constellation_qpsk> digital_constellation_qpsk_sptr;
+
+// public constructor
+digital_constellation_qpsk_sptr
+digital_make_constellation_qpsk ();
+
+/*!
+ * \brief Digital constellation for QPSK
+ * \ingroup digital
+ */
+class digital_constellation_qpsk : public digital_constellation
+{
+ public:
+
+ digital_constellation_qpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend digital_constellation_qpsk_sptr
+ digital_make_constellation_qpsk ();
+
+};
+
+
+/************************************************************/
+/* digital_constellation_dqpsk */
+/* */
+/* Works with differential encoding; slower decisions. */
+/* */
+/************************************************************/
+
+class digital_constellation_dqpsk;
+typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
+
+// public constructor
+digital_constellation_dqpsk_sptr
+digital_make_constellation_dqpsk ();
+
+/*!
+ * \brief Digital constellation for DQPSK
+ * \ingroup digital
+ */
+class digital_constellation_dqpsk : public digital_constellation
+{
+ public:
+
+ digital_constellation_dqpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend digital_constellation_dqpsk_sptr
+ digital_make_constellation_dqpsk ();
+
+};
+
+
+/************************************************************/
+/* digital_constellation_8psk */
+/* */
+/* Only works for 8PSK. */
+/* */
+/************************************************************/
+
+class digital_constellation_8psk;
+typedef boost::shared_ptr<digital_constellation_8psk> digital_constellation_8psk_sptr;
+
+// public constructor
+digital_constellation_8psk_sptr
+digital_make_constellation_8psk ();
+
+/*!
+ * \brief Digital constellation for 8PSK
+ * \ingroup digital
+ */
+class digital_constellation_8psk : public digital_constellation
+{
+ public:
+
+ digital_constellation_8psk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend digital_constellation_8psk_sptr
+ digital_make_constellation_8psk ();
+
+};
+
+#endif
diff --git a/gr-digital/include/digital_constellation_decoder_cb.h b/gr-digital/include/digital_constellation_decoder_cb.h
new file mode 100644
index 000000000..d587f6bc4
--- /dev/null
+++ b/gr-digital/include/digital_constellation_decoder_cb.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 3, 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_DIGITAL_CONSTELLATION_DECODER_CB_H
+#define INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H
+
+#include <gr_block.h>
+#include <digital_constellation.h>
+#include <vector>
+
+class digital_constellation_decoder_cb;
+typedef boost::shared_ptr<digital_constellation_decoder_cb>digital_constellation_decoder_cb_sptr;
+
+digital_constellation_decoder_cb_sptr
+digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
+
+/*!
+ * \brief Constellation Decoder
+ * \ingroup coding_blk
+ * \ingroup digital
+ *
+ */
+class digital_constellation_decoder_cb : public gr_block
+{
+
+ private:
+ digital_constellation_sptr d_constellation;
+ unsigned int d_dim;
+
+ friend digital_constellation_decoder_cb_sptr
+ digital_make_constellation_decoder_cb (digital_constellation_sptr constellation);
+
+ digital_constellation_decoder_cb (digital_constellation_sptr constellation);
+
+ public:
+
+ 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);
+};
+
+#endif
diff --git a/gr-digital/include/digital_constellation_receiver_cb.h b/gr-digital/include/digital_constellation_receiver_cb.h
new file mode 100644
index 000000000..a67f67082
--- /dev/null
+++ b/gr-digital/include/digital_constellation_receiver_cb.h
@@ -0,0 +1,121 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 3, 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_DIGITAL_CONSTELLATION_RECEIVER_CB_H
+#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H
+
+#include <gr_block.h>
+#include <digital_constellation.h>
+#include <gri_control_loop.h>
+#include <gr_complex.h>
+#include <math.h>
+#include <fstream>
+
+class digital_constellation_receiver_cb;
+typedef boost::shared_ptr<digital_constellation_receiver_cb> digital_constellation_receiver_cb_sptr;
+
+// public constructor
+digital_constellation_receiver_cb_sptr
+digital_make_constellation_receiver_cb (digital_constellation_sptr constellation,
+ float loop_bw, float fmin, float fmax);
+
+/*!
+ * \brief This block takes care of receiving generic modulated signals
+ * through phase, frequency, and symbol synchronization.
+ * \ingroup sync_blk
+ * \ingroup demod_blk
+ * \ingroup digital
+ *
+ * This block takes care of receiving generic modulated signals
+ * through phase, frequency, and symbol synchronization. It performs
+ * carrier frequency and phase locking as well as symbol timing
+ * recovery.
+ *
+ * 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.
+ *
+ * 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 digital_constellation_receiver_cb : public gr_block, public gri_control_loop
+{
+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);
+
+protected:
+
+ /*!
+ * \brief Constructor to synchronize incoming M-PSK symbols
+ *
+ * \param constellation constellation of points for generic modulation
+ * \param loop_bw Loop bandwidth of the Costas Loop (~ 2pi/100)
+ * \param fmin minimum normalized frequency value the loop can achieve
+ * \param fmax maximum normalized frequency value the loop can achieve
+ *
+ * The constructor also chooses which phase detector and decision maker to use in the
+ * work loop based on the value of M.
+ */
+ digital_constellation_receiver_cb (digital_constellation_sptr constellation,
+ float loop_bw, float fmin, float fmax);
+
+ void phase_error_tracking(float phase_error);
+
+private:
+ unsigned int d_M;
+
+ digital_constellation_sptr d_constellation;
+ unsigned int d_current_const_point;
+
+ //! delay line length.
+ static const unsigned int DLLEN = 8;
+
+ //! delay line plus some length for overflow protection
+ gr_complex d_dl[2*DLLEN] __attribute__ ((aligned(8)));
+
+ //! index to delay line
+ unsigned int d_dl_idx;
+
+ friend digital_constellation_receiver_cb_sptr
+ digital_make_constellation_receiver_cb (digital_constellation_sptr constell,
+ float loop_bw, float fmin, float fmax);
+};
+
+#endif
diff --git a/gr-digital/include/digital_correlate_access_code_bb.h b/gr-digital/include/digital_correlate_access_code_bb.h
new file mode 100644
index 000000000..c21875f0e
--- /dev/null
+++ b/gr-digital/include/digital_correlate_access_code_bb.h
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2006,2011 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 3, 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_DIGITAL_CORRELATE_ACCESS_CODE_BB_H
+#define INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H
+
+#include <gr_sync_block.h>
+#include <string>
+
+class digital_correlate_access_code_bb;
+typedef boost::shared_ptr<digital_correlate_access_code_bb> digital_correlate_access_code_bb_sptr;
+
+/*!
+ * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100"
+ * \param threshold maximum number of bits that may be wrong
+ */
+digital_correlate_access_code_bb_sptr
+digital_make_correlate_access_code_bb (const std::string &access_code, int threshold);
+
+/*!
+ * \brief Examine input for specified access code, one bit at a time.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * input: stream of bits, 1 bit per input byte (data in LSB)
+ * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit)
+ *
+ * Each output byte contains two valid bits, the data bit, and the
+ * flag bit. The LSB (bit 0) is the data bit, and is the original
+ * input data, delayed 64 bits. Bit 1 is the
+ * flag bit and is 1 if the corresponding data bit is the first data
+ * bit following the access code. Otherwise the flag bit is 0.
+ */
+class digital_correlate_access_code_bb : public gr_sync_block
+{
+ friend digital_correlate_access_code_bb_sptr
+ digital_make_correlate_access_code_bb (const std::string &access_code, int threshold);
+ private:
+ unsigned long long d_access_code; // access code to locate start of packet
+ // access code is left justified in the word
+ unsigned long long d_data_reg; // used to look for access_code
+ unsigned long long d_flag_reg; // keep track of decisions
+ unsigned long long d_flag_bit; // mask containing 1 bit which is location of new flag
+ unsigned long long d_mask; // masks access_code bits (top N bits are set where
+ // N is the number of bits in the access code)
+ unsigned int d_threshold; // how many bits may be wrong in sync vector
+
+ protected:
+ digital_correlate_access_code_bb(const std::string &access_code, int threshold);
+
+ public:
+ ~digital_correlate_access_code_bb();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+
+ /*!
+ * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100"
+ */
+ bool set_access_code (const std::string &access_code);
+};
+
+#endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H */
diff --git a/gr-digital/include/digital_costas_loop_cc.h b/gr-digital/include/digital_costas_loop_cc.h
new file mode 100644
index 000000000..3811825dd
--- /dev/null
+++ b/gr-digital/include/digital_costas_loop_cc.h
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2011 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 3, 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_DIGITAL_COSTAS_LOOP_CC_H
+#define INCLUDED_DIGITAL_COSTAS_LOOP_CC_H
+
+#include <gr_sync_block.h>
+#include <gri_control_loop.h>
+#include <stdexcept>
+#include <fstream>
+
+
+/*!
+ * \brief A Costas loop carrier recovery module.
+ * \ingroup sync_blk
+ * \ingroup digital
+ *
+ * The Costas loop locks to the center frequency of a signal and
+ * downconverts it to baseband. The second (order=2) order loop is
+ * used for BPSK where the real part of the output signal is the
+ * baseband BPSK signal and the imaginary part is the error
+ * signal. When order=4, it can be used for quadrature modulations
+ * where both I and Q (real and imaginary) are outputted.
+ *
+ * More details can be found online:
+ *
+ * J. Feigin, "Practical Costas loop design: Designing a simple and
+ * inexpensive BPSK Costas loop carrier recovery circuit," RF signal
+ * processing, pp. 20-36, 2002.
+ *
+ * http://rfdesign.com/images/archive/0102Feigin20.pdf
+ *
+ * \param alpha the loop gain used for phase adjustment
+ * \param beta the loop gain for frequency adjustments
+ * \param max_freq the maximum frequency deviation (radians/sample) the loop can handle
+ * \param min_freq the minimum frequency deviation (radians/sample) the loop can handle
+ * \param order the loop order, either 2 or 4
+ */
+class digital_costas_loop_cc;
+typedef boost::shared_ptr<digital_costas_loop_cc> digital_costas_loop_cc_sptr;
+
+
+digital_costas_loop_cc_sptr
+digital_make_costas_loop_cc (float loop_bw, int order
+ ) throw (std::invalid_argument);
+
+
+/*!
+ * \brief Carrier tracking PLL for QPSK
+ * \ingroup sync_blk
+ * input: complex; output: complex
+ * <br>The Costas loop can have two output streams:
+ * stream 1 is the baseband I and Q;
+ * stream 2 is the normalized frequency of the loop
+ *
+ * \p order must be 2 or 4.
+ */
+class digital_costas_loop_cc : public gr_sync_block, public gri_control_loop
+{
+ friend digital_costas_loop_cc_sptr
+ digital_make_costas_loop_cc (float loop_bw, int order
+ ) throw (std::invalid_argument);
+
+ int d_order;
+
+ digital_costas_loop_cc (float loop_bw, int order
+ ) throw (std::invalid_argument);
+
+ /*! \brief the phase detector circuit for 8th-order PSK loops
+ * \param sample complex sample
+ * \return the phase error
+ */
+ float phase_detector_8(gr_complex sample) const; // for 8PSK
+
+ /*! \brief the phase detector circuit for fourth-order loops
+ * \param sample complex sample
+ * \return the phase error
+ */
+ float phase_detector_4(gr_complex sample) const; // for QPSK
+
+ /*! \brief the phase detector circuit for second-order loops
+ * \param sample a complex sample
+ * \return the phase error
+ */
+ float phase_detector_2(gr_complex sample) const; // for BPSK
+
+
+ float (digital_costas_loop_cc::*d_phase_detector)(gr_complex sample) const;
+
+public:
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gr-digital/include/digital_cpmmod_bc.h b/gr-digital/include/digital_cpmmod_bc.h
new file mode 100644
index 000000000..85b901ba2
--- /dev/null
+++ b/gr-digital/include/digital_cpmmod_bc.h
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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 3, 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_DIGITAL_CPMMOD_BC_H
+#define INCLUDED_DIGITAL_CPMMOD_BC_H
+
+#include <gr_hier_block2.h>
+#include <gr_char_to_float.h>
+#include <gr_interp_fir_filter_fff.h>
+#include <gr_frequency_modulator_fc.h>
+#include <gr_cpm.h>
+
+
+class digital_cpmmod_bc;
+typedef boost::shared_ptr<digital_cpmmod_bc> digital_cpmmod_bc_sptr;
+
+
+digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta=0.3);
+
+/*!
+ * \brief Generic CPM modulator
+ *
+ * \ingroup modulation_blk
+ * \ingroup digital
+ *
+ * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM
+ * or GAUSSIAN. See gr_cpm::phase_response() for a
+ * detailed description.
+ * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum
+ * phase change that can occur between two symbols, i.e., if
+ * you only send ones, the phase will increase by \f$ h \cdot
+ * \pi\f$ every \p samples_per_sym samples. Set this to 0.5
+ * for Minimum Shift Keying variants.
+ * \param samples_per_sym Samples per symbol.
+ * \param L The length of the phase duration in symbols. For L=1, this
+ * yields full- response CPM symbols, for L > 1,
+ * partial-response.
+ * \param beta For LSRC, this is the rolloff factor. For Gaussian
+ * pulses, this is the 3 dB time-bandwidth product.
+ *
+ * Examples:
+ * - Setting h = 0.5, L = 1, type = LREC yields MSK.
+ * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK
+ * as used in GSM.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class digital_cpmmod_bc : public gr_hier_block2
+{
+ friend digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+ std::vector<float> d_taps;
+ gr_char_to_float_sptr d_char_to_float;
+ gr_interp_fir_filter_fff_sptr d_pulse_shaper;
+ gr_frequency_modulator_fc_sptr d_fm;
+
+protected:
+ digital_cpmmod_bc(gr_cpm::cpm_type type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+public:
+ //! Return the phase response FIR taps
+ std::vector<float> get_taps() { return d_taps; };
+};
+
+#endif /* INCLUDED_DIGITAL_CPMMOD_BC_H */
+
diff --git a/gr-digital/include/digital_crc32.h b/gr-digital/include/digital_crc32.h
new file mode 100644
index 000000000..869cf7f45
--- /dev/null
+++ b/gr-digital/include/digital_crc32.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2011 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 3, 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_DIGITAL_CRC32_H
+#define INCLUDED_DIGITAL_CRC32_H
+
+#include <string>
+#include <gr_types.h>
+
+/*!
+ * \brief update running CRC-32
+ * \ingroup digital
+ *
+ * Update a running CRC with the bytes buf[0..len-1] The CRC should be
+ * initialized to all 1's, and the transmitted value is the 1's
+ * complement of the final running CRC. The resulting CRC should be
+ * transmitted in big endian order.
+ */
+unsigned int
+digital_update_crc32(unsigned int crc, const unsigned char *buf, size_t len);
+
+unsigned int
+digital_update_crc32(unsigned int crc, const std::string buf);
+
+unsigned int
+digital_crc32(const unsigned char *buf, size_t len);
+
+unsigned int
+digital_crc32(const std::string buf);
+
+#endif /* INCLUDED_CRC32_H */
diff --git a/gr-digital/include/digital_fll_band_edge_cc.h b/gr-digital/include/digital_fll_band_edge_cc.h
new file mode 100644
index 000000000..576dfab87
--- /dev/null
+++ b/gr-digital/include/digital_fll_band_edge_cc.h
@@ -0,0 +1,213 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2011 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 3, 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_DIGITAL_FLL_BAND_EDGE_CC_H
+#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_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;
+digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym,
+ float rolloff,
+ int filter_size,
+ float bandwidth);
+
+/*!
+ * \class digital_fll_band_edge_cc
+ * \brief Frequency Lock Loop using band-edge filters
+ *
+ * \ingroup general
+ * \ingroup digital
+ *
+ * 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).
+ *
+ * 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
+ * '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.
+ *
+ * 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_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
+{
+ private:
+ /*!
+ * Build the FLL
+ * \param samps_per_sym (float) Number of samples per symbol of signal
+ * \param rolloff (float) Rolloff factor of signal
+ * \param filter_size (int) Size (in taps) of the filter
+ * \param bandwidth (float) Loop bandwidth
+ */
+ friend digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym,
+ float rolloff,
+ int filter_size,
+ float bandwidth);
+
+ float d_sps;
+ float d_rolloff;
+ int d_filter_size;
+
+ std::vector<gr_complex> d_taps_lower;
+ std::vector<gr_complex> d_taps_upper;
+ bool d_updated;
+
+ /*!
+ * Build the FLL
+ * \param samps_per_sym (float) number of samples per symbol
+ * \param rolloff (float) Rolloff (excess bandwidth) of signal filter
+ * \param filter_size (int) number of filter taps to generate
+ * \param bandwidth (float) Loop bandwidth
+ */
+ digital_fll_band_edge_cc(float samps_per_sym, float rolloff,
+ int filter_size, float bandwidth);
+
+ /*!
+ * Design the band-edge filter based on the number of samples per symbol,
+ * filter rolloff factor, and the filter size
+ *
+ * \param samps_per_sym (float) Number of samples per symbol of signal
+ * \param rolloff (float) Rolloff factor of signal
+ * \param filter_size (int) Size (in taps) of the filter
+ */
+ void design_filter(float samps_per_sym, float rolloff, int filter_size);
+
+public:
+ ~digital_fll_band_edge_cc ();
+
+ /*******************************************************************
+ SET FUNCTIONS
+ *******************************************************************/
+
+ /*!
+ * \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.
+ *
+ * \param sps (float) new samples per symbol
+ *
+ */
+ void set_samples_per_symbol(float sps);
+
+ /*!
+ * \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 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]
+ *
+ */
+ void set_rolloff(float rolloff);
+
+ /*!
+ * \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 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);
+
+ /*******************************************************************
+ GET FUNCTIONS
+ *******************************************************************/
+
+ /*!
+ * \brief Returns the number of sampler per symbol used for the filter
+ */
+ float get_samples_per_symbol() const;
+
+ /*!
+ * \brief Returns the rolloff factor used for the filter
+ */
+ float get_rolloff() const;
+
+ /*!
+ * \brief Returns the number of taps of the filter
+ */
+ int get_filter_size() const;
+
+ /*!
+ * Print the taps to screen.
+ */
+ void print_taps();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gr-digital/include/digital_gmskmod_bc.h b/gr-digital/include/digital_gmskmod_bc.h
new file mode 100644
index 000000000..4b0952401
--- /dev/null
+++ b/gr-digital/include/digital_gmskmod_bc.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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 3, 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_DIGITAL_GMSKMOD_BC_H
+#define INCLUDED_DIGITAL_GMSKMOD_BC_H
+
+#include <digital_cpmmod_bc.h>
+
+class digital_gmskmod_bc;
+typedef boost::shared_ptr<digital_gmskmod_bc> digital_gmskmod_bc_sptr;
+
+
+digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym=2,
+ double bt=0.3, unsigned L=4);
+
+/*!
+ * \brief GMSK modulator
+ *
+ * \ingroup modulation_blk
+ * \ingroup digital
+ *
+ * \param samples_per_sym Samples per symbol.
+ * \param bt The 3 dB time-bandwidth product.
+ * \param L The length of the phase duration in symbols. The Gaussian
+ * pulse is truncated after L symbols.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class digital_gmskmod_bc : public digital_cpmmod_bc
+{
+ friend digital_gmskmod_bc_sptr digital_make_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+ digital_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+};
+
+#endif /* INCLUDED_DIGITAL_GMSKMOD_BC_H */
+
diff --git a/gr-digital/include/digital_kurtotic_equalizer_cc.h b/gr-digital/include/digital_kurtotic_equalizer_cc.h
new file mode 100644
index 000000000..018a906b0
--- /dev/null
+++ b/gr-digital/include/digital_kurtotic_equalizer_cc.h
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 3, 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_DIGITAL_KURTOTIC_EQUALIZER_CC_H
+#define INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H
+
+#include <gr_adaptive_fir_ccc.h>
+#include <gr_math.h>
+#include <iostream>
+
+class digital_kurtotic_equalizer_cc;
+typedef boost::shared_ptr<digital_kurtotic_equalizer_cc> digital_kurtotic_equalizer_cc_sptr;
+
+digital_kurtotic_equalizer_cc_sptr
+digital_make_kurtotic_equalizer_cc(int num_taps, float mu);
+
+/*!
+ * \brief Implements a kurtosis-based adaptive equalizer on complex stream
+ * \ingroup eq_blk
+ * \ingroup digital
+ *
+ * Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind
+ * equalization algorithm," IEEE Conf. on Control, Automation,
+ * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057.
+ */
+class digital_kurtotic_equalizer_cc : public gr_adaptive_fir_ccc
+{
+private:
+ float d_mu;
+ float d_p, d_m;
+ gr_complex d_q, d_u;
+ float d_alpha_p, d_alpha_q, d_alpha_m;
+
+ friend digital_kurtotic_equalizer_cc_sptr digital_make_kurtotic_equalizer_cc(int num_taps,
+ float mu);
+ digital_kurtotic_equalizer_cc(int num_taps, float mu);
+
+ gr_complex sign(gr_complex x)
+ {
+ float re = (float)(x.real() >= 0.0f);
+ float im = (float)(x.imag() >= 0.0f);
+ return gr_complex(re, im);
+ }
+
+protected:
+
+ virtual gr_complex error(const gr_complex &out)
+ {
+
+ // p = E[|z|^2]
+ // q = E[z^2]
+ // m = E[|z|^4]
+ // u = E[kurtosis(z)]
+
+ float nrm = norm(out);
+ gr_complex cnj = conj(out);
+ float epsilon_f = 1e-12;
+ gr_complex epsilon_c = gr_complex(1e-12, 1e-12);
+
+
+ d_p = (1-d_alpha_p)*d_p + (d_alpha_p)*nrm + epsilon_f;
+ d_q = (1-d_alpha_q)*d_q + (d_alpha_q)*out*out + epsilon_c;
+ d_m = (1-d_alpha_m)*d_m + (d_alpha_m)*nrm*nrm + epsilon_f;
+ d_u = d_m - 2.0f*(d_p*d_p) - d_q*d_q;
+
+ gr_complex F = (1.0f / (d_p*d_p*d_p)) *
+ (sign(d_u) * (nrm*cnj - 2.0f*d_p*cnj - conj(d_q)*out) -
+ abs(d_u)*cnj);
+
+ //std::cout << "out: " << out << " p: " << d_p << " q: " << d_q;
+ //std::cout << " m: " << d_m << " u: " << d_u << std::endl;
+ //std::cout << "error: " << F << std::endl;
+
+ float re = gr_clip(F.real(), 1.0);
+ float im = gr_clip(F.imag(), 1.0);
+ return gr_complex(re, im);
+ }
+
+ virtual void update_tap(gr_complex &tap, const gr_complex &in)
+ {
+ tap += d_mu*in*d_error;
+ }
+
+public:
+ void set_gain(float mu)
+ {
+ if(mu < 0)
+ throw std::out_of_range("digital_kurtotic_equalizer::set_gain: Gain value must be >= 0");
+ d_mu = mu;
+ }
+};
+
+#endif
diff --git a/gr-digital/include/digital_lms_dd_equalizer_cc.h b/gr-digital/include/digital_lms_dd_equalizer_cc.h
new file mode 100644
index 000000000..050d8781d
--- /dev/null
+++ b/gr-digital/include/digital_lms_dd_equalizer_cc.h
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 3, 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_DIGITAL_LMS_DD_EQUALIZER_CC_H
+#define INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H
+
+#include <gr_adaptive_fir_ccc.h>
+#include <digital_constellation.h>
+
+class digital_lms_dd_equalizer_cc;
+typedef boost::shared_ptr<digital_lms_dd_equalizer_cc> digital_lms_dd_equalizer_cc_sptr;
+
+digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+/*!
+ * \brief Least-Mean-Square Decision Directed Equalizer (complex in/out)
+ * \ingroup eq_blk
+ * \ingroup digital
+ *
+ * This block implements an LMS-based decision-directed equalizer.
+ * It uses a set of weights, w, to correlate against the inputs, u,
+ * and a decisions is then made from this output. The error
+ * in the decision is used to update teh weight vector.
+ *
+ * y[n] = conj(w[n]) u[n]
+ * d[n] = decision(y[n])
+ * e[n] = d[n] - y[n]
+ * w[n+1] = w[n] + mu u[n] conj(e[n])
+ *
+ * Where mu is a gain value (between 0 and 1 and usualy small,
+ * around 0.001 - 0.01.
+ *
+ * This block uses the digital_constellation object for making
+ * the decision from y[n]. Create the constellation object for
+ * whatever constellation is to be used and pass in the object.
+ * In Python, you can use something like:
+ * self.constellation = digital.constellation_qpsk()
+ * To create a QPSK constellation (see the digital_constellation
+ * block for more details as to what constellations are available
+ * or how to create your own). You then pass the object to this
+ * block as an sptr, or using "self.constellation.base()".
+ *
+ * The theory for this algorithm can be found in Chapter 9 of:
+ * S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ:
+ * Prentice Hall, 1996.
+ *
+ */
+class digital_lms_dd_equalizer_cc : public gr_adaptive_fir_ccc
+{
+private:
+ friend digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+ float d_mu;
+ std::vector<gr_complex> d_taps;
+ digital_constellation_sptr d_cnst;
+
+ digital_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+protected:
+
+ virtual gr_complex error(const gr_complex &out)
+ {
+ gr_complex decision, error;
+ d_cnst->map_to_points(d_cnst->decision_maker(&out), &decision);
+ error = decision - out;
+ return error;
+ }
+
+ virtual void update_tap(gr_complex &tap, const gr_complex &in)
+ {
+ tap += d_mu*conj(in)*d_error;
+ }
+
+public:
+ float get_gain()
+ {
+ return d_mu;
+ }
+
+ void set_gain(float mu)
+ {
+ if(mu < 0.0f || mu > 1.0f) {
+ throw std::out_of_range("digital_lms_dd_equalizer::set_mu: Gain value must in [0, 1]");
+ }
+ else {
+ d_mu = mu;
+ }
+ }
+
+};
+
+#endif
diff --git a/gr-digital/include/digital_metric_type.h b/gr-digital/include/digital_metric_type.h
new file mode 100644
index 000000000..83de166f0
--- /dev/null
+++ b/gr-digital/include/digital_metric_type.h
@@ -0,0 +1,31 @@
+/* -*- 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 3, 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_DIGITAL_METRIC_TYPE_H
+#define INCLUDED_DIGITAL_METRIC_TYPE_H
+
+typedef enum {
+ TRELLIS_EUCLIDEAN = 200, TRELLIS_HARD_SYMBOL, TRELLIS_HARD_BIT
+} trellis_metric_type_t;
+
+#endif
+
diff --git a/gr-digital/include/digital_mpsk_receiver_cc.h b/gr-digital/include/digital_mpsk_receiver_cc.h
new file mode 100644
index 000000000..74aca5649
--- /dev/null
+++ b/gr-digital/include/digital_mpsk_receiver_cc.h
@@ -0,0 +1,302 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2011 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 3, 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_DIGITAL_MPSK_RECEIVER_CC_H
+#define INCLUDED_DIGITAL_MPSK_RECEIVER_CC_H
+
+#include <gruel/attributes.h>
+#include <gri_control_loop.h>
+#include <gr_block.h>
+#include <gr_complex.h>
+#include <fstream>
+
+class gri_mmse_fir_interpolator_cc;
+
+class digital_mpsk_receiver_cc;
+typedef boost::shared_ptr<digital_mpsk_receiver_cc> digital_mpsk_receiver_cc_sptr;
+
+// public constructor
+digital_mpsk_receiver_cc_sptr
+digital_make_mpsk_receiver_cc (unsigned int M, float theta,
+ 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.
+ * \ingroup sync_blk
+ * \ingroup demod_blk
+ * \ingroup digital
+ *
+ * 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 digital_mpsk_receiver_cc : public gr_block, public gri_control_loop
+{
+ public:
+ ~digital_mpsk_receiver_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);
+ d_omega_mid = 0.5*(d_min_omega+d_max_omega);
+ }
+
+ //! (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; }
+
+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 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]
+ * \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.
+ */
+ digital_mpsk_receiver_cc (unsigned int M, float theta,
+ float loop_bw,
+ float fmin, float fmax,
+ float mu, float gain_mu,
+ float omega, float gain_omega, float omega_rel);
+
+ void make_constellation();
+ void mm_sampler(const gr_complex symbol);
+ void mm_error_tracking(gr_complex sample);
+ 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 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 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/
+ */
+ unsigned int 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 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.
+ *
+ * \returns the index to d_constellation that minimizes the error/
+ */
+ unsigned int decision_qpsk(gr_complex sample) const;
+
+private:
+ unsigned int d_M;
+ float d_theta;
+
+ /*!
+ * \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.
+ *
+ * \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
+
+
+ std::vector<gr_complex> d_constellation;
+ unsigned int d_current_const_point;
+
+ // Members related to symbol timing
+ float d_mu, d_gain_mu;
+ float d_omega, d_gain_omega, d_omega_rel, d_max_omega, d_min_omega, d_omega_mid;
+ 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 (digital_mpsk_receiver_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_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN];
+
+ //! index to delay line
+ unsigned int d_dl_idx;
+
+ friend digital_mpsk_receiver_cc_sptr
+ digital_make_mpsk_receiver_cc (unsigned int M, float theta,
+ float loop_bw,
+ float fmin, float fmax,
+ float mu, float gain_mu,
+ float omega, float gain_omega, float omega_rel);
+};
+
+#endif
diff --git a/gr-digital/include/digital_ofdm_cyclic_prefixer.h b/gr-digital/include/digital_ofdm_cyclic_prefixer.h
new file mode 100644
index 000000000..a3c32125b
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_cyclic_prefixer.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2011 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 3, 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_DIGITAL_OFDM_CYCLIC_PREFIXER_H
+#define INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H
+
+#include <gr_sync_interpolator.h>
+#include <stdio.h>
+
+class digital_ofdm_cyclic_prefixer;
+typedef boost::shared_ptr<digital_ofdm_cyclic_prefixer> digital_ofdm_cyclic_prefixer_sptr;
+
+digital_ofdm_cyclic_prefixer_sptr
+digital_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size);
+
+
+/*!
+ * \brief adds a cyclic prefix vector to an input size long ofdm
+ * symbol(vector) and converts vector to a stream output_size long.
+ * \ingroup ofdm_blk
+ */
+class digital_ofdm_cyclic_prefixer : public gr_sync_interpolator
+{
+ friend digital_ofdm_cyclic_prefixer_sptr
+ digital_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size);
+
+ protected:
+ digital_ofdm_cyclic_prefixer (size_t input_size, size_t output_size);
+
+ public:
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ private:
+ size_t d_input_size;
+ size_t d_output_size;
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H */
diff --git a/gr-digital/include/digital_ofdm_frame_acquisition.h b/gr-digital/include/digital_ofdm_frame_acquisition.h
new file mode 100644
index 000000000..971202099
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_frame_acquisition.h
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2011 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 3, 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_DIGITAL_OFDM_FRAME_ACQUISITION_H
+#define INCLUDED_DIGITAL_OFDM_FRAME_ACQUISITION_H
+
+
+#include <gr_block.h>
+#include <vector>
+
+class digital_ofdm_frame_acquisition;
+typedef boost::shared_ptr<digital_ofdm_frame_acquisition> digital_ofdm_frame_acquisition_sptr;
+
+digital_ofdm_frame_acquisition_sptr
+digital_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len=10);
+
+/*!
+ * \brief take a vector of complex constellation points in from an FFT
+ * and performs a correlation and equalization.
+ * \ingroup demodulation_blk
+ * \ingroup ofdm_blk
+ *
+ * This block takes the output of an FFT of a received OFDM symbol and finds the
+ * start of a frame based on two known symbols. It also looks at the surrounding
+ * bins in the FFT output for the correlation in case there is a large frequency
+ * shift in the data. This block assumes that the fine frequency shift has already
+ * been corrected and that the samples fall in the middle of one FFT bin.
+ *
+ * It then uses one of those known
+ * symbols to estimate the channel response over all subcarriers and does a simple
+ * 1-tap equalization on all subcarriers. This corrects for the phase and amplitude
+ * distortion caused by the channel.
+ */
+
+class digital_ofdm_frame_acquisition : public gr_block
+{
+ /*!
+ * \brief Build an OFDM correlator and equalizer.
+ * \param occupied_carriers The number of subcarriers with data in the received symbol
+ * \param fft_length The size of the FFT vector (occupied_carriers + unused carriers)
+ * \param cplen The length of the cycle prefix
+ * \param known_symbol A vector of complex numbers representing a known symbol at the
+ * start of a frame (usually a BPSK PN sequence)
+ * \param max_fft_shift_len Set's the maximum distance you can look between bins for correlation
+ */
+ friend digital_ofdm_frame_acquisition_sptr
+ digital_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len);
+
+protected:
+ digital_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len);
+
+ private:
+ unsigned char slicer(gr_complex x);
+ void correlate(const gr_complex *symbol, int zeros_on_left);
+ void calculate_equalizer(const gr_complex *symbol, int zeros_on_left);
+ gr_complex coarse_freq_comp(int freq_delta, int count);
+
+ unsigned int d_occupied_carriers; // !< \brief number of subcarriers with data
+ unsigned int d_fft_length; // !< \brief length of FFT vector
+ unsigned int d_cplen; // !< \brief length of cyclic prefix in samples
+ unsigned int d_freq_shift_len; // !< \brief number of surrounding bins to look at for correlation
+ std::vector<gr_complex> d_known_symbol; // !< \brief known symbols at start of frame
+ std::vector<float> d_known_phase_diff; // !< \brief factor used in correlation from known symbol
+ std::vector<float> d_symbol_phase_diff; // !< \brief factor used in correlation from received symbol
+ std::vector<gr_complex> d_hestimate; // !< channel estimate
+ int d_coarse_freq; // !< \brief search distance in number of bins
+ unsigned int d_phase_count; // !< \brief accumulator for coarse freq correction
+ float d_snr_est; // !< an estimation of the signal to noise ratio
+
+ gr_complex *d_phase_lut; // !< look-up table for coarse frequency compensation
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ public:
+ /*!
+ * \brief Return an estimate of the SNR of the channel
+ */
+ float snr() { return d_snr_est; }
+
+ ~digital_ofdm_frame_acquisition(void);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+
+#endif
diff --git a/gr-digital/include/digital_ofdm_frame_sink.h b/gr-digital/include/digital_ofdm_frame_sink.h
new file mode 100644
index 000000000..3575ee35b
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_frame_sink.h
@@ -0,0 +1,126 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2011 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 3, 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_DIGITAL_OFDM_FRAME_SINK_H
+#define INCLUDED_DIGITAL_OFDM_FRAME_SINK_H
+
+#include <gr_sync_block.h>
+#include <gr_msg_queue.h>
+
+class digital_ofdm_frame_sink;
+typedef boost::shared_ptr<digital_ofdm_frame_sink> digital_ofdm_frame_sink_sptr;
+
+digital_ofdm_frame_sink_sptr
+digital_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,
+ const std::vector<unsigned char> &sym_value_out,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain=0.25, float freq_gain=0.25*0.25/4.0);
+
+/*!
+ * \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs
+ * them into packets, and sends to to a message queue sink.
+ * \ingroup sink_blk
+ * \ingroup ofdm_blk
+ *
+ * NOTE: The mod input parameter simply chooses a pre-defined demapper/slicer. Eventually,
+ * we want to be able to pass in a reference to an object to do the demapping and slicing
+ * for a given modulation type.
+ */
+class digital_ofdm_frame_sink : public gr_sync_block
+{
+ friend digital_ofdm_frame_sink_sptr
+ digital_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,
+ const std::vector<unsigned char> &sym_value_out,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
+
+ private:
+ enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER};
+
+ static const int MAX_PKT_LEN = 4096;
+ static const int HEADERBYTELEN = 4;
+
+ gr_msg_queue_sptr d_target_queue; // where to send the packet when received
+ state_t d_state;
+ unsigned int d_header; // header bits
+ int d_headerbytelen_cnt; // how many so far
+
+ unsigned char *d_bytes_out; // hold the current bytes produced by the demapper
+
+ unsigned int d_occupied_carriers;
+ unsigned int d_byte_offset;
+ unsigned int d_partial_byte;
+
+ unsigned char d_packet[MAX_PKT_LEN]; // assembled payload
+ int d_packetlen; // length of packet
+ int d_packet_whitener_offset; // offset into whitener string to use
+ int d_packetlen_cnt; // how many so far
+
+ gr_complex * d_derotated_output; // Pointer to output stream to send deroated symbols out
+
+ std::vector<gr_complex> d_sym_position;
+ std::vector<unsigned char> d_sym_value_out;
+ std::vector<gr_complex> d_dfe;
+ unsigned int d_nbits;
+
+ unsigned char d_resid;
+ unsigned int d_nresid;
+ float d_phase;
+ float d_freq;
+ float d_phase_gain;
+ float d_freq_gain;
+ float d_eq_gain;
+
+ std::vector<int> d_subcarrier_map;
+
+ protected:
+ digital_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
+ const std::vector<unsigned char> &sym_value_out,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
+
+ void enter_search();
+ void enter_have_sync();
+ void enter_have_header();
+
+ bool header_ok()
+ {
+ // confirm that two copies of header info are identical
+ return ((d_header >> 16) ^ (d_header & 0xffff)) == 0;
+ }
+
+ unsigned char slicer(const gr_complex x);
+ unsigned int demapper(const gr_complex *in,
+ unsigned char *out);
+
+ bool set_sym_value_out(const std::vector<gr_complex> &sym_position,
+ const std::vector<unsigned char> &sym_value_out);
+
+ public:
+ ~digital_ofdm_frame_sink();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_OFDM_FRAME_SINK_H */
diff --git a/gr-digital/include/digital_ofdm_insert_preamble.h b/gr-digital/include/digital_ofdm_insert_preamble.h
new file mode 100644
index 000000000..a7d87d42f
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_insert_preamble.h
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2011 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 3, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_INSERT_PREAMBLE_H
+#define INCLUDED_DIGITAL_OFDM_INSERT_PREAMBLE_H
+
+#include <gr_block.h>
+#include <vector>
+
+class digital_ofdm_insert_preamble;
+typedef boost::shared_ptr<digital_ofdm_insert_preamble> digital_ofdm_insert_preamble_sptr;
+
+digital_ofdm_insert_preamble_sptr
+digital_make_ofdm_insert_preamble(int fft_length,
+ const std::vector<std::vector<gr_complex> > &preamble);
+
+/*!
+ * \brief insert "pre-modulated" preamble symbols before each payload.
+ * \ingroup sync_blk
+ * \ingroup ofdm_blk
+ *
+ * <pre>
+ * input 1: stream of vectors of gr_complex [fft_length]
+ * These are the modulated symbols of the payload.
+ *
+ * input 2: stream of char. The LSB indicates whether the corresponding
+ * symbol on input 1 is the first symbol of the payload or not.
+ * It's a 1 if the corresponding symbol is the first symbol,
+ * otherwise 0.
+ *
+ * N.B., this implies that there must be at least 1 symbol in the payload.
+ *
+ *
+ * output 1: stream of vectors of gr_complex [fft_length]
+ * These include the preamble symbols and the payload symbols.
+ *
+ * output 2: stream of char. The LSB indicates whether the corresponding
+ * symbol on input 1 is the first symbol of a packet (i.e., the
+ * first symbol of the preamble.) It's a 1 if the corresponding
+ * symbol is the first symbol, otherwise 0.
+ * </pre>
+ *
+ * \param fft_length length of each symbol in samples.
+ * \param preamble vector of symbols that represent the pre-modulated preamble.
+ */
+
+class digital_ofdm_insert_preamble : public gr_block
+{
+ friend digital_ofdm_insert_preamble_sptr
+ digital_make_ofdm_insert_preamble(int fft_length,
+ const std::vector<std::vector<gr_complex> > &preamble);
+
+protected:
+ digital_ofdm_insert_preamble(int fft_length,
+ const std::vector<std::vector<gr_complex> > &preamble);
+
+private:
+ enum state_t {
+ ST_IDLE,
+ ST_PREAMBLE,
+ ST_FIRST_PAYLOAD,
+ ST_PAYLOAD
+ };
+
+ int d_fft_length;
+ const std::vector<std::vector<gr_complex> > d_preamble;
+ state_t d_state;
+ int d_nsymbols_output;
+ int d_pending_flag;
+
+ void enter_idle();
+ void enter_preamble();
+ void enter_first_payload();
+ void enter_payload();
+
+
+public:
+ ~digital_ofdm_insert_preamble();
+
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_INSERT_PREAMBLE_H */
diff --git a/gr-digital/include/digital_ofdm_mapper_bcv.h b/gr-digital/include/digital_ofdm_mapper_bcv.h
new file mode 100644
index 000000000..e9b47eb9d
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_mapper_bcv.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2011 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 3, 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_DIGITAL_OFDM_MAPPER_BCV_H
+#define INCLUDED_DIGITAL_OFDM_MAPPER_BCV_H
+
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+class digital_ofdm_mapper_bcv;
+typedef boost::shared_ptr<digital_ofdm_mapper_bcv> digital_ofdm_mapper_bcv_sptr;
+
+digital_ofdm_mapper_bcv_sptr
+digital_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit,
+ unsigned occupied_carriers, unsigned int fft_length);
+
+/*!
+ * \brief take a stream of bytes in and map to a vector of complex
+ * constellation points suitable for IFFT input to be used in an ofdm
+ * modulator. Abstract class must be subclassed with specific mapping.
+ * \ingroup modulation_blk
+ * \ingroup ofdm_blk
+ */
+
+class digital_ofdm_mapper_bcv : public gr_sync_block
+{
+ friend digital_ofdm_mapper_bcv_sptr
+ digital_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit,
+ unsigned occupied_carriers, unsigned int fft_length);
+protected:
+ digital_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit,
+ unsigned occupied_carriers, unsigned int fft_length);
+
+ private:
+ std::vector<gr_complex> d_constellation;
+ gr_msg_queue_sptr d_msgq;
+ gr_message_sptr d_msg;
+ unsigned d_msg_offset;
+ bool d_eof;
+
+ unsigned int d_occupied_carriers;
+ unsigned int d_fft_length;
+ unsigned int d_bit_offset;
+ int d_pending_flag;
+
+ unsigned long d_nbits;
+ unsigned char d_msgbytes;
+
+ unsigned char d_resid;
+ unsigned int d_nresid;
+
+ std::vector<int> d_subcarrier_map;
+
+ int randsym();
+
+ public:
+ ~digital_ofdm_mapper_bcv(void);
+
+ gr_msg_queue_sptr msgq() const { return d_msgq; }
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+};
+
+#endif
diff --git a/gr-digital/include/digital_ofdm_sampler.h b/gr-digital/include/digital_ofdm_sampler.h
new file mode 100644
index 000000000..01aa40d46
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_sampler.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2011 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 3, 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_DIGITAL_OFDM_SAMPLER_H
+#define INCLUDED_DIGITAL_OFDM_SAMPLER_H
+
+#include <gr_sync_block.h>
+
+class digital_ofdm_sampler;
+typedef boost::shared_ptr<digital_ofdm_sampler> digital_ofdm_sampler_sptr;
+
+digital_ofdm_sampler_sptr digital_make_ofdm_sampler (unsigned int fft_length,
+ unsigned int symbol_length,
+ unsigned int timeout=1000);
+
+/*!
+ * \brief does the rest of the OFDM stuff
+ * \ingroup ofdm_blk
+ */
+class digital_ofdm_sampler : public gr_block
+{
+ friend digital_ofdm_sampler_sptr digital_make_ofdm_sampler (unsigned int fft_length,
+ unsigned int symbol_length,
+ unsigned int timeout);
+
+ digital_ofdm_sampler (unsigned int fft_length,
+ unsigned int symbol_length,
+ unsigned int timeout);
+
+ private:
+ enum state_t {STATE_NO_SIG, STATE_PREAMBLE, STATE_FRAME};
+
+ state_t d_state;
+ unsigned int d_timeout_max;
+ unsigned int d_timeout;
+ unsigned int d_fft_length;
+ unsigned int d_symbol_length;
+
+ public:
+ 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);
+};
+
+#endif