four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
modem/modem_OFDM2.cpp
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 
 All Classes Functions Variables