int main() { //int int M = 16; //Tamaño de la constelación (M = 16,64,256) int k = log2(M); //Bits por símbolo int N = 1000000; //Número de bits a simular int i, j, z; int y, m; int qamLength; //Double double Ec,Eb, BER_sum; //Vectores vec SNRdB, BER; vec EbN0dB, EbN0, N0; //Vectores binarios bvec in_bits, dec_bits; //Vectores complejos cvec qamSymbols, r0n, r1n; cvec s0, s1, h0; cvec h1, r0, r1; cvec h0neg, reciv; //Matrices complejas cmat H, R, Hh; cmat recR0R1; //Classes QAM qam(M); //Se define el modulador M-QAM BERC berc; //Clase de contador de BER AWGN_Channel awgn_channel(0.1); //Clase de canal AWGN it_file ff; //Clase para fuardar resultados en archivo //Parámetros del ruido AWGN Ec = 1.0; //La energía transmitida por símbolo QAM es 1 Eb = Ec / k; //La energía transmitida por bit es Ec/tamaño de palabra SNRdB = linspace(0,25,26); //Vector de SNR en dB EbN0dB = SNRdB - 10*log10(k); //Se convierte el parámetro SNR a N0, para poder utilizar EbN0 = inv_dB(EbN0dB); //la clase AWGN predefinida en la libreria N0 = Eb * pow(EbN0, -1.0); ; //Aleatorización de los generadores de valores rand RNG_randomize(); //Se generan N-bits aleatorios: in_bits = randb(N); //Se modula el vector bits y se guardan los símbolos en el vector qamSymbols qam.modulate_bits(in_bits, qamSymbols); qamLength = qamSymbols.length(); //Tamaño del vector de símbolos //Dividimos el vector de símbolos en s0 y s1, un ejemplo a continuación: //qamSymbols = [a b c d e f]; //s0 = [a c e] //s1 = [b d f] s0 = zeros_c(1,qamLength/2); s1 = zeros_c(1,qamLength/2); z = 0; for (j=0; j < qamLength; j = j+2){ if (j == 0){ s0(j) = qamSymbols(j); s1(j) = qamSymbols(j+1); }else { s0(z) = qamSymbols(j); s1(z) = qamSymbols(j+1); } z++; } std::complex<double> mycomplex (0,1); BER = zeros(1,SNRdB.length()); //Vector para guardar los resultados de BER totales BER_sum = 0; //Ciclo de codificación de Alamouti con ruido, decodificación de Alamouti, //demodulación QAM y cálculo de BER for (i=0; i < SNRdB.length(); i++) { for (m=0; m < 5; m++) { //Caracterización del canal h0 y h1, canales Rayleigh h0 = 1/sqrt(2)*(randn(1,qamLength/2)) + mycomplex * (randn(1,qamLength/2)); h1 = 1/sqrt(2)*(randn(1,qamLength/2)) + mycomplex * (randn(1,qamLength/2)); //Señal recibida sin ruido r0 = elem_mult(h0,s0) + elem_mult(h1,s1); //r0 = h0*s0 + h1*s1 h0neg = -1*h0; r1 = elem_mult(h0neg,conj(s1)) + elem_mult(h1,conj(s0));//r1 = -h0*conj(s1) + h1*conj(s0) //Señal recibida con ruido awgn_channel.set_noise(N0(i)); r0n = awgn_channel(r0); //r0 = h0*s0 + h1*s1 + n0 r1n = awgn_channel(r1); //r1 = -h0*conj(s1) + h1*conj(s0) + n1 H = zeros_c(2,2); //Vector vacío para guardar la matriz de canal R = zeros_c(2,1); //Vector vacío para guardaar la matriz de señal recibida reciv = zeros_c(1,(r0.length()+r1.length())); //Vector para almacenar los símbolos recibidos //------------------Decodificación de Alamouti---------------------------------------------- y = 0; for (k = 0; k < h0.length(); k++) { //Formamos la matriz de canal H = [h0 h1;h1* -h0*] H(0,0) = h0(k); H(0,1) = h1(k); H(1,0) = conj(h1(k)); H(1,1) = -1*conj(h0(k)); //Calculamos la matriz pseudoinversa Hh = conj(H); Hh = Hh.transpose(); H = inv(Hh*H)*Hh; //Matriz pseudo inversa, equivalente a H = pinv(H) en MATLAB R(0,0) = r0n(k); R(1,0) = conj(r1n(k)); //Vector de señal recivida R = [r0; conj(r1)] recR0R1 = H*R; //Decodificación de símbolos recR0R1 = recR0R1.transpose(); //Símbolos decodificados guardados en la variable reciv reciv(y) = recR0R1(0,0); reciv(y+1) = recR0R1(0,1); y = y + 2; } //----------------Fin de decodificación de Alamouti------------------------------------------- //Se demodula el vector qamSymbols y se guardan esos bits en dec_bits qam.demodulate_bits(reciv, dec_bits); //cout<<"Dec bits = "<< dec_bits <<endl; //Cálculo de BER berc.clear(); berc.count(in_bits, dec_bits); //Se guardan los datos en el vector de resultados BER BER_sum = BER_sum+ berc.get_errorrate(); } BER(i) = BER_sum/5; BER_sum = 0; } //Se muestran los resultados totales cout<<"--------------------------------Resultados--------------------------------------"<<endl; cout<<"SNR dB ="<< SNRdB <<endl; cout<<"BER ="<< BER <<endl; cout<<"--------------------------------------------------------------------------------"<<endl; cout <<"Resultados guardados en ./MIMO_2X1_alamouti_qam_result_file.it" << endl; cout << endl; //Se almacenan los resultados de la simulación en un archivo .it: ff.open("MIMO_2X1_alamouti_qam_result_file.it"); ff << Name("SNR_QAM") << SNRdB; ff << Name("BER_QAM") << BER; ff.close(); }
TEST (Demapper, All) { //parameters int const_size = 16; string demapper_method[] = {"Hassibi_maxlogMAP", "GA", "sGA", "mmsePIC", "zfPIC"}; string code_name = "V-BLAST_MxN"; int em_antennas = 2; int rec_antennas = 2; int channel_uses = 1; int perm_len = pow2i(6);//permutation length //QAM modulator class QAM mod(const_size); //Space-Time code parameters STC st_block_code(code_name, const_size, em_antennas, channel_uses);//generate matrices for LD code (following Hassibi's approach) //SISO blocks SISO siso; siso.set_constellation(mod.bits_per_symbol(), mod.get_symbols(), mod.get_bits2symbols()); siso.set_st_block_code(st_block_code.get_nb_symbols_per_block(), st_block_code.get_1st_gen_matrix(), st_block_code.get_2nd_gen_matrix(), rec_antennas); siso.set_noise(1e-1); //bits generation bvec bits = randb(perm_len); //QAM modulation cvec em = mod.modulate_bits(bits)/sqrt(double(em_antennas));//normalize emitted symbols //ST code cmat S = st_block_code.encode(em); //internal variables int symb_block = st_block_code.get_nb_symbols_per_block(); int nb_symb = perm_len/mod.bits_per_symbol();//number of symbols at the modulator output int nb_subblocks = nb_symb/symb_block;//number of blocks of ST code emitted in an interleaver period int tx_duration = channel_uses*nb_subblocks;//transmission duration expressed in number of symbol periods //ideal channel ASSERT_EQ(em_antennas, rec_antennas); cmat mimo_channel = eye_c(em_antennas); cmat rec(tx_duration,rec_antennas); for (int ns=0;ns<nb_subblocks;ns++) { rec.set_submatrix(ns*channel_uses, 0, S(ns*channel_uses, (ns+1)*channel_uses-1, 0, em_antennas-1)* mimo_channel); } //first decoder vec demapper_apriori_data(perm_len); vec demapper_extrinsic_data(perm_len); demapper_apriori_data.zeros();//a priori information of emitted bits cmat ch_att(em_antennas*rec_antennas, tx_duration); ch_att = kron(reshape(mimo_channel, em_antennas*rec_antennas, 1), ones_c(1, tx_duration)); siso.set_impulse_response(ch_att); BERC ber; for (unsigned int n = 0; n < sizeof(demapper_method)/sizeof(demapper_method[0]); ++n) { siso.set_demapper_method(demapper_method[n]); siso.demapper(demapper_extrinsic_data, rec, demapper_apriori_data); //show results ber.count((demapper_extrinsic_data > 0), bits); ASSERT_DOUBLE_EQ(0, ber.get_errorrate()); demapper_extrinsic_data.zeros(); } }