![]() |
four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
|
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