using namespace itpp;
using namespace std;
int main(int argc, char **argv)
{
int nC;
int nRx;
int nTx;
int Tc;
if (argc != 5) {
cout << "Usage: cm nTx nRx nC Tc" << endl << "Example: cm 2 2 1 100000 (2x2 QPSK MIMO on slow fading channel)" << endl;
exit(1);
}
else {
sscanf(argv[1], "%i", &nTx);
sscanf(argv[2], "%i", &nRx);
sscanf(argv[3], "%i", &nC);
sscanf(argv[4], "%i", &Tc);
}
cout << "Initializing.. " << nTx << " TX antennas, " << nRx << " RX antennas, "
<< (1 << nC) << "-PAM per dimension, coherence time " << Tc << endl;
const vec EbN0db = "-5:0.5:50";
const int Nmethods = 2;
const int Nbitsmax = 50000000;
const int Nu = 1000;
int Nbers, Nfers;
double BERmin, FERmin;
if (Tc == 1) {
BERmin = 0.001;
FERmin = 1.0e-10;
Nbers = 1000;
Nfers = 200;
}
else {
BERmin = 1.0e-15;
FERmin = 0.01;
Nbers = -1;
Nfers = 200;
}
ivec generator(3);
generator(0) = 0133;
generator(1) = 0165;
generator(2) = 0171;
double rate = 1.0 / 3.0;
bvec dummy;
const int Nctx = (int)(2 * nC * nTx *
ceil(
double(Nc) /
double(2 * nC * nTx)));
const int Nvec = Nctx / (2 * nC * nTx);
const int Nbitspvec = 2 * nC * nTx;
chan.
set_M(nTx, 1 << (2*nC));
cout << chan << endl;
sequence_interleaver_b.randomize_interleaver_sequence();
sequence_interleaver_i.set_interleaver_sequence(sequence_interleaver_b.get_interleaver_sequence());
ivec Contflag =
ones_i(Nmethods);
if (
pow(2.0, nC*2.0*nTx) > 256) {
Contflag(1) = 0;
}
if (nTx > nRx) {
Contflag(0) = 0;
}
cout << "Running methods: " << Contflag << endl;
cout.setf(ios::fixed, ios::floatfield);
cout.setf(ios::showpoint);
cout.precision(5);
for (
int nsnr = 0; nsnr <
length(EbN0db); nsnr++) {
const double Eb = 1.0;
const double N0 =
inv_dB(-EbN0db(nsnr));
const double sigma2 = N0;
const double Es = rate * 2 * nC * Eb;
const double Ess =
sqrt(Es);
for (int i = 0; i < Nmethods; i++) {
}
long int nbits = 0;
while (nbits < Nbitsmax) {
nbits += Nu;
bvec inputbits =
randb(Nu);
bvec txbits;
txbits = sequence_interleaver_b.interleave(txbits);
for (int k = 0; k < Nvec; k++) {
if (k % Tc == 0) {
H(k / Tc) = Ess *
randn_c(nRx, nTx);
}
bvec bitstmp = txbits(k * 2 * nTx * nC, (k + 1) * 2 * nTx * nC - 1);
Y(k) = H(k / Tc) * x + e;
}
for (int i = 0; i < Nmethods; i++) {
}
QLLRvec llr_apr =
zeros_i(nC * 2 * nTx);
QLLRvec llr_apost =
zeros_i(nC * 2 * nTx);
for (int k = 0; k < Nvec; k++) {
if (Contflag(0)) {
LLRin(0).set_subvector(k*Nbitspvec, llr_apost);
}
if (Contflag(1)) {
LLRin(1).set_subvector(k*Nbitspvec, llr_apost);
}
}
for (int i = 0; i < Nmethods; i++) {
bvec decoded_bits;
if (Contflag(i)) {
bercu(i).count(txbits(0, Nc - 1), LLRin(i)(0, Nc - 1) < 0);
LLRin(i) = sequence_interleaver_i.deinterleave(LLRin(i), 0);
berc(i).
count(inputbits(0, Nu - 1), decoded_bits(0, Nu - 1));
ferc(i).
count(inputbits(0, Nu - 1), decoded_bits(0, Nu - 1));
}
}
int minber = 1000000;
int minfer = 1000000;
for (int i = 0; i < Nmethods; i++) {
if (Contflag(i)) {
minber =
min(minber,
round_i(berc(i).get_errors()));
minfer =
min(minfer,
round_i(ferc(i).get_errors()));
}
}
if (Nbers > 0 && minber > Nbers) { break;}
if (Nfers > 0 && minfer > Nfers) { break;}
}
cout << "-----------------------------------------------------" << endl;
cout << "Eb/N0: " << EbN0db(nsnr) << " dB. Simulated " << nbits << " bits." << endl;
cout << " Uncoded BER: " << bercu(0).get_errorrate() << " (ZF); " << bercu(1).get_errorrate() << " (ML)" << endl;
cout.flush();
int contflag = 0;
for (int i = 0; i < Nmethods; i++) {
if (Contflag(i)) {
if (berc(i).get_errorrate() > BERmin) { contflag = 1; }
else { Contflag(i) = 0; }
if (ferc(i).get_errorrate() > FERmin) { contflag = 1; }
else { Contflag(i) = 0; }
}
}
if (contflag) { continue; }
else {break; }
}
return 0;
}