diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2019-08-07 21:45:12 +0200 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2019-08-09 23:04:28 +0200 |
commit | f7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch) | |
tree | e09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-digital/include | |
parent | 78431dc6941e3acc67c858277dfe4a0ed583643c (diff) |
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-digital/include')
80 files changed, 5872 insertions, 5915 deletions
diff --git a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h index e89e4527a7..3024b45912 100644 --- a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h @@ -27,55 +27,61 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \ingroup coding_blk + * + * \brief + * Scramble an input stream using an LFSR. + * + * \details + * This block scrambles up to 8 bits per byte of the input + * data stream, starting at the LSB. + * + * The scrambler works by XORing the incoming bit stream by the + * output of the LFSR. Optionally, after \p count bits have been + * processed, the shift register is reset to the \p seed value. + * This allows processing fixed length vectors of samples. + * + * Alternatively, the LFSR can be reset using a reset tag to + * scramble variable length vectors. However, it cannot be reset + * between bytes. + * + * For details on configuring the LFSR, see gr::digital::lfsr. + */ +class DIGITAL_API additive_scrambler_bb : virtual public sync_block +{ +public: + // gr::digital::additive_scrambler_bb::sptr + typedef boost::shared_ptr<additive_scrambler_bb> sptr; /*! - * \ingroup coding_blk - * - * \brief - * Scramble an input stream using an LFSR. - * - * \details - * This block scrambles up to 8 bits per byte of the input - * data stream, starting at the LSB. + * \brief Create additive scrambler. * - * The scrambler works by XORing the incoming bit stream by the - * output of the LFSR. Optionally, after \p count bits have been - * processed, the shift register is reset to the \p seed value. - * This allows processing fixed length vectors of samples. - * - * Alternatively, the LFSR can be reset using a reset tag to - * scramble variable length vectors. However, it cannot be reset - * between bytes. - * - * For details on configuring the LFSR, see gr::digital::lfsr. + * \param mask Polynomial mask for LFSR + * \param seed Initial shift register contents + * \param len Shift register length + * \param count Number of bytes after which shift register is reset, 0=never + * \param bits_per_byte Number of bits per byte + * \param reset_tag_key When a tag with this key is detected, the shift register is + * reset (when this is set, count is ignored!) */ - class DIGITAL_API additive_scrambler_bb : virtual public sync_block - { - public: - // gr::digital::additive_scrambler_bb::sptr - typedef boost::shared_ptr<additive_scrambler_bb> sptr; - - /*! - * \brief Create additive scrambler. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * \param count Number of bytes after which shift register is reset, 0=never - * \param bits_per_byte Number of bits per byte - * \param reset_tag_key When a tag with this key is detected, the shift register is reset (when this is set, count is ignored!) - */ - static sptr make(int mask, int seed, int len, int count=0, int bits_per_byte=1, const std::string &reset_tag_key=""); + static sptr make(int mask, + int seed, + int len, + int count = 0, + int bits_per_byte = 1, + const std::string& reset_tag_key = ""); - virtual int mask() const = 0; - virtual int seed() const = 0; - virtual int len() const = 0; - virtual int count() const = 0; - virtual int bits_per_byte() = 0; - }; + virtual int mask() const = 0; + virtual int seed() const = 0; + virtual int len() const = 0; + virtual int count() const = 0; + virtual int bits_per_byte() = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_ADDITIVE_SCRAMBLER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/api.h b/gr-digital/include/gnuradio/digital/api.h index 71ca19ad58..722ceff2cc 100644 --- a/gr-digital/include/gnuradio/digital/api.h +++ b/gr-digital/include/gnuradio/digital/api.h @@ -25,9 +25,9 @@ #include <gnuradio/attributes.h> #ifdef gnuradio_digital_EXPORTS -# define DIGITAL_API __GR_ATTR_EXPORT +#define DIGITAL_API __GR_ATTR_EXPORT #else -# define DIGITAL_API __GR_ATTR_IMPORT +#define DIGITAL_API __GR_ATTR_IMPORT #endif #endif /* INCLUDED_DIGITAL_API_H */ diff --git a/gr-digital/include/gnuradio/digital/binary_slicer_fb.h b/gr-digital/include/gnuradio/digital/binary_slicer_fb.h index 0670ca09c6..0b27304415 100644 --- a/gr-digital/include/gnuradio/digital/binary_slicer_fb.h +++ b/gr-digital/include/gnuradio/digital/binary_slicer_fb.h @@ -27,29 +27,29 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Slice float binary symbol producing 1 bit output + * \ingroup symbol_coding_blk + * + * \details + * \li input[0][n] < 0 --> 0 + * \li input[0][n] >= 0 --> 1 + */ +class DIGITAL_API binary_slicer_fb : virtual public sync_block +{ +public: + // gr::digital::binary_slicer_fb::sptr + typedef boost::shared_ptr<binary_slicer_fb> sptr; /*! - * \brief Slice float binary symbol producing 1 bit output - * \ingroup symbol_coding_blk - * - * \details - * \li input[0][n] < 0 --> 0 - * \li input[0][n] >= 0 --> 1 + * \brief Make binary symbol slicer block. */ - class DIGITAL_API binary_slicer_fb : virtual public sync_block - { - public: - // gr::digital::binary_slicer_fb::sptr - typedef boost::shared_ptr<binary_slicer_fb> sptr; - - /*! - * \brief Make binary symbol slicer block. - */ - static sptr make(); - }; + static sptr make(); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_BINARY_SLICER_FB_H */ diff --git a/gr-digital/include/gnuradio/digital/burst_shaper.h b/gr-digital/include/gnuradio/digital/burst_shaper.h index 25277595b3..140e8cbfa0 100644 --- a/gr-digital/include/gnuradio/digital/burst_shaper.h +++ b/gr-digital/include/gnuradio/digital/burst_shaper.h @@ -27,97 +27,98 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Burst shaper block for applying burst padding and ramping. + * \ingroup packet_operators_blk + * + * \details + * + * This block applies a configurable amount of zero padding before + * and/or after a burst indicated by tagged stream length tags. + * + * If phasing symbols are used, an alternating pattern of +1/-1 + * symbols of length ceil(N/2) will be inserted before and after + * each burst, where N is the length of the taps vector. The ramp- + * up/ramp-down shape will be applied to these phasing symbols. + * + * If phasing symbols are not used, the taper will be applied + * directly to the head and tail of each burst. + * + * Length tags will be updated to include the length of any added + * zero padding or phasing symbols and will be placed at the + * beginning of the modified tagged stream. Any other tags found at + * the same offset as a length tag will also be placed at the + * beginning of the modified tagged stream, since these tags are + * assumed to be associated with the burst rather than a specific + * sample. For example, if "tx_time" tags are used to control + * bursts, their offsets should be consistent with their associated + * burst's length tags. Tags at other offsets will be placed with + * the samples on which they were found. + * + * \li input: stream of T + * \li output: stream of T + */ +template <class T> +class DIGITAL_API burst_shaper : virtual public block +{ +public: + typedef boost::shared_ptr<burst_shaper<T>> sptr; /*! - * \brief Burst shaper block for applying burst padding and ramping. - * \ingroup packet_operators_blk - * - * \details - * - * This block applies a configurable amount of zero padding before - * and/or after a burst indicated by tagged stream length tags. - * - * If phasing symbols are used, an alternating pattern of +1/-1 - * symbols of length ceil(N/2) will be inserted before and after - * each burst, where N is the length of the taps vector. The ramp- - * up/ramp-down shape will be applied to these phasing symbols. + * Make a burst shaper block. * - * If phasing symbols are not used, the taper will be applied - * directly to the head and tail of each burst. - * - * Length tags will be updated to include the length of any added - * zero padding or phasing symbols and will be placed at the - * beginning of the modified tagged stream. Any other tags found at - * the same offset as a length tag will also be placed at the - * beginning of the modified tagged stream, since these tags are - * assumed to be associated with the burst rather than a specific - * sample. For example, if "tx_time" tags are used to control - * bursts, their offsets should be consistent with their associated - * burst's length tags. Tags at other offsets will be placed with - * the samples on which they were found. - * - * \li input: stream of T - * \li output: stream of T + * \param taps: vector of window taper taps; the first ceil(N/2) + * items are the up flank and the last ceil(N/2) + * items are the down flank. If taps.size() is odd, + * the middle tap will be used as the last item of + * the up flank and first item of the down flank. + * \param pre_padding: number of zero samples to insert before + * the burst. + * \param post_padding: number of zero samples to append after + * the burst. + * \param insert_phasing: if true, insert alternating +1/-1 + * pattern of length ceil(N/2) before and + * after the burst and apply ramp up and + * ramp down taps, respectively, to the + * inserted patterns instead of the head + * and tail items of the burst. + * \param length_tag_name: the name of the tagged stream length + * tag key. */ - template <class T> - class DIGITAL_API burst_shaper : virtual public block - { - public: - typedef boost::shared_ptr< burst_shaper<T> > sptr; - - /*! - * Make a burst shaper block. - * - * \param taps: vector of window taper taps; the first ceil(N/2) - * items are the up flank and the last ceil(N/2) - * items are the down flank. If taps.size() is odd, - * the middle tap will be used as the last item of - * the up flank and first item of the down flank. - * \param pre_padding: number of zero samples to insert before - * the burst. - * \param post_padding: number of zero samples to append after - * the burst. - * \param insert_phasing: if true, insert alternating +1/-1 - * pattern of length ceil(N/2) before and - * after the burst and apply ramp up and - * ramp down taps, respectively, to the - * inserted patterns instead of the head - * and tail items of the burst. - * \param length_tag_name: the name of the tagged stream length - * tag key. - */ - static sptr make(const std::vector<T> &taps, - int pre_padding=0, int post_padding=0, - bool insert_phasing=false, - const std::string &length_tag_name="packet_len"); + static sptr make(const std::vector<T>& taps, + int pre_padding = 0, + int post_padding = 0, + bool insert_phasing = false, + const std::string& length_tag_name = "packet_len"); - /*! - * Returns the amount of zero padding inserted before each burst. - */ - virtual int pre_padding() const = 0; + /*! + * Returns the amount of zero padding inserted before each burst. + */ + virtual int pre_padding() const = 0; - /*! - * Returns the amount of zero padding inserted after each burst. - */ - virtual int post_padding() const = 0; + /*! + * Returns the amount of zero padding inserted after each burst. + */ + virtual int post_padding() const = 0; - /*! - * Returns the total amount of zero padding and phasing symbols - * inserted before each burst. - */ - virtual int prefix_length() const = 0; + /*! + * Returns the total amount of zero padding and phasing symbols + * inserted before each burst. + */ + virtual int prefix_length() const = 0; - /*! - * Returns the total amount of zero padding and phasing symbols - * inserted after each burst. - */ - virtual int suffix_length() const = 0; - }; + /*! + * Returns the total amount of zero padding and phasing symbols + * inserted after each burst. + */ + virtual int suffix_length() const = 0; +}; - typedef burst_shaper<float> burst_shaper_ff; - typedef burst_shaper<gr_complex> burst_shaper_cc; - } // namespace digital +typedef burst_shaper<float> burst_shaper_ff; +typedef burst_shaper<gr_complex> burst_shaper_cc; +} // namespace digital } // namespace gr #endif /* BURST_SHAPER_H */ diff --git a/gr-digital/include/gnuradio/digital/chunks_to_symbols.h b/gr-digital/include/gnuradio/digital/chunks_to_symbols.h index f7cdd45352..3ca9e1d19d 100644 --- a/gr-digital/include/gnuradio/digital/chunks_to_symbols.h +++ b/gr-digital/include/gnuradio/digital/chunks_to_symbols.h @@ -28,55 +28,55 @@ #include <cstdint> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Map a stream of unpacked symbol indexes to stream of + * float or complex constellation points in D dimensions (D = 1 by + * default) \ingroup converter_blk + * + * \details + * \li input: stream of IN_T + * \li output: stream of OUT_T + * + * \li out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 + * + * The combination of gr::blocks::packed_to_unpacked_XX followed + * by gr::digital::chunks_to_symbols_XY handles the general case + * of mapping from a stream of bytes or shorts into arbitrary + * float or complex symbols. + * + * \sa gr::blocks::packed_to_unpacked_bb, gr::blocks::unpacked_to_packed_bb, + * \sa gr::blocks::packed_to_unpacked_ss, gr::blocks::unpacked_to_packed_ss, + * \sa gr::digital::chunks_to_symbols_bf, gr::digital::chunks_to_symbols_bc. + * \sa gr::digital::chunks_to_symbols_sf, gr::digital::chunks_to_symbols_sc. + */ +template <class IN_T, class OUT_T> +class DIGITAL_API chunks_to_symbols : virtual public sync_interpolator +{ +public: + typedef boost::shared_ptr<chunks_to_symbols<IN_T, OUT_T>> sptr; /*! - * \brief Map a stream of unpacked symbol indexes to stream of - * float or complex constellation points in D dimensions (D = 1 by - * default) \ingroup converter_blk - * - * \details - * \li input: stream of IN_T - * \li output: stream of OUT_T - * - * \li out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 + * Make a chunks-to-symbols block. * - * The combination of gr::blocks::packed_to_unpacked_XX followed - * by gr::digital::chunks_to_symbols_XY handles the general case - * of mapping from a stream of bytes or shorts into arbitrary - * float or complex symbols. - * - * \sa gr::blocks::packed_to_unpacked_bb, gr::blocks::unpacked_to_packed_bb, - * \sa gr::blocks::packed_to_unpacked_ss, gr::blocks::unpacked_to_packed_ss, - * \sa gr::digital::chunks_to_symbols_bf, gr::digital::chunks_to_symbols_bc. - * \sa gr::digital::chunks_to_symbols_sf, gr::digital::chunks_to_symbols_sc. + * \param symbol_table: list that maps chunks to symbols. + * \param D: dimension of table. */ - template <class IN_T, class OUT_T> - class DIGITAL_API chunks_to_symbols : virtual public sync_interpolator - { - public: - typedef boost::shared_ptr< chunks_to_symbols<IN_T,OUT_T> > sptr; - - /*! - * Make a chunks-to-symbols block. - * - * \param symbol_table: list that maps chunks to symbols. - * \param D: dimension of table. - */ - static sptr make(const std::vector<OUT_T> &symbol_table, const int D = 1); + static sptr make(const std::vector<OUT_T>& symbol_table, const int D = 1); - virtual int D() const = 0; - virtual std::vector<OUT_T> symbol_table() const = 0; - virtual void set_symbol_table(const std::vector<OUT_T> &symbol_table) =0; - }; + virtual int D() const = 0; + virtual std::vector<OUT_T> symbol_table() const = 0; + virtual void set_symbol_table(const std::vector<OUT_T>& symbol_table) = 0; +}; - typedef chunks_to_symbols<std::uint8_t, float> chunks_to_symbols_bf; - typedef chunks_to_symbols<std::uint8_t, gr_complex> chunks_to_symbols_bc; - typedef chunks_to_symbols<std::int16_t, float> chunks_to_symbols_sf; - typedef chunks_to_symbols<std::int16_t, gr_complex> chunks_to_symbols_sc; - typedef chunks_to_symbols<std::int32_t, float> chunks_to_symbols_if; - typedef chunks_to_symbols<std::int32_t, gr_complex> chunks_to_symbols_ic; - } /* namespace digital */ +typedef chunks_to_symbols<std::uint8_t, float> chunks_to_symbols_bf; +typedef chunks_to_symbols<std::uint8_t, gr_complex> chunks_to_symbols_bc; +typedef chunks_to_symbols<std::int16_t, float> chunks_to_symbols_sf; +typedef chunks_to_symbols<std::int16_t, gr_complex> chunks_to_symbols_sc; +typedef chunks_to_symbols<std::int32_t, float> chunks_to_symbols_if; +typedef chunks_to_symbols<std::int32_t, gr_complex> chunks_to_symbols_ic; +} /* namespace digital */ } /* namespace gr */ #endif /* CHUNKS_TO_SYMBOLS_H */ diff --git a/gr-digital/include/gnuradio/digital/clock_recovery_mm_cc.h b/gr-digital/include/gnuradio/digital/clock_recovery_mm_cc.h index c487f01db4..dab3d38699 100644 --- a/gr-digital/include/gnuradio/digital/clock_recovery_mm_cc.h +++ b/gr-digital/include/gnuradio/digital/clock_recovery_mm_cc.h @@ -21,85 +21,87 @@ */ #ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H -#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H +#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H #include <gnuradio/digital/api.h> #include <gnuradio/block.h> namespace gr { - namespace digital { - +namespace digital { + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex + * output. \ingroup synchronizers_blk + * + * \details + * This implements the Mueller and Müller (M&M) discrete-time + * error-tracking synchronizer. + * + * The peak to peak input signal amplitude must be symmetrical + * about zero, as the M&M timing error detector (TED) is a + * decision directed TED, and this block uses a symbol decision + * slicer referenced at zero. + * + * The input signal peak amplitude should be controlled to a + * consistent level (e.g. +/- 1.0) before this block to achieve + * consistent results for given gain settings; as the TED's output + * error signal is directly affected by the input amplitude. + * + * The input signal must have peaks in order for the TED to output + * a correct error signal. If the input signal pulses do not have + * peaks (e.g. rectangular pulses) the input signal should be + * conditioned with a matched pulse filter or other appropriate + * filter to peak the input pulses. For a rectangular base pulse + * that is N samples wide, the matched filter taps would be + * [1.0/float(N)]*N, or in other words a moving average over N + * samples. + * + * This block will output samples at a rate of one sample per + * recovered symbol, and is thus not outputting at a constant rate. + * + * Output symbols are not a subset of input, but may be interpolated. + * + * The complex version here is based on: Modified Mueller and + * Muller clock recovery circuit: + * + * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller + * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22 + * June 1995, pp. 1032 - 1033. + */ +class DIGITAL_API clock_recovery_mm_cc : virtual public block +{ +public: + // gr::digital::clock_recovery_mm_cc::sptr + typedef boost::shared_ptr<clock_recovery_mm_cc> sptr; + /*! - * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output. - * \ingroup synchronizers_blk - * - * \details - * This implements the Mueller and Müller (M&M) discrete-time - * error-tracking synchronizer. - * - * The peak to peak input signal amplitude must be symmetrical - * about zero, as the M&M timing error detector (TED) is a - * decision directed TED, and this block uses a symbol decision - * slicer referenced at zero. - * - * The input signal peak amplitude should be controlled to a - * consistent level (e.g. +/- 1.0) before this block to achieve - * consistent results for given gain settings; as the TED's output - * error signal is directly affected by the input amplitude. - * - * The input signal must have peaks in order for the TED to output - * a correct error signal. If the input signal pulses do not have - * peaks (e.g. rectangular pulses) the input signal should be - * conditioned with a matched pulse filter or other appropriate - * filter to peak the input pulses. For a rectangular base pulse - * that is N samples wide, the matched filter taps would be - * [1.0/float(N)]*N, or in other words a moving average over N - * samples. + * Make a M&M clock recovery block. * - * This block will output samples at a rate of one sample per - * recovered symbol, and is thus not outputting at a constant rate. - * - * Output symbols are not a subset of input, but may be interpolated. - * - * The complex version here is based on: Modified Mueller and - * Muller clock recovery circuit: - * - * 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. + * \param omega Initial estimate of samples per symbol + * \param gain_omega Gain setting for omega update loop + * \param mu Initial estimate of phase of sample + * \param gain_mu Gain setting for mu update loop + * \param omega_relative_limit limit on omega */ - class DIGITAL_API clock_recovery_mm_cc : virtual public block - { - public: - // gr::digital::clock_recovery_mm_cc::sptr - typedef boost::shared_ptr<clock_recovery_mm_cc> sptr; - - /*! - * Make a M&M clock recovery block. - * - * \param omega Initial estimate of samples per symbol - * \param gain_omega Gain setting for omega update loop - * \param mu Initial estimate of phase of sample - * \param gain_mu Gain setting for mu update loop - * \param omega_relative_limit limit on omega - */ - static sptr make(float omega, float gain_omega, - float mu, float gain_mu, - float omega_relative_limit); + static sptr make(float omega, + float gain_omega, + float mu, + float gain_mu, + float omega_relative_limit); - virtual float mu() const = 0; - virtual float omega() const = 0; - virtual float gain_mu() const = 0; - virtual float gain_omega() const = 0; + virtual float mu() const = 0; + virtual float omega() const = 0; + virtual float gain_mu() const = 0; + virtual float gain_omega() const = 0; - virtual void set_verbose(bool verbose) = 0; - virtual void set_gain_mu (float gain_mu) = 0; - virtual void set_gain_omega (float gain_omega) = 0; - virtual void set_mu (float mu) = 0; - virtual void set_omega (float omega) = 0; - }; + virtual void set_verbose(bool verbose) = 0; + virtual void set_gain_mu(float gain_mu) = 0; + virtual void set_gain_omega(float gain_omega) = 0; + virtual void set_mu(float mu) = 0; + virtual void set_omega(float omega) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/clock_recovery_mm_ff.h b/gr-digital/include/gnuradio/digital/clock_recovery_mm_ff.h index 61b2e96ac8..437f9acbce 100644 --- a/gr-digital/include/gnuradio/digital/clock_recovery_mm_ff.h +++ b/gr-digital/include/gnuradio/digital/clock_recovery_mm_ff.h @@ -21,82 +21,84 @@ */ #ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H -#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H +#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H #include <gnuradio/digital/api.h> #include <gnuradio/block.h> namespace gr { - namespace digital { - +namespace digital { + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with float input, float + * output. \ingroup synchronizers_blk + * + * \details + * This implements the Mueller and Müller (M&M) discrete-time + * error-tracking synchronizer. + * + * The peak to peak input signal amplitude must be symmetrical + * about zero, as the M&M timing error detector (TED) is a + * decision directed TED, and this block uses a symbol decision + * slicer referenced at zero. + * + * The input signal peak amplitude should be controlled to a + * consistent level (e.g. +/- 1.0) before this block to achieve + * consistent results for given gain settings; as the TED's output + * error signal is directly affected by the input amplitude. + * + * The input signal must have peaks in order for the TED to output + * a correct error signal. If the input signal pulses do not have + * peaks (e.g. rectangular pulses) the input signal should be + * conditioned with a matched pulse filter or other appropriate + * filter to peak the input pulses. For a rectangular base pulse + * that is N samples wide, the matched filter taps would be + * [1.0/float(N)]*N, or in other words a moving average over N + * samples. + * + * This block will output samples at a rate of one sample per + * recovered symbol, and is thus not outputting at a constant rate. + * + * Output symbols are not a subset of input, but may be interpolated. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc + * Moeneclaey, & Stefan Fechtel. ISBN 0-471-50275-8. + */ +class DIGITAL_API clock_recovery_mm_ff : virtual public block +{ +public: + // gr::digital::clock_recovery_mm_ff::sptr + typedef boost::shared_ptr<clock_recovery_mm_ff> sptr; + /*! - * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output. - * \ingroup synchronizers_blk - * - * \details - * This implements the Mueller and Müller (M&M) discrete-time - * error-tracking synchronizer. - * - * The peak to peak input signal amplitude must be symmetrical - * about zero, as the M&M timing error detector (TED) is a - * decision directed TED, and this block uses a symbol decision - * slicer referenced at zero. - * - * The input signal peak amplitude should be controlled to a - * consistent level (e.g. +/- 1.0) before this block to achieve - * consistent results for given gain settings; as the TED's output - * error signal is directly affected by the input amplitude. - * - * The input signal must have peaks in order for the TED to output - * a correct error signal. If the input signal pulses do not have - * peaks (e.g. rectangular pulses) the input signal should be - * conditioned with a matched pulse filter or other appropriate - * filter to peak the input pulses. For a rectangular base pulse - * that is N samples wide, the matched filter taps would be - * [1.0/float(N)]*N, or in other words a moving average over N - * samples. - * - * This block will output samples at a rate of one sample per - * recovered symbol, and is thus not outputting at a constant rate. - * - * Output symbols are not a subset of input, but may be interpolated. + * Make a M&M clock recovery block. * - * See "Digital Communication Receivers: Synchronization, Channel - * Estimation and Signal Processing" by Heinrich Meyr, Marc - * Moeneclaey, & Stefan Fechtel. ISBN 0-471-50275-8. + * \param omega Initial estimate of samples per symbol + * \param gain_omega Gain setting for omega update loop + * \param mu Initial estimate of phase of sample + * \param gain_mu Gain setting for mu update loop + * \param omega_relative_limit maximum relative deviation from omega */ - class DIGITAL_API clock_recovery_mm_ff : virtual public block - { - public: - // gr::digital::clock_recovery_mm_ff::sptr - typedef boost::shared_ptr<clock_recovery_mm_ff> sptr; + static sptr make(float omega, + float gain_omega, + float mu, + float gain_mu, + float omega_relative_limit); - /*! - * Make a M&M clock recovery block. - * - * \param omega Initial estimate of samples per symbol - * \param gain_omega Gain setting for omega update loop - * \param mu Initial estimate of phase of sample - * \param gain_mu Gain setting for mu update loop - * \param omega_relative_limit maximum relative deviation from omega - */ - static sptr make(float omega, float gain_omega, - float mu, float gain_mu, - float omega_relative_limit); - - virtual float mu() const = 0; - virtual float omega() const = 0; - virtual float gain_mu() const = 0; - virtual float gain_omega() const = 0; + virtual float mu() const = 0; + virtual float omega() const = 0; + virtual float gain_mu() const = 0; + virtual float gain_omega() const = 0; - virtual void set_verbose(bool verbose) = 0; - virtual void set_gain_mu (float gain_mu) = 0; - virtual void set_gain_omega (float gain_omega) = 0; - virtual void set_mu (float mu) = 0; - virtual void set_omega (float omega) = 0; - }; + virtual void set_verbose(bool verbose) = 0; + virtual void set_gain_mu(float gain_mu) = 0; + virtual void set_gain_omega(float gain_omega) = 0; + virtual void set_mu(float mu) = 0; + virtual void set_omega(float omega) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H */ diff --git a/gr-digital/include/gnuradio/digital/cma_equalizer_cc.h b/gr-digital/include/gnuradio/digital/cma_equalizer_cc.h index c9cfb6d767..e4973c28f8 100644 --- a/gr-digital/include/gnuradio/digital/cma_equalizer_cc.h +++ b/gr-digital/include/gnuradio/digital/cma_equalizer_cc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -21,55 +21,55 @@ */ #ifndef INCLUDED_DIGITAL_CMA_EQUALIZER_CC_H -#define INCLUDED_DIGITAL_CMA_EQUALIZER_CC_H +#define INCLUDED_DIGITAL_CMA_EQUALIZER_CC_H #include <gnuradio/digital/api.h> #include <gnuradio/sync_decimator.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Implements constant modulus adaptive filter on complex stream. + * \ingroup equalizers_blk + * + * \details + * The error value and tap update equations (for p=2) can be found in: + * + * D. Godard, "Self-Recovering Equalization and Carrier Tracking + * in Two-Dimensional Data Communication Systems," IEEE + * Transactions on Communications, Vol. 28, No. 11, pp. 1867 - + * 1875, 1980. + */ +class DIGITAL_API cma_equalizer_cc : virtual public sync_decimator +{ +protected: + virtual gr_complex error(const gr_complex& out) = 0; + virtual void update_tap(gr_complex& tap, const gr_complex& in) = 0; + +public: + // gr::digital::cma_equalizer_cc::sptr + typedef boost::shared_ptr<cma_equalizer_cc> sptr; /*! - * \brief Implements constant modulus adaptive filter on complex stream. - * \ingroup equalizers_blk + * Make a CMA Equalizer block * - * \details - * The error value and tap update equations (for p=2) can be found in: - * - * D. Godard, "Self-Recovering Equalization and Carrier Tracking - * in Two-Dimensional Data Communication Systems," IEEE - * Transactions on Communications, Vol. 28, No. 11, pp. 1867 - - * 1875, 1980. + * \param num_taps Numer of taps in the equalizer (channel size) + * \param modulus Modulus of the modulated signals + * \param mu Gain of the update loop + * \param sps Number of samples per symbol of the input signal */ - class DIGITAL_API cma_equalizer_cc: virtual public sync_decimator - { - protected: - virtual gr_complex error(const gr_complex &out) = 0; - virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; - - public: - // gr::digital::cma_equalizer_cc::sptr - typedef boost::shared_ptr<cma_equalizer_cc> sptr; - - /*! - * Make a CMA Equalizer block - * - * \param num_taps Numer of taps in the equalizer (channel size) - * \param modulus Modulus of the modulated signals - * \param mu Gain of the update loop - * \param sps Number of samples per symbol of the input signal - */ - static sptr make(int num_taps, float modulus, float mu, int sps); + static sptr make(int num_taps, float modulus, float mu, int sps); - virtual void set_taps(const std::vector<gr_complex> &taps) = 0; - virtual std::vector<gr_complex> taps() const = 0; - virtual float gain() const = 0; - virtual void set_gain(float mu) = 0; - virtual float modulus() const = 0; - virtual void set_modulus(float mod) = 0; - }; + virtual void set_taps(const std::vector<gr_complex>& taps) = 0; + virtual std::vector<gr_complex> taps() const = 0; + virtual float gain() const = 0; + virtual void set_gain(float mu) = 0; + virtual float modulus() const = 0; + virtual void set_modulus(float mod) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CMA_EQUALIZER_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/constellation.h b/gr-digital/include/gnuradio/digital/constellation.h index 0a90d7e8d3..8ea728fc74 100644 --- a/gr-digital/include/gnuradio/digital/constellation.h +++ b/gr-digital/include/gnuradio/digital/constellation.h @@ -21,7 +21,7 @@ */ #ifndef INCLUDED_DIGITAL_CONSTELLATION_H -#define INCLUDED_DIGITAL_CONSTELLATION_H +#define INCLUDED_DIGITAL_CONSTELLATION_H #include <gnuradio/digital/api.h> #include <gnuradio/digital/metric_type.h> @@ -32,672 +32,665 @@ #include <vector> namespace gr { - namespace digital { +namespace digital { - /************************************************************/ - /* constellation */ - /* */ - /* Base class defining interface. */ - /************************************************************/ +/************************************************************/ +/* constellation */ +/* */ +/* Base class defining interface. */ +/************************************************************/ - class constellation; - typedef boost::shared_ptr<constellation> constellation_sptr; +class constellation; +typedef boost::shared_ptr<constellation> constellation_sptr; - /*! - * \brief An abstracted constellation object - * \ingroup symbol_coding_blk - * - * \details - * 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<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - bool normalize_points=true); - constellation(); - virtual ~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, gr::digital::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<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(); - } - - pmt::pmt_t as_pmt() - { - return pmt::make_any(boost::any(base())); - } - - /*! \brief Generates the soft decision LUT based on - * constellation and symbol map. - * - * \details Generates the soft decision LUT based on - * constellation and symbol map. It can be given a estimate of - * the noise power in the channel as \p npwr. - * - * \param precision Number of bits of precision on each axis. - * \param npwr Estimate of the noise power (if known). - * - * This is expensive to compute. - */ - void gen_soft_dec_lut(int precision, float npwr=1.0); - - /*! \brief Calculate soft decisions for the given \p sample. - * - * \details Calculate the soft decisions from the given \p sample - * at the given noise power \p npwr. - * - * This is a very costly algorithm (especially for higher order - * modulations) and should be used sparingly. It uses the - * #gen_soft_dec_lut function to generate the LUT, which - * should be done once or if a large change in the noise floor - * is detected. - * - * Instead of using this function, generate the LUT using the - * #gen_soft_dec_lut after creating the constellation object - * and then use the #soft_decision_maker function to return the - * answer from the LUT. - * - * \param sample The complex sample to get the soft decisions. - * \param npwr Estimate of the noise power (if known). - */ - virtual std::vector<float> calc_soft_dec(gr_complex sample, float npwr=1.0); - - /*! \brief Define a soft decision look-up table. - * - * \details Define a soft decision look-up table (LUT). Because - * soft decisions can be calculated in various ways with various - * levels of accuracy and complexity, this function allows - * users to create a LUT in their own way. - * - * Setting the LUT here means that #has_soft_dec_lut will return - * true. Decision vectors returned by #soft_decision_maker will - * be calculated using this LUT. - * - * \param soft_dec_lut The soft decision LUT as a vector of - * tuples (vectors in C++) of soft decisions. Each - * element of the LUT is a vector of k-bit floats (where - * there are k bits/sample in the constellation). - * \param precision The number of bits of precision used when - * generating the LUT. - */ - void set_soft_dec_lut(const std::vector< std::vector<float> > &soft_dec_lut, - int precision); - - //! Returns True if the soft decision LUT has been defined, False otherwise. - bool has_soft_dec_lut(); - - - std::vector< std::vector<float> > soft_dec_lut(); - - - - /*! \brief Returns the soft decisions for the given \p sample. - * - * \details Returns the soft decisions for the given \p - * sample. If a LUT is defined for the object, the decisions - * will be calculated from there. Otherwise, this function will - * call calc_soft_dec directly to calculate the soft decisions. - * - * \param sample The complex sample to get the soft decisions. - */ - std::vector<float> soft_decision_maker(gr_complex sample); - - - protected: - std::vector<gr_complex> d_constellation; - std::vector<int> d_pre_diff_code; - bool d_apply_pre_diff_code; - unsigned int d_rotational_symmetry; - unsigned int d_dimensionality; - unsigned int d_arity; - //! The factor by which the user given constellation points were - //! scaled by to achieve an average amplitude of 1. - float d_scalefactor; - float d_re_min, d_re_max, d_im_min, d_im_max; - - std::vector< std::vector<float> > d_soft_dec_lut; - int d_lut_precision; - float d_lut_scale; - - float get_distance(unsigned int index, const gr_complex *sample); - unsigned int get_closest_point(const gr_complex *sample); - void calc_arity(); - - void max_min_axes(); - }; - - /************************************************************/ - /* constellation_calcdist */ - /* */ - /************************************************************/ - - /*! \brief Calculate Euclidian distance for any constellation - * \ingroup digital - * - * \details - * 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 +/*! + * \brief An abstracted constellation object + * \ingroup symbol_coding_blk + * + * \details + * 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<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + bool normalize_points = true); + constellation(); + virtual ~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, + gr::digital::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<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() { - public: - typedef boost::shared_ptr<constellation_calcdist> sptr; - - /*! - * Make a general constellation object that calculates the Euclidean distance for hard decisions. - * - * \param constell List of constellation points (order of list matches pre_diff_code) - * \param pre_diff_code List of alphabet symbols (before applying any differential - * coding) (order of list matches constell) - * \param rotational_symmetry Number of rotations around unit circle that have the same representation. - * \param dimensionality Number of dimensions to the constellation. - * \param normalize_points Normalize constellation points to mean(abs(points))=1 (default is true) - */ - static sptr make(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - bool normalize_points=true); - - 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); - - protected: - constellation_calcdist(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - bool nomalize_points=true); - }; - - - /************************************************************/ - /*! constellation_sector */ - /************************************************************/ + return floor(log(double(d_constellation.size())) / d_dimensionality / log(2.0)); + } - /*! - * \brief Sectorized digital constellation - * \ingroup digital + unsigned int arity() { return d_arity; } + + constellation_sptr base() { return shared_from_this(); } + + pmt::pmt_t as_pmt() { return pmt::make_any(boost::any(base())); } + + /*! \brief Generates the soft decision LUT based on + * constellation and symbol map. * - * \details - * Constellation space is divided into sectors. Each sector is - * associated with the nearest constellation point. + * \details Generates the soft decision LUT based on + * constellation and symbol map. It can be given a estimate of + * the noise power in the channel as \p npwr. + * + * \param precision Number of bits of precision on each axis. + * \param npwr Estimate of the noise power (if known). + * + * This is expensive to compute. */ - class DIGITAL_API constellation_sector : public constellation - { - public: - - /*! - * Make a sectorized constellation object. - * - * \param constell List of constellation points (order of list matches pre_diff_code) - * \param pre_diff_code List of alphabet symbols (before applying any differential - * coding) (order of list matches constell) - * \param rotational_symmetry Number of rotations around unit circle that have the same representation. - * \param dimensionality Number of z-axis dimensions to the constellation - * \param n_sectors Number of sectors in the constellation. - */ - constellation_sector(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - unsigned int n_sectors); - - ~constellation_sector(); - - 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<int> sector_values; - }; - - /************************************************************/ - /* constellation_rect */ - /************************************************************/ + void gen_soft_dec_lut(int precision, float npwr = 1.0); - /*! - * \brief Rectangular digital constellation - * \ingroup digital + /*! \brief Calculate soft decisions for the given \p sample. * - * Only implemented for 1-(complex)dimensional constellation. + * \details Calculate the soft decisions from the given \p sample + * at the given noise power \p npwr. * - * Constellation space is divided into rectangular sectors. Each - * sector is associated with the nearest constellation point. + * This is a very costly algorithm (especially for higher order + * modulations) and should be used sparingly. It uses the + * #gen_soft_dec_lut function to generate the LUT, which + * should be done once or if a large change in the noise floor + * is detected. * - * Works well for square QAM. + * Instead of using this function, generate the LUT using the + * #gen_soft_dec_lut after creating the constellation object + * and then use the #soft_decision_maker function to return the + * answer from the LUT. * - * Works for any generic constellation provided sectors are not - * too large. + * \param sample The complex sample to get the soft decisions. + * \param npwr Estimate of the noise power (if known). */ - class DIGITAL_API constellation_rect - : public constellation_sector - { - public: - typedef boost::shared_ptr<constellation_rect> sptr; - - /*! - * Make a rectangular constellation object. - * - * \param constell List of constellation points (order of list matches pre_diff_code) - * \param pre_diff_code List of alphabet symbols (before applying any differential - * coding) (order of list matches constell) - * \param rotational_symmetry Number of rotations around unit circle that have the same representation. - * \param real_sectors Number of sectors the real axis is split in to. - * \param imag_sectors Number of sectors the imag axis is split in to. - * \param width_real_sectors width of each real sector to calculate decision boundaries. - * \param width_imag_sectors width of each imag sector to calculate decision boundaries. - */ - static constellation_rect::sptr make(std::vector<gr_complex> constell, - std::vector<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_rect(); - - protected: - - constellation_rect(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, - unsigned int imag_sectors, - float width_real_sectors, - float width_imag_sectors); - - unsigned int get_sector(const gr_complex *sample); - gr_complex calc_sector_center(unsigned int sector); - 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_expl_rect */ - /************************************************************/ + virtual std::vector<float> calc_soft_dec(gr_complex sample, float npwr = 1.0); - /*! - * \brief Rectangular digital constellation. - * \ingroup digital + /*! \brief Define a soft decision look-up table. * - * \details - * Only implemented for 1-(complex)dimensional constellation. + * \details Define a soft decision look-up table (LUT). Because + * soft decisions can be calculated in various ways with various + * levels of accuracy and complexity, this function allows + * users to create a LUT in their own way. * - * Constellation space is divided into rectangular sectors. Each - * sector is associated with the nearest constellation point. + * Setting the LUT here means that #has_soft_dec_lut will return + * true. Decision vectors returned by #soft_decision_maker will + * be calculated using this LUT. * - * This class is different from constellation_rect in that the - * mapping from sector to constellation point is explicitly passed - * into the constructor as sector_values. Usually we do not need - * this, since we want each sector to be automatically mapped to - * the closest constellation point, however sometimes it's nice to - * have the flexibility. + * \param soft_dec_lut The soft decision LUT as a vector of + * tuples (vectors in C++) of soft decisions. Each + * element of the LUT is a vector of k-bit floats (where + * there are k bits/sample in the constellation). + * \param precision The number of bits of precision used when + * generating the LUT. */ - class DIGITAL_API constellation_expl_rect - : public constellation_rect - { - public: - typedef boost::shared_ptr<constellation_expl_rect> sptr; + void set_soft_dec_lut(const std::vector<std::vector<float>>& soft_dec_lut, + int precision); - static sptr make(std::vector<gr_complex> constellation, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, - unsigned int imag_sectors, - float width_real_sectors, - float width_imag_sectors, - std::vector<unsigned int> sector_values); - ~constellation_expl_rect(); - - protected: - constellation_expl_rect(std::vector<gr_complex> constellation, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, - unsigned int imag_sectors, - float width_real_sectors, - float width_imag_sectors, - std::vector<unsigned int> sector_values); - - unsigned int calc_sector_value (unsigned int sector) { - return d_sector_values[sector]; - } + //! Returns True if the soft decision LUT has been defined, False otherwise. + bool has_soft_dec_lut(); - private: - std::vector<unsigned int> d_sector_values; - }; - /************************************************************/ - /* constellation_psk */ - /************************************************************/ + std::vector<std::vector<float>> soft_dec_lut(); - /*! - * \brief constellation_psk - * \ingroup digital + + /*! \brief Returns the soft decisions for the given \p sample. * - * Constellation space is divided into pie slices sectors. + * \details Returns the soft decisions for the given \p + * sample. If a LUT is defined for the object, the decisions + * will be calculated from there. Otherwise, this function will + * call calc_soft_dec directly to calculate the soft decisions. * - * Each slice is associated with the nearest constellation point. + * \param sample The complex sample to get the soft decisions. + */ + std::vector<float> soft_decision_maker(gr_complex sample); + + +protected: + std::vector<gr_complex> d_constellation; + std::vector<int> d_pre_diff_code; + bool d_apply_pre_diff_code; + unsigned int d_rotational_symmetry; + unsigned int d_dimensionality; + unsigned int d_arity; + //! The factor by which the user given constellation points were + //! scaled by to achieve an average amplitude of 1. + float d_scalefactor; + float d_re_min, d_re_max, d_im_min, d_im_max; + + std::vector<std::vector<float>> d_soft_dec_lut; + int d_lut_precision; + float d_lut_scale; + + float get_distance(unsigned int index, const gr_complex* sample); + unsigned int get_closest_point(const gr_complex* sample); + void calc_arity(); + + void max_min_axes(); +}; + +/************************************************************/ +/* constellation_calcdist */ +/* */ +/************************************************************/ + +/*! \brief Calculate Euclidian distance for any constellation + * \ingroup digital + * + * \details + * 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; + + /*! + * Make a general constellation object that calculates the Euclidean distance for hard + * decisions. * - * Works well for PSK but nothing else. + * \param constell List of constellation points (order of list matches pre_diff_code) + * \param pre_diff_code List of alphabet symbols (before applying any differential + * coding) (order of list matches constell) + * \param rotational_symmetry Number of rotations around unit circle that have the + * same representation. \param dimensionality Number of dimensions to the + * constellation. \param normalize_points Normalize constellation points to + * mean(abs(points))=1 (default is true) + */ + static sptr make(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + bool normalize_points = true); + + 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); + +protected: + constellation_calcdist(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + bool nomalize_points = true); +}; + + +/************************************************************/ +/*! constellation_sector */ +/************************************************************/ + +/*! + * \brief Sectorized digital constellation + * \ingroup digital + * + * \details + * Constellation space is divided into sectors. Each sector is + * associated with the nearest constellation point. + */ +class DIGITAL_API constellation_sector : public constellation +{ +public: + /*! + * Make a sectorized constellation object. * - * Assumes that there is a constellation point at 1.x + * \param constell List of constellation points (order of list matches pre_diff_code) + * \param pre_diff_code List of alphabet symbols (before applying any differential + * coding) (order of list matches constell) + * \param rotational_symmetry Number of rotations around unit circle that have the + * same representation. \param dimensionality Number of z-axis dimensions to the + * constellation \param n_sectors Number of sectors in the constellation. */ - class DIGITAL_API constellation_psk : public constellation_sector - { - public: - typedef boost::shared_ptr<constellation_psk> sptr; + constellation_sector(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + unsigned int n_sectors); - // public constructor - static sptr make(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int n_sectors); + ~constellation_sector(); - ~constellation_psk(); + unsigned int decision_maker(const gr_complex* sample); - protected: - unsigned int get_sector(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 calc_sector_value(unsigned int sector); + unsigned int n_sectors; - constellation_psk(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int n_sectors); - }; +private: + std::vector<int> sector_values; +}; +/************************************************************/ +/* constellation_rect */ +/************************************************************/ - /************************************************************/ - /* constellation_bpsk */ - /* */ - /* Only works for BPSK. */ - /* */ - /************************************************************/ +/*! + * \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; /*! - * \brief Digital constellation for BPSK . - * \ingroup digital + * Make a rectangular constellation object. * - * \details - * \verbatim - 0 | 1 - \endverbatim + * \param constell List of constellation points (order of list matches pre_diff_code) + * \param pre_diff_code List of alphabet symbols (before applying any differential + * coding) (order of list matches constell) + * \param rotational_symmetry Number of rotations around unit circle that have the + * same representation. \param real_sectors Number of sectors the real axis is split + * in to. \param imag_sectors Number of sectors the imag axis is split in to. \param + * width_real_sectors width of each real sector to calculate decision boundaries. + * \param width_imag_sectors width of each imag sector to calculate decision + * boundaries. */ - class DIGITAL_API constellation_bpsk : public constellation + static constellation_rect::sptr make(std::vector<gr_complex> constell, + std::vector<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_rect(); + +protected: + constellation_rect(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); + + unsigned int get_sector(const gr_complex* sample); + gr_complex calc_sector_center(unsigned int sector); + 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_expl_rect */ +/************************************************************/ + +/*! + * \brief Rectangular digital constellation. + * \ingroup digital + * + * \details + * Only implemented for 1-(complex)dimensional constellation. + * + * Constellation space is divided into rectangular sectors. Each + * sector is associated with the nearest constellation point. + * + * This class is different from constellation_rect in that the + * mapping from sector to constellation point is explicitly passed + * into the constructor as sector_values. Usually we do not need + * this, since we want each sector to be automatically mapped to + * the closest constellation point, however sometimes it's nice to + * have the flexibility. + */ +class DIGITAL_API constellation_expl_rect : public constellation_rect +{ +public: + typedef boost::shared_ptr<constellation_expl_rect> sptr; + + static sptr make(std::vector<gr_complex> constellation, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors, + std::vector<unsigned int> sector_values); + ~constellation_expl_rect(); + +protected: + constellation_expl_rect(std::vector<gr_complex> constellation, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors, + std::vector<unsigned int> sector_values); + + unsigned int calc_sector_value(unsigned int sector) { - public: - typedef boost::shared_ptr<constellation_bpsk> sptr; + return d_sector_values[sector]; + } - // public constructor - static sptr make(); +private: + std::vector<unsigned int> d_sector_values; +}; - ~constellation_bpsk(); +/************************************************************/ +/* constellation_psk */ +/************************************************************/ - unsigned int decision_maker(const gr_complex *sample); +/*! + * \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; - protected: - constellation_bpsk(); - }; + // public constructor + static sptr make(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int n_sectors); + ~constellation_psk(); - /************************************************************/ - /* constellation_qpsk */ - /* */ - /* Only works for QPSK. */ - /* */ - /************************************************************/ +protected: + unsigned int get_sector(const gr_complex* sample); - /*! - * \brief Digital constellation for QPSK - * \ingroup digital - * - * \details Constellation diagram assumes little endian format e.g. top, left means 2 not 1. - * \verbatim - 01 | 11 - ------- - 00 | 10 - \endverbatim - */ - class DIGITAL_API constellation_qpsk : public constellation - { - public: - typedef boost::shared_ptr<constellation_qpsk> sptr; + unsigned int calc_sector_value(unsigned int sector); - // public constructor - static sptr make(); + constellation_psk(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int n_sectors); +}; - ~constellation_qpsk(); - unsigned int decision_maker(const gr_complex *sample); +/************************************************************/ +/* constellation_bpsk */ +/* */ +/* Only works for BPSK. */ +/* */ +/************************************************************/ - protected: - constellation_qpsk(); - }; +/*! + * \brief Digital constellation for BPSK . + * \ingroup digital + * + * \details + * \verbatim + 0 | 1 + \endverbatim + */ +class DIGITAL_API constellation_bpsk : public constellation +{ +public: + typedef boost::shared_ptr<constellation_bpsk> sptr; + // public constructor + static sptr make(); - /************************************************************/ - /* constellation_dqpsk */ - /* */ - /* Works with differential encoding; slower decisions. */ - /* */ - /************************************************************/ + ~constellation_bpsk(); - /*! - * \brief Digital constellation for DQPSK. - * \ingroup digital - * - * \details - * \verbatim - 01 | 00 - ------- - 11 | 10 - \endverbatim - */ - class DIGITAL_API constellation_dqpsk : public constellation - { - public: - typedef boost::shared_ptr<constellation_dqpsk> sptr; + unsigned int decision_maker(const gr_complex* sample); - // public constructor - static sptr make(); +protected: + constellation_bpsk(); +}; - ~constellation_dqpsk(); - unsigned int decision_maker(const gr_complex *sample); +/************************************************************/ +/* constellation_qpsk */ +/* */ +/* Only works for QPSK. */ +/* */ +/************************************************************/ - protected: - constellation_dqpsk(); - }; +/*! + * \brief Digital constellation for QPSK + * \ingroup digital + * + * \details Constellation diagram assumes little endian format e.g. top, left means 2 + not 1. + * \verbatim + 01 | 11 + ------- + 00 | 10 + \endverbatim + */ +class DIGITAL_API constellation_qpsk : public constellation +{ +public: + typedef boost::shared_ptr<constellation_qpsk> sptr; + // public constructor + static sptr make(); - /************************************************************/ - /* constellation_8psk */ - /* */ - /* Only works for 8PSK. */ - /* */ - /************************************************************/ + ~constellation_qpsk(); - /*! - * \brief Digital constellation for 8PSK. - * \ingroup digital - * - * \details - * \verbatim - 101 | 100 - 001 | 000 - ----------------- - 011 | 010 - 111 | 110 - \endverbatim - */ - class DIGITAL_API constellation_8psk : public constellation - { - public: - typedef boost::shared_ptr<constellation_8psk> sptr; + unsigned int decision_maker(const gr_complex* sample); - // public constructor - static sptr make(); +protected: + constellation_qpsk(); +}; - ~constellation_8psk(); - unsigned int decision_maker(const gr_complex *sample); +/************************************************************/ +/* constellation_dqpsk */ +/* */ +/* Works with differential encoding; slower decisions. */ +/* */ +/************************************************************/ - protected: - constellation_8psk(); - }; +/*! + * \brief Digital constellation for DQPSK. + * \ingroup digital + * + * \details + * \verbatim + 01 | 00 + ------- + 11 | 10 + \endverbatim + */ +class DIGITAL_API constellation_dqpsk : public constellation +{ +public: + typedef boost::shared_ptr<constellation_dqpsk> sptr; - /************************************************************/ - /* constellation_8psk_natural */ - /* */ - /* Only works for natural 8psk */ - /* */ - /************************************************************/ + // public constructor + static sptr make(); - /*! - * \brief Digital constellation for natually mapped 8PSK. - * \ingroup digital - * - * \details - * \verbatim - 011 | 010 - 100 | 001 - ----------------- - 101 | 000 - 110 | 111 - \endverbatim - */ - class DIGITAL_API constellation_8psk_natural : public constellation - { - public: - typedef boost::shared_ptr<constellation_8psk_natural> sptr; + ~constellation_dqpsk(); - // public constructor - static sptr make(); + unsigned int decision_maker(const gr_complex* sample); - ~constellation_8psk_natural(); +protected: + constellation_dqpsk(); +}; - unsigned int decision_maker(const gr_complex *sample); - protected: - constellation_8psk_natural(); - }; +/************************************************************/ +/* constellation_8psk */ +/* */ +/* Only works for 8PSK. */ +/* */ +/************************************************************/ - /************************************************************/ - /* constellation_16qam */ - /* */ - /* the 16qam mapping used in set partition of tcm */ - /* */ - /************************************************************/ +/*! + * \brief Digital constellation for 8PSK. + * \ingroup digital + * + * \details + * \verbatim + 101 | 100 + 001 | 000 + ----------------- + 011 | 010 + 111 | 110 + \endverbatim + */ +class DIGITAL_API constellation_8psk : public constellation +{ +public: + typedef boost::shared_ptr<constellation_8psk> sptr; - /*! - * \brief Digital constellation for 16qam. - * \ingroup digital - * - * \details - * \verbatim - 1000 1101 | 1100 1001 - | - 1111 1010 | 1011 1110 - ----------------- - 0100 0001 | 0000 0101 - | - 0011 0110 | 0111 0010 - \endverbatim - */ - class DIGITAL_API constellation_16qam : public constellation - { - public: - typedef boost::shared_ptr<constellation_16qam> sptr; + // public constructor + static sptr make(); + + ~constellation_8psk(); + + unsigned int decision_maker(const gr_complex* sample); + +protected: + constellation_8psk(); +}; + +/************************************************************/ +/* constellation_8psk_natural */ +/* */ +/* Only works for natural 8psk */ +/* */ +/************************************************************/ + +/*! + * \brief Digital constellation for natually mapped 8PSK. + * \ingroup digital + * + * \details + * \verbatim + 011 | 010 + 100 | 001 + ----------------- + 101 | 000 + 110 | 111 + \endverbatim + */ +class DIGITAL_API constellation_8psk_natural : public constellation +{ +public: + typedef boost::shared_ptr<constellation_8psk_natural> sptr; + + // public constructor + static sptr make(); + + ~constellation_8psk_natural(); + + unsigned int decision_maker(const gr_complex* sample); + +protected: + constellation_8psk_natural(); +}; + +/************************************************************/ +/* constellation_16qam */ +/* */ +/* the 16qam mapping used in set partition of tcm */ +/* */ +/************************************************************/ + +/*! + * \brief Digital constellation for 16qam. + * \ingroup digital + * + * \details + * \verbatim +1000 1101 | 1100 1001 + | +1111 1010 | 1011 1110 + ----------------- +0100 0001 | 0000 0101 + | +0011 0110 | 0111 0010 + \endverbatim + */ +class DIGITAL_API constellation_16qam : public constellation +{ +public: + typedef boost::shared_ptr<constellation_16qam> sptr; - // public constructor - static sptr make(); + // public constructor + static sptr make(); - ~constellation_16qam(); + ~constellation_16qam(); - unsigned int decision_maker(const gr_complex *sample); + unsigned int decision_maker(const gr_complex* sample); - protected: - constellation_16qam(); - }; +protected: + constellation_16qam(); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CONSTELLATION_H */ diff --git a/gr-digital/include/gnuradio/digital/constellation_decoder_cb.h b/gr-digital/include/gnuradio/digital/constellation_decoder_cb.h index 51feb95b7c..dde95100e9 100644 --- a/gr-digital/include/gnuradio/digital/constellation_decoder_cb.h +++ b/gr-digital/include/gnuradio/digital/constellation_decoder_cb.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -28,35 +28,34 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Constellation Decoder + * \ingroup symbol_coding_blk + * + * \details + * Decode a constellation's points from a complex space to + * (unpacked) bits based on the map of the \p consetllation + * object. + */ +class DIGITAL_API constellation_decoder_cb : virtual public block +{ +public: + // gr::digital::constellation_decoder_cb::sptr + typedef boost::shared_ptr<constellation_decoder_cb> sptr; /*! - * \brief Constellation Decoder - * \ingroup symbol_coding_blk + * \brief Make constellation decoder block. * - * \details - * Decode a constellation's points from a complex space to - * (unpacked) bits based on the map of the \p consetllation - * object. + * \param constellation A constellation derived from class + * 'constellation'. Use base() method to get a shared pointer to + * this base class type. */ - class DIGITAL_API constellation_decoder_cb - : virtual public block - { - public: - // gr::digital::constellation_decoder_cb::sptr - typedef boost::shared_ptr<constellation_decoder_cb> sptr; - - /*! - * \brief Make constellation decoder block. - * - * \param constellation A constellation derived from class - * 'constellation'. Use base() method to get a shared pointer to - * this base class type. - */ - static sptr make(constellation_sptr constellation); - }; + static sptr make(constellation_sptr constellation); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CONSTELLATION_DECODER_CB_H */ diff --git a/gr-digital/include/gnuradio/digital/constellation_receiver_cb.h b/gr-digital/include/gnuradio/digital/constellation_receiver_cb.h index af00c36619..f992257096 100644 --- a/gr-digital/include/gnuradio/digital/constellation_receiver_cb.h +++ b/gr-digital/include/gnuradio/digital/constellation_receiver_cb.h @@ -21,7 +21,7 @@ */ #ifndef INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H -#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H +#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H #include <gnuradio/digital/api.h> #include <gnuradio/digital/constellation.h> @@ -29,57 +29,56 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief This block makes hard decisions about the received + * symbols (using a constellation object) and also fine tunes + * phase synchronization. + * + * \details + * + * 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. + * + * Message Ports: + * + * set_constellation (input): + * Receives a PMT any containing a new gr::digital::constellation object. + * The PMT is cast back to a gr::digital::constellation_sptr + * and passes this to set_constellation. + * + * rotate_phase (input): + * Receives a PMT double to update the phase. + * The phase value passed in the message is added to the + * current phase of the receiver. + */ +class DIGITAL_API constellation_receiver_cb : virtual public block, + virtual public blocks::control_loop +{ +public: + // gr::digital::constellation_receiver_cb::sptr + typedef boost::shared_ptr<constellation_receiver_cb> sptr; /*! - * \brief This block makes hard decisions about the received - * symbols (using a constellation object) and also fine tunes - * phase synchronization. - * - * \details - * - * 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. + * \brief Constructs a constellation receiver that (phase/fine + * freq) synchronizes and decodes constellation points specified + * by a constellation object. * - * Message Ports: - * - * set_constellation (input): - * Receives a PMT any containing a new gr::digital::constellation object. - * The PMT is cast back to a gr::digital::constellation_sptr - * and passes this to set_constellation. - * - * rotate_phase (input): - * Receives a PMT double to update the phase. - * The phase value passed in the message is added to the - * current phase of the receiver. + * \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 */ - class DIGITAL_API constellation_receiver_cb - : virtual public block, - virtual public blocks::control_loop - { - public: - // gr::digital::constellation_receiver_cb::sptr - typedef boost::shared_ptr<constellation_receiver_cb> sptr; - - /*! - * \brief Constructs a constellation receiver that (phase/fine - * freq) synchronizes and decodes constellation points specified - * by a constellation object. - * - * \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 - */ - static sptr make(constellation_sptr constellation, - float loop_bw, float fmin, float fmax); + static sptr + make(constellation_sptr constellation, float loop_bw, float fmin, float fmax); - virtual void phase_error_tracking(float phase_error) = 0; - }; + virtual void phase_error_tracking(float phase_error) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H */ diff --git a/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h b/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h index 653a94b478..0f821e311f 100644 --- a/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h +++ b/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2013 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, @@ -28,35 +28,34 @@ #include <gnuradio/sync_interpolator.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Constellation Decoder + * \ingroup symbol_coding_blk + * + * \details + * Decode a constellation's points from a complex space to soft + * bits based on the map and soft decision LUT of the \p + * consetllation object. + */ +class DIGITAL_API constellation_soft_decoder_cf : virtual public sync_interpolator +{ +public: + // gr::digital::constellation_soft_decoder_cf::sptr + typedef boost::shared_ptr<constellation_soft_decoder_cf> sptr; /*! - * \brief Constellation Decoder - * \ingroup symbol_coding_blk + * \brief Make constellation decoder block. * - * \details - * Decode a constellation's points from a complex space to soft - * bits based on the map and soft decision LUT of the \p - * consetllation object. + * \param constellation A constellation derived from class + * 'constellation'. Use base() method to get a shared pointer to + * this base class type. */ - class DIGITAL_API constellation_soft_decoder_cf - : virtual public sync_interpolator - { - public: - // gr::digital::constellation_soft_decoder_cf::sptr - typedef boost::shared_ptr<constellation_soft_decoder_cf> sptr; - - /*! - * \brief Make constellation decoder block. - * - * \param constellation A constellation derived from class - * 'constellation'. Use base() method to get a shared pointer to - * this base class type. - */ - static sptr make(constellation_sptr constellation); - }; + static sptr make(constellation_sptr constellation); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_H */ diff --git a/gr-digital/include/gnuradio/digital/corr_est_cc.h b/gr-digital/include/gnuradio/digital/corr_est_cc.h index 2c77b65c66..b3788586b8 100644 --- a/gr-digital/include/gnuradio/digital/corr_est_cc.h +++ b/gr-digital/include/gnuradio/digital/corr_est_cc.h @@ -27,100 +27,102 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Correlate stream with a pre-defined sequence and estimate peak + * \ingroup synchronizers_blk + * + * \details + * Input: + * \li Stream of complex samples. + * + * Output: + * \li Output stream that just passes the input complex samples + * \li tag 'phase_est': estimate of phase offset + * \li tag 'time_est': estimate of symbol timing offset + * \li tag 'corr_est': the correlation value of the estimates + * \li tag 'amp_est': 1 over the estimated amplitude + * \li tag 'corr_start': the start sample of the correlation and the value + * + * \li Optional 2nd output stream providing the advanced correlator output + * + * This block is designed to search for a sync word by correlation + * and uses the results of the correlation to get a time and phase + * offset estimate. These estimates are passed downstream as + * stream tags for use by follow-on synchronization blocks. + * + * The sync word is provided as a set of symbols after being + * filtered by a baseband matched filter. + * + * The phase_est tag can be used by downstream blocks to adjust + * their phase estimator/correction loops, and is currently + * implemented by the gr::digital::costas_loop_cc block. + * + * The time_est tag can be used to adjust the sampling timing + * estimate of any downstream synchronization blocks and is + * currently implemented by the gr::digital::pfb_clock_sync_ccf + * block. + * + * The caller must provide a "time_est" and "phase_est" tag + * marking delay from the start of the correlated signal segment, + * in order to mark the proper point in the sync word for + * downstream synchronization blocks. Generally this block cannot + * know where the actual sync word symbols are located relative to + * "corr_start", given that some modulations have pulses with + * intentional ISI. The user should manually examine the primary + * output and the "corr_start" tag position to determine the + * required tag delay settings for the particular modulation, + * sync word, and downstream blocks used. + * + * For a discussion of the properties of complex correlations, + * with respect to signal processing, see: + * Marple, Jr., S. L., "Estimating Group Delay and Phase Delay + * via Discrete-Time 'Analytic' Cross-Correlation, _IEEE_Transcations_ + * _on_Signal_Processing_, Volume 47, No. 9, September 1999 + * + */ +typedef enum { + THRESHOLD_DYNAMIC, + THRESHOLD_ABSOLUTE, +} tm_type; + +class DIGITAL_API corr_est_cc : virtual public sync_block +{ +public: + typedef boost::shared_ptr<corr_est_cc> sptr; /*! - * \brief Correlate stream with a pre-defined sequence and estimate peak - * \ingroup synchronizers_blk - * - * \details - * Input: - * \li Stream of complex samples. - * - * Output: - * \li Output stream that just passes the input complex samples - * \li tag 'phase_est': estimate of phase offset - * \li tag 'time_est': estimate of symbol timing offset - * \li tag 'corr_est': the correlation value of the estimates - * \li tag 'amp_est': 1 over the estimated amplitude - * \li tag 'corr_start': the start sample of the correlation and the value - * - * \li Optional 2nd output stream providing the advanced correlator output - * - * This block is designed to search for a sync word by correlation - * and uses the results of the correlation to get a time and phase - * offset estimate. These estimates are passed downstream as - * stream tags for use by follow-on synchronization blocks. - * - * The sync word is provided as a set of symbols after being - * filtered by a baseband matched filter. + * Make a block that correlates against the \p symbols vector + * and outputs a phase and symbol timing estimate. * - * The phase_est tag can be used by downstream blocks to adjust - * their phase estimator/correction loops, and is currently - * implemented by the gr::digital::costas_loop_cc block. - * - * The time_est tag can be used to adjust the sampling timing - * estimate of any downstream synchronization blocks and is - * currently implemented by the gr::digital::pfb_clock_sync_ccf - * block. - * - * The caller must provide a "time_est" and "phase_est" tag - * marking delay from the start of the correlated signal segment, - * in order to mark the proper point in the sync word for - * downstream synchronization blocks. Generally this block cannot - * know where the actual sync word symbols are located relative to - * "corr_start", given that some modulations have pulses with - * intentional ISI. The user should manually examine the primary - * output and the "corr_start" tag position to determine the - * required tag delay settings for the particular modulation, - * sync word, and downstream blocks used. - * - * For a discussion of the properties of complex correlations, - * with respect to signal processing, see: - * Marple, Jr., S. L., "Estimating Group Delay and Phase Delay - * via Discrete-Time 'Analytic' Cross-Correlation, _IEEE_Transcations_ - * _on_Signal_Processing_, Volume 47, No. 9, September 1999 + * \param symbols Set of symbols to correlate against (e.g., a + * sync word). + * \param sps Samples per symbol + * \param mark_delay tag marking delay in samples after the + * corr_start tag + * \param threshold Threshold of correlator, relative to a 100% + * correlation (1.0). Default is 0.9. + * \param threshold_method Method for computing threshold. * */ - typedef enum { - THRESHOLD_DYNAMIC, - THRESHOLD_ABSOLUTE, - } tm_type; - - class DIGITAL_API corr_est_cc : virtual public sync_block - { - public: - typedef boost::shared_ptr<corr_est_cc> sptr; - - /*! - * Make a block that correlates against the \p symbols vector - * and outputs a phase and symbol timing estimate. - * - * \param symbols Set of symbols to correlate against (e.g., a - * sync word). - * \param sps Samples per symbol - * \param mark_delay tag marking delay in samples after the - * corr_start tag - * \param threshold Threshold of correlator, relative to a 100% - * correlation (1.0). Default is 0.9. - * \param threshold_method Method for computing threshold. - * - */ - static sptr make(const std::vector<gr_complex> &symbols, - float sps, unsigned int mark_delay, float threshold=0.9, - tm_type threshold_method=THRESHOLD_ABSOLUTE); + static sptr make(const std::vector<gr_complex>& symbols, + float sps, + unsigned int mark_delay, + float threshold = 0.9, + tm_type threshold_method = THRESHOLD_ABSOLUTE); - virtual std::vector<gr_complex> symbols() const = 0; - virtual void set_symbols(const std::vector<gr_complex> &symbols) = 0; + virtual std::vector<gr_complex> symbols() const = 0; + virtual void set_symbols(const std::vector<gr_complex>& symbols) = 0; - virtual unsigned int mark_delay() const = 0; - virtual void set_mark_delay(unsigned int mark_delay) = 0; + virtual unsigned int mark_delay() const = 0; + virtual void set_mark_delay(unsigned int mark_delay) = 0; - virtual float threshold() const = 0; - virtual void set_threshold(float threshold) = 0; - }; + virtual float threshold() const = 0; + virtual void set_threshold(float threshold) = 0; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_CORR_EST_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_bb.h b/gr-digital/include/gnuradio/digital/correlate_access_code_bb.h index 2f7b700ac9..3cddc892a2 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_bb.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_bb.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2005,2006,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, @@ -28,48 +28,48 @@ #include <string> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup packet_operators_blk + * \ingroup deprecated_blk + * + * \details + * input: stream of bits, 1 bit per input byte (data in LSB) + * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) + * + * Each output byte contains two valid bits, the data bit, and the + * flag bit. The LSB (bit 0) is the data bit, and is the original + * input data, delayed 64 bits. Bit 1 is the flag bit and is 1 if + * the corresponding data bit is the first data bit following the + * access code. Otherwise the flag bit is 0. + */ +class DIGITAL_API correlate_access_code_bb : virtual public sync_block +{ +public: + // gr::digital::correlate_access_code_bb::sptr + typedef boost::shared_ptr<correlate_access_code_bb> sptr; /*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup packet_operators_blk - * \ingroup deprecated_blk + * Make a correlate_access_code block. * - * \details - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) - * - * Each output byte contains two valid bits, the data bit, and the - * flag bit. The LSB (bit 0) is the data bit, and is the original - * input data, delayed 64 bits. Bit 1 is the flag bit and is 1 if - * the corresponding data bit is the first data bit following the - * access code. Otherwise the flag bit is 0. + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong */ - class DIGITAL_API correlate_access_code_bb : virtual public sync_block - { - public: - // gr::digital::correlate_access_code_bb::sptr - typedef boost::shared_ptr<correlate_access_code_bb> sptr; - - /*! - * Make a correlate_access_code block. - * - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - */ - static sptr make(const std::string &access_code, int threshold); + static sptr make(const std::string& access_code, int threshold); - /*! - * Set a new access code. - * - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - */ - virtual bool set_access_code(const std::string &access_code) = 0; - }; + /*! + * Set a new access code. + * + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + */ + virtual bool set_access_code(const std::string& access_code) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_bb_ts.h b/gr-digital/include/gnuradio/digital/correlate_access_code_bb_ts.h index a933aec116..d561f9878b 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_bb_ts.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_bb_ts.h @@ -28,52 +28,51 @@ #include <string> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup packet_operators_blk + * + * \details + * input: stream of bits (unpacked bytes) + * output: a tagged stream set of bits from the payload following + * the access code and header. + * + * This block searches for the given access code by reading in the + * input bits. Once found, it expects the following 32 samples to + * contain a header that includes the frame length (16 bits for + * the length, repeated). It decodes the header to get the frame + * length in order to set up the the tagged stream key + * information. + * + * The output of this block is appropriate for use with tagged + * stream blocks. + */ +class DIGITAL_API correlate_access_code_bb_ts : virtual public block +{ +public: + // gr::digital::correlate_access_code_bb_ts::sptr + typedef boost::shared_ptr<correlate_access_code_bb_ts> sptr; /*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup packet_operators_blk - * - * \details - * input: stream of bits (unpacked bytes) - * output: a tagged stream set of bits from the payload following - * the access code and header. - * - * This block searches for the given access code by reading in the - * input bits. Once found, it expects the following 32 samples to - * contain a header that includes the frame length (16 bits for - * the length, repeated). It decodes the header to get the frame - * length in order to set up the the tagged stream key - * information. - * - * The output of this block is appropriate for use with tagged - * stream blocks. + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong + * \param tag_name key of the tag inserted into the tag stream */ - class DIGITAL_API correlate_access_code_bb_ts : virtual public block - { - public: - // gr::digital::correlate_access_code_bb_ts::sptr - typedef boost::shared_ptr<correlate_access_code_bb_ts> sptr; - - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ - static sptr make(const std::string &access_code, - int threshold, - const std::string &tag_name); + static sptr + make(const std::string& access_code, int threshold, const std::string& tag_name); - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - */ - virtual bool set_access_code(const std::string &access_code) = 0; - virtual unsigned long long access_code() const = 0; - }; + /*! + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + */ + virtual bool set_access_code(const std::string& access_code) = 0; + virtual unsigned long long access_code() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_TS_H */ diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h b/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h index dfad78ccc4..070b8d3246 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h @@ -28,52 +28,51 @@ #include <string> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup packet_operators_blk + * + * \details + * input: stream of floats (generally, soft decisions) + * output: a tagged stream set of samples from the payload following + * the access code and header. + * + * This block searches for the given access code by slicing the + * soft decision symbol inputs. Once found, it expects the + * following 32 samples to contain a header that includes the + * frame length (16 bits for the length, repeated). It decodes the + * header to get the frame length in order to set up the the + * tagged stream key information. + * + * The output of this block is appropriate for use with tagged + * stream blocks. + */ +class DIGITAL_API correlate_access_code_ff_ts : virtual public block +{ +public: + // gr::digital::correlate_access_code_ff_ts::sptr + typedef boost::shared_ptr<correlate_access_code_ff_ts> sptr; /*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup packet_operators_blk - * - * \details - * input: stream of floats (generally, soft decisions) - * output: a tagged stream set of samples from the payload following - * the access code and header. - * - * This block searches for the given access code by slicing the - * soft decision symbol inputs. Once found, it expects the - * following 32 samples to contain a header that includes the - * frame length (16 bits for the length, repeated). It decodes the - * header to get the frame length in order to set up the the - * tagged stream key information. - * - * The output of this block is appropriate for use with tagged - * stream blocks. + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong + * \param tag_name key of the tag inserted into the tag stream */ - class DIGITAL_API correlate_access_code_ff_ts : virtual public block - { - public: - // gr::digital::correlate_access_code_ff_ts::sptr - typedef boost::shared_ptr<correlate_access_code_ff_ts> sptr; - - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ - static sptr make(const std::string &access_code, - int threshold, - const std::string &tag_name); + static sptr + make(const std::string& access_code, int threshold, const std::string& tag_name); - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - */ - virtual bool set_access_code(const std::string &access_code) = 0; - virtual unsigned long long access_code() const = 0; - }; + /*! + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + */ + virtual bool set_access_code(const std::string& access_code) = 0; + virtual unsigned long long access_code() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_FF_TS_H */ diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_tag_bb.h b/gr-digital/include/gnuradio/digital/correlate_access_code_tag_bb.h index d064c45709..7d87003a1a 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_tag_bb.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_tag_bb.h @@ -28,46 +28,45 @@ #include <string> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup packet_operators_blk + * + * \details + * input: stream of bits, 1 bit per input byte (data in LSB) + * output: unaltered stream of bits (plus tags) + * + * This block annotates the input stream with tags. The tags have + * key name [tag_name], specified in the constructor. Used for + * searching an input data stream for preambles, etc. + */ +class DIGITAL_API correlate_access_code_tag_bb : virtual public sync_block +{ +public: + // gr::digital::correlate_access_code_tag_bb::sptr + typedef boost::shared_ptr<correlate_access_code_tag_bb> sptr; /*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup packet_operators_blk - * - * \details - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: unaltered stream of bits (plus tags) - * - * This block annotates the input stream with tags. The tags have - * key name [tag_name], specified in the constructor. Used for - * searching an input data stream for preambles, etc. + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong + * \param tag_name key of the tag inserted into the tag stream */ - class DIGITAL_API correlate_access_code_tag_bb : virtual public sync_block - { - public: - // gr::digital::correlate_access_code_tag_bb::sptr - typedef boost::shared_ptr<correlate_access_code_tag_bb> sptr; + static sptr + make(const std::string& access_code, int threshold, const std::string& tag_name); - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ - static sptr make(const std::string &access_code, - int threshold, - const std::string &tag_name); - - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - */ - virtual bool set_access_code(const std::string &access_code) = 0; - virtual void set_threshold(int threshold) = 0; - virtual void set_tagname(const std::string &tagname) = 0; - }; + /*! + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + */ + virtual bool set_access_code(const std::string& access_code) = 0; + virtual void set_threshold(int threshold) = 0; + virtual void set_tagname(const std::string& tagname) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_TAG_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_tag_ff.h b/gr-digital/include/gnuradio/digital/correlate_access_code_tag_ff.h index 9eaad08c69..726d0a964a 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_tag_ff.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_tag_ff.h @@ -28,47 +28,46 @@ #include <string> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup packet_operators_blk + * + * \details + * input: stream of floats (generally, soft decisions) + * output: unaltered stream of bits (plus tags) + * + * This block annotates the input stream with tags. The tags have + * key name [tag_name], specified in the constructor. Used for + * searching an input data stream for preambles, etc., by slicing + * the soft decision symbol inputs. + */ +class DIGITAL_API correlate_access_code_tag_ff : virtual public sync_block +{ +public: + // gr::digital::correlate_access_code_tag_ff::sptr + typedef boost::shared_ptr<correlate_access_code_tag_ff> sptr; /*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup packet_operators_blk - * - * \details - * input: stream of floats (generally, soft decisions) - * output: unaltered stream of bits (plus tags) - * - * This block annotates the input stream with tags. The tags have - * key name [tag_name], specified in the constructor. Used for - * searching an input data stream for preambles, etc., by slicing - * the soft decision symbol inputs. + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong + * \param tag_name key of the tag inserted into the tag stream */ - class DIGITAL_API correlate_access_code_tag_ff : virtual public sync_block - { - public: - // gr::digital::correlate_access_code_tag_ff::sptr - typedef boost::shared_ptr<correlate_access_code_tag_ff> sptr; + static sptr + make(const std::string& access_code, int threshold, const std::string& tag_name); - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ - static sptr make(const std::string &access_code, - int threshold, - const std::string &tag_name); - - /*! - * \param access_code is represented with 1 byte per bit, - * e.g., "010101010111000100" - */ - virtual bool set_access_code(const std::string &access_code) = 0; - virtual void set_threshold(int threshold) = 0; - virtual void set_tagname(const std::string &tagname) = 0; - }; + /*! + * \param access_code is represented with 1 byte per bit, + * e.g., "010101010111000100" + */ + virtual bool set_access_code(const std::string& access_code) = 0; + virtual void set_threshold(int threshold) = 0; + virtual void set_tagname(const std::string& tagname) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_TAG_FF_H */ diff --git a/gr-digital/include/gnuradio/digital/costas_loop_cc.h b/gr-digital/include/gnuradio/digital/costas_loop_cc.h index ff5b9b993a..ebca2962d8 100644 --- a/gr-digital/include/gnuradio/digital/costas_loop_cc.h +++ b/gr-digital/include/gnuradio/digital/costas_loop_cc.h @@ -28,65 +28,64 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief A Costas loop carrier recovery module. + * \ingroup synchronizers_blk + * + * \details + * The Costas loop locks to the center frequency of a signal and + * downconverts it to baseband. + * + * \li When order=2: used for BPSK where the real part of the + * output signal is the baseband BPSK signal and the imaginary + * part is the error signal. + * + * \li When order=4: can be used for QPSK where both I and Q (real + * and imaginary) are outputted. + * + * \li When order=8: used for 8PSK. + * + * More details can be found online: + * + * J. Feigin, "Practical Costas loop design: Designing a simple + * and inexpensive BPSK Costas loop carrier recovery circuit," RF + * signal processing, pp. 20-36, 2002. + * + * http://rfdesign.com/images/archive/0102Feigin20.pdf + * + * The Costas loop can have two output streams: + * \li stream 1 (required) is the baseband I and Q; + * \li stream 2 (optional) is the normalized frequency of the loop + * + * There is a single optional message input: + * \li noise: A noise floor estimate used to calculate the SNR of a sample. + */ +class DIGITAL_API costas_loop_cc : virtual public sync_block, + virtual public blocks::control_loop +{ +public: + // gr::digital::costas_loop_cc::sptr + typedef boost::shared_ptr<costas_loop_cc> sptr; /*! - * \brief A Costas loop carrier recovery module. - * \ingroup synchronizers_blk + * Make a Costas loop carrier recovery block. * - * \details - * The Costas loop locks to the center frequency of a signal and - * downconverts it to baseband. - * - * \li When order=2: used for BPSK where the real part of the - * output signal is the baseband BPSK signal and the imaginary - * part is the error signal. - * - * \li When order=4: can be used for QPSK where both I and Q (real - * and imaginary) are outputted. - * - * \li When order=8: used for 8PSK. - * - * More details can be found online: - * - * J. Feigin, "Practical Costas loop design: Designing a simple - * and inexpensive BPSK Costas loop carrier recovery circuit," RF - * signal processing, pp. 20-36, 2002. - * - * http://rfdesign.com/images/archive/0102Feigin20.pdf - * - * The Costas loop can have two output streams: - * \li stream 1 (required) is the baseband I and Q; - * \li stream 2 (optional) is the normalized frequency of the loop - * - * There is a single optional message input: - * \li noise: A noise floor estimate used to calculate the SNR of a sample. + * \param loop_bw internal 2nd order loop bandwidth (~ 2pi/100) + * \param order the loop order, either 2, 4, or 8 + * \param use_snr Use or ignore SNR estimates (from noise message port) + * in measurements; also uses tanh instead of slicing. */ - class DIGITAL_API costas_loop_cc - : virtual public sync_block, - virtual public blocks::control_loop - { - public: - // gr::digital::costas_loop_cc::sptr - typedef boost::shared_ptr<costas_loop_cc> sptr; - - /*! - * Make a Costas loop carrier recovery block. - * - * \param loop_bw internal 2nd order loop bandwidth (~ 2pi/100) - * \param order the loop order, either 2, 4, or 8 - * \param use_snr Use or ignore SNR estimates (from noise message port) - * in measurements; also uses tanh instead of slicing. - */ - static sptr make(float loop_bw, int order, bool use_snr=false); + static sptr make(float loop_bw, int order, bool use_snr = false); - /*! - * Returns the current value of the loop error. - */ - virtual float error() const = 0; - }; + /*! + * Returns the current value of the loop error. + */ + virtual float error() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_COSTAS_LOOP_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/cpmmod_bc.h b/gr-digital/include/gnuradio/digital/cpmmod_bc.h index 885c653de4..fead20246a 100644 --- a/gr-digital/include/gnuradio/digital/cpmmod_bc.h +++ b/gr-digital/include/gnuradio/digital/cpmmod_bc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -28,90 +28,90 @@ #include <gnuradio/analog/cpm.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Generic CPM modulator + * \ingroup modulators_blk + * + * \details + * Examples: + * - Setting h = 0.5, L = 1, type = LREC yields MSK. + * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK + * as used in GSM. + * + * The input of this block are symbols from an M-ary alphabet + * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the + * valid inputs are +/-1. + * The modulator will silently accept any other inputs, though. + * The output is the phase-modulated signal. + */ +class DIGITAL_API cpmmod_bc : virtual public hier_block2 +{ +public: + // gr::digital::cpmmod_bc::sptr + typedef boost::shared_ptr<cpmmod_bc> sptr; /*! - * \brief Generic CPM modulator - * \ingroup modulators_blk - * - * \details - * Examples: - * - Setting h = 0.5, L = 1, type = LREC yields MSK. - * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK - * as used in GSM. + * Make CPM modulator block. * - * The input of this block are symbols from an M-ary alphabet - * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the - * valid inputs are +/-1. - * The modulator will silently accept any other inputs, though. - * The output is the phase-modulated signal. + * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM + * or GAUSSIAN. See gr_cpm::phase_response() for a + * detailed description. + * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum + * phase change that can occur between two symbols, i.e., if + * you only send ones, the phase will increase by \f$ h \cdot + * \pi\f$ every \p samples_per_sym samples. Set this to 0.5 + * for Minimum Shift Keying variants. + * \param samples_per_sym Samples per symbol. + * \param L The length of the phase duration in symbols. For L=1, this + * yields full- response CPM symbols, for L > 1, + * partial-response. + * \param beta For LSRC, this is the rolloff factor. For Gaussian + * pulses, this is the 3 dB time-bandwidth product. */ - class DIGITAL_API cpmmod_bc : virtual public hier_block2 - { - public: - // gr::digital::cpmmod_bc::sptr - typedef boost::shared_ptr<cpmmod_bc> sptr; + static sptr make(analog::cpm::cpm_type type, + float h, + int samples_per_sym, + int L, + double beta = 0.3); - /*! - * Make CPM modulator block. - * - * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM - * or GAUSSIAN. See gr_cpm::phase_response() for a - * detailed description. - * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum - * phase change that can occur between two symbols, i.e., if - * you only send ones, the phase will increase by \f$ h \cdot - * \pi\f$ every \p samples_per_sym samples. Set this to 0.5 - * for Minimum Shift Keying variants. - * \param samples_per_sym Samples per symbol. - * \param L The length of the phase duration in symbols. For L=1, this - * yields full- response CPM symbols, for L > 1, - * partial-response. - * \param beta For LSRC, this is the rolloff factor. For Gaussian - * pulses, this is the 3 dB time-bandwidth product. - */ - static sptr make(analog::cpm::cpm_type type, float h, - int samples_per_sym, - int L, double beta=0.3); - - /*! - * Make GMSK modulator block. - * - * The type is GAUSSIAN and the modulation index for GMSK is - * 0.5. This are populated automatically by this factory - * function. - * - * \param samples_per_sym Samples per symbol. - * \param L The length of the phase duration in symbols. For L=1, this - * yields full- response CPM symbols, for L > 1, - * partial-response. - * \param beta For LSRC, this is the rolloff factor. For Gaussian - * pulses, this is the 3 dB time-bandwidth product. - */ - static sptr make_gmskmod_bc(int samples_per_sym=2, - int L=4, double beta=0.3); + /*! + * Make GMSK modulator block. + * + * The type is GAUSSIAN and the modulation index for GMSK is + * 0.5. This are populated automatically by this factory + * function. + * + * \param samples_per_sym Samples per symbol. + * \param L The length of the phase duration in symbols. For L=1, this + * yields full- response CPM symbols, for L > 1, + * partial-response. + * \param beta For LSRC, this is the rolloff factor. For Gaussian + * pulses, this is the 3 dB time-bandwidth product. + */ + static sptr make_gmskmod_bc(int samples_per_sym = 2, int L = 4, double beta = 0.3); - //! Return the phase response FIR taps - virtual std::vector<float> taps() const = 0; + //! Return the phase response FIR taps + virtual std::vector<float> taps() const = 0; - //! Return the type of CPM modulator - virtual int type() const = 0; + //! Return the type of CPM modulator + virtual int type() const = 0; - //! Return the modulation index of the modulator. - virtual float index() const = 0; + //! Return the modulation index of the modulator. + virtual float index() const = 0; - //! Return the number of samples per symbol - virtual int samples_per_sym() const = 0; + //! Return the number of samples per symbol + virtual int samples_per_sym() const = 0; - //! Return the length of the phase duration (in symbols) - virtual int length() const = 0; + //! Return the length of the phase duration (in symbols) + virtual int length() const = 0; - //! Return the value of beta for the modulator - virtual double beta() const = 0; - }; + //! Return the value of beta for the modulator + virtual double beta() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_CPMMOD_BC_H */ - diff --git a/gr-digital/include/gnuradio/digital/crc32.h b/gr-digital/include/gnuradio/digital/crc32.h index 1f7581fd69..03d9774d2d 100644 --- a/gr-digital/include/gnuradio/digital/crc32.h +++ b/gr-digital/include/gnuradio/digital/crc32.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2005,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, @@ -28,31 +28,28 @@ #include <gnuradio/types.h> namespace gr { - namespace digital { - - /*! - * \brief update running CRC-32 - * \ingroup packet_operators_blk - * - * \details - * Update a running CRC with the bytes buf[0..len-1] The CRC - * should be initialized to all 1's, and the transmitted value is - * the 1's complement of the final running CRC. The resulting CRC - * should be transmitted in big endian order. - */ - DIGITAL_API unsigned int - update_crc32(unsigned int crc, const unsigned char *buf, size_t len); - - DIGITAL_API unsigned int - update_crc32(unsigned int crc, const std::string buf); - - DIGITAL_API unsigned int - crc32(const unsigned char *buf, size_t len); - - DIGITAL_API unsigned int - crc32(const std::string buf); - - } /* namespace digital */ +namespace digital { + +/*! + * \brief update running CRC-32 + * \ingroup packet_operators_blk + * + * \details + * Update a running CRC with the bytes buf[0..len-1] The CRC + * should be initialized to all 1's, and the transmitted value is + * the 1's complement of the final running CRC. The resulting CRC + * should be transmitted in big endian order. + */ +DIGITAL_API unsigned int +update_crc32(unsigned int crc, const unsigned char* buf, size_t len); + +DIGITAL_API unsigned int update_crc32(unsigned int crc, const std::string buf); + +DIGITAL_API unsigned int crc32(const unsigned char* buf, size_t len); + +DIGITAL_API unsigned int crc32(const std::string buf); + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_CRC32_H */ diff --git a/gr-digital/include/gnuradio/digital/crc32_async_bb.h b/gr-digital/include/gnuradio/digital/crc32_async_bb.h index 335ac20438..0679c27e2b 100644 --- a/gr-digital/include/gnuradio/digital/crc32_async_bb.h +++ b/gr-digital/include/gnuradio/digital/crc32_async_bb.h @@ -28,43 +28,43 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Byte-stream CRC block for async messages + * \ingroup packet_operators_blk + * + * \details + * + * Processes packets (as async PDU messages) for CRC32. The \p + * check parameter determines if the block acts to check and strip + * the CRC or to calculate and append the CRC32. + * + * The input PDU is expected to be a message of packet bytes. + * + * When using check mode, if the CRC passes, the output is a + * payload of the message with the CRC stripped, so the output + * will be 4 bytes smaller than the input. + * + * When using calculate mode (check == false), then the CRC is + * calculated on the PDU and appended to it. The output is then 4 + * bytes longer than the input. + * + * This block implements the CRC32 using the Boost crc_optimal + * class for 32-bit CRCs with the standard generator 0x04C11DB7. + */ +class DIGITAL_API crc32_async_bb : virtual public block +{ +public: + typedef boost::shared_ptr<crc32_async_bb> sptr; /*! - * \brief Byte-stream CRC block for async messages - * \ingroup packet_operators_blk - * - * \details - * - * Processes packets (as async PDU messages) for CRC32. The \p - * check parameter determines if the block acts to check and strip - * the CRC or to calculate and append the CRC32. - * - * The input PDU is expected to be a message of packet bytes. - * - * When using check mode, if the CRC passes, the output is a - * payload of the message with the CRC stripped, so the output - * will be 4 bytes smaller than the input. - * - * When using calculate mode (check == false), then the CRC is - * calculated on the PDU and appended to it. The output is then 4 - * bytes longer than the input. - * - * This block implements the CRC32 using the Boost crc_optimal - * class for 32-bit CRCs with the standard generator 0x04C11DB7. + * \param check Set to true if you want to check CRC, false to create CRC. */ - class DIGITAL_API crc32_async_bb : virtual public block - { - public: - typedef boost::shared_ptr<crc32_async_bb> sptr; - - /*! - * \param check Set to true if you want to check CRC, false to create CRC. - */ - static sptr make(bool check=false); - }; + static sptr make(bool check = false); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_CRC32_ASYNC_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/crc32_bb.h b/gr-digital/include/gnuradio/digital/crc32_bb.h index a00195434b..7817915e21 100644 --- a/gr-digital/include/gnuradio/digital/crc32_bb.h +++ b/gr-digital/include/gnuradio/digital/crc32_bb.h @@ -28,34 +28,36 @@ #include <gnuradio/tagged_stream_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Byte-stream CRC block + * \ingroup packet_operators_blk + * + * \details + * Input: stream of bytes, which form a packet. The first byte of the packet + * has a tag with key "length" and the value being the number of bytes in the + * packet. + * + * Output: The same bytes as incoming, but trailing a CRC32 of the packet. + * The tag is re-set to the new length. + */ +class DIGITAL_API crc32_bb : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<crc32_bb> sptr; /*! - * \brief Byte-stream CRC block - * \ingroup packet_operators_blk - * - * \details - * Input: stream of bytes, which form a packet. The first byte of the packet - * has a tag with key "length" and the value being the number of bytes in the - * packet. - * - * Output: The same bytes as incoming, but trailing a CRC32 of the packet. - * The tag is re-set to the new length. + * \param check Set to true if you want to check CRC, false to create CRC. + * \param lengthtagname Length tag key for the tagged stream. + * \param packed If the data is packed or unpacked bits (default=true). */ - class DIGITAL_API crc32_bb : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<crc32_bb> sptr; - - /*! - * \param check Set to true if you want to check CRC, false to create CRC. - * \param lengthtagname Length tag key for the tagged stream. - * \param packed If the data is packed or unpacked bits (default=true). - */ - static sptr make(bool check=false, const std::string& lengthtagname="packet_len", bool packed=true); - }; - - } // namespace digital + static sptr make(bool check = false, + const std::string& lengthtagname = "packet_len", + bool packed = true); +}; + +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_CRC32_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/descrambler_bb.h b/gr-digital/include/gnuradio/digital/descrambler_bb.h index 10efde275e..e15d1a4dbf 100644 --- a/gr-digital/include/gnuradio/digital/descrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/descrambler_bb.h @@ -27,34 +27,34 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Descramber an input stream using an LFSR. + * \ingroup coding_blk + * + * \details + * Descramble an input stream using an LFSR. This block works on + * the LSB only of the input data stream, i.e., on an "unpacked + * binary" stream, and produces the same format on its output. + */ +class DIGITAL_API descrambler_bb : virtual public sync_block +{ +public: + // gr::digital::descrambler_bb::sptr + typedef boost::shared_ptr<descrambler_bb> sptr; /*! - * \brief Descramber an input stream using an LFSR. - * \ingroup coding_blk + * \brief Make a descrambler block. * - * \details - * Descramble an input stream using an LFSR. This block works on - * the LSB only of the input data stream, i.e., on an "unpacked - * binary" stream, and produces the same format on its output. + * \param mask Polynomial mask for LFSR + * \param seed Initial shift register contents + * \param len Shift register length */ - class DIGITAL_API descrambler_bb : virtual public sync_block - { - public: - // gr::digital::descrambler_bb::sptr - typedef boost::shared_ptr<descrambler_bb> sptr; - - /*! - * \brief Make a descrambler block. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - */ - static sptr make(int mask, int seed, int len); - }; + static sptr make(int mask, int seed, int len); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_DESCRAMBLER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/diff_decoder_bb.h b/gr-digital/include/gnuradio/digital/diff_decoder_bb.h index 941531142f..0987976c14 100644 --- a/gr-digital/include/gnuradio/digital/diff_decoder_bb.h +++ b/gr-digital/include/gnuradio/digital/diff_decoder_bb.h @@ -27,31 +27,31 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Differential encoder: y[0] = (x[0] - x[-1]) % M + * \ingroup symbol_coding_blk + * + * \details + * Uses current and previous symbols and the alphabet modulus to + * perform differential decoding. + */ +class DIGITAL_API diff_decoder_bb : virtual public sync_block +{ +public: + // gr::digital::diff_decoder_bb::sptr + typedef boost::shared_ptr<diff_decoder_bb> sptr; /*! - * \brief Differential encoder: y[0] = (x[0] - x[-1]) % M - * \ingroup symbol_coding_blk + * Make a differential decoder block. * - * \details - * Uses current and previous symbols and the alphabet modulus to - * perform differential decoding. + * \param modulus Modulus of code's alphabet */ - class DIGITAL_API diff_decoder_bb : virtual public sync_block - { - public: - // gr::digital::diff_decoder_bb::sptr - typedef boost::shared_ptr<diff_decoder_bb> sptr; - - /*! - * Make a differential decoder block. - * - * \param modulus Modulus of code's alphabet - */ - static sptr make(unsigned int modulus); - }; + static sptr make(unsigned int modulus); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_DIFF_DECODER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/diff_encoder_bb.h b/gr-digital/include/gnuradio/digital/diff_encoder_bb.h index 63ac2d07b9..39bd3a123a 100644 --- a/gr-digital/include/gnuradio/digital/diff_encoder_bb.h +++ b/gr-digital/include/gnuradio/digital/diff_encoder_bb.h @@ -27,31 +27,31 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Differential decoder: y[0] = (x[0] + y[-1]) % M + * \ingroup symbol_coding_blk + * + * \details + * Uses current and previous symbols and the alphabet modulus to + * perform differential encoding. + */ +class DIGITAL_API diff_encoder_bb : virtual public sync_block +{ +public: + // gr::digital::diff_encoder_bb::sptr + typedef boost::shared_ptr<diff_encoder_bb> sptr; /*! - * \brief Differential decoder: y[0] = (x[0] + y[-1]) % M - * \ingroup symbol_coding_blk + * Make a differential encoder block. * - * \details - * Uses current and previous symbols and the alphabet modulus to - * perform differential encoding. + * \param modulus Modulus of code's alphabet */ - class DIGITAL_API diff_encoder_bb : virtual public sync_block - { - public: - // gr::digital::diff_encoder_bb::sptr - typedef boost::shared_ptr<diff_encoder_bb> sptr; - - /*! - * Make a differential encoder block. - * - * \param modulus Modulus of code's alphabet - */ - static sptr make(unsigned int modulus); - }; + static sptr make(unsigned int modulus); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_DIFF_ENCODER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/diff_phasor_cc.h b/gr-digital/include/gnuradio/digital/diff_phasor_cc.h index efcc3b367a..a3260c5a7b 100644 --- a/gr-digital/include/gnuradio/digital/diff_phasor_cc.h +++ b/gr-digital/include/gnuradio/digital/diff_phasor_cc.h @@ -27,31 +27,31 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Differential decoding based on phase change. + * \ingroup symbol_coding_blk + * + * \details + * Uses the phase difference between two symbols to determine the + * output symbol: + * + * out[i] = in[i] * conj(in[i-1]); + */ +class DIGITAL_API diff_phasor_cc : virtual public sync_block +{ +public: + // gr::digital::diff_phasor_cc::sptr + typedef boost::shared_ptr<diff_phasor_cc> sptr; /*! - * \brief Differential decoding based on phase change. - * \ingroup symbol_coding_blk - * - * \details - * Uses the phase difference between two symbols to determine the - * output symbol: - * - * out[i] = in[i] * conj(in[i-1]); + * Make a differential phasor decoding block. */ - class DIGITAL_API diff_phasor_cc : virtual public sync_block - { - public: - // gr::digital::diff_phasor_cc::sptr - typedef boost::shared_ptr<diff_phasor_cc> sptr; - - /*! - * Make a differential phasor decoding block. - */ - static sptr make(); - }; + static sptr make(); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_DIFF_PHASOR_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/fll_band_edge_cc.h b/gr-digital/include/gnuradio/digital/fll_band_edge_cc.h index 3f38848442..48acd4de4d 100644 --- a/gr-digital/include/gnuradio/digital/fll_band_edge_cc.h +++ b/gr-digital/include/gnuradio/digital/fll_band_edge_cc.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2009,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, @@ -21,159 +21,158 @@ */ #ifndef INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H -#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H +#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H #include <gnuradio/digital/api.h> #include <gnuradio/sync_block.h> #include <gnuradio/blocks/control_loop.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Frequency Lock Loop using band-edge filters + * \ingroup synchronizers_blk + * + * \details + * The frequency lock loop derives a band-edge filter that covers + * the upper and lower bandwidths of a digitally-modulated + * signal. The bandwidth range is determined by the excess + * bandwidth (e.g., rolloff factor) of the modulated signal. The + * placement in frequency of the band-edges is determined by the + * oversampling ratio (number of samples per symbol) and the + * excess bandwidth. The size of the filters should be fairly + * large so as to average over a number of symbols. + * + * The FLL works by filtering the upper and lower band edges into + * x_u(t) and x_l(t), respectively. These are combined to form + * cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining + * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} + * (where ^* is the complex conjugate) provides an error signal at + * the DC term that is directly proportional to the carrier + * frequency. We then make a second-order loop using the error + * signal that is the running average of e(t). + * + * In practice, the above equation can be simplified by just + * comparing the absolute value squared of the output of both + * filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - + * norm(x_u(t)). + * + * In theory, the band-edge filter is the derivative of the + * matched filter in frequency, (H_be(f) = frac{H(f)}{df}). In + * practice, this comes down to a quarter sine wave at the point + * of the matched filter's rolloff (if it's a raised-cosine, the + * derivative of a cosine is a sine). Extend this sine by another + * quarter wave to make a half wave around the band-edges is + * equivalent in time to the sum of two sinc functions. The + * baseband filter for the band edges is therefore derived from + * this sum of sincs. The band edge filters are then just the + * baseband signal modulated to the correct place in + * frequency. All of these calculations are done in the + * 'design_filter' function. + * + * Note: We use FIR filters here because the filters have to have + * a flat phase response over the entire frequency range to allow + * their comparisons to be valid. + * + * It is very important that the band edge filters be the + * derivatives of the pulse shaping filter, and that they be + * linear phase. Otherwise, the variance of the error will be very + * large. + */ +class DIGITAL_API fll_band_edge_cc : virtual public sync_block, + virtual public blocks::control_loop +{ +public: + // gr::digital::fll_band_edge_cc::sptr + typedef boost::shared_ptr<fll_band_edge_cc> sptr; /*! - * \brief Frequency Lock Loop using band-edge filters - * \ingroup synchronizers_blk + * Make an FLL block. * - * \details - * The frequency lock loop derives a band-edge filter that covers - * the upper and lower bandwidths of a digitally-modulated - * signal. The bandwidth range is determined by the excess - * bandwidth (e.g., rolloff factor) of the modulated signal. The - * placement in frequency of the band-edges is determined by the - * oversampling ratio (number of samples per symbol) and the - * excess bandwidth. The size of the filters should be fairly - * large so as to average over a number of symbols. + * \param samps_per_sym (float) number of samples per symbol + * \param rolloff (float) Rolloff (excess bandwidth) of signal filter + * \param filter_size (int) number of filter taps to generate + * \param bandwidth (float) Loop bandwidth + */ + static sptr + make(float samps_per_sym, float rolloff, int filter_size, float bandwidth); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Set the number of samples per symbol * - * The FLL works by filtering the upper and lower band edges into - * x_u(t) and x_l(t), respectively. These are combined to form - * cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining - * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} - * (where ^* is the complex conjugate) provides an error signal at - * the DC term that is directly proportional to the carrier - * frequency. We then make a second-order loop using the error - * signal that is the running average of e(t). + * Set's the number of samples per symbol the system should + * use. This value is used to calculate the filter taps and will + * force a recalculation. * - * In practice, the above equation can be simplified by just - * comparing the absolute value squared of the output of both - * filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - - * norm(x_u(t)). + * \param sps (float) new samples per symbol + */ + virtual void set_samples_per_symbol(float sps) = 0; + + /*! + * \brief Set the rolloff factor of the shaping filter + * + * This sets the rolloff factor that is used in the pulse + * shaping filter and is used to calculate the filter + * taps. Changing this will force a recalculation of the filter + * taps. + * + * This should be the same value that is used in the + * transmitter's pulse shaping filter. It must be between 0 and + * 1 and is usually between 0.2 and 0.5 (where 0.22 and 0.35 are + * commonly used values). + * + * \param rolloff (float) new shaping filter rolloff factor [0,1] + */ + virtual void set_rolloff(float rolloff) = 0; + + /*! + * \brief Set the number of taps in the filter * - * In theory, the band-edge filter is the derivative of the - * matched filter in frequency, (H_be(f) = frac{H(f)}{df}). In - * practice, this comes down to a quarter sine wave at the point - * of the matched filter's rolloff (if it's a raised-cosine, the - * derivative of a cosine is a sine). Extend this sine by another - * quarter wave to make a half wave around the band-edges is - * equivalent in time to the sum of two sinc functions. The - * baseband filter for the band edges is therefore derived from - * this sum of sincs. The band edge filters are then just the - * baseband signal modulated to the correct place in - * frequency. All of these calculations are done in the - * 'design_filter' function. + * This sets the number of taps in the band-edge + * filters. Setting this will force a recalculation of the + * filter taps. * - * Note: We use FIR filters here because the filters have to have - * a flat phase response over the entire frequency range to allow - * their comparisons to be valid. + * This should be about the same number of taps used in the + * transmitter's shaping filter and also not very large. A large + * number of taps will result in a large delay between input and + * frequency estimation, and so will not be as accurate. Between + * 30 and 70 taps is usual. * - * It is very important that the band edge filters be the - * derivatives of the pulse shaping filter, and that they be - * linear phase. Otherwise, the variance of the error will be very - * large. + * \param filter_size (float) number of taps in the filters */ - class DIGITAL_API fll_band_edge_cc - : virtual public sync_block, - virtual public blocks::control_loop - { - public: - // gr::digital::fll_band_edge_cc::sptr - typedef boost::shared_ptr<fll_band_edge_cc> sptr; - - /*! - * Make an FLL block. - * - * \param samps_per_sym (float) number of samples per symbol - * \param rolloff (float) Rolloff (excess bandwidth) of signal filter - * \param filter_size (int) number of filter taps to generate - * \param bandwidth (float) Loop bandwidth - */ - static sptr make(float samps_per_sym, float rolloff, - int filter_size, float bandwidth); - - /******************************************************************* - SET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Set the number of samples per symbol - * - * Set's the number of samples per symbol the system should - * use. This value is used to calculate the filter taps and will - * force a recalculation. - * - * \param sps (float) new samples per symbol - */ - virtual void set_samples_per_symbol(float sps) = 0; - - /*! - * \brief Set the rolloff factor of the shaping filter - * - * This sets the rolloff factor that is used in the pulse - * shaping filter and is used to calculate the filter - * taps. Changing this will force a recalculation of the filter - * taps. - * - * This should be the same value that is used in the - * transmitter's pulse shaping filter. It must be between 0 and - * 1 and is usually between 0.2 and 0.5 (where 0.22 and 0.35 are - * commonly used values). - * - * \param rolloff (float) new shaping filter rolloff factor [0,1] - */ - virtual void set_rolloff(float rolloff) = 0; - - /*! - * \brief Set the number of taps in the filter - * - * This sets the number of taps in the band-edge - * filters. Setting this will force a recalculation of the - * filter taps. - * - * This should be about the same number of taps used in the - * transmitter's shaping filter and also not very large. A large - * number of taps will result in a large delay between input and - * frequency estimation, and so will not be as accurate. Between - * 30 and 70 taps is usual. - * - * \param filter_size (float) number of taps in the filters - */ - virtual void set_filter_size(int filter_size) = 0; - - /******************************************************************* - GET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Returns the number of sampler per symbol used for the filter - */ - virtual float samples_per_symbol() const = 0; - - /*! - * \brief Returns the rolloff factor used for the filter - */ - virtual float rolloff() const = 0; - - /*! - * \brief Returns the number of taps of the filter - */ - virtual int filter_size() const = 0; - - /*! - * Print the taps to screen. - */ - virtual void print_taps() = 0; - }; - - } /* namespace digital */ + virtual void set_filter_size(int filter_size) = 0; + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the number of sampler per symbol used for the filter + */ + virtual float samples_per_symbol() const = 0; + + /*! + * \brief Returns the rolloff factor used for the filter + */ + virtual float rolloff() const = 0; + + /*! + * \brief Returns the number of taps of the filter + */ + virtual int filter_size() const = 0; + + /*! + * Print the taps to screen. + */ + virtual void print_taps() = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/framer_sink_1.h b/gr-digital/include/gnuradio/digital/framer_sink_1.h index 7d13e4d6c0..4c46f50c1f 100644 --- a/gr-digital/include/gnuradio/digital/framer_sink_1.h +++ b/gr-digital/include/gnuradio/digital/framer_sink_1.h @@ -28,41 +28,41 @@ #include <gnuradio/msg_queue.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Given a stream of bits and access_code flags, assemble packets. + * \ingroup packet_operators_blk + * + * \details + * input: stream of bytes from digital_correlate_access_code_bb + * output: none. Pushes assembled packet into target queue + * + * The framer expects a fixed length header of 2 16-bit shorts + * containing the payload length, followed by the payload. If the + * 2 16-bit shorts are not identical, this packet is + * ignored. Better algs are welcome. + * + * The input data consists of bytes that have two bits used. Bit + * 0, the LSB, contains the data bit. Bit 1 if set, indicates that + * the corresponding bit is the the first bit of the packet. That + * is, this bit is the first one after the access code. + */ +class DIGITAL_API framer_sink_1 : virtual public sync_block +{ +public: + // gr::digital::framer_sink_1::sptr + typedef boost::shared_ptr<framer_sink_1> sptr; /*! - * \brief Given a stream of bits and access_code flags, assemble packets. - * \ingroup packet_operators_blk - * - * \details - * input: stream of bytes from digital_correlate_access_code_bb - * output: none. Pushes assembled packet into target queue + * Make a framer_sink_1 block. * - * The framer expects a fixed length header of 2 16-bit shorts - * containing the payload length, followed by the payload. If the - * 2 16-bit shorts are not identical, this packet is - * ignored. Better algs are welcome. - * - * The input data consists of bytes that have two bits used. Bit - * 0, the LSB, contains the data bit. Bit 1 if set, indicates that - * the corresponding bit is the the first bit of the packet. That - * is, this bit is the first one after the access code. + * \param target_queue The message queue where frames go. */ - class DIGITAL_API framer_sink_1 : virtual public sync_block - { - public: - // gr::digital::framer_sink_1::sptr - typedef boost::shared_ptr<framer_sink_1> sptr; - - /*! - * Make a framer_sink_1 block. - * - * \param target_queue The message queue where frames go. - */ - static sptr make(msg_queue::sptr target_queue); - }; + static sptr make(msg_queue::sptr target_queue); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_FRAMER_SINK_1_H */ diff --git a/gr-digital/include/gnuradio/digital/glfsr.h b/gr-digital/include/gnuradio/digital/glfsr.h index 449eeaa618..0b5141f1fd 100644 --- a/gr-digital/include/gnuradio/digital/glfsr.h +++ b/gr-digital/include/gnuradio/digital/glfsr.h @@ -27,33 +27,37 @@ #include <boost/cstdint.hpp> namespace gr { - namespace digital { - - /*! - * \brief Galois Linear Feedback Shift Register using specified polynomial mask - * \ingroup waveform_generators_blk - * - * \details - * Generates a maximal length pseudo-random sequence of length 2^degree-1 - */ - class DIGITAL_API glfsr - { - private: - uint32_t d_shift_register; - uint32_t d_mask; +namespace digital { - public: - glfsr(uint32_t mask, uint32_t seed) { d_shift_register = seed; d_mask = mask; } - ~glfsr(); +/*! + * \brief Galois Linear Feedback Shift Register using specified polynomial mask + * \ingroup waveform_generators_blk + * + * \details + * Generates a maximal length pseudo-random sequence of length 2^degree-1 + */ +class DIGITAL_API glfsr +{ +private: + uint32_t d_shift_register; + uint32_t d_mask; + +public: + glfsr(uint32_t mask, uint32_t seed) + { + d_shift_register = seed; + d_mask = mask; + } + ~glfsr(); - static uint32_t glfsr_mask(unsigned int degree); + static uint32_t glfsr_mask(unsigned int degree); - uint8_t next_bit(); + uint8_t next_bit(); - uint32_t mask() const { return d_mask; } - }; + uint32_t mask() const { return d_mask; } +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_GLFSR_H */ diff --git a/gr-digital/include/gnuradio/digital/glfsr_source_b.h b/gr-digital/include/gnuradio/digital/glfsr_source_b.h index 46ea38ebb5..d7cf875adb 100644 --- a/gr-digital/include/gnuradio/digital/glfsr_source_b.h +++ b/gr-digital/include/gnuradio/digital/glfsr_source_b.h @@ -27,37 +27,39 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Galois LFSR pseudo-random source + * \ingroup waveform_generators_blk + */ +class DIGITAL_API glfsr_source_b : virtual public sync_block +{ +public: + // gr::digital::glfsr_source_b::sptr + typedef boost::shared_ptr<glfsr_source_b> sptr; /*! - * \brief Galois LFSR pseudo-random source - * \ingroup waveform_generators_blk + * Make a Galois LFSR pseudo-random source block. + * + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param repeat Set to repeat sequence. + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. */ - class DIGITAL_API glfsr_source_b : virtual public sync_block - { - public: - // gr::digital::glfsr_source_b::sptr - typedef boost::shared_ptr<glfsr_source_b> sptr; - - /*! - * Make a Galois LFSR pseudo-random source block. - * - * \param degree Degree of shift register must be in [1, 32]. If mask - * is 0, the degree determines a default mask (see - * digital_impl_glfsr.cc for the mapping). - * \param repeat Set to repeat sequence. - * \param mask Allows a user-defined bit mask for indexes of the shift - * register to feed back. - * \param seed Initial setting for values in shift register. - */ - static sptr make(unsigned int degree, bool repeat=true, - uint32_t mask=0x0, uint32_t seed=0x1); - - virtual uint32_t period() const = 0; - virtual uint32_t mask() const = 0; - }; - - } /* namespace digital */ + static sptr make(unsigned int degree, + bool repeat = true, + uint32_t mask = 0x0, + uint32_t seed = 0x1); + + virtual uint32_t period() const = 0; + virtual uint32_t mask() const = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_GLFSR_SOURCE_B_H */ diff --git a/gr-digital/include/gnuradio/digital/glfsr_source_f.h b/gr-digital/include/gnuradio/digital/glfsr_source_f.h index b86f83cd93..f655b606e6 100644 --- a/gr-digital/include/gnuradio/digital/glfsr_source_f.h +++ b/gr-digital/include/gnuradio/digital/glfsr_source_f.h @@ -27,37 +27,37 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Galois LFSR pseudo-random source generating float outputs -1.0 - 1.0. + * \ingroup waveform_generators_blk + */ +class DIGITAL_API glfsr_source_f : virtual public sync_block +{ +public: + // gr::digital::glfsr_source_f::sptr + typedef boost::shared_ptr<glfsr_source_f> sptr; /*! - * \brief Galois LFSR pseudo-random source generating float outputs -1.0 - 1.0. - * \ingroup waveform_generators_blk + * Make a Galois LFSR pseudo-random source block. + * + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param repeat Set to repeat sequence. + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. */ - class DIGITAL_API glfsr_source_f : virtual public sync_block - { - public: - // gr::digital::glfsr_source_f::sptr - typedef boost::shared_ptr<glfsr_source_f> sptr; - - /*! - * Make a Galois LFSR pseudo-random source block. - * - * \param degree Degree of shift register must be in [1, 32]. If mask - * is 0, the degree determines a default mask (see - * digital_impl_glfsr.cc for the mapping). - * \param repeat Set to repeat sequence. - * \param mask Allows a user-defined bit mask for indexes of the shift - * register to feed back. - * \param seed Initial setting for values in shift register. - */ - static sptr make(unsigned int degree, bool repeat=true, - uint32_t mask=0, uint32_t seed=1); - - virtual uint32_t period() const = 0; - virtual uint32_t mask() const = 0; - }; - - } /* namespace digital */ + static sptr + make(unsigned int degree, bool repeat = true, uint32_t mask = 0, uint32_t seed = 1); + + virtual uint32_t period() const = 0; + virtual uint32_t mask() const = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_GLFSR_SOURCE_F_H */ diff --git a/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h b/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h index 5a80670ddd..3091a1fad9 100644 --- a/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h +++ b/gr-digital/include/gnuradio/digital/hdlc_deframer_bp.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2014 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, @@ -27,31 +27,30 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief HDLC deframer which takes in unpacked bits, and outputs PDU + * binary blobs. Frames which do not pass CRC are rejected. + * + * \ingroup pkt_operators_blk + * + */ +class DIGITAL_API hdlc_deframer_bp : virtual public gr::sync_block +{ +public: + typedef boost::shared_ptr<hdlc_deframer_bp> sptr; /*! - * \brief HDLC deframer which takes in unpacked bits, and outputs PDU - * binary blobs. Frames which do not pass CRC are rejected. - * - * \ingroup pkt_operators_blk + * \brief Return a shared_ptr to a new instance of digital::hdlc_deframer. * + * \param length_min: Minimum frame size (default: 32) + * \param length_max: Maximum frame size (default: 500) */ - class DIGITAL_API hdlc_deframer_bp : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr<hdlc_deframer_bp> sptr; + static sptr make(int length_min, int length_max); +}; - /*! - * \brief Return a shared_ptr to a new instance of digital::hdlc_deframer. - * - * \param length_min: Minimum frame size (default: 32) - * \param length_max: Maximum frame size (default: 500) - */ - static sptr make(int length_min, int length_max); - }; - - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HDLC_DEFRAMER_BP_H */ - diff --git a/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h b/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h index 9f77f61540..ef295370df 100644 --- a/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h +++ b/gr-digital/include/gnuradio/digital/hdlc_framer_pb.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2014 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, @@ -27,39 +27,38 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief HDLC framer which takes in PMT binary blobs and outputs HDLC + * frames as unpacked bits, with CRC and bit stuffing added. The first sample + * of the frame is tagged with the tag frame_tag_name and includes a + * length field for tagged_stream use. + * + * This block outputs one whole frame at a time; if there is not enough + * output buffer space to fit a frame, it is pushed onto a queue. As a result + * flowgraphs which only run for a finite number of samples may not receive + * all frames in the queue, due to the scheduler's granularity. For + * flowgraphs that stream continuously (anything using a USRP) this should + * not be an issue. + * + * \ingroup pkt_operators_blk + * + */ +class DIGITAL_API hdlc_framer_pb : virtual public gr::sync_block +{ +public: + typedef boost::shared_ptr<hdlc_framer_pb> sptr; /*! - * \brief HDLC framer which takes in PMT binary blobs and outputs HDLC - * frames as unpacked bits, with CRC and bit stuffing added. The first sample - * of the frame is tagged with the tag frame_tag_name and includes a - * length field for tagged_stream use. - * - * This block outputs one whole frame at a time; if there is not enough - * output buffer space to fit a frame, it is pushed onto a queue. As a result - * flowgraphs which only run for a finite number of samples may not receive - * all frames in the queue, due to the scheduler's granularity. For - * flowgraphs that stream continuously (anything using a USRP) this should - * not be an issue. - * - * \ingroup pkt_operators_blk + * \brief Return a shared_ptr to a new instance of digital::hdlc_framer. * + * \param frame_tag_name: The tag to add to the first sample of each frame. */ - class DIGITAL_API hdlc_framer_pb : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr<hdlc_framer_pb> sptr; - - /*! - * \brief Return a shared_ptr to a new instance of digital::hdlc_framer. - * - * \param frame_tag_name: The tag to add to the first sample of each frame. - */ - static sptr make(const std::string frame_tag_name); - }; + static sptr make(const std::string frame_tag_name); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HDLC_FRAMER_PB_H */ - diff --git a/gr-digital/include/gnuradio/digital/header_buffer.h b/gr-digital/include/gnuradio/digital/header_buffer.h index b2e24a4e14..fee3a7eefe 100644 --- a/gr-digital/include/gnuradio/digital/header_buffer.h +++ b/gr-digital/include/gnuradio/digital/header_buffer.h @@ -28,284 +28,283 @@ #include <stdlib.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Helper class for handling payload headers. - * \ingroup packet_operators_blk - * - * \details - * - * This class is used by the header format blocks (e.g., - * digital::header_format_default) to make it easier to deal with - * payload headers. This class functions in two different ways - * depending on if it is used in a transmitter or receiver. When - * used in a transmitter, this class helps us build headers out of - * the fields of the protocol. When used in a receiver, this class - * helps us parse the received bits into the protocol's fields. - * - * This page describes how to work with the different modes, - * transmit or receive. The class is instructed as to which mode - * it is in by how the constructor is called. If the constructor - * is passed a valid array (non NULL), then it is in transmit mode - * and will pack this buffer with the header fields. If that - * buffer is NULL, the object is in receive mode. - * - * \section header_buffer_tx Transmit Mode - * - * When passed a valid buffer in the constructor, this object is in - * transmit mode. We can then use the add_field[N] functions to - * add new fields to this header. The buffer MUST be large enough - * to hold the full header. As this class is meant to work mostly - * with the digital::header_format_default and child - * classes, the header length can be read from - * digital::header_format_default::header_nbytes(). - * - * Each field is a specific length of 8, 16, 32, or 64 bits that - * are to be transmitted in network byte order. We can adjust the - * direction of the bytes by setting the byte-swap flag, \p bs, to - * true or false. - * - * The length argument (\p len) for all add_field[N] calls is the - * number of bytes actually accounted for in the data - * structure. Often, we would use the full size of the field, - * which is sizeof(dtype), and the add_field[N] call defaults to - * len=N. Occasionally, we may need to use fewer bytes than - * actually represented by the data type. An example would be the - * access code used in the header_format_default, which is a - * uint64_t type but may have fewer bytes used in the actual - * access code. - * - * The function that calls this class is expected to handle the - * memory handling of the buffer -- both allocating and - * deallocating. - * - * As simple example of using this class in transmit mode: - * - * \verbatim - uint8_t* buffer = (uint8_t*)volk_malloc(header_nbytes(), - volk_get_alignment()); +/*! + * \brief Helper class for handling payload headers. + * \ingroup packet_operators_blk + * + * \details + * + * This class is used by the header format blocks (e.g., + * digital::header_format_default) to make it easier to deal with + * payload headers. This class functions in two different ways + * depending on if it is used in a transmitter or receiver. When + * used in a transmitter, this class helps us build headers out of + * the fields of the protocol. When used in a receiver, this class + * helps us parse the received bits into the protocol's fields. + * + * This page describes how to work with the different modes, + * transmit or receive. The class is instructed as to which mode + * it is in by how the constructor is called. If the constructor + * is passed a valid array (non NULL), then it is in transmit mode + * and will pack this buffer with the header fields. If that + * buffer is NULL, the object is in receive mode. + * + * \section header_buffer_tx Transmit Mode + * + * When passed a valid buffer in the constructor, this object is in + * transmit mode. We can then use the add_field[N] functions to + * add new fields to this header. The buffer MUST be large enough + * to hold the full header. As this class is meant to work mostly + * with the digital::header_format_default and child + * classes, the header length can be read from + * digital::header_format_default::header_nbytes(). + * + * Each field is a specific length of 8, 16, 32, or 64 bits that + * are to be transmitted in network byte order. We can adjust the + * direction of the bytes by setting the byte-swap flag, \p bs, to + * true or false. + * + * The length argument (\p len) for all add_field[N] calls is the + * number of bytes actually accounted for in the data + * structure. Often, we would use the full size of the field, + * which is sizeof(dtype), and the add_field[N] call defaults to + * len=N. Occasionally, we may need to use fewer bytes than + * actually represented by the data type. An example would be the + * access code used in the header_format_default, which is a + * uint64_t type but may have fewer bytes used in the actual + * access code. + * + * The function that calls this class is expected to handle the + * memory handling of the buffer -- both allocating and + * deallocating. + * + * As simple example of using this class in transmit mode: + * + * \verbatim + uint8_t* buffer = (uint8_t*)volk_malloc(header_nbytes(), + volk_get_alignment()); - header_buffer hdr(buffer); - hdr.add_field64(sync_word, sync_word_len); - hdr.add_field16(payload_length); - hdr.add_field8(header_flags); - hdr.add_field8(header_options); + header_buffer hdr(buffer); + hdr.add_field64(sync_word, sync_word_len); + hdr.add_field16(payload_length); + hdr.add_field8(header_flags); + hdr.add_field8(header_options); - // Do something with the header + // Do something with the header - volk_free(buffer); - \endverbatim - * - * In this example, the header contains four fields: - * - * \verbatim - |0 15|16 23|24 31| - | sync word | - | | - | length | flags | options | - \endverbatim - * - * The sync word can be up to 64-bits, but the add_field64 is also - * passed the number of actual bytes in the sync word and so could - * be fewer. - * - * \section header_buffer_rx Receive Mode - * - * In receive mode, we build up the header as bits are received by - * inserting them with insert_bit. We can find out how long the - * current header is, in bits, using the call to length(). If the - * header is of the appropriate length, we can then start - * extracting the fields from it. When we are done with the - * current header, call clear() to reset the internal buffer to - * empty, which will mean that length() returns 0. - * - * The header fields are extracted using the extract_field[N] - * functions. Like the add_field[N] functions, we specify the size - * (in bits) of the field we are extracting. We pass this function - * the bit-position of the expected field in the received header - * buffer. The extract_field[N] assumes that the number of bits - * for the field is N, but we can tell the function to use fewer - * bits if we want. Setting the length parameter of these - * functions greater than N is illegal, and it will throw an - * error. - * - * For example, given a header of | length | seq. num. | where the - * length is 16 bits and the sequence number is 32 bits, we would - * use: - * - * \verbatim - uint16_t len = d_hdr_reg.extract_field16(0); - uint32_t seq = d_hdr_reg.extract_field32(16); - \endverbatim - * - * The extract_field functions are specific to data types of the - * field and the number of bits for each field is inferred by the - * data type. So extract_field16 assumes we want all 16 bits in - * the field represented. - * - * Some headers have fields that are not standard sizes of - * integers, like a 1 bit, 4 bit, or even 12 bit fields. We can - * ask for fewer bits for each field. say: - * - * \verbatim - |0 15|16 19|20 31| - | len | flags | options | - \endverbatim - * - * We would use the following extraction functions: - * - * \verbatim - uint16_t len = d_hdr_reg.extract_field16(0); - uint8_t flags = d_hdr_reg.extract_field8(16, 4); - uint16_t opts = d_hdr_reg.extract_field16(20, 12); - \endverbatim - * - * \sa header_format_default - * \sa header_format_counter - * \sa header_format_crc - */ - class DIGITAL_API header_buffer - { - private: - size_t d_offset; - uint8_t *d_buffer; - - std::vector<bool> d_input; + volk_free(buffer); + \endverbatim + * + * In this example, the header contains four fields: + * + * \verbatim + |0 15|16 23|24 31| + | sync word | + | | + | length | flags | options | + \endverbatim + * + * The sync word can be up to 64-bits, but the add_field64 is also + * passed the number of actual bytes in the sync word and so could + * be fewer. + * + * \section header_buffer_rx Receive Mode + * + * In receive mode, we build up the header as bits are received by + * inserting them with insert_bit. We can find out how long the + * current header is, in bits, using the call to length(). If the + * header is of the appropriate length, we can then start + * extracting the fields from it. When we are done with the + * current header, call clear() to reset the internal buffer to + * empty, which will mean that length() returns 0. + * + * The header fields are extracted using the extract_field[N] + * functions. Like the add_field[N] functions, we specify the size + * (in bits) of the field we are extracting. We pass this function + * the bit-position of the expected field in the received header + * buffer. The extract_field[N] assumes that the number of bits + * for the field is N, but we can tell the function to use fewer + * bits if we want. Setting the length parameter of these + * functions greater than N is illegal, and it will throw an + * error. + * + * For example, given a header of | length | seq. num. | where the + * length is 16 bits and the sequence number is 32 bits, we would + * use: + * + * \verbatim + uint16_t len = d_hdr_reg.extract_field16(0); + uint32_t seq = d_hdr_reg.extract_field32(16); + \endverbatim + * + * The extract_field functions are specific to data types of the + * field and the number of bits for each field is inferred by the + * data type. So extract_field16 assumes we want all 16 bits in + * the field represented. + * + * Some headers have fields that are not standard sizes of + * integers, like a 1 bit, 4 bit, or even 12 bit fields. We can + * ask for fewer bits for each field. say: + * + * \verbatim + |0 15|16 19|20 31| + | len | flags | options | + \endverbatim + * + * We would use the following extraction functions: + * + * \verbatim + uint16_t len = d_hdr_reg.extract_field16(0); + uint8_t flags = d_hdr_reg.extract_field8(16, 4); + uint16_t opts = d_hdr_reg.extract_field16(20, 12); + \endverbatim + * + * \sa header_format_default + * \sa header_format_counter + * \sa header_format_crc + */ +class DIGITAL_API header_buffer +{ +private: + size_t d_offset; + uint8_t* d_buffer; - public: - /*! - * Create a header buffer object with a pre-allocated buffer, \p - * buffer, to hold the formatted header data. - * - * If \p buffer is set to NULL, then this object is in receive - * mode meant to receive bits from an incoming data stream and - * provide the ability to extract fields. In this mode, calls to - * add_field are invalid and will be nops. - */ - header_buffer(uint8_t *buffer=NULL); + std::vector<bool> d_input; - /*! - * Class destructor. - */ - ~header_buffer(); +public: + /*! + * Create a header buffer object with a pre-allocated buffer, \p + * buffer, to hold the formatted header data. + * + * If \p buffer is set to NULL, then this object is in receive + * mode meant to receive bits from an incoming data stream and + * provide the ability to extract fields. In this mode, calls to + * add_field are invalid and will be nops. + */ + header_buffer(uint8_t* buffer = NULL); - /*! - * Clears the header. - * - * In transmit mode, this resets the current offset so new - * add_field functions start adding data to the start of the - * buffer. - * - * In receive mode, this clears the buffer that we have inserted - * bits in to. - */ - void clear(); + /*! + * Class destructor. + */ + ~header_buffer(); + /*! + * Clears the header. + * + * In transmit mode, this resets the current offset so new + * add_field functions start adding data to the start of the + * buffer. + * + * In receive mode, this clears the buffer that we have inserted + * bits in to. + */ + void clear(); - /*! - * In transmit mode, this returns the length of the data in - * the buffer (not the allocated buffer length). - * - * In receiving mode, this returns the current length in bits of - * the received header. - */ - size_t length() const; - /*! - * Returns a constant pointer to the buffer. - */ - const uint8_t* header() const; + /*! + * In transmit mode, this returns the length of the data in + * the buffer (not the allocated buffer length). + * + * In receiving mode, this returns the current length in bits of + * the received header. + */ + size_t length() const; - /*! - * Add an 8-bit field to the header. - * - * \param data The 8-bit data item. - * \param len Length (in bits) of \p data. - * \param bs Set to 'true' to byte swap the data. - */ - void add_field8(uint8_t data, int len=8, bool bs=false); + /*! + * Returns a constant pointer to the buffer. + */ + const uint8_t* header() const; - /*! - * Add an 16-bit field to the header. - * - * \param data The 16-bit data item. - * \param len Length (in bits) of \p data. - * \param bs Set to 'true' to byte swap the data. - */ - void add_field16(uint16_t data, int len=16, bool bs=false); + /*! + * Add an 8-bit field to the header. + * + * \param data The 8-bit data item. + * \param len Length (in bits) of \p data. + * \param bs Set to 'true' to byte swap the data. + */ + void add_field8(uint8_t data, int len = 8, bool bs = false); - /*! - * Add an 32-bit field to the header. - * - * \param data The 32-bit data item. - * \param len Length (in bits) of \p data. - * \param bs Set to 'true' to byte swap the data. - */ - void add_field32(uint32_t data, int len=32, bool bs=false); + /*! + * Add an 16-bit field to the header. + * + * \param data The 16-bit data item. + * \param len Length (in bits) of \p data. + * \param bs Set to 'true' to byte swap the data. + */ + void add_field16(uint16_t data, int len = 16, bool bs = false); - /*! - * Add an 64-bit field to the header. - * - * \param data The 64-bit data item. - * \param len Length (in bits) of \p data. - * \param bs Set to 'true' to byte swap the data. - */ - void add_field64(uint64_t data, int len=64, bool bs=false); + /*! + * Add an 32-bit field to the header. + * + * \param data The 32-bit data item. + * \param len Length (in bits) of \p data. + * \param bs Set to 'true' to byte swap the data. + */ + void add_field32(uint32_t data, int len = 32, bool bs = false); + /*! + * Add an 64-bit field to the header. + * + * \param data The 64-bit data item. + * \param len Length (in bits) of \p data. + * \param bs Set to 'true' to byte swap the data. + */ + void add_field64(uint64_t data, int len = 64, bool bs = false); - /***************************************************** - * Receive mode to build a header from bits * - *****************************************************/ + /***************************************************** + * Receive mode to build a header from bits * + *****************************************************/ - /*! - * Insert a new bit on the back of the input buffer. This - * function is used in receive mode to add new bits as they are - * received for later use of the extract_field functions. - * - * \param bit New bit to add. - */ - void insert_bit(int bit); + /*! + * Insert a new bit on the back of the input buffer. This + * function is used in receive mode to add new bits as they are + * received for later use of the extract_field functions. + * + * \param bit New bit to add. + */ + void insert_bit(int bit); - /*! - * Returns up to an 8-bit field in the packet header. - * - * \param pos Bit position of the start of the field. - * \param len The number of bits in the field. - * \param bs Set to 'true' to byte swap the data. - */ - uint8_t extract_field8(int pos, int len=8, bool bs=false); + /*! + * Returns up to an 8-bit field in the packet header. + * + * \param pos Bit position of the start of the field. + * \param len The number of bits in the field. + * \param bs Set to 'true' to byte swap the data. + */ + uint8_t extract_field8(int pos, int len = 8, bool bs = false); - /*! - * Returns up to a 16-bit field in the packet header. - * - * \param pos Bit position of the start of the field. - * \param len The number of bits in the field. - * \param bs Set to 'true' to byte swap the data. - */ - uint16_t extract_field16(int pos, int len=16, bool bs=false); + /*! + * Returns up to a 16-bit field in the packet header. + * + * \param pos Bit position of the start of the field. + * \param len The number of bits in the field. + * \param bs Set to 'true' to byte swap the data. + */ + uint16_t extract_field16(int pos, int len = 16, bool bs = false); - /*! - * Returns up to a 32-bit field in the packet header. - * - * \param pos Bit position of the start of the field. - * \param len The number of bits in the field. - * \param bs Set to 'true' to byte swap the data. - */ - uint32_t extract_field32(int pos, int len=32, bool bs=false); + /*! + * Returns up to a 32-bit field in the packet header. + * + * \param pos Bit position of the start of the field. + * \param len The number of bits in the field. + * \param bs Set to 'true' to byte swap the data. + */ + uint32_t extract_field32(int pos, int len = 32, bool bs = false); - /*! - * Returns up to a 64-bit field in the packet header. - * - * \param pos Bit position of the start of the field. - * \param len The number of bits in the field. - * \param bs Set to 'true' to byte swap the data. - */ - uint64_t extract_field64(int pos, int len=64, bool bs=false); - }; + /*! + * Returns up to a 64-bit field in the packet header. + * + * \param pos Bit position of the start of the field. + * \param len The number of bits in the field. + * \param bs Set to 'true' to byte swap the data. + */ + uint64_t extract_field64(int pos, int len = 64, bool bs = false); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_BUFFER_H */ diff --git a/gr-digital/include/gnuradio/digital/header_format_base.h b/gr-digital/include/gnuradio/digital/header_format_base.h index 557a55cdcf..81278e80c1 100644 --- a/gr-digital/include/gnuradio/digital/header_format_base.h +++ b/gr-digital/include/gnuradio/digital/header_format_base.h @@ -29,197 +29,197 @@ #include <boost/enable_shared_from_this.hpp> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Base header formatter class. + * \ingroup packet_operators_blk + * + * \details + * + * Creates a base class that other packet formatters will inherit + * from. The child classes create and parse protocol-specific + * headers. To add a new protocol processing class, create a class + * that inherits from this and overload the necessary + * functions. The main functions to overload are: + * + * \li header_format_base::format: takes in a payload and + * creates a header from it. + * + * \li header_format_base::parse: receive bits and extract + * the header info. These are expected to be hard bits (0 or 1) + * that have either been sliced or gone through an FEC decoder. + * + * \li header_format_base::header_nbits: the number of bits + * in the full header (including an access code). + * + * \li header_format_base::header_ok: checks to see if the + * received header is ok. Since the header often specifies the + * length of the frame to decode next, it is important that this + * information be correct. + * + * \li header_format_base::header_payload: unpacks the header + * register (from the class header_buffer) as a set of bits into + * its component parts of the header. For example, this may find + * and extract the frame length field as a 16-bit value and/or + * flags related to the type of modulation and FEC codes used in + * the frame's payload. + * + * Protected functions of this class that the child class should + * overload include: + * + * \li enter_search + * \li enter_have_sync + * \li enter_have_header + * + * These three function represent the different states of the + * parsing state machine. Expected behavior is that the protocol + * has some known word that we are first looking for the identify + * the start of the frame. The parsing FSM starts in a state to + * search for the beginning of the header, normally by looking for + * a known word (i.e., the access code). Then it changes state to + * read in the full header. We expect that the protocol provides + * the length of the header for processing, so the parsing looks + * pulls in the full length of the header. Then it changes state + * to the "have header" state for checking and processing. The + * base class provides the basic functionality for this state + * machine. However, most likely, each child class must manage + * these states for themselves. + * + * This class is specifically designed to work with packets/frames + * in the asynchronous PDU architecture of GNU Radio. See the + * packet_format_async block for formatting the headers onto + * payloads and packet_parse_b block for parsing headers in a + * receiver. + * + * The Packet Format block takes in a PDU and uses a formatter + * class derived from this class to add a header onto the + * packet. The Packet Format blocks takes in the PDU, unpacks the + * message, and passes it to a formatter class' format function, + * which builds a header based on the payload. The header is + * passed back and emitted from formatter block as a separate + * output. The async format block, packet_format_async, has two + * message output ports. The 'header' port passes the header out + * as a PDU and the 'payload' passes the payload out as a PDU. The + * flowgraph can then separately modulate and combine these two + * pieces in the follow-on processing. + * + * The packet_sync_b block uses the formatter class by calling the + * 'parse' function to parse the received packet headers. This + * parser block is a sink for the data stream and emits a message + * from an 'info' port that contains an PMT dictionary of the + * information in the header. The formatter class determines the + * dictionary keys. + * + * This is the base class for dealing with formatting headers for + * different protocols and purposes. For other header formatting + * behaviors, create a child class from here and overload the + * format, parse, and parsing state machine functions as + * necessary. + * + * \sa header_format_default + * \sa header_format_counter + */ +class DIGITAL_API header_format_base + : public boost::enable_shared_from_this<gr::digital::header_format_base> +{ +public: + typedef boost::shared_ptr<header_format_base> sptr; + + header_format_base(); + virtual ~header_format_base(); + + sptr base() { return shared_from_this(); }; + sptr formatter() { return shared_from_this(); }; /*! - * \brief Base header formatter class. - * \ingroup packet_operators_blk - * - * \details - * - * Creates a base class that other packet formatters will inherit - * from. The child classes create and parse protocol-specific - * headers. To add a new protocol processing class, create a class - * that inherits from this and overload the necessary - * functions. The main functions to overload are: - * - * \li header_format_base::format: takes in a payload and - * creates a header from it. - * - * \li header_format_base::parse: receive bits and extract - * the header info. These are expected to be hard bits (0 or 1) - * that have either been sliced or gone through an FEC decoder. - * - * \li header_format_base::header_nbits: the number of bits - * in the full header (including an access code). - * - * \li header_format_base::header_ok: checks to see if the - * received header is ok. Since the header often specifies the - * length of the frame to decode next, it is important that this - * information be correct. + * Function to creates a header. The child classes overload this + * function to format the header in the protocol-specific way. * - * \li header_format_base::header_payload: unpacks the header - * register (from the class header_buffer) as a set of bits into - * its component parts of the header. For example, this may find - * and extract the frame length field as a 16-bit value and/or - * flags related to the type of modulation and FEC codes used in - * the frame's payload. + * \param nbytes_in The length (in bytes) of the \p input payload + * \param input An array of unsigned chars of the packet payload + * \param output A pmt::u8vector with the new header prepended + * onto the input data. + * \param info A pmt::dict containing meta data and info about + * the PDU (generally from the metadata portion of the + * input PDU). Data can be extracted from this for the + * header formatting or inserted. * - * Protected functions of this class that the child class should - * overload include: - * - * \li enter_search - * \li enter_have_sync - * \li enter_have_header - * - * These three function represent the different states of the - * parsing state machine. Expected behavior is that the protocol - * has some known word that we are first looking for the identify - * the start of the frame. The parsing FSM starts in a state to - * search for the beginning of the header, normally by looking for - * a known word (i.e., the access code). Then it changes state to - * read in the full header. We expect that the protocol provides - * the length of the header for processing, so the parsing looks - * pulls in the full length of the header. Then it changes state - * to the "have header" state for checking and processing. The - * base class provides the basic functionality for this state - * machine. However, most likely, each child class must manage - * these states for themselves. - * - * This class is specifically designed to work with packets/frames - * in the asynchronous PDU architecture of GNU Radio. See the - * packet_format_async block for formatting the headers onto - * payloads and packet_parse_b block for parsing headers in a - * receiver. - * - * The Packet Format block takes in a PDU and uses a formatter - * class derived from this class to add a header onto the - * packet. The Packet Format blocks takes in the PDU, unpacks the - * message, and passes it to a formatter class' format function, - * which builds a header based on the payload. The header is - * passed back and emitted from formatter block as a separate - * output. The async format block, packet_format_async, has two - * message output ports. The 'header' port passes the header out - * as a PDU and the 'payload' passes the payload out as a PDU. The - * flowgraph can then separately modulate and combine these two - * pieces in the follow-on processing. - * - * The packet_sync_b block uses the formatter class by calling the - * 'parse' function to parse the received packet headers. This - * parser block is a sink for the data stream and emits a message - * from an 'info' port that contains an PMT dictionary of the - * information in the header. The formatter class determines the - * dictionary keys. + * MUST be overloaded. + */ + virtual bool format(int nbytes_in, + const unsigned char* input, + pmt::pmt_t& output, + pmt::pmt_t& info) = 0; + + /*! + * Parses a header. This function is overloaded in the child + * class, which knows how to convert the incoming hard bits (0's + * and 1's) back into a packet header. * - * This is the base class for dealing with formatting headers for - * different protocols and purposes. For other header formatting - * behaviors, create a child class from here and overload the - * format, parse, and parsing state machine functions as - * necessary. + * \param nbits_in The number of bits in the input array. + * \param input The input as hard decision bits. + * \param info A vector of pmt::dicts to hold any meta data or + * info about the PDU. When parsing the header, the + * formatter can add info from the header into this dict. + * Each packet has a single PMT dictionary of info, so + * the vector length is the number of packets received + * extracted during one call to this parser function. + * \param nbits_processed Number of input bits actually + * processed; If all goes well, this is nbits_in. A + * premature return after a bad header could be less than + * this. * - * \sa header_format_default - * \sa header_format_counter + * MUST be overloaded. + */ + virtual bool parse(int nbits_in, + const unsigned char* input, + std::vector<pmt::pmt_t>& info, + int& nbits_processed) = 0; + + /*! + * Returns the length of the formatted header in bits. + * MUST be overloaded. */ - class DIGITAL_API header_format_base - : public boost::enable_shared_from_this<gr::digital::header_format_base> - { - public: - typedef boost::shared_ptr<header_format_base> sptr; - - header_format_base(); - virtual ~header_format_base(); - - sptr base() { return shared_from_this(); }; - sptr formatter() { return shared_from_this(); }; - - /*! - * Function to creates a header. The child classes overload this - * function to format the header in the protocol-specific way. - * - * \param nbytes_in The length (in bytes) of the \p input payload - * \param input An array of unsigned chars of the packet payload - * \param output A pmt::u8vector with the new header prepended - * onto the input data. - * \param info A pmt::dict containing meta data and info about - * the PDU (generally from the metadata portion of the - * input PDU). Data can be extracted from this for the - * header formatting or inserted. - * - * MUST be overloaded. - */ - virtual bool format(int nbytes_in, - const unsigned char *input, - pmt::pmt_t &output, - pmt::pmt_t &info) = 0; - - /*! - * Parses a header. This function is overloaded in the child - * class, which knows how to convert the incoming hard bits (0's - * and 1's) back into a packet header. - * - * \param nbits_in The number of bits in the input array. - * \param input The input as hard decision bits. - * \param info A vector of pmt::dicts to hold any meta data or - * info about the PDU. When parsing the header, the - * formatter can add info from the header into this dict. - * Each packet has a single PMT dictionary of info, so - * the vector length is the number of packets received - * extracted during one call to this parser function. - * \param nbits_processed Number of input bits actually - * processed; If all goes well, this is nbits_in. A - * premature return after a bad header could be less than - * this. - * - * MUST be overloaded. - */ - virtual bool parse(int nbits_in, - const unsigned char *input, - std::vector<pmt::pmt_t> &info, - int &nbits_processed) = 0; - - /*! - * Returns the length of the formatted header in bits. - * MUST be overloaded. - */ - virtual size_t header_nbits() const = 0; - - /*! - * Returns the length of the formatted header in bytes. - * Auto-calculated from the overloaded header_nbits(). - */ - size_t header_nbytes() const; - - protected: - enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC}; - - state_t d_state; //!< state of the state machine - header_buffer d_hdr_reg; //!< header_buffer object to hold header bits - pmt::pmt_t d_info; //!< info captured from the header - - //! Enter Search state of the state machine to find the access code. - virtual void enter_search(); - - //! Access code found, start getting the header - virtual void enter_have_sync(); - - //! Header found, setup for pulling in the hard decision bits - virtual void enter_have_header(int payload_len); - - //! Verify that the header is valid - virtual bool header_ok() = 0; - - /*! Get info from the header; return payload length and package - * rest of data in d_info dictionary. - */ - virtual int header_payload() = 0; - - /*! Used by blocks to access the logger system. - */ - gr::logger_ptr d_logger; - gr::logger_ptr d_debug_logger; - }; - - } // namespace digital + virtual size_t header_nbits() const = 0; + + /*! + * Returns the length of the formatted header in bytes. + * Auto-calculated from the overloaded header_nbits(). + */ + size_t header_nbytes() const; + +protected: + enum state_t { STATE_SYNC_SEARCH, STATE_HAVE_SYNC }; + + state_t d_state; //!< state of the state machine + header_buffer d_hdr_reg; //!< header_buffer object to hold header bits + pmt::pmt_t d_info; //!< info captured from the header + + //! Enter Search state of the state machine to find the access code. + virtual void enter_search(); + + //! Access code found, start getting the header + virtual void enter_have_sync(); + + //! Header found, setup for pulling in the hard decision bits + virtual void enter_have_header(int payload_len); + + //! Verify that the header is valid + virtual bool header_ok() = 0; + + /*! Get info from the header; return payload length and package + * rest of data in d_info dictionary. + */ + virtual int header_payload() = 0; + + /*! Used by blocks to access the logger system. + */ + gr::logger_ptr d_logger; + gr::logger_ptr d_debug_logger; +}; + +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H */ diff --git a/gr-digital/include/gnuradio/digital/header_format_counter.h b/gr-digital/include/gnuradio/digital/header_format_counter.h index 752a9ec775..e04ef7e019 100644 --- a/gr-digital/include/gnuradio/digital/header_format_counter.h +++ b/gr-digital/include/gnuradio/digital/header_format_counter.h @@ -27,108 +27,105 @@ #include <gnuradio/digital/header_format_default.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Header formatter that adds the payload bits/symbol + * format and a packet number counter. + * \ingroup packet_operators_blk + * + * \details + * + * Child class of header_format_default. This version adds two + * fields to the header: + * + * \li bps (16 bits): bits/symbol used when modulating the payload. + * \li count (16 bits): a counter for the packet number. + * + * Like the default packet formatter, the length is encoded as a + * 16-bit value repeated twice. The full packet looks like: + * \verbatim + | access code | hdr | payload | + \endverbatim + * + * Where the access code is <= 64 bits and hdr is: + * \verbatim + | 0 -- 15 | 16 -- 31 | + | pkt len | pkt len | + | bits/sym | counter | + \endverbatim + * + * The access code and header are formatted for network byte order. + * + * \sa header_format_default + */ +class DIGITAL_API header_format_counter : public header_format_default +{ +public: + header_format_counter(const std::string& access_code, int threshold, int bps); + virtual ~header_format_counter(); /*! - * \brief Header formatter that adds the payload bits/symbol - * format and a packet number counter. - * \ingroup packet_operators_blk - * - * \details - * - * Child class of header_format_default. This version adds two - * fields to the header: + * Creates a header from the access code and packet length to + * build an output packet in the form: * - * \li bps (16 bits): bits/symbol used when modulating the payload. - * \li count (16 bits): a counter for the packet number. - * - * Like the default packet formatter, the length is encoded as a - * 16-bit value repeated twice. The full packet looks like: * \verbatim - | access code | hdr | payload | + | access code | pkt len | pkt len | bps | counter | \endverbatim * - * Where the access code is <= 64 bits and hdr is: - * \verbatim - | 0 -- 15 | 16 -- 31 | - | pkt len | pkt len | - | bits/sym | counter | - \endverbatim - * - * The access code and header are formatted for network byte order. - * - * \sa header_format_default + * \param nbytes_in The length (in bytes) of the \p input payload + * \param input An array of unsigned chars of the packet payload + * \param output A pmt::u8vector with the new header prepended + * onto the input data. + * \param info A pmt::dict containing meta data and info about + * the PDU (generally from the metadata portion of the + * input PDU). Data can be extracted from this for the + * header formatting or inserted. */ - class DIGITAL_API header_format_counter - : public header_format_default - { - public: - header_format_counter(const std::string &access_code, - int threshold, int bps); - virtual ~header_format_counter(); + virtual bool format(int nbytes_in, + const unsigned char* input, + pmt::pmt_t& output, + pmt::pmt_t& info); - /*! - * Creates a header from the access code and packet length to - * build an output packet in the form: - * - * \verbatim - | access code | pkt len | pkt len | bps | counter | - \endverbatim - * - * \param nbytes_in The length (in bytes) of the \p input payload - * \param input An array of unsigned chars of the packet payload - * \param output A pmt::u8vector with the new header prepended - * onto the input data. - * \param info A pmt::dict containing meta data and info about - * the PDU (generally from the metadata portion of the - * input PDU). Data can be extracted from this for the - * header formatting or inserted. - */ - virtual bool format(int nbytes_in, - const unsigned char *input, - pmt::pmt_t &output, - pmt::pmt_t &info); - - /*! - * Returns the length of the formatted header in bits. - */ - virtual size_t header_nbits() const; + /*! + * Returns the length of the formatted header in bits. + */ + virtual size_t header_nbits() const; - /*! - * Factory to create an async packet header formatter; returns - * an sptr to the object. - * - * \param access_code An access code that is used to find and - * synchronize the start of a packet. Used in the parser and in - * other blocks like a corr_est block that helps trigger the - * receiver. Can be up to 64-bits long. - * \param threshold How many bits can be wrong in the access - * code and still count as correct. - * \param bps The number of bits/second used in the payload's - * modulator. - */ - static sptr make(const std::string &access_code, - int threshold, int bps); + /*! + * Factory to create an async packet header formatter; returns + * an sptr to the object. + * + * \param access_code An access code that is used to find and + * synchronize the start of a packet. Used in the parser and in + * other blocks like a corr_est block that helps trigger the + * receiver. Can be up to 64-bits long. + * \param threshold How many bits can be wrong in the access + * code and still count as correct. + * \param bps The number of bits/second used in the payload's + * modulator. + */ + static sptr make(const std::string& access_code, int threshold, int bps); - protected: - uint16_t d_counter; //!< keeps track of the number of packets transmitted +protected: + uint16_t d_counter; //!< keeps track of the number of packets transmitted - //! Verify that the header is valid - bool header_ok(); + //! Verify that the header is valid + bool header_ok(); - /*! Get info from the header; return payload length and package - * rest of data in d_info dictionary. - * - * Extracts the header of the form: - * - * \verbatim - | access code | pkt len | pkt len | bps | counter | payload | - \endverbatim - */ - int header_payload(); - }; + /*! Get info from the header; return payload length and package + * rest of data in d_info dictionary. + * + * Extracts the header of the form: + * + * \verbatim + | access code | pkt len | pkt len | bps | counter | payload | + \endverbatim + */ + int header_payload(); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_COUNTER_H */ diff --git a/gr-digital/include/gnuradio/digital/header_format_crc.h b/gr-digital/include/gnuradio/digital/header_format_crc.h index edb18844db..410e6273fa 100644 --- a/gr-digital/include/gnuradio/digital/header_format_crc.h +++ b/gr-digital/include/gnuradio/digital/header_format_crc.h @@ -28,91 +28,91 @@ #include <boost/crc.hpp> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Header formatter that includes the payload length, + * packet number, and a CRC check on the header. + * \ingroup packet_operators_blk + * + * \details + * + * Child class of header_format_base. This version's header + * format looks like: + * + * \li length (12 bits): length of the payload + * \li number (12 bits): packet number + * \li CRC8 (8 bits): A CRC8 check on the header contents + * + * Instead of duplicating the payload length, we only add it once + * and use the CRC8 to make sure it's correctly received. + * + * \verbatim + | 0 -- 11 | 12 -- 23 | 24 -- 31 | + | len | pkt len | CRC8 | + \endverbatim + * + * Reimplements packet_header_default in the style of the + * header_format_base. + */ +class DIGITAL_API header_format_crc : public header_format_base +{ +public: + header_format_crc(const std::string& len_key_name = "packet_len", + const std::string& num_key_name = "packet_num"); + virtual ~header_format_crc(); + + void set_header_num(unsigned header_num) { d_header_number = header_num; }; /*! - * \brief Header formatter that includes the payload length, - * packet number, and a CRC check on the header. - * \ingroup packet_operators_blk + * \brief Encodes the header information in the given tags into + * bits and places them into \p out. * * \details - * - * Child class of header_format_base. This version's header - * format looks like: - * - * \li length (12 bits): length of the payload - * \li number (12 bits): packet number - * \li CRC8 (8 bits): A CRC8 check on the header contents - * - * Instead of duplicating the payload length, we only add it once - * and use the CRC8 to make sure it's correctly received. - * - * \verbatim - | 0 -- 11 | 12 -- 23 | 24 -- 31 | - | len | pkt len | CRC8 | - \endverbatim - * - * Reimplements packet_header_default in the style of the - * header_format_base. + * Uses the following header format: + * - Bits 0-11: The packet length (what was stored in the tag with key \p + * len_tag_key) + * - Bits 12-23: The header number (counts up everytime this function is called) + * - Bit 24-31: 8-Bit CRC */ - class DIGITAL_API header_format_crc - : public header_format_base - { - public: - header_format_crc(const std::string &len_key_name="packet_len", - const std::string &num_key_name="packet_num"); - virtual ~header_format_crc(); - - void set_header_num(unsigned header_num) { d_header_number = header_num; }; - - /*! - * \brief Encodes the header information in the given tags into - * bits and places them into \p out. - * - * \details - * Uses the following header format: - * - Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) - * - Bits 12-23: The header number (counts up everytime this function is called) - * - Bit 24-31: 8-Bit CRC - */ - virtual bool format(int nbytes_in, - const unsigned char *input, - pmt::pmt_t &output, - pmt::pmt_t &info); + virtual bool format(int nbytes_in, + const unsigned char* input, + pmt::pmt_t& output, + pmt::pmt_t& info); - virtual bool parse(int nbits_in, - const unsigned char *input, - std::vector<pmt::pmt_t> &info, - int &nbits_processed); + virtual bool parse(int nbits_in, + const unsigned char* input, + std::vector<pmt::pmt_t>& info, + int& nbits_processed); - /*! - * Returns the length of the formatted header in bits. - */ - virtual size_t header_nbits() const; + /*! + * Returns the length of the formatted header in bits. + */ + virtual size_t header_nbits() const; - /*! - * Factory to create an async packet header formatter; returns - * an sptr to the object. - */ - static sptr make(const std::string &len_key_name="packet_len", - const std::string &num_key_name="packet_num"); + /*! + * Factory to create an async packet header formatter; returns + * an sptr to the object. + */ + static sptr make(const std::string& len_key_name = "packet_len", + const std::string& num_key_name = "packet_num"); - protected: - uint16_t d_header_number; - pmt::pmt_t d_len_key_name; - pmt::pmt_t d_num_key_name; - boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl; +protected: + uint16_t d_header_number; + pmt::pmt_t d_len_key_name; + pmt::pmt_t d_num_key_name; + boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl; - //! Verify that the header is valid - virtual bool header_ok(); + //! Verify that the header is valid + virtual bool header_ok(); - /*! Get info from the header; return payload length and package - * rest of data in d_info dictionary. - */ - virtual int header_payload(); - }; + /*! Get info from the header; return payload length and package + * rest of data in d_info dictionary. + */ + virtual int header_payload(); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_CRC_H */ diff --git a/gr-digital/include/gnuradio/digital/header_format_default.h b/gr-digital/include/gnuradio/digital/header_format_default.h index bfea3567f8..14af67dfdc 100644 --- a/gr-digital/include/gnuradio/digital/header_format_default.h +++ b/gr-digital/include/gnuradio/digital/header_format_default.h @@ -30,194 +30,191 @@ #include <boost/enable_shared_from_this.hpp> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Default header formatter for PDU formatting. + * \ingroup packet_operators_blk + * + * \details + * Used to handle the default packet header. + * + * See the parent class header_format_base for details of how + * these classes operate. + * + * The default header created in this base class consists of an + * access code and the packet length. The length is encoded as a + * 16-bit value repeated twice: + * + * \verbatim + | access code | hdr | payload | + \endverbatim + * + * Where the access code is <= 64 bits and hdr is: + * + * \verbatim + | 0 -- 15 | 16 -- 31 | + | pkt len | pkt len | + \endverbatim + * + * The access code and header are formatted for network byte order. + * + * This header generator does not calculate or append a CRC to the + * packet. Use the CRC32 Async block for that before adding the + * header. The header's length will then measure the payload plus + * the CRC length (4 bytes for a CRC32). + * + * The default header parser produces a PMT dictionary that + * contains the following keys. All formatter blocks MUST produce + * these two values in any dictionary. + * + * \li "payload symbols": the number of symbols in the + * payload. The payload decoder will have to know how this relates + * to the number of bits received. This block knows nothing about + * the payload modulation or the number of bits/symbol. Use the + * gr::digital::header_format_counter for that purpose. + * + * \sa header_format_counter + * \sa header_format_crc + * \sa header_format_ofdm + */ +class DIGITAL_API header_format_default : public header_format_base +{ +public: + header_format_default(const std::string& access_code, int threshold, int bps); + virtual ~header_format_default(); /*! - * \brief Default header formatter for PDU formatting. - * \ingroup packet_operators_blk - * - * \details - * Used to handle the default packet header. - * - * See the parent class header_format_base for details of how - * these classes operate. - * - * The default header created in this base class consists of an - * access code and the packet length. The length is encoded as a - * 16-bit value repeated twice: + * Creates a header from the access code and packet length and + * creates an output header as a PMT vector in the form: * * \verbatim - | access code | hdr | payload | + | access code | pkt len | pkt len | \endverbatim * - * Where the access code is <= 64 bits and hdr is: + * \param nbytes_in The length (in bytes) of the \p input payload + * \param input An array of unsigned chars of the packet payload + * \param output A pmt::u8vector with the new header prepended + * onto the input data. + * \param info A pmt::dict containing meta data and info about + * the PDU (generally from the metadata portion of the + * input PDU). Data can be extracted from this for the + * header formatting or inserted. + */ + virtual bool format(int nbytes_in, + const unsigned char* input, + pmt::pmt_t& output, + pmt::pmt_t& info); + + /*! + * Parses a header of the form: * * \verbatim - | 0 -- 15 | 16 -- 31 | - | pkt len | pkt len | + | access code | pkt len | pkt len | payload | \endverbatim * - * The access code and header are formatted for network byte order. + * This is implemented as a state machine that starts off + * searching for the access code. Once found, the access code is + * used to find the start of the packet and the following + * header. This default header encodes the length of the payload + * a 16 bit integer twice. The state machine finds the header + * and checks that both payload length values are the same. It + * then goes into its final state that reads in the payload + * (based on the payload length) and produces a payload as a PMT + * u8 vector of packed bytes. * - * This header generator does not calculate or append a CRC to the - * packet. Use the CRC32 Async block for that before adding the - * header. The header's length will then measure the payload plus - * the CRC length (4 bytes for a CRC32). - * - * The default header parser produces a PMT dictionary that - * contains the following keys. All formatter blocks MUST produce - * these two values in any dictionary. - * - * \li "payload symbols": the number of symbols in the - * payload. The payload decoder will have to know how this relates - * to the number of bits received. This block knows nothing about - * the payload modulation or the number of bits/symbol. Use the - * gr::digital::header_format_counter for that purpose. + * \param nbits_in The number of bits in the input array. + * \param input The input as hard decision bits. + * \param info A vector of pmt::dicts to hold any meta data or + * info about the PDU. When parsing the header, the + * formatter can add info from the header into this dict. + * Each packet has a single PMT dictionary of info, so + * the vector length is the number of packets received + * extracted during one call to this parser function. + * \param nbits_processed Number of input bits actually + * processed; If all goes well, this is nbits_in. A + * premature return after a bad header could be less than + * this. + */ + virtual bool parse(int nbits_in, + const unsigned char* input, + std::vector<pmt::pmt_t>& info, + int& nbits_processed); + + /*! + * Returns the length of the formatted header in bits. + */ + virtual size_t header_nbits() const; + + /*! + * Updates the access code. Must be a string of 1's and 0's and + * <= 64 bits. + */ + bool set_access_code(const std::string& access_code); + + /*! + * Returns the formatted access code as a 64-bit register. + */ + unsigned long long access_code() const; + + /*! + * Sets the threshold for number of access code bits can be in + * error before detection. Defaults to 0. + */ + void set_threshold(unsigned int thresh = 0); + + /*! + * Returns threshold value for access code detection. + */ + unsigned int threshold() const; + + /*! + * Factory to create an async packet header formatter; returns + * an sptr to the object. * - * \sa header_format_counter - * \sa header_format_crc - * \sa header_format_ofdm + * \param access_code An access code that is used to find and + * synchronize the start of a packet. Used in the parser and in + * other blocks like a corr_est block that helps trigger the + * receiver. Can be up to 64-bits long. + * \param threshold How many bits can be wrong in the access + * code and still count as correct. + * \param bps The number of bits/second used in the payload's + * modulator. + */ + static sptr make(const std::string& access_code, int threshold, int bps = 1); + +protected: + uint64_t d_access_code; //!< register to hold the access code + size_t d_access_code_len; //!< length in bits of the access code + + uint16_t d_bps; //!< bits/sec of payload modulation + + unsigned long long d_data_reg; //!< used to look for access_code + unsigned long long d_mask; /*!< masks access_code bits (top N bits are set where + N is the number of bits in the access code) */ + unsigned int d_threshold; //!< how many bits may be wrong in sync vector + + int d_pkt_len; //!< Length of the packet to put into the output buffer + int d_pkt_count; //!< Number of bytes bits already received + + int d_nbits; //!< num bits processed since reset + + //! Access code found, start getting the header + virtual void enter_have_sync(); + + //! Header found, setup for pulling in the hard decision bits + virtual void enter_have_header(int payload_len); + + //! Verify that the header is valid + virtual bool header_ok(); + + /*! Get info from the header; return payload length and package + * rest of data in d_info dictionary. */ - class DIGITAL_API header_format_default - : public header_format_base - { - public: - header_format_default(const std::string &access_code, int threshold, - int bps); - virtual ~header_format_default(); - - /*! - * Creates a header from the access code and packet length and - * creates an output header as a PMT vector in the form: - * - * \verbatim - | access code | pkt len | pkt len | - \endverbatim - * - * \param nbytes_in The length (in bytes) of the \p input payload - * \param input An array of unsigned chars of the packet payload - * \param output A pmt::u8vector with the new header prepended - * onto the input data. - * \param info A pmt::dict containing meta data and info about - * the PDU (generally from the metadata portion of the - * input PDU). Data can be extracted from this for the - * header formatting or inserted. - */ - virtual bool format(int nbytes_in, - const unsigned char *input, - pmt::pmt_t &output, - pmt::pmt_t &info); - - /*! - * Parses a header of the form: - * - * \verbatim - | access code | pkt len | pkt len | payload | - \endverbatim - * - * This is implemented as a state machine that starts off - * searching for the access code. Once found, the access code is - * used to find the start of the packet and the following - * header. This default header encodes the length of the payload - * a 16 bit integer twice. The state machine finds the header - * and checks that both payload length values are the same. It - * then goes into its final state that reads in the payload - * (based on the payload length) and produces a payload as a PMT - * u8 vector of packed bytes. - * - * \param nbits_in The number of bits in the input array. - * \param input The input as hard decision bits. - * \param info A vector of pmt::dicts to hold any meta data or - * info about the PDU. When parsing the header, the - * formatter can add info from the header into this dict. - * Each packet has a single PMT dictionary of info, so - * the vector length is the number of packets received - * extracted during one call to this parser function. - * \param nbits_processed Number of input bits actually - * processed; If all goes well, this is nbits_in. A - * premature return after a bad header could be less than - * this. - */ - virtual bool parse(int nbits_in, - const unsigned char *input, - std::vector<pmt::pmt_t> &info, - int &nbits_processed); - - /*! - * Returns the length of the formatted header in bits. - */ - virtual size_t header_nbits() const; - - /*! - * Updates the access code. Must be a string of 1's and 0's and - * <= 64 bits. - */ - bool set_access_code(const std::string &access_code); - - /*! - * Returns the formatted access code as a 64-bit register. - */ - unsigned long long access_code() const; - - /*! - * Sets the threshold for number of access code bits can be in - * error before detection. Defaults to 0. - */ - void set_threshold(unsigned int thresh=0); - - /*! - * Returns threshold value for access code detection. - */ - unsigned int threshold() const; - - /*! - * Factory to create an async packet header formatter; returns - * an sptr to the object. - * - * \param access_code An access code that is used to find and - * synchronize the start of a packet. Used in the parser and in - * other blocks like a corr_est block that helps trigger the - * receiver. Can be up to 64-bits long. - * \param threshold How many bits can be wrong in the access - * code and still count as correct. - * \param bps The number of bits/second used in the payload's - * modulator. - */ - static sptr make(const std::string &access_code, int threshold, - int bps = 1); - - protected: - uint64_t d_access_code; //!< register to hold the access code - size_t d_access_code_len; //!< length in bits of the access code - - uint16_t d_bps; //!< bits/sec of payload modulation - - unsigned long long d_data_reg; //!< used to look for access_code - unsigned long long d_mask; /*!< masks access_code bits (top N bits are set where - N is the number of bits in the access code) */ - unsigned int d_threshold; //!< how many bits may be wrong in sync vector - - int d_pkt_len; //!< Length of the packet to put into the output buffer - int d_pkt_count; //!< Number of bytes bits already received - - int d_nbits; //!< num bits processed since reset - - //! Access code found, start getting the header - virtual void enter_have_sync(); - - //! Header found, setup for pulling in the hard decision bits - virtual void enter_have_header(int payload_len); - - //! Verify that the header is valid - virtual bool header_ok(); - - /*! Get info from the header; return payload length and package - * rest of data in d_info dictionary. - */ - virtual int header_payload(); - }; - - } // namespace digital + virtual int header_payload(); +}; + +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H */ diff --git a/gr-digital/include/gnuradio/digital/header_format_ofdm.h b/gr-digital/include/gnuradio/digital/header_format_ofdm.h index b426c74cbc..ca68435fc5 100644 --- a/gr-digital/include/gnuradio/digital/header_format_ofdm.h +++ b/gr-digital/include/gnuradio/digital/header_format_ofdm.h @@ -28,100 +28,102 @@ #include <boost/crc.hpp> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Header formatter that includes the payload length, + * packet number, and a CRC check on the header. + * \ingroup packet_operators_blk + * + * \details + * + * Child class of header_format_base. This version's header + * format looks like: + * + * \li length (12 bits): length of the payload + * \li number (12 bits): packet number + * \li CRC8 (8 bits): A CRC8 check on the header contents + * + * Instead of duplicating the payload length, we only add it once + * and use the CRC8 to make sure it's correctly received. + * + * \verbatim + | 0 -- 11 | 12 -- 23 | 24 -- 31 | + | len | pkt len | CRC8 | + \endverbatim + * + * Reimplements packet_header_default in the style of the + * header_format_base. + */ +class DIGITAL_API header_format_ofdm : public header_format_crc +{ +public: + header_format_ofdm(const std::vector<std::vector<int>>& occupied_carriers, + int n_syms, + const std::string& len_key_name = "packet_len", + const std::string& frame_key_name = "frame_len", + const std::string& num_key_name = "packet_num", + int bits_per_header_sym = 1, + int bits_per_payload_sym = 1, + bool scramble_header = false); + virtual ~header_format_ofdm(); /*! - * \brief Header formatter that includes the payload length, - * packet number, and a CRC check on the header. - * \ingroup packet_operators_blk + * \brief Encodes the header information in the given tags into + * bits and places them into \p out. * * \details - * - * Child class of header_format_base. This version's header - * format looks like: - * - * \li length (12 bits): length of the payload - * \li number (12 bits): packet number - * \li CRC8 (8 bits): A CRC8 check on the header contents - * - * Instead of duplicating the payload length, we only add it once - * and use the CRC8 to make sure it's correctly received. - * - * \verbatim - | 0 -- 11 | 12 -- 23 | 24 -- 31 | - | len | pkt len | CRC8 | - \endverbatim - * - * Reimplements packet_header_default in the style of the - * header_format_base. + * Uses the following header format: + * - Bits 0-11: The packet length (what was stored in the tag with key \p + * len_tag_key) + * - Bits 12-23: The header number (counts up everytime this function is called) + * - Bit 24-31: 8-Bit CRC */ - class DIGITAL_API header_format_ofdm - : public header_format_crc - { - public: - header_format_ofdm(const std::vector<std::vector<int> > &occupied_carriers, - int n_syms, - const std::string &len_key_name="packet_len", - const std::string &frame_key_name="frame_len", - const std::string &num_key_name="packet_num", - int bits_per_header_sym=1, - int bits_per_payload_sym=1, - bool scramble_header=false); - virtual ~header_format_ofdm(); + virtual bool format(int nbytes_in, + const unsigned char* input, + pmt::pmt_t& output, + pmt::pmt_t& info); - /*! - * \brief Encodes the header information in the given tags into - * bits and places them into \p out. - * - * \details - * Uses the following header format: - * - Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) - * - Bits 12-23: The header number (counts up everytime this function is called) - * - Bit 24-31: 8-Bit CRC - */ - virtual bool format(int nbytes_in, - const unsigned char *input, - pmt::pmt_t &output, - pmt::pmt_t &info); + virtual bool parse(int nbits_in, + const unsigned char* input, + std::vector<pmt::pmt_t>& info, + int& nbits_processed); - virtual bool parse(int nbits_in, - const unsigned char *input, - std::vector<pmt::pmt_t> &info, - int &nbits_processed); - - /*! - * Returns the length of the formatted header in bits. - */ - virtual size_t header_nbits() const; + /*! + * Returns the length of the formatted header in bits. + */ + virtual size_t header_nbits() const; - /*! - * Factory to create an async packet header formatter; returns - * an sptr to the object. - */ - static sptr make(const std::vector<std::vector<int> > &occupied_carriers, - int n_syms, - const std::string &len_key_name="packet_len", - const std::string &frame_key_name="frame_len", - const std::string &num_key_name="packet_num", - int bits_per_header_sym=1, - int bits_per_payload_sym=1, - bool scramble_header=false); + /*! + * Factory to create an async packet header formatter; returns + * an sptr to the object. + */ + static sptr make(const std::vector<std::vector<int>>& occupied_carriers, + int n_syms, + const std::string& len_key_name = "packet_len", + const std::string& frame_key_name = "frame_len", + const std::string& num_key_name = "packet_num", + int bits_per_header_sym = 1, + int bits_per_payload_sym = 1, + bool scramble_header = false); - protected: - pmt::pmt_t d_frame_key_name; //!< Tag key of the additional frame length tag - const std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data - int d_syms_per_set; //!< Helper variable: Total number of elements in d_occupied_carriers - int d_bits_per_payload_sym; - std::vector<uint8_t> d_scramble_mask; //!< Bits are xor'd with this before tx'ing - size_t d_header_len; +protected: + pmt::pmt_t d_frame_key_name; //!< Tag key of the additional frame length tag + const std::vector<std::vector<int>> + d_occupied_carriers; //!< Which carriers/symbols carry data + int d_syms_per_set; //!< Helper variable: Total number of elements in + //!< d_occupied_carriers + int d_bits_per_payload_sym; + std::vector<uint8_t> d_scramble_mask; //!< Bits are xor'd with this before tx'ing + size_t d_header_len; - /*! Get info from the header; return payload length and package - * rest of data in d_info dictionary. - */ - virtual int header_payload(); - }; + /*! Get info from the header; return payload length and package + * rest of data in d_info dictionary. + */ + virtual int header_payload(); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_OFDM_H */ diff --git a/gr-digital/include/gnuradio/digital/header_payload_demux.h b/gr-digital/include/gnuradio/digital/header_payload_demux.h index bcd6bd108a..0bccf0bfb1 100644 --- a/gr-digital/include/gnuradio/digital/header_payload_demux.h +++ b/gr-digital/include/gnuradio/digital/header_payload_demux.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 2012-2016 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, @@ -26,174 +26,174 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Header/Payload demuxer (HPD). + * \ingroup packet_operators_blk + * + * \details + * This block is designed to demultiplex packets from a bursty transmission. + * The typical application for this block is the case when you are receiving + * packets with yet-to-determine length. This block will pass the header + * section to other blocks for demodulation. Using the information from the + * demodulated header, it will then output the payload. The beginning of the + * header needs to be identified by a trigger signal (see below). + * + * \section hpd_theory_of_ops Theory of Operation + * + * Input 0 takes a continuous transmission of samples (items). + * Input 1 is an optional input for the trigger signal (mark beginning of + * packets). In this case, a non-zero value on input 1 identifies the beginning of a + * packet. Otherwise, a tag with the key specified in \p trigger_tag_key is used as a + * trigger (its value is irrelevant). + * + * Until a trigger signal is detected, all samples are dropped onto the floor. + * Once a trigger is detected, a total of \p header_len items are copied to output 0. + * The block then stalls until it receives a message on the message port + * \p header_data. The message must be a PMT dictionary; all key/value pairs are + * copied as tags to the first item of the payload (which is assumed to be the + * first item after the header). + * The value corresponding to the key specified in \p length_tag_key is read + * and taken as the payload length. The payload, together with the header data + * as tags, is then copied to output 1. + * + * If the header demodulation fails, the header must send a PMT with value + * pmt::PMT_F. The state gets reset and the header is ignored. + * + * \section hpd_item_sizes Symbols, Items and Item Sizes + * + * To generically and transparently handle different kinds of modulations, + * including OFDM, this block distinguises between \b symbols and \b items. + * + * Items are what are consumed at the input. Anything that uses complex samples + * will therefore use an itemsize of `sizeof(gr_complex)`. Symbols are a way of + * grouping items. In OFDM, we usually don't care about individual samples, but + * we do care about full OFDM symbols, so we set \p items_per_symbol to the + * IFFT / FFT length of the OFDM modulator / demodulator. + * For single-carrier modulations, this value can be set to the number of + * samples per symbol, to handle data in number of symbols, or to 1 to + * handle data in number of samples. + * If specified, \p guard_interval items are discarded before every symbol. + * This is useful for demuxing bursts of OFDM signals. + * + * On the output, we can deal with symbols directly by setting \p output_symbols + * to true. In that case, the output item size is the <em>symbol size</em>. + * + * \b Example: OFDM with 48 sub-carriers, using a length-64 IFFT on the + * modulator, and a cyclic-prefix length of 16 samples. In this case, + * \p itemsize is `sizeof(gr_complex)`, because we're receiving complex + * samples. One OFDM symbol has 64 samples, hence \p items_per_symbol is + * set to 64, and \p guard_interval to 16. The header length is specified + * in number of OFDM symbols. Because we want to deal with full OFDM + * symbols, we set \p output_symbols to true. + * + * \b Example: PSK-modulated signals, with 4 samples per symbol. Again, + * \p itemsize is `sizeof(gr_complex)` because we're still dealing with + * complex samples. \p items_per_symbol is 4, because one item is one + * sample. \p guard_interval must be set to 0. The header length is + * given in number of PSK symbols. + * + * \section hpd_uncertainty Handling timing uncertainty on the trigger + * + * By default, the assumption is made that the trigger arrives on *exactly* + * the sample that the header starts. These triggers typically come from + * timing synchronization algorithms which may be suboptimal, and have a + * known timing uncertainty (e.g., we know the trigger might be a sample + * too early or too late). + * + * The demuxer has an option for this case, the \p header_padding. If this + * value is non-zero, it specifies the number of items that are prepended + * and appended to the header before copying it to the header output. + * + * Example: Say our synchronization algorithm can be off by up to two + * samples, and the header length is 20 samples. So we set \p header_len + * to 20, and \p header_padding to 2. + * Now assume a trigger arrives on sample index 100. We copy a total of + * 24 samples to the header port, starting at sample index 98. + * + * The payload is *not* padded. Let's say the header demod reports a + * payload length of 100. In the previous examples, we would copy 100 + * samples to the payload port, starting at sample index 120 (this means + * the padded samples appended to the header are copied to both ports!). + * However, the header demodulator has the option to specify a payload + * offset, which cannot exceed the padding value. To do this, include + * a key `payload_offset` in the message sent back to the HPD. A negative + * value means the payload starts earlier than otherwise. + * (If you wanted to always pad the payload, you could set `payload_offset` + * to `-header_padding` and increase the reported length of the payload). + * + * Because the padding is specified in number of items, and not symbols, + * this value can only be multiples of the number of items per symbol *if* + * either \p output_symbols is true, or a guard interval is specified (or + * both). Note that in practice, it is rare that both a guard interval is + * specified *and* a padding value is required. The difference between the + * padding value and a guard interval is that a guard interval is part of + * the signal, and comes with *every* symbol, whereas the header padding + * is added to only the header, and is not by design. + * + * \section hpd_tag_handling Tag Handling + * + * Any tags on the input stream are copied to the corresponding output *if* they're + * on an item that is propagated. Note that a tag on the header items is copied to the + * header stream; that means the header-parsing block must handle these tags if they + * should go on the payload. + * A special case are tags on items that make up the guard interval. These are copied + * to the first item of the following symbol. + * If a tag is situated very close to the end of the payload, it might be unclear if + * it belongs to this packet or the following. In this case, it is possible that the + * tag might be propagated twice. + * + * Tags outside of packets are generally discarded. If there are tags that + * carry important information that must not be list, there are two + * additional mechanisms to preserve the tags: + * - Timing tags might be relevant to know \b when a packet was received. By + * specifying the name of a timestamp tag and the sample rate at this block, it + * keeps track of the time and will add the time to the first item of every packet. + * The name of the timestamp tag is usually 'rx_time' (see, e.g., + * gr::uhd::usrp_source::make()). + * The time value must be specified in the UHD time format. + * - Other tags are simply stored and updated. As an example, the user might want to know + * the rx frequency, which UHD stores in the rx_freq tag. In this case, add the tag name + * 'rx_freq' to the list of \p special_tags. This block will then always save the most + * current value of 'rx_freq' and add it to the beginning of every packet. + * + */ +class DIGITAL_API header_payload_demux : virtual public block +{ +public: + typedef boost::shared_ptr<header_payload_demux> sptr; /*! - * \brief Header/Payload demuxer (HPD). - * \ingroup packet_operators_blk - * - * \details - * This block is designed to demultiplex packets from a bursty transmission. - * The typical application for this block is the case when you are receiving - * packets with yet-to-determine length. This block will pass the header - * section to other blocks for demodulation. Using the information from the - * demodulated header, it will then output the payload. The beginning of the - * header needs to be identified by a trigger signal (see below). - * - * \section hpd_theory_of_ops Theory of Operation - * - * Input 0 takes a continuous transmission of samples (items). - * Input 1 is an optional input for the trigger signal (mark beginning of - * packets). In this case, a non-zero value on input 1 identifies the beginning of a packet. - * Otherwise, a tag with the key specified in \p trigger_tag_key is used as a - * trigger (its value is irrelevant). - * - * Until a trigger signal is detected, all samples are dropped onto the floor. - * Once a trigger is detected, a total of \p header_len items are copied to output 0. - * The block then stalls until it receives a message on the message port - * \p header_data. The message must be a PMT dictionary; all key/value pairs are - * copied as tags to the first item of the payload (which is assumed to be the - * first item after the header). - * The value corresponding to the key specified in \p length_tag_key is read - * and taken as the payload length. The payload, together with the header data - * as tags, is then copied to output 1. - * - * If the header demodulation fails, the header must send a PMT with value - * pmt::PMT_F. The state gets reset and the header is ignored. - * - * \section hpd_item_sizes Symbols, Items and Item Sizes - * - * To generically and transparently handle different kinds of modulations, - * including OFDM, this block distinguises between \b symbols and \b items. - * - * Items are what are consumed at the input. Anything that uses complex samples - * will therefore use an itemsize of `sizeof(gr_complex)`. Symbols are a way of - * grouping items. In OFDM, we usually don't care about individual samples, but - * we do care about full OFDM symbols, so we set \p items_per_symbol to the - * IFFT / FFT length of the OFDM modulator / demodulator. - * For single-carrier modulations, this value can be set to the number of - * samples per symbol, to handle data in number of symbols, or to 1 to - * handle data in number of samples. - * If specified, \p guard_interval items are discarded before every symbol. - * This is useful for demuxing bursts of OFDM signals. - * - * On the output, we can deal with symbols directly by setting \p output_symbols - * to true. In that case, the output item size is the <em>symbol size</em>. - * - * \b Example: OFDM with 48 sub-carriers, using a length-64 IFFT on the - * modulator, and a cyclic-prefix length of 16 samples. In this case, - * \p itemsize is `sizeof(gr_complex)`, because we're receiving complex - * samples. One OFDM symbol has 64 samples, hence \p items_per_symbol is - * set to 64, and \p guard_interval to 16. The header length is specified - * in number of OFDM symbols. Because we want to deal with full OFDM - * symbols, we set \p output_symbols to true. - * - * \b Example: PSK-modulated signals, with 4 samples per symbol. Again, - * \p itemsize is `sizeof(gr_complex)` because we're still dealing with - * complex samples. \p items_per_symbol is 4, because one item is one - * sample. \p guard_interval must be set to 0. The header length is - * given in number of PSK symbols. - * - * \section hpd_uncertainty Handling timing uncertainty on the trigger - * - * By default, the assumption is made that the trigger arrives on *exactly* - * the sample that the header starts. These triggers typically come from - * timing synchronization algorithms which may be suboptimal, and have a - * known timing uncertainty (e.g., we know the trigger might be a sample - * too early or too late). - * - * The demuxer has an option for this case, the \p header_padding. If this - * value is non-zero, it specifies the number of items that are prepended - * and appended to the header before copying it to the header output. - * - * Example: Say our synchronization algorithm can be off by up to two - * samples, and the header length is 20 samples. So we set \p header_len - * to 20, and \p header_padding to 2. - * Now assume a trigger arrives on sample index 100. We copy a total of - * 24 samples to the header port, starting at sample index 98. - * - * The payload is *not* padded. Let's say the header demod reports a - * payload length of 100. In the previous examples, we would copy 100 - * samples to the payload port, starting at sample index 120 (this means - * the padded samples appended to the header are copied to both ports!). - * However, the header demodulator has the option to specify a payload - * offset, which cannot exceed the padding value. To do this, include - * a key `payload_offset` in the message sent back to the HPD. A negative - * value means the payload starts earlier than otherwise. - * (If you wanted to always pad the payload, you could set `payload_offset` - * to `-header_padding` and increase the reported length of the payload). - * - * Because the padding is specified in number of items, and not symbols, - * this value can only be multiples of the number of items per symbol *if* - * either \p output_symbols is true, or a guard interval is specified (or - * both). Note that in practice, it is rare that both a guard interval is - * specified *and* a padding value is required. The difference between the - * padding value and a guard interval is that a guard interval is part of - * the signal, and comes with *every* symbol, whereas the header padding - * is added to only the header, and is not by design. - * - * \section hpd_tag_handling Tag Handling - * - * Any tags on the input stream are copied to the corresponding output *if* they're - * on an item that is propagated. Note that a tag on the header items is copied to the - * header stream; that means the header-parsing block must handle these tags if they - * should go on the payload. - * A special case are tags on items that make up the guard interval. These are copied - * to the first item of the following symbol. - * If a tag is situated very close to the end of the payload, it might be unclear if - * it belongs to this packet or the following. In this case, it is possible that the - * tag might be propagated twice. - * - * Tags outside of packets are generally discarded. If there are tags that - * carry important information that must not be list, there are two - * additional mechanisms to preserve the tags: - * - Timing tags might be relevant to know \b when a packet was received. By - * specifying the name of a timestamp tag and the sample rate at this block, it - * keeps track of the time and will add the time to the first item of every packet. - * The name of the timestamp tag is usually 'rx_time' (see, e.g., - * gr::uhd::usrp_source::make()). - * The time value must be specified in the UHD time format. - * - Other tags are simply stored and updated. As an example, the user might want to know the - * rx frequency, which UHD stores in the rx_freq tag. In this case, add the tag name 'rx_freq' - * to the list of \p special_tags. This block will then always save the most current value of - * 'rx_freq' and add it to the beginning of every packet. - * + * \param header_len Number of symbols per header + * \param items_per_symbol Number of items per symbol + * \param guard_interval Number of items between two consecutive symbols + * \param length_tag_key Key of the frame length tag + * \param trigger_tag_key Key of the trigger tag + * \param output_symbols Output symbols (true) or items (false)? + * \param itemsize Item size (bytes per item) + * \param timing_tag_key The name of the tag with timing information, usually + * 'rx_time' or empty (this means timing info is discarded) \param samp_rate Sampling + * rate at the input. Necessary to calculate the rx time of packets. \param + * special_tags A vector of strings denoting tags which shall be preserved (see \ref + * hpd_tag_handling) \param header_padding A number of items that is appended and + * prepended to the header. */ - class DIGITAL_API header_payload_demux : virtual public block - { - public: - typedef boost::shared_ptr<header_payload_demux> sptr; + static sptr + make(const int header_len, + const int items_per_symbol = 1, + const int guard_interval = 0, + const std::string& length_tag_key = "frame_len", + const std::string& trigger_tag_key = "", + const bool output_symbols = false, + const size_t itemsize = sizeof(gr_complex), + const std::string& timing_tag_key = "", + const double samp_rate = 1.0, + const std::vector<std::string>& special_tags = std::vector<std::string>(), + const size_t header_padding = 0); +}; - /*! - * \param header_len Number of symbols per header - * \param items_per_symbol Number of items per symbol - * \param guard_interval Number of items between two consecutive symbols - * \param length_tag_key Key of the frame length tag - * \param trigger_tag_key Key of the trigger tag - * \param output_symbols Output symbols (true) or items (false)? - * \param itemsize Item size (bytes per item) - * \param timing_tag_key The name of the tag with timing information, usually 'rx_time' or empty (this means timing info is discarded) - * \param samp_rate Sampling rate at the input. Necessary to calculate the rx time of packets. - * \param special_tags A vector of strings denoting tags which shall be preserved (see \ref hpd_tag_handling) - * \param header_padding A number of items that is appended and prepended to the header. - */ - static sptr make( - const int header_len, - const int items_per_symbol=1, - const int guard_interval=0, - const std::string &length_tag_key="frame_len", - const std::string &trigger_tag_key="", - const bool output_symbols=false, - const size_t itemsize=sizeof(gr_complex), - const std::string &timing_tag_key="", - const double samp_rate=1.0, - const std::vector<std::string> &special_tags=std::vector<std::string>(), - const size_t header_padding=0 - ); - }; - - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H */ - diff --git a/gr-digital/include/gnuradio/digital/interpolating_resampler_type.h b/gr-digital/include/gnuradio/digital/interpolating_resampler_type.h index 78687a545a..572adaceb6 100644 --- a/gr-digital/include/gnuradio/digital/interpolating_resampler_type.h +++ b/gr-digital/include/gnuradio/digital/interpolating_resampler_type.h @@ -24,17 +24,17 @@ #define INCLUDED_DIGITAL_INTERPOLATING_RESAMPLER_TYPE_H namespace gr { - namespace digital { +namespace digital { - // Interpolating Resampler type - enum ir_type { - IR_NONE = -1, - IR_MMSE_8TAP = 0, // Valid for [-Fs/4, Fs/4] bandlimited input - IR_PFB_NO_MF = 1, // No matched filtering, just interpolation - IR_PFB_MF = 2, - }; +// Interpolating Resampler type +enum ir_type { + IR_NONE = -1, + IR_MMSE_8TAP = 0, // Valid for [-Fs/4, Fs/4] bandlimited input + IR_PFB_NO_MF = 1, // No matched filtering, just interpolation + IR_PFB_MF = 2, +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_INTERPOLATING_RESAMPLER_TYPE_H */ diff --git a/gr-digital/include/gnuradio/digital/kurtotic_equalizer_cc.h b/gr-digital/include/gnuradio/digital/kurtotic_equalizer_cc.h index a23cfa1377..3605adf1e9 100644 --- a/gr-digital/include/gnuradio/digital/kurtotic_equalizer_cc.h +++ b/gr-digital/include/gnuradio/digital/kurtotic_equalizer_cc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -21,43 +21,42 @@ */ #ifndef INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H -#define INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H +#define INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H #include <gnuradio/digital/api.h> #include <gnuradio/sync_decimator.h> namespace gr { - namespace digital { - - /*! - * \brief Implements a kurtosis-based adaptive equalizer on complex stream - * \ingroup equalizers_blk - * - * \details - * Warning: This block does not yet work. - * - * "Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind - * equalization algorithm," IEEE Conf. on Control, Automation, - * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057." - */ - class DIGITAL_API kurtotic_equalizer_cc : - virtual public sync_decimator - { - protected: - virtual gr_complex error(const gr_complex &out) = 0; - virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; - - public: - // gr::digital::kurtotic_equalizer_cc::sptr - typedef boost::shared_ptr<kurtotic_equalizer_cc> sptr; - - static sptr make(int num_taps, float mu); - - virtual float gain() const = 0; - virtual void set_gain(float mu) = 0; - }; - - } /* namespace digital */ +namespace digital { + +/*! + * \brief Implements a kurtosis-based adaptive equalizer on complex stream + * \ingroup equalizers_blk + * + * \details + * Warning: This block does not yet work. + * + * "Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind + * equalization algorithm," IEEE Conf. on Control, Automation, + * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057." + */ +class DIGITAL_API kurtotic_equalizer_cc : virtual public sync_decimator +{ +protected: + virtual gr_complex error(const gr_complex& out) = 0; + virtual void update_tap(gr_complex& tap, const gr_complex& in) = 0; + +public: + // gr::digital::kurtotic_equalizer_cc::sptr + typedef boost::shared_ptr<kurtotic_equalizer_cc> sptr; + + static sptr make(int num_taps, float mu); + + virtual float gain() const = 0; + virtual void set_gain(float mu) = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_KURTOTIC_EQUALIZER_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/lfsr.h b/gr-digital/include/gnuradio/digital/lfsr.h index 57bda3b0a6..d7502a3a39 100644 --- a/gr-digital/include/gnuradio/digital/lfsr.h +++ b/gr-digital/include/gnuradio/digital/lfsr.h @@ -28,136 +28,137 @@ #include <stdint.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Fibonacci Linear Feedback Shift Register using specified - * polynomial mask - * \ingroup misc - * - * \details - * Generates a maximal length pseudo-random sequence of length - * 2^degree-1 - * - * Constructor: digital::lfsr(int mask, int seed, int reg_len); - * - * \param mask - polynomial coefficients representing the - * locations of feedback taps from a shift register - * which are xor'ed together to form the new high - * order bit. - * - * Some common masks might be: - * x^4 + x^3 + x^0 = 0x19 - * x^5 + x^3 + x^0 = 0x29 - * x^6 + x^5 + x^0 = 0x61 - * - * \param seed - the initialization vector placed into the - * register during initialization. Low order bit - * corresponds to x^0 coefficient -- the first to be - * shifted as output. - * - * \param reg_len - specifies the length of the feedback shift - * register to be used. During each iteration, the - * register is rightshifted one and the new bit is - * placed in bit reg_len. reg_len should generally be - * at least order(mask) + 1 - * - * - * see http://en.wikipedia.org/wiki/Linear_feedback_shift_register - * for more explanation. - * - * next_bit() - Standard LFSR operation - * - * Perform one cycle of the LFSR. The output bit is taken from - * the shift register LSB. The shift register MSB is assigned from - * the modulo 2 sum of the masked shift register. - * - * next_bit_scramble(unsigned char input) - Scramble an input stream - * - * Perform one cycle of the LFSR. The output bit is taken from - * the shift register LSB. The shift register MSB is assigned from - * the modulo 2 sum of the masked shift register and the input LSB. - * - * next_bit_descramble(unsigned char input) - Descramble an input stream - * - * Perform one cycle of the LFSR. The output bit is taken from - * the modulo 2 sum of the masked shift register and the input LSB. - * The shift register MSB is assigned from the LSB of the input. - * - * See http://en.wikipedia.org/wiki/Scrambler for operation of these - * last two functions (see multiplicative scrambler.) - */ - class lfsr - { - private: - uint32_t d_shift_register; - uint32_t d_mask; - uint32_t d_seed; - uint32_t d_shift_register_length; // less than 32 +/*! + * \brief Fibonacci Linear Feedback Shift Register using specified + * polynomial mask + * \ingroup misc + * + * \details + * Generates a maximal length pseudo-random sequence of length + * 2^degree-1 + * + * Constructor: digital::lfsr(int mask, int seed, int reg_len); + * + * \param mask - polynomial coefficients representing the + * locations of feedback taps from a shift register + * which are xor'ed together to form the new high + * order bit. + * + * Some common masks might be: + * x^4 + x^3 + x^0 = 0x19 + * x^5 + x^3 + x^0 = 0x29 + * x^6 + x^5 + x^0 = 0x61 + * + * \param seed - the initialization vector placed into the + * register during initialization. Low order bit + * corresponds to x^0 coefficient -- the first to be + * shifted as output. + * + * \param reg_len - specifies the length of the feedback shift + * register to be used. During each iteration, the + * register is rightshifted one and the new bit is + * placed in bit reg_len. reg_len should generally be + * at least order(mask) + 1 + * + * + * see http://en.wikipedia.org/wiki/Linear_feedback_shift_register + * for more explanation. + * + * next_bit() - Standard LFSR operation + * + * Perform one cycle of the LFSR. The output bit is taken from + * the shift register LSB. The shift register MSB is assigned from + * the modulo 2 sum of the masked shift register. + * + * next_bit_scramble(unsigned char input) - Scramble an input stream + * + * Perform one cycle of the LFSR. The output bit is taken from + * the shift register LSB. The shift register MSB is assigned from + * the modulo 2 sum of the masked shift register and the input LSB. + * + * next_bit_descramble(unsigned char input) - Descramble an input stream + * + * Perform one cycle of the LFSR. The output bit is taken from + * the modulo 2 sum of the masked shift register and the input LSB. + * The shift register MSB is assigned from the LSB of the input. + * + * See http://en.wikipedia.org/wiki/Scrambler for operation of these + * last two functions (see multiplicative scrambler.) + */ +class lfsr +{ +private: + uint32_t d_shift_register; + uint32_t d_mask; + uint32_t d_seed; + uint32_t d_shift_register_length; // less than 32 - static uint32_t - popCount(uint32_t x) - { - uint32_t r = x - ((x >> 1) & 033333333333) - - ((x >> 2) & 011111111111); - return ((r + (r >> 3)) & 030707070707) % 63; - } + static uint32_t popCount(uint32_t x) + { + uint32_t r = x - ((x >> 1) & 033333333333) - ((x >> 2) & 011111111111); + return ((r + (r >> 3)) & 030707070707) % 63; + } - public: - lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len) - : d_shift_register(seed), - d_mask(mask), - d_seed(seed), - d_shift_register_length(reg_len) - { - if(reg_len > 31) - throw std::invalid_argument("reg_len must be <= 31"); - } +public: + lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len) + : d_shift_register(seed), + d_mask(mask), + d_seed(seed), + d_shift_register_length(reg_len) + { + if (reg_len > 31) + throw std::invalid_argument("reg_len must be <= 31"); + } - unsigned char next_bit() - { - unsigned char output = d_shift_register & 1; - unsigned char newbit = popCount( d_shift_register & d_mask )%2; - d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); - return output; - } + unsigned char next_bit() + { + unsigned char output = d_shift_register & 1; + unsigned char newbit = popCount(d_shift_register & d_mask) % 2; + d_shift_register = + ((d_shift_register >> 1) | (newbit << d_shift_register_length)); + return output; + } - unsigned char next_bit_scramble(unsigned char input) - { - unsigned char output = d_shift_register & 1; - unsigned char newbit = (popCount( d_shift_register & d_mask )%2)^(input & 1); - d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); - return output; - } + unsigned char next_bit_scramble(unsigned char input) + { + unsigned char output = d_shift_register & 1; + unsigned char newbit = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1); + d_shift_register = + ((d_shift_register >> 1) | (newbit << d_shift_register_length)); + return output; + } - unsigned char next_bit_descramble(unsigned char input) - { - unsigned char output = (popCount( d_shift_register & d_mask )%2)^(input & 1); - unsigned char newbit = input & 1; - d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); - return output; - } + unsigned char next_bit_descramble(unsigned char input) + { + unsigned char output = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1); + unsigned char newbit = input & 1; + d_shift_register = + ((d_shift_register >> 1) | (newbit << d_shift_register_length)); + return output; + } - /*! - * Reset shift register to initial seed value - */ - void reset() { d_shift_register = d_seed; } + /*! + * Reset shift register to initial seed value + */ + void reset() { d_shift_register = d_seed; } - /*! - * Rotate the register through x number of bits - * where we are just throwing away the results to get queued up correctly - */ - void pre_shift(int num) - { - for(int i=0; i<num; i++) { - next_bit(); - } - } + /*! + * Rotate the register through x number of bits + * where we are just throwing away the results to get queued up correctly + */ + void pre_shift(int num) + { + for (int i = 0; i < num; i++) { + next_bit(); + } + } - int mask() const { return d_mask; } - }; + int mask() const { return d_mask; } +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_LFSR_H */ diff --git a/gr-digital/include/gnuradio/digital/lms_dd_equalizer_cc.h b/gr-digital/include/gnuradio/digital/lms_dd_equalizer_cc.h index ce8d04d1cb..3d946ec33f 100644 --- a/gr-digital/include/gnuradio/digital/lms_dd_equalizer_cc.h +++ b/gr-digital/include/gnuradio/digital/lms_dd_equalizer_cc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -28,74 +28,71 @@ #include <gnuradio/digital/constellation.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Least-Mean-Square Decision Directed Equalizer (complex in/out) + * \ingroup equalizers_blk + * + * \details + * This block implements an LMS-based decision-directed equalizer. + * It uses a set of weights, w, to correlate against the inputs, + * u, and a decisions is then made from this output. The error in + * the decision is used to update the weight vector. + * + * y[n] = conj(w[n]) u[n] + * d[n] = decision(y[n]) + * e[n] = d[n] - y[n] + * w[n+1] = w[n] + mu u[n] conj(e[n]) + * + * Where mu is a gain value (between 0 and 1 and usually small, + * around 0.001 - 0.01. + * + * This block uses the digital_constellation object for making the + * decision from y[n]. Create the constellation object for + * whatever constellation is to be used and pass in the object. + * In Python, you can use something like: + * + * self.constellation = digital.constellation_qpsk() + * + * To create a QPSK constellation (see the digital_constellation + * block for more details as to what constellations are available + * or how to create your own). You then pass the object to this + * block as an sptr, or using "self.constellation.base()". + * + * The theory for this algorithm can be found in Chapter 9 of: + * S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ: + * Prentice Hall, 1996. + */ +class DIGITAL_API lms_dd_equalizer_cc : virtual public sync_decimator +{ +protected: + virtual gr_complex error(const gr_complex& out) = 0; + virtual void update_tap(gr_complex& tap, const gr_complex& in) = 0; + +public: + // gr::digital::lms_dd_equalizer_cc::sptr + typedef boost::shared_ptr<lms_dd_equalizer_cc> sptr; /*! - * \brief Least-Mean-Square Decision Directed Equalizer (complex in/out) - * \ingroup equalizers_blk - * - * \details - * This block implements an LMS-based decision-directed equalizer. - * It uses a set of weights, w, to correlate against the inputs, - * u, and a decisions is then made from this output. The error in - * the decision is used to update the weight vector. - * - * y[n] = conj(w[n]) u[n] - * d[n] = decision(y[n]) - * e[n] = d[n] - y[n] - * w[n+1] = w[n] + mu u[n] conj(e[n]) - * - * Where mu is a gain value (between 0 and 1 and usually small, - * around 0.001 - 0.01. + * Make an LMS decision-directed equalizer * - * This block uses the digital_constellation object for making the - * decision from y[n]. Create the constellation object for - * whatever constellation is to be used and pass in the object. - * In Python, you can use something like: - * - * self.constellation = digital.constellation_qpsk() - * - * To create a QPSK constellation (see the digital_constellation - * block for more details as to what constellations are available - * or how to create your own). You then pass the object to this - * block as an sptr, or using "self.constellation.base()". - * - * The theory for this algorithm can be found in Chapter 9 of: - * S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ: - * Prentice Hall, 1996. + * \param num_taps Number of taps in the equalizer (channel size) + * \param mu Gain of the update loop + * \param sps Number of samples per symbol of the input signal + * \param cnst A constellation derived from class + * 'constellation'. Use base() method to get a shared pointer to + * this base class type. */ - class DIGITAL_API lms_dd_equalizer_cc : - virtual public sync_decimator - { - protected: - virtual gr_complex error(const gr_complex &out) = 0; - virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; - - public: - // gr::digital::lms_dd_equalizer_cc::sptr - typedef boost::shared_ptr<lms_dd_equalizer_cc> sptr; - - /*! - * Make an LMS decision-directed equalizer - * - * \param num_taps Number of taps in the equalizer (channel size) - * \param mu Gain of the update loop - * \param sps Number of samples per symbol of the input signal - * \param cnst A constellation derived from class - * 'constellation'. Use base() method to get a shared pointer to - * this base class type. - */ - static sptr make(int num_taps, - float mu, int sps, - constellation_sptr cnst); + static sptr make(int num_taps, float mu, int sps, constellation_sptr cnst); - virtual void set_taps(const std::vector<gr_complex> &taps) = 0; - virtual std::vector<gr_complex> taps() const = 0; - virtual float gain() const = 0; - virtual void set_gain(float mu) = 0; - }; + virtual void set_taps(const std::vector<gr_complex>& taps) = 0; + virtual std::vector<gr_complex> taps() const = 0; + virtual float gain() const = 0; + virtual void set_gain(float mu) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/map_bb.h b/gr-digital/include/gnuradio/digital/map_bb.h index e1bbb1d9b5..5d28072ce7 100644 --- a/gr-digital/include/gnuradio/digital/map_bb.h +++ b/gr-digital/include/gnuradio/digital/map_bb.h @@ -27,37 +27,37 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief output[i] = map[input[i]] + * \ingroup symbol_coding_blk + * + * \details + * This block maps an incoming signal to the value in the map. + * The block expects that the incoming signal has a maximum + * value of len(map)-1. + * + * -> output[i] = map[input[i]] + */ +class DIGITAL_API map_bb : virtual public sync_block +{ +public: + // gr::digital::map_bb::sptr + typedef boost::shared_ptr<map_bb> sptr; /*! - * \brief output[i] = map[input[i]] - * \ingroup symbol_coding_blk + * Make a map block. * - * \details - * This block maps an incoming signal to the value in the map. - * The block expects that the incoming signal has a maximum - * value of len(map)-1. - * - * -> output[i] = map[input[i]] + * \param map a vector of integers that maps x to map[x]. */ - class DIGITAL_API map_bb : virtual public sync_block - { - public: - // gr::digital::map_bb::sptr - typedef boost::shared_ptr<map_bb> sptr; - - /*! - * Make a map block. - * - * \param map a vector of integers that maps x to map[x]. - */ - static sptr make(const std::vector<int> &map); - - virtual void set_map(const std::vector<int> &map) = 0; - virtual std::vector<int> map() const = 0; - }; - - } /* namespace digital */ + static sptr make(const std::vector<int>& map); + + virtual void set_map(const std::vector<int>& map) = 0; + virtual std::vector<int> map() const = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_MAP_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/metric_type.h b/gr-digital/include/gnuradio/digital/metric_type.h index c277f01d27..1b94b42727 100644 --- a/gr-digital/include/gnuradio/digital/metric_type.h +++ b/gr-digital/include/gnuradio/digital/metric_type.h @@ -24,14 +24,15 @@ #define INCLUDED_DIGITAL_METRIC_TYPE_H namespace gr { - namespace digital { +namespace digital { - typedef enum { - TRELLIS_EUCLIDEAN = 200, TRELLIS_HARD_SYMBOL, TRELLIS_HARD_BIT - } trellis_metric_type_t; - - } /* namespace digital */ +typedef enum { + TRELLIS_EUCLIDEAN = 200, + TRELLIS_HARD_SYMBOL, + TRELLIS_HARD_BIT +} trellis_metric_type_t; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_METRIC_TYPE_H */ - diff --git a/gr-digital/include/gnuradio/digital/modulate_vector.h b/gr-digital/include/gnuradio/digital/modulate_vector.h index 6083099a89..45e87385a2 100644 --- a/gr-digital/include/gnuradio/digital/modulate_vector.h +++ b/gr-digital/include/gnuradio/digital/modulate_vector.h @@ -26,45 +26,44 @@ #include <gnuradio/types.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Modulate a vector of data and apply a shaping filter. - * - * \p modulator: Pointer to a byte-to-complex modulator block. - * \p data: Vector of bytes to modulate into symbols. - * \p taps: Post-modulation symbol shaping filter taps. - * - * \details - * This function modulates the input vector and applies a - * symbol shaping filter. It is intended for use with the - * corr_est_cc block as the symbol stream to correlate - * against. - * - * Any differential encoding or other data coding must be - * performed on the input vector before this modulation - * operation. - * - * Be aware that the format of the incoming data must match - * the format the modulator block is expecting. GNURadio - * modulator blocks are inconsistent in their data type - * expectations. For instance, cpmmod_bc expects unpacked, - * signed bytes in (-1, 1), while gmsk_mod expects packed, - * unsigned bytes in (0, 1). In other words, the output of - * gmsk_mod given the input vector [0xaa, 0x00] is equivalent - * to the output of cpmmod_bc given the input vector - * [1,255,1,255,1,255,1,255,255,255,255,255,255,255,255,255] - * - * Please check the documentation or source of the modulator - * before using this function. - * - */ - DIGITAL_API std::vector<gr_complex> - modulate_vector_bc(basic_block_sptr modulator, - std::vector<uint8_t> data, - std::vector<float> taps); +/*! + * \brief Modulate a vector of data and apply a shaping filter. + * + * \p modulator: Pointer to a byte-to-complex modulator block. + * \p data: Vector of bytes to modulate into symbols. + * \p taps: Post-modulation symbol shaping filter taps. + * + * \details + * This function modulates the input vector and applies a + * symbol shaping filter. It is intended for use with the + * corr_est_cc block as the symbol stream to correlate + * against. + * + * Any differential encoding or other data coding must be + * performed on the input vector before this modulation + * operation. + * + * Be aware that the format of the incoming data must match + * the format the modulator block is expecting. GNURadio + * modulator blocks are inconsistent in their data type + * expectations. For instance, cpmmod_bc expects unpacked, + * signed bytes in (-1, 1), while gmsk_mod expects packed, + * unsigned bytes in (0, 1). In other words, the output of + * gmsk_mod given the input vector [0xaa, 0x00] is equivalent + * to the output of cpmmod_bc given the input vector + * [1,255,1,255,1,255,1,255,255,255,255,255,255,255,255,255] + * + * Please check the documentation or source of the modulator + * before using this function. + * + */ +DIGITAL_API std::vector<gr_complex> modulate_vector_bc(basic_block_sptr modulator, + std::vector<uint8_t> data, + std::vector<float> taps); - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_MODULATE_VECTOR_H */ diff --git a/gr-digital/include/gnuradio/digital/mpsk_snr_est.h b/gr-digital/include/gnuradio/digital/mpsk_snr_est.h index 0f19ed338f..0bde417209 100644 --- a/gr-digital/include/gnuradio/digital/mpsk_snr_est.h +++ b/gr-digital/include/gnuradio/digital/mpsk_snr_est.h @@ -27,273 +27,262 @@ #include <gnuradio/gr_complex.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief A block for computing SNR of a signal. - * \ingroup measurement_tools_blk - * - * \details - * Below are some ROUGH estimates of what values of SNR each of - * these types of estimators is good for. In general, these offer - * a trade-off between accuracy and performance. +/*! + * \brief A block for computing SNR of a signal. + * \ingroup measurement_tools_blk + * + * \details + * Below are some ROUGH estimates of what values of SNR each of + * these types of estimators is good for. In general, these offer + * a trade-off between accuracy and performance. + * + * \li SNR_EST_SIMPLE: Simple estimator (>= 7 dB) + * \li SNR_EST_SKEW: Skewness-base est (>= 5 dB) + * \li SNR_EST_M2M4: 2nd & 4th moment est (>= 1 dB) + * \li SNR_EST_SVR: SVR-based est (>= 0dB) + */ +typedef enum { + SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB) + SNR_EST_SKEW, // Skewness-base est (>= 5 dB) + SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB) + SNR_EST_SVR // SVR-based est (>= 0dB) +} snr_est_type_t; + +/*! \brief A parent class for SNR estimators, specifically for + * M-PSK signals in AWGN channels. + * \ingroup snr_blk + */ +class DIGITAL_API mpsk_snr_est +{ +protected: + double d_alpha, d_beta; + double d_signal, d_noise; + +public: + /*! Constructor * - * \li SNR_EST_SIMPLE: Simple estimator (>= 7 dB) - * \li SNR_EST_SKEW: Skewness-base est (>= 5 dB) - * \li SNR_EST_M2M4: 2nd & 4th moment est (>= 1 dB) - * \li SNR_EST_SVR: SVR-based est (>= 0dB) - */ - typedef enum { - SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB) - SNR_EST_SKEW, // Skewness-base est (>= 5 dB) - SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB) - SNR_EST_SVR // SVR-based est (>= 0dB) - } snr_est_type_t; - - /*! \brief A parent class for SNR estimators, specifically for - * M-PSK signals in AWGN channels. - * \ingroup snr_blk + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API mpsk_snr_est - { - protected: - double d_alpha, d_beta; - double d_signal, d_noise; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - */ - mpsk_snr_est(double alpha); - virtual ~mpsk_snr_est(); + mpsk_snr_est(double alpha); + virtual ~mpsk_snr_est(); - //! Get the running-average coefficient - double alpha() const; + //! Get the running-average coefficient + double alpha() const; - //! Set the running-average coefficient - void set_alpha(double alpha); + //! Set the running-average coefficient + void set_alpha(double alpha); - //! Update the current registers - virtual int update(int noutput_items, - const gr_complex *input); + //! Update the current registers + virtual int update(int noutput_items, const gr_complex* input); - //! Use the register values to compute a new estimate - virtual double snr(); + //! Use the register values to compute a new estimate + virtual double snr(); - //! Returns the signal power estimate - virtual double signal(); + //! Returns the signal power estimate + virtual double signal(); - //! Returns the noise power estimate - virtual double noise(); - }; + //! Returns the noise power estimate + virtual double noise(); +}; - //! \brief SNR Estimator using simple mean/variance estimates. - /*! \ingroup snr_blk +//! \brief SNR Estimator using simple mean/variance estimates. +/*! \ingroup snr_blk + * + * A very simple SNR estimator that just uses mean and variance + * estimates of an M-PSK constellation. This estimator is quick + * and cheap and accurate for high SNR (above 7 dB or so) but + * quickly starts to overestimate the SNR at low SNR. + */ +class DIGITAL_API mpsk_snr_est_simple : public mpsk_snr_est +{ +private: + double d_y1, d_y2; + double d_counter; + +public: + /*! Constructor * - * A very simple SNR estimator that just uses mean and variance - * estimates of an M-PSK constellation. This estimator is quick - * and cheap and accurate for high SNR (above 7 dB or so) but - * quickly starts to overestimate the SNR at low SNR. + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API mpsk_snr_est_simple : - public mpsk_snr_est - { - private: - double d_y1, d_y2; - double d_counter; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - */ - mpsk_snr_est_simple(double alpha); - ~mpsk_snr_est_simple() {} - - int update(int noutput_items, - const gr_complex *input); - double snr(); - }; - - - //! \brief SNR Estimator using skewness correction. - /*! \ingroup snr_blk - * - * This is an estimator that came from a discussion between Tom - * Rondeau and fred harris with no known paper reference. The - * idea is that at low SNR, the variance estimations will be - * affected because of fold-over around the decision boundaries, - * which results in a skewness to the samples. We estimate the - * skewness and use this as a correcting term. + mpsk_snr_est_simple(double alpha); + ~mpsk_snr_est_simple() {} + + int update(int noutput_items, const gr_complex* input); + double snr(); +}; + + +//! \brief SNR Estimator using skewness correction. +/*! \ingroup snr_blk + * + * This is an estimator that came from a discussion between Tom + * Rondeau and fred harris with no known paper reference. The + * idea is that at low SNR, the variance estimations will be + * affected because of fold-over around the decision boundaries, + * which results in a skewness to the samples. We estimate the + * skewness and use this as a correcting term. + * + * This algorithm only appears to work well for BPSK signals. + */ +class DIGITAL_API mpsk_snr_est_skew : public mpsk_snr_est +{ +private: + double d_y1, d_y2, d_y3; + double d_counter; + +public: + /*! Constructor * - * This algorithm only appears to work well for BPSK signals. + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API mpsk_snr_est_skew : - public mpsk_snr_est - { - private: - double d_y1, d_y2, d_y3; - double d_counter; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - */ - mpsk_snr_est_skew(double alpha); - ~mpsk_snr_est_skew() {} - - int update(int noutput_items, - const gr_complex *input); - double snr(); - }; - - - //! \brief SNR Estimator using 2nd and 4th-order moments. - /*! \ingroup snr_blk - * - * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th - * (M4) order moments. This estimator uses knowledge of the - * kurtosis of the signal (\f$k_a)\f$ and noise (\f$k_w\f$) to make its - * estimation. We use Beaulieu's approximations here to M-PSK - * signals and AWGN channels such that \f$k_a=1\f$ and \f$k_w=2\f$. These - * approximations significantly reduce the complexity of the - * calculations (and computations) required. + mpsk_snr_est_skew(double alpha); + ~mpsk_snr_est_skew() {} + + int update(int noutput_items, const gr_complex* input); + double snr(); +}; + + +//! \brief SNR Estimator using 2nd and 4th-order moments. +/*! \ingroup snr_blk + * + * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th + * (M4) order moments. This estimator uses knowledge of the + * kurtosis of the signal (\f$k_a)\f$ and noise (\f$k_w\f$) to make its + * estimation. We use Beaulieu's approximations here to M-PSK + * signals and AWGN channels such that \f$k_a=1\f$ and \f$k_w=2\f$. These + * approximations significantly reduce the complexity of the + * calculations (and computations) required. + * + * Reference: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ +class DIGITAL_API mpsk_snr_est_m2m4 : public mpsk_snr_est +{ +private: + double d_y1, d_y2; + +public: + /*! Constructor * - * Reference: - * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR - * estimation techniques for the AWGN channel," IEEE - * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API mpsk_snr_est_m2m4 : - public mpsk_snr_est - { - private: - double d_y1, d_y2; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - */ - mpsk_snr_est_m2m4(double alpha); - ~mpsk_snr_est_m2m4() {} - - int update(int noutput_items, - const gr_complex *input); - double snr(); - }; - - - //! \brief SNR Estimator using 2nd and 4th-order moments. - /*! \ingroup snr_blk - * - * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th - * (M4) order moments. This estimator uses knowledge of the - * kurtosis of the signal (k_a) and noise (k_w) to make its - * estimation. In this case, you can set your own estimations for - * k_a and k_w, the kurtosis of the signal and noise, to fit this - * estimation better to your signal and channel conditions. - * - * A word of warning: this estimator has not been fully tested or - * proved with any amount of rigor. The estimation for M4 in - * particular might be ignoring effectf of when k_a and k_w are - * different. Use this estimator with caution and a copy of the - * reference on hand. - * - * The digital_mpsk_snr_est_m2m4 assumes k_a and k_w to simplify - * the computations for M-PSK and AWGN channels. Use that - * estimator unless you have a way to guess or estimate these - * values here. - * - * Original paper: - * R. Matzner, "An SNR estimation algorithm for complex baseband - * signal using higher order statistics," Facta Universitatis - * (Nis), no. 6, pp. 41-52, 1993. + mpsk_snr_est_m2m4(double alpha); + ~mpsk_snr_est_m2m4() {} + + int update(int noutput_items, const gr_complex* input); + double snr(); +}; + + +//! \brief SNR Estimator using 2nd and 4th-order moments. +/*! \ingroup snr_blk + * + * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th + * (M4) order moments. This estimator uses knowledge of the + * kurtosis of the signal (k_a) and noise (k_w) to make its + * estimation. In this case, you can set your own estimations for + * k_a and k_w, the kurtosis of the signal and noise, to fit this + * estimation better to your signal and channel conditions. + * + * A word of warning: this estimator has not been fully tested or + * proved with any amount of rigor. The estimation for M4 in + * particular might be ignoring effectf of when k_a and k_w are + * different. Use this estimator with caution and a copy of the + * reference on hand. + * + * The digital_mpsk_snr_est_m2m4 assumes k_a and k_w to simplify + * the computations for M-PSK and AWGN channels. Use that + * estimator unless you have a way to guess or estimate these + * values here. + * + * Original paper: + * R. Matzner, "An SNR estimation algorithm for complex baseband + * signal using higher order statistics," Facta Universitatis + * (Nis), no. 6, pp. 41-52, 1993. + * + * Reference used in derivation: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ +class DIGITAL_API snr_est_m2m4 : public mpsk_snr_est +{ +private: + double d_y1, d_y2; + double d_ka, d_kw; + +public: + /*! Constructor * - * Reference used in derivation: - * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR - * estimation techniques for the AWGN channel," IEEE - * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. + * \param ka: estimate of the signal kurtosis (1 for PSK) + * \param kw: estimate of the channel noise kurtosis (2 for AWGN) */ - class DIGITAL_API snr_est_m2m4 : - public mpsk_snr_est - { - private: - double d_y1, d_y2; - double d_ka, d_kw; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - * \param ka: estimate of the signal kurtosis (1 for PSK) - * \param kw: estimate of the channel noise kurtosis (2 for AWGN) - */ - snr_est_m2m4(double alpha, double ka, double kw); - ~snr_est_m2m4() {} - - int update(int noutput_items, - const gr_complex *input); - double snr(); - }; - - - //! \brief Signal-to-Variation Ratio SNR Estimator. - /*! \ingroup snr_blk - * - * This estimator actually comes from an SNR estimator for M-PSK - * signals in fading channels, but this implementation is - * specifically for AWGN channels. The math was simplified to - * assume a signal and noise kurtosis (\f$k_a\f$ and \f$k_w\f$) for M-PSK - * signals in AWGN. These approximations significantly reduce the - * complexity of the calculations (and computations) required. - * - * Original paper: - * A. L. Brandao, L. B. Lopes, and D. C. McLernon, "In-service - * monitoring of multipath delay and cochannel interference for - * indoor mobile communication systems," Proc. IEEE - * Int. Conf. Communications, vol. 3, pp. 1458-1462, May 1994. + snr_est_m2m4(double alpha, double ka, double kw); + ~snr_est_m2m4() {} + + int update(int noutput_items, const gr_complex* input); + double snr(); +}; + + +//! \brief Signal-to-Variation Ratio SNR Estimator. +/*! \ingroup snr_blk + * + * This estimator actually comes from an SNR estimator for M-PSK + * signals in fading channels, but this implementation is + * specifically for AWGN channels. The math was simplified to + * assume a signal and noise kurtosis (\f$k_a\f$ and \f$k_w\f$) for M-PSK + * signals in AWGN. These approximations significantly reduce the + * complexity of the calculations (and computations) required. + * + * Original paper: + * A. L. Brandao, L. B. Lopes, and D. C. McLernon, "In-service + * monitoring of multipath delay and cochannel interference for + * indoor mobile communication systems," Proc. IEEE + * Int. Conf. Communications, vol. 3, pp. 1458-1462, May 1994. + * + * Reference: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ +class DIGITAL_API mpsk_snr_est_svr : public mpsk_snr_est +{ +private: + double d_y1, d_y2; + +public: + /*! Constructor * - * Reference: - * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR - * estimation techniques for the AWGN channel," IEEE - * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + * Parameters: + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API mpsk_snr_est_svr : - public mpsk_snr_est - { - private: - double d_y1, d_y2; - - public: - /*! Constructor - * - * Parameters: - * \param alpha: the update rate of internal running average - * calculations. - */ - mpsk_snr_est_svr(double alpha); - ~mpsk_snr_est_svr() {} - - int update(int noutput_items, - const gr_complex *input); - double snr(); - }; - - } /* namespace digital */ + mpsk_snr_est_svr(double alpha); + ~mpsk_snr_est_svr() {} + + int update(int noutput_items, const gr_complex* input); + double snr(); +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_MPSK_SNR_EST_H */ diff --git a/gr-digital/include/gnuradio/digital/mpsk_snr_est_cc.h b/gr-digital/include/gnuradio/digital/mpsk_snr_est_cc.h index 41a649cf58..8bab217b35 100644 --- a/gr-digital/include/gnuradio/digital/mpsk_snr_est_cc.h +++ b/gr-digital/include/gnuradio/digital/mpsk_snr_est_cc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -28,69 +28,67 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief A block for computing SNR of a signal. - * \ingroup measurement_tools_blk - * - * \details - * This block can be used to monitor and retrieve estimations of - * the signal SNR. It is designed to work in a flowgraph and - * passes all incoming data along to its output. +/*! + * \brief A block for computing SNR of a signal. + * \ingroup measurement_tools_blk + * + * \details + * This block can be used to monitor and retrieve estimations of + * the signal SNR. It is designed to work in a flowgraph and + * passes all incoming data along to its output. + * + * The block is designed for use with M-PSK signals + * especially. The type of estimator is specified as the \p type + * parameter in the constructor. The estimators tend to trade off + * performance for accuracy, although experimentation should be + * done to figure out the right approach for a given + * implementation. Further, the current set of estimators are + * designed and proven theoretically under AWGN conditions; some + * amount of error should be assumed and/or estimated for real + * channel conditions. + */ +class DIGITAL_API mpsk_snr_est_cc : virtual public sync_block +{ +public: + // gr::digital::mpsk_snr_est_cc::sptr + typedef boost::shared_ptr<mpsk_snr_est_cc> sptr; + + /*! Factory function returning shared pointer of this class * - * The block is designed for use with M-PSK signals - * especially. The type of estimator is specified as the \p type - * parameter in the constructor. The estimators tend to trade off - * performance for accuracy, although experimentation should be - * done to figure out the right approach for a given - * implementation. Further, the current set of estimators are - * designed and proven theoretically under AWGN conditions; some - * amount of error should be assumed and/or estimated for real - * channel conditions. + * \param type: the type of estimator to use gr::digital::snr_est_type_t + * "snr_est_type_t" for details about the available types + * \param tag_nsamples: after this many samples, a tag containing + * the SNR (key='snr') will be sent + * \param alpha: the update rate of internal running average + * calculations */ - class DIGITAL_API mpsk_snr_est_cc : virtual public sync_block - { - public: - // gr::digital::mpsk_snr_est_cc::sptr - typedef boost::shared_ptr<mpsk_snr_est_cc> sptr; - - /*! Factory function returning shared pointer of this class - * - * \param type: the type of estimator to use gr::digital::snr_est_type_t - * "snr_est_type_t" for details about the available types - * \param tag_nsamples: after this many samples, a tag containing - * the SNR (key='snr') will be sent - * \param alpha: the update rate of internal running average - * calculations - */ - static sptr make(snr_est_type_t type, - int tag_nsamples=10000, - double alpha=0.001); + static sptr make(snr_est_type_t type, int tag_nsamples = 10000, double alpha = 0.001); - //! Return the estimated signal-to-noise ratio in decibels - virtual double snr() = 0; + //! Return the estimated signal-to-noise ratio in decibels + virtual double snr() = 0; - //! Return the type of estimator in use - virtual snr_est_type_t type() const = 0; + //! Return the type of estimator in use + virtual snr_est_type_t type() const = 0; - //! Return how many samples between SNR tags - virtual int tag_nsample() const = 0; + //! Return how many samples between SNR tags + virtual int tag_nsample() const = 0; - //! Get the running-average coefficient - virtual double alpha() const = 0; + //! Get the running-average coefficient + virtual double alpha() const = 0; - //! Set type of estimator to use - virtual void set_type(snr_est_type_t t) = 0; + //! Set type of estimator to use + virtual void set_type(snr_est_type_t t) = 0; - //! Set the number of samples between SNR tags - virtual void set_tag_nsample(int n) = 0; + //! Set the number of samples between SNR tags + virtual void set_tag_nsample(int n) = 0; - //! Set the running-average coefficient - virtual void set_alpha(double alpha) = 0; - }; + //! Set the running-average coefficient + virtual void set_alpha(double alpha) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_MPSK_SNR_EST_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h b/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h index 770bd91da1..858bb7ca2b 100644 --- a/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h +++ b/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h @@ -27,50 +27,49 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief MSK/GMSK timing recovery + * \ingroup synchronizers_blk + * + * This block performs timing synchronization on CPM modulations using a + * fourth-order nonlinearity feedback method which is non-data-aided. The + * block does not require prior phase synchronization but is relatively + * sensitive to frequency offset (keep offset to 0.1x symbol rate). + * + * For details on the algorithm, see: + * A.N. D'Andrea, U. Mengali, R. Reggiannini: A digital approach to clock + * recovery in generalized minimum shift keying. IEEE Transactions on + * Vehicular Technology, Vol. 39, Issue 3. + */ +class DIGITAL_API msk_timing_recovery_cc : virtual public gr::block +{ +public: + typedef boost::shared_ptr<msk_timing_recovery_cc> sptr; /*! - * \brief MSK/GMSK timing recovery - * \ingroup synchronizers_blk + * \brief Make an MSK timing recovery block. * - * This block performs timing synchronization on CPM modulations using a - * fourth-order nonlinearity feedback method which is non-data-aided. The - * block does not require prior phase synchronization but is relatively - * sensitive to frequency offset (keep offset to 0.1x symbol rate). + * \param sps: Samples per symbol + * \param gain: Loop gain of timing error filter (try 0.05) + * \param limit: Relative limit of timing error (try 0.1 for 10% error max) + * \param osps: Output samples per symbol * - * For details on the algorithm, see: - * A.N. D'Andrea, U. Mengali, R. Reggiannini: A digital approach to clock - * recovery in generalized minimum shift keying. IEEE Transactions on - * Vehicular Technology, Vol. 39, Issue 3. */ - class DIGITAL_API msk_timing_recovery_cc : virtual public gr::block - { - public: - typedef boost::shared_ptr<msk_timing_recovery_cc> sptr; - - /*! - * \brief Make an MSK timing recovery block. - * - * \param sps: Samples per symbol - * \param gain: Loop gain of timing error filter (try 0.05) - * \param limit: Relative limit of timing error (try 0.1 for 10% error max) - * \param osps: Output samples per symbol - * - */ - static sptr make(float sps, float gain, float limit, int osps); + static sptr make(float sps, float gain, float limit, int osps); - virtual void set_gain(float gain)=0; - virtual float get_gain(void)=0; + virtual void set_gain(float gain) = 0; + virtual float get_gain(void) = 0; - virtual void set_limit(float limit)=0; - virtual float get_limit(void)=0; + virtual void set_limit(float limit) = 0; + virtual float get_limit(void) = 0; - virtual void set_sps(float sps)=0; - virtual float get_sps(void)=0; - }; + virtual void set_sps(float sps) = 0; + virtual float get_sps(void) = 0; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_carrier_allocator_cvc.h b/gr-digital/include/gnuradio/digital/ofdm_carrier_allocator_cvc.h index 6a15037b43..f7d7658d08 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_carrier_allocator_cvc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_carrier_allocator_cvc.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2013 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, @@ -28,92 +28,93 @@ #include <gnuradio/tagged_stream_block.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Create frequency domain OFDM symbols from complex values, add pilots. - * \ingroup ofdm_blk - * - * \details - * This block turns a stream of complex, scalar modulation symbols into vectors - * which are the input for an IFFT in an OFDM transmitter. It also supports the - * possibility of placing pilot symbols onto the carriers. - * - * The carriers can be allocated freely, if a carrier is not allocated, it is set - * to zero. This allows doing OFDMA-style carrier allocations. - * - * Input: A tagged stream of complex scalars. The first item must have a tag - * containing the number of complex symbols in this frame. - * Output: A tagged stream of complex vectors of length fft_len. This can directly - * be connected to an FFT block. Make sure to set this block to 'reverse' - * for the IFFT. If \p output_is_shifted is true, the FFT block must activate - * FFT shifting, otherwise, set shifting to false. If given, sync words are - * prepended to the output. Note that sync words are prepended verbatim, - * make sure they are shifted (or not). - * - * Carrier indexes are always such that index 0 is the DC carrier (note: you should - * not allocate this carrier). The carriers below the DC carrier are either indexed - * with negative numbers, or with indexes larger than \p fft_len/2. Index -1 and index - * \p fft_len-1 both identify the carrier below the DC carrier. - * - * There are some basic checks in place during initialization which check that the - * carrier allocation table is valid. However, it is possible to overwrite data symbols - * with pilot symbols, or provide a carrier allocation that has mismatching pilot symbol - * positions and -values. - * - * Tags are propagated such that a tag on an incoming complex symbol is mapped to the - * corresponding OFDM symbol. There is one exception: If a tag is on the first OFDM - * symbol, it is assumed that this tag should stay there, so it is moved to the front - * even if a sync word is included (any other tags will never be attached to the - * sync word). This allows tags to control the transmit timing to pass through in the - * correct position. - */ - class DIGITAL_API ofdm_carrier_allocator_cvc : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<ofdm_carrier_allocator_cvc> sptr; +/*! + * \brief Create frequency domain OFDM symbols from complex values, add pilots. + * \ingroup ofdm_blk + * + * \details + * This block turns a stream of complex, scalar modulation symbols into vectors + * which are the input for an IFFT in an OFDM transmitter. It also supports the + * possibility of placing pilot symbols onto the carriers. + * + * The carriers can be allocated freely, if a carrier is not allocated, it is set + * to zero. This allows doing OFDMA-style carrier allocations. + * + * Input: A tagged stream of complex scalars. The first item must have a tag + * containing the number of complex symbols in this frame. + * Output: A tagged stream of complex vectors of length fft_len. This can directly + * be connected to an FFT block. Make sure to set this block to 'reverse' + * for the IFFT. If \p output_is_shifted is true, the FFT block must activate + * FFT shifting, otherwise, set shifting to false. If given, sync words are + * prepended to the output. Note that sync words are prepended verbatim, + * make sure they are shifted (or not). + * + * Carrier indexes are always such that index 0 is the DC carrier (note: you should + * not allocate this carrier). The carriers below the DC carrier are either indexed + * with negative numbers, or with indexes larger than \p fft_len/2. Index -1 and index + * \p fft_len-1 both identify the carrier below the DC carrier. + * + * There are some basic checks in place during initialization which check that the + * carrier allocation table is valid. However, it is possible to overwrite data symbols + * with pilot symbols, or provide a carrier allocation that has mismatching pilot symbol + * positions and -values. + * + * Tags are propagated such that a tag on an incoming complex symbol is mapped to the + * corresponding OFDM symbol. There is one exception: If a tag is on the first OFDM + * symbol, it is assumed that this tag should stay there, so it is moved to the front + * even if a sync word is included (any other tags will never be attached to the + * sync word). This allows tags to control the transmit timing to pass through in the + * correct position. + */ +class DIGITAL_API ofdm_carrier_allocator_cvc : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<ofdm_carrier_allocator_cvc> sptr; - virtual std::string len_tag_key() = 0; - virtual const int fft_len() = 0; - virtual std::vector<std::vector<int> > occupied_carriers() = 0; + virtual std::string len_tag_key() = 0; + virtual const int fft_len() = 0; + virtual std::vector<std::vector<int>> occupied_carriers() = 0; - /* - * \param fft_len FFT length, is also the maximum width of the OFDM symbols, the - * output vector size and maximum value for elements in - * \p occupied_carriers and \p pilot_carriers. - * \param occupied_carriers A vector of vectors of indexes. Example: if - * occupied_carriers = ((1, 2, 3), (1, 2, 4)), the first - * three input symbols will be mapped to carriers 1, 2 - * and 3. After that, a new OFDM symbol is started. The next - * three input symbols will be placed onto carriers 1, 2 - * and 4 of the second OFDM symbol. The allocation then - * starts from the beginning. - * Order matters! The first input symbol is always mapped - * onto occupied_carriers[0][0]. - * \param pilot_carriers The position of the pilot symbols. Same as occupied_carriers, - * but the actual symbols are taken from pilot_symbols instead - * of the input stream. - * \param pilot_symbols The pilot symbols which are placed onto the pilot carriers. - * pilot_symbols[0][0] is placed onto the first OFDM symbol, on - * carrier index pilot_carriers[0][0] etc. - * \param sync_words OFDM symbols that are prepended to the OFDM frame (usually for - * synchronisation purposes, e.g. OFDM symbols with every second - * sub-carrier being idle). Is a vector of complex vectors of length - * \p fft_len - * \param len_tag_key The key of the tag identifying the length of the input packet. - * \param output_is_shifted whether to 'fftshift' the output OFDM symbols. If used, the followup FFT should be instantaited such that it knows that the input is shifted. Default is true. - */ - static sptr make( - int fft_len, - const std::vector<std::vector<int> > &occupied_carriers, - const std::vector<std::vector<int> > &pilot_carriers, - const std::vector<std::vector<gr_complex> > &pilot_symbols, - const std::vector<std::vector<gr_complex> > &sync_words, - const std::string &len_tag_key = "packet_len", - const bool output_is_shifted=true); - }; + /* + * \param fft_len FFT length, is also the maximum width of the OFDM symbols, the + * output vector size and maximum value for elements in + * \p occupied_carriers and \p pilot_carriers. + * \param occupied_carriers A vector of vectors of indexes. Example: if + * occupied_carriers = ((1, 2, 3), (1, 2, 4)), the first + * three input symbols will be mapped to carriers 1, 2 + * and 3. After that, a new OFDM symbol is started. The next + * three input symbols will be placed onto carriers 1, 2 + * and 4 of the second OFDM symbol. The allocation then + * starts from the beginning. + * Order matters! The first input symbol is always mapped + * onto occupied_carriers[0][0]. + * \param pilot_carriers The position of the pilot symbols. Same as occupied_carriers, + * but the actual symbols are taken from pilot_symbols instead + * of the input stream. + * \param pilot_symbols The pilot symbols which are placed onto the pilot carriers. + * pilot_symbols[0][0] is placed onto the first OFDM symbol, on + * carrier index pilot_carriers[0][0] etc. + * \param sync_words OFDM symbols that are prepended to the OFDM frame (usually for + * synchronisation purposes, e.g. OFDM symbols with every second + * sub-carrier being idle). Is a vector of complex vectors of length + * \p fft_len + * \param len_tag_key The key of the tag identifying the length of the input packet. + * \param output_is_shifted whether to 'fftshift' the output OFDM symbols. If used, + * the followup FFT should be instantaited such that it knows that the input is + * shifted. Default is true. + */ + static sptr make(int fft_len, + const std::vector<std::vector<int>>& occupied_carriers, + const std::vector<std::vector<int>>& pilot_carriers, + const std::vector<std::vector<gr_complex>>& pilot_symbols, + const std::vector<std::vector<gr_complex>>& sync_words, + const std::string& len_tag_key = "packet_len", + const bool output_is_shifted = true); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H */ diff --git a/gr-digital/include/gnuradio/digital/ofdm_chanest_vcvc.h b/gr-digital/include/gnuradio/digital/ofdm_chanest_vcvc.h index 4ccc3896c9..248ad8c0eb 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_chanest_vcvc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_chanest_vcvc.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2013 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, @@ -27,71 +27,66 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Estimate channel and coarse frequency offset for OFDM from preambles + * \ingroup ofdm_blk + * \ingroup syncronizers_blk + * + * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected + * to be synchronisation symbols, which are used to estimate the coarse freq offset + * and the initial equalizer taps (these symbols are removed from the stream). + * The following \p n_data_symbols are passed through unmodified (the actual + * equalisation must be done elsewhere). Output: The data symbols, without the + * synchronisation symbols. The first data symbol passed through has two tags: + * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of + * carriers, and 'ofdm_sync_eq_taps' (complex vector). Any tags attached to the + * synchronisation symbols are attached to the first data symbol. All other tags are + * propagated as expected. + * + * Note: The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest + * is not. + * + * This block assumes the frequency offset is even (i.e. an integer multiple of 2). + * + * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for + * OFDM", Communications, IEEE Transactions on, 1997. [2] K.D. Kammeyer, + * "Nachrichtenuebertragung," Chapter. 16.3.2. + */ +class DIGITAL_API ofdm_chanest_vcvc : virtual public block +{ +public: + typedef boost::shared_ptr<ofdm_chanest_vcvc> sptr; /*! - * \brief Estimate channel and coarse frequency offset for OFDM from preambles - * \ingroup ofdm_blk - * \ingroup syncronizers_blk - * - * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected - * to be synchronisation symbols, which are used to estimate the coarse freq offset - * and the initial equalizer taps (these symbols are removed from the stream). - * The following \p n_data_symbols are passed through unmodified (the actual equalisation - * must be done elsewhere). - * Output: The data symbols, without the synchronisation symbols. - * The first data symbol passed through has two tags: - * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers, - * and 'ofdm_sync_eq_taps' (complex vector). - * Any tags attached to the synchronisation symbols are attached to the first data - * symbol. All other tags are propagated as expected. - * - * Note: The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest is not. - * - * This block assumes the frequency offset is even (i.e. an integer multiple of 2). - * - * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM", - * Communications, IEEE Transactions on, 1997. - * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2. + * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its + * length must be the FFT length. For Schmidl & Cox synchronisation, every second + * sub-carrier has to be zero. \param sync_symbol2 Second synchronisation symbol in + * the frequency domain. Must be equal to the FFT length, or zero length if only one + * synchronisation symbol is used. Using this symbol is how synchronisation is + * described in [1]. Leaving this empty forces us to interpolate the equalizer taps. + * If you are using an unusual sub-carrier configuration (e.g. + * because of OFDMA), this sync symbol is used to identify the active sub-carriers. If + * you only have one synchronisation symbol, set the active sub-carriers to a non-zero + * value in here, and also set \p force_one_sync_symbol parameter + * to true. \param n_data_symbols The number of data symbols following each set of + * synchronisation symbols. Must be at least 1. \param eq_noise_red_len If non-zero, + * noise reduction for the equalizer taps is done according to [2]. In this case, it + * is the channel influence time in number of samples. A good value is usually the + * length of the cyclic prefix. \param max_carr_offset Limit the number of + * sub-carriers the frequency offset can maximally be. Leave this zero to try all + * possibilities. \param force_one_sync_symbol See \p sync_symbol2. */ - class DIGITAL_API ofdm_chanest_vcvc : virtual public block - { - public: - typedef boost::shared_ptr<ofdm_chanest_vcvc> sptr; + static sptr make(const std::vector<gr_complex>& sync_symbol1, + const std::vector<gr_complex>& sync_symbol2, + int n_data_symbols, + int eq_noise_red_len = 0, + int max_carr_offset = -1, + bool force_one_sync_symbol = false); +}; - /*! - * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its length must be - * the FFT length. For Schmidl & Cox synchronisation, every second sub-carrier - * has to be zero. - * \param sync_symbol2 Second synchronisation symbol in the frequency domain. Must be equal to - * the FFT length, or zero length if only one synchronisation symbol is used. - * Using this symbol is how synchronisation is described in [1]. Leaving this - * empty forces us to interpolate the equalizer taps. - * If you are using an unusual sub-carrier configuration (e.g. because of OFDMA), - * this sync symbol is used to identify the active sub-carriers. If you only - * have one synchronisation symbol, set the active sub-carriers to a non-zero - * value in here, and also set \p force_one_sync_symbol parameter to true. - * \param n_data_symbols The number of data symbols following each set of synchronisation symbols. - * Must be at least 1. - * \param eq_noise_red_len If non-zero, noise reduction for the equalizer taps is done according - * to [2]. In this case, it is the channel influence time in number of - * samples. A good value is usually the length of the cyclic prefix. - * \param max_carr_offset Limit the number of sub-carriers the frequency offset can maximally be. - * Leave this zero to try all possibilities. - * \param force_one_sync_symbol See \p sync_symbol2. - */ - static sptr make( - const std::vector<gr_complex> &sync_symbol1, - const std::vector<gr_complex> &sync_symbol2, - int n_data_symbols, - int eq_noise_red_len=0, - int max_carr_offset=-1, - bool force_one_sync_symbol=false - ); - }; - - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_cyclic_prefixer.h b/gr-digital/include/gnuradio/digital/ofdm_cyclic_prefixer.h index 70d37a6bc1..f0f0d16097 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_cyclic_prefixer.h +++ b/gr-digital/include/gnuradio/digital/ofdm_cyclic_prefixer.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2013 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, @@ -27,46 +27,43 @@ #include <gnuradio/tagged_stream_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Adds a cyclic prefix and performs pulse shaping on OFDM symbols. + * \ingroup ofdm_blk + * + * \details + * Input: OFDM symbols (in the time domain, i.e. after the IFFT). Optionally, + * entire frames can be processed. In this case, \p len_tag_key must be + * specified which holds the key of the tag that denotes how + * many OFDM symbols are in a frame. + * Output: A stream of (scalar) complex symbols, which include the cyclic prefix + * and the pulse shaping. + * Note: If complete frames are processed, and \p rolloff_len is greater + * than zero, the final OFDM symbol is followed by the delay line of + * the pulse shaping. + * + * The pulse shape is a raised cosine in the time domain. + */ +class DIGITAL_API ofdm_cyclic_prefixer : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<ofdm_cyclic_prefixer> sptr; /*! - * \brief Adds a cyclic prefix and performs pulse shaping on OFDM symbols. - * \ingroup ofdm_blk - * - * \details - * Input: OFDM symbols (in the time domain, i.e. after the IFFT). Optionally, - * entire frames can be processed. In this case, \p len_tag_key must be - * specified which holds the key of the tag that denotes how - * many OFDM symbols are in a frame. - * Output: A stream of (scalar) complex symbols, which include the cyclic prefix - * and the pulse shaping. - * Note: If complete frames are processed, and \p rolloff_len is greater - * than zero, the final OFDM symbol is followed by the delay line of - * the pulse shaping. - * - * The pulse shape is a raised cosine in the time domain. + * \param input_size FFT length (i.e. length of the OFDM symbols) + * \param output_size FFT length + cyclic prefix length (in samples) + * \param rolloff_len Length of the rolloff flank in samples + * \param len_tag_key For framed processing the key of the length tag */ - class DIGITAL_API ofdm_cyclic_prefixer : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<ofdm_cyclic_prefixer> sptr; + static sptr make(size_t input_size, + size_t output_size, + int rolloff_len = 0, + const std::string& len_tag_key = ""); +}; - /*! - * \param input_size FFT length (i.e. length of the OFDM symbols) - * \param output_size FFT length + cyclic prefix length (in samples) - * \param rolloff_len Length of the rolloff flank in samples - * \param len_tag_key For framed processing the key of the length tag - */ - static sptr make( - size_t input_size, - size_t output_size, - int rolloff_len=0, - const std::string &len_tag_key="" - ); - }; - - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_equalizer_base.h b/gr-digital/include/gnuradio/digital/ofdm_equalizer_base.h index 85443da8f2..392f576a60 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_equalizer_base.h +++ b/gr-digital/include/gnuradio/digital/ofdm_equalizer_base.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -28,81 +28,81 @@ #include <boost/enable_shared_from_this.hpp> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Base class for implementation details of frequency-domain OFDM equalizers. - * \ingroup ofdm_blk - * \ingroup equalizers_blk - */ - class DIGITAL_API ofdm_equalizer_base - : public boost::enable_shared_from_this<ofdm_equalizer_base> - { - protected: - int d_fft_len; +/*! + * \brief Base class for implementation details of frequency-domain OFDM equalizers. + * \ingroup ofdm_blk + * \ingroup equalizers_blk + */ +class DIGITAL_API ofdm_equalizer_base + : public boost::enable_shared_from_this<ofdm_equalizer_base> +{ +protected: + int d_fft_len; - public: - typedef boost::shared_ptr<ofdm_equalizer_base> sptr; +public: + typedef boost::shared_ptr<ofdm_equalizer_base> sptr; - ofdm_equalizer_base(int fft_len); - virtual ~ofdm_equalizer_base(); + ofdm_equalizer_base(int fft_len); + virtual ~ofdm_equalizer_base(); - //! Reset the channel information state knowledge - virtual void reset() = 0; - //! Run the actual equalization - virtual void equalize( - gr_complex *frame, - int n_sym, - const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), - const std::vector<tag_t> &tags = std::vector<tag_t>()) = 0; - //! Return the current channel state - virtual void get_channel_state(std::vector<gr_complex> &taps) = 0; - int fft_len() { return d_fft_len; }; - sptr base() { return shared_from_this(); }; - }; + //! Reset the channel information state knowledge + virtual void reset() = 0; + //! Run the actual equalization + virtual void + equalize(gr_complex* frame, + int n_sym, + const std::vector<gr_complex>& initial_taps = std::vector<gr_complex>(), + const std::vector<tag_t>& tags = std::vector<tag_t>()) = 0; + //! Return the current channel state + virtual void get_channel_state(std::vector<gr_complex>& taps) = 0; + int fft_len() { return d_fft_len; }; + sptr base() { return shared_from_this(); }; +}; - /* \brief Base class for implementation details of 1-dimensional OFDM FDEs which use pilot tones. - * \ingroup digital - * - */ - class DIGITAL_API ofdm_equalizer_1d_pilots : public ofdm_equalizer_base - { - protected: - //! If \p d_occupied_carriers[k][l] is true, symbol k, carrier l is carrying data. - // (this is a different format than occupied_carriers!) - std::vector<bool> d_occupied_carriers; - //! If \p d_pilot_carriers[k][l] is true, symbol k, carrier l is carrying data. - // (this is a different format than pilot_carriers!) - std::vector<std::vector<bool> > d_pilot_carriers; - //! If \p d_pilot_carriers[k][l] is true, d_pilot_symbols[k][l] is its tx'd value. - // (this is a different format than pilot_symbols!) - std::vector<std::vector<gr_complex> > d_pilot_symbols; - //! In case the frame doesn't begin with OFDM symbol 0, this is the index of the first symbol - int d_symbols_skipped; - //! The current position in the set of pilot symbols - int d_pilot_carr_set; - //! Vector of length d_fft_len saving the current channel state (on the occupied carriers) - std::vector<gr_complex> d_channel_state; +/* \brief Base class for implementation details of 1-dimensional OFDM FDEs which use pilot + * tones. \ingroup digital + * + */ +class DIGITAL_API ofdm_equalizer_1d_pilots : public ofdm_equalizer_base +{ +protected: + //! If \p d_occupied_carriers[k][l] is true, symbol k, carrier l is carrying data. + // (this is a different format than occupied_carriers!) + std::vector<bool> d_occupied_carriers; + //! If \p d_pilot_carriers[k][l] is true, symbol k, carrier l is carrying data. + // (this is a different format than pilot_carriers!) + std::vector<std::vector<bool>> d_pilot_carriers; + //! If \p d_pilot_carriers[k][l] is true, d_pilot_symbols[k][l] is its tx'd value. + // (this is a different format than pilot_symbols!) + std::vector<std::vector<gr_complex>> d_pilot_symbols; + //! In case the frame doesn't begin with OFDM symbol 0, this is the index of the first + //! symbol + int d_symbols_skipped; + //! The current position in the set of pilot symbols + int d_pilot_carr_set; + //! Vector of length d_fft_len saving the current channel state (on the occupied + //! carriers) + std::vector<gr_complex> d_channel_state; - public: - typedef boost::shared_ptr<ofdm_equalizer_1d_pilots> sptr; +public: + typedef boost::shared_ptr<ofdm_equalizer_1d_pilots> sptr; - ofdm_equalizer_1d_pilots( - int fft_len, - const std::vector<std::vector<int> > &occupied_carriers, - const std::vector<std::vector<int> > &pilot_carriers, - const std::vector<std::vector<gr_complex> > &pilot_symbols, - int symbols_skipped, - bool input_is_shifted); - ~ofdm_equalizer_1d_pilots(); + ofdm_equalizer_1d_pilots(int fft_len, + const std::vector<std::vector<int>>& occupied_carriers, + const std::vector<std::vector<int>>& pilot_carriers, + const std::vector<std::vector<gr_complex>>& pilot_symbols, + int symbols_skipped, + bool input_is_shifted); + ~ofdm_equalizer_1d_pilots(); - void reset(); - void get_channel_state(std::vector<gr_complex> &taps); - }; + void reset(); + void get_channel_state(std::vector<gr_complex>& taps); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_equalizer_simpledfe.h b/gr-digital/include/gnuradio/digital/ofdm_equalizer_simpledfe.h index 03a4c82b91..e65a1d27a7 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_equalizer_simpledfe.h +++ b/gr-digital/include/gnuradio/digital/ofdm_equalizer_simpledfe.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,106 +27,108 @@ #include <gnuradio/digital/ofdm_equalizer_base.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Simple decision feedback equalizer for OFDM. - * \ingroup ofdm_blk - * \ingroup equalizers_blk - * - * \details - * Equalizes an OFDM signal symbol by symbol using knowledge of the - * complex modulations symbols. - * For every symbol, the following steps are performed: - * - On every sub-carrier, decode the modulation symbol - * - Use the difference between the decoded symbol and the received symbol - * to update the channel state on this carrier - * - Whenever a pilot symbol is found, it uses the known pilot symbol to - * update the channel state. - * - * This equalizer makes a lot of assumptions: - * - The initial channel state is good enough to decode the first - * symbol without error (unless the first symbol only consists of pilot - * tones) - * - The channel changes only very slowly, such that the channel state - * from one symbol is enough to decode the next - * - SNR low enough that equalization will always suffice to correctly - * decode a symbol - * If these assumptions are not met, the most common error is that the - * channel state is estimated incorrectly during equalization; after that, - * all subsequent symbols will be completely wrong. - * - * Note that the equalized symbols are *exact points* on the constellation. - * This means soft information of the modulation symbols is lost after the - * equalization, which is suboptimal for channel codes that use soft decision. - * - */ - class DIGITAL_API ofdm_equalizer_simpledfe : public ofdm_equalizer_1d_pilots - { - public: - typedef boost::shared_ptr<ofdm_equalizer_simpledfe> sptr; +/*! + * \brief Simple decision feedback equalizer for OFDM. + * \ingroup ofdm_blk + * \ingroup equalizers_blk + * + * \details + * Equalizes an OFDM signal symbol by symbol using knowledge of the + * complex modulations symbols. + * For every symbol, the following steps are performed: + * - On every sub-carrier, decode the modulation symbol + * - Use the difference between the decoded symbol and the received symbol + * to update the channel state on this carrier + * - Whenever a pilot symbol is found, it uses the known pilot symbol to + * update the channel state. + * + * This equalizer makes a lot of assumptions: + * - The initial channel state is good enough to decode the first + * symbol without error (unless the first symbol only consists of pilot + * tones) + * - The channel changes only very slowly, such that the channel state + * from one symbol is enough to decode the next + * - SNR low enough that equalization will always suffice to correctly + * decode a symbol + * If these assumptions are not met, the most common error is that the + * channel state is estimated incorrectly during equalization; after that, + * all subsequent symbols will be completely wrong. + * + * Note that the equalized symbols are *exact points* on the constellation. + * This means soft information of the modulation symbols is lost after the + * equalization, which is suboptimal for channel codes that use soft decision. + * + */ +class DIGITAL_API ofdm_equalizer_simpledfe : public ofdm_equalizer_1d_pilots +{ +public: + typedef boost::shared_ptr<ofdm_equalizer_simpledfe> sptr; - ofdm_equalizer_simpledfe( - int fft_len, - const gr::digital::constellation_sptr &constellation, - const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), - int symbols_skipped = 0, - float alpha = 0.1, - bool input_is_shifted = true); + ofdm_equalizer_simpledfe(int fft_len, + const gr::digital::constellation_sptr& constellation, + const std::vector<std::vector<int>>& occupied_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<int>>& pilot_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<gr_complex>>& pilot_symbols = + std::vector<std::vector<gr_complex>>(), + int symbols_skipped = 0, + float alpha = 0.1, + bool input_is_shifted = true); - ~ofdm_equalizer_simpledfe(); + ~ofdm_equalizer_simpledfe(); - void equalize(gr_complex *frame, - int n_sym, - const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), - const std::vector<tag_t> &tags = std::vector<tag_t>()); + void equalize(gr_complex* frame, + int n_sym, + const std::vector<gr_complex>& initial_taps = std::vector<gr_complex>(), + const std::vector<tag_t>& tags = std::vector<tag_t>()); - /* - * \param fft_len FFT length - * \param constellation The constellation object describing the modulation used - * on the subcarriers (e.g. QPSK). This is used to decode - * the individual symbols. - * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator - * for a description. - * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator - * for a description. - * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator - * for a description. - * \param alpha Averaging coefficient (in a nutshell, if \f$H_{i,k}\f$ is the channel - * state for carrier i and symbol k, - * \f$H_{i,k+1} = \alpha H_{i,k} + (1 - \alpha) H_{i,k+1}\f$. Make this - * larger if there's more noise, but keep in mind that larger values - * of alpha mean slower response to channel changes). - * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers. - * If the first symbol of the frame was removed (e.g. to decode the - * header), set this make sure the pilot symbols are correctly - * identified. - * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. - * the first input items is on the DC carrier. - * Note that a lot of the OFDM receiver blocks operate on shifted - * signals! - */ - static sptr make( - int fft_len, - const gr::digital::constellation_sptr &constellation, - const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), - int symbols_skipped=0, - float alpha=0.1, - bool input_is_shifted=true - ); + /* + * \param fft_len FFT length + * \param constellation The constellation object describing the modulation used + * on the subcarriers (e.g. QPSK). This is used to decode + * the individual symbols. + * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator + * for a description. + * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param alpha Averaging coefficient (in a nutshell, if \f$H_{i,k}\f$ is the channel + * state for carrier i and symbol k, + * \f$H_{i,k+1} = \alpha H_{i,k} + (1 - \alpha) H_{i,k+1}\f$. Make this + * larger if there's more noise, but keep in mind that larger values + * of alpha mean slower response to channel changes). + * \param symbols_skipped Starting position within occupied_carriers and + * pilot_carriers. If the first symbol of the frame was removed (e.g. to decode the + * header), set this make sure the pilot symbols are correctly + * identified. + * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. + * the first input items is on the DC carrier. + * Note that a lot of the OFDM receiver blocks operate on + * shifted signals! + */ + static sptr make(int fft_len, + const gr::digital::constellation_sptr& constellation, + const std::vector<std::vector<int>>& occupied_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<int>>& pilot_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<gr_complex>>& pilot_symbols = + std::vector<std::vector<gr_complex>>(), + int symbols_skipped = 0, + float alpha = 0.1, + bool input_is_shifted = true); - private: - gr::digital::constellation_sptr d_constellation; - //! Averaging coefficient - float d_alpha; - }; +private: + gr::digital::constellation_sptr d_constellation; + //! Averaging coefficient + float d_alpha; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_equalizer_static.h b/gr-digital/include/gnuradio/digital/ofdm_equalizer_static.h index ed3fe83f04..411e8c40f1 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_equalizer_static.h +++ b/gr-digital/include/gnuradio/digital/ofdm_equalizer_static.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,78 +27,79 @@ #include <gnuradio/digital/ofdm_equalizer_base.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Very simple static equalizer for OFDM. - * \ingroup ofdm_blk - * \ingroup equalizers_blk - * - * \details - * This is an extremely simple equalizer. It will only work for - * high-SNR, very, very slowly changing channels. - * - * It simply divides the signal with the currently known channel - * state. Whenever a pilot symbol comes around, it updates the - * channel state on that particular carrier by dividing the - * received symbol with the known pilot symbol. - */ - class DIGITAL_API ofdm_equalizer_static : public ofdm_equalizer_1d_pilots - { - public: - typedef boost::shared_ptr<ofdm_equalizer_static> sptr; +/*! + * \brief Very simple static equalizer for OFDM. + * \ingroup ofdm_blk + * \ingroup equalizers_blk + * + * \details + * This is an extremely simple equalizer. It will only work for + * high-SNR, very, very slowly changing channels. + * + * It simply divides the signal with the currently known channel + * state. Whenever a pilot symbol comes around, it updates the + * channel state on that particular carrier by dividing the + * received symbol with the known pilot symbol. + */ +class DIGITAL_API ofdm_equalizer_static : public ofdm_equalizer_1d_pilots +{ +public: + typedef boost::shared_ptr<ofdm_equalizer_static> sptr; - ofdm_equalizer_static( - int fft_len, - const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), - int symbols_skipped = 0, - bool input_is_shifted = true - ); - ~ofdm_equalizer_static(); + ofdm_equalizer_static(int fft_len, + const std::vector<std::vector<int>>& occupied_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<int>>& pilot_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<gr_complex>>& pilot_symbols = + std::vector<std::vector<gr_complex>>(), + int symbols_skipped = 0, + bool input_is_shifted = true); + ~ofdm_equalizer_static(); - /*! \brief Divide the input signal with the current channel state. - * - * Does the following (and nothing else): - * - Divide every OFDM symbol with the current channel state - * - If a pilot symbol is found, re-set the channel state by dividing the received - * symbol with the known pilot symbol - */ - void equalize(gr_complex *frame, - int n_sym, - const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), - const std::vector<tag_t> &tags = std::vector<tag_t>()); + /*! \brief Divide the input signal with the current channel state. + * + * Does the following (and nothing else): + * - Divide every OFDM symbol with the current channel state + * - If a pilot symbol is found, re-set the channel state by dividing the received + * symbol with the known pilot symbol + */ + void equalize(gr_complex* frame, + int n_sym, + const std::vector<gr_complex>& initial_taps = std::vector<gr_complex>(), + const std::vector<tag_t>& tags = std::vector<tag_t>()); - /* - * \param fft_len FFT length - * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator - * for a description. - * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator - * for a description. - * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator - * for a description. - * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers. - * If the first symbol of the frame was removed (e.g. to decode the - * header), set this make sure the pilot symbols are correctly - * identified. - * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. - * the first input items is on the DC carrier. - * Note that a lot of the OFDM receiver blocks operate on shifted - * signals! - */ - static sptr make( - int fft_len, - const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), - const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), - int symbols_skipped = 0, - bool input_is_shifted = true - ); - }; + /* + * \param fft_len FFT length + * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator + * for a description. + * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param symbols_skipped Starting position within occupied_carriers and + * pilot_carriers. If the first symbol of the frame was removed (e.g. to decode the + * header), set this make sure the pilot symbols are correctly + * identified. + * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. + * the first input items is on the DC carrier. + * Note that a lot of the OFDM receiver blocks operate on + * shifted signals! + */ + static sptr make(int fft_len, + const std::vector<std::vector<int>>& occupied_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<int>>& pilot_carriers = + std::vector<std::vector<int>>(), + const std::vector<std::vector<gr_complex>>& pilot_symbols = + std::vector<std::vector<gr_complex>>(), + int symbols_skipped = 0, + bool input_is_shifted = true); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h index be38b6f8ae..112e61d565 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,55 +27,51 @@ #include <gnuradio/tagged_stream_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief OFDM frame equalizer + * \ingroup ofdm_blk + * + * \details + * Performs equalization in one or two dimensions on a tagged OFDM frame. + * + * This does two things: + * First, it removes the coarse carrier offset. If a tag is found on the first + * item with the key 'ofdm_sync_carr_offset', this is interpreted as the coarse + * frequency offset in number of carriers. + * Next, it performs equalization in one or two dimensions on a tagged OFDM frame. + * The actual equalization is done by a ofdm_frame_equalizer object, outside of + * the block. + * + * Note that the tag with the coarse carrier offset is not removed. Blocks + * downstream from this block must not attempt to also correct this offset. + * + * Input: a tagged series of OFDM symbols. + * Output: The same as the input, but equalized and frequency-corrected. + */ +class DIGITAL_API ofdm_frame_equalizer_vcvc : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<ofdm_frame_equalizer_vcvc> sptr; /*! - * \brief OFDM frame equalizer - * \ingroup ofdm_blk - * - * \details - * Performs equalization in one or two dimensions on a tagged OFDM frame. - * - * This does two things: - * First, it removes the coarse carrier offset. If a tag is found on the first - * item with the key 'ofdm_sync_carr_offset', this is interpreted as the coarse - * frequency offset in number of carriers. - * Next, it performs equalization in one or two dimensions on a tagged OFDM frame. - * The actual equalization is done by a ofdm_frame_equalizer object, outside of - * the block. - * - * Note that the tag with the coarse carrier offset is not removed. Blocks - * downstream from this block must not attempt to also correct this offset. - * - * Input: a tagged series of OFDM symbols. - * Output: The same as the input, but equalized and frequency-corrected. + * \param equalizer The equalizer object that will do the actual work + * \param cp_len Length of the cyclic prefix in samples (required to correct the + * frequency offset) \param tsb_key TSB key \param propagate_channel_state If true, + * the channel state after the last symbol will be added to the first symbol as a tag + * \param fixed_frame_len Set if the frame length is fixed. When this value is given, + * the TSB tag key can be left empty, but it is useful even + * when using tagged streams at the input. */ - class DIGITAL_API ofdm_frame_equalizer_vcvc : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<ofdm_frame_equalizer_vcvc> sptr; + static sptr make(ofdm_equalizer_base::sptr equalizer, + int cp_len, + const std::string& tsb_key = "frame_len", + bool propagate_channel_state = false, + int fixed_frame_len = 0); +}; - /*! - * \param equalizer The equalizer object that will do the actual work - * \param cp_len Length of the cyclic prefix in samples (required to correct the frequency offset) - * \param tsb_key TSB key - * \param propagate_channel_state If true, the channel state after the last symbol - * will be added to the first symbol as a tag - * \param fixed_frame_len Set if the frame length is fixed. When this value is given, - * the TSB tag key can be left empty, but it is useful even - * when using tagged streams at the input. - */ - static sptr make( - ofdm_equalizer_base::sptr equalizer, - int cp_len, - const std::string &tsb_key="frame_len", - bool propagate_channel_state=false, - int fixed_frame_len=0 - ); - }; - - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_serializer_vcc.h b/gr-digital/include/gnuradio/digital/ofdm_serializer_vcc.h index a445118678..2fabbd9f1d 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_serializer_vcc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_serializer_vcc.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,73 +27,73 @@ #include <gnuradio/digital/ofdm_carrier_allocator_cvc.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Serializes complex modulations symbols from OFDM sub-carriers + * \ingroup ofdm_blk + * + * \details + * This is the inverse block to the carrier_allocator_cvc. It outputs the + * complex data symbols as a tagged stream, discarding the pilot symbols. + * + * If given, two different tags are parsed: The first key (\p len_tag_key) + * specifies the number of OFDM symbols in the frame at the input. The + * second key (\p packet_len_tag_key) specifies the number of complex symbols + * that are coded into this frame. If given, this second key is then used + * at the output, otherwise, \p len_tag_key is used. + * If both are given, the packet length specifies the maximum number of + * output items, and the frame length specifies the exact number of + * consumed input items. + * + * It is possible to correct a carrier offset in this function by passing + * another tag with said offset. + * + * Input: Complex vectors of length \p fft_len + * Output: Complex scalars, in the same order as specified in occupied_carriers. + */ +class DIGITAL_API ofdm_serializer_vcc : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<ofdm_serializer_vcc> sptr; /*! - * \brief Serializes complex modulations symbols from OFDM sub-carriers - * \ingroup ofdm_blk - * - * \details - * This is the inverse block to the carrier_allocator_cvc. It outputs the - * complex data symbols as a tagged stream, discarding the pilot symbols. - * - * If given, two different tags are parsed: The first key (\p len_tag_key) - * specifies the number of OFDM symbols in the frame at the input. The - * second key (\p packet_len_tag_key) specifies the number of complex symbols - * that are coded into this frame. If given, this second key is then used - * at the output, otherwise, \p len_tag_key is used. - * If both are given, the packet length specifies the maximum number of - * output items, and the frame length specifies the exact number of - * consumed input items. - * - * It is possible to correct a carrier offset in this function by passing - * another tag with said offset. - * - * Input: Complex vectors of length \p fft_len - * Output: Complex scalars, in the same order as specified in occupied_carriers. + * \param fft_len FFT length + * \param occupied_carriers See ofdm_carrier_allocator_cvc. + * \param len_tag_key The key of the tag identifying the length of the input frame in + * OFDM symbols. \param packet_len_tag_key The key of the tag identifying the number + * of complex symbols in this packet. \param symbols_skipped If the first symbol is + * not allocated as in \p occupied_carriers[0], set this \param carr_offset_key When + * this block should correct a carrier offset, specify the tag key of the offset here + * (not necessary if following an ofdm_frame_equalizer_vcvc) \param input_is_shifted + * If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this + * to false */ - class DIGITAL_API ofdm_serializer_vcc : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<ofdm_serializer_vcc> sptr; - - /*! - * \param fft_len FFT length - * \param occupied_carriers See ofdm_carrier_allocator_cvc. - * \param len_tag_key The key of the tag identifying the length of the input frame in OFDM symbols. - * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet. - * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this - * \param carr_offset_key When this block should correct a carrier offset, specify the tag key of the offset here (not necessary if following an ofdm_frame_equalizer_vcvc) - * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false - */ - static sptr make( - int fft_len, - const std::vector<std::vector<int> > &occupied_carriers, - const std::string &len_tag_key="frame_len", - const std::string &packet_len_tag_key="", - int symbols_skipped=0, - const std::string &carr_offset_key="", - bool input_is_shifted=true - ); + static sptr make(int fft_len, + const std::vector<std::vector<int>>& occupied_carriers, + const std::string& len_tag_key = "frame_len", + const std::string& packet_len_tag_key = "", + int symbols_skipped = 0, + const std::string& carr_offset_key = "", + bool input_is_shifted = true); - /*! - * \param allocator The carrier allocator block of which this shall be the inverse - * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet. - * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this - * \param carr_offset_key When this block should correct a carrier offset, specify the tag key of the offset here (not necessary if following an ofdm_frame_equalizer_vcvc) - * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false - */ - static sptr make( - const gr::digital::ofdm_carrier_allocator_cvc::sptr &allocator, - const std::string &packet_len_tag_key="", - int symbols_skipped=0, - const std::string &carr_offset_key="", - bool input_is_shifted=true - ); - }; + /*! + * \param allocator The carrier allocator block of which this shall be the inverse + * \param packet_len_tag_key The key of the tag identifying the number of complex + * symbols in this packet. \param symbols_skipped If the first symbol is not allocated + * as in \p occupied_carriers[0], set this \param carr_offset_key When this block + * should correct a carrier offset, specify the tag key of the offset here (not + * necessary if following an ofdm_frame_equalizer_vcvc) \param input_is_shifted If the + * input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false + */ + static sptr make(const gr::digital::ofdm_carrier_allocator_cvc::sptr& allocator, + const std::string& packet_len_tag_key = "", + int symbols_skipped = 0, + const std::string& carr_offset_key = "", + bool input_is_shifted = true); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H */ - diff --git a/gr-digital/include/gnuradio/digital/ofdm_sync_sc_cfb.h b/gr-digital/include/gnuradio/digital/ofdm_sync_sc_cfb.h index 701874037b..42970765f6 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_sync_sc_cfb.h +++ b/gr-digital/include/gnuradio/digital/ofdm_sync_sc_cfb.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2013 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, @@ -28,60 +28,59 @@ #include <gnuradio/hier_block2.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Schmidl & Cox synchronisation for OFDM - * \ingroup ofdm_blk - * \ingroup synchronizers_blk - * - * \details - * Input: complex samples. - * Output 0: Fine frequency offset, scaled by the OFDM symbol duration. - * This is \f$\hat{\varphi}\f$ in [1]. The normalized frequency - * offset is then 2.0*output0/fft_len. - * Output 1: Beginning of the first OFDM symbol after the first (doubled) OFDM - * symbol. The beginning is marked with a 1 (it's 0 everywhere else). - * - * The evaluation of the coarse frequency offset is *not* done in this block. - * Also, the initial equalizer taps are not calculated here. - * - * Note that we use a different normalization factor in the timing metric than - * the authors do in their original work[1]. If the timing metric (8) is - * \f[ - * M(d) = \frac{|P(d)|^2}{(R(d))^2}, - * \f] - * we calculate the normalization as - * \f[ - * R(d) = \frac{1}{2} \sum_{k=0}^{N-1} |r_{k+d}|^2, - * \f] - * i.e., we estimate the energy from *both* half-symbols. This avoids spurious detects - * at the end of a burst, when the energy level suddenly drops. - * - * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM", - * Communications, IEEE Transactions on, 1997. - */ - class DIGITAL_API ofdm_sync_sc_cfb : virtual public hier_block2 - { - public: - typedef boost::shared_ptr<ofdm_sync_sc_cfb> sptr; +/*! + * \brief Schmidl & Cox synchronisation for OFDM + * \ingroup ofdm_blk + * \ingroup synchronizers_blk + * + * \details + * Input: complex samples. + * Output 0: Fine frequency offset, scaled by the OFDM symbol duration. + * This is \f$\hat{\varphi}\f$ in [1]. The normalized frequency + * offset is then 2.0*output0/fft_len. + * Output 1: Beginning of the first OFDM symbol after the first (doubled) OFDM + * symbol. The beginning is marked with a 1 (it's 0 everywhere else). + * + * The evaluation of the coarse frequency offset is *not* done in this block. + * Also, the initial equalizer taps are not calculated here. + * + * Note that we use a different normalization factor in the timing metric than + * the authors do in their original work[1]. If the timing metric (8) is + * \f[ + * M(d) = \frac{|P(d)|^2}{(R(d))^2}, + * \f] + * we calculate the normalization as + * \f[ + * R(d) = \frac{1}{2} \sum_{k=0}^{N-1} |r_{k+d}|^2, + * \f] + * i.e., we estimate the energy from *both* half-symbols. This avoids spurious detects + * at the end of a burst, when the energy level suddenly drops. + * + * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for + * OFDM", Communications, IEEE Transactions on, 1997. + */ +class DIGITAL_API ofdm_sync_sc_cfb : virtual public hier_block2 +{ +public: + typedef boost::shared_ptr<ofdm_sync_sc_cfb> sptr; - /*! \param fft_len FFT length - * \param cp_len Length of the guard interval (cyclic prefix) in samples - * \param use_even_carriers If true, the carriers in the sync preamble are occupied such - * that the even carriers are used (0, 2, 4, ...). If you use all - * carriers, that would include the DC carrier, so be careful. - * \param threshold detection threshold. Default is 0.9. - */ - static sptr make(int fft_len, int cp_len, bool use_even_carriers=false, - float threshold=0.9); + /*! \param fft_len FFT length + * \param cp_len Length of the guard interval (cyclic prefix) in samples + * \param use_even_carriers If true, the carriers in the sync preamble are occupied + * such that the even carriers are used (0, 2, 4, ...). If you use all carriers, that + * would include the DC carrier, so be careful. \param threshold detection threshold. + * Default is 0.9. + */ + static sptr + make(int fft_len, int cp_len, bool use_even_carriers = false, float threshold = 0.9); - virtual void set_threshold(float threshold) = 0; - virtual float threshold() const = 0; - }; + virtual void set_threshold(float threshold) = 0; + virtual float threshold() const = 0; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H */ - diff --git a/gr-digital/include/gnuradio/digital/packet_header_default.h b/gr-digital/include/gnuradio/digital/packet_header_default.h index 9ffb3d047b..4c5337685c 100644 --- a/gr-digital/include/gnuradio/digital/packet_header_default.h +++ b/gr-digital/include/gnuradio/digital/packet_header_default.h @@ -28,87 +28,86 @@ #include <boost/crc.hpp> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Default header formatter for digital packet transmission. + * \ingroup packet_operators_blk + * + * \details + * For bursty/packetized digital transmission, packets are usually prepended + * with a packet header, containing the number of bytes etc. + * This class is not a block, but a tool to create these packet header. + * + * This is a default packet header (see header_formatter()) for a description + * on the header format). To create other header, derive packet header creator + * classes from this function. + * + * gr::digital::packet_headergenerator_bb uses header generators derived from + * this class to create packet headers from data streams. + */ +class DIGITAL_API packet_header_default + : public boost::enable_shared_from_this<gr::digital::packet_header_default> +{ +public: + typedef boost::shared_ptr<packet_header_default> sptr; + + packet_header_default(long header_len, + const std::string& len_tag_key = "packet_len", + const std::string& num_tag_key = "packet_num", + int bits_per_byte = 1); + virtual ~packet_header_default(); + + sptr base() { return shared_from_this(); }; + sptr formatter() { return shared_from_this(); }; + + void set_header_num(unsigned header_num) { d_header_number = header_num; }; + long header_len() { return d_header_len; }; + pmt::pmt_t len_tag_key() { return d_len_tag_key; }; /*! - * \brief Default header formatter for digital packet transmission. - * \ingroup packet_operators_blk + * \brief Encodes the header information in the given tags into bits and places them + * into \p out * - * \details - * For bursty/packetized digital transmission, packets are usually prepended - * with a packet header, containing the number of bytes etc. - * This class is not a block, but a tool to create these packet header. + * Uses the following header format: + * Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) + * Bits 12-23: The header number (counts up everytime this function is called) + * Bit 24-31: 8-Bit CRC + * All other bits: Are set to zero * - * This is a default packet header (see header_formatter()) for a description - * on the header format). To create other header, derive packet header creator - * classes from this function. + * If the header length is smaller than 32, bits are simply left out. For this + * reason, they always start with the LSB. * - * gr::digital::packet_headergenerator_bb uses header generators derived from - * this class to create packet headers from data streams. + * However, it is recommended to stay above 32 Bits, in order to have a working + * CRC. */ - class DIGITAL_API packet_header_default - : public boost::enable_shared_from_this<gr::digital::packet_header_default> - { - public: - typedef boost::shared_ptr<packet_header_default> sptr; + virtual bool header_formatter(long packet_len, + unsigned char* out, + const std::vector<tag_t>& tags = std::vector<tag_t>()); - packet_header_default(long header_len, - const std::string &len_tag_key="packet_len", - const std::string &num_tag_key="packet_num", - int bits_per_byte=1); - virtual ~packet_header_default(); - - sptr base() { return shared_from_this(); }; - sptr formatter() { return shared_from_this(); }; - - void set_header_num(unsigned header_num) { d_header_number = header_num; }; - long header_len() { return d_header_len; }; - pmt::pmt_t len_tag_key() { return d_len_tag_key; }; - - /*! - * \brief Encodes the header information in the given tags into bits and places them into \p out - * - * Uses the following header format: - * Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) - * Bits 12-23: The header number (counts up everytime this function is called) - * Bit 24-31: 8-Bit CRC - * All other bits: Are set to zero - * - * If the header length is smaller than 32, bits are simply left out. For this - * reason, they always start with the LSB. - * - * However, it is recommended to stay above 32 Bits, in order to have a working - * CRC. - */ - virtual bool header_formatter(long packet_len, - unsigned char *out, - const std::vector<tag_t> &tags=std::vector<tag_t>()); - - /*! - * \brief Inverse function to header_formatter(). - * - * Reads the bit stream in \p header and writes a corresponding tag into \p tags. - */ - virtual bool header_parser( - const unsigned char *header, - std::vector<tag_t> &tags); + /*! + * \brief Inverse function to header_formatter(). + * + * Reads the bit stream in \p header and writes a corresponding tag into \p tags. + */ + virtual bool header_parser(const unsigned char* header, std::vector<tag_t>& tags); - static sptr make(long header_len, - const std::string &len_tag_key="packet_len", - const std::string &num_tag_key="packet_num", - int bits_per_byte=1); + static sptr make(long header_len, + const std::string& len_tag_key = "packet_len", + const std::string& num_tag_key = "packet_num", + int bits_per_byte = 1); - protected: - long d_header_len; - pmt::pmt_t d_len_tag_key; - pmt::pmt_t d_num_tag_key; - int d_bits_per_byte; - unsigned d_header_number; - unsigned d_mask; - boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl; - }; +protected: + long d_header_len; + pmt::pmt_t d_len_tag_key; + pmt::pmt_t d_num_tag_key; + int d_bits_per_byte; + unsigned d_header_number; + unsigned d_mask; + boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H */ diff --git a/gr-digital/include/gnuradio/digital/packet_header_ofdm.h b/gr-digital/include/gnuradio/digital/packet_header_ofdm.h index 9703f2e352..708fc842f1 100644 --- a/gr-digital/include/gnuradio/digital/packet_header_ofdm.h +++ b/gr-digital/include/gnuradio/digital/packet_header_ofdm.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,94 +27,87 @@ #include <gnuradio/digital/packet_header_default.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Header utility for OFDM signals. - * \ingroup ofdm_blk - */ - class DIGITAL_API packet_header_ofdm : public packet_header_default - { - public: - typedef boost::shared_ptr<packet_header_ofdm> sptr; +/*! + * \brief Header utility for OFDM signals. + * \ingroup ofdm_blk + */ +class DIGITAL_API packet_header_ofdm : public packet_header_default +{ +public: + typedef boost::shared_ptr<packet_header_ofdm> sptr; - packet_header_ofdm( - const std::vector<std::vector<int> > &occupied_carriers, - int n_syms, - const std::string &len_tag_key, - const std::string &frame_len_tag_key, - const std::string &num_tag_key, - int bits_per_header_sym, - int bits_per_payload_sym, - bool scramble_header); - ~packet_header_ofdm(); + packet_header_ofdm(const std::vector<std::vector<int>>& occupied_carriers, + int n_syms, + const std::string& len_tag_key, + const std::string& frame_len_tag_key, + const std::string& num_tag_key, + int bits_per_header_sym, + int bits_per_payload_sym, + bool scramble_header); + ~packet_header_ofdm(); - /*! - * \brief Header formatter. - * - * Does the same as packet_header_default::header_formatter(), but - * optionally scrambles the bits (this is more important for OFDM to avoid - * PAPR spikes). - */ - bool header_formatter( - long packet_len, - unsigned char *out, - const std::vector<tag_t> &tags - ); + /*! + * \brief Header formatter. + * + * Does the same as packet_header_default::header_formatter(), but + * optionally scrambles the bits (this is more important for OFDM to avoid + * PAPR spikes). + */ + bool + header_formatter(long packet_len, unsigned char* out, const std::vector<tag_t>& tags); - /*! - * \brief Inverse function to header_formatter(). - * - * Does the same as packet_header_default::header_parser(), but - * adds another tag that stores the number of OFDM symbols in the - * packet. - * Note that there is usually no linear connection between the number - * of OFDM symbols and the packet length because a packet might - * finish mid-OFDM-symbol. - */ - bool header_parser( - const unsigned char *header, - std::vector<tag_t> &tags); + /*! + * \brief Inverse function to header_formatter(). + * + * Does the same as packet_header_default::header_parser(), but + * adds another tag that stores the number of OFDM symbols in the + * packet. + * Note that there is usually no linear connection between the number + * of OFDM symbols and the packet length because a packet might + * finish mid-OFDM-symbol. + */ + bool header_parser(const unsigned char* header, std::vector<tag_t>& tags); - /*! - * \param occupied_carriers See carrier allocator - * \param n_syms The number of OFDM symbols the header should be (usually 1) - * \param len_tag_key The tag key used for the packet length (number of bytes) - * \param frame_len_tag_key The tag key used for the frame length (number of - * OFDM symbols, this is the tag key required for the - * frame equalizer etc.) - * \param num_tag_key The tag key used for packet numbering. - * \param bits_per_header_sym Bits per complex symbol in the header, e.g. 1 if - * the header is BPSK modulated, 2 if it's QPSK - * modulated etc. - * \param bits_per_payload_sym Bits per complex symbol in the payload. This is - * required to figure out how many OFDM symbols - * are necessary to encode the given number of - * bytes. - * \param scramble_header Set this to true to scramble the bits. This is highly - * recommended, as it reduces PAPR spikes. - */ - static sptr make( - const std::vector<std::vector<int> > &occupied_carriers, - int n_syms, - const std::string &len_tag_key="packet_len", - const std::string &frame_len_tag_key="frame_len", - const std::string &num_tag_key="packet_num", - int bits_per_header_sym=1, - int bits_per_payload_sym=1, - bool scramble_header=false - ); + /*! + * \param occupied_carriers See carrier allocator + * \param n_syms The number of OFDM symbols the header should be (usually 1) + * \param len_tag_key The tag key used for the packet length (number of bytes) + * \param frame_len_tag_key The tag key used for the frame length (number of + * OFDM symbols, this is the tag key required for the + * frame equalizer etc.) + * \param num_tag_key The tag key used for packet numbering. + * \param bits_per_header_sym Bits per complex symbol in the header, e.g. 1 if + * the header is BPSK modulated, 2 if it's QPSK + * modulated etc. + * \param bits_per_payload_sym Bits per complex symbol in the payload. This is + * required to figure out how many OFDM symbols + * are necessary to encode the given number of + * bytes. + * \param scramble_header Set this to true to scramble the bits. This is highly + * recommended, as it reduces PAPR spikes. + */ + static sptr make(const std::vector<std::vector<int>>& occupied_carriers, + int n_syms, + const std::string& len_tag_key = "packet_len", + const std::string& frame_len_tag_key = "frame_len", + const std::string& num_tag_key = "packet_num", + int bits_per_header_sym = 1, + int bits_per_payload_sym = 1, + bool scramble_header = false); - protected: - pmt::pmt_t d_frame_len_tag_key; //!< Tag key of the additional frame length tag - const std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data - int d_bits_per_payload_sym; - std::vector<unsigned char> d_scramble_mask; //!< Bits are xor'd with this before tx'ing - }; +protected: + pmt::pmt_t d_frame_len_tag_key; //!< Tag key of the additional frame length tag + const std::vector<std::vector<int>> + d_occupied_carriers; //!< Which carriers/symbols carry data + int d_bits_per_payload_sym; + std::vector<unsigned char> + d_scramble_mask; //!< Bits are xor'd with this before tx'ing +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H */ - diff --git a/gr-digital/include/gnuradio/digital/packet_headergenerator_bb.h b/gr-digital/include/gnuradio/digital/packet_headergenerator_bb.h index c5b6b3e698..d0d491267b 100644 --- a/gr-digital/include/gnuradio/digital/packet_headergenerator_bb.h +++ b/gr-digital/include/gnuradio/digital/packet_headergenerator_bb.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,49 +27,44 @@ #include <gnuradio/digital/packet_header_default.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief Generates a header for a tagged, streamed packet. - * \ingroup packet_operators_blk - * - * \details - * Input: A tagged stream. This is consumed entirely, it is not appended - * to the output stream. - * Output: An tagged stream containing the header. The details on the header - * are set in a header formatter object (of type packet_header_default - * or a subclass thereof). If only a number of bits is specified, a - * default header is generated (see packet_header_default). - */ - class DIGITAL_API packet_headergenerator_bb : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<packet_headergenerator_bb> sptr; +/*! + * \brief Generates a header for a tagged, streamed packet. + * \ingroup packet_operators_blk + * + * \details + * Input: A tagged stream. This is consumed entirely, it is not appended + * to the output stream. + * Output: An tagged stream containing the header. The details on the header + * are set in a header formatter object (of type packet_header_default + * or a subclass thereof). If only a number of bits is specified, a + * default header is generated (see packet_header_default). + */ +class DIGITAL_API packet_headergenerator_bb : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<packet_headergenerator_bb> sptr; - /* \param header_formatter A header formatter object. - * \param len_tag_key Length tag key. Note that for header generation, - * it is irrelevant which tag names are set in the - * formatter object, only this value is relevant! - */ - static sptr make( - const packet_header_default::sptr &header_formatter, - const std::string &len_tag_key="packet_len" - ); + /* \param header_formatter A header formatter object. + * \param len_tag_key Length tag key. Note that for header generation, + * it is irrelevant which tag names are set in the + * formatter object, only this value is relevant! + */ + static sptr make(const packet_header_default::sptr& header_formatter, + const std::string& len_tag_key = "packet_len"); - /* \param header_len If this value is given, a packet_header_default - * object is used to generate the header. This is - * the number of bits per header. - * \param len_tag_key Length tag key. - */ - static sptr make( - long header_len, - const std::string &len_tag_key = "packet_len"); + /* \param header_len If this value is given, a packet_header_default + * object is used to generate the header. This is + * the number of bits per header. + * \param len_tag_key Length tag key. + */ + static sptr make(long header_len, const std::string& len_tag_key = "packet_len"); - virtual void set_header_formatter(packet_header_default::sptr header_formatter)=0; - }; + virtual void set_header_formatter(packet_header_default::sptr header_formatter) = 0; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_PACKET_HEADERGENERATOR_BB_H */ - diff --git a/gr-digital/include/gnuradio/digital/packet_headerparser_b.h b/gr-digital/include/gnuradio/digital/packet_headerparser_b.h index a0ca48f192..30a3cd0d26 100644 --- a/gr-digital/include/gnuradio/digital/packet_headerparser_b.h +++ b/gr-digital/include/gnuradio/digital/packet_headerparser_b.h @@ -1,18 +1,18 @@ /* -*- c++ -*- */ /* Copyright 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, @@ -27,45 +27,44 @@ #include <gnuradio/digital/packet_header_default.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Post header metadata as a PMT + * \ingroup packet_operators_blk + * + * \details + * In a sense, this is the inverse block to packet_headergenerator_bb. + * The difference is, the parsed header is not output as a stream, + * but as a PMT dictionary, which is published to message port with + * the id "header_data". + * + * The dictionary consists of the tags created by the header formatter + * object. You should be able to use the exact same formatter object + * as used on the Tx side in the packet_headergenerator_bb. + * + * If only a header length is given, this block uses the default header + * format. + */ +class DIGITAL_API packet_headerparser_b : virtual public sync_block +{ +public: + typedef boost::shared_ptr<packet_headerparser_b> sptr; /*! - * \brief Post header metadata as a PMT - * \ingroup packet_operators_blk - * - * \details - * In a sense, this is the inverse block to packet_headergenerator_bb. - * The difference is, the parsed header is not output as a stream, - * but as a PMT dictionary, which is published to message port with - * the id "header_data". - * - * The dictionary consists of the tags created by the header formatter - * object. You should be able to use the exact same formatter object - * as used on the Tx side in the packet_headergenerator_bb. - * - * If only a header length is given, this block uses the default header - * format. + * \param header_formatter Header object. This should be the same as used for + * packet_headergenerator_bb. */ - class DIGITAL_API packet_headerparser_b : virtual public sync_block - { - public: - typedef boost::shared_ptr<packet_headerparser_b> sptr; - - /*! - * \param header_formatter Header object. This should be the same as used for - * packet_headergenerator_bb. - */ - static sptr make(const gr::digital::packet_header_default::sptr &header_formatter); + static sptr make(const gr::digital::packet_header_default::sptr& header_formatter); - /*! - * \param header_len Number of bytes per header - * \param len_tag_key Length Tag Key - */ - static sptr make(long header_len, const std::string &len_tag_key); - }; + /*! + * \param header_len Number of bytes per header + * \param len_tag_key Length Tag Key + */ + static sptr make(long header_len, const std::string& len_tag_key); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H */ - diff --git a/gr-digital/include/gnuradio/digital/packet_sink.h b/gr-digital/include/gnuradio/digital/packet_sink.h index a0a56bc4ff..ba5d5a1aff 100644 --- a/gr-digital/include/gnuradio/digital/packet_sink.h +++ b/gr-digital/include/gnuradio/digital/packet_sink.h @@ -28,53 +28,53 @@ #include <gnuradio/msg_queue.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief process received bits looking for packet sync, header, + * and process bits into packet + * \ingroup packet_operators_blk + * + * \details + * input: stream of symbols to be sliced. + * + * output: none. Pushes assembled packet into target queue + * + * The packet sink takes in a stream of binary symbols that are + * sliced around 0. The bits are then checked for the \p + * sync_vector to determine find and decode the packet. It then + * expects a fixed length header of 2 16-bit shorts containing the + * payload length, followed by the payload. If the 2 16-bit shorts + * are not identical, this packet is ignored. Better algs are + * welcome. + * + * This block is not very useful anymore as it only works with + * 2-level modulations such as BPSK or GMSK. The block can + * generally be replaced with a correlate access code and frame + * sink blocks. + */ +class DIGITAL_API packet_sink : virtual public sync_block +{ +public: + // gr::digital::packet_sink::sptr + typedef boost::shared_ptr<packet_sink> sptr; /*! - * \brief process received bits looking for packet sync, header, - * and process bits into packet - * \ingroup packet_operators_blk - * - * \details - * input: stream of symbols to be sliced. - * - * output: none. Pushes assembled packet into target queue + * Make a packet_sink block. * - * The packet sink takes in a stream of binary symbols that are - * sliced around 0. The bits are then checked for the \p - * sync_vector to determine find and decode the packet. It then - * expects a fixed length header of 2 16-bit shorts containing the - * payload length, followed by the payload. If the 2 16-bit shorts - * are not identical, this packet is ignored. Better algs are - * welcome. - * - * This block is not very useful anymore as it only works with - * 2-level modulations such as BPSK or GMSK. The block can - * generally be replaced with a correlate access code and frame - * sink blocks. + * \param sync_vector The synchronization vector as a vector of 1's and 0's. + * \param target_queue The message queue that packets are sent to. + * \param threshold Number of bits that can be incorrect in the \p sync_vector. */ - class DIGITAL_API packet_sink : virtual public sync_block - { - public: - // gr::digital::packet_sink::sptr - typedef boost::shared_ptr<packet_sink> sptr; - - /*! - * Make a packet_sink block. - * - * \param sync_vector The synchronization vector as a vector of 1's and 0's. - * \param target_queue The message queue that packets are sent to. - * \param threshold Number of bits that can be incorrect in the \p sync_vector. - */ - static sptr make(const std::vector<unsigned char>& sync_vector, - msg_queue::sptr target_queue, - int threshold=-1); + static sptr make(const std::vector<unsigned char>& sync_vector, + msg_queue::sptr target_queue, + int threshold = -1); - //! return true if we detect carrier - virtual bool carrier_sensed() const = 0; - }; + //! return true if we detect carrier + virtual bool carrier_sensed() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_PACKET_SINK_H */ diff --git a/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h b/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h index 9bbe5bdbff..9d1241df2b 100644 --- a/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h +++ b/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h @@ -22,325 +22,327 @@ #ifndef INCLUDED_DIGITAL_PFB_CLOCK_SYNC_CCF_H -#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_CCF_H +#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_CCF_H #include <gnuradio/digital/api.h> #include <gnuradio/filter/fir_filter.h> #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Timing synchronizer using polyphase filterbanks + * \ingroup synchronizers_blk + * + * \details + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one + * filterbank contains the signal's pulse shaping matched filter + * (such as a root raised cosine filter), where each branch of the + * filterbank contains a different phase of the filter. The + * second filterbank contains the derivatives of the filters in + * the first filterbank. Thinking of this in the time domain, the + * first filterbank contains filters that have a sinc shape to + * them. We want to align the output signal to be sampled at + * exactly the peak of the sinc shape. The derivative of the sinc + * contains a zero at the maximum point of the sinc (sinc(0) = 1, + * sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the + * ith filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error + * in the real and imaginary parts. There are two reasons we + * multiply by the signal itself. First, if the symbol could be + * positive or negative going, but we want the error term to + * always tell us to go in the same direction depending on which + * side of the zero point we are on. The sign of x_i[n] adjusts + * the error term to do this. Second, the magnitude of x_i[n] + * scales the error term depending on the symbol's amplitude, so + * larger signals give us a stronger error term because we have + * more confidence in that symbol's value. Using the magnitude of + * x_i[n] instead of just the sign is especially good for signals + * with low SNR. + * + * The error signal, e[n], gives us a value proportional to how + * far away from the zero point we are in the derivative + * signal. We want to drive this value to zero, so we set up a + * second order loop. We have two variables for this loop; d_k is + * the filter number in the filterbank we are on and d_rate is the + * rate which we travel through the filters in the steady + * state. That is, due to the natural clock differences between + * the transmitter and receiver, d_rate represents that difference + * and would traverse the filter phase paths to keep the receiver + * locked. Thinking of this as a second-order PLL, the d_rate is + * the frequency and d_k is the phase. So we update d_rate and d_k + * using the standard loop equations based on two error signals, + * d_alpha and d_beta. We have these two values set based on each + * other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while + * d_beta is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of + * samples per symbol, because it defaults to return a single + * point representing the symbol. The sps can be any positive real + * number and does not need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of + * the inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is + * suggested in that blog post as the step size for the number of + * radians around the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this + * block is the taps of the filter. One of the benefits of this + * algorithm is that you can put the matched filter in here as the + * taps, so you get both the matched filter and sample timing + * correction in one go. So create your normal matched filter. For + * a typical digital modulation, this is a root raised cosine + * filter. The number of taps of this filter is based on how long + * you expect the channel to be; that is, how many symbols do you + * want to combine to get the current symbols energy back (there's + * probably a better way of stating that). It's usually 5 to 10 or + * so. That gives you your filter, but now we need to think about + * it as a filter with different phase profiles in each filter. So + * take this number of taps and multiply it by the number of + * filters. This is the number you would use to create your + * prototype filter. When you use this in the PFB filerbank, it + * segments these taps into the filterbanks in such a way that + * each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also + * be set and defaults to 32. With 32 filters, you get a good + * enough resolution in the phase to produce very small, almost + * unnoticeable, ISI. Going to 64 filters can reduce this more, + * but after that there is very little gained for the extra + * complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a + * different phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is + * the max_rate_devitation, which defaults to 1.5. This is how far + * we allow d_rate to swing, positive or negative, from + * 0. Constraining the rate can help keep the algorithm from + * walking too far away to lock during times when there is no + * signal. + * + * \li \p osps (default=1): The osps is the number of output + * samples per symbol. By default, the algorithm produces 1 sample + * per symbol, sampled at the exact sample value. This osps value + * was added to better work with equalizers, which do a better job + * of modeling the channel if they have 2 samps/sym. + * + * Reference: + * f. j. harris and M. Rice, "Multirate Digital Filters for Symbol + * Timing Synchronization in Software Defined Radios", IEEE + * Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001. + * + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.127.1757 + */ +class DIGITAL_API pfb_clock_sync_ccf : virtual public block +{ +public: + // gr::digital::pfb_clock_sync_ccf::sptr + typedef boost::shared_ptr<pfb_clock_sync_ccf> sptr; /*! - * \brief Timing synchronizer using polyphase filterbanks - * \ingroup synchronizers_blk + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per symbol in the incoming signal + * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. + * \param taps (vector<int>) The filter taps. + * \param filter_size (uint) The number of filters in the filterbank (default = 32). + * \param init_phase (float) The initial phase to look at, or which filter to start + * with (default = 0). + * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * \param osps (int) The number of output samples per symbol (default=1). + */ + static sptr make(double sps, + float loop_bw, + const std::vector<float>& taps, + unsigned int filter_size = 32, + float init_phase = 0, + float max_rate_deviation = 1.5, + int osps = 1); + + /*! \brief update the system gains from omega and eta * - * \details - * This block performs timing synchronization for PAM signals by - * minimizing the derivative of the filtered signal, which in turn - * maximizes the SNR and minimizes ISI. + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + virtual void update_gains() = 0; + + /*! + * Resets the filterbank's filter taps with the new prototype filter. + */ + virtual void update_taps(const std::vector<float>& taps) = 0; + + /*! + * Used to set the taps of the filters in the filterbank and + * differential filterbank. * - * This approach works by setting up two filterbanks; one - * filterbank contains the signal's pulse shaping matched filter - * (such as a root raised cosine filter), where each branch of the - * filterbank contains a different phase of the filter. The - * second filterbank contains the derivatives of the filters in - * the first filterbank. Thinking of this in the time domain, the - * first filterbank contains filters that have a sinc shape to - * them. We want to align the output signal to be sampled at - * exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, - * sinc(0)' = 0). Furthermore, the region around the zero point - * is relatively linear. We make use of this fact to generate the - * error signal. + * WARNING: this should not be used externally and will be moved + * to a private function in the next API. + */ + virtual void + set_taps(const std::vector<float>& taps, + std::vector<std::vector<float>>& ourtaps, + std::vector<gr::filter::kernel::fir_filter_ccf*>& ourfilter) = 0; + + /*! + * Returns all of the taps of the matched filter + */ + virtual std::vector<std::vector<float>> taps() const = 0; + + /*! + * Returns all of the taps of the derivative filter + */ + virtual std::vector<std::vector<float>> diff_taps() const = 0; + + /*! + * Returns the taps of the matched filter for a particular channel + */ + virtual std::vector<float> channel_taps(int channel) const = 0; + + /*! + * Returns the taps in the derivative filter for a particular channel + */ + virtual std::vector<float> diff_channel_taps(int channel) const = 0; + + /*! + * Return the taps as a formatted string for printing + */ + virtual std::string taps_as_string() const = 0; + + /*! + * Return the derivative filter taps as a formatted string for printing + */ + virtual std::string diff_taps_as_string() const = 0; + + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Set the loop bandwidth * - * If the signal out of the derivative filters is d_i[n] for the - * ith filter, and the output of the matched filter is x_i[n], we - * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + - * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error - * in the real and imaginary parts. There are two reasons we - * multiply by the signal itself. First, if the symbol could be - * positive or negative going, but we want the error term to - * always tell us to go in the same direction depending on which - * side of the zero point we are on. The sign of x_i[n] adjusts - * the error term to do this. Second, the magnitude of x_i[n] - * scales the error term depending on the symbol's amplitude, so - * larger signals give us a stronger error term because we have - * more confidence in that symbol's value. Using the magnitude of - * x_i[n] instead of just the sign is especially good for signals - * with low SNR. + * Set the loop filter's bandwidth to \p bw. This should be + * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be + * a positive number. * - * The error signal, e[n], gives us a value proportional to how - * far away from the zero point we are in the derivative - * signal. We want to drive this value to zero, so we set up a - * second order loop. We have two variables for this loop; d_k is - * the filter number in the filterbank we are on and d_rate is the - * rate which we travel through the filters in the steady - * state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference - * and would traverse the filter phase paths to keep the receiver - * locked. Thinking of this as a second-order PLL, the d_rate is - * the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, - * d_alpha and d_beta. We have these two values set based on each - * other for a critically damped system, so in the block - * constructor, we just ask for "gain," which is d_alpha while - * d_beta is equal to (gain^2)/4. + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are recalculated by a call to update_gains(). * - * The block's parameters are: + * \param bw (float) new bandwidth + */ + virtual void set_loop_bandwidth(float bw) = 0; + + /*! + * \brief Set the loop damping factor * - * \li \p sps: The clock sync block needs to know the number of - * samples per symbol, because it defaults to return a single - * point representing the symbol. The sps can be any positive real - * number and does not need to be an integer. + * Set the loop filter's damping factor to \p df. The damping + * factor should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are + * doing. It must be a number between 0 and 1. * - * \li \p loop_bw: The loop bandwidth is used to set the gain of - * the inner control loop (see: - * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). - * This should be set small (a value of around 2pi/100 is - * suggested in that blog post as the step size for the number of - * radians around the unit circle to move relative to the error). + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are recalculated by a call to update_gains(). * - * \li \p taps: One of the most important parameters for this - * block is the taps of the filter. One of the benefits of this - * algorithm is that you can put the matched filter in here as the - * taps, so you get both the matched filter and sample timing - * correction in one go. So create your normal matched filter. For - * a typical digital modulation, this is a root raised cosine - * filter. The number of taps of this filter is based on how long - * you expect the channel to be; that is, how many symbols do you - * want to combine to get the current symbols energy back (there's - * probably a better way of stating that). It's usually 5 to 10 or - * so. That gives you your filter, but now we need to think about - * it as a filter with different phase profiles in each filter. So - * take this number of taps and multiply it by the number of - * filters. This is the number you would use to create your - * prototype filter. When you use this in the PFB filerbank, it - * segments these taps into the filterbanks in such a way that - * each bank now represents the filter at different phases, - * equally spaced at 2pi/N, where N is the number of filters. + * \param df (float) new damping factor + */ + virtual void set_damping_factor(float df) = 0; + + /*! + * \brief Set the loop gain alpha * - * \li \p filter_size (default=32): The number of filters can also - * be set and defaults to 32. With 32 filters, you get a good - * enough resolution in the phase to produce very small, almost - * unnoticeable, ISI. Going to 64 filters can reduce this more, - * but after that there is very little gained for the extra - * complexity. + * Set's the loop filter's alpha gain parameter. * - * \li \p init_phase (default=0): The initial phase is another - * settable parameter and refers to the filter path the algorithm - * initially looks at (i.e., d_k starts at init_phase). This value - * defaults to zero, but it might be useful to start at a - * different phase offset, such as the mid-point of the filters. + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. * - * \li \p max_rate_deviation (default=1.5): The next parameter is - * the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from - * 0. Constraining the rate can help keep the algorithm from - * walking too far away to lock during times when there is no - * signal. + * \param alpha (float) new alpha gain + */ + virtual void set_alpha(float alpha) = 0; + + /*! + * \brief Set the loop gain beta * - * \li \p osps (default=1): The osps is the number of output - * samples per symbol. By default, the algorithm produces 1 sample - * per symbol, sampled at the exact sample value. This osps value - * was added to better work with equalizers, which do a better job - * of modeling the channel if they have 2 samps/sym. + * Set's the loop filter's beta gain parameter. * - * Reference: - * f. j. harris and M. Rice, "Multirate Digital Filters for Symbol - * Timing Synchronization in Software Defined Radios", IEEE - * Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001. + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. * - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.127.1757 + * \param beta (float) new beta gain + */ + virtual void set_beta(float beta) = 0; + + /*! + * Set the maximum deviation from 0 d_rate can have + */ + virtual void set_max_rate_deviation(float m) = 0; + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + virtual float loop_bandwidth() const = 0; + + /*! + * \brief Returns the loop damping factor + */ + virtual float damping_factor() const = 0; + + /*! + * \brief Returns the loop gain alpha + */ + virtual float alpha() const = 0; + + /*! + * \brief Returns the loop gain beta + */ + virtual float beta() const = 0; + + /*! + * \brief Returns the current clock rate */ - class DIGITAL_API pfb_clock_sync_ccf : virtual public block - { - public: - // gr::digital::pfb_clock_sync_ccf::sptr - typedef boost::shared_ptr<pfb_clock_sync_ccf> sptr; - - /*! - * Build the polyphase filterbank timing synchronizer. - * \param sps (double) The number of samples per symbol in the incoming signal - * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. - * \param taps (vector<int>) The filter taps. - * \param filter_size (uint) The number of filters in the filterbank (default = 32). - * \param init_phase (float) The initial phase to look at, or which filter to start - * with (default = 0). - * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). - * \param osps (int) The number of output samples per symbol (default=1). - */ - static sptr make(double sps, float loop_bw, - const std::vector<float> &taps, - unsigned int filter_size=32, - float init_phase=0, - float max_rate_deviation=1.5, - int osps=1); - - /*! \brief update the system gains from omega and eta - * - * This function updates the system gains based on the loop - * bandwidth and damping factor of the system. - * These two factors can be set separately through their own - * set functions. - */ - virtual void update_gains() = 0; - - /*! - * Resets the filterbank's filter taps with the new prototype filter. - */ - virtual void update_taps(const std::vector<float> &taps) = 0; - - /*! - * Used to set the taps of the filters in the filterbank and - * differential filterbank. - * - * WARNING: this should not be used externally and will be moved - * to a private function in the next API. - */ - virtual void set_taps(const std::vector<float> &taps, - std::vector< std::vector<float> > &ourtaps, - std::vector<gr::filter::kernel::fir_filter_ccf*> &ourfilter) = 0; - - /*! - * Returns all of the taps of the matched filter - */ - virtual std::vector< std::vector<float> > taps() const = 0; - - /*! - * Returns all of the taps of the derivative filter - */ - virtual std::vector< std::vector<float> > diff_taps() const = 0; - - /*! - * Returns the taps of the matched filter for a particular channel - */ - virtual std::vector<float> channel_taps(int channel) const = 0; - - /*! - * Returns the taps in the derivative filter for a particular channel - */ - virtual std::vector<float> diff_channel_taps(int channel) const = 0; - - /*! - * Return the taps as a formatted string for printing - */ - virtual std::string taps_as_string() const = 0; - - /*! - * Return the derivative filter taps as a formatted string for printing - */ - virtual std::string diff_taps_as_string() const = 0; - - - /******************************************************************* - SET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Set the loop bandwidth - * - * Set the loop filter's bandwidth to \p bw. This should be - * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be - * a positive number. - * - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are recalculated by a call to update_gains(). - * - * \param bw (float) new bandwidth - */ - virtual void set_loop_bandwidth(float bw) = 0; - - /*! - * \brief Set the loop damping factor - * - * Set the loop filter's damping factor to \p df. The damping - * factor should be sqrt(2)/2.0 for critically damped systems. - * Set it to anything else only if you know what you are - * doing. It must be a number between 0 and 1. - * - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are recalculated by a call to update_gains(). - * - * \param df (float) new damping factor - */ - virtual void set_damping_factor(float df) = 0; - - /*! - * \brief Set the loop gain alpha - * - * Set's the loop filter's alpha gain parameter. - * - * This value should really only be set by adjusting the loop - * bandwidth and damping factor. - * - * \param alpha (float) new alpha gain - */ - virtual void set_alpha(float alpha) = 0; - - /*! - * \brief Set the loop gain beta - * - * Set's the loop filter's beta gain parameter. - * - * This value should really only be set by adjusting the loop - * bandwidth and damping factor. - * - * \param beta (float) new beta gain - */ - virtual void set_beta(float beta) = 0; - - /*! - * Set the maximum deviation from 0 d_rate can have - */ - virtual void set_max_rate_deviation(float m) = 0; - - /******************************************************************* - GET FUNCTIONS - *******************************************************************/ - - /*! - * \brief Returns the loop bandwidth - */ - virtual float loop_bandwidth() const = 0; - - /*! - * \brief Returns the loop damping factor - */ - virtual float damping_factor() const = 0; - - /*! - * \brief Returns the loop gain alpha - */ - virtual float alpha() const = 0; - - /*! - * \brief Returns the loop gain beta - */ - virtual float beta() const = 0; - - /*! - * \brief Returns the current clock rate - */ - virtual float clock_rate() const = 0; - - /*! - * \brief Returns the current error of the control loop. - */ - virtual float error() const = 0; - - /*! - * \brief Returns the current rate of the control loop. - */ - virtual float rate() const = 0; - - /*! - * \brief Returns the current phase arm of the control loop. - */ - virtual float phase() const = 0; - }; - - } /* namespace digital */ + virtual float clock_rate() const = 0; + + /*! + * \brief Returns the current error of the control loop. + */ + virtual float error() const = 0; + + /*! + * \brief Returns the current rate of the control loop. + */ + virtual float rate() const = 0; + + /*! + * \brief Returns the current phase arm of the control loop. + */ + virtual float phase() const = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_PFB_CLOCK_SYNC_CCF_H */ diff --git a/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h b/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h index 67c3d2d17e..90396ba2fc 100644 --- a/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h +++ b/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h @@ -21,312 +21,313 @@ */ #ifndef INCLUDED_DIGITAL_PFB_CLOCK_SYNC_FFF_H -#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_FFF_H +#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_FFF_H #include <gnuradio/digital/api.h> #include <gnuradio/filter/fir_filter.h> #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Timing synchronizer using polyphase filterbanks + * \ingroup synchronizers_blk + * + * \details + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one + * filterbank contains the signal's pulse shaping matched filter + * (such as a root raised cosine filter), where each branch of the + * filterbank contains a different phase of the filter. The + * second filterbank contains the derivatives of the filters in + * the first filterbank. Thinking of this in the time domain, the + * first filterbank contains filters that have a sinc shape to + * them. We want to align the output signal to be sampled at + * exactly the peak of the sinc shape. The derivative of the sinc + * contains a zero at the maximum point of the sinc (sinc(0) = 1, + * sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the + * ith filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error + * in the real and imaginary parts. There are two reasons we + * multiply by the signal itself. First, if the symbol could be + * positive or negative going, but we want the error term to + * always tell us to go in the same direction depending on which + * side of the zero point we are on. The sign of x_i[n] adjusts + * the error term to do this. Second, the magnitude of x_i[n] + * scales the error term depending on the symbol's amplitude, so + * larger signals give us a stronger error term because we have + * more confidence in that symbol's value. Using the magnitude of + * x_i[n] instead of just the sign is especially good for signals + * with low SNR. + * + * The error signal, e[n], gives us a value proportional to how + * far away from the zero point we are in the derivative + * signal. We want to drive this value to zero, so we set up a + * second order loop. We have two variables for this loop; d_k is + * the filter number in the filterbank we are on and d_rate is the + * rate which we travel through the filters in the steady + * state. That is, due to the natural clock differences between + * the transmitter and receiver, d_rate represents that difference + * and would traverse the filter phase paths to keep the receiver + * locked. Thinking of this as a second-order PLL, the d_rate is + * the frequency and d_k is the phase. So we update d_rate and d_k + * using the standard loop equations based on two error signals, + * d_alpha and d_beta. We have these two values set based on each + * other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while + * d_beta is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of + * samples per symbol, because it defaults to return a single + * point representing the symbol. The sps can be any positive real + * number and does not need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of + * the inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is + * suggested in that blog post as the step size for the number of + * radians around the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this + * block is the taps of the filter. One of the benefits of this + * algorithm is that you can put the matched filter in here as the + * taps, so you get both the matched filter and sample timing + * correction in one go. So create your normal matched filter. For + * a typical digital modulation, this is a root raised cosine + * filter. The number of taps of this filter is based on how long + * you expect the channel to be; that is, how many symbols do you + * want to combine to get the current symbols energy back (there's + * probably a better way of stating that). It's usually 5 to 10 or + * so. That gives you your filter, but now we need to think about + * it as a filter with different phase profiles in each filter. So + * take this number of taps and multiply it by the number of + * filters. This is the number you would use to create your + * prototype filter. When you use this in the PFB filerbank, it + * segments these taps into the filterbanks in such a way that + * each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also + * be set and defaults to 32. With 32 filters, you get a good + * enough resolution in the phase to produce very small, almost + * unnoticeable, ISI. Going to 64 filters can reduce this more, + * but after that there is very little gained for the extra + * complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a + * different phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is + * the max_rate_devitation, which defaults to 1.5. This is how far + * we allow d_rate to swing, positive or negative, from + * 0. Constraining the rate can help keep the algorithm from + * walking too far away to lock during times when there is no + * signal. + * + * \li \p osps (default=1): The osps is the number of output + * samples per symbol. By default, the algorithm produces 1 sample + * per symbol, sampled at the exact sample value. This osps value + * was added to better work with equalizers, which do a better job + * of modeling the channel if they have 2 samps/sym. + * + * Reference: + * f. j. harris and M. Rice, "Multirate Digital Filters for Symbol + * Timing Synchronization in Software Defined Radios", IEEE + * Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001. + * + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.127.1757 + */ +class DIGITAL_API pfb_clock_sync_fff : virtual public block +{ +public: + // gr::digital::pfb_clock_sync_fff::sptr + typedef boost::shared_ptr<pfb_clock_sync_fff> sptr; /*! - * \brief Timing synchronizer using polyphase filterbanks - * \ingroup synchronizers_blk - * - * \details - * This block performs timing synchronization for PAM signals by - * minimizing the derivative of the filtered signal, which in turn - * maximizes the SNR and minimizes ISI. - * - * This approach works by setting up two filterbanks; one - * filterbank contains the signal's pulse shaping matched filter - * (such as a root raised cosine filter), where each branch of the - * filterbank contains a different phase of the filter. The - * second filterbank contains the derivatives of the filters in - * the first filterbank. Thinking of this in the time domain, the - * first filterbank contains filters that have a sinc shape to - * them. We want to align the output signal to be sampled at - * exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, - * sinc(0)' = 0). Furthermore, the region around the zero point - * is relatively linear. We make use of this fact to generate the - * error signal. - * - * If the signal out of the derivative filters is d_i[n] for the - * ith filter, and the output of the matched filter is x_i[n], we - * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + - * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error - * in the real and imaginary parts. There are two reasons we - * multiply by the signal itself. First, if the symbol could be - * positive or negative going, but we want the error term to - * always tell us to go in the same direction depending on which - * side of the zero point we are on. The sign of x_i[n] adjusts - * the error term to do this. Second, the magnitude of x_i[n] - * scales the error term depending on the symbol's amplitude, so - * larger signals give us a stronger error term because we have - * more confidence in that symbol's value. Using the magnitude of - * x_i[n] instead of just the sign is especially good for signals - * with low SNR. - * - * The error signal, e[n], gives us a value proportional to how - * far away from the zero point we are in the derivative - * signal. We want to drive this value to zero, so we set up a - * second order loop. We have two variables for this loop; d_k is - * the filter number in the filterbank we are on and d_rate is the - * rate which we travel through the filters in the steady - * state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference - * and would traverse the filter phase paths to keep the receiver - * locked. Thinking of this as a second-order PLL, the d_rate is - * the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, - * d_alpha and d_beta. We have these two values set based on each - * other for a critically damped system, so in the block - * constructor, we just ask for "gain," which is d_alpha while - * d_beta is equal to (gain^2)/4. - * - * The block's parameters are: + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per second in the incoming signal + * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by + * default. \param taps (vector<int>) The filter taps. \param filter_size (uint) The + * number of filters in the filterbank (default = 32). \param init_phase (float) The + * initial phase to look at, or which filter to start with (default = 0). \param + * max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). \param + * osps (int) The number of output samples per symbol (default=1). * - * \li \p sps: The clock sync block needs to know the number of - * samples per symbol, because it defaults to return a single - * point representing the symbol. The sps can be any positive real - * number and does not need to be an integer. - * - * \li \p loop_bw: The loop bandwidth is used to set the gain of - * the inner control loop (see: - * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). - * This should be set small (a value of around 2pi/100 is - * suggested in that blog post as the step size for the number of - * radians around the unit circle to move relative to the error). - * - * \li \p taps: One of the most important parameters for this - * block is the taps of the filter. One of the benefits of this - * algorithm is that you can put the matched filter in here as the - * taps, so you get both the matched filter and sample timing - * correction in one go. So create your normal matched filter. For - * a typical digital modulation, this is a root raised cosine - * filter. The number of taps of this filter is based on how long - * you expect the channel to be; that is, how many symbols do you - * want to combine to get the current symbols energy back (there's - * probably a better way of stating that). It's usually 5 to 10 or - * so. That gives you your filter, but now we need to think about - * it as a filter with different phase profiles in each filter. So - * take this number of taps and multiply it by the number of - * filters. This is the number you would use to create your - * prototype filter. When you use this in the PFB filerbank, it - * segments these taps into the filterbanks in such a way that - * each bank now represents the filter at different phases, - * equally spaced at 2pi/N, where N is the number of filters. - * - * \li \p filter_size (default=32): The number of filters can also - * be set and defaults to 32. With 32 filters, you get a good - * enough resolution in the phase to produce very small, almost - * unnoticeable, ISI. Going to 64 filters can reduce this more, - * but after that there is very little gained for the extra - * complexity. - * - * \li \p init_phase (default=0): The initial phase is another - * settable parameter and refers to the filter path the algorithm - * initially looks at (i.e., d_k starts at init_phase). This value - * defaults to zero, but it might be useful to start at a - * different phase offset, such as the mid-point of the filters. - * - * \li \p max_rate_deviation (default=1.5): The next parameter is - * the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from - * 0. Constraining the rate can help keep the algorithm from - * walking too far away to lock during times when there is no - * signal. - * - * \li \p osps (default=1): The osps is the number of output - * samples per symbol. By default, the algorithm produces 1 sample - * per symbol, sampled at the exact sample value. This osps value - * was added to better work with equalizers, which do a better job - * of modeling the channel if they have 2 samps/sym. - * - * Reference: - * f. j. harris and M. Rice, "Multirate Digital Filters for Symbol - * Timing Synchronization in Software Defined Radios", IEEE - * Selected Areas in Communications, Vol. 19, No. 12, Dec., 2001. - * - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.127.1757 */ - class DIGITAL_API pfb_clock_sync_fff : virtual public block - { - public: - // gr::digital::pfb_clock_sync_fff::sptr - typedef boost::shared_ptr<pfb_clock_sync_fff> sptr; + static sptr make(double sps, + float gain, + const std::vector<float>& taps, + unsigned int filter_size = 32, + float init_phase = 0, + float max_rate_deviation = 1.5, + int osps = 1); - /*! - * Build the polyphase filterbank timing synchronizer. - * \param sps (double) The number of samples per second in the incoming signal - * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by default. - * \param taps (vector<int>) The filter taps. - * \param filter_size (uint) The number of filters in the filterbank (default = 32). - * \param init_phase (float) The initial phase to look at, or which filter to start - * with (default = 0). - * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). - * \param osps (int) The number of output samples per symbol (default=1). - * - */ - static sptr make(double sps, float gain, - const std::vector<float> &taps, - unsigned int filter_size=32, - float init_phase=0, - float max_rate_deviation=1.5, - int osps=1); - - /*! \brief update the system gains from omega and eta - * - * This function updates the system gains based on the loop - * bandwidth and damping factor of the system. - * These two factors can be set separately through their own - * set functions. - */ - virtual void update_gains() = 0; + /*! \brief update the system gains from omega and eta + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + virtual void update_gains() = 0; - /*! - * Resets the filterbank's filter taps with the new prototype filter. - */ - virtual void update_taps(const std::vector<float> &taps) = 0; + /*! + * Resets the filterbank's filter taps with the new prototype filter. + */ + virtual void update_taps(const std::vector<float>& taps) = 0; - /*! - * Used to set the taps of the filters in the filterbank and - * differential filterbank. - * - * WARNING: this should not be used externally and will be moved - * to a private function in the next API. - */ - virtual void set_taps(const std::vector<float> &taps, - std::vector< std::vector<float> > &ourtaps, - std::vector<gr::filter::kernel::fir_filter_fff*> &ourfilter) = 0; + /*! + * Used to set the taps of the filters in the filterbank and + * differential filterbank. + * + * WARNING: this should not be used externally and will be moved + * to a private function in the next API. + */ + virtual void + set_taps(const std::vector<float>& taps, + std::vector<std::vector<float>>& ourtaps, + std::vector<gr::filter::kernel::fir_filter_fff*>& ourfilter) = 0; - /*! - * Returns all of the taps of the matched filter - */ - virtual std::vector< std::vector<float> > taps() const = 0; + /*! + * Returns all of the taps of the matched filter + */ + virtual std::vector<std::vector<float>> taps() const = 0; - /*! - * Returns all of the taps of the derivative filter - */ - virtual std::vector< std::vector<float> > diff_taps() const = 0; + /*! + * Returns all of the taps of the derivative filter + */ + virtual std::vector<std::vector<float>> diff_taps() const = 0; - /*! - * Returns the taps of the matched filter for a particular channel - */ - virtual std::vector<float> channel_taps(int channel) const = 0; + /*! + * Returns the taps of the matched filter for a particular channel + */ + virtual std::vector<float> channel_taps(int channel) const = 0; - /*! - * Returns the taps in the derivative filter for a particular channel - */ - virtual std::vector<float> diff_channel_taps(int channel) const = 0; + /*! + * Returns the taps in the derivative filter for a particular channel + */ + virtual std::vector<float> diff_channel_taps(int channel) const = 0; - /*! - * Return the taps as a formatted string for printing - */ - virtual std::string taps_as_string() const = 0; + /*! + * Return the taps as a formatted string for printing + */ + virtual std::string taps_as_string() const = 0; - /*! - * Return the derivative filter taps as a formatted string for printing - */ - virtual std::string diff_taps_as_string() const = 0; + /*! + * Return the derivative filter taps as a formatted string for printing + */ + virtual std::string diff_taps_as_string() const = 0; - /******************************************************************* - SET FUNCTIONS - *******************************************************************/ + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ - /*! - * \brief Set the loop bandwidth - * - * Set the loop filter's bandwidth to \p bw. This should be - * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be - * a positive number. - * - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are recalculated by a call to update_gains(). - * - * \param bw (float) new bandwidth - */ - virtual void set_loop_bandwidth(float bw) = 0; + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be + * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be + * a positive number. + * + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + */ + virtual void set_loop_bandwidth(float bw) = 0; - /*! - * \brief Set the loop damping factor - * - * Set the loop filter's damping factor to \p df. The damping - * factor should be sqrt(2)/2.0 for critically damped systems. - * Set it to anything else only if you know what you are - * doing. It must be a number between 0 and 1. - * - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are recalculated by a call to update_gains(). - * - * \param df (float) new damping factor - */ - virtual void set_damping_factor(float df) = 0; + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping + * factor should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are + * doing. It must be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + */ + virtual void set_damping_factor(float df) = 0; - /*! - * \brief Set the loop gain alpha - * - * Set's the loop filter's alpha gain parameter. - * - * This value should really only be set by adjusting the loop - * bandwidth and damping factor. - * - * \param alpha (float) new alpha gain - */ - virtual void set_alpha(float alpha) = 0; + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. + * + * \param alpha (float) new alpha gain + */ + virtual void set_alpha(float alpha) = 0; - /*! - * \brief Set the loop gain beta - * - * Set's the loop filter's beta gain parameter. - * - * This value should really only be set by adjusting the loop - * bandwidth and damping factor. - * - * \param beta (float) new beta gain - */ - virtual void set_beta(float beta) = 0; + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. + * + * \param beta (float) new beta gain + */ + virtual void set_beta(float beta) = 0; - /*! - * Set the maximum deviation from 0 d_rate can have - */ - virtual void set_max_rate_deviation(float m) = 0; + /*! + * Set the maximum deviation from 0 d_rate can have + */ + virtual void set_max_rate_deviation(float m) = 0; - /******************************************************************* - GET FUNCTIONS - *******************************************************************/ + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ - /*! - * \brief Returns the loop bandwidth - */ - virtual float loop_bandwidth() const = 0; + /*! + * \brief Returns the loop bandwidth + */ + virtual float loop_bandwidth() const = 0; - /*! - * \brief Returns the loop damping factor - */ - virtual float damping_factor() const = 0; + /*! + * \brief Returns the loop damping factor + */ + virtual float damping_factor() const = 0; - /*! - * \brief Returns the loop gain alpha - */ - virtual float alpha() const = 0; + /*! + * \brief Returns the loop gain alpha + */ + virtual float alpha() const = 0; - /*! - * \brief Returns the loop gain beta - */ - virtual float beta() const = 0; + /*! + * \brief Returns the loop gain beta + */ + virtual float beta() const = 0; - /*! - * \brief Returns the current clock rate - */ - virtual float clock_rate() const = 0; - }; + /*! + * \brief Returns the current clock rate + */ + virtual float clock_rate() const = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_PFB_CLOCK_SYNC_FFF_H */ diff --git a/gr-digital/include/gnuradio/digital/pn_correlator_cc.h b/gr-digital/include/gnuradio/digital/pn_correlator_cc.h index c98f086aa0..f4e9cc12d4 100644 --- a/gr-digital/include/gnuradio/digital/pn_correlator_cc.h +++ b/gr-digital/include/gnuradio/digital/pn_correlator_cc.h @@ -27,37 +27,37 @@ #include <gnuradio/sync_decimator.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief PN code sequential search correlator + * \ingroup synchronizers_blk + * + * \details + * Receives complex baseband signal, outputs complex correlation + * against reference PN code, one sample per PN code period. The + * PN sequence is generated using a GLFSR. + */ +class DIGITAL_API pn_correlator_cc : virtual public sync_decimator +{ +public: + // gr::digital::pn_correlator_cc::sptr + typedef boost::shared_ptr<pn_correlator_cc> sptr; /*! - * \brief PN code sequential search correlator - * \ingroup synchronizers_blk + * \brief Make PN code sequential search correlator block. * - * \details - * Receives complex baseband signal, outputs complex correlation - * against reference PN code, one sample per PN code period. The - * PN sequence is generated using a GLFSR. + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. */ - class DIGITAL_API pn_correlator_cc : virtual public sync_decimator - { - public: - // gr::digital::pn_correlator_cc::sptr - typedef boost::shared_ptr<pn_correlator_cc> sptr; - - /*! - * \brief Make PN code sequential search correlator block. - * - * \param degree Degree of shift register must be in [1, 32]. If mask - * is 0, the degree determines a default mask (see - * digital_impl_glfsr.cc for the mapping). - * \param mask Allows a user-defined bit mask for indexes of the shift - * register to feed back. - * \param seed Initial setting for values in shift register. - */ - static sptr make(int degree, int mask=0, int seed=1); - }; + static sptr make(int degree, int mask = 0, int seed = 1); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_PN_CORRELATOR_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/probe_density_b.h b/gr-digital/include/gnuradio/digital/probe_density_b.h index ff5ce22080..d7afce524b 100644 --- a/gr-digital/include/gnuradio/digital/probe_density_b.h +++ b/gr-digital/include/gnuradio/digital/probe_density_b.h @@ -25,44 +25,44 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \ingroup measurement_tools_blk + * + * This block maintains a running average of the input stream and + * makes it available as an accessor function. The input stream is + * type unsigned char. + * + * If you send this block a stream of unpacked bytes, it will tell + * you what the bit density is. + */ +class DIGITAL_API probe_density_b : virtual public sync_block +{ +public: + // gr::digital::probe_density_b::sptr + typedef boost::shared_ptr<probe_density_b> sptr; /*! - * \ingroup measurement_tools_blk + * Make a density probe block. * - * This block maintains a running average of the input stream and - * makes it available as an accessor function. The input stream is - * type unsigned char. + * \param alpha Average filter constant * - * If you send this block a stream of unpacked bytes, it will tell - * you what the bit density is. */ - class DIGITAL_API probe_density_b : virtual public sync_block - { - public: - // gr::digital::probe_density_b::sptr - typedef boost::shared_ptr<probe_density_b> sptr; - - /*! - * Make a density probe block. - * - * \param alpha Average filter constant - * - */ - static sptr make(double alpha); + static sptr make(double alpha); - /*! - * \brief Returns the current density value - */ - virtual double density() const = 0; + /*! + * \brief Returns the current density value + */ + virtual double density() const = 0; - /*! - * \brief Set the average filter constant - */ - virtual void set_alpha(double alpha) = 0; - }; + /*! + * \brief Set the average filter constant + */ + virtual void set_alpha(double alpha) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_PROBE_DENSITY_B_H */ diff --git a/gr-digital/include/gnuradio/digital/probe_mpsk_snr_est_c.h b/gr-digital/include/gnuradio/digital/probe_mpsk_snr_est_c.h index 615f1a9311..eecfa81762 100644 --- a/gr-digital/include/gnuradio/digital/probe_mpsk_snr_est_c.h +++ b/gr-digital/include/gnuradio/digital/probe_mpsk_snr_est_c.h @@ -28,84 +28,82 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { - /*! - * \brief A probe for computing SNR of a PSK signal. - * \ingroup measurement_tools_blk - * - * \details - * This is a probe block (a sink) that can be used to monitor and - * retrieve estimations of the signal SNR. This probe is designed - * for use with M-PSK signals especially. The type of estimator is - * specified as the \p type parameter in the constructor. The - * estimators tend to trade off performance for accuracy, although - * experimentation should be done to figure out the right approach - * for a given implementation. Further, the current set of - * estimators are designed and proven theoretically under AWGN - * conditions; some amount of error should be assumed and/or - * estimated for real channel conditions. +/*! + * \brief A probe for computing SNR of a PSK signal. + * \ingroup measurement_tools_blk + * + * \details + * This is a probe block (a sink) that can be used to monitor and + * retrieve estimations of the signal SNR. This probe is designed + * for use with M-PSK signals especially. The type of estimator is + * specified as the \p type parameter in the constructor. The + * estimators tend to trade off performance for accuracy, although + * experimentation should be done to figure out the right approach + * for a given implementation. Further, the current set of + * estimators are designed and proven theoretically under AWGN + * conditions; some amount of error should be assumed and/or + * estimated for real channel conditions. + * + * The block has three output message ports that will emit a + * message every msg_samples number of samples. These message + * ports are: + * \li snr: the current SNR estimate (in dB) + * \li signal: the current signal power estimate (in dBx) + * \li noise: the current noise power estimate (in dBx) + * + * Some calibration is required to convert dBx of the signal and + * noise power estimates to real measurements, such as dBm. + */ +class DIGITAL_API probe_mpsk_snr_est_c : virtual public sync_block +{ +public: + // gr::digital::probe_mpsk_snr_est_c::sptr + typedef boost::shared_ptr<probe_mpsk_snr_est_c> sptr; + + /*! Make an MPSK SNR probe. * - * The block has three output message ports that will emit a - * message every msg_samples number of samples. These message - * ports are: - * \li snr: the current SNR estimate (in dB) - * \li signal: the current signal power estimate (in dBx) - * \li noise: the current noise power estimate (in dBx) + * Parameters: * - * Some calibration is required to convert dBx of the signal and - * noise power estimates to real measurements, such as dBm. + * \param type: the type of estimator to use see + * gr::digital::snr_est_type_t for details about the types. + * \param msg_nsamples: [not implemented yet] after this many + * samples, a message containing the SNR (key='snr') will be sent + * \param alpha: the update rate of internal running average + * calculations. */ - class DIGITAL_API probe_mpsk_snr_est_c : virtual public sync_block - { - public: - // gr::digital::probe_mpsk_snr_est_c::sptr - typedef boost::shared_ptr<probe_mpsk_snr_est_c> sptr; - - /*! Make an MPSK SNR probe. - * - * Parameters: - * - * \param type: the type of estimator to use see - * gr::digital::snr_est_type_t for details about the types. - * \param msg_nsamples: [not implemented yet] after this many - * samples, a message containing the SNR (key='snr') will be sent - * \param alpha: the update rate of internal running average - * calculations. - */ - static sptr make(snr_est_type_t type, - int msg_nsamples=10000, - double alpha=0.001); - - //! Return the estimated signal-to-noise ratio in decibels - virtual double snr() = 0; - - //! Return the estimated signal power in decibels - virtual double signal() = 0; - - //! Return the estimated noise power in decibels - virtual double noise() = 0; - - //! Return the type of estimator in use - virtual snr_est_type_t type() const = 0; - - //! Return how many samples between SNR messages - virtual int msg_nsample() const = 0; - - //! Get the running-average coefficient - virtual double alpha() const = 0; - - //! Set type of estimator to use - virtual void set_type(snr_est_type_t t) = 0; - - //! Set the number of samples between SNR messages - virtual void set_msg_nsample(int n) = 0; - - //! Set the running-average coefficient - virtual void set_alpha(double alpha) = 0; - }; - - } /* namespace digital */ + static sptr make(snr_est_type_t type, int msg_nsamples = 10000, double alpha = 0.001); + + //! Return the estimated signal-to-noise ratio in decibels + virtual double snr() = 0; + + //! Return the estimated signal power in decibels + virtual double signal() = 0; + + //! Return the estimated noise power in decibels + virtual double noise() = 0; + + //! Return the type of estimator in use + virtual snr_est_type_t type() const = 0; + + //! Return how many samples between SNR messages + virtual int msg_nsample() const = 0; + + //! Get the running-average coefficient + virtual double alpha() const = 0; + + //! Set type of estimator to use + virtual void set_type(snr_est_type_t t) = 0; + + //! Set the number of samples between SNR messages + virtual void set_msg_nsample(int n) = 0; + + //! Set the running-average coefficient + virtual void set_alpha(double alpha) = 0; +}; + +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_PROBE_MPSK_SNR_EST_C_H */ diff --git a/gr-digital/include/gnuradio/digital/protocol_formatter_async.h b/gr-digital/include/gnuradio/digital/protocol_formatter_async.h index 560a236ce7..67eaf33d20 100644 --- a/gr-digital/include/gnuradio/digital/protocol_formatter_async.h +++ b/gr-digital/include/gnuradio/digital/protocol_formatter_async.h @@ -29,60 +29,60 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Uses a header format object to append a header onto a + * PDU. + * + * \ingroup packet_operators_blk + * + * \details + * This block takes in PDUs and creates a header, generally for + * MAC-level processing. Each received PDU is assumed to be its + * own frame, so any fragmentation would be done upstream in or + * before the flowgraph. + * + * The header that is created and transmitted out of the 'header' + * message port as a PDU. The header is based entirely on the \p + * format object, which is an object derived from the + * header_format_base class. All of these packet header format + * objects operate the same: they take in the payload data as well + * as possible extra metadata info about the PDU; the format + * object then returns the output PDU as a PMT argument along + * with any changes to the metadata info PMT. + * + * For different packet header formatting needs, we can define new + * classes that inherit from the header_format_base block + * and which overload the header_format_base::format + * function. + * + * \sa header_format_base + * \sa header_format_default + * \sa header_format_counter + * + * This block only uses asynchronous message passing interfaces to + * receiver and emit PDUs. The message ports are: + * + * \li in: receives PDUs for the frame payload + * \li header: the header formatted for the given frame + * \li payload: the payload + */ +class DIGITAL_API protocol_formatter_async : virtual public block +{ +public: + typedef boost::shared_ptr<protocol_formatter_async> sptr; /*! - * \brief Uses a header format object to append a header onto a - * PDU. - * - * \ingroup packet_operators_blk - * - * \details - * This block takes in PDUs and creates a header, generally for - * MAC-level processing. Each received PDU is assumed to be its - * own frame, so any fragmentation would be done upstream in or - * before the flowgraph. - * - * The header that is created and transmitted out of the 'header' - * message port as a PDU. The header is based entirely on the \p - * format object, which is an object derived from the - * header_format_base class. All of these packet header format - * objects operate the same: they take in the payload data as well - * as possible extra metadata info about the PDU; the format - * object then returns the output PDU as a PMT argument along - * with any changes to the metadata info PMT. + * Make a packet header block using a given \p format. * - * For different packet header formatting needs, we can define new - * classes that inherit from the header_format_base block - * and which overload the header_format_base::format - * function. - * - * \sa header_format_base - * \sa header_format_default - * \sa header_format_counter - * - * This block only uses asynchronous message passing interfaces to - * receiver and emit PDUs. The message ports are: - * - * \li in: receives PDUs for the frame payload - * \li header: the header formatted for the given frame - * \li payload: the payload + * \param format The format object to use when creating the + * header for the packet. */ - class DIGITAL_API protocol_formatter_async : virtual public block - { - public: - typedef boost::shared_ptr<protocol_formatter_async> sptr; - - /*! - * Make a packet header block using a given \p format. - * - * \param format The format object to use when creating the - * header for the packet. - */ - static sptr make(const header_format_base::sptr &format); - }; + static sptr make(const header_format_base::sptr& format); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_ASYNC_H */ diff --git a/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h b/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h index 2a57fdc75a..81a83a26fb 100644 --- a/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h +++ b/gr-digital/include/gnuradio/digital/protocol_formatter_bb.h @@ -29,53 +29,53 @@ #include <gnuradio/tagged_stream_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Uses a header format object to create a header from a + * tagged stream packet. + * + * \ingroup packet_operators_blk + * + * \details + * This block takes in tagged stream and creates a header, + * generally for MAC-level processing. Each received tagged stream + * is assumed to be its own frame, so any fragmentation would be + * done upstream in or before the flowgraph. + * + * The header that is created and transmitted from this block. The + * payload should then be sent as a parallel tagged stream to be + * muxed together later. The header is based entirely on the \p + * format object, which is an object derived from the + * header_format_base class. All of these packet header format + * objects operate the same: they take in the payload data as well + * as possible extra metadata info about the PDU; the format + * object then returns the output and metadata info. This block + * then transmits the header vector and attaches and metadata as + * tags at the start of the header. + * + * \sa protocol_formatter_async + */ +class DIGITAL_API protocol_formatter_bb : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<protocol_formatter_bb> sptr; /*! - * \brief Uses a header format object to create a header from a - * tagged stream packet. - * - * \ingroup packet_operators_blk - * - * \details - * This block takes in tagged stream and creates a header, - * generally for MAC-level processing. Each received tagged stream - * is assumed to be its own frame, so any fragmentation would be - * done upstream in or before the flowgraph. + * Make a packet header block using a given \p format. * - * The header that is created and transmitted from this block. The - * payload should then be sent as a parallel tagged stream to be - * muxed together later. The header is based entirely on the \p - * format object, which is an object derived from the - * header_format_base class. All of these packet header format - * objects operate the same: they take in the payload data as well - * as possible extra metadata info about the PDU; the format - * object then returns the output and metadata info. This block - * then transmits the header vector and attaches and metadata as - * tags at the start of the header. - * - * \sa protocol_formatter_async + * \param format The format object to use when creating the + * header for the packet. Derived from the + * header_format_base class. + * \param len_tag_key The tagged stream length key. */ - class DIGITAL_API protocol_formatter_bb : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<protocol_formatter_bb> sptr; - - /*! - * Make a packet header block using a given \p format. - * - * \param format The format object to use when creating the - * header for the packet. Derived from the - * header_format_base class. - * \param len_tag_key The tagged stream length key. - */ - static sptr make(const header_format_base::sptr &format, - const std::string &len_tag_key="packet_len"); + static sptr make(const header_format_base::sptr& format, + const std::string& len_tag_key = "packet_len"); - virtual void set_header_format(header_format_base::sptr &format) = 0; - }; + virtual void set_header_format(header_format_base::sptr& format) = 0; +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PROTOCOL_FORMATTER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/protocol_parser_b.h b/gr-digital/include/gnuradio/digital/protocol_parser_b.h index 89c7f7edd3..d3e6b79ccf 100644 --- a/gr-digital/include/gnuradio/digital/protocol_parser_b.h +++ b/gr-digital/include/gnuradio/digital/protocol_parser_b.h @@ -29,52 +29,52 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Block that synchronizes to a header based on a header + * format object class. Designed to accept hard bits and produce + * PDUs with packed bytes (pmt::u8vector). + * + * \ingroup packet_operators_blk + * + * \details + * + * A packet synchronizer block. This block takes in hard bits + * (unpacked bytes; 1's and 0's as the LSB) and finds the access + * code as a sync word to find the start of a frame. + * + * The block uses a format object derived from a + * header_format_base class. + * + * Once the frame is detected (usually through the use of an + * access code), the block uses the format object's parser + * function to decode the remaining header. Generally, as in the + * default header case, the header will contain the length of the + * frame's payload. That and anything else in the header will + * generally go into the PDU's meta-data dictionary. + * + * The block will output a PDU that contains frame's header info + * in the meta-data portion of the PDU and the payload itself. The + * payload is packed hard bits as taken from the input stream. + * + * \sa packet_sync_ff for a soft decision version. + */ +class DIGITAL_API protocol_parser_b : virtual public sync_block +{ +public: + typedef boost::shared_ptr<protocol_parser_b> sptr; /*! - * \brief Block that synchronizes to a header based on a header - * format object class. Designed to accept hard bits and produce - * PDUs with packed bytes (pmt::u8vector). - * - * \ingroup packet_operators_blk - * - * \details - * - * A packet synchronizer block. This block takes in hard bits - * (unpacked bytes; 1's and 0's as the LSB) and finds the access - * code as a sync word to find the start of a frame. + * Make a packet header block using a given \p format. * - * The block uses a format object derived from a - * header_format_base class. - * - * Once the frame is detected (usually through the use of an - * access code), the block uses the format object's parser - * function to decode the remaining header. Generally, as in the - * default header case, the header will contain the length of the - * frame's payload. That and anything else in the header will - * generally go into the PDU's meta-data dictionary. - * - * The block will output a PDU that contains frame's header info - * in the meta-data portion of the PDU and the payload itself. The - * payload is packed hard bits as taken from the input stream. - * - * \sa packet_sync_ff for a soft decision version. + * \param format The format object to use when reading the + * header. */ - class DIGITAL_API protocol_parser_b : virtual public sync_block - { - public: - typedef boost::shared_ptr<protocol_parser_b> sptr; - - /*! - * Make a packet header block using a given \p format. - * - * \param format The format object to use when reading the - * header. - */ - static sptr make(const header_format_base::sptr &format); - }; + static sptr make(const header_format_base::sptr& format); +}; - } // namespace digital +} // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_PROTOCOL_PARSER_B_H */ diff --git a/gr-digital/include/gnuradio/digital/scrambler_bb.h b/gr-digital/include/gnuradio/digital/scrambler_bb.h index 4ba83daf60..a7197bfefd 100644 --- a/gr-digital/include/gnuradio/digital/scrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/scrambler_bb.h @@ -27,34 +27,34 @@ #include <gnuradio/sync_block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief Scramble an input stream using an LFSR. + * \ingroup coding_blk + * + * \details + * This block works on the LSB only of the input data stream, + * i.e., on an "unpacked binary" stream, and produces the same + * format on its output. + */ +class DIGITAL_API scrambler_bb : virtual public sync_block +{ +public: + // gr::digital::scrambler_bb::sptr + typedef boost::shared_ptr<scrambler_bb> sptr; /*! - * \brief Scramble an input stream using an LFSR. - * \ingroup coding_blk + * Make a scramber block. * - * \details - * This block works on the LSB only of the input data stream, - * i.e., on an "unpacked binary" stream, and produces the same - * format on its output. + * \param mask Polynomial mask for LFSR + * \param seed Initial shift register contents + * \param len Shift register length */ - class DIGITAL_API scrambler_bb : virtual public sync_block - { - public: - // gr::digital::scrambler_bb::sptr - typedef boost::shared_ptr<scrambler_bb> sptr; - - /*! - * Make a scramber block. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - */ - static sptr make(int mask, int seed, int len); - }; + static sptr make(int mask, int seed, int len); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_SCRAMBLER_BB_H */ diff --git a/gr-digital/include/gnuradio/digital/simple_correlator.h b/gr-digital/include/gnuradio/digital/simple_correlator.h index 763705c6b9..93e3b39eac 100644 --- a/gr-digital/include/gnuradio/digital/simple_correlator.h +++ b/gr-digital/include/gnuradio/digital/simple_correlator.h @@ -27,23 +27,23 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { - - /*! - * \brief inverse of simple_framer (more or less) - * \ingroup packet_operators_blk - * \ingroup deprecated_blk - */ - class DIGITAL_API simple_correlator : virtual public block - { - public: - // gr::digital::simple_correlator::sptr - typedef boost::shared_ptr<simple_correlator> sptr; +namespace digital { - static sptr make(int payload_bytesize); - }; +/*! + * \brief inverse of simple_framer (more or less) + * \ingroup packet_operators_blk + * \ingroup deprecated_blk + */ +class DIGITAL_API simple_correlator : virtual public block +{ +public: + // gr::digital::simple_correlator::sptr + typedef boost::shared_ptr<simple_correlator> sptr; + + static sptr make(int payload_bytesize); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_SIMPLE_CORRELATOR_H */ diff --git a/gr-digital/include/gnuradio/digital/simple_framer.h b/gr-digital/include/gnuradio/digital/simple_framer.h index cddb152ca3..91edfb05c2 100644 --- a/gr-digital/include/gnuradio/digital/simple_framer.h +++ b/gr-digital/include/gnuradio/digital/simple_framer.h @@ -27,33 +27,33 @@ #include <gnuradio/block.h> namespace gr { - namespace digital { +namespace digital { + +/*! + * \brief add sync field, seq number and command field to payload + * \ingroup packet_operators_blk + * \ingroup deprecated_blk + * + * \details + * Takes in enough samples to create a full output frame. The + * frame is prepended with the GRSF_SYNC (defined in + * simple_framer_sync.h) and an 8-bit sequence number. + */ +class DIGITAL_API simple_framer : virtual public block +{ +public: + // gr::digital::simple_framer::sptr + typedef boost::shared_ptr<simple_framer> sptr; /*! - * \brief add sync field, seq number and command field to payload - * \ingroup packet_operators_blk - * \ingroup deprecated_blk + * Make a simple_framer block. * - * \details - * Takes in enough samples to create a full output frame. The - * frame is prepended with the GRSF_SYNC (defined in - * simple_framer_sync.h) and an 8-bit sequence number. + * \param payload_bytesize The size of the payload in bytes. */ - class DIGITAL_API simple_framer : virtual public block - { - public: - // gr::digital::simple_framer::sptr - typedef boost::shared_ptr<simple_framer> sptr; - - /*! - * Make a simple_framer block. - * - * \param payload_bytesize The size of the payload in bytes. - */ - static sptr make(int payload_bytesize); - }; + static sptr make(int payload_bytesize); +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_SIMPLE_FRAMER_H */ diff --git a/gr-digital/include/gnuradio/digital/simple_framer_sync.h b/gr-digital/include/gnuradio/digital/simple_framer_sync.h index f6c8f148e6..532a9937c0 100644 --- a/gr-digital/include/gnuradio/digital/simple_framer_sync.h +++ b/gr-digital/include/gnuradio/digital/simple_framer_sync.h @@ -24,33 +24,34 @@ #define INCLUDED_GR_SIMPLE_FRAMER_SYNC_H namespace gr { - namespace digital { +namespace digital { - /*! - * Here are a couple of maximum length sequences (m-sequences) - * that were generated by the the "mseq" matlab/octave code - * downloaded from: <a - * href="http://www.mathworks.com/matlabcentral/fileexchange/990">http://www.mathworks.com/matlabcentral/fileexchange/990</a> - * - * <pre> - * 31-bit m-sequence: - * 0110100100001010111011000111110 - * 0x690AEC76 (padded on right with a zero) - * - * 63-bit m-sequence: - * 101011001101110110100100111000101111001010001100001000001111110 - * 0xACDDA4E2F28C20FC (padded on right with a zero) - * </pre> - */ - static const unsigned long long GRSF_SYNC = 0xacdda4e2f28c20fcULL; +/*! + * Here are a couple of maximum length sequences (m-sequences) + * that were generated by the the "mseq" matlab/octave code + * downloaded from: <a + * href="http://www.mathworks.com/matlabcentral/fileexchange/990">http://www.mathworks.com/matlabcentral/fileexchange/990</a> + * + * <pre> + * 31-bit m-sequence: + * 0110100100001010111011000111110 + * 0x690AEC76 (padded on right with a zero) + * + * 63-bit m-sequence: + * 101011001101110110100100111000101111001010001100001000001111110 + * 0xACDDA4E2F28C20FC (padded on right with a zero) + * </pre> + */ +static const unsigned long long GRSF_SYNC = 0xacdda4e2f28c20fcULL; - static const int GRSF_BITS_PER_BYTE = 8; - static const int GRSF_SYNC_OVERHEAD = sizeof(GRSF_SYNC); - static const int GRSF_PAYLOAD_OVERHEAD = 1; // 1 byte seqno - static const int GRSF_TAIL_PAD = 1; // one byte trailing padding - static const int GRSF_OVERHEAD = GRSF_SYNC_OVERHEAD + GRSF_PAYLOAD_OVERHEAD + GRSF_TAIL_PAD; +static const int GRSF_BITS_PER_BYTE = 8; +static const int GRSF_SYNC_OVERHEAD = sizeof(GRSF_SYNC); +static const int GRSF_PAYLOAD_OVERHEAD = 1; // 1 byte seqno +static const int GRSF_TAIL_PAD = 1; // one byte trailing padding +static const int GRSF_OVERHEAD = + GRSF_SYNC_OVERHEAD + GRSF_PAYLOAD_OVERHEAD + GRSF_TAIL_PAD; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_GR_SIMPLE_FRAMER_SYNC_H */ diff --git a/gr-digital/include/gnuradio/digital/symbol_sync_cc.h b/gr-digital/include/gnuradio/digital/symbol_sync_cc.h index 24cd0a14de..3bfb971b8d 100644 --- a/gr-digital/include/gnuradio/digital/symbol_sync_cc.h +++ b/gr-digital/include/gnuradio/digital/symbol_sync_cc.h @@ -30,11 +30,36 @@ #include <gnuradio/digital/interpolating_resampler_type.h> namespace gr { - namespace digital { - +namespace digital { + +/*! + * \brief Symbol Synchronizer block with complex input, complex output. + * \ingroup synchronizers_blk + * + * \details + * This implements a discrete-time error-tracking synchronizer. + * + * For this block to work properly, the input stream must meet the + * following requirements: + * + * 1. if not using the PFB Matched Filter interpolator, and using + * a non-CPM timing error detector, the input pulses must have peaks + * (not flat), which usually can be implemented by using a matched + * filter before this block. + * + * 2. for decision directed timing error detectors, the input pulses + * should nominally match the normalized slicer constellation, which + * is normalized to an average symbol magnitude of 1.0 over the entire + * constellation. + */ +class DIGITAL_API symbol_sync_cc : virtual public block +{ +public: + // gr::digital::symbol_sync_cc::sptr + typedef boost::shared_ptr<symbol_sync_cc> sptr; + /*! - * \brief Symbol Synchronizer block with complex input, complex output. - * \ingroup synchronizers_blk + * Make a Symbol Synchronizer block. * * \details * This implements a discrete-time error-tracking synchronizer. @@ -51,266 +76,241 @@ namespace gr { * should nominally match the normalized slicer constellation, which * is normalized to an average symbol magnitude of 1.0 over the entire * constellation. + * + * \param detector_type + * The enumerated type of timing error detector to use. + * See enum ted_type for a list of possible types. + * + * \param sps + * User specified nominal clock period in samples per symbol. + * + * \param loop_bw + * Approximate normailzed loop bandwidth of the symbol clock tracking + * loop. It should nominally be close to 0, but greater than 0. If + * unsure, start with a number around 2*pi*0.040, and experiment to find + * the value that works best for your situation. + * + * \param damping_factor + * Damping factor of the symbol clock tracking loop. + * Damping < 1.0f is an under-damped loop. + * Damping = 1.0f/sqrt(2.0f) is a maximally flat loop response. + * Damping = 1.0f is a critically-damped loop. + * Damping > 1.0f is an over-damped loop. + * + * \param ted_gain + * Expected gain of the timing error detector, given the TED in use + * and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * \param max_deviation + * Maximum absolute deviation of the average clock period estimate + * from the user specified nominal clock period in samples per symbol. + * + * \param osps + * The number of output samples per symbol (default=1). + * + * \param slicer + * A constellation obj shared pointer that will be used by + * decision directed timing error detectors to make decisions. + * I.e. the timing error detector will use this constellation + * as a slicer, if the particular algorithm needs sliced + * symbols. + * + * \param interp_type + * The enumerated type of interpolating resampler to use. + * See the interpolating resampler type enum for a list of possible types. + * + * \param n_filters + * The number of arms in the polyphase filterbank of the interpolating + * resampler, if using an interpolating resampler that uses a PFB. + * + * \param taps + * The prototype filter for the polyphase filterbank of the interpolating + * resampler, if using an interpolating resampler that uses a PFB. */ - class DIGITAL_API symbol_sync_cc : virtual public block - { - public: - // gr::digital::symbol_sync_cc::sptr - typedef boost::shared_ptr<symbol_sync_cc> sptr; + static sptr make(enum ted_type detector_type, + float sps, + float loop_bw, + float damping_factor = 1.0f, + float ted_gain = 1.0f, + float max_deviation = 1.5f, + int osps = 1, + constellation_sptr slicer = constellation_sptr(), + ir_type interp_type = IR_MMSE_8TAP, + int n_filters = 128, + const std::vector<float>& taps = std::vector<float>()); - /*! - * Make a Symbol Synchronizer block. - * - * \details - * This implements a discrete-time error-tracking synchronizer. - * - * For this block to work properly, the input stream must meet the - * following requirements: - * - * 1. if not using the PFB Matched Filter interpolator, and using - * a non-CPM timing error detector, the input pulses must have peaks - * (not flat), which usually can be implemented by using a matched - * filter before this block. - * - * 2. for decision directed timing error detectors, the input pulses - * should nominally match the normalized slicer constellation, which - * is normalized to an average symbol magnitude of 1.0 over the entire - * constellation. - * - * \param detector_type - * The enumerated type of timing error detector to use. - * See enum ted_type for a list of possible types. - * - * \param sps - * User specified nominal clock period in samples per symbol. - * - * \param loop_bw - * Approximate normailzed loop bandwidth of the symbol clock tracking - * loop. It should nominally be close to 0, but greater than 0. If - * unsure, start with a number around 2*pi*0.040, and experiment to find - * the value that works best for your situation. - * - * \param damping_factor - * Damping factor of the symbol clock tracking loop. - * Damping < 1.0f is an under-damped loop. - * Damping = 1.0f/sqrt(2.0f) is a maximally flat loop response. - * Damping = 1.0f is a critically-damped loop. - * Damping > 1.0f is an over-damped loop. - * - * \param ted_gain - * Expected gain of the timing error detector, given the TED in use - * and the anticipated input amplitude, pulse shape, and Es/No. - * This value is the slope of the TED's S-curve at timing offset tau = 0. - * This value is normally computed by the user analytically or by - * simulation in a tool outside of GNURadio. - * This value must be correct for the loop filter gains to be computed - * properly from the desired input loop bandwidth and damping factor. - * - * \param max_deviation - * Maximum absolute deviation of the average clock period estimate - * from the user specified nominal clock period in samples per symbol. - * - * \param osps - * The number of output samples per symbol (default=1). - * - * \param slicer - * A constellation obj shared pointer that will be used by - * decision directed timing error detectors to make decisions. - * I.e. the timing error detector will use this constellation - * as a slicer, if the particular algorithm needs sliced - * symbols. - * - * \param interp_type - * The enumerated type of interpolating resampler to use. - * See the interpolating resampler type enum for a list of possible types. - * - * \param n_filters - * The number of arms in the polyphase filterbank of the interpolating - * resampler, if using an interpolating resampler that uses a PFB. - * - * \param taps - * The prototype filter for the polyphase filterbank of the interpolating - * resampler, if using an interpolating resampler that uses a PFB. - */ - static sptr make(enum ted_type detector_type, - float sps, - float loop_bw, - float damping_factor = 1.0f, - float ted_gain = 1.0f, - float max_deviation = 1.5f, - int osps = 1, - constellation_sptr slicer = constellation_sptr(), - ir_type interp_type = IR_MMSE_8TAP, - int n_filters = 128, - const std::vector<float> &taps = std::vector<float>()); - - /*! - * \brief Returns the normalized approximate loop bandwidth. - * - * \details - * See the documentation for set_loop_bandwidth() for more details. - * - * Note that if set_alpha() or set_beta() were called to directly - * set gains, the value returned by this method will be inaccurate/stale. - */ - virtual float loop_bandwidth() const = 0; + /*! + * \brief Returns the normalized approximate loop bandwidth. + * + * \details + * See the documentation for set_loop_bandwidth() for more details. + * + * Note that if set_alpha() or set_beta() were called to directly + * set gains, the value returned by this method will be inaccurate/stale. + */ + virtual float loop_bandwidth() const = 0; - /*! - * \brief Returns the loop damping factor. - * - * \details - * See the documentation for set_damping_factor() for more details. - * - * Note that if set_alpha() or set_beta() were called to directly - * set gains, the value returned by this method will be inaccurate/stale. - */ - virtual float damping_factor() const = 0; + /*! + * \brief Returns the loop damping factor. + * + * \details + * See the documentation for set_damping_factor() for more details. + * + * Note that if set_alpha() or set_beta() were called to directly + * set gains, the value returned by this method will be inaccurate/stale. + */ + virtual float damping_factor() const = 0; - /*! - * \brief Returns the user provided expected gain of the Timing Error - * Detector. - * - * \details - * See the documentation for set_ted_gain() for more details. - */ - virtual float ted_gain() const = 0; + /*! + * \brief Returns the user provided expected gain of the Timing Error + * Detector. + * + * \details + * See the documentation for set_ted_gain() for more details. + */ + virtual float ted_gain() const = 0; - /*! - * \brief Returns the PI filter proportional gain, alpha. - * - * \details - * See the documentation for set_alpha() for more details. - */ - virtual float alpha() const = 0; + /*! + * \brief Returns the PI filter proportional gain, alpha. + * + * \details + * See the documentation for set_alpha() for more details. + */ + virtual float alpha() const = 0; - /*! - * \brief Returns the PI filter integral gain, beta. - * - * \details - * See the documentation for set_beta() for more details. - */ - virtual float beta() const = 0; + /*! + * \brief Returns the PI filter integral gain, beta. + * + * \details + * See the documentation for set_beta() for more details. + */ + virtual float beta() const = 0; - /*! - * \brief Set the normalized approximate loop bandwidth. - * - * \details - * Set the normalized approximate loop bandwidth. - * Useful values are usually close to 0.0, e.g. 2*pi*0.045. - * - * It should be a small positive number, corresponding to the normalized - * natural radian frequency of the loop as digital low-pass filter that is - * filtering the clock phase/timing error. - * - * Technically this parameter corresponds to the natural radian frequency - * of the 2nd order loop transfer function (scaled by Fs), - * which is the radius of the pole locations in the s-plane of an - * underdamped analog 2nd order system. - * - * The input parameter corresponds to omega_n_norm in the following - * relation: - * - * omega_n_norm = omega_n*T = 2*pi*f_n*T = 2*pi*f_n_norm - * - * where T is the period of the clock being estimated by this - * clock tracking loop, and omega_n is the natural radian frequency - * of the 2nd order loop transfer function. - * - * When a new loop bandwidth is set, the gains, alpha and beta, - * of the loop are automatically recalculated. - * - * \param omega_n_norm normalized approximate loop bandwidth - */ - virtual void set_loop_bandwidth (float omega_n_norm) = 0; + /*! + * \brief Set the normalized approximate loop bandwidth. + * + * \details + * Set the normalized approximate loop bandwidth. + * Useful values are usually close to 0.0, e.g. 2*pi*0.045. + * + * It should be a small positive number, corresponding to the normalized + * natural radian frequency of the loop as digital low-pass filter that is + * filtering the clock phase/timing error. + * + * Technically this parameter corresponds to the natural radian frequency + * of the 2nd order loop transfer function (scaled by Fs), + * which is the radius of the pole locations in the s-plane of an + * underdamped analog 2nd order system. + * + * The input parameter corresponds to omega_n_norm in the following + * relation: + * + * omega_n_norm = omega_n*T = 2*pi*f_n*T = 2*pi*f_n_norm + * + * where T is the period of the clock being estimated by this + * clock tracking loop, and omega_n is the natural radian frequency + * of the 2nd order loop transfer function. + * + * When a new loop bandwidth is set, the gains, alpha and beta, + * of the loop are automatically recalculated. + * + * \param omega_n_norm normalized approximate loop bandwidth + */ + virtual void set_loop_bandwidth(float omega_n_norm) = 0; - /*! - * \brief Set the loop damping factor. - * - * \details - * Set the damping factor of the loop. - * Damping in the range (0.0, 1.0) yields an under-damped loop. - * Damping in the range (1.0, Inf) yields an over-damped loop. - * Damping equal to 1.0 yields a crtically-damped loop. - * Damping equal to 1.0/sqrt(2.0) yields a maximally flat - * loop filter response. - * - * Damping factor of the 2nd order loop transfer function. - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are automatcally recalculated. - * - * \param zeta loop damping factor - */ - virtual void set_damping_factor (float zeta) = 0; + /*! + * \brief Set the loop damping factor. + * + * \details + * Set the damping factor of the loop. + * Damping in the range (0.0, 1.0) yields an under-damped loop. + * Damping in the range (1.0, Inf) yields an over-damped loop. + * Damping equal to 1.0 yields a crtically-damped loop. + * Damping equal to 1.0/sqrt(2.0) yields a maximally flat + * loop filter response. + * + * Damping factor of the 2nd order loop transfer function. + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param zeta loop damping factor + */ + virtual void set_damping_factor(float zeta) = 0; - /*! - * \brief Set the expected gain of the Timing Error Detector. - * - * \details - * Sets the expected gain of the timing error detector, given the TED in - * use and the anticipated input amplitude, pulse shape, and Es/No. - * This value is the slope of the TED's S-curve at timing offset tau = 0. - * This value is normally computed by the user analytically or by - * simulation in a tool outside of GNURadio. - * This value must be correct for the loop filter gains to be computed - * properly from the desired input loop bandwidth and damping factor. - * - * When a new ted_gain is set, the gains, alpha and beta, - * of the loop are automatcally recalculated. - * - * \param ted_gain expected gain of the timing error detector - */ - virtual void set_ted_gain (float ted_gain) = 0; + /*! + * \brief Set the expected gain of the Timing Error Detector. + * + * \details + * Sets the expected gain of the timing error detector, given the TED in + * use and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * When a new ted_gain is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param ted_gain expected gain of the timing error detector + */ + virtual void set_ted_gain(float ted_gain) = 0; - /*! - * \brief Set the PI filter proportional gain, alpha. - * - * \details - * Sets the PI filter proportional gain, alpha. - * This gain directly mutliplies the clock phase/timing error - * term in the PI filter when advancing the loop. - * It most directly affects the instantaneous clock period estimate, - * T_inst, and instantaneous clock phase estimate, tau. - * - * This value would normally be adjusted by setting the loop - * bandwidth and damping factor. However, - * it can be set here directly if desired. - * - * Setting this parameter directly is probably only feasible if - * the user is directly observing the estimates of average clock - * period and instantaneous clock period over time in response to - * an impulsive change in the input stream (i.e. watching the loop - * transient behavior at the start of a data burst). - * - * \param alpha PI filter proportional gain - */ - virtual void set_alpha (float alpha) = 0; + /*! + * \brief Set the PI filter proportional gain, alpha. + * + * \details + * Sets the PI filter proportional gain, alpha. + * This gain directly mutliplies the clock phase/timing error + * term in the PI filter when advancing the loop. + * It most directly affects the instantaneous clock period estimate, + * T_inst, and instantaneous clock phase estimate, tau. + * + * This value would normally be adjusted by setting the loop + * bandwidth and damping factor. However, + * it can be set here directly if desired. + * + * Setting this parameter directly is probably only feasible if + * the user is directly observing the estimates of average clock + * period and instantaneous clock period over time in response to + * an impulsive change in the input stream (i.e. watching the loop + * transient behavior at the start of a data burst). + * + * \param alpha PI filter proportional gain + */ + virtual void set_alpha(float alpha) = 0; - /*! - * \brief Set the PI filter integral gain, beta. - * - * \details - * Sets the PI filter integral gain, beta. - * This gain is used when integrating the clock phase/timing error - * term in the PI filter when advancing the loop. - * It most directly affects the average clock period estimate, - * T_avg. - * - * This value would normally be adjusted by setting the loop - * bandwidth and damping factor. However, - * it can be set here directly if desired. - * - * Setting this parameter directly is probably only feasible if - * the user is directly observing the estimates of average clock - * period and instantaneous clock period over time in response to - * an impulsive change in the input stream (i.e. watching the loop - * transient behavior at the start of a data burst). - * - * \param beta PI filter integral gain - */ - virtual void set_beta (float beta) = 0; - }; + /*! + * \brief Set the PI filter integral gain, beta. + * + * \details + * Sets the PI filter integral gain, beta. + * This gain is used when integrating the clock phase/timing error + * term in the PI filter when advancing the loop. + * It most directly affects the average clock period estimate, + * T_avg. + * + * This value would normally be adjusted by setting the loop + * bandwidth and damping factor. However, + * it can be set here directly if desired. + * + * Setting this parameter directly is probably only feasible if + * the user is directly observing the estimates of average clock + * period and instantaneous clock period over time in response to + * an impulsive change in the input stream (i.e. watching the loop + * transient behavior at the start of a data burst). + * + * \param beta PI filter integral gain + */ + virtual void set_beta(float beta) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_SYMBOL_SYNC_CC_H */ diff --git a/gr-digital/include/gnuradio/digital/symbol_sync_ff.h b/gr-digital/include/gnuradio/digital/symbol_sync_ff.h index 027ecca520..45d3f93266 100644 --- a/gr-digital/include/gnuradio/digital/symbol_sync_ff.h +++ b/gr-digital/include/gnuradio/digital/symbol_sync_ff.h @@ -30,11 +30,36 @@ #include <gnuradio/digital/interpolating_resampler_type.h> namespace gr { - namespace digital { - +namespace digital { + +/*! + * \brief Symbol Synchronizer block with float input, float output. + * \ingroup synchronizers_blk + * + * \details + * This implements a discrete-time error-tracking synchronizer. + * + * For this block to work properly, the input stream must meet the + * following requirements: + * + * 1. if not using the PFB Matched Filter interpolator, and using + * a non-CPM timing error detector, the input pulses must have peaks + * (not flat), which usually can be implemented by using a matched + * filter before this block. + * + * 2. for decision directed timing error detectors, the input pulses + * should nominally match the normalized slicer constellation, which + * is normalized to an average symbol magnitude of 1.0 over the entire + * constellation. + */ +class DIGITAL_API symbol_sync_ff : virtual public block +{ +public: + // gr::digital::symbol_sync_ff::sptr + typedef boost::shared_ptr<symbol_sync_ff> sptr; + /*! - * \brief Symbol Synchronizer block with float input, float output. - * \ingroup synchronizers_blk + * Make a Symbol Synchronizer block. * * \details * This implements a discrete-time error-tracking synchronizer. @@ -51,266 +76,241 @@ namespace gr { * should nominally match the normalized slicer constellation, which * is normalized to an average symbol magnitude of 1.0 over the entire * constellation. + * + * \param detector_type + * The enumerated type of timing error detector to use. + * See enum ted_type for a list of possible types. + * + * \param sps + * User specified nominal clock period in samples per symbol. + * + * \param loop_bw + * Approximate normailzed loop bandwidth of the symbol clock tracking + * loop. It should nominally be close to 0, but greater than 0. If + * unsure, start with a number around 2*pi*0.040, and experiment to find + * the value that works best for your situation. + * + * \param damping_factor + * Damping factor of the symbol clock tracking loop. + * Damping < 1.0f is an under-damped loop. + * Damping = 1.0f/sqrt(2.0f) is a maximally flat loop response. + * Damping = 1.0f is a critically-damped loop. + * Damping > 1.0f is an over-damped loop. + * + * \param ted_gain + * Expected gain of the timing error detector, given the TED in use + * and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * \param max_deviation + * Maximum absolute deviation of the average clock period estimate + * from the user specified nominal clock period in samples per symbol. + * + * \param osps + * The number of output samples per symbol (default=1). + * + * \param slicer + * A constellation obj shared pointer that will be used by + * decision directed timing error detectors to make decisions. + * I.e. the timing error detector will use this constellation + * as a slicer, if the particular algorithm needs sliced + * symbols. + * + * \param interp_type + * The enumerated type of interpolating resampler to use. + * See the interpolating resampler type enum for a list of possible types. + * + * \param n_filters + * The number of arms in the polyphase filterbank of the interpolating + * resampler, if using an interpolating resampler that uses a PFB. + * + * \param taps + * The prototype filter for the polyphase filterbank of the interpolating + * resampler, if using an interpolating resampler that uses a PFB. */ - class DIGITAL_API symbol_sync_ff : virtual public block - { - public: - // gr::digital::symbol_sync_ff::sptr - typedef boost::shared_ptr<symbol_sync_ff> sptr; + static sptr make(enum ted_type detector_type, + float sps, + float loop_bw, + float damping_factor = 1.0f, + float ted_gain = 1.0f, + float max_deviation = 1.5f, + int osps = 1, + constellation_sptr slicer = constellation_sptr(), + ir_type interp_type = IR_MMSE_8TAP, + int n_filters = 128, + const std::vector<float>& taps = std::vector<float>()); - /*! - * Make a Symbol Synchronizer block. - * - * \details - * This implements a discrete-time error-tracking synchronizer. - * - * For this block to work properly, the input stream must meet the - * following requirements: - * - * 1. if not using the PFB Matched Filter interpolator, and using - * a non-CPM timing error detector, the input pulses must have peaks - * (not flat), which usually can be implemented by using a matched - * filter before this block. - * - * 2. for decision directed timing error detectors, the input pulses - * should nominally match the normalized slicer constellation, which - * is normalized to an average symbol magnitude of 1.0 over the entire - * constellation. - * - * \param detector_type - * The enumerated type of timing error detector to use. - * See enum ted_type for a list of possible types. - * - * \param sps - * User specified nominal clock period in samples per symbol. - * - * \param loop_bw - * Approximate normailzed loop bandwidth of the symbol clock tracking - * loop. It should nominally be close to 0, but greater than 0. If - * unsure, start with a number around 2*pi*0.040, and experiment to find - * the value that works best for your situation. - * - * \param damping_factor - * Damping factor of the symbol clock tracking loop. - * Damping < 1.0f is an under-damped loop. - * Damping = 1.0f/sqrt(2.0f) is a maximally flat loop response. - * Damping = 1.0f is a critically-damped loop. - * Damping > 1.0f is an over-damped loop. - * - * \param ted_gain - * Expected gain of the timing error detector, given the TED in use - * and the anticipated input amplitude, pulse shape, and Es/No. - * This value is the slope of the TED's S-curve at timing offset tau = 0. - * This value is normally computed by the user analytically or by - * simulation in a tool outside of GNURadio. - * This value must be correct for the loop filter gains to be computed - * properly from the desired input loop bandwidth and damping factor. - * - * \param max_deviation - * Maximum absolute deviation of the average clock period estimate - * from the user specified nominal clock period in samples per symbol. - * - * \param osps - * The number of output samples per symbol (default=1). - * - * \param slicer - * A constellation obj shared pointer that will be used by - * decision directed timing error detectors to make decisions. - * I.e. the timing error detector will use this constellation - * as a slicer, if the particular algorithm needs sliced - * symbols. - * - * \param interp_type - * The enumerated type of interpolating resampler to use. - * See the interpolating resampler type enum for a list of possible types. - * - * \param n_filters - * The number of arms in the polyphase filterbank of the interpolating - * resampler, if using an interpolating resampler that uses a PFB. - * - * \param taps - * The prototype filter for the polyphase filterbank of the interpolating - * resampler, if using an interpolating resampler that uses a PFB. - */ - static sptr make(enum ted_type detector_type, - float sps, - float loop_bw, - float damping_factor = 1.0f, - float ted_gain = 1.0f, - float max_deviation = 1.5f, - int osps = 1, - constellation_sptr slicer = constellation_sptr(), - ir_type interp_type = IR_MMSE_8TAP, - int n_filters = 128, - const std::vector<float> &taps = std::vector<float>()); - - /*! - * \brief Returns the normalized approximate loop bandwidth. - * - * \details - * See the documentation for set_loop_bandwidth() for more details. - * - * Note that if set_alpha() or set_beta() were called to directly - * set gains, the value returned by this method will be inaccurate/stale. - */ - virtual float loop_bandwidth() const = 0; + /*! + * \brief Returns the normalized approximate loop bandwidth. + * + * \details + * See the documentation for set_loop_bandwidth() for more details. + * + * Note that if set_alpha() or set_beta() were called to directly + * set gains, the value returned by this method will be inaccurate/stale. + */ + virtual float loop_bandwidth() const = 0; - /*! - * \brief Returns the loop damping factor. - * - * \details - * See the documentation for set_damping_factor() for more details. - * - * Note that if set_alpha() or set_beta() were called to directly - * set gains, the value returned by this method will be inaccurate/stale. - */ - virtual float damping_factor() const = 0; + /*! + * \brief Returns the loop damping factor. + * + * \details + * See the documentation for set_damping_factor() for more details. + * + * Note that if set_alpha() or set_beta() were called to directly + * set gains, the value returned by this method will be inaccurate/stale. + */ + virtual float damping_factor() const = 0; - /*! - * \brief Returns the user provided expected gain of the Timing Error - * Detector. - * - * \details - * See the documentation for set_ted_gain() for more details. - */ - virtual float ted_gain() const = 0; + /*! + * \brief Returns the user provided expected gain of the Timing Error + * Detector. + * + * \details + * See the documentation for set_ted_gain() for more details. + */ + virtual float ted_gain() const = 0; - /*! - * \brief Returns the PI filter proportional gain, alpha. - * - * \details - * See the documentation for set_alpha() for more details. - */ - virtual float alpha() const = 0; + /*! + * \brief Returns the PI filter proportional gain, alpha. + * + * \details + * See the documentation for set_alpha() for more details. + */ + virtual float alpha() const = 0; - /*! - * \brief Returns the PI filter integral gain, beta. - * - * \details - * See the documentation for set_beta() for more details. - */ - virtual float beta() const = 0; + /*! + * \brief Returns the PI filter integral gain, beta. + * + * \details + * See the documentation for set_beta() for more details. + */ + virtual float beta() const = 0; - /*! - * \brief Set the normalized approximate loop bandwidth. - * - * \details - * Set the normalized approximate loop bandwidth. - * Useful values are usually close to 0.0, e.g. 2*pi*0.045. - * - * It should be a small positive number, corresponding to the normalized - * natural radian frequency of the loop as digital low-pass filter that is - * filtering the clock phase/timing error. - * - * Technically this parameter corresponds to the natural radian frequency - * of the 2nd order loop transfer function (scaled by Fs), - * which is the radius of the pole locations in the s-plane of an - * underdamped analog 2nd order system. - * - * The input parameter corresponds to omega_n_norm in the following - * relation: - * - * omega_n_norm = omega_n*T = 2*pi*f_n*T = 2*pi*f_n_norm - * - * where T is the period of the clock being estimated by this - * clock tracking loop, and omega_n is the natural radian frequency - * of the 2nd order loop transfer function. - * - * When a new loop bandwidth is set, the gains, alpha and beta, - * of the loop are automatically recalculated. - * - * \param omega_n_norm normalized approximate loop bandwidth - */ - virtual void set_loop_bandwidth (float omega_n_norm) = 0; + /*! + * \brief Set the normalized approximate loop bandwidth. + * + * \details + * Set the normalized approximate loop bandwidth. + * Useful values are usually close to 0.0, e.g. 2*pi*0.045. + * + * It should be a small positive number, corresponding to the normalized + * natural radian frequency of the loop as digital low-pass filter that is + * filtering the clock phase/timing error. + * + * Technically this parameter corresponds to the natural radian frequency + * of the 2nd order loop transfer function (scaled by Fs), + * which is the radius of the pole locations in the s-plane of an + * underdamped analog 2nd order system. + * + * The input parameter corresponds to omega_n_norm in the following + * relation: + * + * omega_n_norm = omega_n*T = 2*pi*f_n*T = 2*pi*f_n_norm + * + * where T is the period of the clock being estimated by this + * clock tracking loop, and omega_n is the natural radian frequency + * of the 2nd order loop transfer function. + * + * When a new loop bandwidth is set, the gains, alpha and beta, + * of the loop are automatically recalculated. + * + * \param omega_n_norm normalized approximate loop bandwidth + */ + virtual void set_loop_bandwidth(float omega_n_norm) = 0; - /*! - * \brief Set the loop damping factor. - * - * \details - * Set the damping factor of the loop. - * Damping in the range (0.0, 1.0) yields an under-damped loop. - * Damping in the range (1.0, Inf) yields an over-damped loop. - * Damping equal to 1.0 yields a crtically-damped loop. - * Damping equal to 1.0/sqrt(2.0) yields a maximally flat - * loop filter response. - * - * Damping factor of the 2nd order loop transfer function. - * When a new damping factor is set, the gains, alpha and beta, - * of the loop are automatcally recalculated. - * - * \param zeta loop damping factor - */ - virtual void set_damping_factor (float zeta) = 0; + /*! + * \brief Set the loop damping factor. + * + * \details + * Set the damping factor of the loop. + * Damping in the range (0.0, 1.0) yields an under-damped loop. + * Damping in the range (1.0, Inf) yields an over-damped loop. + * Damping equal to 1.0 yields a crtically-damped loop. + * Damping equal to 1.0/sqrt(2.0) yields a maximally flat + * loop filter response. + * + * Damping factor of the 2nd order loop transfer function. + * When a new damping factor is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param zeta loop damping factor + */ + virtual void set_damping_factor(float zeta) = 0; - /*! - * \brief Set the expected gain of the Timing Error Detector. - * - * \details - * Sets the expected gain of the timing error detector, given the TED in - * use and the anticipated input amplitude, pulse shape, and Es/No. - * This value is the slope of the TED's S-curve at timing offset tau = 0. - * This value is normally computed by the user analytically or by - * simulation in a tool outside of GNURadio. - * This value must be correct for the loop filter gains to be computed - * properly from the desired input loop bandwidth and damping factor. - * - * When a new ted_gain is set, the gains, alpha and beta, - * of the loop are automatcally recalculated. - * - * \param ted_gain expected gain of the timing error detector - */ - virtual void set_ted_gain (float ted_gain) = 0; + /*! + * \brief Set the expected gain of the Timing Error Detector. + * + * \details + * Sets the expected gain of the timing error detector, given the TED in + * use and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * When a new ted_gain is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param ted_gain expected gain of the timing error detector + */ + virtual void set_ted_gain(float ted_gain) = 0; - /*! - * \brief Set the PI filter proportional gain, alpha. - * - * \details - * Sets the PI filter proportional gain, alpha. - * This gain directly mutliplies the clock phase/timing error - * term in the PI filter when advancing the loop. - * It most directly affects the instantaneous clock period estimate, - * T_inst, and instantaneous clock phase estimate, tau. - * - * This value would normally be adjusted by setting the loop - * bandwidth and damping factor. However, - * it can be set here directly if desired. - * - * Setting this parameter directly is probably only feasible if - * the user is directly observing the estimates of average clock - * period and instantaneous clock period over time in response to - * an impulsive change in the input stream (i.e. watching the loop - * transient behavior at the start of a data burst). - * - * \param alpha PI filter proportional gain - */ - virtual void set_alpha (float alpha) = 0; + /*! + * \brief Set the PI filter proportional gain, alpha. + * + * \details + * Sets the PI filter proportional gain, alpha. + * This gain directly mutliplies the clock phase/timing error + * term in the PI filter when advancing the loop. + * It most directly affects the instantaneous clock period estimate, + * T_inst, and instantaneous clock phase estimate, tau. + * + * This value would normally be adjusted by setting the loop + * bandwidth and damping factor. However, + * it can be set here directly if desired. + * + * Setting this parameter directly is probably only feasible if + * the user is directly observing the estimates of average clock + * period and instantaneous clock period over time in response to + * an impulsive change in the input stream (i.e. watching the loop + * transient behavior at the start of a data burst). + * + * \param alpha PI filter proportional gain + */ + virtual void set_alpha(float alpha) = 0; - /*! - * \brief Set the PI filter integral gain, beta. - * - * \details - * Sets the PI filter integral gain, beta. - * This gain is used when integrating the clock phase/timing error - * term in the PI filter when advancing the loop. - * It most directly affects the average clock period estimate, - * T_avg. - * - * This value would normally be adjusted by setting the loop - * bandwidth and damping factor. However, - * it can be set here directly if desired. - * - * Setting this parameter directly is probably only feasible if - * the user is directly observing the estimates of average clock - * period and instantaneous clock period over time in response to - * an impulsive change in the input stream (i.e. watching the loop - * transient behavior at the start of a data burst). - * - * \param beta PI filter integral gain - */ - virtual void set_beta (float beta) = 0; - }; + /*! + * \brief Set the PI filter integral gain, beta. + * + * \details + * Sets the PI filter integral gain, beta. + * This gain is used when integrating the clock phase/timing error + * term in the PI filter when advancing the loop. + * It most directly affects the average clock period estimate, + * T_avg. + * + * This value would normally be adjusted by setting the loop + * bandwidth and damping factor. However, + * it can be set here directly if desired. + * + * Setting this parameter directly is probably only feasible if + * the user is directly observing the estimates of average clock + * period and instantaneous clock period over time in response to + * an impulsive change in the input stream (i.e. watching the loop + * transient behavior at the start of a data burst). + * + * \param beta PI filter integral gain + */ + virtual void set_beta(float beta) = 0; +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_SYMBOL_SYNC_FF_H */ diff --git a/gr-digital/include/gnuradio/digital/timing_error_detector_type.h b/gr-digital/include/gnuradio/digital/timing_error_detector_type.h index e2bc51e80e..38de48225a 100644 --- a/gr-digital/include/gnuradio/digital/timing_error_detector_type.h +++ b/gr-digital/include/gnuradio/digital/timing_error_detector_type.h @@ -24,23 +24,23 @@ #define INCLUDED_DIGITAL_TIMING_ERROR_DETECTOR_TYPE_H namespace gr { - namespace digital { +namespace digital { - // Timing Error Detector types. - enum ted_type { - TED_NONE = -1, - TED_MUELLER_AND_MULLER = 0, // Decision directed - TED_MOD_MUELLER_AND_MULLER = 1, // Decision directed - TED_ZERO_CROSSING = 2, // Decision directed - TED_GARDNER = 4, - TED_EARLY_LATE = 5, - TED_DANDREA_AND_MENGALI_GEN_MSK = 6, // Operates on the CPM signal - TED_SIGNAL_TIMES_SLOPE_ML = 7, // ML approx. for small signal - TED_SIGNUM_TIMES_SLOPE_ML = 8, // ML approx. for large signal - TED_MENGALI_AND_DANDREA_GMSK = 9, // Operates on the CPM signal - }; +// Timing Error Detector types. +enum ted_type { + TED_NONE = -1, + TED_MUELLER_AND_MULLER = 0, // Decision directed + TED_MOD_MUELLER_AND_MULLER = 1, // Decision directed + TED_ZERO_CROSSING = 2, // Decision directed + TED_GARDNER = 4, + TED_EARLY_LATE = 5, + TED_DANDREA_AND_MENGALI_GEN_MSK = 6, // Operates on the CPM signal + TED_SIGNAL_TIMES_SLOPE_ML = 7, // ML approx. for small signal + TED_SIGNUM_TIMES_SLOPE_ML = 8, // ML approx. for large signal + TED_MENGALI_AND_DANDREA_GMSK = 9, // Operates on the CPM signal +}; - } /* namespace digital */ +} /* namespace digital */ } /* namespace gr */ #endif /* INCLUDED_DIGITAL_TIMING_ERROR_DETECTOR_TYPE_H */ |