Turbo Code simulator
Mathys Walma (walma@sce.carleton.ca), June 29, 1998
Based on paper:
[1] William E. Ryan, "A Turbo Code Tutorial,"
http://telsat.nmsu.edu/~wryan/turbo2c.ps
A copy of the paper is included in the archive.
There is a lot of diagnostic code in the main() part of the program. Also
included in the main() is code so that the simulation can start where it left
off if the program is stopped for some reason. After each turbo code run, the
important variables are saved in a file to facilitate this.
The main routine that implements the BCJR decode algorithm is decode().
Thanks to [1] for the pseudo-code. Decode takes a number of arguments, most
are self explanatory.
unsigned decode (double *channelmesg, double *parity1, double *parity2,
unsigned size, bool *mesg);
* channelmesg is the AWGN corrupted message
* parity1 is the AWGN corrupted parity bits from the first recursive
convolutional encoder
* parity2 is the AWGN corrupted parity bits from the second recursive
convolutional encoder and interleaver combination
* size is the size of the interleaver
* mesg is the orignal message that is compared after each iteration to the
decoded message. If they are the same, the decoder exits early
* the value returned is the number of iterations done before successful
decoding
After each iteration encode() checks the decoded message with the original
message to see if the message has been decoded properly. If it has, no more
iterations are done, thereby saving time in the simulation. This also
provides useful information as to the distribution of the number of iterations
for different Eb/No values.
The Eb/No value used in the program (the dB variable) isn't the one usually
quoted in the literature. The Eb/No in the literature is for uncoded bits.
The Eb/No in the program is for the coded bits. For example. in a rate 1/3
code the values would be 4.77 dB apart [10*log(1/3)].
The decode() routine isn't very efficient. During debugging I noticed that in
the 'for' loops often the only thing that would change was a sign bit between
loops, and so values could be precalculated and then based on the sign bit the
appropriate value could be chosen.
As well, the code for parity1 and parity2 information could have been combined
into one, making it easy to extend the decoder into a lower rate decoder
(ie. 1/4 or 1/5). As it is, the code for parity1 decoding and parity2
decoding is almost identical.
The recursive convolutional encoder can be changed with minimal effort, a few
global variables, and of course the createencodetable routine need changing.
The createencodetable routine creates a look up table that represents the
state transition diagram of the encoder. The encode/decode routines then uses
this look up table to encode/deocde blocks of information.
The interleaver size can be modified by changing the global variable N.
SEED is the random number seed and can be used to get reproducable results.
The random number generator comes from Numberical Recipes in C and is included
as a C++ object in a separate file (random.cpp ripped from another project).
The Gaussian generator gaussian(double variance) isn't terribly efficient, but
is numerically valid after comparing to theoretical values for variance, mean,
and examining histograms of generated values. It uses the Central Limit
Theorem, by adding 24 uniform random numbers to approximate a gaussian random
variable. Other routines were tried but didn't come as close to the
theoretical values that this routine did. The numbers are always generated
with a zero mean.
The program was compiled as is with Borland C++ 5.0 under Windows 95 (as a
32bit console appliation), and also with gcc under SUN OS with no problems
(math library needed for gcc {-lm}).
I am always interested in hearing from people that used this program.