four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
modem/modem_OFDM1.cpp
00001 /*
00002  * Copyright 2012-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_OFDM1.m and demod_OFDM1.m
00021  *
00022  *
00023  */
00024 
00025 #include <itpp/itcomm.h>
00026 #include <itpp/stat/misc_stat.h>
00027 #include <math.h>
00028 #include "modem_OFDM1.hpp"
00029 #include <itpp/itbase.h>
00030 #include <complex>
00031 #include <itpp/base/sort.h>
00032 
00033 
00034 using namespace itpp;
00035 using namespace std;
00036 
00037 OFDM1::OFDM1(void){
00038   pilot_power_factor=1;
00039   estimate_SINR=false;
00040   pulse_shape="0.0546,-0.0898,-0.0587,0.3134,0.5612,0.3133,-0.0587,-0.0898,0.0546";
00041   pulse_shape_delay=4;
00042 };
00043 
00044 
00045 uint32_t OFDM1::number_of_modulation_symbols(void){
00046   return  ((Ns-known_symbol_pos.length())*length_ix);
00047 };
00048 
00049 uint32_t OFDM1::waveform_length(void){
00050   return (max(d_reorder)*Ns*(Nfft+Np));
00051 };
00052 
00053 
00054 void OFDM1::init(bool use_pilot_carriers, bool prepend_training,uint32_t prefix_length,uint32_t number_of_symbols, ivec known_symbol_postion_index, ivec reorder){
00055     
00056     pz_init_fft();
00057     Ns=number_of_symbols;
00058     known_symbol_pos=known_symbol_postion_index;
00059     d_reorder=reorder;
00060 
00061     do_use_pilot_carriers=use_pilot_carriers;
00062     do_prepend_training=prepend_training;
00063 
00064     Np=prefix_length;
00065 
00066     if (do_use_pilot_carriers) 
00067       length_ix=36;
00068     else
00069       length_ix=38;
00070 
00071     length_ix_all=38;
00072 
00073     pilot_symbol=1.0+1.0i;
00074     h.set_size(Nfft);
00075     
00076     
00077     string temp_str;
00078     temp_str="1,1,-1,1,1,1,1,-1,1,1,1,-1,1,1,1,-1,-1,-1,1,1,1,1, ";
00079     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, ";
00080     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, ";
00081     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, ";
00082     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, ";
00083     temp_str+="1,1,-1,1,1,1,1,1,1,-1,1,-1,-1,-1,1,-1,-1,1,-1,1 ";
00084     train=temp_str.c_str();
00085     ix.set_size(length_ix);
00086 
00087 
00088 
00089     { uint32_t counter=0;
00090       for (uint32_t i1=1;i1<pilot_carrier1;i1++) {
00091         ix(counter++)=i1;
00092       };
00093 
00094       for (uint32_t i1=pilot_carrier1+1;i1<=rightmost_carrier;i1++) {
00095         ix(counter++)=i1;
00096       };
00097       rightmost_carrier_sub=counter-1;
00098       leftmost_carrier_sub=counter;
00099 
00100       for (uint32_t i1=leftmost_carrier;i1<pilot_carrier2;i1++) {
00101         ix(counter++)=i1;
00102       };
00103       
00104       for (uint32_t i1=pilot_carrier2+1;i1<Nfft;i1++){
00105         ix(counter++)=i1;
00106       };
00107     };
00108     
00109     ix_all.set_size(length_ix_all);
00110     {uint32_t counter=0;
00111 
00112       for (uint32_t i1=1;i1<=rightmost_carrier;i1++) {
00113         ix_all(counter++)=i1;
00114       };
00115       for (uint32_t i1=leftmost_carrier;i1<Nfft;i1++) {
00116         ix_all(counter++)=i1;
00117       };
00118 
00119     };
00120 
00121 
00122     ix_sub.set_size(length_ix);
00123     {int counter=0;
00124       for (uint32_t i1=0;i1<(length_ix+2);i1++) {
00125         for (uint32_t i2=0;i2<length_ix;i2++) {
00126           if (ix_all(i1)==ix(i2)) {
00127             ix_sub(counter)=i1;
00128             counter++;
00129           };
00130         };
00131       };
00132     };
00133   
00134     for (uint32_t i1=0;i1<length_ix+2;i1++) {
00135       if (ix_all(i1)==(int32_t) pilot_carrier1) {
00136         pilot_carrier1_sub=i1;
00137       };
00138 
00139       if (ix_all(i1)==(int32_t) pilot_carrier2) {
00140         pilot_carrier2_sub=i1;
00141       };
00142     };
00143 
00144     if (!do_use_pilot_carriers) {
00145       ix=ix_all;
00146       for (uint32_t i1=0;i1<length_ix;i1++)
00147         ix_sub(i1)=i1;
00148     };
00149 
00150     int no_interleavers=8;
00151     symbol_interleave_matrix.set_size(no_interleavers,length_ix);
00152     symbol_de_interleave_matrix.set_size(no_interleavers,length_ix);
00153     RNG_reset(101);
00154     ivec temp1(length_ix), temp2(length_ix);
00155     Sort<double> my_sort_f;
00156     Sort<int> my_sort_i;
00157 
00158     for (int i1=0;i1<no_interleavers;i1++) {
00159       temp1=my_sort_f.sort_index(0,(int) (length_ix-1),randu(length_ix));
00160       temp2=my_sort_i.sort_index(0,(int) (length_ix-1),temp1);
00161       
00162       symbol_interleave_matrix.set_row(i1,temp1);
00163       symbol_de_interleave_matrix.set_row(i1,temp2);      
00164     };
00165 
00166 
00167       
00168 
00169   } ;
00170 
00171 void OFDM1::pilot_pattern(cvec &burst, cvec precoder) {
00172 
00173 
00174   burst(0)=0.0+0.0i;  burst(1)=-1.0-1.0i; burst(2)=-1.0-1.0i; 
00175   burst(3)=1.0+1.0i; burst(4)=-1.0-1.0i; 
00176   burst(5)=1.0+1.0i; burst(6)=-1.0-1.0i; burst(7)=1.0+1.0i; 
00177   burst(8)=1.0+1.0i; burst(9)=-1.0-1.0i; 
00178   burst(10)=-1.0-1.0i; burst(11)=-1.0+1.0i; 
00179   burst(12)=-1.0+1.0i; burst(13)=1.0+1.0i; 
00180   burst(14)=-1.0+1.0i;  burst(15)=-1.0+1.0i; 
00181   burst(16)=-1.0+1.0i; burst(17)=1.0+1.0i; 
00182   burst(18)=1.0+1.0i; burst(19)=1.0+1.0i; 
00183   burst(20)=0.0+0.0i; burst(21)=0.0+0.0i; 
00184   burst(22)=0.0+0.0i; burst(23)=0.0+0.0i; 
00185   burst(24)=0.0+0.0i; burst(25)=0.0+0.0i; 
00186   burst(26)=0.0+0.0i; burst(27)=0.0+0.0i; 
00187   burst(28)=0.0+0.0i; burst(29)=0.0+0.0i; 
00188   burst(30)=0.0+0.0i; burst(31)=0.0+0.0i; 
00189   burst(32)=0.0+0.0i; burst(33)=0.0+0.0i; 
00190   burst(34)=0.0+0.0i; burst(35)=0.0+0.0i; 
00191   burst(36)=0.0+0.0i; burst(37)=0.0+0.0i; 
00192   burst(38)=0.0+0.0i; burst(39)=0.0+0.0i; 
00193   burst(40)=0.0+0.0i; burst(41)=0.0+0.0i; 
00194   burst(42)=0.0+0.0i; burst(43)=0.0+0.0i; 
00195   burst(44)=0.0+0.0i; 
00196   burst(45)=0.0+0.0i; burst(46)=0.0+0.0i; 
00197   burst(47)=0.0+0.0i; burst(48)=0.0+0.0i; 
00198   burst(49)=0.0+0.0i; burst(50)=0.0+0.0i; 
00199   burst(51)=0.0+0.0i; burst(52)=0.0+0.0i; 
00200   burst(53)=0.0+0.0i; burst(54)=0.0+0.0i; 
00201   burst(55)=0.0+0.0i; burst(56)=0.0+0.0i; 
00202   burst(57)=0.0+0.0i; burst(58)=0.0+0.0i; 
00203   burst(59)=0.0+0.0i; burst(60)=0.0+0.0i; 
00204   burst(61)=-1.0+1.0i; burst(62)=1.0+1.0i; 
00205   burst(63)=-1.0-1.0i; burst(64)=-1.0+1.0i; 
00206   burst(65)=1.0+1.0i; burst(66)=-1.0-1.0i; 
00207   burst(67)=-1.0-1.0i; burst(68)=1.0+1.0i; 
00208   burst(69)=-1.0+1.0i;  burst(70)=-1.0-1.0i; burst(71)=-1.0+1.0i; 
00209   burst(72)=-1.0-1.0i; burst(73)=-1.0+1.0i; burst(74)=-1.0+1.0i; 
00210   burst(75)=-1.0-1.0i; burst(76)=1.0+1.0i; 
00211   burst(77)=-1.0-1.0i; burst(78)=-1.0+1.0i; 
00212   burst(79)=1.0+1.0i;
00213 
00214   for (uint32_t i1=0;i1<Nfft;i1++) {
00215     burst(i1)=burst(i1)*pilot_power_factor/sqrt(2);
00216   };
00217 
00218 
00219   for (uint32_t i1=0;i1<length_ix_all;i1++) {
00220     burst(ix_all(i1))=burst(ix_all(i1))*precoder(i1);
00221   };
00222 
00223 
00224 }; 
00225 
00226 
00227 ivec OFDM1::start_of_known_symbol(void){
00228   ivec temp;
00229   temp.set_length(known_symbol_pos.length());
00230   for (int i1=0;i1<known_symbol_pos.length();i1++) {
00231     temp(i1)=d_reorder.get(known_symbol_pos(i1))*(Nfft+Np);
00232   };
00233   return temp;
00234 };
00235 
00236 
00237 
00238 void OFDM1::modulate(cvec &waveform,const cvec &symbols_in,  
00239                      const uint32_t offset,
00240 double &rms_power,const cvec &precoder)
00241 
00242 {
00243 
00244     cvec symbol(Nfft), symbol_temp(Nfft);
00245     cvec waveform_temp(Nfft);
00246     double power=0,temp;
00247     bool the_symbol_is_known;
00248     int i4; // Counter from symbols_in
00249 
00250     i4=0;
00251     symbol.zeros();
00252 
00253     for (int i1=0;i1<(int) Ns;i1++) {
00254       
00255       the_symbol_is_known=false;
00256       for (int i2=0;i2<known_symbol_pos.length();i2++) {
00257          if (i1==known_symbol_pos(i2))
00258            the_symbol_is_known=true;
00259       };
00260 
00261           
00262 
00263       if (the_symbol_is_known) {
00264         
00265          pilot_pattern(symbol,precoder);
00266 
00267          
00268       } else {  
00269 
00270         for (uint32_t i3=0;i3<length_ix;i3++) {
00271           symbol(ix(i3))=symbols_in(i4)*precoder(ix_sub(i3)); 
00272           i4++;
00273         };
00274         if (do_use_pilot_carriers) {
00275                 symbol[pilot_carrier1]=(1.0+1.0i)/sqrt(2);
00276                 symbol[pilot_carrier2]=(1.0+1.0i)/sqrt(2);
00277                 symbol[pilot_carrier1]*=precoder(pilot_carrier1_sub);
00278                 symbol[pilot_carrier2]*=precoder(pilot_carrier2_sub);
00279         };
00280       };          
00281         
00282       
00283       //waveform_temp=ifft(symbol,Nfft);
00284       pz_ifft(symbol,waveform_temp);
00285       waveform_temp=concat(waveform_temp.mid(Nfft-Np,Np),waveform_temp);
00286       waveform_temp=filter(pulse_shape,1,waveform_temp);
00287 
00288       if (rms_power!=-10) {
00289         temp=norm(waveform_temp.mid(Np,Nfft));
00290         power=power+temp*temp;
00291         temp=norm(waveform_temp);
00292         power=power+temp*temp;
00293       };
00294 
00295       int replace_pos=d_reorder(i1)*(Nfft+Np)+offset-pulse_shape_delay;
00296 
00297       if (replace_pos<0) {
00298         std::cout << "writing outside of waveform in OFDM1::modulate \n";
00299         exit(1);
00300       };
00301       
00302       for (int i2=0;i2<waveform_temp.size();i2++) {
00303          waveform(i2+replace_pos)+=waveform_temp(i2);
00304       };
00305 
00306       
00307 
00308     }; 
00309     if (rms_power!=-10) {
00310       power=power/(Ns*Nfft);
00311       rms_power=sqrt(power);
00312     };
00313     
00314 
00315 };
00316 
00317 
00318 
00319 
00320 void OFDM1::insert_pilot(cvec &waveform, uint32_t symbol_position, uint32_t offset, 
00321 cvec precoder) {
00322   cvec symbol(Nfft);
00323   cvec waveform_temp(Nfft);
00324   symbol.zeros();
00325   pilot_pattern(symbol,precoder);
00326   //waveform_temp=ifft(symbol,Nfft);
00327   pz_ifft(symbol,waveform_temp);
00328 
00329   waveform.replace_mid(symbol_position*(Nfft+Np)+Np+offset,waveform_temp);
00330   waveform.replace_mid(symbol_position*(Nfft+Np)+offset,waveform_temp.mid(Nfft-Np,Np));
00331 };
00332 
00333 
00334 void OFDM1::estimate_channel(cvec waveform,double  &noise_variance_normalized, 
00335                              cvec &h, uint32_t start_sample) {
00336   double noise_variance;
00337   estimate_channel(waveform,noise_variance_normalized,h,start_sample,noise_variance);
00338 
00339 };
00340 
00341 
00342 
00343 void OFDM1::estimate_channel(cvec waveform,double  &noise_variance_normalized,
00344                              cvec &h, uint32_t start_sample, double &noise_variance) {
00345 
00346     cvec pilot(Nfft);
00347     int i1,counter;
00348     complex <double> hhat, actual_meas, ideal_meas, error;
00349     double error_div_h;
00350     cvec signal(Nfft);
00351     cvec h_rotated(Nfft);
00352     complex<double> rotation;
00353 
00354 
00355 
00356     //signal=fft(waveform.mid(0,Nfft));
00357     pz_fft(waveform.mid(start_sample,Nfft),signal);
00358     pilot.set_length(Nfft);
00359     pilot_pattern(pilot,ones_c(length_ix_all));
00360     h=signal(ix_all);    
00361     h/=pilot(ix_all);
00362 
00363 
00364 
00365     noise_variance_normalized=0;
00366     noise_variance=0;
00367     counter=0;
00368 
00369     for (i1=1;i1<ix_all.length()-1;i1++) {
00370 
00371       if (((ix_all(i1)-ix_all(i1-1))==1) && ((ix_all(i1+1)-ix_all(i1))==1)) {
00372 
00373         hhat=0.5*abs(h(i1-1))+0.5*abs(h(i1+1));
00374         complex<double> t;
00375         t=h(i1+1)/h(i1-1);
00376         double a=arg(h(i1-1))+0.5*arg(t);
00377         hhat=polar(abs(hhat),a);
00378         ideal_meas=hhat*pilot(ix_all(i1));
00379 
00380         actual_meas=signal(ix_all(i1)); 
00381         error=ideal_meas-actual_meas;
00382                 
00383         noise_variance+=abs(error)*abs(error);
00384         error_div_h=abs(error)/abs(h(i1));
00385         noise_variance_normalized+=error_div_h*error_div_h;
00386         counter++;
00387       }
00388     };
00389     noise_variance_normalized/=counter;
00390     noise_variance/=counter;
00391 
00392 
00393 
00394  };
00395  
00396 
00397 
00398 void OFDM1::init_multi_antenna(uint32_t no_ant, int32_t buffer_size, ivec &interferers_known_pos_in) {
00399  
00400   for (uint32_t i1=0;i1<Ns;i1++) {
00401      x[i1].set_size(no_ant,length_ix_all);
00402   };
00403   he.set_size(no_ant,length_ix_all);
00404   interferers_known_pos=interferers_known_pos_in;
00405   for (int i1=0;i1<interferers_known_pos.length();i1++) {
00406     hi[i1].set_size(no_ant,length_ix_all);
00407   };
00408 
00409   int num_payload_symbols=0;
00410   bool the_symbol_is_known;
00411   for (int i1=0;i1<(int) Ns;i1++) {
00412     the_symbol_is_known=false;
00413     for (int i2=0;i2<known_symbol_pos.length();i2++) {
00414          if (i1==known_symbol_pos(i2))
00415            the_symbol_is_known=true;
00416     };
00417 
00418     if (!(the_symbol_is_known)) {
00419         num_payload_symbols++;
00420     };    
00421   };
00422 
00423   x_c.set_size(length_ix_all,num_payload_symbols);
00424 
00425 
00426 }
00427 
00428 
00429 void OFDM1::demodulate_multi_antenna(const cmat &waveform,vec &soft_bit, uint32_t start_sample, int modulation_order){
00430 
00431     cvec waveform_temp(Nfft);
00432     double noise_variance, noise_variance_norm;
00433     vec noise_variance_vec; // Noise variance estmimated during pilot.
00434     vec noise_variance_SINR; // Noise variance estmimated when there is
00435                              // no signal. Only for benchmarking
00436     vec soft_temp;
00437     cvec symbolsc(Nfft);
00438     bool the_symbol_is_known;
00439     int32_t num_payload_symbols;
00440     double D=0.0, DI=0.0;
00441     
00442     noise_variance_vec.set_length(waveform.rows());
00443     // Estimate noise variance for analysis purposes
00444 
00445     if (estimate_SINR) {
00446       noise_variance_SINR.set_length(waveform.rows());
00447       int Nsymb;
00448       int start_ix=noise_estimation_start_ix;
00449       int stop_ix;
00450       
00451       for (int i2=0;i2<waveform.rows();i2++) {
00452         noise_variance_SINR(i2)=0;
00453         start_ix=noise_estimation_start_ix;
00454         stop_ix=start_ix+Nfft;
00455         Nsymb=0;
00456         while (stop_ix<noise_estimation_stop_ix) {
00457           waveform_temp=(waveform.get_row(i2)).mid(start_ix,Nfft);
00458           pz_fft(waveform_temp,symbolsc);
00459           noise_variance_SINR(i2)+=sum(sqr(symbolsc(ix_all)))/length_ix_all;
00460           start_ix=stop_ix+1;
00461           stop_ix=start_ix+Nfft;
00462           Nsymb++;
00463         };
00464         noise_variance_SINR(i2)=noise_variance_SINR(i2)/Nsymb;
00465       };
00466     };
00467 
00468     // Do FFT on all signals except pilot
00469     int i10=0;
00470     for (int i1=0;i1<(int) Ns;i1++) {
00471       the_symbol_is_known=false;
00472       for (int i2=0;i2<known_symbol_pos.length();i2++) {         
00473         if (i1==known_symbol_pos(i2))
00474            the_symbol_is_known=true;
00475       };
00476 
00477       if (!(the_symbol_is_known)) {
00478         for (int i2=0;i2<waveform.rows();i2++) {
00479            waveform_temp=(waveform.get_row(i2)).mid((Nfft+Np)*d_reorder(i1)+start_sample,Nfft);
00480            //symbolsc=fft(waveform_temp);
00481            pz_fft(waveform_temp,symbolsc);
00482            x[i10].set_row(i2,symbolsc(ix_all));
00483         };
00484         i10++;
00485       };          
00486     };
00487     num_payload_symbols=i10;
00488 
00489     if (modulation_order==0) return;
00490 
00491     // Estimate the vector channel of desired signal and interferers
00492     for (int i2=0;i2<he.rows();i2++) {
00493        double dummy;
00494 
00495        int s=start_of_known_symbol()(0)+start_sample;
00496        waveform_temp=(waveform.get_row(i2)).mid(s,Nfft);
00497        estimate_channel(waveform_temp,noise_variance_norm,
00498                         h,0,noise_variance);
00499 
00500        noise_variance_vec(i2)=noise_variance;
00501        he.set_row(i2,h);
00502        for (int i1=0;i1<interferers_known_pos.length();i1++) {
00503          s=start_sample+interferers_known_pos(i1)*(Nfft+Np);
00504          waveform_temp=(waveform.get_row(i2)).mid(s,Nfft);
00505          estimate_channel(waveform_temp,dummy,h,0);
00506          hi[i1].set_row(i2,h);
00507        };
00508     };
00509 
00510     noise_variance=mean(noise_variance_vec);
00511 
00512     if (modulation_order==1) return;
00513 
00514 
00515     cmat Rs; // Structured covariance matrix
00516     cmat Ru; // Un-structured covariance matrix
00517     cmat temp;
00518     cvec temp1;
00519     complex<double> hc;
00520     cvec w(waveform.rows());
00521     
00522 
00523     Rs.set_size(waveform.rows(),waveform.rows());
00524     Ru.set_size(waveform.rows(),waveform.rows());
00525 
00526     temp.set_size(waveform.rows(),waveform.rows());
00527     temp1.set_length(waveform.rows());
00528 
00529     for (uint32_t i2=0;i2<length_ix_all;i2++) {
00530 
00531       Ru.zeros();
00532       for (int i1=0;i1<num_payload_symbols;i1++) {
00533         temp1=(x[i1]).get_col(i2);
00534         Ru+=outer_product(temp1,temp1,true);
00535       };
00536       Rs=outer_product(he.get_col(i2),he.get_col(i2),true);
00537       for (int i1=0;i1<interferers_known_pos.length();i1++) {
00538         Rs=Rs+outer_product(hi[i1].get_col(i2),hi[i1].get_col(i2),true);
00539       };
00540       Rs=Rs+diag(noise_variance_vec);
00541       w=inv(Rs)*he.get_col(i2);
00542       w=w/norm(w,2); 
00543 
00544       if (estimate_SINR) {
00545         double d;
00546         DI+=abs(elem_mult_sum(conj(w),(Rs+
00547                          diag(noise_variance_SINR-noise_variance_vec))*w));
00548         d=abs(elem_mult_sum(conj(w),he.get_col(i2)));
00549         D+=d*d;
00550       };
00551       
00552 
00553       h(i2)=elem_mult_sum(he.get_col(i2),conj(w));
00554       for (int i1=0;i1<num_payload_symbols;i1++) {
00555         x_c(i2,i1)=elem_mult_sum(x[i1].get_col(i2),conj(w));
00556       };
00557 
00558     };
00559 
00560     if (estimate_SINR) {
00561        SINR=D/(DI-D);
00562     };
00563 
00564     if (modulation_order==2) return;
00565 
00566     #if 0    
00567     cvec symbol;
00568     symbol.set_length(length_ix_all);
00569     soft_temp.set_length(length_ix);
00570     int bits_per_symbol=log2(modulation_order);
00571 
00572     // Re-estimate noise variance
00573     double noise_variance_temp;
00574     noise_variance=0;
00575     for (int i1=0;i1<num_payload_symbols;i1++) {
00576        symbol=x_c.get_col(i1);
00577        noise_variance_temp=0;
00578        soft_output(symbol,noise_variance_temp,modulation_order,soft_temp);
00579        noise_variance+=noise_variance_temp;
00580     };
00581     noise_variance/=num_payload_symbols;
00582 
00583 
00584     // Soft-value extraction
00585     for (int i1=0;i1<num_payload_symbols;i1++) {
00586        symbol=x_c.get_col(i1);
00587        soft_output(symbol,noise_variance,modulation_order,soft__temp);
00588        soft_bit.replace_mid(i1*length_ix*bits_per_symbol,soft_temp);
00589     };
00590     #endif
00591 };
00592 
00593 void OFDM1::extract_multi_antenna(const cmat &waveform,
00594                                   uint32_t start_sample){
00595 
00596   // When calling this function the following members will be set
00597   // x_c : A matrix which contains the combined signal (#subcarrier,#symbol)
00598   // h : Channel estimate including combiner #subcarriers
00599   // x[#symbols]: The raw complex samples. Each matrix (#subcarrier,#symbol).
00600   // he: Channel estimate for the desired signal (#antenna,#subcarrier)
00601   // hi[#interferers]: Channel estimate of interfering signals.
00602   
00603   vec dummy;
00604 
00605   demodulate_multi_antenna(waveform,dummy,start_sample,2);
00606 };
00607 
00608 
00609 void OFDM1::extract_multi_antenna(const cmat &waveform,
00610                                   uint32_t start_sample, cvec &symbols_out){
00611 
00612   // As the short version but also including equalization and estimation of the noise
00613   // in the equalized samples
00614   
00615   vec dummy;
00616   cvec signal(length_ix_all);
00617   std::complex<double> cpec;
00618 
00619   demodulate_multi_antenna(waveform,dummy,start_sample,2);
00620 
00621 
00622   uint32_t i3=0;  
00623   //std::cout << "h=" << h << "; \n";
00624   //std::cout << "x_c=" << x_c << "; \n";
00625 
00626   for (int i1=0;i1<x_c.cols();i1++) {
00627 
00628     elem_div_out( x_c.get_col(i1),h,signal);
00629 
00630     if (do_use_pilot_carriers) {
00631           // Common phase error correction (CPEC)
00632           //cpec=pilot_symbol/(signal(pilot_carrier1_sub)/h(pilot_carrier1_sub)+
00633           //         signal(pilot_carrier2_sub)/h(pilot_carrier2_sub));
00634 
00635         cpec=pilot_symbol/signal(pilot_carrier1_sub)+
00636           pilot_symbol/signal(pilot_carrier2_sub);      
00637         cpec=cpec/abs(cpec);
00638         signal=signal*cpec;
00639 
00640     };
00641 
00642     for (uint32_t i2=0;i2<length_ix;i2++) {
00643       symbols_out(i3)=signal(ix_sub(i2));
00644       i3=i3+1;
00645     };
00646   };
00647 
00648   
00649 };
00650 
00651 #if 0
00652 void OFDM1::extract_multi_antenna(const cmat &waveform,
00653                                   uint32_t start_sample, cvec &symbols_out){
00654 
00655   // As the short version but also including equalization and estimation of the noise
00656   // in the equalized samples
00657   
00658   //QAM modulation;
00659   vec dummy;
00660   //cvec symbol(1);
00661   //cvec closest_constellation_point(1);
00662 
00663   //modulation.set_M(modulation_order);  
00664   demodulate_multi_antenna(waveform,dummy,start_sample,2);
00665 
00666 
00667   uint32_t i3=0;
00668   cvec temp(length_ix);
00669 
00670   for (int i1=0;i1<x_c.cols();i1++) {
00671       elem_div_out( x_c.get_col(i1),h(ix_sub),temp);
00672       for (uint32_t i2=0;i2<length_ix;i2++) {
00673         symbols_out(i3)=temp(i2);
00674         i3=i3+1;
00675       };
00676   };
00677 
00678 
00679 };
00680 #endif
00681 
00682 
00683 
00684 void OFDM1::demodulate(const cvec &waveform,cvec &symbols_out, uint32_t start_sample, const cvec &h,  double &rms_signal)
00685 {
00686    double power,temp;
00687     cvec symbolsc(Nfft);
00688     vec soft_temp;
00689     bool the_symbol_is_known;
00690     cvec signal(Nfft), demodulator_input;
00691     int i4; // Counter in symbols_out
00692     std::complex<double> cpec;
00693     int s;
00694 
00695     demodulator_input.set_length(length_ix);
00696 
00697     i4=0;
00698     power=0.0;
00699     cpec=1.0;
00700     
00701     for (int i1=0;i1<(int) Ns;i1++) {
00702         
00703       
00704        the_symbol_is_known=false;
00705        for (int i2=0;i2<known_symbol_pos.length();i2++) {
00706          if (i1==known_symbol_pos(i2))
00707            the_symbol_is_known=true;
00708        };
00709 
00710       if (!the_symbol_is_known) {
00711 
00712         s=(Nfft+Np)*d_reorder(i1)+start_sample;
00713         
00714         symbolsc=waveform.mid(s,Nfft);
00715         temp=norm(symbolsc);
00716         power=power+temp*temp;
00717 
00718         pz_fft(symbolsc,signal);
00719 
00720         //std::cout << "h1=" << h(pilot_carrier1_sub) << "\n";
00721         //std::cout << "s1=" << signal(pilot_carrier1) << "\n";
00722         //std::cout << "h2=" << h(pilot_carrier2_sub) << "\n";
00723         //std::cout << "s2=" << signal(pilot_carrier2) << "\n";
00724         //std::cout << "pilot_symbol=" << pilot_symbol << "\n";
00725 
00726         if (do_use_pilot_carriers) {
00727           // Common phase error correction (CPEC)
00728           //cpec=pilot_symbol/(signal(pilot_carrier1_sub)/h(pilot_carrier1_sub)+
00729           //         signal(pilot_carrier2_sub)/h(pilot_carrier2_sub));
00730 
00731           cpec=pilot_symbol/(signal(pilot_carrier1)/h(pilot_carrier1_sub)+
00732                      signal(pilot_carrier2)/h(pilot_carrier2_sub));
00733 
00734           cpec=cpec/abs(cpec);
00735 
00736         };
00737             
00738         elem_div_out(signal(ix_all),h,demodulator_input);
00739 
00740 
00741         if (do_use_pilot_carriers) 
00742           demodulator_input=demodulator_input*cpec;
00743 
00744 
00745         for (uint32_t i5=0;i5<length_ix;i5++) {
00746           symbols_out(i4)=demodulator_input(ix_sub(i5));
00747           i4++;
00748         };
00749       };  
00750     };
00751     power=power/((Ns-known_symbol_pos.length())*Nfft);
00752     rms_signal=sqrt(power);
00753 }
00754 
00755 
00756 void OFDM1::synchronize(cvec &waveform, uint32_t &start_pos,double &f_offset) {
00757     cvec de_spread(train.size());
00758     
00759     uint32_t Nlags;
00760     double max_value;
00761     int start_pos_int, max_index;
00762 
00763     Nlags=waveform.length()-train.length()+1;
00764     vec FrequencyIx(Nlags), Criterions(Nlags);
00765 
00766     for (uint32_t i1=0; i1<Nlags;i1 ++) {
00767       de_spread=elem_mult(waveform.mid(i1,train.length()),conj(train));
00768       max_value=max(abs(fft(de_spread,Nfft_sync)),max_index);
00769       FrequencyIx(i1)=max_index;
00770       Criterions(i1)=max_value;
00771     };
00772 
00773     max_value=max(Criterions,start_pos_int);
00774     start_pos=start_pos_int;
00775     f_offset=FrequencyIx(start_pos)/Nfft_sync;
00776     if (f_offset>0.5)
00777       f_offset=f_offset-1;
00778 
00779     f_offset=f_offset*25e6;
00780     
00781  
00782 }
00783 
00784 void OFDM1::synchronize(cvec &waveform, uint32_t &start_pos) {
00785     cvec de_spread(train.size());
00786     
00787     uint32_t Nlags;
00788     double max_value;
00789     int start_pos_int;
00790 
00791     Nlags=waveform.length()-train.length()+1;
00792     vec Criterions(Nlags);
00793 
00794     for (uint32_t i1=0; i1<Nlags;i1 ++) {
00795       de_spread=elem_mult(waveform.mid(i1,train.length()),conj(train));
00796       max_value=sum(abs(de_spread));
00797       Criterions(i1)=max_value;
00798     };
00799 
00800     max_value=max(Criterions,start_pos_int);
00801     start_pos=start_pos_int;
00802     
00803  
00804 }
00805 
00806 void OFDM1::interleave_symbols(cvec &symbols, int index) {
00807 
00808   cvec symbol;
00809   
00810   index=index % symbol_interleave_matrix.rows();
00811   symbol.set_length(length_ix);
00812   
00813   for (uint32_t i1=0;i1<Ns-known_symbol_pos.length();i1++) {
00814     symbol=symbols.mid(i1*length_ix,length_ix);
00815     symbol=symbol(symbol_interleave_matrix.get_row(index));
00816     symbols.set_subvector(i1*length_ix,symbol);
00817   };
00818  
00819 };
00820 
00821 void OFDM1::de_interleave_symbols(cvec &symbols, int index) {
00822 
00823   cvec symbol;
00824   
00825   index=index % symbol_de_interleave_matrix.rows();
00826   symbol.set_length(length_ix);
00827   
00828   for (uint32_t i1=0;i1<Ns-known_symbol_pos.length();i1++) {
00829     symbol=symbols.mid(i1*length_ix,length_ix);
00830     symbol=symbol(symbol_de_interleave_matrix.get_row(index));
00831     symbols.set_subvector(i1*length_ix,symbol);
00832   };
00833   
00834 
00835 };
00836 
 All Classes Functions Variables