four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
modem/modem_OFDM2.hpp
00001 /*
00002  * Copyright 2013, Per Zetterberg
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation, either version 3 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 /* This code should implement, more or less, the same functions as 
00019  * 
00020  * mod_OFDM2.m and demod_OFDM2.m
00021  *
00022  *
00023  */
00024 
00025 #include <itpp/itcomm.h>
00026 #include <complex>
00027 #include <iostream>
00028 #include <boost/format.hpp>
00029 
00030  
00031 using namespace std;
00032 using namespace itpp;
00033 
00034 #ifndef MODEM_OFDM2_H
00035 #define MODEM_OFDM2_H
00036 
00044 class OFDM2 {
00045 
00046 public:
00047 
00048   uint32_t rightmost_carrier; // Set in init
00049   uint32_t leftmost_carrier; // Set in init
00050   int rightmost_carrier_IEEE; // Set in init
00051   int leftmost_carrier_IEEE; // Set in init
00052   
00053 
00054 
00055   static const uint32_t Nfft=80;
00056   uint32_t pilot_carrier1; // Set in init
00057   uint32_t pilot_carrier2; // 
00058   static const uint32_t Nfft_sync=65536; // Frequency offsets with 25e6/Nfft_sync spacing.
00059   static const uint32_t gap=3;
00060 
00061   cmat a1c, a2c;
00062   
00063   double d_noise_variance_receiver;
00064   ivec known_symbol_pos;
00065   ivec interferers_known_pos;
00066   uint32_t Ns;//, nof_symbols_storage;
00067   complex<double> pilot_symbol;
00068   //uint32_t storage_ix;
00069   int first_payload_symbol_index;
00070   ivec ix, ix_all, ix_sub, ix_null;
00071   ivec closest_pilot;
00072   ivec closest_pilot_all;
00073   ivec ix_all_IEEE;
00074   uint32_t length_ix, length_ix_all;
00075   int pilot_carrier1_sub, pilot_carrier2_sub;
00076   int rightmost_carrier_sub, leftmost_carrier_sub;
00077   //cvec ConstellationStorage; //(length_ix*nof_symbols_storage);
00078   cvec train;
00079   cvec h;
00080   cvec pulse_shape;
00081   int pulse_shape_delay;
00082   bool do_use_pilot_carriers, do_prepend_training;
00083   bool per_symbol_phase_derotation;
00084   uint32_t Np;
00085   ivec d_reorder;
00086   double pilot_power_factor;
00087   cmat he; // Channel estimate of desired signal stream
00088   cmat hi[10]; // Channel estimate of at most 10 interfering signal streams
00089   cmat x; // 
00090   cmat x_c; // Combined signal
00091   cmat x_cp; // Combined with per antenna common phase-error correction.
00092   bool estimate_SINR; // If you want the receiver to estimate it's own SINR.
00093   double SINR; // Here's the result.
00094   int noise_estimation_start_ix, noise_estimation_stop_ix; // Defines where
00095                                    // in the buffer samples can be taken for
00096                                    // additive noise estimation.
00097   cvec cpe00;
00098   //OFDM2(bool use_pilot_carriers, bool prepend_training,uint32_t prefix_length);
00099 
00104   OFDM2(void);
00105 
00106 
00107 
00109   uint32_t Nfftr(void){return Nfft;};
00110 
00112   uint32_t number_of_modulation_symbols(void);
00113 
00115   uint32_t waveform_length(void);
00116 
00118   uint32_t prefix_length(void) { return Np; };
00119   
00120 
00122   uint32_t length(void) { return (Np+Nfft); };
00123 
00126   ivec start_of_known_symbol(void);
00127   
00136   void init_multi_antenna(uint32_t no_ant, int32_t buffer_size, ivec &interferer_pos,double noise_variance);
00137 
00139   void pilot_pattern(cvec &burst, cvec precoder);
00140 
00148   void insert_pilot(cvec &waveform, uint32_t symbol_number, uint32_t offset,
00149 cvec precoder);
00150 
00151   void insert_pilot(cmat &waveform, uint32_t symbol_number, uint32_t offset,
00152                     int antenna_ix,double scaling);
00153 
00154  
00155   
00168 void modulate(cvec &waveform,const cvec &symbols_in,  
00169                const uint32_t offset,double &rms_power,const cvec &precoder);
00170 
00171 
00172   void modulate_multi_antenna(cmat &waveform,
00173 const cvec &symbols_in,  
00174                      const uint32_t offset,
00175                               vec &rms_power,const cmat &V, double scaling, 
00176 int Nss);
00177 
00178   void modulate_multi_antenna(cmat &waveform,
00179 const cmat &symbols_in,  
00180                      const uint32_t offset,
00181                               vec &rms_power,const cmat V[], double scaling, ivec stream_ix_this_node, int symbols_ix_start=0, int num_symbols=0) const;
00182 
00183 
00184 
00193   void estimate_channel(cvec waveform,double  &noise_variance_normalized,cvec &h, uint32_t start_sample);  
00194 
00204   void estimate_channel(cvec waveform,double  &noise_variance_normalized,
00205                       cvec &h, uint32_t start_sample, double &noise_variance);
00206 
00217   void demodulate(const cvec &waveform,cvec &symbols_out, uint32_t start_sample,
00218            const cvec &h, double &rms_signal);
00219 
00220 
00222   void demodulate_multi_antenna(const cmat &waveform,vec &soft_bit, uint32_t start_sample, int modulation_order,int num_symbols_to_extract);
00223 
00224 
00236   void extract_multi_antenna(const cmat &waveform,uint32_t start_sample,
00237 int num_symbols_to_extract);
00238  
00239 
00249   void extract_multi_antenna(const cmat &waveform,
00250    uint32_t start_sample, cvec &symbols_out,int num_symbols_to_extract); 
00251 
00252 
00253   /* \brief This function initializes the parameters used for the IEEE802.11ac
00254        MU-MIMO feedback.
00255      \param b_phis The number of bits in the phis representation.
00256      \param b_psis The number of bits in the psis representation.
00257      \param num_ms_ant Number of mobile antennas represented in the feedback. 
00258      \param num_of_tx_antennas Number of transmitter side antennas represented in the feedback.
00259      \param Ng The number of subcarriers per subcarrier-group.
00260   */
00261   void init_compressed_feedback(int b_psis,int b_phis, uint32_t num_ms_ant, uint32_t num_of_tx_antennas, int Ng, double noise_variance_per_subcarrier,bool IA_compression);
00262 
00263 
00264   void change_Ng(int Ng) {d_Ng=Ng;};
00265   ivec scwcf(void){return scwcfs[d_Ng-1];};
00266   ivec scwcf_ix_all(void){return scwcf_ix_alls[d_Ng-1];};
00267   ivec scwcf_ix_all_high(void){return scwcf_ix_all_highs[d_Ng-1];};
00268   ivec scwcf_ix_all_low(void){return scwcf_ix_all_lows[d_Ng-1];};
00269 
00270   /* \brief This class encapsulates the compressed beamforming feedback 
00271      format of IEEE802.11n and IEEE802.11ac. 
00272      \param phis The Givens rotation angle indecies.
00273      \param psis The complex rotation angle indecies.
00274      \param SNRs The SNRs of the streams according to the 
00275      \param Na_phis The number of phi angles per MIMO subcarrier matrix.
00276      \param Na_psis The number of psi angels per MIMO subcarrier matrix.
00277 
00278   */
00279   struct compressed_feedback_IEEE80211ac {
00280     ivec phis;
00281     ivec psis;
00282     std::vector<int> bar_SNRs;
00283     std::vector<int> delta_SNRs;
00284     
00285     uint16_t Na_phis;
00286     uint16_t Na_psis; 
00287   };
00288 
00289   /* \brief Calculate the compressed feedback parameters according
00290      to 802.11ac with exclusize MIMO SNR feedback reporting.
00291      \param H[] This is an array of num_of_tx_antennas elements,
00292       where each element is an IT++ cmat matrix. This matrix
00293       has it's number of rows equal to the number of receiver antennas
00294       and it's number of columns equal to the number of subcarriers
00295       of the OFDM modulation. */
00296 
00297   compressed_feedback_IEEE80211ac compress_feedback(cmat H[]);
00298 
00299   /* \brief Uncompress (unpack) the feedback provided by the feedback
00300      input. Fill the result into the array of matrices H[].
00301      The so obtained channels H[] can be used for beamforming. 
00302  */
00303   void uncompress_feedback(cmat H[],const OFDM2::compressed_feedback_IEEE80211ac &feedback);
00304 
00305 
00306   /* \brief Synchronize against synchronization sequence (i.e. the
00307 sequence which is pre-pended if prepend_training=true when calling init),
00308 and simultaneosly search for frequency offset. The function is only
00309 implemented based for using a single antenna.
00310     \param waveform Received samples.
00311     \param start_pos Estimated start position.
00312     \param f_offset Estimated frequency offset.
00313 */
00314   void synchronize(cvec &waveform, uint32_t &start_pos,double &f_offset);
00315 
00316   /* \brief Synchronize against synchronization sequence (i.e. the
00317 sequence which is pre-pended if prepend_training=true when calling init),
00318 and simultaneosly search for frequency offset. The function is only
00319 implemented based for using a single antenna.
00320     \param waveform Received samples.
00321     \param start_pos Estimated start position.
00322 */
00323   void synchronize(cvec &waveform, uint32_t &start_pos);
00324 
00335   void init(bool use_pilot_carriers, bool prepend_training,uint32_t prefix_length,uint32_t Ns, ivec known_pos, ivec re_order);
00336 
00346   void change_pulse_shape(cvec new_pulse_shape, int new_pulse_shape_delay);
00347 
00348 
00349   void interleave_symbols(cvec &symbol, int index);
00350 
00359   void de_interleave_symbols(cvec &symbol, int index);
00360 
00362   void pz_init_fft(ivec ix_all){
00363     double a;
00364     Wfft.set_size(Nfft,Nfft);
00365     Wifft.set_size(Nfft,Nfft);
00366 
00367     for (uint32_t i1=0;i1<Nfft;i1++) {
00368       for (uint32_t i2=0;i2<Nfft;i2++) {
00369         a=-2*pi;
00370         a=a*i1;
00371         a=a*i2;
00372         a=a/Nfft;
00373         Wfft(i1,i2)=polar(1.0,a);
00374         a=2*pi;
00375         a=a*i2;
00376         a=a*i1;
00377         a=a/Nfft;
00378         Wifft(i1,i2)=polar((1.0/Nfft),a);
00379       };
00380     };  
00381     
00382     Wifft_sub=Wifft.get_cols(ix_all);
00383     Wifft_sub_filtered.set_size(Nfft+Np+pulse_shape.length()-1,
00384                                 Wifft_sub.cols());
00385 
00386     cvec temp1(Nfft);
00387     cvec temp2(Nfft+Np+pulse_shape.length()-1);
00388     temp2.zeros();
00389     cvec temp3(Nfft+Np+pulse_shape.length()-1);
00390 
00391     for (int i1=0;i1<Wifft_sub.cols();i1++) {
00392 
00393       temp1=Wifft_sub.get_col(i1);
00394       for (int i2=0;i2<(int) Nfft;i2++) 
00395         temp2(i2+Np)=temp1(i2);
00396 
00397       for (int i2=0;i2<(int) Np;i2++) 
00398         temp2(i2)=temp1(i2+Nfft-Np);
00399 
00400       temp3=filter(pulse_shape,1,temp2);
00401       //std::cout << "temp3=" << temp3 << std::endl;
00402       //exit(1);
00403 
00404       Wifft_sub_filtered.set_col(i1,temp3);
00405 
00406     };
00407     length_Wifft_sub_filtered=Wifft_sub_filtered.rows();
00408     //std::cout << "\n \n \n";
00409     //std::cout << "wf=" << Wifft_sub_filtered.get_col(0) << "\n";
00410     //std::cout << "\n \n \n";
00411     //std::cout << "w=" << Wifft_sub.get_col(0) << "\n";
00412     //exit(1);
00413 
00414 
00415   };
00416 
00418   void pz_fft(const cvec &in,cvec &out) { out=Wfft*in; };
00419 
00420 
00421 
00423   void pz_ifft(const cvec &in,cvec &out) { out=Wifft*in; };
00424 
00425   cmat Wfft;
00426   cmat Wifft;
00427   cmat Wifft_sub;
00428   cmat Wifft_sub_filtered;
00429   int length_Wifft_sub_filtered;
00430 
00431   imat symbol_interleave_matrix;
00432   imat symbol_de_interleave_matrix;
00433 
00434   static const int max_Ng=18;
00435   
00436   #if 0
00437   ivec scwcf_ix_all;
00438   ivec scwcf_ix_all_high;
00439   ivec scwcf_ix_all_low;
00440   ivec scwcf;
00441   ivec scwds;
00442   #endif
00443 
00444   ivec scwcfs[max_Ng];
00445   ivec scwdss[max_Ng];
00446   ivec scwcf_lows[max_Ng];
00447   ivec scwcf_highs[max_Ng];
00448 
00449   ivec scwcf_ix_all_lows[max_Ng];
00450   ivec scwcf_ix_all_highs[max_Ng];
00451   ivec scwcf_ix_alls[max_Ng];
00452   ivec scwcf_ds_lows[max_Ng];
00453   ivec scwcf_ds_highs[max_Ng];
00454   ivec scwcf_has_dss[max_Ng];
00455 
00456   int d_num_delta_SNRs[max_Ng];
00457 
00458   private:
00459   
00460   // Store parameters related to IEEE802.11ac MU MIMO feedback
00461   int d_b_psis, d_b_phis;
00462   int d_num_ms_ant;
00463   int d_num_tx_antennas;
00464   int d_Ng;
00465   //vec psis_codebook;
00466   //vec phis_codebook;
00467   int n_psis_codebook;
00468   int n_phis_codebook;
00469   double psis_res, phis_res;
00470   #if 0
00471   ivec scwcf_low;
00472   ivec scwcf_high;
00473   ivec scwcf_has_ds;
00474   ivec scwcf_ds_low;
00475   ivec scwcf_ds_high;
00476   int d_num_delta_SNR;
00477   #endif
00478   double d_noise_variance_per_subcarrier;
00479   bool d_IA_compression;
00480   cvec pilot_pattern_vec;
00481 
00482   cvec time_domain_pilot;
00483   cvec time_domain_filtered_pilot;
00484 
00485 
00487   void unpackV(ivec &psis_sc,ivec &phis_sc, cmat &V);
00488 
00490   void packV(ivec &psis_sc,ivec &phis_sc, const cmat &V);
00491 
00492 };
00493 
00494 #endif
00495 
 All Classes Functions Variables