four_multi
Multi-Antenna,Multi-Node,Multi-Band,Multi-Cell
modem/AMC.cpp
00001 // Copyright 2011-2013, Per Zetterberg, KTH Royal Institute of Technology
00002 //
00003 // This program is free software: you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation, either version 3 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 //
00016 
00017 
00018 #include "LDPC1.hpp"
00019 #include "AMC.hpp"
00020 #include <itpp/itcomm.h>
00021 #include <iostream>
00022 #include <fstream>
00023 #include <math.h>
00024 #include <cmath>
00025 #include <string>
00026 #include <unistd.h>
00027 
00028 using namespace itpp;
00029 using namespace std;
00030 
00031 AMC::AMC(void) {};
00032 
00033 void AMC::init(uint32_t code_word_size,bool load_from_file) {
00034 
00035   b0.init(0.25,code_word_size,10,load_from_file,"code_data1.it");
00036   b1.init(0.5,code_word_size,10,load_from_file,"code_data2.it");
00037   b2.init(0.625,code_word_size,10,load_from_file,"code_data3.it");
00038   b3.init(0.75,code_word_size,10,load_from_file,"code_data4.it");
00039 
00040   m_code_word_size=code_word_size;
00041 
00042   soft_bit.set_length(code_word_size);
00043   only_raw_bits=false; 
00044 };
00045 
00046 int AMC::codec_message_size(uint32_t codec_ix)  {
00047   return codec(codec_ix)->message_length();
00048 }
00049 
00050 void AMC::encode(uint32_t codec_ix, bvec message, bvec &transmitted) {
00051   codec(codec_ix)->chan_encode(message,transmitted);
00052 };
00053 
00054 void AMC::modulate(uint32_t modulation_order, uint32_t codec_ix,  bvec message, bvec &transmitted, cvec &symbols,int skip_symbols)  {
00055   ivec ti(1);    
00056   cvec ci(1);
00057 
00058   qam.set_M(modulation_order);
00059   codec(codec_ix)->chan_encode(message,transmitted);  
00060 
00061   int f=qam.bits_per_symbol();
00062   ivec b2s=qam.get_bits2symbols();
00063   int symbol_index;
00064 
00065   for (int i1=0;i1<transmitted.length()/f;i1++) {
00066 
00067     symbol_index=b2s(bin2dec(transmitted(i1*f,i1*f+f-1)));    
00068     ti(0)=symbol_index;
00069     qam.modulate(ti,ci);
00070     symbols(i1+skip_symbols)=ci(0);
00071         
00072   };
00073 
00074 
00075 };
00076 
00077 
00078 double AMC::evm(uint32_t modulation_order, bvec &transmitted,  cvec &symbols, int skip_symbols) {
00079   ivec ti(1);    
00080   cvec ci(1);
00081   double evm=0.0;
00082   ivec b2s=qam.get_bits2symbols();
00083   int symbol_index;
00084 
00085   qam.set_M(modulation_order);
00086   int f=qam.bits_per_symbol();
00087 
00088   for (int i1=0;i1<transmitted.length()/f;i1++) {
00089     symbol_index=b2s(bin2dec(transmitted(i1*f,i1*f+f-1)));
00090     ti(0)=symbol_index;
00091     qam.modulate(ti,ci);
00092     evm+=sqr(symbols(i1+skip_symbols)-ci(0));
00093     
00094   };
00095   evm/=(transmitted.length()/f);
00096   evm=sqrt(evm);
00097   return evm;
00098 
00099 };
00100 
00101 
00102 
00103 void AMC::demodulate(const cvec &input_symbols, double noise_variance, uint32_t modulation_order, uint32_t codec_ix, bvec &message_hat, bvec &transmitted_hat) 
00104  {
00105 
00106   qam.set_M(modulation_order);
00107   for (int i1=1;i1<=log2(modulation_order);i1++) {
00108     soft_bit(m_code_word_size-1)=0;
00109   };
00110 
00111   qam.demodulate_soft_bits(input_symbols,noise_variance,soft_bit);
00112 
00113   transmitted_hat=soft_bit<0;
00114 
00115   if (!only_raw_bits) {
00116     codec(codec_ix)->chan_decode(soft_bit,message_hat);
00117   };
00118 
00119 };
00120 
00121 double AMC::noise_variance(const cvec &symbols, uint32_t modulation_order){
00122 
00123   QAM modulation;
00124   double noise_variance_norm;
00125   cvec closest_constellation_point(1);
00126   cvec symbol(1);
00127 
00128   modulation.set_M(modulation_order);  
00129 
00130   // Estimate noise variance in symbols
00131   noise_variance_norm=0;
00132   for (int i1=0;i1<symbols.length();i1++) {
00133     symbol=symbols(i1);
00134     closest_constellation_point=modulation.modulate_bits(
00135                       modulation.demodulate_bits(symbol));
00136 
00137        
00138     noise_variance_norm+=sum(sqr(symbol-closest_constellation_point));
00139   };
00140   noise_variance_norm/=symbols.length();
00141   if (noise_variance_norm<1e-3)
00142     noise_variance_norm=1e-3;
00143 
00144   return noise_variance_norm;
00145 }
00146 
00147 
00148 uint32_t AMC::rand_new(uint64_t *next)  {
00149   uint32_t temp;
00150   (*next) = (*next) * 1103515245 + 12345;
00151   temp = (*next) >> 16;
00152   return (temp % 32768);
00153 };
00154 
00155 void AMC::randb_thread_safe(int size, bvec &out, uint64_t *seed)  {
00156   randb_thread_safe(0,size,out,seed);
00157 };
00158 
00159 
00160 void AMC::randb_thread_safe(int start_ix, int length, bvec &out, uint64_t *seed)  {
00161   for (int i1=start_ix;i1<start_ix+length;i1++) {
00162     out(i1)=rand_new(seed) & 1;
00163   }; 
00164 };
00165 
00166 
00167 void AMC::run_through_all_mcs(void)  {
00168    #define NO_OF_FRAMES 1000
00169   
00170    ivec modulation_orders="4,16,64,256";
00171 
00172    vec sigmas="1.5849    1.4125    1.2589    1.1220    1.0000    0.8913  \
00173                0.7943    0.7079    0.6310    0.5623    0.5012    0.4467  \
00174                0.3981    0.3548    0.3162    0.2818    0.2512    0.2239  \
00175                0.1995    0.1778    0.1585    0.1413    0.1259    0.1122  \
00176                0.1000    0.0891    0.0794    0.0708    0.0631    0.0562  \
00177                0.0501    0.0447    0.0398    0.0355    0.0316    0.0282 ";
00178 
00179 
00180    int modulation_order;
00181    int l,r;
00182    double FER, BER, Rate, BERc, BERc_raw, BER_raw;
00183    mat results(modulation_orders.length()*no_of_codecs(),sigmas.length());
00184    mat BERs(modulation_orders.length()*no_of_codecs(),sigmas.length());
00185    mat BERs_raw(modulation_orders.length()*no_of_codecs(),sigmas.length());
00186 
00187    vec Rates(modulation_orders.length()*no_of_codecs());
00188    bvec input, transmitted, message_hat, transmitted_hat;
00189    cvec symbols;
00190 
00191    Real_Timer timer;
00192    double max_time=0;
00193    BERC berc;
00194    double s2;
00195   
00196    input.set_size(codec_message_size(no_of_codecs()-1));
00197    message_hat.set_size(codec_message_size(no_of_codecs()-1));
00198    transmitted.set_size(m_code_word_size);
00199    transmitted_hat.set_size(m_code_word_size);
00200    symbols.set_size(m_code_word_size/log2((modulation_orders[0])));
00201    RNG_reset(10);               
00202    cout << "Hang on ... this is gonna take a while ...\n";
00203 
00204    for (int i1=0;i1<modulation_orders.length();i1++) {
00205      modulation_order=modulation_orders[i1];
00206      cout << "Modulation order=" << modulation_order << endl;
00207      usleep(1000);
00208 
00209      for (int c=0;c<no_of_codecs();c++) {
00210        cout << "Code number=" << c << endl;       
00211        l=codec_message_size(c);
00212 
00213        r=i1+c*modulation_orders.length();
00214        Rate=(float (l))/((float) m_code_word_size)*
00215                              log2((float) modulation_order);
00216        Rates(r)=Rate;
00217        max_time=0;
00218   
00219        for (int i4=0;i4<sigmas.length();i4++) {
00220          FER=0;
00221          BERc=0;
00222          BERc_raw=0;
00223          usleep(10);
00224 
00225 
00226          for (uint32_t f=0;f<NO_OF_FRAMES;f++) {
00227            
00228            input.set_subvector(0,randb(l));
00229            modulate(modulation_order,c,input.mid(0,l),transmitted,symbols,0);
00230            usleep(10);     
00231 
00232            symbols=symbols+sigmas(i4)*randn_c(symbols.length());
00233            timer.reset();
00234            timer.start();
00235 
00236            s2=sigmas(i4)*sigmas(i4);
00237            s2=noise_variance(symbols.mid(0,m_code_word_size/log2( modulation_order)), modulation_order);
00238 
00239            demodulate(symbols.mid(0,
00240              m_code_word_size/log2( modulation_order)),
00241                       s2,
00242                           modulation_order,c,message_hat,transmitted_hat); 
00243            
00244            timer.stop();
00245            if (timer.get_time()>max_time)
00246              max_time=timer.get_time();
00247 
00248            berc.clear();
00249            berc.count(transmitted,transmitted_hat);  
00250            BER_raw=berc.get_errorrate();
00251 
00252            berc.clear();
00253            berc.count(input.mid(0,l),message_hat.mid(0,l));
00254            BER=berc.get_errorrate();
00255            if (BER>0)
00256              FER=FER+(1.0/((double) NO_OF_FRAMES));
00257 
00258            BERc=BERc+(BER/((double) NO_OF_FRAMES));
00259            BERc_raw=BERc_raw+(BER_raw/((double) NO_OF_FRAMES));
00260            
00261 
00262          };
00263 
00264          std::cout << "res=" << i4 <<"," << s2 << "," << "FER=" << FER << std::endl;
00265          results(r,i4)=FER;
00266          BERs(r,i4)=BERc;
00267          BERs_raw(r,i4)=BERc_raw;
00268        };
00269        std::cout << "Max used time=" << max_time << endl;
00270      };
00271    }; 
00272 
00273 
00274   it_file d1;
00275   d1.open("results_MCS.it");
00276   d1<< Name("results") << results;
00277   d1<< Name("sigmas") << sigmas;
00278   d1<< Name("Rates") << Rates;
00279   d1<< Name("BERs") << BERs;
00280   d1<< Name("BERs_raw") << BERs_raw;
00281   d1.close();
00282 
00283   // Plot results in matlab
00284   // plot(-10*log10(sigmas),(1-results).*repmat(Rates,1,23),'-x') %Waterfall
00285   // plot(-10*log10(sigmas),results,'-x') % FER.
00286 
00287 
00288 };
 All Classes Functions Variables