summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/general
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/lib/general')
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am18
-rw-r--r--gnuradio-core/src/lib/general/general.i10
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation.cc368
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation.h322
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation.i146
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.cc78
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.h64
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.i38
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_receiver_cb.cc131
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_receiver_cb.h149
-rw-r--r--gnuradio-core/src/lib/general/gr_constellation_receiver_cb.i43
-rw-r--r--gnuradio-core/src/lib/general/gr_int_to_float.cc59
-rw-r--r--gnuradio-core/src/lib/general/gr_int_to_float.h51
-rw-r--r--gnuradio-core/src/lib/general/gr_int_to_float.i30
-rw-r--r--gnuradio-core/src/lib/general/gr_metric_type.h31
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc374
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h120
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i39
18 files changed, 2069 insertions, 2 deletions
diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am
index 3ceea7a6d..3b8997d8c 100644
--- a/gnuradio-core/src/lib/general/Makefile.am
+++ b/gnuradio-core/src/lib/general/Makefile.am
@@ -56,7 +56,10 @@ libgeneral_la_SOURCES = \
gr_complex_to_xxx.cc \
gr_conjugate_cc.cc \
gr_copy.cc \
+ gr_constellation.cc \
gr_constellation_decoder_cb.cc \
+ gr_constellation_decoder2_cb.cc \
+ gr_constellation_receiver_cb.cc \
gr_correlate_access_code_bb.cc \
gr_costas_loop_cc.cc \
gr_count_bits.cc \
@@ -111,6 +114,7 @@ libgeneral_la_SOURCES = \
gr_ofdm_demapper_vcb.cc \
gr_ofdm_mapper_bcv.cc \
gr_ofdm_frame_sink.cc \
+ gr_ofdm_frame_sink2.cc \
gr_ofdm_insert_preamble.cc \
gr_ofdm_sampler.cc \
gr_pa_2x2_phase_combiner.cc \
@@ -139,6 +143,7 @@ libgeneral_la_SOURCES = \
gr_rms_cf.cc \
gr_rms_ff.cc \
gr_short_to_float.cc \
+ gr_int_to_float.cc \
gr_simple_correlator.cc \
gr_simple_framer.cc \
gr_simple_squelch_cc.cc \
@@ -212,7 +217,10 @@ grinclude_HEADERS = \
gr_complex_to_interleaved_short.h \
gr_complex_to_xxx.h \
gr_conjugate_cc.h \
+ gr_constellation.h \
gr_constellation_decoder_cb.h \
+ gr_constellation_decoder2_cb.h \
+ gr_constellation_receiver_cb.h \
gr_copy.h \
gr_correlate_access_code_bb.h \
gr_costas_loop_cc.h \
@@ -261,8 +269,8 @@ grinclude_HEADERS = \
gr_log2_const.h \
gr_map_bb.h \
gr_math.h \
+ gr_metric_type.h \
gr_misc.h \
- gr_mpsk_receiver_cc.h \
gr_nco.h \
gr_nlog10_ff.h \
gr_nop.h \
@@ -273,6 +281,7 @@ grinclude_HEADERS = \
gr_ofdm_demapper_vcb.h \
gr_ofdm_mapper_bcv.h \
gr_ofdm_frame_sink.h \
+ gr_ofdm_frame_sink2.h \
gr_ofdm_insert_preamble.h \
gr_ofdm_sampler.h \
gr_pa_2x2_phase_combiner.h \
@@ -301,6 +310,7 @@ grinclude_HEADERS = \
gr_rms_cf.h \
gr_rms_ff.h \
gr_short_to_float.h \
+ gr_int_to_float.h \
gr_simple_correlator.h \
gr_simple_framer.h \
gr_simple_framer_sync.h \
@@ -386,7 +396,10 @@ swiginclude_HEADERS = \
gr_complex_to_interleaved_short.i \
gr_complex_to_xxx.i \
gr_conjugate_cc.i \
+ gr_constellation.i \
gr_constellation_decoder_cb.i \
+ gr_constellation_decoder2_cb.i \
+ gr_constellation_receiver_cb.i \
gr_copy.i \
gr_correlate_access_code_bb.i \
gr_costas_loop_cc.i \
@@ -418,6 +431,7 @@ swiginclude_HEADERS = \
gr_glfsr_source_b.i \
gr_glfsr_source_f.i \
gr_head.i \
+ gr_int_to_float.i \
gr_interleave.i \
gr_interleaved_short_to_complex.i \
gr_iqcomp_cc.i \
@@ -427,7 +441,6 @@ swiginclude_HEADERS = \
gr_lms_dfe_cc.i \
gr_lms_dfe_ff.i \
gr_map_bb.i \
- gr_mpsk_receiver_cc.i \
gr_nlog10_ff.i \
gr_nop.i \
gr_null_sink.i \
@@ -437,6 +450,7 @@ swiginclude_HEADERS = \
gr_ofdm_demapper_vcb.i \
gr_ofdm_mapper_bcv.i \
gr_ofdm_frame_sink.i \
+ gr_ofdm_frame_sink2.i \
gr_ofdm_insert_preamble.i \
gr_ofdm_sampler.i \
gr_pa_2x2_phase_combiner.i \
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index fb9c4c0f2..d9648ef64 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -42,6 +42,7 @@
#include <gr_float_to_char.h>
#include <gr_float_to_uchar.h>
#include <gr_short_to_float.h>
+#include <gr_int_to_float.h>
#include <gr_char_to_float.h>
#include <gr_uchar_to_float.h>
#include <gr_frequency_modulator_fc.h>
@@ -69,6 +70,8 @@
#include <gr_fake_channel_coder_pp.h>
#include <gr_throttle.h>
#include <gr_mpsk_receiver_cc.h>
+#include <gr_constellation_receiver_cb.h>
+#include <gr_constellation.h>
#include <gr_stream_mux.h>
#include <gr_stream_to_streams.h>
#include <gr_streams_to_stream.h>
@@ -97,6 +100,7 @@
#include <gr_ofdm_cyclic_prefixer.h>
#include <gr_ofdm_mapper_bcv.h>
#include <gr_ofdm_frame_sink.h>
+#include <gr_ofdm_frame_sink2.h>
#include <gr_ofdm_insert_preamble.h>
#include <gr_ofdm_sampler.h>
#include <gr_regenerate_bb.h>
@@ -111,6 +115,7 @@
#include <gr_correlate_access_code_bb.h>
#include <gr_diff_phasor_cc.h>
#include <gr_constellation_decoder_cb.h>
+#include <gr_constellation_decoder2_cb.h>
#include <gr_binary_slicer_fb.h>
#include <gr_diff_encoder_bb.h>
#include <gr_diff_decoder_bb.h>
@@ -167,6 +172,7 @@
%include "gr_float_to_char.i"
%include "gr_float_to_uchar.i"
%include "gr_short_to_float.i"
+%include "gr_int_to_float.i"
%include "gr_char_to_float.i"
%include "gr_uchar_to_float.i"
%include "gr_frequency_modulator_fc.i"
@@ -194,6 +200,8 @@
%include "gr_fake_channel_coder_pp.i"
%include "gr_throttle.i"
%include "gr_mpsk_receiver_cc.i"
+%include "gr_constellation_receiver_cb.i"
+%include "gr_constellation.i"
%include "gr_stream_mux.i"
%include "gr_stream_to_streams.i"
%include "gr_streams_to_stream.i"
@@ -222,6 +230,7 @@
%include "gr_ofdm_cyclic_prefixer.i"
%include "gr_ofdm_mapper_bcv.i"
%include "gr_ofdm_frame_sink.i"
+%include "gr_ofdm_frame_sink2.i"
%include "gr_ofdm_insert_preamble.i"
%include "gr_ofdm_sampler.i"
%include "gr_regenerate_bb.i"
@@ -236,6 +245,7 @@
%include "gr_correlate_access_code_bb.i"
%include "gr_diff_phasor_cc.i"
%include "gr_constellation_decoder_cb.i"
+%include "gr_constellation_decoder2_cb.i"
%include "gr_binary_slicer_fb.i"
%include "gr_diff_encoder_bb.i"
%include "gr_diff_decoder_bb.i"
diff --git a/gnuradio-core/src/lib/general/gr_constellation.cc b/gnuradio-core/src/lib/general/gr_constellation.cc
new file mode 100644
index 000000000..eede99ffd
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation.cc
@@ -0,0 +1,368 @@
+/* -*- 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.
+ */
+
+#include <gr_io_signature.h>
+#include <gr_constellation.h>
+#include <gr_metric_type.h>
+#include <gr_math.h>
+#include <gr_complex.h>
+#include <math.h>
+#include <iostream>
+#include <stdlib.h>
+#include <float.h>
+#include <stdexcept>
+
+#define M_TWOPI (2*M_PI)
+#define SQRT_TWO 0.707107
+
+// Base Constellation Class
+
+gr_constellation::gr_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry, unsigned int dimensionality) :
+ d_constellation(constellation),
+ d_pre_diff_code(pre_diff_code),
+ d_rotational_symmetry(rotational_symmetry),
+ d_dimensionality(dimensionality)
+{
+ if (pre_diff_code.size() == 0)
+ d_apply_pre_diff_code = false;
+ else if (pre_diff_code.size() != constellation.size())
+ throw std::runtime_error ("The constellation and pre-diff code must be of the same length.");
+ else
+ d_apply_pre_diff_code = true;
+ calc_arity();
+}
+
+gr_constellation::gr_constellation () :
+ d_apply_pre_diff_code(false),
+ d_rotational_symmetry(0),
+ d_dimensionality(1)
+{
+ calc_arity();
+}
+
+//! Returns the constellation points for a symbol value
+void gr_constellation::map_to_points(unsigned int value, gr_complex *points) {
+ for (unsigned int i=0; i<d_dimensionality; i++)
+ points[i] = d_constellation[value*d_dimensionality + i];
+}
+
+std::vector<gr_complex> gr_constellation::map_to_points_v(unsigned int value) {
+ std::vector<gr_complex> points_v;
+ points_v.resize(d_dimensionality);
+ map_to_points(value, &(points_v[0]));
+ return points_v;
+}
+
+float gr_constellation::get_distance(unsigned int index, const gr_complex *sample) {
+ float dist = 0;
+ for (unsigned int i=0; i<d_dimensionality; i++) {
+ dist += norm(sample[i] - d_constellation[index*d_dimensionality + i]);
+ }
+ return dist;
+}
+
+unsigned int gr_constellation::get_closest_point(const gr_complex *sample) {
+
+ unsigned int min_index = 0;
+ float min_euclid_dist;
+ float euclid_dist;
+
+ min_euclid_dist = get_distance(0, sample);
+ min_index = 0;
+ for (unsigned int j = 1; j < d_arity; j++){
+ euclid_dist = get_distance(j, sample);
+ if (euclid_dist < min_euclid_dist){
+ min_euclid_dist = euclid_dist;
+ min_index = j;
+ }
+ }
+ return min_index;
+}
+
+unsigned int gr_constellation::decision_maker_pe(const gr_complex *sample, float *phase_error)
+{
+ unsigned int index = decision_maker(sample);
+ *phase_error = 0;
+ for (unsigned int d=0; d<d_dimensionality; d++)
+ *phase_error += -arg(sample[d]*conj(d_constellation[index+d]));
+ return index;
+}
+
+/*
+unsigned int gr_constellation::decision_maker_e(const gr_complex *sample, float *error)
+{
+ unsigned int index = decision_maker(sample);
+ *error = 0;
+ for (unsigned int d=0; d<d_dimensionality; d++)
+ *error += sample[d]*conj(d_constellation[index+d]);
+ return index;
+}
+*/
+
+std::vector<gr_complex> gr_constellation::s_points () {
+ if (d_dimensionality != 1)
+ throw std::runtime_error ("s_points only works for dimensionality 1 constellations.");
+ else
+ return d_constellation;
+}
+
+std::vector<std::vector<gr_complex> > gr_constellation::v_points () {
+ std::vector<std::vector<gr_complex> > vv_const;
+ vv_const.resize(d_arity);
+ for (unsigned int p=0; p<d_arity; p++) {
+ std::vector<gr_complex> v_const;
+ v_const.resize(d_dimensionality);
+ for (unsigned int d=0; d<d_dimensionality; d++) {
+ v_const[d] = d_constellation[p*d_dimensionality+d];
+ }
+ vv_const[p] = v_const;
+ }
+ return vv_const;
+}
+
+void gr_constellation::calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type) {
+ switch (type){
+ case TRELLIS_EUCLIDEAN:
+ calc_euclidean_metric(sample, metric);
+ break;
+ case TRELLIS_HARD_SYMBOL:
+ calc_hard_symbol_metric(sample, metric);
+ break;
+ case TRELLIS_HARD_BIT:
+ throw std::runtime_error ("Invalid metric type (not yet implemented).");
+ break;
+ default:
+ throw std::runtime_error ("Invalid metric type.");
+ }
+}
+
+void gr_constellation::calc_euclidean_metric(const gr_complex *sample, float *metric) {
+ for (unsigned int o=0; o<d_arity; o++) {
+ metric[o] = get_distance(o, sample);
+ }
+}
+
+void gr_constellation::calc_hard_symbol_metric(const gr_complex *sample, float *metric){
+ float minm = FLT_MAX;
+ unsigned int minmi = 0;
+ for (unsigned int o=0; o<d_arity; o++) {
+ float dist = get_distance(o, sample);
+ if (dist < minm) {
+ minm = dist;
+ minmi = o;
+ }
+ }
+ for(unsigned int o=0; o<d_arity; o++) {
+ metric[o] = (o==minmi?0.0:1.0);
+ }
+}
+
+void gr_constellation::calc_arity () {
+ if (d_constellation.size() % d_dimensionality != 0)
+ throw std::runtime_error ("Constellation vector size must be a multiple of the dimensionality.");
+ d_arity = d_constellation.size()/d_dimensionality;
+}
+
+unsigned int gr_constellation::decision_maker_v (std::vector<gr_complex> sample) {
+ assert(sample.size() == d_dimensionality);
+ return decision_maker (&(sample[0]));
+}
+
+gr_constellation_calcdist_sptr
+gr_make_constellation_calcdist(std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry, unsigned int dimensionality)
+{
+ return gr_constellation_calcdist_sptr(new gr_constellation_calcdist (constellation, pre_diff_code, rotational_symmetry,
+ dimensionality));
+}
+
+gr_constellation_calcdist::gr_constellation_calcdist(std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality) :
+ gr_constellation(constellation, pre_diff_code, rotational_symmetry, dimensionality)
+{}
+
+// Chooses points base on shortest distance.
+// Inefficient.
+unsigned int gr_constellation_calcdist::decision_maker(const gr_complex *sample)
+{
+ return get_closest_point(sample);
+}
+
+gr_constellation_sector::gr_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) :
+ gr_constellation(constellation, pre_diff_code, rotational_symmetry, dimensionality),
+ n_sectors(n_sectors)
+{
+}
+
+unsigned int gr_constellation_sector::decision_maker (const gr_complex *sample) {
+ unsigned int sector;
+ sector = get_sector(sample);
+ return sector_values[sector];
+}
+
+void gr_constellation_sector::find_sector_values () {
+ unsigned int i;
+ sector_values.clear();
+ for (i=0; i<n_sectors; i++) {
+ sector_values.push_back(calc_sector_value(i));
+ }
+}
+
+gr_constellation_rect_sptr
+gr_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)
+{
+ return gr_constellation_rect_sptr(new gr_constellation_rect (constellation, pre_diff_code, rotational_symmetry,
+ real_sectors, imag_sectors, width_real_sectors,
+ width_imag_sectors));
+ }
+
+gr_constellation_rect::gr_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) :
+ gr_constellation_sector(constellation, pre_diff_code, rotational_symmetry, 1, real_sectors * imag_sectors),
+ n_real_sectors(real_sectors), n_imag_sectors(imag_sectors),
+ d_width_real_sectors(width_real_sectors), d_width_imag_sectors(width_imag_sectors)
+{
+ find_sector_values();
+}
+
+unsigned int gr_constellation_rect::get_sector (const gr_complex *sample) {
+ int real_sector, imag_sector;
+ unsigned int sector;
+ real_sector = int(real(*sample)/d_width_real_sectors + n_real_sectors/2.0);
+ if (real_sector < 0) real_sector = 0;
+ if (real_sector >= n_real_sectors) real_sector = n_real_sectors-1;
+ imag_sector = int(imag(*sample)/d_width_imag_sectors + n_imag_sectors/2.0);
+ if (imag_sector < 0) imag_sector = 0;
+ if (imag_sector >= n_imag_sectors) imag_sector = n_imag_sectors-1;
+ sector = real_sector * n_imag_sectors + imag_sector;
+ return sector;
+}
+
+unsigned int gr_constellation_rect::calc_sector_value (unsigned int sector) {
+ unsigned int real_sector, imag_sector;
+ gr_complex sector_center;
+ unsigned int closest_point;
+ real_sector = float(sector)/n_imag_sectors;
+ imag_sector = sector - real_sector * n_imag_sectors;
+ sector_center = gr_complex((real_sector + 0.5 - n_real_sectors/2.0) * d_width_real_sectors,
+ (imag_sector + 0.5 - n_imag_sectors/2.0) * d_width_imag_sectors);
+ closest_point = get_closest_point(&sector_center);
+ return closest_point;
+}
+
+
+gr_constellation_psk_sptr
+gr_make_constellation_psk(std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors)
+{
+ return gr_constellation_psk_sptr(new gr_constellation_psk (constellation, pre_diff_code,
+ n_sectors));
+}
+
+gr_constellation_psk::gr_constellation_psk (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors) :
+ gr_constellation_sector(constellation, pre_diff_code, constellation.size(), 1, n_sectors)
+{
+ find_sector_values();
+}
+
+unsigned int gr_constellation_psk::get_sector (const gr_complex *sample) {
+ float phase = arg(*sample);
+ float width = M_TWOPI / n_sectors;
+ int sector = floor(phase/width + 0.5);
+ unsigned int u_sector;
+ if (sector < 0) sector += n_sectors;
+ u_sector = sector;
+ return sector;
+}
+
+unsigned int gr_constellation_psk::calc_sector_value (unsigned int sector) {
+ float phase = sector * M_TWOPI / n_sectors;
+ gr_complex sector_center = gr_complex(cos(phase), sin(phase));
+ unsigned int closest_point = get_closest_point(&sector_center);
+ return closest_point;
+}
+
+
+gr_constellation_bpsk_sptr
+gr_make_constellation_bpsk()
+{
+ return gr_constellation_bpsk_sptr(new gr_constellation_bpsk ());
+}
+
+gr_constellation_bpsk::gr_constellation_bpsk ()
+{
+ d_constellation.resize(2);
+ d_constellation[0] = gr_complex(-1, 0);
+ d_constellation[1] = gr_complex(1, 0);
+ d_rotational_symmetry = 2;
+ d_dimensionality = 1;
+ calc_arity();
+}
+
+unsigned int gr_constellation_bpsk::decision_maker(const gr_complex *sample)
+{
+ return (real(*sample) > 0);
+}
+
+
+gr_constellation_qpsk_sptr
+gr_make_constellation_qpsk()
+{
+ return gr_constellation_qpsk_sptr(new gr_constellation_qpsk ());
+}
+
+gr_constellation_qpsk::gr_constellation_qpsk ()
+{
+ d_constellation.resize(4);
+ // Gray-coded
+ d_constellation[0] = gr_complex(-SQRT_TWO, -SQRT_TWO);
+ d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO);
+ d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO);
+ d_rotational_symmetry = 4;
+ d_dimensionality = 1;
+ calc_arity();
+}
+
+unsigned int gr_constellation_qpsk::decision_maker(const gr_complex *sample)
+{
+ // Real component determines small bit.
+ // Imag component determines big bit.
+ return 2*(imag(*sample)>0) + (real(*sample)>0);
+}
diff --git a/gnuradio-core/src/lib/general/gr_constellation.h b/gnuradio-core/src/lib/general/gr_constellation.h
new file mode 100644
index 000000000..f6726a9b5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation.h
@@ -0,0 +1,322 @@
+/* -*- 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_GR_CONSTELLATION_H
+#define INCLUDED_GR_CONSTELLATION_H
+
+#include <vector>
+#include <math.h>
+#include <gr_complex.h>
+#include <boost/enable_shared_from_this.hpp>
+#include <gr_metric_type.h>
+
+/************************************************************/
+/* gr_constellation */
+/* */
+/* Base class defining interface. */
+/************************************************************/
+
+class gr_constellation;
+typedef boost::shared_ptr<gr_constellation> gr_constellation_sptr;
+
+class gr_constellation : public boost::enable_shared_from_this<gr_constellation>
+{
+public:
+ gr_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry, unsigned int dimensionality);
+ gr_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;}
+ //! 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(d_constellation.size())/d_dimensionality/log(2));
+ }
+
+ unsigned int arity () {
+ return d_arity;
+ }
+
+ gr_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 ();
+};
+
+/************************************************************/
+/* gr_constellation_calcdist */
+/* */
+/* Constellation which calculates the distance to each */
+/* point in the constellation for decision making. */
+/* Inefficient for large constellations. */
+/************************************************************/
+
+class gr_constellation_calcdist;
+typedef boost::shared_ptr<gr_constellation_calcdist> gr_constellation_calcdist_sptr;
+
+// public constructor
+gr_constellation_calcdist_sptr
+gr_make_constellation_calcdist (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry, unsigned int dimensionality);
+
+
+class gr_constellation_calcdist : public gr_constellation
+{
+ public:
+ gr_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 gr_constellation_calcdist_sptr
+ gr_make_constellation_calcdist (std::vector<gr_complex> constellation);
+};
+
+/************************************************************/
+/* gr_constellation_sector */
+/* */
+/* An abstract class. */
+/* Constellation space is divided into sectors. */
+/* Each sector is associated with the nearest constellation */
+/* point. */
+/************************************************************/
+
+class gr_constellation_sector : public gr_constellation
+{
+ public:
+
+ gr_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;
+
+};
+
+/************************************************************/
+/* gr_constellation_rect */
+/* */
+/* 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 gr_constellation_rect;
+typedef boost::shared_ptr<gr_constellation_rect> gr_constellation_rect_sptr;
+
+// public constructor
+gr_constellation_rect_sptr
+gr_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 gr_constellation_rect : public gr_constellation_sector
+{
+ public:
+
+ gr_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 gr_constellation_rect_sptr
+ gr_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);
+
+};
+
+/************************************************************/
+/* gr_constellation_psk */
+/* */
+/* 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. */
+/************************************************************/
+
+class gr_constellation_psk;
+typedef boost::shared_ptr<gr_constellation_psk> gr_constellation_psk_sptr;
+
+// public constructor
+gr_constellation_psk_sptr
+gr_make_constellation_psk (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+class gr_constellation_psk : public gr_constellation_sector
+{
+ public:
+
+ gr_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 gr_constellation_psk_sptr
+ gr_make_constellation_psk (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+
+};
+
+/************************************************************/
+/* gr_constellation_bpsk */
+/* */
+/* Only works for BPSK. */
+/* */
+/************************************************************/
+
+class gr_constellation_bpsk;
+typedef boost::shared_ptr<gr_constellation_bpsk> gr_constellation_bpsk_sptr;
+
+// public constructor
+gr_constellation_bpsk_sptr
+gr_make_constellation_bpsk ();
+
+class gr_constellation_bpsk : public gr_constellation
+{
+ public:
+
+ gr_constellation_bpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend gr_constellation_bpsk_sptr
+ gr_make_constellation_bpsk ();
+
+};
+
+/************************************************************/
+/* gr_constellation_qpsk */
+/* */
+/* Only works for QPSK. */
+/* */
+/************************************************************/
+
+class gr_constellation_qpsk;
+typedef boost::shared_ptr<gr_constellation_qpsk> gr_constellation_qpsk_sptr;
+
+// public constructor
+gr_constellation_qpsk_sptr
+gr_make_constellation_qpsk ();
+
+class gr_constellation_qpsk : public gr_constellation
+{
+ public:
+
+ gr_constellation_qpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend gr_constellation_qpsk_sptr
+ gr_make_constellation_qpsk ();
+
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_constellation.i b/gnuradio-core/src/lib/general/gr_constellation.i
new file mode 100644
index 000000000..179e68136
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation.i
@@ -0,0 +1,146 @@
+/* -*- 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.
+ */
+
+%template(gr_complex_vector) std::vector<gr_complex>;
+%template(unsigned_int_vector) std::vector<unsigned int>;
+
+// Make sure metric types get SWIGed.
+%include gr_metric_type.h
+
+class gr_constellation;
+typedef boost::shared_ptr<gr_constellation> gr_constellation_sptr;
+%template(gr_constellation_sptr) boost::shared_ptr<gr_constellation>;
+
+class gr_constellation
+{
+public:
+ gr_constellation (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
+ std::vector<gr_complex> points();
+ std::vector<gr_complex> s_points();
+ std::vector<std::vector<gr_complex> > v_points();
+ virtual unsigned int decision_maker (gr_complex *sample) = 0;
+ unsigned int decision_maker_v (std::vector<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);
+ std::vector<gr_complex> map_to_points_v(unsigned int value);
+ unsigned int bits_per_symbol ();
+ unsigned int arity ();
+ gr_constellation_sptr base ();
+ bool apply_pre_diff_code();
+ std::vector<unsigned int> pre_diff_code();
+ unsigned int rotational_symmetry();
+ unsigned int dimensionality();
+};
+
+class gr_constellation_calcdist;
+typedef boost::shared_ptr<gr_constellation_calcdist> gr_constellation_calcdist_sptr;
+%template(gr_constellation_calcdist_sptr) boost::shared_ptr<gr_constellation_calcdist>;
+%rename(constellation_calcdist) gr_make_constellation_calcdist;
+gr_constellation_calcdist_sptr
+gr_make_constellation_calcdist(std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
+%ignore gr_constellation_calcdist;
+
+class gr_constellation_calcdist: public gr_constellation
+{
+ public:
+ gr_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);
+};
+
+class gr_constellation_sector: public gr_constellation
+{
+};
+
+class gr_constellation_rect;
+typedef boost::shared_ptr<gr_constellation_rect> gr_constellation_rect_sptr;
+%template(gr_constellation_rect_sptr) boost::shared_ptr<gr_constellation_rect>;
+%rename(constellation_rect) gr_make_constellation_rect;
+gr_constellation_rect_sptr gr_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);
+%ignore gr_constellation_rect;
+
+class gr_constellation_rect : public gr_constellation_sector
+{
+public:
+ gr_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 gr_constellation_psk;
+typedef boost::shared_ptr<gr_constellation_psk> gr_constellation_psk_sptr;
+%template(gr_constellation_psk_sptr) boost::shared_ptr<gr_constellation_psk>;
+%rename(constellation_psk) gr_make_constellation_psk;
+gr_constellation_psk_sptr gr_make_constellation_psk(std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+%ignore gr_constellation_psk;
+
+class gr_constellation_psk : public gr_constellation_sector
+{
+public:
+ gr_constellation_psk (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int n_sectors);
+};
+
+class gr_constellation_bpsk;
+typedef boost::shared_ptr<gr_constellation_bpsk> gr_constellation_bpsk_sptr;
+%template(gr_constellation_bpsk_sptr) boost::shared_ptr<gr_constellation_bpsk>;
+%rename(constellation_bpsk) gr_make_constellation_bpsk;
+gr_constellation_bpsk_sptr gr_make_constellation_bpsk();
+%ignore gr_constellation_bpsk;
+
+class gr_constellation_bpsk : public gr_constellation
+{
+public:
+ gr_constellation_bpsk ();
+};
+
+class gr_constellation_qpsk;
+typedef boost::shared_ptr<gr_constellation_qpsk> gr_constellation_qpsk_sptr;
+%template(gr_constellation_qpsk_sptr) boost::shared_ptr<gr_constellation_qpsk>;
+%rename(constellation_qpsk) gr_make_constellation_qpsk;
+gr_constellation_qpsk_sptr gr_make_constellation_qpsk();
+%ignore gr_constellation_qpsk;
+
+class gr_constellation_qpsk : public gr_constellation
+{
+public:
+ gr_constellation_qpsk ();
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.cc b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.cc
new file mode 100644
index 000000000..a63c1d38a
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.cc
@@ -0,0 +1,78 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_constellation_decoder2_cb.h>
+#include <gr_constellation.h>
+#include <gr_io_signature.h>
+#include <iostream>
+
+gr_constellation_decoder2_cb_sptr
+gr_make_constellation_decoder2_cb (gr_constellation_sptr constellation)
+{
+ return gr_constellation_decoder2_cb_sptr
+ (new gr_constellation_decoder2_cb(constellation));
+}
+
+gr_constellation_decoder2_cb::
+gr_constellation_decoder2_cb (gr_constellation_sptr constellation)
+ : gr_block ("constellation_decoder2_cb",
+ gr_make_io_signature (1, 1, sizeof (gr_complex)),
+ gr_make_io_signature (1, 1, sizeof (unsigned char))),
+ d_constellation(constellation),
+ d_dim(constellation->dimensionality())
+{
+ set_relative_rate (1.0 / ((double) d_dim));
+}
+
+void
+gr_constellation_decoder2_cb::forecast (int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+ unsigned int input_required = noutput_items * d_dim;
+
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++)
+ ninput_items_required[i] = input_required;
+}
+
+
+int
+gr_constellation_decoder2_cb::
+general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ gr_complex const *in = (const gr_complex *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ for(int i = 0; i < noutput_items; i++){
+ out[i] = d_constellation->decision_maker(&(in[i*d_dim]));
+ }
+
+ consume_each (noutput_items * d_dim);
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.h b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.h
new file mode 100644
index 000000000..51891b636
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.h
@@ -0,0 +1,64 @@
+/* -*- 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_GR_CONSTELLATION_DECODER2_CB_H
+#define INCLUDED_GR_CONSTELLATION_DECODER2_CB_H
+
+#include <gr_block.h>
+#include <gr_constellation.h>
+#include <vector>
+
+class gr_constellation_decoder2_cb;
+typedef boost::shared_ptr<gr_constellation_decoder2_cb> gr_constellation_decoder2_cb_sptr;
+
+gr_constellation_decoder2_cb_sptr
+gr_make_constellation_decoder2_cb (gr_constellation_sptr constellation);
+
+/*!
+ * \brief Constellation Decoder
+ * \ingroup coding_blk
+ *
+ */
+class gr_constellation_decoder2_cb : public gr_block
+{
+
+ private:
+ gr_constellation_sptr d_constellation;
+ unsigned int d_dim;
+
+ friend gr_constellation_decoder2_cb_sptr
+ gr_make_constellation_decoder2_cb (gr_constellation_sptr constellation);
+
+ gr_constellation_decoder2_cb (gr_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/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.i b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.i
new file mode 100644
index 000000000..2865363d8
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_decoder2_cb.i
@@ -0,0 +1,38 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,constellation_decoder2_cb)
+
+gr_constellation_decoder2_cb_sptr
+gr_make_constellation_decoder2_cb (gr_constellation_sptr constellation);
+
+class gr_constellation_decoder2_cb : public gr_sync_block
+{
+ private:
+ gr_constellation_decoder2_cb (gr_constellation_sptr constellation);
+
+ friend gr_constellation_decoder2_cb_sptr
+ gr_make_constellation_decoder2_cb (gr_constellation_sptr constellation);
+
+ public:
+ ~gr_constellation_decoder2_cb();
+};
diff --git a/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.cc b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.cc
new file mode 100644
index 000000000..c1b56f44f
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.cc
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2006,2007,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include <gr_prefs.h>
+#include <gr_constellation.h>
+#include <gr_constellation_receiver_cb.h>
+#include <stdexcept>
+#include <gr_math.h>
+#include <gr_expj.h>
+
+
+#define M_TWOPI (2*M_PI)
+#define VERBOSE_MM 0 // Used for debugging symbol timing loop
+#define VERBOSE_COSTAS 0 // Used for debugging phase and frequency tracking
+
+// Public constructor
+
+gr_constellation_receiver_cb_sptr
+gr_make_constellation_receiver_cb(gr_constellation_sptr constell,
+ float alpha, float beta,
+ float fmin, float fmax)
+{
+ return gnuradio::get_initial_sptr(new gr_constellation_receiver_cb (constell,
+ alpha, beta,
+ fmin, fmax));
+}
+
+static int ios[] = {sizeof(char), sizeof(float), sizeof(float), sizeof(float)};
+static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
+gr_constellation_receiver_cb::gr_constellation_receiver_cb (gr_constellation_sptr constellation,
+ float alpha, float beta,
+ float fmin, float fmax)
+ : gr_block ("constellation_receiver_cb",
+ gr_make_io_signature (1, 1, sizeof (gr_complex)),
+ gr_make_io_signaturev (1, 4, iosig)),
+ d_constellation(constellation),
+ d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0),
+ d_current_const_point(0)
+{
+ if (d_constellation->dimensionality() != 1)
+ throw std::runtime_error ("This receiver only works with constellations of dimension 1.");
+}
+
+void
+gr_constellation_receiver_cb::phase_error_tracking(float phase_error)
+{
+ d_freq += d_beta*phase_error; // adjust frequency based on error
+ d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error
+
+ // Make sure we stay within +-2pi
+ while(d_phase > M_TWOPI)
+ d_phase -= M_TWOPI;
+ while(d_phase < -M_TWOPI)
+ d_phase += M_TWOPI;
+
+ // Limit the frequency range
+ d_freq = gr_branchless_clip(d_freq, d_max_freq);
+
+#if VERBOSE_COSTAS
+ printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n",
+ phase_error, d_phase, d_freq, sample.real(), sample.imag(),
+ d_constellation->points()[d_current_const_point].real(), d_constellation->points()[d_current_const_point].imag());
+#endif
+}
+
+int
+gr_constellation_receiver_cb::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ int i=0;
+
+ float phase_error;
+ unsigned int sym_value;
+ gr_complex sample, nco;
+
+ float *out_err = 0, *out_phase = 0, *out_freq = 0;
+ if(output_items.size() == 4) {
+ out_err = (float *) output_items[1];
+ out_phase = (float *) output_items[2];
+ out_freq = (float *) output_items[3];
+ }
+
+ while((i < noutput_items) && (i < ninput_items[0])) {
+ sample = in[i];
+ nco = gr_expj(d_phase); // get the NCO value for derotating the current sample
+ sample = nco*sample; // get the downconverted symbol
+ sym_value = d_constellation->decision_maker_pe(&sample, &phase_error);
+ // phase_error = -arg(sample*conj(d_constellation->points()[sym_value]));
+ phase_error_tracking(phase_error); // corrects phase and frequency offsets
+ out[i] = sym_value;
+ if(output_items.size() == 4) {
+ out_err[i] = phase_error;
+ out_phase[i] = d_phase;
+ out_freq[i] = d_freq;
+ }
+ i++;
+ }
+
+ consume_each(i);
+ return i;
+}
+
diff --git a/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.h b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.h
new file mode 100644
index 000000000..80ffcc873
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.h
@@ -0,0 +1,149 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,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_GR_CONSTELLATION_RECEIVER_CB_H
+#define INCLUDED_GR_CONSTELLATION_RECEIVER_CB_H
+
+#include <gr_block.h>
+#include <gr_constellation.h>
+#include <gr_complex.h>
+#include <math.h>
+#include <fstream>
+
+class gr_constellation_receiver_cb;
+typedef boost::shared_ptr<gr_constellation_receiver_cb> gr_constellation_receiver_cb_sptr;
+
+// public constructor
+gr_constellation_receiver_cb_sptr
+gr_make_constellation_receiver_cb (gr_constellation_sptr constellation,
+ float alpha, float beta,
+ 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
+ *
+ * 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 gr_constellation_receiver_cb : public gr_block
+{
+ 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);
+
+
+ // Member function related to the phase/frequency tracking portion of the receiver
+ //! (CL) Returns the value for alpha (the phase gain term)
+ float alpha() const { return d_alpha; }
+
+ //! (CL) Returns the value of beta (the frequency gain term)
+ float beta() const { return d_beta; }
+
+ //! (CL) Returns the current value of the frequency of the NCO in the Costas loop
+ float freq() const { return d_freq; }
+
+ //! (CL) Returns the current value of the phase of the NCO in the Costal loop
+ float phase() const { return d_phase; }
+
+ //! (CL) Sets the value for alpha (the phase gain term)
+ void set_alpha(float alpha) { d_alpha = alpha; }
+
+ //! (CL) Setss the value of beta (the frequency gain term)
+ void set_beta(float beta) { d_beta = beta; }
+
+ //! (CL) Sets the current value of the frequency of the NCO in the Costas loop
+ void set_freq(float freq) { d_freq = freq; }
+
+ //! (CL) Setss the current value of the phase of the NCO in the Costal loop
+ void set_phase(float phase) { d_phase = phase; }
+
+
+protected:
+
+ /*!
+ * \brief Constructor to synchronize incoming M-PSK symbols
+ *
+ * \param constellation constellation of points for generic modulation
+ * \param alpha gain parameter to adjust the phase in the Costas loop (~0.01)
+ * \param beta gain parameter to adjust the frequency in the Costas loop (~alpha^2/4)
+ * \param fmin minimum normalized frequency value the loop can achieve
+ * \param fmax maximum normalized frequency value the loop can achieve
+ *
+ * The constructor also chooses which phase detector and decision maker to use in the work loop based on the
+ * value of M.
+ */
+ gr_constellation_receiver_cb (gr_constellation_sptr constellation,
+ float alpha, float beta,
+ float fmin, float fmax);
+
+ void phase_error_tracking(float phase_error);
+
+ private:
+ unsigned int d_M;
+
+ // Members related to carrier and phase tracking
+ float d_alpha;
+ float d_beta;
+ float d_freq, d_max_freq, d_min_freq;
+ float d_phase;
+
+ gr_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 gr_constellation_receiver_cb_sptr
+ gr_make_constellation_receiver_cb (gr_constellation_sptr constell,
+ float alpha, float beta,
+ float fmin, float fmax);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.i b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.i
new file mode 100644
index 000000000..f4df49701
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_constellation_receiver_cb.i
@@ -0,0 +1,43 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,constellation_receiver_cb);
+
+gr_constellation_receiver_cb_sptr gr_make_constellation_receiver_cb (gr_constellation_sptr constellation,
+ float alpha, float beta,
+ float fmin, float fmax);
+class gr_constellation_receiver_cb : public gr_block
+{
+ private:
+ gr_constellation_receiver_cb (gr_contellation_sptr constellation,
+ float alpha, float beta,
+ float fmin, float fmax);
+public:
+ float alpha() const { return d_alpha; }
+ float beta() const { return d_beta; }
+ float freq() const { return d_freq; }
+ float phase() const { return d_phase; }
+ void set_alpha(float alpha) { d_alpha = alpha; }
+ void set_beta(float beta) { d_beta = beta; }
+ void set_freq(float freq) { d_freq = freq; }
+ void set_phase(float phase) { d_phase = phase; }
+};
diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.cc b/gnuradio-core/src/lib/general/gr_int_to_float.cc
new file mode 100644
index 000000000..b5a19e5c0
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_int_to_float.cc
@@ -0,0 +1,59 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_int_to_float.h>
+#include <gr_io_signature.h>
+
+gr_int_to_float_sptr
+gr_make_int_to_float ()
+{
+ return gnuradio::get_initial_sptr(new gr_int_to_float ());
+}
+
+gr_int_to_float::gr_int_to_float ()
+ : gr_sync_block ("gr_int_to_float",
+ gr_make_io_signature (1, 1, sizeof (int32_t)),
+ gr_make_io_signature (1, 1, sizeof (float)))
+{
+}
+
+int
+gr_int_to_float::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const int32_t *in = (const int32_t *) input_items[0];
+ float *out = (float *) output_items[0];
+
+ for(int i=0; i < noutput_items; i++) {
+ out[i] = (float)in[i];
+ }
+
+ return noutput_items;
+}
+
+
+
diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.h b/gnuradio-core/src/lib/general/gr_int_to_float.h
new file mode 100644
index 000000000..cf1223be5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_int_to_float.h
@@ -0,0 +1,51 @@
+/* -*- 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_GR_INT_TO_FLOAT_H
+#define INCLUDED_GR_INT_TO_FLOAT_H
+
+#include <gr_sync_block.h>
+
+class gr_int_to_float;
+typedef boost::shared_ptr<gr_int_to_float> gr_int_to_float_sptr;
+
+gr_int_to_float_sptr
+gr_make_int_to_float ();
+
+/*!
+ * \brief Convert stream of short to a stream of float
+ * \ingroup converter_blk
+ */
+
+class gr_int_to_float : public gr_sync_block
+{
+ friend gr_int_to_float_sptr gr_make_int_to_float ();
+ gr_int_to_float ();
+
+ public:
+ virtual int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+
+#endif /* INCLUDED_GR_INT_TO_FLOAT_H */
diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.i b/gnuradio-core/src/lib/general/gr_int_to_float.i
new file mode 100644
index 000000000..8cb9e35b5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_int_to_float.i
@@ -0,0 +1,30 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,int_to_float)
+
+gr_int_to_float_sptr gr_make_int_to_float ();
+
+class gr_int_to_float : public gr_sync_block
+{
+ gr_int_to_float ();
+};
diff --git a/gnuradio-core/src/lib/general/gr_metric_type.h b/gnuradio-core/src/lib/general/gr_metric_type.h
new file mode 100644
index 000000000..74c93b55e
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_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_GR_METRIC_TYPE_H
+#define INCLUDED_GR_METRIC_TYPE_H
+
+typedef enum {
+ TRELLIS_EUCLIDEAN = 200, TRELLIS_HARD_SYMBOL, TRELLIS_HARD_BIT
+} trellis_metric_type_t;
+
+#endif
+
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc
new file mode 100644
index 000000000..40574b4e9
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc
@@ -0,0 +1,374 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_ofdm_frame_sink2.h>
+#include <gr_io_signature.h>
+#include <gr_expj.h>
+#include <gr_math.h>
+#include <math.h>
+#include <cstdio>
+#include <stdexcept>
+#include <iostream>
+#include <string.h>
+#include <gr_constellation.h>
+
+#define VERBOSE 0
+
+inline void
+gr_ofdm_frame_sink2::enter_search()
+{
+ if (VERBOSE)
+ fprintf(stderr, "@ enter_search\n");
+
+ d_state = STATE_SYNC_SEARCH;
+
+}
+
+inline void
+gr_ofdm_frame_sink2::enter_have_sync()
+{
+ if (VERBOSE)
+ fprintf(stderr, "@ enter_have_sync\n");
+
+ d_state = STATE_HAVE_SYNC;
+
+ // clear state of demapper
+ d_byte_offset = 0;
+ d_partial_byte = 0;
+
+ d_header = 0;
+ d_headerbytelen_cnt = 0;
+
+ // Resetting PLL
+ d_freq = 0.0;
+ d_phase = 0.0;
+ fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
+}
+
+inline void
+gr_ofdm_frame_sink2::enter_have_header()
+{
+ d_state = STATE_HAVE_HEADER;
+
+ // header consists of two 16-bit shorts in network byte order
+ // payload length is lower 12 bits
+ // whitener offset is upper 4 bits
+ d_packetlen = (d_header >> 16) & 0x0fff;
+ d_packet_whitener_offset = (d_header >> 28) & 0x000f;
+ d_packetlen_cnt = 0;
+
+ if (VERBOSE)
+ fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n",
+ d_packetlen, d_packet_whitener_offset);
+}
+
+
+unsigned int gr_ofdm_frame_sink2::demapper(const gr_complex *in,
+ unsigned char *out)
+{
+ unsigned int i=0, bytes_produced=0;
+ gr_complex carrier;
+
+ carrier=gr_expj(d_phase);
+
+ gr_complex accum_error = 0.0;
+ //while(i < d_occupied_carriers) {
+ while(i < d_subcarrier_map.size()) {
+ if(d_nresid > 0) {
+ d_partial_byte |= d_resid;
+ d_byte_offset += d_nresid;
+ d_nresid = 0;
+ d_resid = 0;
+ }
+
+ //while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
+ while((d_byte_offset < 8) && (i < d_subcarrier_map.size())) {
+ //gr_complex sigrot = in[i]*carrier*d_dfe[i];
+ gr_complex sigrot = in[d_subcarrier_map[i]]*carrier*d_dfe[i];
+
+ if(d_derotated_output != NULL){
+ d_derotated_output[i] = sigrot;
+ }
+
+ unsigned char bits = d_constell->decision_maker(&sigrot);
+
+ gr_complex closest_sym = d_constell->points()[bits];
+
+ accum_error += sigrot * conj(closest_sym);
+
+ // FIX THE FOLLOWING STATEMENT
+ if (norm(sigrot)> 0.001) d_dfe[i] += d_eq_gain*(closest_sym/sigrot-d_dfe[i]);
+
+ i++;
+
+ if((8 - d_byte_offset) >= d_nbits) {
+ d_partial_byte |= bits << (d_byte_offset);
+ d_byte_offset += d_nbits;
+ }
+ else {
+ d_nresid = d_nbits-(8-d_byte_offset);
+ int mask = ((1<<(8-d_byte_offset))-1);
+ d_partial_byte |= (bits & mask) << d_byte_offset;
+ d_resid = bits >> (8-d_byte_offset);
+ d_byte_offset += (d_nbits - d_nresid);
+ }
+ //printf("demod symbol: %.4f + j%.4f bits: %x partial_byte: %x byte_offset: %d resid: %x nresid: %d\n",
+ // in[i-1].real(), in[i-1].imag(), bits, d_partial_byte, d_byte_offset, d_resid, d_nresid);
+ }
+
+ if(d_byte_offset == 8) {
+ //printf("demod byte: %x \n\n", d_partial_byte);
+ out[bytes_produced++] = d_partial_byte;
+ d_byte_offset = 0;
+ d_partial_byte = 0;
+ }
+ }
+ //std::cerr << "accum_error " << accum_error << std::endl;
+
+ float angle = arg(accum_error);
+
+ d_freq = d_freq - d_freq_gain*angle;
+ d_phase = d_phase + d_freq - d_phase_gain*angle;
+ if (d_phase >= 2*M_PI) d_phase -= 2*M_PI;
+ if (d_phase <0) d_phase += 2*M_PI;
+
+ //if(VERBOSE)
+ // std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << std::endl;
+
+ return bytes_produced;
+}
+
+
+gr_ofdm_frame_sink2_sptr
+gr_make_ofdm_frame_sink2(gr_constellation_sptr constell,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
+ float phase_gain, float freq_gain)
+{
+ return gnuradio::get_initial_sptr(new gr_ofdm_frame_sink2(constell,
+ target_queue, occupied_carriers,
+ phase_gain, freq_gain));
+}
+
+
+gr_ofdm_frame_sink2::gr_ofdm_frame_sink2(gr_constellation_sptr constell,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
+ float phase_gain, float freq_gain)
+ : gr_sync_block ("ofdm_frame_sink2",
+ gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)),
+ d_constell(constell),
+ d_target_queue(target_queue), d_occupied_carriers(occupied_carriers),
+ d_byte_offset(0), d_partial_byte(0),
+ d_resid(0), d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain),
+ d_eq_gain(0.05)
+{
+ if (d_constell->dimensionality() != 1)
+ throw std::runtime_error ("This receiver only works with constellations of dimension 1.");
+
+ std::string carriers = "FE7F";
+
+ // A bit hacky to fill out carriers to occupied_carriers length
+ int diff = (d_occupied_carriers - 4*carriers.length());
+ while(diff > 7) {
+ carriers.insert(0, "f");
+ carriers.insert(carriers.length(), "f");
+ diff -= 8;
+ }
+
+ // if there's extras left to be processed
+ // divide remaining to put on either side of current map
+ // all of this is done to stick with the concept of a carrier map string that
+ // can be later passed by the user, even though it'd be cleaner to just do this
+ // on the carrier map itself
+ int diff_left=0;
+ int diff_right=0;
+
+ // dictionary to convert from integers to ascii hex representation
+ char abc[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ if(diff > 0) {
+ char c[2] = {0,0};
+
+ diff_left = (int)ceil((float)diff/2.0f); // number of carriers to put on the left side
+ c[0] = abc[(1 << diff_left) - 1]; // convert to bits and move to ASCI integer
+ carriers.insert(0, c);
+
+ diff_right = diff - diff_left; // number of carriers to put on the right side
+ c[0] = abc[0xF^((1 << diff_right) - 1)]; // convert to bits and move to ASCI integer
+ carriers.insert(carriers.length(), c);
+ }
+
+ // It seemed like such a good idea at the time...
+ // because we are only dealing with the occupied_carriers
+ // at this point, the diff_left in the following compensates
+ // for any offset from the 0th carrier introduced
+ unsigned int i,j,k;
+ for(i = 0; i < (d_occupied_carriers/4)+diff_left; i++) {
+ char c = carriers[i];
+ for(j = 0; j < 4; j++) {
+ k = (strtol(&c, NULL, 16) >> (3-j)) & 0x1;
+ if(k) {
+ d_subcarrier_map.push_back(4*i + j - diff_left);
+ }
+ }
+ }
+
+ // make sure we stay in the limit currently imposed by the occupied_carriers
+ if(d_subcarrier_map.size() > d_occupied_carriers) {
+ throw std::invalid_argument("gr_ofdm_mapper_bcv: subcarriers allocated exceeds size of occupied carriers");
+ }
+
+ d_bytes_out = new unsigned char[d_occupied_carriers];
+ d_dfe.resize(occupied_carriers);
+ fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
+
+ d_nbits = d_constell->bits_per_symbol();
+
+ enter_search();
+}
+
+gr_ofdm_frame_sink2::~gr_ofdm_frame_sink2 ()
+{
+ delete [] d_bytes_out;
+}
+
+
+int
+gr_ofdm_frame_sink2::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ const char *sig = (const char *) input_items[1];
+ unsigned int j = 0;
+ unsigned int bytes=0;
+
+ // If the output is connected, send it the derotated symbols
+ if(output_items.size() >= 1)
+ d_derotated_output = (gr_complex *)output_items[0];
+ else
+ d_derotated_output = NULL;
+
+ if (VERBOSE)
+ fprintf(stderr,">>> Entering state machine\n");
+
+ switch(d_state) {
+
+ case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt
+ if (VERBOSE)
+ fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items);
+
+ if (sig[0]) { // Found it, set up for header decode
+ enter_have_sync();
+ }
+ break;
+
+ case STATE_HAVE_SYNC:
+ // only demod after getting the preamble signal; otherwise, the
+ // equalizer taps will screw with the PLL performance
+ bytes = demapper(&in[0], d_bytes_out);
+
+ if (VERBOSE) {
+ if(sig[0])
+ printf("ERROR -- Found SYNC in HAVE_SYNC\n");
+ fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n",
+ d_headerbytelen_cnt, d_header);
+ }
+
+ j = 0;
+ while(j < bytes) {
+ d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF);
+ j++;
+
+ if (++d_headerbytelen_cnt == HEADERBYTELEN) {
+
+ if (VERBOSE)
+ fprintf(stderr, "got header: 0x%08x\n", d_header);
+
+ // we have a full header, check to see if it has been received properly
+ if (header_ok()){
+ enter_have_header();
+
+ if (VERBOSE)
+ printf("\nPacket Length: %d\n", d_packetlen);
+
+ while((j < bytes) && (d_packetlen_cnt < d_packetlen)) {
+ d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
+ }
+
+ if(d_packetlen_cnt == d_packetlen) {
+ gr_message_sptr msg =
+ gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen);
+ memcpy(msg->msg(), d_packet, d_packetlen_cnt);
+ d_target_queue->insert_tail(msg); // send it
+ msg.reset(); // free it up
+
+ enter_search();
+ }
+ }
+ else {
+ enter_search(); // bad header
+ }
+ }
+ }
+ break;
+
+ case STATE_HAVE_HEADER:
+ bytes = demapper(&in[0], d_bytes_out);
+
+ if (VERBOSE) {
+ if(sig[0])
+ printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen);
+ fprintf(stderr,"Packet Build\n");
+ }
+
+ j = 0;
+ while(j < bytes) {
+ d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
+
+ if (d_packetlen_cnt == d_packetlen){ // packet is filled
+ // build a message
+ // NOTE: passing header field as arg1 is not scalable
+ gr_message_sptr msg =
+ gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt);
+ memcpy(msg->msg(), d_packet, d_packetlen_cnt);
+
+ d_target_queue->insert_tail(msg); // send it
+ msg.reset(); // free it up
+
+ enter_search();
+ break;
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+
+ } // switch
+
+ return 1;
+}
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h
new file mode 100644
index 000000000..de8c6a37e
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h
@@ -0,0 +1,120 @@
+/* -*- 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_GR_OFDM_FRAME_SINK2_H
+#define INCLUDED_GR_OFDM_FRAME_SINK2_H
+
+#include <gr_sync_block.h>
+#include <gr_msg_queue.h>
+#include <gr_constellation.h>
+
+class gr_ofdm_frame_sink2;
+typedef boost::shared_ptr<gr_ofdm_frame_sink2> gr_ofdm_frame_sink2_sptr;
+
+gr_ofdm_frame_sink2_sptr
+gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell,
+ 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 gr_ofdm_frame_sink2 : public gr_sync_block
+{
+ friend gr_ofdm_frame_sink2_sptr
+ gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell,
+ 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
+
+ gr_constellation_sptr d_constell;
+ 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:
+ gr_ofdm_frame_sink2(gr_constellation_sptr constell,
+ 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);
+
+ public:
+ ~gr_ofdm_frame_sink2();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_OFDM_FRAME_SINK2_H */
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i
new file mode 100644
index 000000000..8fa320089
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i
@@ -0,0 +1,39 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink2);
+
+gr_ofdm_frame_sink2_sptr
+gr_make_ofdm_frame_sink2(gr_constellation_sptr constell,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain=0.25, float freq_gain=0.25*0.25/4);
+
+class gr_ofdm_frame_sink2 : public gr_sync_block
+{
+ protected:
+ gr_ofdm_frame_sink2(gr_constellation_sptr constell,
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
+
+ public:
+ ~gr_ofdm_frame_sink2();
+};