File: turbo_test.cpp

package info (click to toggle)
libitpp 4.0.4-2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 7,520 kB
  • ctags: 6,341
  • sloc: cpp: 51,608; sh: 9,248; makefile: 636; fortran: 8
file content (175 lines) | stat: -rw-r--r-- 6,214 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*!
 * \file
 * \brief Turbo encoder/decoder class test program
 * \author Pal Frenger and Erik G. Larsson
 *
 * -------------------------------------------------------------------------
 *
 * IT++ - C++ library of mathematical, signal processing, speech processing,
 *        and communications classes and functions
 *
 * Copyright (C) 1995-2008  (see AUTHORS file for a list of contributors)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * -------------------------------------------------------------------------
 */

#include <itpp/itcomm.h>

using namespace itpp;
using namespace std;


int main()
{
  Turbo_Codec turbo;
  ivec gen(2);
  gen(0) = 07; gen(1) = 05;
  int constraint_length = 3;
  int block_length = 400;
  ivec interleaver_sequence = wcdma_turbo_interleaver_sequence(block_length);
  int iterations = 8;
  string metric = "LOGMAX";
  double logmax_scale_factor = 0.7;
  bool adaptive_stop = true;
  turbo.set_parameters(gen, gen, constraint_length, interleaver_sequence,
		       iterations, metric, logmax_scale_factor,
		       adaptive_stop);
  int num_blocks = 50;

  vec EbN0db = "0.0 0.5 1.0 1.5 2.0";
  double A = 1.0;
  double Ts = 1.0;
  double Ec = A * A * Ts;
  double r = block_length / (3.0 * block_length + 8.0); // 8 tailbits
  double Eb = Ec / r;
  vec EbN0 = pow(10.0, 0.1 * EbN0db);
  vec N0 = Eb * pow(EbN0, -1.0);
  vec sigma2 = N0 / 2;
  ivec nrof_used_iterations;

  vec symbols, received;
  bvec input, coded_bits, decoded_bits, transmitted;

  Normal_RNG noise_src;
  RNG_reset(12345);

  BPSK bpsk;
  BERC berc;

  cout << "=============================================" << endl;
  cout << "           Starting Simulation               " << endl;
  cout << " Bit error rate as a function of Eb/N0       " << endl;
  cout << "=============================================" << endl;
  cout << "  Block length = " << block_length << endl;
  cout << "  Generator polynomials = " << std::oct << gen << std::dec << endl;
  cout << "  Max number of Iterations = " << iterations << endl;
  cout << "  Adaptive stop = " << adaptive_stop << endl;
  cout << "  Eb/N0 = " << EbN0db << " [dB]" << endl;
  cout << "  Turbo encoder rate 1/3 (plus tail bits)" << endl;
  cout << "=============================================" << endl;

  mat err = zeros(4,EbN0db.length());
  mat cor = zeros(4,EbN0db.length());
  mat ber = zeros(4,EbN0db.length());
  mat avg_nrof_iterations = zeros(4,EbN0db.length());
  LLR_calc_unit lowresllrcalc(10,7,9);  // table with low resolution
  Array<Real_Timer> timer(4);
  for (int i = 0; i < 4; i++) { 
    timer(i).reset();
  }

  for (int i = 0; i < EbN0db.length(); i++) {
    cout << "Now simulating EbN0db = " << EbN0db(i) << endl;

    noise_src.setup(0.0, sigma2(i));
    turbo.set_awgn_channel_parameters(Ec, N0(i));
    input = randb(block_length * num_blocks);

    turbo.encode(input,transmitted);
    bpsk.modulate_bits(transmitted, symbols);
    received = symbols + noise_src(transmitted.length());

    // -- logmax decoding --
    turbo.set_metric("LOGMAX",1.0);
    timer(0).start();
    turbo.decode(received, decoded_bits, nrof_used_iterations);
    timer(0).stop();
    berc.clear();
    berc.count(input,decoded_bits);
    err(0,i) = berc.get_errors();
    cor(0,i) = berc.get_corrects();
    ber(0,i) = berc.get_errorrate();
    avg_nrof_iterations(0,i) = static_cast<double>(sum(nrof_used_iterations)) / length(nrof_used_iterations);

    // -- logmap decoding --
    turbo.set_metric("LOGMAP",1.0);
    timer(1).start();
    turbo.decode(received, decoded_bits, nrof_used_iterations);
    timer(1).stop();
    berc.clear();
    berc.count(input,decoded_bits);
    err(1,i) = berc.get_errors();
    cor(1,i) = berc.get_corrects();
    ber(1,i) = berc.get_errorrate();
    avg_nrof_iterations(1,i) = static_cast<double>(sum(nrof_used_iterations)) / length(nrof_used_iterations);

    // -- QLLR decoding, default resolution --
    turbo.set_metric("TABLE",1.0);
    timer(2).start();
    turbo.decode(received, decoded_bits, nrof_used_iterations);
    timer(2).stop();
    berc.clear();
    berc.count(input,decoded_bits);
    err(2,i) = berc.get_errors();
    cor(2,i) = berc.get_corrects();
    ber(2,i) = berc.get_errorrate();
    avg_nrof_iterations(2,i) = static_cast<double>(sum(nrof_used_iterations)) / length(nrof_used_iterations);

    // -- QLLR decoding, low resolution --
    turbo.set_metric("TABLE",1.0,lowresllrcalc);
    timer(3).start();
    turbo.decode(received, decoded_bits, nrof_used_iterations);
    timer(3).stop();
    berc.clear();
    berc.count(input,decoded_bits);
    err(3,i) = berc.get_errors();
    cor(3,i) = berc.get_corrects();
    ber(3,i) = berc.get_errorrate();
    avg_nrof_iterations(3,i) = static_cast<double>(sum(nrof_used_iterations)) / length(nrof_used_iterations);

  }

  cout << "Results: (1st row: logmax, 2nd row: logmap, 3rd row: qllr, default resolution, 4th row: qllr, low resolution" << endl;
  cout << "Bit error rate: " << endl;
  cout << "ber = " << ber << endl;
  cout << "Average numer of iterations used: " << endl;
  cout << avg_nrof_iterations  << endl;
  cout << "Number of bit errors counted: " << endl;
  cout << "err = " << err << endl;
  cout << "Number of correct bits counted: " << endl;
  cout << "cor = " << cor << endl;

  /*
  // The test program cannot print this out, but on my system
  // the QLLR based decoder is about 8 times faster than logmap. -EGL
  cout << "Timers: ";
  for (int i=0; i<4; i++) { cout << timer(i).get_time() << "  "; }
  cout << endl;
  */

  return 0;
}