GNU Radio 3.6.5 C++ API
digital_ofdm_chanest_vcvc.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /* Copyright 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GNU Radio
5  *
6  * GNU Radio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * GNU Radio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GNU Radio; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #ifndef INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
23 #define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
24 
25 #include <digital_api.h>
26 #include <gr_block.h>
27 
29 
31 
32 /*
33  * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its length must be
34  * the FFT length. For Schmidl & Cox synchronisation, every second sub-carrier
35  * has to be zero.
36  * \param sync_symbol2 Second synchronisation symbol in the frequency domain. Must be equal to
37  * the FFT length, or zero length if only one synchronisation symbol is used.
38  * Using this symbol is how synchronisation is described in [1]. Leaving this
39  * empty forces us to interpolate the equalizer taps.
40  * If you are using an unusual sub-carrier configuration (e.g. because of OFDMA),
41  * this sync symbol is used to identify the active sub-carriers. If you only
42  * have one synchronisation symbol, set the active sub-carriers to a non-zero
43  * value in here, and also set \p force_one_sync_symbol parameter to true.
44  * \param n_data_symbols The number of data symbols following each set of synchronisation symbols.
45  * Must be at least 1.
46  * \param eq_noise_red_len If non-zero, noise reduction for the equalizer taps is done according
47  * to [2]. In this case, it is the channel influence time in number of
48  * samples. A good value is usually the length of the cyclic prefix.
49  * \param max_carr_offset Limit the number of sub-carriers the frequency offset can maximally be.
50  * Leave this zero to try all possibilities.
51  * \param force_one_sync_symbol See \p sync_symbol2.
52  */
55  const std::vector<gr_complex> &sync_symbol1,
56  const std::vector<gr_complex> &sync_symbol2,
57  int n_data_symbols,
58  int eq_noise_red_len=0,
59  int max_carr_offset=-1,
60  bool force_one_sync_symbol=false);
61 
62 /*!
63  * \brief Estimate channel and coarse frequency offset for OFDM from preambles
64  * \ingroup ofdm_blk
65  * \ingroup syncronizers_blk
66  *
67  * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected
68  * to be synchronisation symbols, which are used to estimate the coarse freq offset
69  * and the initial equalizer taps (these symbols are removed from the stream).
70  * The following \p n_data_symbols are passed through unmodified (the actual equalisation
71  * must be done elsewhere).
72  * Output: The data symbols, without the synchronisation symbols.
73  * The first data symbol passed through has two tags:
74  * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers,
75  * and 'ofdm_sync_eq_taps' (complex vector).
76  * Any tags attached to the synchronisation symbols are attached to the first data
77  * symbol. All other tags are propagated as expected.
78  *
79  * Note: The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest is not.
80  *
81  * This block assumes the frequency offset is even (i.e. an integer multiple of 2).
82  *
83  * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM",
84  * Communications, IEEE Transactions on, 1997.
85  * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2.
86  */
88 {
89  private:
90  friend DIGITAL_API digital_ofdm_chanest_vcvc_sptr digital_make_ofdm_chanest_vcvc (const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
91 
92  int d_fft_len; //! FFT length
93  int d_n_data_syms; //! Number of data symbols following the sync symbol(s)
94  int d_n_sync_syms; //! Number of sync symbols (1 or 2)
95  //! 0 if no noise reduction is done for the initial channel state estimation. Otherwise, the maximum length of the channel delay in samples.
96  int d_eq_noise_red_len;
97  //! Is sync_symbol1 if d_n_sync_syms == 1, otherwise sync_symbol2. Used as a reference symbol to estimate the channel.
98  std::vector<gr_complex> d_ref_sym;
99  //! If d_n_sync_syms == 2 this is used as a differential correlation vector (called 'v' in [1]).
100  std::vector<gr_complex> d_corr_v;
101  //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset
102  std::vector<float> d_known_symbol_diffs;
103  //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset (temp. variable)
104  std::vector<float> d_new_symbol_diffs;
105  //! The index of the first carrier with data (index 0 is not DC here, but the lowest frequency)
106  int d_first_active_carrier;
107  //! The index of the last carrier with data
108  int d_last_active_carrier;
109  //! If true, the channel estimation must be interpolated
110  bool d_interpolate;
111  //! Maximum carrier offset (negative value!)
112  int d_max_neg_carr_offset;
113  //! Maximum carrier offset (positive value!)
114  int d_max_pos_carr_offset;
115 
116 
117  digital_ofdm_chanest_vcvc(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
118 
119  //! Calculate the coarse frequency offset in number of carriers
120  int get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2);
121  //! Estimate the channel (phase and amplitude offset per carrier)
122  void get_chan_taps(const gr_complex *sync_sym1, const gr_complex *sync_sym2, int carr_offset, std::vector<gr_complex> &taps);
123 
124  public:
126 
127  void forecast (int noutput_items, gr_vector_int &ninput_items_required);
128  int general_work (int noutput_items,
129  gr_vector_int &ninput_items,
130  gr_vector_const_void_star &input_items,
131  gr_vector_void_star &output_items);
132 };
133 
134 #endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H */
135