diff options
author | Tom Rondeau <trondeau@vt.edu> | 2012-08-11 11:04:03 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2012-08-11 11:04:03 -0400 |
commit | a6e56683cf74054fad6774138bea9f844c76be09 (patch) | |
tree | 1749031397ac4ebdc117b05a753c82976e8aca62 /gr-digital/include/digital | |
parent | af0a5780201c71c8f2d682cdab2274942e5771d5 (diff) |
digital: converted over constellation and related blocks.
Possibly still a work-in-progress. Need to convert over some more before QA can be run.
Diffstat (limited to 'gr-digital/include/digital')
-rw-r--r-- | gr-digital/include/digital/CMakeLists.txt | 6 | ||||
-rw-r--r-- | gr-digital/include/digital/constellation.h | 417 | ||||
-rw-r--r-- | gr-digital/include/digital/constellation_decoder_cb.h | 55 | ||||
-rw-r--r-- | gr-digital/include/digital/constellation_receiver_cb.h | 93 |
4 files changed, 568 insertions, 3 deletions
diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt index 0f009f1fa8..0fdc0dd008 100644 --- a/gr-digital/include/digital/CMakeLists.txt +++ b/gr-digital/include/digital/CMakeLists.txt @@ -84,9 +84,9 @@ install(FILES clock_recovery_mm_ff.h cma_equalizer_cc.h # cpmmod_bc.h -# constellation.h -# constellation_receiver_cb.h -# constellation_decoder_cb.h + constellation.h + constellation_receiver_cb.h + constellation_decoder_cb.h # correlate_access_code_bb.h # correlate_access_code_tag_bb.h # costas_loop_cc.h diff --git a/gr-digital/include/digital/constellation.h b/gr-digital/include/digital/constellation.h new file mode 100644 index 0000000000..49da76f70d --- /dev/null +++ b/gr-digital/include/digital/constellation.h @@ -0,0 +1,417 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010-2012 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 <digital/api.h> +#include <digital_metric_type.h> +#include <boost/enable_shared_from_this.hpp> +#include <gr_complex.h> +#include <vector> + +namespace gr { + namespace digital { + + /************************************************************/ + /* constellation */ + /* */ + /* Base class defining interface. */ + /************************************************************/ + + class constellation; + typedef boost::shared_ptr<constellation> 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_API constellation + : public boost::enable_shared_from_this<constellation> + { + public: + constellation(std::vector<gr_complex> constell, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); + constellation(); + ~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; + } + + 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(); + }; + + /************************************************************/ + /* constellation_calcdist */ + /* */ + /************************************************************/ + + /*! \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_API constellation_calcdist + : public constellation + { + public: + typedef boost::shared_ptr<constellation_calcdist> sptr; + + // public constructor + static sptr make(std::vector<gr_complex> constell, + 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: + constellation_calcdist(std::vector<gr_complex> constell, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); + }; + + + /************************************************************/ + /*! 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_API constellation_sector : public constellation + { + public: + + constellation_sector(std::vector<gr_complex> constell, + 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; + }; + + /************************************************************/ + /* 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_API constellation_rect + : public constellation_sector + { + public: + typedef boost::shared_ptr<constellation_rect> sptr; + + // public constructor + static constellation_rect::sptr make(std::vector<gr_complex> constell, + 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; + + constellation_rect(std::vector<gr_complex> constell, + 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); + }; + + + /************************************************************/ + /* constellation_psk */ + /************************************************************/ + + /*! + * \brief 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_API constellation_psk : public constellation_sector + { + public: + typedef boost::shared_ptr<constellation_psk> sptr; + + // public constructor + static sptr make(std::vector<gr_complex> constell, + std::vector<unsigned int> pre_diff_code, + unsigned int n_sectors); + + ~constellation_psk(); + + protected: + unsigned int get_sector(const gr_complex *sample); + + unsigned int calc_sector_value(unsigned int sector); + + private: + constellation_psk(std::vector<gr_complex> constell, + std::vector<unsigned int> pre_diff_code, + unsigned int n_sectors); + }; + + + /************************************************************/ + /* constellation_bpsk */ + /* */ + /* Only works for BPSK. */ + /* */ + /************************************************************/ + + /*! + * \brief Digital constellation for BPSK + * \ingroup digital + */ + class DIGITAL_API constellation_bpsk : public constellation + { + public: + typedef boost::shared_ptr<constellation_bpsk> sptr; + + // public constructor + static sptr make(); + + ~constellation_bpsk(); + + unsigned int decision_maker(const gr_complex *sample); + + private: + constellation_bpsk(); + }; + + + /************************************************************/ + /* constellation_qpsk */ + /* */ + /* Only works for QPSK. */ + /* */ + /************************************************************/ + + /*! + * \brief Digital constellation for QPSK + * \ingroup digital + */ + class DIGITAL_API constellation_qpsk : public constellation + { + public: + typedef boost::shared_ptr<constellation_qpsk> sptr; + + // public constructor + static sptr make(); + + ~constellation_qpsk(); + + unsigned int decision_maker(const gr_complex *sample); + + private: + constellation_qpsk(); + }; + + + /************************************************************/ + /* constellation_dqpsk */ + /* */ + /* Works with differential encoding; slower decisions. */ + /* */ + /************************************************************/ + + /*! + * \brief Digital constellation for DQPSK + * \ingroup digital + */ + class DIGITAL_API constellation_dqpsk : public constellation + { + public: + typedef boost::shared_ptr<constellation_dqpsk> sptr; + + // public constructor + static sptr make(); + + ~constellation_dqpsk(); + + unsigned int decision_maker(const gr_complex *sample); + + private: + constellation_dqpsk(); + }; + + + /************************************************************/ + /* constellation_8psk */ + /* */ + /* Only works for 8PSK. */ + /* */ + /************************************************************/ + + /*! + * \brief Digital constellation for 8PSK + * \ingroup digital + */ + class DIGITAL_API constellation_8psk : public constellation + { + public: + typedef boost::shared_ptr<constellation_8psk> sptr; + + // public constructor + static sptr make(); + + ~constellation_8psk(); + + unsigned int decision_maker(const gr_complex *sample); + + private: + constellation_8psk(); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_CONSTELLATION_H */ 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 0000000000..2a98cae643 --- /dev/null +++ b/gr-digital/include/digital/constellation_decoder_cb.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 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 <digital/api.h> +#include <digital/constellation.h> +#include <gr_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief Constellation Decoder + * \ingroup coding_blk + * \ingroup digital + * + */ + class DIGITAL_API constellation_decoder_cb + : virtual public gr_block + { + public: + // gr::digital::constellation_decoder_cb::sptr + typedef boost::shared_ptr<constellation_decoder_cb> sptr; + + /*! + * \brief Make constellation decoder block. + */ + static sptr make(constellation_sptr constellation); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H */ 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 0000000000..b1c415ea09 --- /dev/null +++ b/gr-digital/include/digital/constellation_receiver_cb.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 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 <digital/api.h> +#include <digital/constellation.h> +#include <gr_block.h> + +namespace gr { + namespace digital { + + /*! + * \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_API constellation_receiver_cb + : virtual public gr_block + { + public: + // gr::digital::constellation_receiver_cb::sptr + typedef boost::shared_ptr<constellation_receiver_cb> sptr; + + /*! + * \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 chooses which phase detector and decision + * maker to use in the work loop based on the value of M. + */ + static sptr make(constellation_sptr constellation, + float loop_bw, float fmin, float fmax); + + virtual void phase_error_tracking(float phase_error) = 0; + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H */ |