00001
00002 #include <itpp/itcomm.h>
00003
00004 using std::cout;
00005 using std::endl;
00006 using namespace itpp;
00007 using namespace std;
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 void ZF_demod(ND_UQAM &channel, ivec &LLR_apr, ivec &LLR_apost, double sigma2, cmat &H, cvec &y)
00019 {
00020 it_assert(H.rows()>=H.cols(),"ZF_demod() - underdetermined systems not tolerated");
00021 cvec shat=ls_solve_od(H,y);
00022 vec Sigma2=real(diag(inv(H.hermitian_transpose()*H)))*sigma2;
00023 cvec h(length(shat));
00024 for (int i=0; i<length(shat); i++) {
00025 shat(i) = shat(i)/sqrt(Sigma2(i));
00026 h(i) = 1.0/sqrt(Sigma2(i));
00027 }
00028 channel.map_demod(LLR_apr,LLR_apost,1.0,h,shat);
00029 }
00030
00031
00032 extern int main(int argc, char **argv)
00033 {
00034
00035 int nC;
00036 int nRx;
00037 int nTx;
00038 int Tc;
00039
00040 if (argc!=5) {
00041 cout << "Usage: cm nTx nRx nC Tc" << endl << "Example: cm 2 2 1 100000 (2x2 QPSK MIMO on slow fading channel)" << endl;
00042 exit(1);
00043 } else {
00044 sscanf(argv[1],"%i",&nTx);
00045 sscanf(argv[2],"%i",&nRx);
00046 sscanf(argv[3],"%i",&nC);
00047 sscanf(argv[4],"%i",&Tc);
00048 }
00049
00050 cout << "Initializing.. " << nTx << " TX antennas, " << nRx << " RX antennas, "
00051 << (1<<nC) << "-PAM per dimension, coherence time " << Tc << endl;
00052
00053
00054 const vec EbN0db = "-5:0.5:50";
00055 const int Nmethods =2;
00056 const long int Nbitsmax=50*1000*1000;
00057 const int Nu = 1000;
00058
00059 int Nbers, Nfers;
00060 double BERmin, FERmin;
00061 if (Tc==1) {
00062 BERmin = 0.001;
00063 FERmin = 1.0e-10;
00064 Nbers = 1000;
00065 Nfers = 200;
00066 } else {
00067 BERmin = 1.0e-15;
00068 FERmin = 0.01;
00069 Nbers = -1;
00070 Nfers = 200;
00071 }
00072
00073
00074 Convolutional_Code code;
00075 ivec generator(3);
00076 generator(0)=0133;
00077 generator(1)=0165;
00078 generator(2)=0171;
00079 double rate=1.0/3.0;
00080 code.set_generator_polynomials(generator, 7);
00081 bvec dummy;
00082 code.encode_tail(randb(Nu),dummy);
00083 const int Nc = length(dummy);
00084
00085
00086
00087 const int Nctx = (int) (2*nC*nTx*ceil(double(Nc)/double(2*nC*nTx)));
00088 const int Nvec = Nctx/(2*nC*nTx);
00089 const int Nbitspvec = 2*nC*nTx;
00090
00091
00092 ND_UQAM chan;
00093 chan.set_Gray_QAM(nTx,1<<(2*nC));
00094 cout << chan << endl;
00095
00096
00097 Sequence_Interleaver<bin> sequence_interleaver_b(Nctx);
00098 Sequence_Interleaver<int> sequence_interleaver_i(Nctx);
00099 sequence_interleaver_b.randomize_interleaver_sequence();
00100 sequence_interleaver_i.set_interleaver_sequence(sequence_interleaver_b.get_interleaver_sequence());
00101
00102
00103
00104 Array<cvec> Y(Nvec);
00105 Array<cmat> H(Nvec/Tc+1);
00106
00107 ivec Contflag = ones_i(Nmethods);
00108 if (pow(2.0,nC*2.0*nTx)>256) {
00109 Contflag(1)=0;
00110 }
00111 if (nTx>nRx) {
00112 Contflag(0)=0;
00113 }
00114 cout << "Running methods: " << Contflag << endl;
00115
00116 cout.setf(ios::fixed, ios::floatfield);
00117 cout.setf(ios::showpoint);
00118 cout.precision(5);
00119
00120
00121 for (int nsnr=0; nsnr<length(EbN0db); nsnr++) {
00122 const double Eb=1.0;
00123 const double N0 = pow(10.0,-EbN0db(nsnr)/10.0);
00124 const double sigma2=N0;
00125 const double Es=rate*2*nC*Eb;
00126
00127
00128 const double Ess=sqrt(Es);
00129
00130 Array<BERC> berc(Nmethods);
00131 Array<BERC> bercu(Nmethods);
00132 Array<BLERC> ferc(Nmethods);
00133
00134 for (int i=0; i<Nmethods; i++) {
00135 ferc(i).set_blocksize(Nu);
00136 }
00137
00138 long int nbits=0;
00139 while (nbits<Nbitsmax) {
00140 nbits += Nu;
00141
00142
00143 bvec inputbits = randb(Nu);
00144 bvec txbits;
00145 code.encode_tail(inputbits, txbits);
00146
00147
00148 txbits=concat(txbits,randb(Nctx-Nc));
00149 txbits = sequence_interleaver_b.interleave(txbits);
00150
00151
00152 for (int k=0; k<Nvec; k++) {
00153
00154
00155
00156
00157
00158 if (k%Tc==0) {
00159 H(k/Tc) = Ess*randn_c(nRx,nTx);
00160 }
00161
00162
00163 bvec bitstmp = txbits(k*2*nTx*nC,(k+1)*2*nTx*nC-1);
00164 cvec x=chan.modulate_bits(bitstmp);
00165 cvec e=sqrt(sigma2)*randn_c(nRx);
00166 Y(k) = H(k/Tc)*x+e;
00167 }
00168
00169
00170 Array<QLLRvec> LLRin(Nmethods);
00171 for (int i=0; i<Nmethods; i++) {
00172 LLRin(i) = zeros_i(Nctx);
00173 }
00174
00175 QLLRvec llr_apr =zeros_i(nC*2*nTx);
00176 QLLRvec llr_apost=zeros_i(nC*2*nTx);
00177 for (int k=0; k<Nvec; k++) {
00178
00179 if (Contflag(0)) {
00180 ZF_demod(chan,llr_apr,llr_apost,sigma2,H(k/Tc),Y(k));
00181 LLRin(0).set_subvector(k*Nbitspvec,(k+1)*Nbitspvec-1,llr_apost);
00182 }
00183
00184
00185 if (Contflag(1)) {
00186 chan.map_demod(llr_apr, llr_apost, sigma2, H(k/Tc), Y(k));
00187 LLRin(1).set_subvector(k*Nbitspvec,(k+1)*Nbitspvec-1,llr_apost);
00188 }
00189 }
00190
00191
00192 for (int i=0; i<Nmethods; i++) {
00193 bvec decoded_bits;
00194 if (Contflag(i)) {
00195 bercu(i).count(txbits(0,Nc-1),LLRin(i)(0,Nc-1)<0);
00196 LLRin(i) = sequence_interleaver_i.deinterleave(LLRin(i),0);
00197
00198 vec llr=chan.get_llrcalc().to_double(LLRin(i).left(Nc));
00199
00200 code.decode_tail(llr,decoded_bits);
00201 berc(i).count(inputbits(0,Nu-1),decoded_bits(0,Nu-1));
00202 ferc(i).count(inputbits(0,Nu-1),decoded_bits(0,Nu-1));
00203 }
00204 }
00205
00206
00207
00208
00209 int minber=1000000;
00210 int minfer=1000000;
00211 for (int i=0; i<Nmethods; i++) {
00212 if (Contflag(i)) {
00213 minber=min(minber,round_i(berc(i).get_errors()));
00214 minfer=min(minfer,round_i(ferc(i).get_errors()));
00215 }
00216 }
00217 if (Nbers>0 && minber>Nbers) { break;}
00218 if (Nfers>0 && minfer>Nfers) { break;}
00219 }
00220
00221 cout << "-----------------------------------------------------" << endl;
00222 cout << "Eb/N0: " << EbN0db(nsnr) << " dB. Simulated " << nbits << " bits." << endl;
00223 cout << " Uncoded BER: " << bercu(0).get_errorrate() << " (ZF); " << bercu(1).get_errorrate() << " (ML)" << endl;
00224 cout << " Coded BER: " << berc(0).get_errorrate() << " (ZF); " << berc(1).get_errorrate() << " (ML)" << endl;
00225 cout << " Coded FER: " << ferc(0).get_errorrate() << " (ZF); " << ferc(1).get_errorrate() << " (ML)" << endl;
00226 cout.flush();
00227
00228
00229
00230 int contflag=0;
00231 for (int i=0; i<Nmethods; i++) {
00232 if (Contflag(i)) {
00233 if (berc(i).get_errorrate()>BERmin) { contflag=1; } else { Contflag(i)= 0; }
00234 if (ferc(i).get_errorrate()>FERmin) { contflag=1; } else { Contflag(i)= 0; }
00235 }
00236 }
00237 if (contflag) { continue; } else {break; }
00238 }
00239
00240 return 0;
00241 }