![]() |
four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
|
00001 /* 00002 * Copyright 2013, Per Zetterberg, KTH Royal Institute of Technology 00003 * 00004 * This program is free software: you can redistribut 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 implemen, 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 <itpp/stat/misc_stat.h> 00027 #include <math.h> 00028 #include "modem_OFDM2.hpp" 00029 #include <itpp/itbase.h> 00030 #include <complex> 00031 #include <itpp/base/sort.h> 00032 #include <itpp/base/specmat.h> 00033 00034 00035 using namespace itpp; 00036 using namespace std; 00037 00038 OFDM2::OFDM2(void){ 00039 pilot_power_factor=1; 00040 estimate_SINR=false; 00041 pulse_shape="0.0546,-0.0898,-0.0587,0.3134,0.5612,0.3133,-0.0587,-0.0898,0.0546"; 00042 00043 //pulse_shape="0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0"; 00044 00045 pulse_shape_delay=4; 00046 per_symbol_phase_derotation=false; 00047 }; 00048 00049 00050 uint32_t OFDM2::number_of_modulation_symbols(void){ 00051 return ((Ns-known_symbol_pos.length())*length_ix); 00052 }; 00053 00054 uint32_t OFDM2::waveform_length(void){ 00055 return (max(d_reorder)*Ns*(Nfft+Np)); 00056 }; 00057 00058 00059 00060 void OFDM2::init(bool use_pilot_carriers, bool prepend_training,uint32_t prefix_length,uint32_t number_of_symbols, ivec known_symbol_postion_index, ivec reorder){ 00061 00062 00063 pilot_carrier1=7; // Defined by IEEE 00064 pilot_carrier2=Nfft-7; // Defined by IEEE 00065 00066 //rightmost_carrier=16; 00067 //leftmost_carrier=Nfft-16; 00068 00069 rightmost_carrier=19; 00070 leftmost_carrier=Nfft-19; 00071 00072 rightmost_carrier_IEEE=rightmost_carrier; 00073 leftmost_carrier_IEEE=leftmost_carrier-Nfft; 00074 00075 00076 Ns=number_of_symbols; 00077 known_symbol_pos=known_symbol_postion_index; 00078 d_reorder=reorder; 00079 00080 do_use_pilot_carriers=use_pilot_carriers; 00081 do_prepend_training=prepend_training; 00082 00083 Np=prefix_length; 00084 00085 00086 if (do_use_pilot_carriers) 00087 length_ix=2*rightmost_carrier-2; 00088 else 00089 length_ix=2*rightmost_carrier; 00090 00091 length_ix_all=2*rightmost_carrier; 00092 00093 for (int i1=0;i1<(int) Ns;i1++) { 00094 if (!(i1==known_symbol_pos(0))) { 00095 first_payload_symbol_index=i1; 00096 break; 00097 }; 00098 }; 00099 00100 00101 00102 pilot_symbol=1.0+1.0i; 00103 h.set_size(Nfft); 00104 00105 string temp_str; 00106 temp_str="1,1,-1,1,1,1,1,-1,1,1,1,-1,1,1,1,-1,-1,-1,1,1,1,1, "; 00107 temp_str+="-1,-1,-1,-1,-1,1,-1,-1,1,-1,1,1,-1,1,1,1,-1,1,1,1,1,-1,-1,-1, "; 00108 temp_str+="-1,1,1,1,1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,-1,1, "; 00109 temp_str+="1,1,1,-1,1,-1,-1,-1,-1,1,1,-1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1, "; 00110 temp_str+="-1,1,1,-1,-1,1,-1,1,-1,1,1,1,1,1,-1,1,1,1,-1,1,-1,-1,1,-1,-1, "; 00111 temp_str+="1,1,-1,1,1,1,1,1,1,-1,1,-1,-1,-1,1,-1,-1,1,-1,1 "; 00112 train=temp_str.c_str(); 00113 ix.set_size(length_ix); 00114 00115 00116 00117 { uint32_t counter=0; 00118 for (uint32_t i1=1;i1<pilot_carrier1;i1++) { 00119 ix(counter++)=i1; 00120 }; 00121 00122 00123 for (uint32_t i1=pilot_carrier1+1;i1<=rightmost_carrier;i1++) { 00124 ix(counter++)=i1; 00125 }; 00126 00127 00128 rightmost_carrier_sub=counter-1; 00129 leftmost_carrier_sub=counter; 00130 00131 for (uint32_t i1=leftmost_carrier;i1<pilot_carrier2;i1++) { 00132 ix(counter++)=i1; 00133 }; 00134 00135 for (uint32_t i1=pilot_carrier2+1;i1<Nfft;i1++){ 00136 ix(counter++)=i1; 00137 }; 00138 }; 00139 00140 00141 00142 ix_all.set_size(length_ix_all); 00143 {uint32_t counter=0; 00144 00145 for (uint32_t i1=1;i1<=rightmost_carrier;i1++) { 00146 ix_all(counter++)=i1; 00147 }; 00148 for (uint32_t i1=leftmost_carrier;i1<Nfft;i1++) { 00149 ix_all(counter++)=i1; 00150 }; 00151 00152 }; 00153 00154 ix_all_IEEE.set_size(length_ix_all); 00155 for (int i1=0;i1<(int) length_ix_all;i1++) { 00156 ix_all_IEEE(i1)=ix_all(i1); 00157 if (ix_all_IEEE(i1) > (int) Nfft/2) 00158 ix_all_IEEE(i1)-=Nfft; 00159 }; 00160 00161 00162 00163 ix_sub.set_size(length_ix); 00164 {int counter=0; 00165 for (uint32_t i1=0;i1<(length_ix+2);i1++) { 00166 for (uint32_t i2=0;i2<length_ix;i2++) { 00167 if (ix_all(i1)==ix(i2)) { 00168 ix_sub(counter)=i1; 00169 counter++; 00170 }; 00171 }; 00172 }; 00173 }; 00174 00175 for (uint32_t i1=0;i1<length_ix+2;i1++) { 00176 if (ix_all(i1)==(int32_t) pilot_carrier1) { 00177 pilot_carrier1_sub=i1; 00178 }; 00179 00180 if (ix_all(i1)==(int32_t) pilot_carrier2) { 00181 pilot_carrier2_sub=i1; 00182 }; 00183 }; 00184 00185 if (!do_use_pilot_carriers) { 00186 ix=ix_all; 00187 for (uint32_t i1=0;i1<length_ix;i1++) 00188 ix_sub(i1)=i1; 00189 }; 00190 00191 00192 00193 closest_pilot.set_length(length_ix); 00194 closest_pilot_all.set_length(length_ix_all); 00195 for (uint32_t i1=0;i1<length_ix;i1++) { 00196 int Nffti=Nfft; 00197 int d1=ix_all(ix_sub(i1))-pilot_carrier1; 00198 if (d1> Nffti/2) 00199 d1=d1-Nffti; 00200 if (d1<-Nffti/2) 00201 d1=d1+Nffti; 00202 int d2=ix_all(ix_sub(i1))-pilot_carrier2; 00203 if (d2>Nffti/2) 00204 d2=d2-Nffti; 00205 if (d2<-Nffti/2) 00206 d2=d2+Nffti; 00207 00208 d1=abs(d1); 00209 d2=abs(d2); 00210 if (d1<d2) 00211 closest_pilot(i1)=1; 00212 else 00213 closest_pilot(i1)=2; 00214 }; 00215 00216 00217 for (uint32_t i1=0;i1<length_ix_all;i1++) { 00218 int Nffti=Nfft; 00219 int d1=ix_all(i1)-pilot_carrier1; 00220 if (d1> Nffti/2) 00221 d1=d1-Nffti; 00222 if (d1<-Nffti/2) 00223 d1=d1+Nffti; 00224 int d2=ix_all(i1)-pilot_carrier1; 00225 if (d2>Nffti/2) 00226 d2=d2-Nffti; 00227 if (d2<-Nffti/2) 00228 d2=d2+Nffti; 00229 00230 d1=abs(d1); 00231 d2=abs(d2); 00232 if (d1<d2) 00233 closest_pilot_all(i1)=1; 00234 else 00235 closest_pilot_all(i1)=2; 00236 }; 00237 00238 00239 00240 int counter=0; 00241 ix_null.set_length(Nfft-length_ix_all); 00242 for (uint32_t i1=0;i1<Nfft;i1++) { 00243 bool is_in_ix_all=false; 00244 for (uint32_t i2=0;i2<length_ix_all;i2++) { 00245 if ((int) i1==ix_all(i2)) 00246 is_in_ix_all=true; 00247 }; 00248 if (!is_in_ix_all) { 00249 ix_null(counter)=i1; 00250 counter++; 00251 }; 00252 00253 }; 00254 00255 pz_init_fft(ix_all); 00256 00257 cvec temp(Nfft); 00258 pilot_pattern(temp,ones_c(length_ix_all)); 00259 pilot_pattern_vec=temp(ix_all); 00260 00261 time_domain_pilot.set_length(Nfft+Np+pulse_shape.length()-1); 00262 time_domain_pilot.zeros(); 00263 pz_ifft(temp,temp); 00264 00265 for (uint32_t i1=0;i1<Nfft;i1++) 00266 time_domain_pilot(i1+Np)=temp(i1); 00267 for (uint32_t i1=0;i1<Np;i1++) 00268 time_domain_pilot(i1)=temp(i1+Nfft-Np); 00269 00270 time_domain_filtered_pilot=filter(pulse_shape,1,time_domain_pilot); 00271 00272 int no_interleavers=8; 00273 symbol_interleave_matrix.set_size(no_interleavers,length_ix); 00274 symbol_de_interleave_matrix.set_size(no_interleavers,length_ix); 00275 RNG_reset(101); 00276 ivec temp1(length_ix), temp2(length_ix); 00277 Sort<double> my_sort_f; 00278 Sort<int> my_sort_i; 00279 00280 for (int i1=0;i1<no_interleavers;i1++) { 00281 temp1=my_sort_f.sort_index(0,(int) (length_ix-1),randu(length_ix)); 00282 temp2=my_sort_i.sort_index(0,(int) (length_ix-1),temp1); 00283 00284 symbol_interleave_matrix.set_row(i1,temp1); 00285 symbol_de_interleave_matrix.set_row(i1,temp2); 00286 }; 00287 00288 00289 00290 } ; 00291 00292 void OFDM2::change_pulse_shape(cvec new_pulse_shape, int new_pulse_shape_delay) { 00293 00294 pulse_shape=new_pulse_shape; 00295 pulse_shape_delay=new_pulse_shape_delay; 00296 00297 pz_init_fft(ix_all); 00298 00299 cvec temp(Nfft); 00300 pilot_pattern(temp,ones_c(length_ix_all)); 00301 pilot_pattern_vec=temp(ix_all); 00302 00303 time_domain_pilot.set_length(Nfft+Np+pulse_shape.length()-1); 00304 time_domain_pilot.zeros(); 00305 pz_ifft(temp,temp); 00306 00307 for (uint32_t i1=0;i1<Nfft;i1++) 00308 time_domain_pilot(i1+Np)=temp(i1); 00309 for (uint32_t i1=0;i1<Np;i1++) 00310 time_domain_pilot(i1)=temp(i1+Nfft-Np); 00311 00312 time_domain_filtered_pilot=filter(pulse_shape,1,time_domain_pilot); 00313 00314 }; 00315 00316 void OFDM2::pilot_pattern(cvec &burst, cvec precoder) { 00317 00318 00319 burst(0)=0.0+0.0i; burst(1)=-1.0-1.0i; burst(2)=-1.0-1.0i; 00320 burst(3)=1.0+1.0i; burst(4)=-1.0-1.0i; 00321 burst(5)=1.0+1.0i; burst(6)=-1.0-1.0i; burst(7)=1.0+1.0i; 00322 burst(8)=1.0+1.0i; burst(9)=-1.0-1.0i; 00323 burst(10)=-1.0-1.0i; burst(11)=-1.0+1.0i; 00324 burst(12)=-1.0+1.0i; burst(13)=1.0+1.0i; 00325 burst(14)=-1.0+1.0i; burst(15)=-1.0+1.0i; 00326 burst(16)=-1.0+1.0i; burst(17)=1.0+1.0i; 00327 burst(18)=1.0+1.0i; burst(19)=1.0+1.0i; 00328 burst(20)=0.0+0.0i; burst(21)=0.0+0.0i; 00329 burst(22)=0.0+0.0i; burst(23)=0.0+0.0i; 00330 burst(24)=0.0+0.0i; burst(25)=0.0+0.0i; 00331 burst(26)=0.0+0.0i; burst(27)=0.0+0.0i; 00332 burst(28)=0.0+0.0i; burst(29)=0.0+0.0i; 00333 burst(30)=0.0+0.0i; burst(31)=0.0+0.0i; 00334 burst(32)=0.0+0.0i; burst(33)=0.0+0.0i; 00335 burst(34)=0.0+0.0i; burst(35)=0.0+0.0i; 00336 burst(36)=0.0+0.0i; burst(37)=0.0+0.0i; 00337 burst(38)=0.0+0.0i; burst(39)=0.0+0.0i; 00338 burst(40)=0.0+0.0i; burst(41)=0.0+0.0i; 00339 burst(42)=0.0+0.0i; burst(43)=0.0+0.0i; 00340 burst(44)=0.0+0.0i; 00341 burst(45)=0.0+0.0i; burst(46)=0.0+0.0i; 00342 burst(47)=0.0+0.0i; burst(48)=0.0+0.0i; 00343 burst(49)=0.0+0.0i; burst(50)=0.0+0.0i; 00344 burst(51)=0.0+0.0i; burst(52)=0.0+0.0i; 00345 burst(53)=0.0+0.0i; burst(54)=0.0+0.0i; 00346 burst(55)=0.0+0.0i; burst(56)=0.0+0.0i; 00347 burst(57)=0.0+0.0i; burst(58)=0.0+0.0i; 00348 burst(59)=0.0+0.0i; burst(60)=0.0+0.0i; 00349 burst(61)=-1.0+1.0i; burst(62)=1.0+1.0i; 00350 burst(63)=-1.0-1.0i; burst(64)=-1.0+1.0i; 00351 burst(65)=1.0+1.0i; burst(66)=-1.0-1.0i; 00352 burst(67)=-1.0-1.0i; burst(68)=1.0+1.0i; 00353 burst(69)=-1.0+1.0i; burst(70)=-1.0-1.0i; burst(71)=-1.0+1.0i; 00354 burst(72)=-1.0-1.0i; burst(73)=-1.0+1.0i; burst(74)=-1.0+1.0i; 00355 burst(75)=-1.0-1.0i; burst(76)=1.0+1.0i; 00356 burst(77)=-1.0-1.0i; burst(78)=-1.0+1.0i; 00357 burst(79)=1.0+1.0i; 00358 00359 00360 for (uint32_t i1=0;i1<Nfft;i1++) { 00361 burst(i1)=burst(i1)*pilot_power_factor/sqrt(2); 00362 }; 00363 00364 00365 for (uint32_t i1=0;i1<length_ix_all;i1++) { 00366 burst(ix_all(i1))=burst(ix_all(i1))*precoder(i1); 00367 }; 00368 00369 00370 //for (uint32_t i1=0;i1<Nfft-length_ix_all;i1++) { 00371 // burst(ix_null(i1))=burst(ix_null(i1))*precoder(0); 00372 //}; 00373 00374 }; 00375 00376 00377 ivec OFDM2::start_of_known_symbol(void){ 00378 ivec temp; 00379 temp.set_length(known_symbol_pos.length()); 00380 for (int i1=0;i1<known_symbol_pos.length();i1++) { 00381 temp(i1)=d_reorder.get(known_symbol_pos(i1))*(Nfft+Np); 00382 }; 00383 return temp; 00384 }; 00385 00386 00387 00388 00389 void OFDM2::modulate(cvec &waveform,const cvec &symbols_in, 00390 const uint32_t offset, 00391 double &rms_power,const cvec &precoder) 00392 00393 { 00394 00395 //cvec symbol(Nfft), symbol_temp(Nfft); 00396 cvec symbol2(length_ix_all); 00397 cvec waveform_temp(Nfft); 00398 double power=0,temp; 00399 bool the_symbol_is_known; 00400 int i4; // Counter from symbols_in 00401 00402 i4=0; 00403 //symbol.zeros(); 00404 00405 for (int i1=0;i1<(int) Ns;i1++) { 00406 00407 the_symbol_is_known=false; 00408 for (int i2=0;i2<known_symbol_pos.length();i2++) { 00409 if (i1==known_symbol_pos(i2)) 00410 the_symbol_is_known=true; 00411 }; 00412 00413 00414 00415 if (the_symbol_is_known) { 00416 00417 //pilot_pattern(symbol,precoder); 00418 //symbol2=symbol(ix_all); 00419 symbol2=elem_mult(pilot_pattern_vec,precoder); 00420 00421 } else { 00422 00423 for (uint32_t i3=0;i3<length_ix;i3++) { 00424 //symbol(ix(i3))=symbols_in(i4)*precoder(ix_sub(i3)); 00425 symbol2(ix_sub(i3))=symbols_in(i4)*precoder(ix_sub(i3)); 00426 i4++; 00427 }; 00428 if (do_use_pilot_carriers) { 00429 //symbol[pilot_carrier1]=(1.0+1.0i)/sqrt(2); 00430 //symbol[pilot_carrier2]=(1.0+1.0i)/sqrt(2); 00431 //symbol[pilot_carrier1]*=precoder(pilot_carrier1_sub); 00432 //symbol[pilot_carrier2]*=precoder(pilot_carrier2_sub); 00433 00434 symbol2[pilot_carrier1_sub]=(1.0+1.0i)/sqrt(2); 00435 symbol2[pilot_carrier2_sub]=(1.0+1.0i)/sqrt(2); 00436 symbol2[pilot_carrier1_sub]*=precoder(pilot_carrier1_sub); 00437 symbol2[pilot_carrier2_sub]*=precoder(pilot_carrier2_sub); 00438 00439 00440 }; 00441 //symbol2=symbol(ix_all); 00442 }; 00443 00444 00445 //waveform_temp=ifft(symbol,Nfft); 00446 //pz_ifft(symbol,waveform_temp); 00447 //waveform_temp=Wifft_sub*symbol(ix_all); 00448 waveform_temp=Wifft_sub*symbol2; 00449 00450 //waveform_temp=concat(waveform_temp.mid(Nfft-Np,Np),waveform_temp); 00451 //waveform_temp=filter(pulse_shape,1,waveform_temp); 00452 00453 00454 if (rms_power!=-10) { 00455 //temp=norm(waveform_temp.mid(Np,Nfft)); 00456 //power=power+temp*temp; 00457 temp=norm(waveform_temp); 00458 power=power+temp*temp; 00459 }; 00460 00461 int replace_pos=d_reorder(i1)*(Nfft+Np)+offset-pulse_shape_delay; 00462 00463 if (replace_pos<0) { 00464 std::cout << "writing outside of waveform in OFDM2::modulate \n"; 00465 exit(1); 00466 }; 00467 00468 for (int i2=0;i2<waveform_temp.size();i2++) { 00469 waveform(Np+i2+replace_pos)+=waveform_temp(i2); 00470 }; 00471 for (int i2=0;i2<(int) Np;i2++){ 00472 waveform(i2+replace_pos)+=waveform_temp(Nfft-Np+i2); 00473 }; 00474 00475 }; 00476 if (rms_power!=-10) { 00477 power=power/(Ns*Nfft); 00478 rms_power=sqrt(power); 00479 }; 00480 00481 00482 }; 00483 00484 00485 void OFDM2::modulate_multi_antenna(cmat &waveform, const cvec &symbols_in, 00486 const uint32_t offset, 00487 vec &rms_power,const cmat &V, double scaling,int Nss) 00488 { 00489 00490 00491 00492 00493 //cvec waveform_temp(Nfft); 00494 cvec waveform_temp(length_Wifft_sub_filtered); 00495 00496 int i4; // Counter from symbols_in 00497 int no_ant=waveform.rows(); 00498 cmat symbol2(length_ix_all,no_ant); 00499 00500 00501 i4=0; 00502 //int Nss=((double) symbols_in.length())/((double) length_ix)+0.999; 00503 00504 /* Known symbol */ 00505 for (int i2=0;i2<no_ant;i2++) { 00506 symbol2.set_col(i2,elem_mult(pilot_pattern_vec,V.get_row(i2))* 00507 scaling); 00508 }; 00509 int replace_pos=d_reorder(0)*(Nfft+Np)+offset-pulse_shape_delay; 00510 for (int i2=0;i2<no_ant;i2++) { 00511 00512 waveform_temp=Wifft_sub_filtered*symbol2.get_col(i2); 00513 00514 for (int i3=0;i3<length_Wifft_sub_filtered;i3++){ 00515 waveform(i2,i3+replace_pos)+=waveform_temp(i3); 00516 }; 00517 }; 00518 00519 00520 if (do_use_pilot_carriers) { 00521 00522 for (int i2=0;i2<no_ant;i2++) { 00523 symbol2(pilot_carrier1_sub,i2)=(1.0+1.0i)/sqrt(2); 00524 symbol2(pilot_carrier2_sub,i2)=(1.0+1.0i)/sqrt(2); 00525 symbol2(pilot_carrier1_sub,i2)*=V(i2,pilot_carrier1_sub)*scaling; 00526 symbol2(pilot_carrier2_sub,i2)*=V(i2,pilot_carrier2_sub)*scaling; 00527 }; 00528 }; 00529 00530 for (int i1=1;i1<(int) Nss+1;i1++) { 00531 00532 00533 for (uint32_t i3=0;i3<length_ix;i3++) { 00534 for (int i2=0;i2<no_ant;i2++) { 00535 symbol2(ix_sub(i3),i2)=symbols_in(i4)*V(i2,ix_sub(i3))*scaling; 00536 }; 00537 i4++; 00538 }; 00539 #if 0 00540 if (do_use_pilot_carriers) { 00541 00542 for (int i2=0;i2<no_ant;i2++) { 00543 symbol2(pilot_carrier1_sub,i2)=(1.0+1.0i)/sqrt(2); 00544 symbol2(pilot_carrier2_sub,i2)=(1.0+1.0i)/sqrt(2); 00545 symbol2(pilot_carrier1_sub,i2)*=V(i2,pilot_carrier1_sub)*scaling; 00546 symbol2(pilot_carrier2_sub,i2)*=V(i2,pilot_carrier2_sub)*scaling; 00547 }; 00548 00549 }; 00550 #endif 00551 00552 int replace_pos=d_reorder(i1)*(Nfft+Np)+offset-pulse_shape_delay; 00553 00554 for (int i2=0;i2<no_ant;i2++) { 00555 00556 waveform_temp=Wifft_sub_filtered*symbol2.get_col(i2); 00557 for (int i3=0;i3<length_Wifft_sub_filtered;i3++){ 00558 waveform(i2,i3+replace_pos)+=waveform_temp(i3); 00559 }; 00560 }; 00561 }; 00562 }; 00563 00564 void OFDM2::modulate_multi_antenna(cmat &waveform, const cmat &symbols_in, 00565 const uint32_t offset, vec &rms_power, const cmat V[], double scaling,ivec stream_ix_this_node, int symbols_ix_start, 00566 int num_symbols) const 00567 00568 { 00569 00570 00571 cvec waveform_temp(length_Wifft_sub_filtered); 00572 00573 int i4; // Counter from symbols_in 00574 int no_ant=waveform.rows(); 00575 int no_streams=symbols_in.rows(); 00576 00577 cmat symbol2(length_ix_all,no_ant); 00578 cvec symbol(length_ix_all); 00579 int replace_pos; 00580 00581 if (num_symbols==0) 00582 num_symbols=Ns-1; 00583 00584 if (symbols_ix_start==0) { 00585 for (int i1=0;i1<no_streams;i1++) { 00586 00587 replace_pos=stream_ix_this_node(i1)*(Nfft+Np)+offset-pulse_shape_delay; 00588 00589 for (int i2=0;i2<no_ant;i2++) { 00590 00591 symbol=elem_mult(pilot_pattern_vec,(V[i1]).get_row(i2))*scaling; 00592 waveform_temp=Wifft_sub_filtered*symbol; 00593 00594 for (int i3=0;i3<length_Wifft_sub_filtered;i3++){ 00595 waveform(i2,i3+replace_pos)+=waveform_temp(i3); 00596 }; 00597 }; 00598 }; 00599 }; 00600 00601 00602 00603 std::complex<double> pilot_symbol=(1.0+1.0i)/sqrt(2); 00604 pilot_symbol*=scaling; 00605 00606 i4=symbols_ix_start*length_ix; 00607 for (int i1=symbols_ix_start+1;i1<=(int) (symbols_ix_start+num_symbols);i1++) { 00608 00609 00610 replace_pos=d_reorder(i1)*(Nfft+Np)+offset-pulse_shape_delay; 00611 symbol2.zeros(); 00612 for (uint32_t i3=0;i3<length_ix;i3++) { 00613 00614 for (int i5=0;i5<no_streams;i5++) { 00615 for (int i2=0;i2<no_ant;i2++) { 00616 symbol2(ix_sub(i3),i2)+=symbols_in(i5,i4)*(V[i5](i2,ix_sub(i3)))*scaling; 00617 }; // i2 00618 }; // i5 00619 i4++; 00620 }; // i3 00621 for (int i5=0;i5<no_streams;i5++) { 00622 for (int i2=0;i2<no_ant;i2++) { 00623 symbol2(pilot_carrier1_sub,i2)+=(V[i5](i2,pilot_carrier1_sub))*pilot_symbol; 00624 symbol2(pilot_carrier2_sub,i2)+=(V[i5](i2,pilot_carrier2_sub))*pilot_symbol; 00625 }; // i2 00626 00627 }; // i5 00628 00629 for (int i2=0;i2<no_ant;i2++) { 00630 waveform_temp=Wifft_sub_filtered*symbol2.get_col(i2); 00631 for (int i3=0;i3<length_Wifft_sub_filtered;i3++){ 00632 waveform(i2,i3+replace_pos)+=waveform_temp(i3); 00633 }; 00634 }; 00635 }; // i1 00636 00637 if (!(rms_power(0)==-10)) { 00638 rms_power.zeros(); 00639 i4=0; 00640 for (int i1=symbols_ix_start+1;i1<=(int) (symbols_ix_start+num_symbols);i1++) { 00641 replace_pos=d_reorder(i1)*(Nfft+Np)+offset; 00642 for (int i2=0;i2<(int) no_ant;i2++) { 00643 for (int i3=0;i3<(int) (Nfft);i3++) { 00644 rms_power(i2)=rms_power(i2)+abs(waveform(i2,i3+replace_pos))*abs(waveform(i2,i3+replace_pos)); 00645 i4++; 00646 }; 00647 }; 00648 }; 00649 rms_power=sqrt(rms_power/i4*no_ant); 00650 }; 00651 00652 }; 00653 00654 00655 00656 00657 void OFDM2::insert_pilot(cvec &waveform, uint32_t symbol_position, uint32_t offset, 00658 cvec precoder) { 00659 cvec symbol(Nfft); 00660 cvec waveform_temp(Nfft); 00661 symbol.zeros(); 00662 pilot_pattern(symbol,precoder); 00663 //waveform_temp=ifft(symbol,Nfft); 00664 pz_ifft(symbol,waveform_temp); 00665 00666 waveform.replace_mid(symbol_position*(Nfft+Np)+Np+offset,waveform_temp); 00667 waveform.replace_mid(symbol_position*(Nfft+Np)+offset,waveform_temp.mid(Nfft-Np,Np)); 00668 }; 00669 00670 00671 void OFDM2::insert_pilot(cmat &waveform, uint32_t symbol_position, 00672 uint32_t offset, int antenna_ix,double scaling){ 00673 00674 int i2=symbol_position*(Nfft+Np)+offset-pulse_shape_delay; 00675 for (int i1=0;i1<time_domain_filtered_pilot.length();i1++) { 00676 waveform(antenna_ix,i2)+=scaling*time_domain_filtered_pilot(i1); 00677 i2++; 00678 }; 00679 00680 }; 00681 00682 00683 void OFDM2::estimate_channel(cvec waveform,double &noise_variance_normalized, 00684 cvec &h, uint32_t start_sample) { 00685 double noise_variance; 00686 estimate_channel(waveform,noise_variance_normalized,h,start_sample,noise_variance); 00687 00688 }; 00689 00690 00691 00692 void OFDM2::estimate_channel(cvec waveform,double &noise_variance_normalized, 00693 cvec &h, uint32_t start_sample, double &noise_variance) { 00694 00695 cvec pilot(Nfft); 00696 int i1,counter; 00697 complex <double> hhat, actual_meas, ideal_meas, error; 00698 double error_div_h; 00699 cvec signal(Nfft); 00700 cvec h_rotated(Nfft); 00701 complex<double> rotation; 00702 00703 00704 00705 //signal=fft(waveform.mid(0,Nfft)); 00706 pz_fft(waveform.mid(start_sample,Nfft),signal); 00707 00708 pilot.set_length(Nfft); 00709 pilot_pattern(pilot,ones_c(length_ix_all)); 00710 h=signal(ix_all); 00711 h/=pilot(ix_all); 00712 00713 00714 noise_variance_normalized=0; 00715 noise_variance=0; 00716 counter=0; 00717 00718 for (i1=1;i1<ix_all.length()-1;i1++) { 00719 00720 if (((ix_all(i1)-ix_all(i1-1))==1) && ((ix_all(i1+1)-ix_all(i1))==1)) { 00721 00722 hhat=0.5*abs(h(i1-1))+0.5*abs(h(i1+1)); 00723 complex<double> t; 00724 t=h(i1+1)/h(i1-1); 00725 double a=arg(h(i1-1))+0.5*arg(t); 00726 hhat=polar(abs(hhat),a); 00727 ideal_meas=hhat*pilot(ix_all(i1)); 00728 00729 actual_meas=signal(ix_all(i1)); 00730 error=ideal_meas-actual_meas; 00731 00732 noise_variance+=abs(error)*abs(error); 00733 error_div_h=abs(error)/abs(h(i1)); 00734 noise_variance_normalized+=error_div_h*error_div_h; 00735 counter++; 00736 } 00737 }; 00738 noise_variance_normalized/=counter; 00739 noise_variance/=counter; 00740 00741 00742 00743 }; 00744 00745 00746 00747 void OFDM2::init_multi_antenna(uint32_t no_ant, int32_t buffer_size, ivec &interferers_known_pos_in, 00748 double noise_variance) { 00749 00750 00751 00752 00753 x.set_size(no_ant,length_ix_all); 00754 00755 00756 //pc1.set_size(no_ant,Ns-known_symbol_pos.length()); // Signal received on pilot_carrier1 all antennas 00757 //pc2.set_size(no_ant,Ns-known_symbol_pos.length()); // Signal received on pilot_carrier2 all antennas 00758 a1c.set_size(no_ant,Ns-known_symbol_pos.length()); // Signal received on pilot_carrier1 all antennas 00759 a2c.set_size(no_ant,Ns-known_symbol_pos.length()); // Signal received on pilot_carrier2 all antennas 00760 a1c.ones(); 00761 a2c.ones(); 00762 00763 00764 he.set_size(no_ant,length_ix_all); 00765 interferers_known_pos=interferers_known_pos_in; 00766 for (int i1=0;i1<interferers_known_pos.length();i1++) { 00767 00768 hi[i1].set_size(no_ant,length_ix_all); 00769 }; 00770 00771 00772 d_noise_variance_receiver=noise_variance; 00773 int num_payload_symbols=0; 00774 bool the_symbol_is_known; 00775 for (int i1=0;i1<(int) Ns;i1++) { 00776 the_symbol_is_known=false; 00777 for (int i2=0;i2<known_symbol_pos.length();i2++) { 00778 if (i1==known_symbol_pos(i2)) 00779 the_symbol_is_known=true; 00780 }; 00781 00782 if (!(the_symbol_is_known)) { 00783 num_payload_symbols++; 00784 }; 00785 }; 00786 00787 x_c.set_size(length_ix_all,num_payload_symbols); 00788 x_cp.set_size(length_ix_all,num_payload_symbols); 00789 00790 00791 } 00792 00793 00794 void OFDM2::demodulate_multi_antenna(const cmat &waveform,vec &soft_bit, uint32_t start_sample, int modulation_order,int num_symbols_to_extract){ 00795 00796 cvec waveform_temp(Nfft); 00797 double noise_variance, noise_variance_norm; 00798 vec noise_variance_vec; // Noise variance estmimated during pilot. 00799 vec noise_variance_SINR; // Noise variance estmimated when there is 00800 // no signal. Only for benchmarking 00801 vec soft_temp; 00802 cvec symbolsc(Nfft); 00803 //bool the_symbol_is_known; 00804 //int32_t num_payload_symbols; 00805 double D=0.0, DI=0.0; 00806 00807 noise_variance_vec.set_length(waveform.rows()); 00808 // Estimate noise variance for analysis purposes 00809 00810 00811 00812 if (estimate_SINR) { 00813 noise_variance_SINR.set_length(waveform.rows()); 00814 int Nsymb; 00815 int start_ix=noise_estimation_start_ix; 00816 int stop_ix; 00817 00818 for (int i2=0;i2<waveform.rows();i2++) { 00819 noise_variance_SINR(i2)=0; 00820 start_ix=noise_estimation_start_ix; 00821 stop_ix=start_ix+Nfft; 00822 Nsymb=0; 00823 while (stop_ix<noise_estimation_stop_ix) { 00824 waveform_temp=(waveform.get_row(i2)).mid(start_ix,Nfft); 00825 pz_fft(waveform_temp,symbolsc); 00826 noise_variance_SINR(i2)+=sum(sqr(symbolsc(ix_all)))/length_ix_all; 00827 start_ix=stop_ix+1; 00828 stop_ix=start_ix+Nfft; 00829 Nsymb++; 00830 }; 00831 noise_variance_SINR(i2)=noise_variance_SINR(i2)/Nsymb; 00832 }; 00833 }; 00834 00835 00836 if (modulation_order==0) return; 00837 00838 00839 00840 // Estimate the vector channel of desired signal and interferers 00841 for (int i2=0;i2<he.rows();i2++) { 00842 double dummy; 00843 00844 00845 int s=start_of_known_symbol()(0)+start_sample; 00846 00847 waveform_temp=(waveform.get_row(i2)).mid(s,Nfft); 00848 estimate_channel(waveform_temp,noise_variance_norm, 00849 h,0,noise_variance); 00850 00851 //if (i2==0) 00852 //std::cout<< "waveform_temp=" << waveform_temp << "\n"; 00853 00854 00855 noise_variance_vec(i2)=noise_variance; 00856 he.set_row(i2,h); 00857 00858 for (int i1=0;i1<interferers_known_pos.length();i1++) { 00859 s=start_sample+interferers_known_pos(i1)*(Nfft+Np); 00860 00861 00862 waveform_temp=(waveform.get_row(i2)).mid(s,Nfft); 00863 estimate_channel(waveform_temp,dummy,h,0); 00864 hi[i1].set_row(i2,h); 00865 }; 00866 }; 00867 00868 00869 noise_variance=mean(noise_variance_vec); 00870 00871 if (modulation_order==1) return; 00872 00873 00874 cmat Rs; // Structured covariance matrix 00875 //cmat Ru; // Un-structured covariance matrix 00876 cmat temp; 00877 cvec temp1; 00878 complex<double> hc; 00879 cvec w(waveform.rows()); 00880 00881 00882 Rs.set_size(waveform.rows(),waveform.rows()); 00883 //Ru.set_size(waveform.rows(),waveform.rows()); 00884 00885 temp.set_size(waveform.rows(),waveform.rows()); 00886 temp1.set_length(waveform.rows()); 00887 00888 int aw=20; // Averaging window for the angles 00889 int aw_i=0; // Index into averaging window. 00890 cvec p10(waveform.rows()), p20(waveform.rows()); 00891 std::complex<double> v1,v2,v3; 00892 int i10=0; 00893 cmat p1r(waveform.rows(),aw); // running average 00894 cmat p2r(waveform.rows(),aw); // running average 00895 p1r.zeros(); 00896 p2r.zeros(); 00897 00898 00899 int i4; 00900 int i3; 00901 00902 // Make an average over the aw first symbols 00903 00904 i10=0; 00905 p10.zeros(); 00906 p20.zeros(); 00907 int is=0; // Number of collected samples 00908 00909 { 00910 int i1=0; 00911 while (is<aw) { 00912 if (!(i1==known_symbol_pos(0))) { 00913 for (i3=0;i3<waveform.rows();i3++) { 00914 i4=(Nfft+Np)*d_reorder(i1)+start_sample; 00915 v1=0; 00916 v2=0; 00917 for (int i5=0;i5<(int) Nfft;i5++) { 00918 v1=v1+Wfft(pilot_carrier1,i5)*waveform(i3,i4); 00919 v2=v2+Wfft(pilot_carrier2,i5)*waveform(i3,i4); 00920 i4++; 00921 }; // i5 00922 //if ((i3==0) && (is<2)) 00923 // std::cout << "v1=" << v1 ; 00924 p10(i3)=p10(i3)+v1; 00925 p20(i3)=p20(i3)+v2; 00926 00927 }; 00928 is++; 00929 }; 00930 i1++; 00931 }; 00932 }; 00933 00934 i10=0; 00935 std::complex<double> c1,c2; 00936 for (int i1=0;i1<(int) num_symbols_to_extract+1;i1++) { 00937 00938 00939 if (!(i1==known_symbol_pos(0))) { 00940 for (i3=0;i3<waveform.rows();i3++) { 00941 i4=(Nfft+Np)*d_reorder(i1)+start_sample; 00942 v1=0; 00943 v2=0; 00944 for (int i5=0;i5<(int) Nfft;i5++) { 00945 v1=v1+Wfft(pilot_carrier1,i5)*waveform(i3,i4); 00946 v2=v2+Wfft(pilot_carrier2,i5)*waveform(i3,i4); 00947 i4++; 00948 }; // i5 00949 00950 p1r(i3,aw_i)=v1; 00951 p2r(i3,aw_i)=v2; 00952 00953 //if ((i10==0) && (i3==0)) 00954 // std::cout << "v1=" << v1 << "\n"; 00955 00956 00957 if (i10>=aw-1) { 00958 00959 00960 c1=p10(i3)/mean(p1r.get_row(i3)); 00961 c1=c1/abs(c1); 00962 c2=p20(i3)/mean(p2r.get_row(i3)); 00963 c2=c2/abs(c2); 00964 a1c(i3,i10)=c1; 00965 a2c(i3,i10)=c2; 00966 00967 //std::cout << "p1r.get_row(i3)=" << p1r.get_row(i3) << std::endl; 00968 //std::cout << "c1=" << c1 << std::endl; 00969 00970 00971 00972 } else { 00973 c1=1; 00974 c2=1; 00975 a1c(i3,i10)=c1; 00976 a2c(i3,i10)=c2; 00977 }; 00978 00979 }; // i3 00980 aw_i++; 00981 aw_i=aw_i % aw; 00982 00983 i10++; 00984 }; // known_symbol_pos 00985 }; // i1 00986 00987 00988 cmat *ac; 00989 00990 for (uint32_t i2=0;i2<length_ix_all;i2++) { 00991 00992 //Ru.zeros(); 00993 //for (int i1=0;i1<num_payload_symbols;i1++) { 00994 // temp1=(x[i1]).get_col(i2); 00995 // Ru+=outer_product(temp1,temp1,true); 00996 //}; 00997 Rs=outer_product(he.get_col(i2),he.get_col(i2),true); 00998 for (int i1=0;i1<interferers_known_pos.length();i1++) { 00999 Rs=Rs+outer_product(hi[i1].get_col(i2),hi[i1].get_col(i2),true); 01000 }; 01001 //Rs=Rs+diag(noise_variance_vec); 01002 complex<double> cnoise_variance=d_noise_variance_receiver; 01003 Rs=Rs+eye_c(Rs.rows())*cnoise_variance; 01004 w=inv(Rs)*he.get_col(i2); 01005 w=w/norm(w,2); 01006 01007 if (false) { //(estimate_SINR) { 01008 double d; 01009 DI+=abs(elem_mult_sum(conj(w),(Rs+ 01010 diag(noise_variance_SINR-noise_variance_vec))*w)); 01011 d=abs(elem_mult_sum(conj(w),he.get_col(i2))); 01012 D+=d*d; 01013 }; 01014 01015 h(i2)=elem_mult_sum(he.get_col(i2),conj(w)); 01016 01017 01018 if (closest_pilot_all(i2)==1) 01019 ac=&a1c; 01020 else 01021 ac=&a2c; 01022 01023 01024 i10=0; 01025 for (int i1=0;i1<(int) num_symbols_to_extract+1;i1++) { 01026 01027 if (i1!=known_symbol_pos(0)) { 01028 01029 01030 #if 1 01031 int i4; 01032 v2=0; 01033 for (int i3=0;i3<waveform.rows();i3++) { 01034 i4=(Nfft+Np)*d_reorder(i1)+start_sample; 01035 v1=0; 01036 for (int i5=0;i5<(int) Nfft;i5++) { 01037 v1=v1+Wfft(ix_all(i2),i5)*waveform(i3,i4); 01038 i4++; 01039 }; 01040 v2=v2+v1*conj(w(i3))*((*ac)(i3,i10)); 01041 //v2=v2+v1*conj(w(i3)); 01042 }; 01043 x_c(i2,i10)=v2; 01044 #endif 01045 01046 i10++; 01047 01048 }; 01049 01050 01051 01052 01053 }; 01054 01055 }; 01056 01057 cpe00.set_length(3); 01058 v1=0; v2=0; 01059 for (int i1=0;i1<aw;i1++) { 01060 v1=v1+x_c(pilot_carrier1_sub,i1); 01061 v2=v2+x_c(pilot_carrier2_sub,i1); 01062 }; 01063 v1=pilot_symbol/v1; 01064 v2=pilot_symbol/v2; 01065 v1=v1/abs(v1); 01066 v2=v2/abs(v2); 01067 cpe00(1)=v1; 01068 cpe00(2)=v2; 01069 01070 if (estimate_SINR) { 01071 SINR=D/(DI-D); 01072 }; 01073 01074 if (modulation_order==2) return; 01075 01076 #if 0 01077 cvec symbol; 01078 symbol.set_length(length_ix_all); 01079 soft_temp.set_length(length_ix); 01080 int bits_per_symbol=log2(modulation_order); 01081 01082 // Re-estimate noise variance 01083 double noise_variance_temp; 01084 noise_variance=0; 01085 for (int i1=0;i1<num_payload_symbols;i1++) { 01086 symbol=x_c.get_col(i1); 01087 noise_variance_temp=0; 01088 soft_output(symbol,noise_variance_temp,modulation_order,soft_temp); 01089 noise_variance+=noise_variance_temp; 01090 }; 01091 noise_variance/=num_payload_symbols; 01092 01093 01094 // Soft-value extraction 01095 for (int i1=0;i1<num_payload_symbols;i1++) { 01096 symbol=x_c.get_col(i1); 01097 soft_output(symbol,noise_variance,modulation_order,soft__temp); 01098 soft_bit.replace_mid(i1*length_ix*bits_per_symbol,soft_temp); 01099 }; 01100 #endif 01101 }; 01102 01103 void OFDM2::extract_multi_antenna(const cmat &waveform, 01104 uint32_t start_sample,int num_symbols_to_extract){ 01105 01106 // When calling this function the following members will be set 01107 // x_c : A matrix which contains the combined signal (#subcarrier,#symbol) 01108 // h : Channel estimate including combiner #subcarriers 01109 // x[#symbols]: The raw complex samples. Each matrix (#subcarrier,#symbol). 01110 // he: Channel estimate for the desired signal (#antenna,#subcarrier) 01111 // hi[#interferers]: Channel estimate of interfering signals. 01112 01113 vec dummy; 01114 01115 demodulate_multi_antenna(waveform,dummy,start_sample,2, 01116 num_symbols_to_extract); 01117 }; 01118 01119 void OFDM2::init_compressed_feedback(int b_psis,int b_phis, uint32_t num_ms_ant, uint32_t num_tx_antennas, int Ng, double noise_variance_per_subcarrier, bool IA_compression) { 01120 d_b_psis=b_psis; 01121 d_b_phis=b_phis; 01122 d_num_ms_ant=num_ms_ant; 01123 d_num_tx_antennas=num_tx_antennas; 01124 d_Ng=Ng; 01125 d_IA_compression=IA_compression; 01126 01127 d_noise_variance_per_subcarrier=noise_variance_per_subcarrier; 01128 psis_res=pi/(pow2(b_psis+1)); 01129 // psis_codebook=(0.5+linspace(0,pow2(b_psis)-1,pow2(b_psis)))*psis_res; 01130 phis_res=pi/(pow2(b_phis-1)); 01131 //phis_codebook=(0.5+linspace(0,pow2(b_phis)-1,pow2(b_phis)))*phis_res; 01132 01133 n_psis_codebook=pow2(b_psis); 01134 n_phis_codebook=pow2(b_phis); 01135 01136 //std::cout << "phis_codebook=" << phis_codebook << std::endl; 01137 //std::cout << "phis_res=" << phis_res << std::endl; 01138 01139 //for (int i1=0;i1<phis_codebook.size();i1++) { 01140 // if (phis_codebook(i1)>pi) 01141 // phis_codebook(i1)=phis_codebook(i1)-2*pi; 01142 //}; 01143 01144 01145 // scwcf : subcarriers with compressed feedback (IEEE notation), 01146 // scwds : subcarriers with delta SNR feedback 01147 // scwcf_low: The subcarriers from scwcf_low(i1) to scwcf_high(i) 01148 // scwcf_high: use primarily scwcf(i1) for channel estimation. 01149 // scwcf_has_ds: scwcf_has_ds(i1)=1 if there is an i2 such 01150 // scwcf(i1)=scwds(i2). 01151 // scwcf_ds_low: Closest delta SNR measurement downwards or equal 01152 // scwcf_ds_high Closest delta SNR measurement upwards or equal (or -1000 if not existent) 01153 // scwcf_ix_all_sub: Index in ix_all 01154 // scwcf_ix_all_low: Index in ix_all corresponding to scwcf_low 01155 // scwcf_ix_all_high: Index in ix_all corresponding to scwcf_high 01156 01157 01158 scwcfs[0]="-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8," 01159 "-6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11," 01160 "12, 13, 14, 15, 16, 17, 18, 19"; 01161 scwcf_lows[0]="-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8," 01162 "-7, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11," 01163 "12, 13, 14, 15, 16, 17, 18, 19"; 01164 scwcf_highs[0]="-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8," 01165 "-6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11," 01166 "12, 13, 14, 15, 16, 17, 18, 19"; 01167 01168 scwdss[0]="-18, -16, -14, -12, -10, -8, -6, -4, -2, -1, 1, 2, 4, 6," 01169 "8, 10, 12,14, 16, 18"; 01170 01171 01172 scwcfs[1]= "-18, -16, -14, -12, -10, -8, -6, -4, -2, -1, 1, 2, 4, 6," 01173 "8, 10, 12, 14, 16, 18"; 01174 scwdss[1]="-16, -12, -8, -4, -1, 1, 4, 8, 12, 16"; 01175 01176 scwcf_lows[1]="-19, -17, -15, -13, -11, -9, -7, -5, -3, -1, 1, 2, 3, 5," 01177 "7, 9, 11, 13, 15, 17"; 01178 scwcf_highs[1]="-18, -16, -14, -12, -10, -8, -6, -4, -2, -1, 1, 2, 4, 6," 01179 "8, 10, 12, 14, 16, 19"; 01180 01181 01182 scwdss[3]="-12, -8, -4, -1, 1, 4, 12"; 01183 scwcfs[3]="-16, -12, -8, -4, -1, 1, 4, 8, 12, 16"; 01184 scwcf_lows[3]="-19, -14,-10, -6, -2, 1, 3, 6, 10, 14"; 01185 scwcf_highs[3]="-15, -11, -7, -3, -1, 2, 5, 9, 13, 19"; 01186 01187 scwcfs[7]= "-16, -8, -1, 1, 8, 16"; 01188 scwcf_lows[7]="-19,-12, -4, 1, 5, 12"; 01189 scwcf_highs[7]="-13, -5, -1, 4, 11,19"; 01190 scwdss[7]="-8, -1, 1, 8"; 01191 01192 01193 scwcfs[15]="-16,-1,1,16"; 01194 scwcf_lows[15]="-19,-8,1,9"; 01195 scwcf_highs[15]=" -9,-1,8,19"; 01196 scwdss[15]="-1,1,"; 01197 01198 01199 01200 scwcfs[16]="-10 10"; 01201 scwcf_lows[16]="-19 1"; 01202 scwcf_highs[16]="-1 19"; 01203 scwdss[16]="-10 10"; 01204 01205 scwcfs[17]="1"; 01206 scwcf_lows[17]="-19"; 01207 scwcf_highs[17]="19"; 01208 scwdss[17]="1,"; 01209 01210 01211 ivec Nss="1,2,4,8,16,17,18"; 01212 int Nsi=0; 01213 for (int Nss_i=0;Nss_i<Nss.length();Nss_i++) { 01214 Nsi=Nss(Nss_i)-1; 01215 01216 01217 scwcf_ix_all_lows[Nsi]=-1000*ones_i(scwcfs[Nsi].length()); 01218 scwcf_ix_all_highs[Nsi]=-1000*ones_i(scwcfs[Nsi].length()); 01219 scwcf_ix_alls[Nsi]=-1000*ones_i(scwcfs[Nsi].length()); 01220 scwcf_ds_lows[Nsi]=-1000*ones_i(scwcfs[Nsi].length()); 01221 scwcf_ds_highs[Nsi]=-1000*ones_i(scwcfs[Nsi].length()); 01222 01223 for (int i1=0;i1<scwdss[Nsi].size();i1++) { 01224 if ((scwdss[Nsi](i1)<leftmost_carrier_IEEE) | (scwdss[Nsi](i1)>rightmost_carrier_IEEE)) { 01225 scwdss[Nsi].del(i1,i1); 01226 } 01227 }; 01228 01229 for (int i1=0;i1<scwcfs[Nsi].size();i1++) { 01230 01231 01232 01233 bool has_ds=false; 01234 int ie=scwcfs[Nsi](i1); 01235 int i4=ie; 01236 if (i4<0) 01237 i4=i4+Nfft; 01238 01239 01240 int i4_low=scwcf_lows[Nsi](i1); 01241 while (i4_low<leftmost_carrier_IEEE) 01242 i4_low++; 01243 01244 while (i4_low>rightmost_carrier_IEEE) 01245 i4_low--; 01246 01247 01248 01249 if (i4_low<0) 01250 i4_low=i4_low+Nfft; 01251 01252 int i4_high=scwcf_highs[Nsi](i1); 01253 while (i4_high<leftmost_carrier_IEEE) 01254 i4_high++; 01255 while (i4_high>rightmost_carrier_IEEE) 01256 i4_high--; 01257 01258 if (i4_high<0) 01259 i4_high=i4_high+Nfft; 01260 01261 if (scwcfs[Nsi].length()==1) { 01262 i4_low=ix_all(0); 01263 i4_high=ix_all(length_ix_all-1); 01264 }; 01265 01266 for (int i2=0;i2<(int) length_ix_all;i2++) { 01267 if (ix_all(i2)==i4) { 01268 scwcf_ix_alls[Nsi](i1)=i2; 01269 }; 01270 if (ix_all(i2)==i4_low) { 01271 scwcf_ix_all_lows[Nsi](i1)=i2; 01272 }; 01273 if (ix_all(i2)==i4_high) { 01274 scwcf_ix_all_highs[Nsi](i1)=i2; 01275 }; 01276 01277 }; 01278 01279 01280 int i2; 01281 for (i2=0;i2<scwdss[Nsi].size();i2++) { 01282 if (scwcfs[Nsi](i1)==scwdss[Nsi](i2)) { 01283 has_ds=true; 01284 break; 01285 }; 01286 }; 01287 01288 scwcf_has_dss[Nsi].ins(scwcf_has_dss[Nsi].length(),has_ds); 01289 if (has_ds) { 01290 scwcf_ds_lows[Nsi](i1)=i2; 01291 scwcf_ds_highs[Nsi](i1)=i2; 01292 } else { 01293 int i2_low=-1000; 01294 for (i2=0;i2<scwdss[Nsi].size();i2++) { 01295 if (scwdss[Nsi](i2)<scwcfs[Nsi](i1)) { 01296 i2_low=i2; 01297 }; 01298 }; 01299 01300 scwcf_ds_lows[Nsi](i1)=i2_low; 01301 int i2_high=-1000; 01302 for (i2=scwdss[Nsi].size()-1;i2>=0;i2--) { 01303 if (scwdss[Nsi](i2)>scwcfs[Nsi](i1)) { 01304 i2_high=i2; 01305 }; 01306 }; 01307 scwcf_ds_highs[Nsi](i1)=i2_high; 01308 }; 01309 01310 }; 01311 01312 01313 01314 01315 d_num_delta_SNRs[Nsi]=0; 01316 for (int i1=0;i1<scwdss[Nsi].size();i1++) { 01317 if ((scwdss[Nsi](i1)>=leftmost_carrier_IEEE) && (scwdss[Nsi](i1)<=rightmost_carrier_IEEE)) { 01318 d_num_delta_SNRs[Nsi]++; 01319 }; 01320 }; 01321 01322 01323 }; 01324 01325 01326 }; 01327 01328 01329 void OFDM2::unpackV(ivec &psis,ivec &phis, cmat &V){ 01330 int i_psis=0; 01331 int i_phis=0; 01332 double phi, psi, c, s; 01333 std::complex<double> t1,t2; 01334 01335 01336 V.zeros(); 01337 for (int i1=0;i1<d_num_ms_ant;i1++){ 01338 V(i1,i1)=1; 01339 }; 01340 01341 for (int l1=d_num_ms_ant-1;l1>=0;l1--) { 01342 for (int l2=d_num_tx_antennas -1;l2>=l1+1;l2--) { 01343 01344 01345 //psi=psis_codebook(psis(i_psis)); 01346 psi=psis_res*(psis(i_psis)+0.5); 01347 01348 01349 c=cos(psi); 01350 s=-sin(psi); 01351 01352 t1=V(l1,l1); 01353 t2=V(l2,l1); 01354 V(l1,l1)=c*t1+s*t2; 01355 V(l2,l1)=-s*t1+c*t2; 01356 for (int i4=l1+1;i4<(int) d_num_ms_ant;i4++) { 01357 t1=V(l1,i4); 01358 t2=V(l2,i4); 01359 V(l1,i4)=c*t1+s*t2; 01360 V(l2,i4)=-s*t1+c*t2; 01361 }; 01362 i_psis++; 01363 }; 01364 01365 for (int l3=d_num_tx_antennas-2;l3>=l1;l3--) { 01366 //phi=phis_codebook(phis(i_phis)); 01367 phi=phis(i_phis); 01368 i_phis++; 01369 if (phi>n_phis_codebook/2) 01370 phi=phi-n_phis_codebook; 01371 phi=(phi+0.5)*phis_res; 01372 01373 01374 if (d_IA_compression) { 01375 if (l1==0) { 01376 if (l3==0) { 01377 phi=0; 01378 }; 01379 if (l3==d_num_tx_antennas/3) { 01380 psi=0; 01381 }; 01382 }; 01383 }; 01384 01385 std::complex<double> c=std::complex<double> (cos(phi),-sin(phi)); 01386 for (int l4=0;l4<(int) d_num_ms_ant;l4++) { 01387 V(l3,l4)=c*V(l3,l4); 01388 }; 01389 }; 01390 01391 }; 01392 01393 }; 01394 01395 void OFDM2::packV(ivec &psis,ivec &phis, const cmat &V){ 01396 01397 cmat Vp=V; 01398 // Number of phis angles 01399 // Nphis=\sum_{i1=0}^{Nr-1} (Nc-1-i1) = (Nc-1)Nr-\sum_{i1=0}^{Nr-1} i1 01400 // = (Nc-1)Nr-Nr/2*(0+Nr-1)=(Nc-1)Nr-Nr^2/2+Nr/2=NcNr-Nr^2/2-Nr/2 01401 01402 // Number of psis angles 01403 // Npsis=\sum_{i1=0}^{Nr-1} (Nc-(i1+1)) = Nr/2*(Nc-1+Nc-(Nr-1+1)) 01404 // = Nr/2*(Nc-1+Nc-Nr)=Nr/2*(2Nc-1-Nr)=NcNr-Nr^2/2-Nr/2 01405 01406 01407 if (d_IA_compression) { 01408 01409 #if 1 01410 double phi=arg(Vp(0,0)); 01411 std::complex<double> c=std::complex<double> (cos(phi),-sin(phi)); 01412 for (int i3=0;i3<d_num_ms_ant;i3++) { 01413 for (int i4=0;i4<d_num_tx_antennas/3;i4++) { 01414 Vp(i4,i3)=c*Vp(i4,i3); 01415 }; 01416 }; 01417 phi=arg(Vp(d_num_tx_antennas/3,0)); 01418 c=std::complex<double> (cos(phi),-sin(phi)); 01419 for (int i3=0;i3<d_num_ms_ant;i3++) { 01420 for (int i4=0;i4<d_num_tx_antennas/3;i4++) { 01421 Vp(i4+d_num_tx_antennas/3,i3)=c*Vp(i4+d_num_tx_antennas/3,i3); 01422 }; 01423 }; 01424 #endif 01425 01426 01427 }; 01428 01429 01430 // Rotation angles 01431 for (int i1=0;i1<d_num_ms_ant;i1++){ // Column 01432 01433 vec phisa=-angle(Vp.get_col(i1)); 01434 01435 #if 0 01436 for (int i2=i1;i2<d_num_tx_antennas-1;i2++) { 01437 //result.phis.push_back(min_index(abs(phis(i2)-phis_codebook))); 01438 phis.ins(phis.length(),min_index(abs(phisa(i2)-phis_codebook))); 01439 //std::cout << "phis=" << phis(phis.length()-1) << "\n"; 01440 }; 01441 #endif 01442 #if 1 01443 int min_ixa; 01444 for (int i2=i1;i2<d_num_tx_antennas-1;i2++) { 01445 //std::cout << "i2=" << i2 << std::endl; 01446 if (phisa(i2)<0) { 01447 min_ixa=(phisa(i2)/phis_res-1.0); 01448 min_ixa=min_ixa+n_phis_codebook;//phis_codebook.length(); 01449 } 01450 else { 01451 min_ixa=(phisa(i2)/phis_res); 01452 }; 01453 01454 //std::cout << "min_ixa=" << min_ixa << std::endl; 01455 phis.ins(phis.length(),min_ixa); 01456 } 01457 01458 01459 #endif 01460 01461 01462 01463 01464 for (int l2=i1;l2<d_num_tx_antennas-1;l2++) { 01465 std::complex<double> c=std::complex<double> 01466 (cos(phisa(l2)),sin(phisa(l2))); 01467 for (int l1=0;l1<d_num_ms_ant;l1++){ // Column 01468 Vp(l2,l1)=Vp(l2,l1)*c; 01469 }; 01470 }; 01471 01472 01473 01474 for (int i2=i1+1;i2<d_num_tx_antennas;i2++) { 01475 01476 double psi_i2_i1; 01477 01478 if (abs(Vp(i1,i1))<1e-5) 01479 psi_i2_i1=pi/2; 01480 else 01481 psi_i2_i1=atan(real(Vp(i2,i1)/Vp(i1,i1))); 01482 01483 01484 #if 0 01485 psis.ins(psis.length(),min_index(abs(psi_i2_i1-psis_codebook))); 01486 #endif 01487 01488 #if 1 01489 int min_ix=(psi_i2_i1/psis_res); 01490 psis.ins(psis.length(),min_ix); 01491 #endif 01492 01493 double c=cos(psi_i2_i1); 01494 double s=sin(psi_i2_i1); 01495 std::complex<double> t1,t2; 01496 01497 t1=Vp(i1,i1); 01498 t2=Vp(i2,i1); 01499 Vp(i1,i1)=c*t1+s*t2; 01500 Vp(i2,i1)=-s*t1+c*t2; 01501 for (int i4=i1+1;i4<(int) d_num_ms_ant;i4++) { 01502 t1=Vp(i1,i4); 01503 t2=Vp(i2,i4); 01504 Vp(i1,i4)=c*t1+s*t2; 01505 Vp(i2,i4)=-s*t1+c*t2; 01506 }; 01507 01508 }; // for i2 01509 01510 }; // for i1 01511 01512 01513 }; 01514 01515 void OFDM2::uncompress_feedback(cmat H[],const OFDM2::compressed_feedback_IEEE80211ac &feedback) { 01516 01517 uint32_t num_of_tx_antennas; 01518 uint32_t num_ms_ant; 01519 01520 01521 01522 num_ms_ant=d_num_ms_ant; 01523 num_of_tx_antennas=d_num_tx_antennas; 01524 01525 01526 /* Unpack average (bar) SNRs first */ 01527 vec bar_SNR(num_ms_ant); 01528 for (int i1=0;i1<(int) num_ms_ant;i1++) { 01529 bar_SNR(i1)=(feedback.bar_SNRs[i1]+128)*0.25-10; 01530 }; 01531 /* Combine with delta SNRs to get SNR per carrier with interpolation */ 01532 01533 01534 01535 //mat SNR(num_ms_ant,scwds.length()); 01536 mat SNR(num_ms_ant,scwdss[d_Ng-1].length()); 01537 vec SNR_sub(num_ms_ant); // SNR on a certain subcarrier in dB 01538 //vec SNR_sub_start(num_ms_ant); // SNR on subcarrier for which delta_SNR is defined. 01539 //vec SNR_sub_stop(num_ms_ant); // SNR on subcarrier for which delta_SNR is defined. 01540 int ix_delta_SNRs=0; // Reading index from feedback.delta_SNRs 01541 01542 01543 for (int i1=0;i1<d_num_delta_SNRs[d_Ng-1];i1++) { 01544 //for (int i1=0;i1<d_num_delta_SNR;i1++) { 01545 for (int i2=0;i2<(int) num_ms_ant;i2++) { // Streams per subcarrier 01546 SNR(i2,i1)=feedback.delta_SNRs[ix_delta_SNRs++]+bar_SNR(i2); 01547 }; 01548 }; 01549 01550 01551 01552 /* Unpack phis and psis abd combine with interpolation*/ 01553 01554 int Na_phis=feedback.Na_phis; 01555 int Na_psis=feedback.Na_psis; 01556 ivec phis(Na_phis); 01557 ivec psis(Na_psis); 01558 01559 cmat V(num_of_tx_antennas,num_ms_ant); 01560 int counter=0; 01561 01562 //for (int i1=0;i1<scwcf.length();i1++) { 01563 for (int i1=0;i1<scwcfs[d_Ng-1].length();i1++) { 01564 01565 //int ie=scwcf(i1); 01566 int ie=scwcfs[d_Ng-1](i1); 01567 01568 if ((ie<leftmost_carrier_IEEE) || (ie>rightmost_carrier_IEEE)) { 01569 continue; 01570 }; 01571 01572 01573 for (int i2=0;i2<Na_phis;i2++) { 01574 phis(i2)=feedback.phis(Na_phis*counter+(Na_phis-1-i2)); 01575 }; 01576 01577 for (int i2=0;i2<Na_psis;i2++) { 01578 psis(i2)=feedback.psis(Na_psis*counter+(Na_psis-1-i2)); 01579 }; 01580 01581 counter++; 01582 01583 01584 unpackV(psis,phis,V); 01585 01586 if (scwcf_has_dss[d_Ng-1](i1)) { 01587 //if (scwcf_has_ds(i1)) { 01588 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01589 //SNR_sub(i2)=SNR(i2,scwcf_ds_low(i1)); 01590 SNR_sub(i2)=SNR(i2,scwcf_ds_lows[d_Ng-1](i1)); 01591 }; 01592 } else { 01593 01594 //if (scwcf_ds_low(i1)==-1000) { 01595 if (scwcf_ds_lows[d_Ng-1](i1)==-1000) { 01596 01597 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01598 //SNR_sub(i2)=SNR(i2,scwcf_ds_high(i1)); 01599 SNR_sub(i2)=SNR(i2,scwcf_ds_highs[d_Ng-1](i1)); 01600 }; 01601 }; 01602 //if (scwcf_ds_high(i1)==-1000) { 01603 if (scwcf_ds_highs[d_Ng-1](i1)==-1000) { 01604 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01605 //SNR_sub(i2)=SNR(i2,scwcf_ds_low(i1)); 01606 SNR_sub(i2)=SNR(i2,scwcf_ds_lows[d_Ng-1](i1)); 01607 }; 01608 }; 01609 #if 0 01610 if ((scwcf_ds_high(i1)>-1000) && (scwcf_ds_low(i1)>-1000)) { 01611 double d=(scwcf(i1)-scwds(scwcf_ds_low(i1)))/(scwds(scwcf_ds_high(i1))-scwds(scwcf_ds_low(i1))); 01612 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01613 SNR_sub(i2)=SNR(i2,scwcf_ds_low(i1))+d*(SNR(i2,scwcf_ds_high(i1))-SNR(i2,scwcf_ds_low(i1))); 01614 }; 01615 }; 01616 #endif 01617 if ((scwcf_ds_highs[d_Ng-1](i1)>-1000) && (scwcf_ds_lows[d_Ng-1](i1)>-1000)) { 01618 double d=(scwcfs[d_Ng-1](i1)-scwdss[d_Ng-1](scwcf_ds_lows[d_Ng-1](i1)))/(scwdss[d_Ng-1](scwcf_ds_highs[d_Ng-1](i1))-scwdss[d_Ng-1](scwcf_ds_lows[d_Ng-1](i1))); 01619 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01620 SNR_sub(i2)=SNR(i2,scwcf_ds_lows[d_Ng-1](i1))+d*(SNR(i2,scwcf_ds_highs[d_Ng-1](i1))-SNR(i2,scwcf_ds_lows[d_Ng-1](i1))); 01621 }; 01622 }; 01623 01624 }; 01625 01626 01627 cmat Ht(num_ms_ant,num_of_tx_antennas); 01628 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01629 double e=sqrt(exp(log(10)*0.1*SNR_sub(i2))* 01630 d_noise_variance_per_subcarrier); 01631 for (int i4=0;i4<(int) num_of_tx_antennas;i4++) { 01632 Ht(i2,i4)=e*conj(V(i4,i2)); 01633 }; 01634 }; 01635 01636 01637 01638 for (int i2=0;i2<(int) num_ms_ant;i2++) { 01639 for (int i4=0;i4<(int) num_of_tx_antennas;i4++) { 01640 //for (int i5=scwcf_ix_all_low(i1);i5<=scwcf_ix_all_high(i1);i5++) { 01641 for (int i5=scwcf_ix_all_lows[d_Ng-1](i1);i5<=scwcf_ix_all_highs[d_Ng-1](i1);i5++) { 01642 H[i4](i2,i5)=Ht(i2,i4); 01643 }; 01644 }; 01645 }; 01646 01647 01648 }; 01649 01650 01651 01652 }; 01653 01654 OFDM2::compressed_feedback_IEEE80211ac OFDM2::compress_feedback(cmat H[]) { 01655 OFDM2::compressed_feedback_IEEE80211ac result; 01656 01657 int num_ms_ant=d_num_ms_ant; 01658 int num_of_tx_antennas=d_num_tx_antennas; 01659 01660 cmat Ht(num_ms_ant,num_of_tx_antennas); 01661 cmat U; 01662 vec s; 01663 cmat V; 01664 vec bar_SNR(num_ms_ant); 01665 ivec bar_SNR_i(num_ms_ant); 01666 bar_SNR.zeros(); 01667 //mat delta_SNR(d_num_delta_SNR,num_ms_ant); 01668 //imat delta_SNR_i(scwcf.size(),num_ms_ant); 01669 mat delta_SNR(d_num_delta_SNRs[d_Ng-1],num_ms_ant); 01670 01671 int num_SNR_estimates=0; 01672 01673 int id=0; // Report Delta SNR subcarrier counter 01674 bool first_iteration=true; 01675 01676 01677 01678 //for (int i1=0;i1<scwcf.length();i1++) { 01679 for (int i1=0;i1<scwcfs[d_Ng-1].length();i1++) { 01680 01681 //int ie=scwcf(i1); // Index IEEE subcarrier numbering 01682 int ie=scwcfs[d_Ng-1](i1); // Index IEEE subcarrier numbering 01683 01684 if ((ie<leftmost_carrier_IEEE) || (ie>rightmost_carrier_IEEE)) { 01685 continue; 01686 }; 01687 01688 01689 // Store MIMO matrix for subchannel ix in Ht 01690 for (int i3=0;i3<num_ms_ant;i3++) { 01691 for (int i2=0;i2<num_of_tx_antennas;i2++) { 01692 //Ht(i3,i2)=(H[i2])(i3,scwcf_ix_all(i1)); 01693 Ht(i3,i2)=(H[i2])(i3,scwcf_ix_alls[d_Ng-1](i1)); 01694 }; 01695 }; 01696 01697 01698 #if 0 01699 cmat Ht="(-0.2130,0.1766),(-1.0431,-0.4140),(-0.4381,2.0034)," 01700 "(0.9835,-0.4320),(1.1437,-0.3601),(0.9726,1.4158);" 01701 "(-0.8657,0.9707),(-0.2701,-0.4383),(-0.4087,0.9510)," 01702 "(-0.2977,0.6489),(-0.5316,0.7059),(-0.5223,-1.6045)"; 01703 #endif 01704 01705 // Ht=USV' 01706 // HtV=US (MxN)*(N,M) (M,M) 01707 // 01708 01709 #if 0 01710 svd(Ht,U,s,V); 01711 V=V.get_cols(0,num_ms_ant-1); 01712 #endif 01713 01714 #if 1 01715 eig_sym(hermitian_transpose(Ht)*Ht,s,V); 01716 V=V.get_cols(num_of_tx_antennas-num_ms_ant,num_of_tx_antennas-1); 01717 #endif 01718 01719 01720 // Make last row real: 01721 #if 0 01722 cvec v_row=V.get_row(num_of_tx_antennas-1); 01723 v_row=elem_div(conj(v_row),to_cvec(abs(v_row))); 01724 V=V*diag(v_row); 01725 #endif 01726 //std::complex<double> c=std::complex<double> (cos(phi),-sin(phi)); 01727 #if 1 01728 std::complex<double> c; 01729 for (int i2=0;i2<V.cols();i2++) { 01730 c=V(num_of_tx_antennas-1,i2); 01731 c=conj(c)/abs(c); 01732 for (int i3=0;i3<V.rows();i3++) { 01733 V(i3,i2)=V(i3,i2)*c; 01734 }; 01735 }; 01736 #endif 01737 01738 01739 01740 01741 // SNR per "stream" 01742 // Ht=U 01743 01744 //vec SNR_subc=diag(abs(hermitian_transpose(U)*Ht*V)); 01745 vec SNR_subc=diag(abs(Ht*V)); 01746 SNR_subc=elem_mult(SNR_subc,SNR_subc); 01747 SNR_subc=SNR_subc/d_noise_variance_per_subcarrier; 01748 SNR_subc=10*log10(SNR_subc); 01749 bar_SNR=bar_SNR+SNR_subc; // Average over streams 01750 num_SNR_estimates++; 01751 01752 01753 // Compress V 01754 packV(result.psis,result.phis,V); 01755 01756 01757 01758 // Save delta_SNR if applicable 01759 //if (scwcf_has_ds(i1)) { 01760 if (scwcf_has_dss[d_Ng-1](i1)) { 01761 delta_SNR.set_row(id,SNR_subc); 01762 id=id+1; 01763 }; 01764 01765 if (first_iteration) { 01766 result.Na_psis=result.psis.size(); 01767 result.Na_phis=result.phis.size(); 01768 first_iteration=false; 01769 }; 01770 01771 01772 }; // for i1 01773 01774 01775 01776 01777 // Average SNR per stream encoding 01778 bar_SNR=bar_SNR/((double) num_SNR_estimates); 01779 double max_bar_SNR=max(bar_SNR); 01780 double compensate_SNR; 01781 if (max_bar_SNR>51.120) 01782 compensate_SNR=51.120-max_bar_SNR; 01783 else 01784 compensate_SNR=0; 01785 01786 //compensate_SNR=0; 01787 01788 01789 for (int i1=0;i1<num_ms_ant;i1++) { 01790 bar_SNR(i1)=bar_SNR(i1)+compensate_SNR; 01791 }; 01792 01793 01794 bar_SNR_i=to_ivec(floor(4*bar_SNR+40+0.5)); 01795 for (int i1=0;i1<num_ms_ant;i1++) { 01796 if (bar_SNR_i(i1)<0) 01797 bar_SNR_i(i1)=-128; 01798 else if (bar_SNR_i(i1)>127+128) 01799 bar_SNR_i(i1)=127; 01800 else 01801 bar_SNR_i(i1)=bar_SNR_i(i1)-128; 01802 01803 result.bar_SNRs.push_back(bar_SNR_i(i1)); 01804 }; 01805 01806 01807 //for (int i3=0;i3<d_num_delta_SNR;i3++) { 01808 for (int i3=0;i3<d_num_delta_SNRs[d_Ng-1];i3++) { 01809 for (int i4=0;i4<num_ms_ant;i4++) { 01810 delta_SNR(i3,i4)=delta_SNR(i3,i4)-bar_SNR(i4)+compensate_SNR; 01811 int snr_ix=floor(delta_SNR(i3,i4)+0.5); 01812 if (snr_ix>7) 01813 snr_ix=7; 01814 else if (snr_ix<-8) 01815 snr_ix=-8; 01816 result.delta_SNRs.push_back(snr_ix); 01817 }; 01818 }; 01819 01820 return result; 01821 } 01822 01823 01824 void OFDM2::extract_multi_antenna(const cmat &waveform, 01825 uint32_t start_sample, cvec &symbols_out, int num_symbols_to_extract){ 01826 01827 // As the short version but also including equalization and estimation of the noise 01828 // in the equalized samples 01829 01830 vec dummy; 01831 cvec signal(length_ix_all); 01832 cvec cpec(3); 01833 std::complex<double> cpec1,cpec2; 01834 01835 demodulate_multi_antenna(waveform,dummy,start_sample,2,num_symbols_to_extract); 01836 01837 01838 uint32_t i3=0; 01839 //std::cout << "h=" << h << "; \n"; 01840 //std::cout << "x_c=" << x_c << "; \n"; 01841 cpec=cpe00; 01842 01843 for (int i1=0;i1<x_c.cols();i1++) { 01844 01845 elem_div_out( x_c.get_col(i1),h,signal); 01846 01847 if (do_use_pilot_carriers) { 01848 // Common phase error correction (CPEC) 01849 //cpec=pilot_symbol/(signal(pilot_carrier1_sub)/h(pilot_carrier1_sub)+ 01850 // signal(pilot_carrier2_sub)/h(pilot_carrier2_sub)); 01851 01852 if (per_symbol_phase_derotation) { 01853 cpec1=pilot_symbol/signal(pilot_carrier1_sub); 01854 cpec2=pilot_symbol/signal(pilot_carrier2_sub); 01855 cpec1=cpec1/abs(cpec1); 01856 cpec2=cpec2/abs(cpec2); 01857 cpec1=1; 01858 cpec2=1; 01859 cpec(1)=cpec1; 01860 cpec(2)=cpec2; 01861 }; 01862 01863 //aw1(aw_ix)=signal(pilot_carrier1_sub); 01864 //aw2(aw_ix)=signal(pilot_carrier2_sub); 01865 01866 01867 }; 01868 01869 01870 for (uint32_t i2=0;i2<length_ix;i2++) { 01871 symbols_out(i3)=signal(ix_sub(i2))*cpec(closest_pilot(i2)); 01872 i3=i3+1; 01873 }; 01874 }; 01875 01876 01877 }; 01878 01879 01880 01881 01882 void OFDM2::demodulate(const cvec &waveform,cvec &symbols_out, uint32_t start_sample, const cvec &h, double &rms_signal) 01883 { 01884 double power,temp; 01885 cvec symbolsc(Nfft); 01886 vec soft_temp; 01887 bool the_symbol_is_known; 01888 cvec signal(Nfft), demodulator_input; 01889 int i4; // Counter in symbols_out 01890 std::complex<double> cpec; 01891 int s; 01892 01893 demodulator_input.set_length(length_ix); 01894 01895 i4=0; 01896 power=0.0; 01897 cpec=1.0; 01898 01899 for (int i1=0;i1<(int) Ns;i1++) { 01900 01901 01902 the_symbol_is_known=false; 01903 for (int i2=0;i2<known_symbol_pos.length();i2++) { 01904 if (i1==known_symbol_pos(i2)) 01905 the_symbol_is_known=true; 01906 }; 01907 01908 if (!the_symbol_is_known) { 01909 01910 s=(Nfft+Np)*d_reorder(i1)+start_sample; 01911 01912 symbolsc=waveform.mid(s,Nfft); 01913 temp=norm(symbolsc); 01914 power=power+temp*temp; 01915 01916 pz_fft(symbolsc,signal); 01917 01918 //std::cout << "h1=" << h(pilot_carrier1_sub) << "\n"; 01919 //std::cout << "s1=" << signal(pilot_carrier1) << "\n"; 01920 //std::cout << "h2=" << h(pilot_carrier2_sub) << "\n"; 01921 //std::cout << "s2=" << signal(pilot_carrier2) << "\n"; 01922 //std::cout << "pilot_symbol=" << pilot_symbol << "\n"; 01923 01924 if (do_use_pilot_carriers) { 01925 // Common phase error correction (CPEC) 01926 //cpec=pilot_symbol/(signal(pilot_carrier1_sub)/h(pilot_carrier1_sub)+ 01927 // signal(pilot_carrier2_sub)/h(pilot_carrier2_sub)); 01928 01929 cpec=pilot_symbol/(signal(pilot_carrier1)/h(pilot_carrier1_sub)+ 01930 signal(pilot_carrier2)/h(pilot_carrier2_sub)); 01931 01932 cpec=cpec/abs(cpec); 01933 01934 }; 01935 01936 elem_div_out(signal(ix_all),h,demodulator_input); 01937 01938 01939 if (do_use_pilot_carriers) 01940 demodulator_input=demodulator_input*cpec; 01941 01942 01943 for (uint32_t i5=0;i5<length_ix;i5++) { 01944 symbols_out(i4)=demodulator_input(ix_sub(i5)); 01945 i4++; 01946 }; 01947 }; 01948 }; 01949 power=power/((Ns-known_symbol_pos.length())*Nfft); 01950 rms_signal=sqrt(power); 01951 } 01952 01953 01954 void OFDM2::synchronize(cvec &waveform, uint32_t &start_pos,double &f_offset) { 01955 cvec de_spread(train.size()); 01956 01957 uint32_t Nlags; 01958 double max_value; 01959 int start_pos_int, max_index; 01960 01961 Nlags=waveform.length()-train.length()+1; 01962 vec FrequencyIx(Nlags), Criterions(Nlags); 01963 01964 for (uint32_t i1=0; i1<Nlags;i1 ++) { 01965 de_spread=elem_mult(waveform.mid(i1,train.length()),conj(train)); 01966 max_value=max(abs(fft(de_spread,Nfft_sync)),max_index); 01967 FrequencyIx(i1)=max_index; 01968 Criterions(i1)=max_value; 01969 }; 01970 01971 max_value=max(Criterions,start_pos_int); 01972 start_pos=start_pos_int; 01973 f_offset=FrequencyIx(start_pos)/Nfft_sync; 01974 if (f_offset>0.5) 01975 f_offset=f_offset-1; 01976 01977 f_offset=f_offset*25e6; 01978 01979 01980 } 01981 01982 void OFDM2::synchronize(cvec &waveform, uint32_t &start_pos) { 01983 cvec de_spread(train.size()); 01984 01985 uint32_t Nlags; 01986 double max_value; 01987 int start_pos_int; 01988 01989 Nlags=waveform.length()-train.length()+1; 01990 vec Criterions(Nlags); 01991 01992 for (uint32_t i1=0; i1<Nlags;i1 ++) { 01993 de_spread=elem_mult(waveform.mid(i1,train.length()),conj(train)); 01994 max_value=sum(abs(de_spread)); 01995 Criterions(i1)=max_value; 01996 }; 01997 01998 max_value=max(Criterions,start_pos_int); 01999 start_pos=start_pos_int; 02000 02001 02002 } 02003 02004 void OFDM2::interleave_symbols(cvec &symbols, int index) { 02005 02006 cvec symbol; 02007 02008 index=index % symbol_interleave_matrix.rows(); 02009 symbol.set_length(length_ix); 02010 02011 for (uint32_t i1=0;i1<Ns-known_symbol_pos.length();i1++) { 02012 symbol=symbols.mid(i1*length_ix,length_ix); 02013 symbol=symbol(symbol_interleave_matrix.get_row(index)); 02014 symbols.set_subvector(i1*length_ix,symbol); 02015 }; 02016 02017 }; 02018 02019 void OFDM2::de_interleave_symbols(cvec &symbols, int index) { 02020 02021 cvec symbol; 02022 02023 index=index % symbol_de_interleave_matrix.rows(); 02024 symbol.set_length(length_ix); 02025 02026 for (uint32_t i1=0;i1<Ns-known_symbol_pos.length();i1++) { 02027 symbol=symbols.mid(i1*length_ix,length_ix); 02028 symbol=symbol(symbol_de_interleave_matrix.get_row(index)); 02029 symbols.set_subvector(i1*length_ix,symbol); 02030 }; 02031 02032 02033 }; 02034