Simulating Turbo Codes using a Modular Simulation Platform
Transcript of Simulating Turbo Codes using a Modular Simulation Platform
Simulating Turbo Codes using a Modular Simulation Platform
by
David C. Lee
Submitted to the Department of Electrical Engineering and Computer Sciencein Partial Fulfillment of the Requirements for the Degree of
Master of Engineering in Electrical Engineering and Computer Science
at the aitKEN
MASSACHUSETTS INSTITUTE OF TECHNOLOGY
May 24, 2002,
Copyright 2002 David C. Lee. All rights reserved.
The author hereby grants to M.I.T. permission to
MASSACHUSETS WSTITUTEOF TECHNOLOGY
JUL 3 1 200?
LIBRARIES
reproduce and distribute publicly paper and electronic copies of this thesisand to grant others the right to do so.
AuthorDepartment of Electrical Engineering and Computer Science
May 24, 2002
Certified byNick Zogakis
VI-A Company Thesis Supervisor
Certified by_Vahid Tarokh
M.I.T. Thesis Supervisor
Accepted by_Arthur C. Smith
Chairman, Department Committee on Graduate Theses
-4
Simulating Turbo Codes using a Modular Simulation Platform
by
David C. Lee
Submitted to theDepartment of Electrical Engineering and Computer Science
May 24, 2002
In Partial Fulfillment of the Requirements for the Degree ofMaster of Engineering in Electrical Engineering and Computer Science
ABSTRACT
A simulation tool was created to evaluate the performance of Turbo codes proposed fordigital subscriber loop channels. The tool is modular and was designed to be highlyflexible. In particular, the use of linked list data structures to handle module input andoutput data flow allows the tool to be structurally flexible. Module definitions aredefined comprehensively and allow for high component flexibility, as well. Expressionsare provided for MAP decoding of convolutional codes under 4-QAM and under higherspectral efficiency modulations. Simulation results match cited results relatively well andindicate that Turbo code algorithms are implemented correctly in the tool. Results offerconfidence in the ability of the simulation tool to correctly estimate the performance ofTurbo codes.
Thesis advisor: Vahid TarokhTitle: Associate Professor
VI-A company supervisor: Nick ZogakisTitle: Systems Engineer
-3-
-4-
ACKNOWLEDGMENTS
The majority of work for this thesis was completed on-site at Texas Instruments,Incorporated, under the mentorship of my supervisor Nick Zogakis. His suggestions andreviews were invaluable throughout the course of this study.
The other members of my group at Texas Instruments were of great help in theirgenerous contribution of time and resources. In particular, my many insightfuldiscussions with Chia-Ning Peng and Elisa Pasquali helped to clarify several issues.During the simulation intensive phase of this study, Texas Instruments contributedvaluable computing time through the use of its workstations. In particular, Nick Zogakis,Konrad Kratochwil, and Brian Weise, were generous in allowing me to use theirworkstations for the simulations. I would also like to thank Krista Jacobsen and PatrickWang for their welcome support and encouragement throughout this study.
At MIT, my thesis advisor Vahid Tarokh was very enlightening in his responsesto my technical questions. Further, his comments and suggestions about the content ofthis thesis greatly helped to shape it into its final form.
I thank Professor Marcus Zahn and Ms. Lydia Wereminski of the MIT VI-Aprogram, and my VI-A advisor Judy Hoyt, for my very positive experiences under theprogram. Lastly, I thank both Texas Instruments and MIT for their support of this study.It has been a rewarding experience!
-5-
-6-
CONTENTS
I Introduction 15
2 Background 192.1 Transm ission using Signal Sets ........................................................... 192.2 T he Shannon L im it .............................................................................. 202.3 Probability of E rror .............................................................................. 222.4 Calculating BER for an AWGN Channel ............................................. 23.2.5 C hannel C oding .................................................................................... 242.6 The C onvolutional C ode ....................................................................... 25
2.6.1 Recursive Systematic Convolutional Code ........................... 262.6.2 Markov Structure of Convolutional Codes ............................ 272.6.3 Decoding using Maximum a posteriori Probability .............. 28
2.7 Symbol Mapping and Channel Observations ...................................... 312.7.1 4-Q A M M odulation ............................................................... 322.7.2 Higher Spectral Efficiency Modulation ................................. 33
2.8 T he T urbo C ode .................................................................................... 362.8.1 The Turbo Encoder ................................................................ 372.8.2 Iterative Decoding and the Turbo Decoder ........................... 382.8.3 Fast Decoding for Rate-1/2 Component Encoders ................ 41
3 The Simulation Tool 453.1 Sim ulation Tool Scope ........................................................................ 453.2 Design Considerations for Structural Flexibility .................................. 47
3.2.1 Simulation Tool Language .................................................... 473.2.2 Module Flow Implementation ............................................... 483.2.3 Data Transfer between Modules ........................................... 493.2.4 M odule Execution .................................................................. 50
3.3 Design Considerations for Component Flexibility ............................... 513.3.1 Linked List Design and Implementation ............................... 523.3.2 Interleaver Design and Implementation ............................... 533.3.3 Convolutional Encoder Design and Implementation ............. 55
3.3.3.1 Use of the Trellis Diagram for Encoding ............... 553.3.3.2 Generating Polynomials ........................................ 573.3.3.3 Constructing the Trellis Diagram ........................... 58
3.3.4 Puncturing / Un-puncturing Module Design and Implementation................................................................................................. 6 0
3.3.5 Signal Mapper Design and Implementation .......................... 62
-7-
3.3.6 Channel and Demodulator Design and Implementation ........3.3.7 MAP Decoder Module Design and Implementation .............
3.4 Sim ulation C ode O rganization .............................................................
4 Simulation Results4.1 Results for Double Parallel Concatenated Turbo Code
4.1.1 Sim ulation 1: Rate-1/2 Turbo code .......................................4.1.2 Simulation 2: Rate-1/2 Turbo code .......................................4.1.3 Sim ulation 3: Rate-2/4 Turbo code .......................................4.1.4 Simulation 4: Rate-2/4 Turbo code .......................................4.1.5 Simulation 5: Rate-2/4 Turbo code .......................................4.1.6 Sim ulation 6: Rate-3/4 Turbo code .......................................4.1.7 Simulation 7: Rate-3/4 Turbo code .......................................4.1.8 Simulation 8: Rate-3/6 Turbo code .......................................4.1.9 Sim ulation 9: Rate-4/6 Turbo code .......................................4.1.10 Sim ulation 10: Rate-4/6 Turbo code .....................................
4.2 Results for Triple Parallel Concatenated Turbo Code ..........................4.2.1 Sim ulation 11: Rate-1/2 Turbo code .....................................4.2.2 Simulation 12: Rate-1/2 Turbo code .....................................
4.3 Sum m ary of Results ..............................................................................
5 Discussion5.1 Reliability of Simulation Tool ..............................................................5.2 Unexpected Simulation Results ............................................................5.3 Sim ulation Speed and M em ory Usage .................................................
6 Conclusions
A Main Simulation Codeturbosim -std.c .......................................................................................turbosim -icoding.c ..............................................................................turbosim -uncoded.c ............................................................................
B Sample Output for turbosim-std.cScreen Output .......................................................................................Output File test. txt .......................................
C Simulation Codegeneral.h ................................................................................................general.c ................................................................................................linkedlist.h ............................................................................................linkedlist.c .............................................................................................source.h .................................................................................................source.c .................................................................................................interleave.h ...........................................................................................interleave.c ............................................................................................
-8-
646566
69707173757678808183858789899192
95959697
99
101101108114
119119123
125125126128129135136139140
co n v .h ................................................................................................... 14 8co n v .c .................................................................................................... 14 9puncture.h ............................................................................................. 159puncturex ............................................................................................. 160mapper.h ............................................................................................... 165m apperx ............................................................................................... 166channel.h ............................................................................................... 177ch an n el.c ............................................................................................... 17 8demod.h ................................................................................................ 180d em o d .c ................................................................................................. 18 1decoder.h ............................................................................................... 184d eco d er.c ............................................................................................... 18 5
References 197
-9-
-10-
LIST OF FIGURES
2-1 BER curve for uncoded 4-QAM ................................................................ 252-2 Rate-1/2 recursive, systematic convolutional code .................................... 262-3 Rate-2/3 recursive, systematic convolutional code .................................... 262-4 Markov diagram of a four state, rate-1/2 convolutional code .................... 272-5 T rellis diagram ............................................................................................ 282-6 C hannel coding .......................................................................................... 292-7 Signal points and labels for 4-QAM ........................................................... 322-8 Signal points and labels for 16-QAM ......................................................... 342-9 Turbo encoder structure .............................................................................. 372-10 Turbo decoder structure .............................................................................. 40
3-1 Turbo encoder from RN-027 .................................................................... 463-2 Turbo encoder from CF-072 ....................................................................... 463-3 Turbo encoder from RN-079 .................................................................... 463 -4 L inked list .................................................................................................. 50
4-1 4-Q A M signal set ........................................................................................ 704-2 16-Q A M signal set ...................................................................................... 704-3 Simulation 1 BER curves for Table 4.2 and Table 4.3 ............................... 734-4 Simulation 2 BER curves for Table 4.2 and Table 4.4 ............................... 744-5 Simulation 3 BER curves for Table 4.6 and Table 4.7 ............................... 764-6 Simulation 4 BER curves for Table 4.6 and Table 4.8 ............................... 774-7 Simulation 5 BER curves for Table 4.6 and Table 4.9 ............................... 794-8 Simulation 6 BER curves for Table 4.11 and Table 4.12 .......................... 814-9 Simulation 8 BER curves for Table 4.16 and Table 4.17 ........................... 844-10 Simulation 9 BER curves for Table 4.19 and Table 4.20 ........................... 864-11 Simulation 10 BER curves for Table 4.19 and Table 4.22 ......................... 884-12 Simulation 11 BER curves for Table 4.24 .................................................. 904-13 Simulation 12 BER curves for Table 4.25 .................................................. 92
- II -
- 12-
LIST OF TABLES
3.1 Sum m ary of sim ulation files ............................................................................. 68
4.1 Simulation I puncturing and mapping scheme ................................................. 714.2 Approximate BER values from cited graphs for simulation I Turbo code ....... 714.3 Simulated BER values for simulation 1 after 10,000 and 100,000 blocks ........ 724.4 Simulated BER values for simulation 2 after 10,000 and 100,000 blocks ........ 744.5 Simulation 3 puncturing and mapping scheme ................................................. 754.6 Approximate BER values from cited graphs for simulation 3 Turbo code ....... 754.7 Simulated BER values for simulation 3 after 10,000 and 100,000 blocks ........ 754.8 Simulated BER values for simulation 4 after 2,500 and 25,000 blocks ............ 774.9 Simulated BER values for simulation 5 after 10,000 and 100,000 blocks ........ 784.10 Simulation 6 puncturing and mapping scheme ................................................. 804.11 Approximate BER values from cited graphs for simulation 6 Turbo code ....... 804.12 Simulated BER values for simulation 6 after 1,666 AND 16,666 blocks ......... 804.13 Simulation 7 puncturing and mapping scheme ................................................. 824.14 Simulated BER values for simulation 7 after 1,666 AND 16,666 blocks ......... 824.15 Simulation 8 puncturing and mapping scheme ................................................. 834.16 Approximate BER values from cited graphs for simulation 8 Turbo code ....... 834.17 Simulated BER values for simulation 8 after 1,666 blocks ............................... 834.18 Simulation 9 puncturing and mapping scheme ................................................. 854.19 Approximate BER values from cited graphs for simulation 9 Turbo code ....... 854.20 Simulated BER values for simulation 9 after 2,500 blocks ............................... 854.21 Simulation 10 puncturing and mapping scheme ............................................... 874.22 Simulated BER values for simulation 10 after 2,500 and 25,000 blocks .......... 874.23 Simulation 11 puncturing and mapping scheme ............................................... 894.24 Simulated BER values for simulation 11 after 650 blocks ................................ 904.25 Simulated BER values for simulation 12 after 1,666 blocks ............................ 914.26 Sum m ary of sim ulation results .......................................................................... 93
5.1 Sim ulation tool m em ory usage .......................................................................... 985.2 Sim ulation tool speed ....................................................................................... 98
- 13 -
- 14-
CHAPTER ONE
INTRODUCTION
Almost every household in the United States uses the telephone system for voice
communications and the cable system for broadcast video. Although traditional uses for
the telephone and cable networks are different, developments in digital communications
in the last fifty years have enabled both systems to be similarly used for data
communications. The telephone system was originally intended for low-bandwidth voice
communications, and its network is optimized to operate primarily in the voice band [1].
Within this band, current computer modems can achieve a data rate of 56 kilobits per
second (kbit/s). Compared to a cable modem, which operates over a system designed for
high-bandwidth video broadcasting, this transfer rate is meager at best. However, with
the advent of digital subscriber loop (DSL) technology, data communications over the
- 15 -
16 CHAPTER ONE
telephone network can now operate beyond the voice band and can achieve
communication speeds similar to that of the cable modem.
One variant of DSL technology is the asymmetrical digital subscriber loop, or
ADSL. In ADSL, the data rate from the end-user to the central office (upstream) is about
one-tenth the rate from the central office to the end-user (downstream). The specification
for ADSL is contained in International Telecommunications Union (ITU) standard
G.992.1, also known as G.dmt. G.dmt specifies an optional channel code as a
performance enhancement feature. Although the use of this code is optional, its use
greatly improves data rate.
Since the adoption of the channel code in G.dmt, even more powerful codes have
been discovered. In particular, the Turbo code has been the focus of much research
effort. The Turbo code is a class of parallel-concatenated codes discovered in 1993.
Research efforts have shown that with the use of Turbo codes, achievable data rates
approach very close to theoretical limits [2].
As part of the ITU's ongoing commitment to improve its standards, it has posted
question 4/15 (question 4, study group 15) to the telecommunications industry to solicit
enhancements to G.dmt and other DSL standards. The response is that many companies
have recommended various Turbo codes as a replacement for the current channel code in
G.dmt. These recommendations specify different types of Turbo codes and some cite
simulation results. There is currently no sure way to compare the different
recommendations because there may be differences in simulation implementations and
test parameters. Thus, there is need for a Turbo code simulation platform that can easily
and efficiently simulate the different Turbo codes specified in the recommendations.
INTRODUCTION 17
This thesis will discuss implementation issues in simulating Turbo codes, present
a modular software tool for simulating Turbo codes, and analyze the performance of the
software tool and the reliability of simulated results. Of particular interest is the modular
implementation of the tool, which allows the tool to be highly flexible. Further, the thesis
describes in detail maximum a posteriori (MAP) probability decoding of convolutional
codes under 4-QAM and under higher spectral efficiency modulations.
CHAPTER TWO
BACKGROUND
The principles of digital communication stem from a field of research called information
theory. This field originated about fifty years ago through the seminal work of Claude
Shannon. Shannon theorized that information can be expressed as binary digits and that
the transmission of information can be quantified. Shannon was one of earliest scientists
to realize binary information, and his work held important notions that paved the way for
modern communication technology. This section will review concepts fundamental to
digital communication and will discuss the Turbo code.
2.1 Transmission using Signal Sets
In a communication channel, information is transmitted through the use of signal carriers.
Each carrier occupies a specific frequency and information is placed onto a carrier by
- 19-
20 CHAPTER TWO
modulating the carrier's amplitude or phase. The set of all possible modulations is called
a signal set, which can be represented as points in a Cartesian space. A group of b
information bits is transmitted by modulating a carrier with one of M = 2bpoints from a
signal set. Each of the M points represents a distinct group of b bits and is also called a
symbol.
A Cartesian space representation is powerful in that it allows us to use familiar
concepts such as magnitude and distance on signal sets. Let P,, i=0, 1, 2, ... , M-1, be
points in a signal set. The average symbol energy E, of the signal set is
M-1 2
where F,.l is the magnitude of Pi. The concept of information bits will become clear in
the sections that follow, but for now suppose that of the b bits in a symbol, only q bits are
categorized as information bits. The average energy per information bit is defined as
EEj -- ES .(2)
2.2 The Shannon Limit
A channel model that is widely used in information theory is the ideal band-limited
additive white Gaussian noise (AWGN) channel. This model reflects important
characteristics of real communication channels and is relatively simple and analytic [3].
In an AWGN channel, the channel is gain insensitive, and transmitted symbols are
altered only by additive noise. The ratio of signal power to noise power is called the
signal-to-noise ratio, or SNR, and it is an important figure in channel coding.
BACKGROUND 21
Using SNR, Shannon expressed in a formula the rate R at which information could
be transmitted with low probability of error. The formula defines a quantity called
channel capacity, and for a channel with bandwidth W, it is (in [bits/second])
C= W log 2 (1+SNR) . (3)
Shannon theorized that it is possible to transmit information at an arbitrarily low
probability of error only if R < C; low probability of error is otherwise unattainable.
Thus, channel capacity acts as an upper bound for transmission rates and is also known as
the Shannon limit.
The Shannon limit can also be interpreted as a lower bound for SNR:
R<W log 2 (1+ SNR)
R <log2 (1+ SNR)
W
R
SNR > 2w -1. (4)
The quantity p = R /W is called spectral efficiency and has units [(bits/second)/Hertz].
The relation in (4) is usually normalized with respect to p and becomes
SNR 2P -I
p p
The quantity SNR /p is equivalent to the ratio E. /NO, where No is the two-sided noise
power spectral density (PSD) of the channel. The quantity Eb /No is widely used in
channel coding and is often expressed in decibels [dB]. The Shannon limit is then
Eb [dB]>10log,0 21 (5)No p )
22 CHAPTER TWO
2.3 Probability of Error
As previously mentioned, symbols transmitted in an AWGN channel are altered by
additive noise. The receiver must try to determine, from the altered symbols, what was
actually transmitted. A simple decision rule, called the minimum distance (MD) decision
rule, chooses the point in the signal set that is closest in distance to the received point.
For example, suppose that a signal set is one-dimensional so that signal set points
are real numbers. Further, assume that the distance between adjacent points in the signal
set is constant and equal to d. Using the MD rule, an erroneous decision will occur if a
symbol is altered by noise n with magnitude greater than d /2. The probability of error
can be expressed using the cumulative distribution function for the Gaussian noise
random variable:
Prn->!= 2 N a 2 dy . (6)
Expressed using the Gaussian probability of error function
Q(x)=fj e 2 dy
the error probability in (6) becomes
probability of error = Q . (7)2(TN
The quantity d /(2JN) is directly related to E /No . The energy per information bit E
is inextricably related to the distance d between adjacent points in the signal set such that
BACKGROUND 23
any increase or decrease in d will affect a similar increase or decrease in Eb .
parameter oN is directly related to No in an AWGN channel by UN2 = No /2.
The
Although
various assumptions were made to arrive at the probability of error expression in (7), the
underlying principle is that probability of error depends on Eb INO. The main point,
shown by this particular case and applicable to other cases, is that probability of error can
be and most often is calculated as a function of E, / NO .
Probability of error is defined as the probability that a bit error will occur given
that all previous bits were correctly decoded. A more practical measure of error is the
percentage of bits that are decoded incorrectly, called the bit error rate (BER). The BER
is also calculated as a function of E, INO .
2.4 Calculating BER for an AWGN Channel
As previously mentioned, the noise variance is uN2 = No /2 for an AWGN channel with
two-sided noise power No. Using this expression together with (2), the noise variance
can be expressed as
2 No( EJN 2_. iqs =E,2 q2 b) .No
Parameters E, and q are predetermined and are generally not altered,'leaving E, /No as
the sole variable. Using (8) for a specific value of E, NO, white noise samples can be
2generated from a Gaussian process with variance aN . Then, these samples can be added
to transmit symbols to simulate an AWGN channel. Using the MD decision rule, the
(8)
BACKGROUND 23
24 CHAPTER TWO
BER curve for a square QAM signal set with M=4 (b=2) is shown in Figure 2-1. This
curve is called an uncoded BER curve because the shape of the curve does not come from
any coding scheme.
2.5 Channel Coding
The BER curve in Figure 2-1 shows that an increase in the quantity E, INO results in a
decrease in the bit error rate. The noise power No is a fixed characteristic of the channel
and cannot be altered. Thus, Eb /No can only be increased by making E, larger, which
can be accomplished by increasing the minimum distance d between points in the signal
set. However, Eb is often limited by regulations specifying maximum transmit power, so
the BER for a signal set can be decreased only to a certain point. With the use of channel
codes, we can achieve lower BERs than that of Figure 2-1 at the same E, /No values.
The BER curve generated using a channel code is called a coded BER curve.
Channel coding relies on a metric called the Hamming distance, which is a
measure of the number of bits that differ between two binary numbers of the same length.
Channel coding adds extra bits to a group of binary numbers, called codewords in coding
jargon, to increase their minimum Hamming distance. For example, the minimum
Hamming distance is I for the set of codewords U = {00, 01, 10, 11}; that is, the
minimum number of bits that differ between any two codewords in the set is 1. Suppose
that the 2-bit codewords in U are each mapped to 3-bit codewords as follows: 00 4 000;
01 + 011; 10 + 101; 11 + 110. Now, the minimum Hamming distance between
codewords in the new set P = {000, 011, 101, 1101 is 2. By increasing the minimum
Hamming distance of a set of codewords, the decoder can better distinguish between
them. The result is that the decoder possesses a limited ability to correct errors. In the
codewords of set P, only two out of three bits are part of the original codewords in U; the
other bit is extra. Since this extra bit must also be transmitted, the overall data
transmission rate is reduced. This reduced data rate is the cost of channel coding.
1.E+00
1.E-01
wI
1.E-02
1.E-03
1.E-04
1.E-05
1.E-06
1.E-07
______________________ [ ______________________ _______________________
__ __ __ 4 __ __ __
3 4 5
Figure 2-1. BER
6 7 8 9
Eb/No [dB]
curve for uncoded 4-QAM
2.6 The Convolutional Code
A convolutional code is a channel code in which each output bit is formed from a linear
sum of present input bits and past input and output bits. The process of generating output
bits requires memory and is the same as a discrete-time convolution operation. A
convolutional code with k input bits and n output bits is denoted as a rate-k/n code, with n
> k.
10
BACKGROUND 25
26 CHAPTER TWO
2.6.1 The Recursive Systematic Convolutional Code
One type of convolutional code is the recursive, systematic convolutional code (RSCC),
which is used as a component of the Turbo code. The term systematic means that k of the
n output bits are exact duplicates of the input bits; these bits are called information bits or
systematic bits. Thus, only (n-k) output bits are formed by convolution; these (n-k) bits
are called parity bits. The term recursive means that the output bits are fed back so that
each parity bit is also a linear sum of previous output bits. Figure 2-2 below shows one
implementation of a rate-1/n RSCC encoder, and Figure 2-3 shows a rate-k/(k+1) RSCC
encoder. In the diagrams below, S1 denotes a memory register, u1 denotes an input bit,
and p1 denotes an output bit.
P1
U 0 3~S
Figure 2-2. Rate-1/2 recursive, systematic convolutional code
U0 p1
)( P~111 30
Figure 2-3. Rate-2/3 recursive, systematic convolutional code
BACKGROUND 27
2.6.2 Markov Structure of Convolutional Codes
A convolutional code can be described using a Markov model in which each state
corresponds to the memory register values of the encoder and each branch corresponds to
a distinct group of input bits. If there are v memory registers and k input bits, the Markov
model will have 2 branches exiting each state and 2' states. The convolutional codes in
Figures 2-2 and 2-3 both have 24 = 16 states, but where the code in Figure 2-2 has two
branches exiting and two branches entering each state, the one in Figure 2-3 has four.
The Markov diagram for a four state, rate-l/2 code might be:
u0o= 10 U0
Figure 2-4. Markov diagram of a four state, rate-1/2 convolutional code
Depending on how memory register bits are assigned, the bit So can correspond to either
the most-significant bit (MSB) or least-significant bit (LSB) of the state. The example in
Figure 2-4 does not make a distinction.
28 CHAPTER TWO
A convolutional code is typically initialized to the zero state. The input bits at
each time period determine which branch is taken and thus, the next state of the code.
When the Markov diagram in Figure 2-4 is laid out for each time period, the resulting
structure is called a trellis. The trellis for the Markov diagram in Figure 2-4 is shown
below. When a convolutional code also ends in the zero state, its trellis is said to be
terminated.
00 00 00
10/ 10
11 11
Figure 2-5. Trellis diagram
2.6.3 Decoding using Maximum a posteriori Probability
The output bits of a convolutional code are mapped to a signal set point, and the point is
transmitted across an AWGN channel. The output of the channel is called an observation
and is also a point in Cartesian space. In two-dimensional space, the observation is
R =(r, r,). The task of the decoder is to determine, from the observation, which
information bits were most probably at the input of the convolutional encoder.
One way to decode the convolutional code is to calculate a posteriori probabilities
(APP) and to choose the largest one. For a rate-k/n convolutional code, the data bits
BACKGROUND 29
U, = i (t corresponding to a discrete time index) can have values i = 0, 1, 2, ... , 2 k_-
The decoder calculates the 2 a posteriori probabilities Pr(u, = i observations), and the
value of i corresponding to the maximum APP is used as the decoded data bits. Thus, the
decision rule is called maximum a posteriori (MAP) probability decision rule.
signJ set
U t MSCC(
* t
AtJJGN channelobsenrdion
U M decoder :
R= (r., ry)
Figure 2-6. Channel coding
MAP decoding of the convolutional code is performed using observations over
several time indices starting at index t =1 to an ending index t = 'r. Therefore,
information bits are decoded in blocks. For a rate-k/n code, the information bits u, at
time t correspond to a trellis branch from a state S,_, = m' to another state St = I,
producing parity bits pt.
Suppose there are N observation points for each block of information bits, and the
vector of those points is denoted by R7N = (R-, RN ). The APP is expressed as:
Pr( u, = i RN )= K Za,_(m'y(R,,mn', m),(in) . (9)t~~~~ ni )i(RI 13 M
30 CHAPTER TWO
K,,,),, is a factor used to normalize the sum of Pr(u, = i RI N ) across all i to unity [12].
The a and # terms in (9) are called state parameters and are defined as
a, (m) = Pr(S, = in R[)
Pr(R, 1 St = m).8t(in)= Pr(R, 1 R[
N+
(10)
(11)
They are recursively calculated using
a, (in) = Ka a,_ (m')y (R,, in', m)
,(M')=- Kg yj(R,, 17', m#4()t+1 m)8+nm
(12)
(13)
K, and K8 are normalization parameters used to ensure that the sum of a, (in) across all
m and of /, (in') across all in' is unity. The a recursion in equation (12) is initialized by
realizing that if a convolutional code starts in state 0, then by the definition in (10)
a(0) = 1 and ao(m)= 0 for in # 0. For the 8 recursion in (13), if a code is terminated,
then we can initialize f, (0) = 1 and P, (in) = 0 for in # 0.
terminated, then there are two ways to initialize #(m).
However, if the code is not
The first way is to make all
8# (m) equiprobable by setting each term to 2 -, where v is the number of memory
registers in the code. The second way [4] is to first calculate the a recursion in (12) and
then equate #,(in)= a,(in) for each m.
The y term in (9) is called a branch parameter is defined as
y,(R,,m',in)= Pr(R,|u, = i, S,, = in', S, = in)-
Pr(u, = i|S,1 = m', S, = M)Pr(S, = mIS,_, = n').
(14)
30 CHAPTER TWO
BACKGROUND 31
The first probability on the right side of (14) is discussed in Section 2.7. The second term
on the right side of (14) is either 0 or 1, depending on whether information bits u, =i
correspond to the branch transition from St, =' to S, =m. The last term in equation
(14) is the a priori probability, which can also be written as Pr(u, =i) for all values of i.
The a priori probability is discussed in Section 2.8.
Note that the subscript for the observation point R is somewhat ambiguous. There
are r time indices and N observations per block, and the two may not be equal. In (9),
the observation R, simply refers to the observation, out of the N in a block, which
contains information for time index t. Thus, a specific observation may be used over
multiple time indices ( N > r) or multiple observations may be required for each time
index ( N < r). In general, r is an integer multiple of N.
2.7 Symbol Mapping and Channel Observations
The beginning of Section 2.6.3 briefly stated that the output bits of a convolutional code
are mapped to a symbol and that channel observations are used in decoding. This section
addresses symbol mapping and channel observations in detail and develops expressions
for the probabilities in (14).
After encoding, the n bits in u, and p, are mapped to a point in the signal set.
Each of the M = 2" symbols in a signal set represents a distinct group, or label, of b bits.
It is possible that b # n, in which case u, and p, will either be spread over multiple
symbols (b < n) or be only part of one symbol (b > n). In most cases, b is a multiple of n.
32 CHAPTER TWO
The following two sub-sections discuss symbol mapping and decoding under 4-
QAM and under higher spectral efficiency modulations for b n.
2.7.1 4-QAM Modulation
Each signal point in a 4-QAM signal set represents two bits. The first bit corresponds to
the x-coordinate, and the second bit corresponds to the y-coordinate. Thus, 4-QAM only
supports rate-1/2 convolutional codes. In this case, b = n, and the number of observation
points N equals the number of time indices r in a block.
01 11* 1- 0
-1 1
* -1- 0
00 10
Figure 2-7. Signal points and labels for 4-QAM
An observation R = (rr, ry ) is a point in two-dimensional space. In the first
probability on the right side of (14), we notice that the x- and y-coordinates are
uncorrelated Gaussian variables, given u, =i,S,_ = m',S, =m. Thus, (14) can be re-
written as
Pr(RIu, = i,S,_, = m',S, = m)= Pr(r ,|u, = i,S,_1 = m',S, = m) (15)
Pr(r,|, = i, S,_, = m', S, = M).
BACKGROUND 33
From the condition u, =i,S,_, =n',St = i, we know the trellis branch at time t and, thus,
the parity bit p, for that branch. If P =(P,, P is the transmit symbol mapped by u,
and p,, then the two probabilities on the right side of (15) are
Pr(r, I = i, S,_ =i', S,= ) = 2 -T' 12 (16)
and
Pr(r, l u, = i, S,_ = m', S, = M)= e- 29 (17)
where o2 is the channel noise variance per real dimension.
2.7.2 Higher Spectral Efficiency Modulations
Equations (15) through (17) do not hold for modulations with spectral efficiencies higher
than 4-QAM. There are only two coordinates per symbol representing more than two bits
per symbol. Regardless of whether b = n or b > n, we still need information for each of
the b bits. The way to generate this information is to calculate a log likelihood ratio
(LLR) for each bit in a symbol [6].
For the purpose of illustration, suppose that the convolutional encoders have rate-
1/2 and that b = 2n = 4 bits. The Turbo encoder generates 1 information bit and 1 parity
bit each time index t. The outputs of the Turbo encoder are arranged in the order u,, ,,t
U,,, p,, and are mapped to a transmit symbol from the 16-QAM signal set shown in
Figure 2-8; there are N = r /2 symbols over the period t = I ... r. Each observation now
corresponds to 4 bits and two trellis branches.
34 CHAPTER TWO
To calculate a bit LLR, we begin by observing that noise in the AWGN channel is
one-dimensional, and the noise samples that move the x- and y-coordinates are
independent. Further, the first b/2 bits of each point are associated with the x-
coordinate, and the last b/2 bits are associated with the y-coordinate. These facts allow
us to consider only the x-coordinate when calculating the LLRs for the first b/2 bits and
to consider only the y-coordinate when calculating the LLRs for the last b/2 bits [6].
00100
01100
0011 01110 0
00010
0000S
0101
0100
1110 1010
1111 1011
1101 10010 0
1100 10000 S
Figure 2-8. Signal points and labels for 16-QAM
The formula [4] for calculating the LLR of the j1h bit L(b) is
le 2U.2
L(bj) n P1:b =1
Ye- 20 U 2 (12
P0~b =0
bfor J <-, and
2(18)
BACKGROUND 35
L(b)= In P1:bj =1
I):h =0
In equations (18) and (19), T is the channel noise variance per real dimension;
R = (rx, r, ) is the observation point; P and P, are the x-coordinates of points where
b, is I and 0, respectively; and P,, and P. are the y-coordinates of points where b is I
and 0, respectively. As shown mathematically in (18) and (19), the LLR is a measure of
the likelihood that Gaussian noise moved the transmitted point from points where b I
versus from points where b, =0.
The probability
shown in (15).
Pr(RIu, =i,S,_, =m',S = m) can no longer be separated as
Instead, the observation point is now separated according to the part of
R, that represents systematic bits u, and the part that represents parity bits p,. Denote
the systematic part as R t and the parity part as RP. Using these two variables, the
analog to equation (15) is
Pr(R,|u, = i, S,1 = m', S, = m)= Pr(R;' u, = i, S,_1 = n', S = m)-Pr(RP|u, = i, S,_ = m', S, = m) .
Using the LLRs from (18) and (19), the probabilities in (20) are calculated as
Pr(R; |u, =i,S,4 =m',S, =in)= hle i bb)t ~b E 11 -- 6eL~i
(20)
(21)
and
Pr(RIu , =i,S, - = m',S, = m)= rHe b)L(b)biep E I+e~b )
for j b .2
(19)
(22)
BACKGROUND 35
36 CHAPTER TWO
The bits b in (21) correspond to u, and the bits in (22) correspond to the parity bits p,
for the trellis branch given by the condition. Equation (21) assumes mutual conditional
independence for the bits in u, , and thus, their individual probabilities are multiplied.
Equation (22) makes the same assumption for p,.
The received coordinates r, and r, in (15) can be analytically expressed as a
transmit value plus Gaussian noise. Further, it is certain that they are probabilistically
separable. In contrast, the parts R;' and R,' in (20) do not have a general analytical form.
The most we can say is that R,' is a function of LLRs in the set { L(bJ) b1 e u, } and
that R,' is a function of LLRs in the set t L(b,) b1 e p, }. Equation (20) assumes that
R;' and R, are conditionally independent even though they may not be [6]. Even so,
assuming independence greatly simplifies the calculations and does not noticeably
degrade decoding performance [6]. Thus, conditional independence is always assumed.
It has been noted [6] that the higher spectral efficiency modulation equations in
this section can be used for decoding 4-QAM modulation without much degradation in
performance. Thus, the equations in this section are used for decoding all types of
modulation.
2.8 The Turbo Code
It has been noted that code concatenation and interleaving can achieve lower error
probabilities [5]. The Turbo code uses both of these concepts.
BACKGROUND 37
2.8.1 The Turbo Encoder
The basic structure of the Turbo encoder is formed by a parallel concatenation of two
RSCCs. The input to one convolutional encoder is a sequence of information bits, and
the input to the second convolutional encoder is an interleaved sequence of those bits.
Then, in a process called puncturing, some of the parity bits from the two encoders are
selectively used while others are discarded. Puncturing allows the overall rate of the
Turbo code to be conveniently tailored.
In Figure 2-9 below, the outputs of the RSCC encoders show only the parity bits.
The two convolutional encoders are usually the same, although they do not need to be. If
the convolutional codes have rate-k/n, then u, represents k bits and p, represents (n-k)
bits.
U Lt
Lit :pit(
t= encoder 1 puncturingmechanism
intereaer Pt010101...
Ut , RCC 101010...encoder 2
Figure 2-9. Turbo encoder structure
The output bits of the Turbo encoder are mapped to a transmit symbol and sent
across the channel, as discussed in Section 2.7. Using the channel observations, bit LLRs
are calculated using equations (18) and (19). Before the parity bit LLRs are used by the
Turbo decoder, they first need to be un-punctured to reverse the puncturing process from
38 CHAPTER TWO
the Turbo encoder. During un-puncturing, a LLR = 0 is inserted in place of a punctured
bit. In the absence of any information about the punctured bit, it is equally likely to be a
zero or a one, producing a LLR of zero.
2.8.2 Iterative Decoding and the Turbo Decoder
The Turbo decoder consists of two MAP decoders, with each one used for decoding one
of the two convolutional codes in the Turbo encoder. The APP depends primarily on
calculating the y parameter, which is composed of the channel observation probability
Pr(R, I u, = i, S,_, = m', S, = M) and an a priori probability Pr(S, = m|S,_, = M') =
Pr(u, = i). From equations (21) and (22), we see that the channel observation probability
is calculated from bit LLRs. A LLR tell us two things about a bit - the sign indicates
whether the bit is zero or one, and the magnitude of the LLR indicates the degree of
certain that the sign is correct. A very negative LLR indicates high certainty that the bit
is zero, whereas a slightly positive LLR indicates low certainty that the bit is one. Thus,
the magnitude of a LLR is called the reliability of a bit decision.
The LLR is called soft data because it provides information for making a bit
decision and for determining the reliability that decision. The MAP decoder is called a
"soft-in soft-out" decoder because it uses soft data input and generates soft data output.
Expanding the y parameter in equation (9), the APP can also be written as
Pr( ut = i R = K,,,, Pr(R, u, = i).Pr(u, = i). (23)
Pr(R, I|u = i, S,_i = m', S, = m)Pr(u, = i|St, = m', S = m).a,, (m'),, (M)n] 112
BACKGROUND 39
The right side of equation (23) has three parts: the systematic channel observation
probability Pr(Rs u, = i) the a priori probability Pr(u, =i), and the last part called the
extrinsic information [2]:
E Pr(R' |u, = i,S,_1 = m', S, = m)Pr(ut = i|S,_1 = m', S, = im). at,(m')t (m)
Pr(ut =i RN
Pr(Rt I u, = i)- Pr(u, = i)
From the extrinsic information, we define the extrinsic probability P,- as
Pr(ut =i RN< =Kex Pr (RIu, = i) Pr(ut = i) (25)
The factor Kx, normalizes the sum of the extrinsic information across all i to unity.
The extrinsic probability is generated by the MAP decoder and is also soft data.
For a time t, the probabilities P,"C correspond to the values of u, =i, and the magnitude
of each P," indicates the certainty of that value of i. Thus, the extrinsic probability
provides soft information about u, = i and can be used as a priori information.
The Turbo decoder has two MAP decoders, and the extrinsic probability at the
output of each MAP decoder is used as the a priori probability in equation (23) in the
other MAP decoder. The point of the extrinsic information is to pass information to the
other MAP decoder that it does not already have. Notice that the extrinsic information
produced by each MAP decoder is a function of the parity bit information for that
decoder. As a result of the puncturing process, each MAP decoder does not possess the
parity bit information in the other decoder. Thus, the extrinsic information produced by
one decoder supplements the information in the other decoder. Further, equation (24)
shows that the systematic channel observation probability Pr(R, Iu, =i) and the a priori
Pr(u, = i) are not part of the extrinsic information. Both MAP decoders
already possess the systematic channel observation, and the a priori probability used in
one decoder is just the extrinsic probability generated by the other decoder. Thus,
Pr(RsIu, = i) and Pr(u, = i) are correctly excluded from the extrinsic information.
The entire process described above is called iterative decoding and is illustrated
below in Example 2-1.
Pr (u=i)
Pr (u'=i) t
P
LfL(L(u) : 0nee e
MAP decoder 1 MAP decoder 2
L(p 1) L(p2)
APP'
APPI
mFximum APPdecision
Figure 2-10. Turbo decoder structure
Example 2-1.
Iteration 1
Iterative decoding using extrinsic probabilities
* MAP decoderPr(u, =i)= 2 -k
I has no a priori input during the first iteration, so it uses
in equation (23) to calculate the APP and generates P eli using
equation (25), for all i = 0, ... , 2 k-' and t =1, ... ,r.
probability
40 CHAPTER TWO
MAP decoder 2 uses the time-interleaved sequence Pr(u,. = i)= P," in equation (23)to calculate the APPs:
Pr( ut, = i RN )= Pr(R u, = i)- P" .
IIPr(R~t'ut, = i, St,,_, = m', St,. = m)Prfut,. = i|S,_, = M', St,. = M)- a,.
MAP decoder 2 generates t,< using (25) for all i and t'.
interleaved sequence with respect to t.
Iteration 2 and beyond
Here, t' refers to an
- MAP decoder I uses the de-interleaved sequence Pr(u, = i)= Pt22 in equation (23) tocalculate the APPs:
Pr(u = i RN =Pr(R;| u,= t .
YJ Pr(R,u, =i,S_ =m',S,
MAP decoder I generates P,'' using (25) for all i and t.
MAP decoder 2 uses the time-interleaved sequence Pr(u,. =i)= P,<' in equation (23)to calculate the APPs:
Pr(u,. =i RN )=Pr(Ri Iu,. = i). Pti
Pr(RmtIu,. = i, S,._, = m', S,, = m)Pr(u, =|_, = m' , -I _ ',(M)
MAP decoder 2 generates p, 2 ,i using (25) for all i and t'. Here, t' refers to aninterleaved sequence with respect to t.
2.8.3 Fast Decoding of Rate-1/n Component Encoders
With minor modifications, we can reduce the amount of computation for MAP decoding
of rate-I/n convolutional codes. There is only one information bit, so k = I and there are
only two APPs. Define the quantity A to be the natural log of the ratio of the two APPs :
BACKGROUND 41
_ (M'),.t,(M)
m)Pr fu, = i|S,_1 = m', St = M). a,_] (M'),t(M)
42 CHAPTER TWO
Pr(u, =1 RN -N(m')y,1 (R,,m,m),(m)A(u )=ln In (26)
' Pru, =01 R, a,- (y 0(R,,Inm)'1 (mn)
Expanding the y parameters in (26) the same way as in (23), equation (26) becomes
A(u, )=L + L' + L
where
L' = In P u 1 =i) and L' =In Pr(u )Pr(R, u, =0) Pr(u, = 0)
Then, the extrinsic information L is calculated by
Et = A(u )-Lt - L' (27)
which is analogous to (25).
Using equation (26), the decoded bit corresponds to the sign of A rather than the
maximum APP. For the case of rate-1/2 RSCCs, using equation (27) instead of equation
(25) to generate extrinsic information results in faster decoding because the operations in
(27) are additive rather than multiplicative. Further, equation (25) generates two extrinsic
probabilities, one for each value of i, while equation (27) only generates one extrinsic
value.
Using these new quantities, the iterative decoding process for rate-1/2 component
codes is illustrated in Example 2-2.
BACKGROUND
Example 2-2. Iterative decoding with rate-k/n (k > 1) component RSCCs
Iteration 1
MAP decoder I has no a priori input during the first iteration,Pr(u, = i) =0.5 in the y terms in equation (26) and generates L, using equation (27),
for all t = l,..., r .
MAP decoder 2 uses the time-interleaved sequence K, to calculate the a priori
probabilities in the the y terms in equation (26) as follows:
Pr(u, = i) =I + e
MAP decoder 2 generates L, using (27) for all t'. Here, t' refers to an interleaved
sequence with respect to t.
Iteration 2 and beyond
- MAP decoder I uses the de-interleaved sequence Lt to calculate the a priori
probabilities in the the y terms in equation (26) as follows:e j2
Pr(u, = i) = ueLtM+ e '
MAP decoder I generates Lt using (27) for all t .
MAP decoder 2 uses the time-interleaved sequence L, to calculate the a priori
probabilities in the the y terms in equation (26) as follows:
Pr(u, =i)= eI+ e 4
MAP decoder 2 generates L using (27) for all t'. Here, t' refers to an interleaved
sequence with respect to t.
so it uses
43
CHAPTER THREE
THE SIMULATION TOOL
The purpose of the tool is to simulate Turbo codes described in the various ITU
contributions. The tool is designed for that specific purpose and will have certain
limitations that make it unsuitable for other applications. These limitations will become
apparent in the sections that follow.
3.1 Simulation Tool Scope
The main Turbo code contributions considered in designing the tool include ITU
documents CF-037 [15], CF-072 [17], RN-027 [20], RN-079 [18], and IC-024 [19]. The
Turbo encoder proposed in CF-037 is the standard structure in Figure 2-9, while other
companies have proposed the variations shown in Figures 3-1 through 3-3.
-45 -
46 CHAPTER THREE
interleaer 2 ?. U"t
Ut '' RSCencoder 1 puncturng
t = ... - -mechanism
t010101...
UF RS(r 32 101010 ...encoder2 I
Figure 3- 1. Turbo encoder from RN-027
Ut
Ut 4 RSCC tencoder 1 punctung
t mechanism
interleaver 11 100100 ... P t010010 ...
U t RS~C 001001 ...encoder 2
- intede;Der 2 n1c de 3S p3 t
Figure 3-2. Turbo encoder from CF-072
Ut interleaer 0 re-3A4 t
Figure 3-3. Turbo encoder from RN-079
The different Turbo encoder structures include parallel concatenations of more
than two RSCC encoders and also serial concatenation of RSCC encoders. The Turbo
decoder structures that correspond to the encoders in Figures 3-1 through 3-3 also differ
,
THE SIMULATION TOOL 47
from the standard structure in Figure 2-10; the differences are straightforward and are not
shown here. Aside from structural differences, the proposed Turbo codes also have
component differences; one Turbo code may work especially well with one type of
interleaver or RSCC encoder while other codes may use other types. Thus, the
simulation tool needs to accommodate both structural and component differences for
different Turbo codes.
3.2 Design Considerations for Structural Flexibility
The simulation platform is designed to be highly flexible, requiring minimal code
changes to simulate different Turbo code proposals. As mentioned in the previous
section, the design should account for structural flexibility and component flexibility.
Structural flexibility is addressed first in this section.
3.2.1 Simulation Tool Language
Figures 2-9, 3-1, 3-2, and 3-3 reveal that the Turbo code is composed of several
independent blocks connected via flow lines. To implement a Turbo code, we can simply
execute each block, or module, in order by following the direction of flow lines.
Although the modules operate independently, data in the form of bits or real values are
still passed between them. Thus, there is need for a system to define connections
between modules and to implement data transfer between them.
The needs of the system fit the description of object-oriented programming
(OOP). However, OOP requires the use of syntax not supported by the compilers
prevalent on most workstations. Thus, the simulation tool is implemented using regular
48 CHAPTER THREE
procedural programming in ANSI-C. Such an implementation still adheres to the design
goals above without any loss of flexibility. The only direct disadvantage of not using
OOP is slightly worse module abstraction and program structure, which does not affect
simulation performance.
3.2.2 Module Flow Implementation
Using ANSI-C, each module can be implemented as a struct, with flow connections
specified by input and output fields:
struct basic-module {
flow type* input;flow-type* output;
Code 1. Module template
Each module must have the input and output fields in code 1, and both fields must be of
the same variable type. This system guarantees that any two modules can be connected
together regardless of whether their connection might make sense at the present time.
Using this system, module flows can be specified by directly equating inputs and outputs:
encoderl.input = bitSource.output;
interleaver.input = bitSource.output;
encoder2.input = interleaver.output;
puncturer.inputl = encoderl.output;
puncturer.input2 = encoder2.output;
Code 2. Module flow connections
THE SIMULATION TOOL 49
The flow implementation in code 2 offers high structural flexibility because
modules are linked by simply defining input and output connections. Thus, modules can
be inserted or deleted with ease.
3.2.3 Data Transfer between Modules
Each module's input and output point to a specific memory location. By equating inputs
and outputs as shown in code 2, we are actually assigning the memory locations of the
input pointers. However, the memory locations of output pointers are not specified. The
flow connection implementation requires each module to allocate memory for its output
pointer internally, while input pointers are assigned externally. When a module places
data at the memory location specified by its output pointer, it is in effect transferring data
to the input of another module. Thus, each module can take data from its input pointer
and write resulting data to its output pointer without having to specifically communicate
with other modules. Simply executing the modules in order of flow direction will
transfer data through the encoder and decoder structures.
The next design issue is to determine how data is organized at each module's
input and output memory locations. Specifically, the generic flow-type designation in
code 1 needs to be replaced with an appropriate data structure type. Consider that data
transferred through the Turbo code is ordered with respect to time and that the actual
amount of data that is transferred can vary depending on the types of components in the
Turbo code. Thus, the data structure must be ordered and must allow data elements to be
easily added or deleted. The most appropriate structure for implementing these
requirements is a linked list.
50 CHAPTER THREE
head
n ext
-3. 1 01 004
tail
Figure 3-4. Linked list
A linked list is a chain of elements, with the first element called the head of the
list and the last element called the tail of the list. Each element contains a pointer to the
previous element in the list and a pointer to the next element in the list. The head has no
previous element and the tail has no next element. The next and previous pointers allow
the linked list to be ordered, and elements can be easily added to or deleted from the list
by changing those pointers. Each element also contains variables to hold data.
3.2.4 Module Execution
The previous sections have created a system for making directional connections between
modules and for transferring data between modules. The only task that remains is to
execute each module in the correct order and allow the data to automatically flow through
the Turbo code structure. The lines in code 3 perform Turbo encoding according to the
structure in Figure 2-9; the variables are the same as those used in code 2.
Each function accepts a struct and uses the variables in the struct to perform its
task. The function reads data from the module's input linked list, and resulting data is
placed in the output linked list. The order of the function calls correctly corresponds to
the flows in Figure 2-9 and to the connections made in code 2. While this ordering can
THE SIMULATION TOOL 51
be automated solely from the flow connections defined in code 2, doing so would likely
detract from the run-time efficiency of the tool. Further, the user can order the functions
quickly and easily, making the automation feature unnecessary.
generate bits(bitSource);doencode(encoderi);terminate(encoderi);
do interleave (interleaver);
doencode (encoder2);
do puncture(puncturer);
Code 3. Turbo encoding
3.3 Design Considerations for Component Flexibility
Section 3.2 created a framework for implementing structural flexibility and for module
execution. This section now addresses considerations for component flexibility.
Component flexibility is based on two factors: 1) the comprehensiveness of module
definitions, and 2) the amount of code changes necessary to create different types of the
same module. The aim is to maximize factor one while minimizing factor two.
Factor one depends on the variable definitions in a module struct. For the purpose
of this simulation tool, factor one can be sufficiently satisfied if the module is capable of
taking on the forms specified in the Turbo code proposals listed in Section 3.1. However,
when obvious extensions of those forms do not unreasonably complicate module
implementation, variable definitions are made intentionally broad to cover those'
extensions.
Factor two depends on module implementation and can rely in part on industry
standards. To minimize the amount of code changes, the user should only need to specify
numerical or string parameters for a module, and the module should create the data
52 CHAPTER THREE
structures it needs from those parameters. Thus, factor two is mainly concerned with
module initialization. The following sections will discuss design and implementation
considerations for all modules available in the simulation tool. Code for these modules
are shown in Appendix C.
3.3.1 Linked List Design and Implementation
The linked list can itself act as a module for generating bits, operating as a bit source.
The theory of a linked list as described in Section 3.2.3 is quite general, and the data
structure can be implemented in *a variety of ways. One simple implementation is to
create an array of elements and to keep track of the number of elements in the list. The
next and previous pointers of each element are implemented as integer values
corresponding to the array index of adjacent elements in the list. Although this
implementation is straightforward, there are two obvious drawbacks. The first is that we
must be sure to allocate enough array cells to hold the maximum possible number of
elements, and this number may not be available during module initialization. The second
drawback is that the list will not always hold the maximum number of elements, and
memory allocated for empty slots in the array is wasted. The use of dynamic memory
allocation and deallocation solves both of these concerns.
typedef struct linkListStructint valueLength;listElement *head, *tail;
struct linkListStruct *output;} linkList;
Code 4. Linked list definition
THE SIMULATION TOOL 53
Code 4 shows the linked list definition used by the simulation tool. During
module initialization, both the head and tail pointers are set to NULL. When the first
element is added to the linked list, memory for the new element is allocated and both the
head and tail point to the same element. As elements are added or deleted, memory for
those elements are allocated or de-allocated, respectively. Thus, there is no need to know
the memory requirements during module initialization, and memory is not wasted.
Each list element is designed to correspond to a specific time index. During a
time index, an element may need to store multiple bits or multiple signal points, so each
list element is designed to hold an array of bits and an array of two-dimensional Cartesian
coordinates. The lengths of the arrays are the same and are specified by the variable
valueLength in code 4. Thus, all elements of a linked list are implemented with the
same data array lengths.
Lastly, during module initialization, the output pointer is set to point back to the
linked list itself. The reason for this redundancy is simply to allow the linked list itself to
be used as an input for module connections, as shown in code 2.
3.3.2 Interleaver Design and Implementation
The interleaver function is relatively simple to implement. An interleaver takes a
sequence of elements and rearranges its order according to a permutation pattern, which
is implemented by a lookup table in the simulation. It is important to note, however, that
because of memory constraints in real-life systems, an actual interleaver implementation
would be algorithmic and would not be a lookup table.
54 CHAPTER THREE
Recall that each MAP decoding process works with a block of bits corresponding
to trellis branch transitions. The number of branch transitions is the same as the number
of time indices and depends on the rate of the convolutional code. Thus, the length of the
input sequence is the same as the number of time indices in a block of bits and depends
on parameters from other modules.
Unlike sequence length, the permutation pattern is unrelated to other module
parameters. However, initializing the variable is not completely straightforward. The
permute pattern is generated algorithmically during module initialization, and new
initialization functions need to be written for new algorithms. ITU proposal RN-029 [21]
describes a two-step semi-random algorithm for generating a permutation pattern, and the
algorithm has been implemented in this tool. Algorithms described in other proposals
[15] may use permutation matrices instead of a permutation pattern in array format. Even
so, the effect of the matrix is to rearrange the order of the input sequence, and that
operation can always be described by a permutation pattern [13]. Thus, some
permutation algorithms may need to be adapted to the array structure used in. the
interleaver module.
Variables for the interleaver module are shown below in code 5.
typedef struct interleaverVarsStructint blockSize;int* permutePattern;
linkList* input;
linkList* output;
interleaverVars;
Code 5. Interleaver module definition
THE SIMULATION TOOL 55
3.3.3 Convolutional Encoder Design and Implementation
Every convolutional encoder structure takes in some number k of input bits and generates
another number n > k of output bits. In doing so, the encoder stores v bits in memory
registers that are each a linear sum of past input and output bits. In a RSCC, k of the n
output bits are exact replicas of the input bits, and the other r = (n - k) are parity bits.
Thus, a RSCC has rate-k/(k+r).
3.3.3.1 Use of the Trellis Diagram for Encoding
Convolutional codes can have very different encoder structures, as shown in Figures 2-2
and 2-3. However, the similarity among all convolutional codes is that their behavior can
be mapped out in a trellis diagram, and the parameters k, r, and v, determine certain
characteristics of the diagram. A trellis diagram has 2' states, with 2k branches entering
each state and 2 branches exiting each state. Each branch corresponds to a unique k-bit
input and also to a r-bit parity number.
In real-life systems, a VLSI implementation of a convolutional encoder is easy
and fast, and allowing the encoder structure to be used for encoding. However, for the
simulation tool, using a trellis diagram to perform convolutional encoding is much more
efficient than using the encoder structure. A trellis branch can be calculated by using a k-
bit input with an encoder starting state and by recording the resulting state and parity bits.
Only 2 k* branch calculations are required to construct a trellis diagram. Then, to
perform encoding, we simply traverse the trellis by following the correct branches. In
contrast, using the encoder structure to perform encoding requires one branch calculation
56 CHAPTER THREE
per time index, and the number of time indices is greater than 2 k+ by several orders of
magnitude.
As shown in code 6, the trellis description is stored in a two-dimensional array.
The first dimension has 2' indices and corresponds to the encoder states. The second
dimension has 2k indices and corresponds to the branches exiting a state. Each branch
stores the starting and ending states, as well as input and parity bits.
typedef struct encoderVarsStructbranch** trellis;int* terminator;char* state;int k;
int r;int V;
linkList* input;linkList* output;
encoderVars;
Code 6. Convolutional encoder module definition
The one-dimensional array terminator describes the path from any state to the
zero state. The index of an array cell is the current state, and the content of the array cell
is the k-bit input corresponding to the next branch to take. The general rule for
terminating a convolutional code with v delay registers is that v input bits are required to
complete the termination. If the code has rate-k/(k+r), then those input bits correspond to
v/k branches. However, since k may not be a multiple of v, the simulation tool uses
-] -k bits to perform the termination.k
3.3.3.2 Generating Polynomials
As described in Section 2.6, the output bits of a convolutional encoder are formed from a
linear sum of current and past input and output bits. For k input bits uo ... Uk], v memory
registers, and r output bits yo ... Yr-I,
k-Iv
010 t (ti=0 j=0
(28)j) + b" y(t-j).i=0 J=I
a"i is the coefficient for calculating output bit y,, using input bit u with delay j.
Similarly, b"' is the coefficient for calculating output bit y,, using output bit y, with
delay j > 0. The binary coefficients a' and b"' determine the encoder connections
shown in Figures 2-2 and 2-3.
For a bit b, +b = -b. Thus, (28) can also be expressed as
r-I v k-I v
Y, (t)+ Y b|" yi(t - j)= a,"' ui(t - j)j.i=0 j=I i=0 j-0
Then, taking the D-transform of (29) and rearranging, we have
y,, (D 1 + JDj ) +0 Y(D (j=0
b7jDk-I
= ut(Di=0
The sequences a,'=ia'0 ... a'" and b"=( b'. .. bt"' are referred to as generating
polynomials because they determine the terms of the delay polynomials in (30) that
generate the output bits. For clarity, the sequences a,"I will be referred to as feed-forward
polynomials, and b"' will be referred to as feedback polynomials.
The convention for describing a convolutional code is to express the feed-forward
and feedback polynomials as octal numbers. The most significant bit (MSB) of the feed-
(29)
(30)a,"'JDJ- 0
THE SIMULATION TOOL 57
58 CHAPTER THREE
forward octal number is a", corresponding to no delay, and the least significant bit
(LSB) is a.", corresponding to highest delay. The feedback polynomial follows the same
delay order.
Using octal notation for the encoder in Figure 2-3, the feed-forward polynomials
for the parity bit are ao = 35 and ao = 278, and the feedback polynomial is bo = 318.
Following the connections for the encoder in Figure 2-2, the generating polynomials are
not immediately obvious. The output is not fed back, and the recursive connections seem
to make the feed-forward polynomial infinitely long even though there are only four
delay registers. In this case, the polynomials can be obtained by analysis:
So(D)= u (D)+ So(D)(D' + D4)
u (D)1+ D' + D4
pO(D)= S,(D)(1+ D + D2 + D4)
PO(D)= + (+D 4 (I+D+D2+D4)
pO(D)(+D'+ D4)=u,(D)(1+D+D2 +D4)
Thus, the feed-forward polynomial is ao = 35,, and the feedback polynomial is bo = 23
3.3.3.3 Constructing the Trellis Diagram
Although every convolutional code can be fully described by its generating polynomials,
implementing the codes can require very different encoder structures, i.e. the placement
of memory registers and bit adders, and the direction of feed-forward and feedback paths.
As an example, the convolutional codes of Figures 2-2 and 2-3 can both be
THE SIMULATION TOOL 59
mathematically described by their generating polynomials, shown in Section 3.3.3.2.
Even so, the encoder in Figure 2-2 is specifically designed for a rate-1/n RSCC, and the
encoder in Figure 2-3 is specifically designed for a rate-k/(k+1) RSCC. It is difficult to
imagine how the generating polynomials for the code in Figure 2-3 would be
implemented on the structure in Figure 2-2. Thus, constructing a trellis diagram requires
knowledge of the encoder structure in addition to the generating polynomials. In fact, it
is interesting to note that the structures in Figures 2-2 and 2-3 can both be used to
implement a rate- 1/2 RSCC and that the two implementations produce different trellises
for the same generating polynomials. This confirms that a trellis diagram depends on
knowledge of both the generating polynomials and the encoder structure.
When constructing the trellis, the simulation tool stores generating polynomials in
two separate variables. Feed-forward polynomials are stored in a three-dimensional
array. The content of each array cell is a coefficient a,', with the first array index
corresponding to output bit p,,, the second to input bit u,, and the third to delay j.
Feedback polynomials are stored in a one-dimensional array, with the array index
corresponding to delay j. The convolutional codes encountered thus far in the ITU Turbo
code proposals only generate one parity bit, so the simulation tool assumes that only one
feedback polynomial is needed. Consequently, only the rate-1/n and the rate-k/(k+1)
RSCC encoder structures in Figures 2-2 and 2-3, respectively, are implemented in the
tool. The rate-1/n structure is only used to implement rate-1/2 codes. The trellis diagram
for RSCCs can be constructed using those two structures, but new code must be written
to implement other types of encoder structures. Of course, the rate-1/n structure can be
60 CHAPTER THREE
used for n > 2, but the feedback array must be modified to hold more than one
polynomial.
3.3.4 Puncturing / Un-Puncturing Module Design and Implementation
The task of the puncturing module is to adjust the overall rate of a Turbo code by
selectively discarding parity bits according to a set pattern. Regardless of how many
linked lists are at the input of the puncturing module, there is only one output list. The
job of the un-puncturing module is to perform the reverse operation and to generate
multiple' outputs from one input list, also according to the same pattern. Thus, the
puncturing module and its counterpart have nearly identical definitions.
typedef struct punctureVarsStructint numInputs;int punctureLength;int currIndex;char** puncturePattern;
linkList** input;linkList* output;
punctureVars;
Code 7. Puncturing module definition
The pattern for each input list is stored in a one-dimensional array, and all of
those patterns are stored in another one-dimensional array. Thus, the patterns for all
inputs are stored in a two-dimensional array. The puncturing patterns are accessed
circularly, and the puncturing module will work for any number of input bits. In general,
though, the number of parity bits per input will be a multiple of the pattern length.
Where the puncturing module works with bits, the un-puncturing module works
with log-likelihood-ratios. When performing un-puncturing, a discarded bit is replaced
THE SIMULATION TOOL 61
with LLR = 0, indicating that the bit is equally likely to be zero or one. Since the
puncturing module will work for any number of input bits, the stop condition for un-
puncturing must make certain that the number of LLRs at each output of the un-
puncturing module is at least the number of parity bits at each input to the puncturing
module.
Consider the two puncturing patterns below:
Pattern 1 Pattern 2
index 0123 012345
input 1: 1010 010000input 2: 0101 000010
In pattern 1, the un-puncturing process can stop when no more LLRs remain at the input
to the un-puncturing module, which can occur at any index. However, the same
condition will not suffice for pattern 2. Suppose that the final LLR input is used at index
I in pattern 2. According to the pattern I stop condition, un-puncturing would end at
index 1. However, it is possible that the puncturing process actually ended at index 2 or
index 3, which would not produce any more parity bits beyond the final bit at index 1.
Thus, the un-puncturing process must not end at index 1. The problem is that the un-
puncturing module does not know whether to end at index 2 or index 3. It only knows
that un-puncturing must end before index 4, when another LLR input is required.
Without any more information, we must assume that having more LLRs than are actually
required is better than having less. Thus, the most appropriate stop condition to use when
performing un-puncturing is ending when the next pattern index requires an input LLR
and none remain.
62 CHAPTER THREE
typedef struct unPunctureVarsStruct
int numOutputs;
int punctureLength;
int currIndex;
char** puncturePattern;
linkList* input;
linkList* output;
unPunctureVars;
Code 8. Un-puncturing module definition
The only main tasks that need to be performed when initialization the puncturing
and un-puncturing modules are assigning the puncturing patterns to the two-dimensional
array puncturePattern and allocating the correct number of input and output linked
lists.
3.3.5 Signal Mapper Design and Implementation
A signal mapper has the task of assigning information bits and parity bits from a Turbo
encoder to points in a signal set. This task can be performed in two steps. The first step
takes the correct number of information and parity bits from the module's inputs and
orders those bit according to a set arrangement. The second step takes the arranged bits
and finds the signal point with a matching label. This process is described in Section 2.7.
The only information needed to perform the first step is the bit arrangement order,
which is specified during module initialization. The simulation tool assumes that if bits
generated from different time indices are grouped together, bits that are generated earlier
will be placed before bits that are generated later. Since the input information and parity
linked lists are already ordered with respect to time, taking the bits sequentially from
those lists automatically satisfies the ordering assumed by the tool. The arrangement
THE SIMULATION TOOL 63
order is stored in a one-dimensional array in which a 's' character specifies an
information bit and a 'p' character specifies a parity bit.
In step two, mapping the bit grouping from step one to a signal point is
straightforward and can be implemented using a lookup table. The lookup table consists
of an array of signal points and array of point labels, and the same indices in the two
arrays correspond to a point-label pair. The signal points and labels are generated during
module initialization. The simulation tool currently uses two-dimensional coordinates for
signal points, and new code must be written for other coordinate types. Further, the tool
has only implemented the square-QAM signal set, and normal and gray labeling. New
code needs to be written for other types of signal sets or labeling schemes.
The module definition is shown in code 9. The variable bitMapper holds the bit
arrangement order needed for step one, and the variable symbolMapper holds the signal
set and point labels needed for step two.
typedef struct twoDsignalMapVarsStructbitMapVars bitMapper;twoDsymbolMapVars symbolMapper;
linkList* inputU;linkList* inputS;linkList* inputP;linkList* output;
} twoDsignalMapVars;
Code 9. Signal mapper module definition
As shown in code 9, the signal mapper module is also designed to accommodate uncoded
bits. For the bit arrangement order stored in bitMapper, the character 'u' specifies an
uncoded bit. However, the simulation tool does not currently use uncoded bits.
64 CHAPTER THREE
3.3.6 Channel and Demodulator Design and Implementation
The channel model used by the simulation tool is the AWGN channel, which is described
2by noise variance O-N . As described in Section 2.4, the noise variance can be calculated
using equation (8), which is shown again below for convenience.
N = E,2q E'No
Es, the average energy per symbol, is stored in the symbolMapper variable of the signal
mapper module defined in Section 3.3.5, and 7, the number of information bits per
symbol, is stored in the bitMapper variable of the same module. E INO is defined in
the main simulation program.
typedef struct channelVarsStructdouble n variance;
linkL ist* input;linkList* output;
} channelvars;
Code 10. Channel module definition
The simulation tool has only implemented the AWGN channel, and new code needs to be
written for other types of channels.
The task of the demodulator module is to calculate bit LLRs from observations at
the output of the channel module. This process is described in Section 2.7.2, and LLR
equations are given in (18) and (19). In calculating bit LLRs, the demodulator module
uses information from the signal mapper module and from the channel module. This
information is not stored in the demodulator module itself and is passed in to the module
function. Although the use of external information in performing the module function
THE SIMULATION TOOL 65
violates module abstraction, making the information internal does not offer any added
benefits from a simulation perspective. Thus, the module was designed to use external
information, and its definition does not contain internal variables.
typedef struct demodulatorVarsStruct
linkList* input;linkList* outputS;linkList* outputP;
demodulatorvars;
Code 11. Demodulator module definition
Section 2.8.1 states that the decoding modules will always use bit LLRs to perform
decoding. Thus, the demodulator module will always output LLRs, and as the next
section will show, the MAP decoder module will always assume that its information and
parity input lists contain LLRs.
3.3.7 MAP Decoder Module Design and Implementation
The main tasks of the MAP decoder module are to produce the a posteriori probabilities
given in (9) and to generate extrinsic information for the iterative decoding process. The
MAP decoding algorithm is described in Section 2.6.3, and the extrinsic information is
shown in equations (25) and (27) in Section 2.8.2 and Section 2.8.3, respectively.
As shown in 2.6.3, producing the APPs requires calculating the a, fl, and y
parameters shown in equations (12), (13), and (14), respectively. Further, the y
parameter must be calculated first since the recursions in (12) and (13) depend on this
parameter. The parameters at (m) and ,(in) are state parameters and each is stored in a
two-dimensional array, with the first dimension in time t and the second in trellis state m.
66 CHAPTER THREE
The gamma parameter y (R,,m',m) is stored in a three-dimensional array, with first
dimension in time t, second dimension in information bits u, = i, and third dimension in
parity bits p, = j. The value of y depends only on the values of i and j for the
information bits and parity bits, respectively. Because the trellis structure from the
convolutional encoder is such an integral part of MAP decoding, the decoder module
stores its own trellis description.
The array bitValue is used in calculating the probability in equation (21) and
holds the individual bits corresponding to u, = i. The module definition is shown below.
typedef struct MAPdecoderVarsStruct {int blockSize, numStates, numInputs;
double explimit;
double ***gamma;double **alpha;double **beta;
char **bitValue;branch **trellis;
linkList* inputS;linkList* inputP;
linkList* inputA;
linkList* outputDprob;
linkList* output-extrinsic;
MAPdecoderVars;
Code 12. MAP decoder module definition
3.4 Simulation Code Organization
The simulation tool is composed of a collection main program files, C header files, and C
source files. Each module has a header file, which contains struct definitions and
function declarations, and a source file, which contains function code. Module source
files primarily include three types of functions - initialization functions, execution
THE SIMULATION TOOL 67
functions, and memory de-allocation functions. Each Turbo code structure is
implemented in a different main program file. Table 3.1 summarizes the different files.
Code for all files are included in Appendices A and C.
68 CHAPTER THREE
File name Descriptionturbosim-std.c main simulation file for double parallel concatenated Turbo code from CF-037
turbosim-icoding.c main simulation file for triple parallel concatenated Turbo code from CF-072
turbosim-uncoded.c main simulation file for uncoded simulation
File name Module Ifunction(s) Module initialization functionsgeneral.hgeneral.c general functions
linkedlist.hlinkedlist.c linked list llistInitVars( )
source.h bit generator module /source.c genBits() selectBlockSize()
Random pattern - randomPatterninitVars( )interleave.h interleaver module / Semi-random pattern - SrandomInitVars( )interleave.c doInterleave( ) Get pattern from a file - interleaverFileInitVars()
convolutional encoderconv.h module / Rate-1/2 - rate] 2initVars()conv.c encodeBlock() Rate-k/(k+l) - ratekk]InitVars()
terminateEncoder() Copy an encoder - duplicateEncoder()
puncture module / 2-input puncturer - twoPuncturelnitVars()puncture.h punctureBlock( ) 3-input puncturer - threePunctureInitVars()puncture.c unpuncture module /
unpunctureBlock() Un-puncturer - unPunctureInitVars()
Bit map pattern - bitMapInitVars( )mapper.h signal mapper module / QAM signal set - QAMSignalSet()mapper.c mapBlock() Normal bit labels - normalMappingInitVars()
Gray code labels - createGrayCode()
channel.h channel module /channel.c sendAWGNblock() channellnitVars()
demodulator module /demod.h demodulateTwoDBlock() demodulatorInitVars()demod.c decodeuncoded()
MAP decoder module Idecoder.h doMAPdecoding() MAPdecoderInitVars()decoder.c doFastRl2MAPdecoding()
Table 3.1. Summary of simulation files
68 CHAPTER THREE
CHAPTER FOUR
SIMULATION RESULTS
The files and modules shown in Table 3.1 form the entire simulation tool. The tool was
used to simulate the Turbo codes from CF-037 and CF-072, and results are compared to
those cited in these documents. Both simulation and cited results are shown in the
sections below.
Simulation results are gathered from running the tool on PCs with Microsoft
Visual C++ and on SUN workstations using the gcc compiler. As different compilers and
computers generate random numbers differently, the simulated results shown below may
not be reproducible in all environments. Even so, results should be similar and BER
curves should fall within the same order of magnitude.
All simulations used square-QAM signal sets with gray labels, which have been
shown to be ideal [8]. The coordinates of the QAM symbols are odd. The all zero label
- 69 -
corresponds to the most negative coordinate. The 4-QAM and 16-QAM signals sets are
shown below in Figures 4-1 and 4-2.
01.
-1
. -1 -00
11.
--
10
10
Figure 4-1. 4-QAM signal set
00100
01100 3
0011 01110 0
-3
0001
0000
Figure 4-2.
-1
0101
00100
-1
-3
1110 10100 0
1111
1S
1101
1100
16-QAM signal set with gray labels
4.1 Results for Double Parallel Concatenated Turbo Code
The encoder structure for the Turbo code in CF-037 is that of Figure 2-9. Both of the
RSCC encoders have rate-1/2, and the generator polynomials
ao = 35 and b =23,. The encoders are implemented using the structure in Figure 2-2.
1011S
3
1001
01000
component are
i ' | 1
70 CHAPTER FOUR
I
SIMULATION RESULTS 71
The simulations used the semi-random interleaver algorithm from [21], which is not same
interleaver specified by CF-037. Even so, it has been noted that interleavers of the same
length have approximately the same performance, so results should not differ much for
the two interleavers. The simulations only used square QAM signal sets. CF-037 is
based primarily on the initial proposal [15], which contains the majority of cited results.
4.1.1 Simulation 1: Rate-1/2 Turbo code
This simulation uses 1024 bits per block and generator polynomials ao = 35 and
b = 238. The signal set is square 4-QAM.
Information bit (u) u1 U2Parity bit (p) pParity bit (p2) P22
Bit mapping per symbol (bo , b1) = (u1 ,p (bo , b1 ) = (u2 , 2)
Table 4.1. Simulation I puncturing and mapping scheme
The values in Table 4.2 are approximations of graph points shown in [15].
Although the values are not exact, they are good guidelines of what the BERs should be.
IterationEWNo 1 2 3 4 8.
0.5 1.00E-01 1.00E-01 1.00E-01 1.00E-01 1.0E-011.0 8.OOE-02 5.OOE-02 2.50E-02 2.OOE-02 1.OOE-021.5 4.50E-02 8.OOE-03 1.00E-03 4.OOE-04 9.OOE-052.0 1.70E-02 2.50E-04 2.50E-06 8.OOE-07 1.1 OE-07
BER values fromTable 4.2. Approximate cited graphs for simulation I Turbo code
72 CHAPTER FOUR
The data in Table 4.3 shows simulated BER values over the same range as Table
4.2. To produce more accurate BER values, ten times more blocks were simulated for the
BERs in the lower part of Table 4.3 than for the upper part. After 8 iterations at
E /No =2.00 [dB], there were only 1.95E-07 - 1024E+05 ~ 20 bit errors. In the
extreme case that these 20 bit errors all occurred during the first 10,000 blocks, the BER
would have been one magnitude higher. Thus, simulating a higher number of blocks for
large Eb / No allows the BER to decrease after an error occurs. In order to produce a
reliable value for a BER in the order of 10-x, a general rule is to simulate 10,+2 bits. Not
all values in Table 4.3 adhere to this rule, however.
IterationEd/No 1 2 3 4 80.50 1.16E-01 1.04E-01 9.86E-02 9.47E-02 8.82E-020.75 1.00E-0 I 7.87E-02 6.52E-02 5.64E-02 4.47E-021.00 8.24E-02 4.93E-02 3.03E-02 2.15E-02 1.30E-021.25 6.38E-02 2.32E-02 8.50E-03 4.46E-03 1.86E-031.50 4.58E-02 7.54E-03 1.37E-03 5.1OE-04 1.55E-04
1.75 2.95E-02 1.58E-03 1.06E-04 2.11 E-05 3.78E-062.00 1.71 E-02 2.22E-04 5.77E-06 1.21 E-06 1.95E-07
Table 4.3. Simulated BER values for simulation I after 10,000 and 100,000 blocks
Cited results in Figure 4-3 and all subsequent plots are marked by square boxes
and dotted lines, while simulated results are marked by crosses and solid lines. BER
curves for 1, 2, 3, 4, and 8 iterations are shown. Figure 4-3 shows that simulated results
match cited results relatively well.
SIMULATION RESULTS 73
1.E+00 -
1.E-01 -
1.E-02 -
1.E-03 -
M1.E-04 -
1.E-05 -
1.E-06 -
1.E-07 -
0
___-_ _
- - - - -X
0.5 1 1.5
Eb/No
Figure 4-3. Simulation I BER curves for Table 4.2 and Table 4.3
4.1.2 Simulation 2: Rate-1/2 Turbo code
The ITU proposal in [20] suggests the use of a rate-1/2 convolutional encoder with
generator polynomials a~ =178 and b =58. This encoder is used in place of the one in
simulation 1 from Section 4.1.1. All other parameters from simulation 1 remain
unchanged.
Figure 4-4 shows that for the Turbo encoder structure from [15], using component
codes with polynomials a~ =35 and b =238 yields better BER performance than using
codes with polynomials ao = 178 and bo = 15.
2 2.5
SIMULATION RESULTS 73
74 CHAPTER FOUR
IterationsEb/No 1 2 3 4 80.50 1.02E-01 8.59E-02 7.92E-02 7.54E-02 6.91E-010.75 8.77E-02 6.43E-02 5.21E-02 4.47E-02 3.36E-021.00 7.28E-02 4.23E-02 2.63E-02 1.80E-02 9.95E-031.25 5.78E-02 2.33E-02 9.28E-03 4.63E-03 I .59E-031.50 4.38E-02 1.02E-02 2.14E-03 6.76E-04 1.12E-04
1.75 3.14E-02 3.62E-03 3.49E-04 6.99E-05 7.26E-062.00 2.11E-02 9.83E-04 3.85E-05 4.78E-06 1.12E-06
Table 4.4. Simulated BER values for simulation 2 after 10,000 and 100,000 blocks
1.E+00
w
1.E-01
1.E-02
1.E-03
1.E-04
1.E-05
1.E-06
1.E-07
"
0
0
0.5 1 1.5 2 2.5
Eb/No
Figure 4-4. Simulation 2 BER curves for Table 4.2 and Table 4.4
74 CHAPTER FOUR
SIMULATION RESULTS 75
4.1.3 Simulation 3: Rate-2/4 Turbo code
This simulation uses 1024 bits per block and generator polynomials a =35 and
b = 238. The signal set is square 16-QAM.
Information bit (u) u1 U2Parity bit (pI) pParity bit (p2) P2
Bit mapping per symbol (bo, b, , b2 , b3) = (up , p , u2 , p 2)
Table 4.5. Simulation 3 puncturing and mapping scheme
IterationsEg/NO 1 2 3 4 8
2.0 9.00E-02 9.00E-02 9.OOE-02 9.OOE-02 9.OOE-022.5 8.OOE-02 7.OOE-02 6.OOE-02 5.50E-02 5.00E-023.0 6.50E-02 3.00E-02 2.50E-02 2.20E-02 1.1OE-023.5 4.00E-02 9.00E-03 2.00E-03 9.00E-04 3.00E-044.0 2.00E-02 8.00E-04 5.OOE-05 2.00E-05 2.00E-064.5 6.00E-03 3.OOE-05 6.00E-07 3.OOE-07 9.00E-085.0 1.00E-03 1.00E-06 5.OOE-08 5.OOE-08 2.00E-08
Table 4.6. Approximate BER values from cited graphs for simulation 3 Turbo code
IterationsEdNo 1 2 3 4 8
2.0 9.34E-02 8.96E-02 8.89E-02 8.88E-02 8.86E-022.5 7.49E-02 6.38E-02 5.93E-02 5.67E-02 5.31E-023.0 5.34E-02 3.1OE-02 2.01E-02 1.51E-02 1.00E-023.5 3.16E-02 6.84E-03 1.77E-03 7.55E-04 2.63E-044.0 1.41E-02 5.23E-04 3.OOE-05 7.52E-06 2.25E-06
4.5 4.56E-03 2.04E-05 8.40E-07 6.05E-07 2.73E-075.0 1.07E-03 9.77E-07 1.27E-07 7.81E-08 4.88E-08
Table 4.7. Simulated BER values for simulation 3 after 10,000 and 100,000 blocks
76 CHAPTER FOUR
w
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
1.E-05
1.E-06
1.E-07
1.E-08
1.5 2 2.5 3 3.5 4 4.5 5 5.5
Eb/No
Figure 4-5. Simulation 3 BER curves for Table 4.6 and Table 4.7
Figure 4-5 shows that for BER above 1.E-07, simulated results match cited results
relatively closely. For lower BERs, the tool may not have simulated enough blocks, and
results do not match as well.
4.1.4 Simulation 4: Rate-2/4 Turbo code
This simulation uses a block size of 4096 bits with the Turbo code parameters of
simulation 3. The interleaver depth increases to 4096, which should improve the
performance of the Turbo code. The lack of a BER value for Eb /No = 3.5 [dB]
indicates that not enough blocks were simulated to generate error.
76 CHAPTER FOUR
SIMULATION RESULTS
IterationsEb/No 1 2 3 4 8
2.5 7.60E-02 6.56E-02 6.18E-02 6.01E-02 5.69E-023.0 5.45E-02 3.08E-02 8.52E-03 8.52E-03 1.50E-033.5 3.20E-02 4.85E-03 1.07E-05 1.07E-05
4.0 1.41E-02 1.59E-04 5.18E-07 5.86E-08 1.95E-08
Table 4.8. Simulated BER values for simulation 4 after 2,500 and 25,000 blocks
1.E+00
1.E-01
1.E-02
1.E-03
u1.E-04In
1.E-05
1.E-06
1.E-07
1.E-08
2 2.5 3 3.5 4 4.5
Eb/No
Figure 4-6. Simulation 4 BER curves for Table 4.6 and Table 4.8
Figure 4-6 shows that, as expected, using a longer interleaver improves the performance
of the Turbo code.
77
78 CHAPTER FOUR
4.1.5 Simulation 5: Rate-2/4 Turbo code
This simulation uses generator polynomials ao = 17, and b =15, with the Turbo code
parameters of simulation 3. The block size is 1024 bits.
IterationsE/No 1 2 3 4 8
2.0 8.62E-02 8.05E-02 7.96E-02 7.94E-02 7.93E-022.5 6.84E-02 5.68E-02 5.30E-02 5.13E-02 4.93E-023.0 4.95E-02 3.02E-02 2.18E-02 1.75E-02 1.29E-023.5 3.15E-02 9.84E-03 3.66E-03 1.88E-03 8.24E-044.0 1.68E-02 1.68E-03 2.26E-04 8.01E-05 1.91E-05
4.5 7.42E-03 1.66E-04 1.08E-05 5.00E-06 1.78E-065.0 2.56E-03 1.14E-05 6.48E-07 3.91E-07 1.95E-07
Table 4.9. Simulated BER values for simulation 5 after 10,000 and 100,000 blocks
As with simulation 2, Figure 4-7 shows again that for the Turbo encoder structure
from [15], using component codes with polynomials ao = 35 and bo =23 yields better
BER performance than using codes with polynomials ao = 17, and bo = 158.
SIMULATION RESULTS
1.E+00
1.E-01
1. E-02
1. E-03
w 1.E-04
1.E-05
1.E-06
1.E-07
1. E-08
1
1.5 2 2.5 3 3.5 4 4.5 5 5.5
Eb/No
Figure 4-7. Simulation 5 BER curves for Table 4.6 and Table 4.9
i i -- i
xI -
79
N-
%P I % Ne %
80 CHAPTER FOUR
4.1.6 Simulation 6: Rate-3/4 Turbo code
This simulation uses 6144 bits per block and generator polynomials a =35, and
bo = 23,. The signal set is square 16-QAM.
Information bit (u) u1 u2 u3 u4 U5 U6Parity bit (p') - P2 - -
Parity bit (p2) _ _ p25Bit mapping (bo ,b1 ,b2 ,b3) = (uI, u2 , u3 p 1p2) (bo ,b1 ,b2 ,b3) = (u4 , u5 , u6 , p 5)
Table 4.10. Simulation 6 puncturing and mapping scheme
IterationsEdNo 1 2 3 4 8
4.5 6.00E-02 6.00E-02 6.00E-02 6.OOE-02 6.OOE-025.0 4.00E-02 3.50E-02 2.50E-02 2.00E-02 1.50E-025.5 2.50E-02 7.OOE-03 9.OOE-04 1.1 OE-04 1.1 0E-076.0 9.OOE-03 2.00E-04 9.OOE-07 9.50E-08 -
Table 4.11. Approximate BER values from cited graphs for simulation 6 Turbo code
IterationsEWNo 1 2 3 4 84.50 5.49E-02 5.23E-02 5.19E-02 5.18E-02 5.18E-024.75 4.74E-02 4.24E-02 4.07E-02 3.98E-02 3.82E-025.00 3.94E-02 3.03E-02 2.49E-02 2.05E-02 1.19E-025.25 3.09E-02 1.70E-03 8.07E-03 3.34E-03 5.64E-045.50 2.25E-02 6.34E-03 8.46E-04 1.08E-04 3.9 1E-07
5.75 1.52E-02 1.45E-03 3.38E-05 8.40E-07 -
6.00 9.08E-03 1.89E-04 8.40E-07 1.56E-07 -
Table 4.12. Simulated BER values for simulation 6 after 1,666 AND 16,666 blocks
SIMULATION RESULTS 81
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
1.E-05
1.E-06
1.E-07
1.E-08
4 4.5 5 5.5 6 6.5Eb/No
Figure 4-8. Simulation 6 BER curves for Table 4.11 and Table 4.12
Aside from the lower BERs, Figure 4-8 shows that simulated results match cited results
relatively well.
4.1.7 Simulation 7: Rate-3/4 Turbo code
This simulation uses 6144 bits per block and rate-3/4
polynomials ao =118, a0 =158, a =178, and bg =138.
specified in [18] and is one of the encoders in Figure 3-3.
QAM.
convolutional encoders with
The rate-3/4 code is the one
The signal set is square 16-
M 01-
82 CHAPTER FOUR
Information bits (u) u1, u2 , u3 U4 , U5, U6
Parity bit (p1) p 1Parity bit (p2 ) P2Bit mapping (bo ,b1 ,b2 ,b3) = (u I, , u) Ip1 1) (bo ,b1 ,b2 ,b3 ) = (u4 , u5 , u6 , p 2)
Table 4.13. Simulation 7 puncturing and mapping scheme
IterationsEb/No 1 2 3 4 8
4.5 5.42E-02 5.07E-02 4.99E-02 4.96E-02 4.94E-025.0 3.84E-02 2.81E-02 2.16E-02 1.68E-02 8.15E-035.5 2.19E-02 6.31E-03 1.14E-03 2.79E-04 3.91E-036.0 9.12E-03 4.08E-04 7.70E-05 1.22E-04 9.89E-04
Simulated BER values for simulation 7 after 1,666 AND 16,666 blocks
The results in Table 4.14 are
puncturing pattern in 4.13, much fewer
Table 4.10. Intuitively, having more
improve the performance of the Turbo c
4.14 shows, performance is actually
monotonically decrease with increasing i
puzzling. Using a rate-3/4 encoder and the
parity bits are punctured than in the scheme in
parity bits, and thus more information, should
ode relative to simulation 6. However, as Table
much worse. Further, the BER does not
terations, which is odd.
Table 4.14.
SIMULATION RESULTS 83
4.1.8 Simulation 8: Rate-3/6 Turbo code
This simulation uses 6144 bits per block and generator polynomials a = 35 and
b = 23,. The signal set is square 64-QAM.
Information bit (u) u1 u 2 u3 u4 u5 U6Parity bit (p) p1 -p P5 -5Parity bit (p2) P 22 - P2 P 26Bit mapping (bo ,b1 ,b2 ,b3, b4, b5 ) = (bo ,b1 ,b2 ,b3, b4 , b5 ) =
(u], u 2 , p i, u3 , P22, p 3) (u4, u5 , p 24, u6 , p 5, P26)
Table 4.15. Simulation 8 puncturing and mapping scheme
IterationsEdNo 1 2 3 4 8
5.0 6.OOE-02 6.OOE-02 6.OOE-02 6.OOE-02 6.OOE-025.5 4.OOE-02 2.1OE-02 1.00E-02 5.50E-03 5.50E-046.0 2.1OE-02 3.OOE-03 1.1OE-04 2.OOE-06 3.OOE-076.5 1.00E-02 1.00E-04 6.OOE-07 -
Table 4.16. Approximate BER values from cited graphs for simulation 8 Turbo code
IterationsEWNo 1 2 3 4 85.00 6.51E-02 6.48E-02 5.08E-02 4.86E-02 4.46E-025.25 5.65E-02 4.09E-02 3.19E-02 2.52E-02 1.13E-025.50 4.75E-02 2.60E-02 1.27E-02 5.13E-03 3.59E-025.75 3.83E-02 1.30E-02 2.30E-03 2.75E-046.00 2.94E-02 4.70E-03 1.85E-04 1.27E-066.25 2.13E-02 1.18E-03 7.03E-06 -
6.50 1.44E-02 2.OOE-04 1.95E-07 -
Table 4.17. Simulated BER values for simulation 8 after 1,666 blocks
1.E+00 _-_---
1.E-01 -_-
1.E-02 -_ - - --_-
1.E-03 -
1.E-04
1.E-05 -
1 .E-06
1.E-074.75 5 5.25 5.5 5.75 6 6.25 6.5 6.75
Eb/No
Figure 4-9. Simulation 8 BER curves for Table 4.16 and Table 4.17
Figure 4-9 shows that cited results and simulated results match relatively well.
84 CHAPTER FOUR
SIMULATION RESULTS 85
4.1.9 Simulation 9: Rate-4/6 Turbo code
This simulation uses 4096 bits per block and generator polynomials ao = 35 and
bo = 238. The signal set is square 64-QAM.
Information bit (u) u1 u2 u3 U4Parity bit (p) p_Parity bit (p2Bit mapping (bo ,b ,b2 ,b3, b4, b5 ) = (ul, u2 , p 1, u3 , u4 , p 3)
Table 4.18. Simulation 9 puncturing and mapping scheme
IterationsEb/No 1 2 3 4 86.75 7.00E-02 6.00E-02 6.00E-02 5.00E-02 4.00E-027.00 6.00E-02 5.00E-02 4.00E-02 4.00E-02 3.00E-027.25 5.OOE-02 3.50E-02 2.20E-02 2.00E-02 1.70E-027.50 4.00E-02 2.70E-02 9.OOE-03 5.00E-03 1.70E-037.75 3.00E-02 1.00E-02 2.00E-03 5.00E-04 5.0E-058.00 2.GOE-02 3.O0E-03 3.OE-04 4.OOE-05 2.00E-068.25 1.00E-02 8.50E-04 2.50E-05 1.1 OE-06 2.GOE-07
Table 4.19. Approximate BER values from cited graphs for simulation 9 Turbo code
IterationsEb/No 1 2 3 4 86.75 5.08E-02 4.61E-02 4.50E-02 4.46E-02 4.43E-027.25 4.46E-02 3.73E-02 3.45E-02 3.29E-02 3.0IE-027.75 3.81E-02 2.72E-02 2.15E-02 1.75E-02 1.11E-028.00 3.13E-02 1.69E-02 8.90E-03 4.70E-03 1.19E-037.75 2.45E-02 8.26E-03 2.04E-03 4.77E-04 1.60E-058.00 1.83E-02 2.97E-03 2.43E-04 2.50E-05 2.34E-068.25 1.27E-02 7.55E-04 2.0GE-05 1.89E-06 5.86E-07
Table 4.20. Simulated BER values for simulation 9 after 2,500 blocks
86 CHAPTER FOUR
wUIn
1.E+00
1.E-01
1.E-02
1.E-03
1.E-04
1.E-05
1.E-06
1.E-07
6.5 6.75 7 7.25 7.5 7.75 8 8.25 8.5
Eb/No
Figure 4-10. Simulation 9 BER curves for Table 4.19 and Table 4.20
Figure 4-10 shows that simulated results and cited results match relatively well.
L+j
86 CHAPTER FOUR
SIMULATION RESULTS 87
4.1.10 Simulation 10: Rate-4/6 Turbo code
This simulation uses 4096 bits per block and a rate-2/3 convolutional encoder with
polynomials a = 35, a," =278, and be = 238. The rate-2/3 code is the one specified in
[18] and is one of the encoder in Figure 3-3. The signal set is square 64-QAM.
Information bit (u) u1, u2 u3 , u4
Parity bit (p') pI1Parity bit (p2) P 2 2Bit mapping (bo ,bI ,b2 ,b3, b4, b5 ) = (uI, u2 , P 1, u3 , u4 , p22)
Table 4.21. Simulation 10 puncturing and mapping scheme
IterationsEdNo 1 2 3 4 86.75 5.17E-02 4.76E-02 4.66E-02 4.63E-02 4.60E-027.25 3.89E-02 2.79E-02 2.14E-02 1.69E-02 9.90E-037.75 2.48E-02 7.35E-03 1.40E-03 2.77E-04 9.67E-068.00 1.82E-02 2.34E-03 1.19E-04 8.33E-06 2.64E-078.25 1.21E-02 4.37E-04 3.32E-06 1.95E-07 1.95E-07
Table 4.22. Simulated BER values for simulation 10 after 2,500 and 25,000 blocks
88 CHAPTER FOUR
1. E+00
1.E-01 -
1.E-02 -
1
ccLuM0
1.E-04
1.E-05
1. E-06
1.E-07
E-03 -
_______ 71f§_______
2I~<~I7T~
-Xi X~ '. 1 XK7~kL
-~ -- I -- V - r - i-
6.5 6.75 7 7.25 7.5 7.75 8 8.25 8.5
Eb/No
Figure 4-11. Simulation 10 BER curves for Table 4.19 and Table 4.22
The rate-2/3 convolutional code allows more parity bits to be retained than the scheme in
simulation 9, while maintaining an overall code rate of 4/6. Figure 4-11 shows that, as
expected, puncturing fewer parity bits results in better performance. This result matches
what is intuitively correct.
88
\ xi i r
CHAPTER FOUR
SIMULATION RESULTS 89
4.2 Results for Triple Parallel Concatenated Turbo Code
The encoder structure for the Turbo code in CF-072 is that of Figure 3-2. All
three component RSCC encoders have rate-1/2 and generator polynomials ao =7 and
b0 =5 The encoders are implemented using the structure in Figure 2-2. The
simulations used the semi-random interleaver algorithm from [21], which is equivalent to
the generatable interleaver used in CF-072 [17]. The simulations only use square QAM
signal sets.
4.2.1 Simulation 11: Rate-1/2 Turbo code
This simulation uses 15844 bits per block and square 4-QAM. Cited results for this
simulation indicate that a BER on the order of 10 -7 is achievable at Eb INO =1.6 [dB]
with four decoder iterations.
Information bit (u) u1 u2 U3Parity bit (p1) p1_Parity bit (p) 2
Parity bit (p ) -2 p 33Bit mapping (bo , b1 ) = (ui ,p 1) (bo , b1 ) = (u 2 p2) (bo , bi) = (u3, p 3)
Table 4.23. Simulation 11 puncturing and mapping scheme
IterationEb/No 1 2 3 4
0.5 1.20E-01 1.19E-01 1.19E-01 1.19E-011.0 9.62E-02 9.35E-02 9.34E-02 9.34E-021.5 7.12E-02 6.49E-02 6.40E-02 6.39E-022.0 4.64E-02 3.51E-02 3.20E-02 3.09E-022.5 2.54E-02 1.23E-02 8.37E-03 6.70E-033.0 1.1 3E-02 2.60E-03 1.03E-03 5.76E-043.5 4.OOE-03 3.69E-04 7.51E-05 2.39E-054.0 1.17E-03 3.22E-05 2.72E-06 1.36E-06
Table 4.24. Simulated BER values for simulation 11 after 650 blocks
As the tables above show, simulated results do not achieve a BER of 10-7 at E, /No = 1.6
[dB]. In fact, simulated results for this Turbo code are much worse than what is cited.
1.E+00
M
1.E-01
1.E-02
1.E-03
1.E-04
1.E-05
1.E-060 1 2 3 4 5
Eb/No
Figure 4-12. Simulation 11 BER curves for Table 4.24
X---- ifX.
90 CHAPTER FOUR
SIMULATION RESULTS 91
4.2.2 Simulation 12: Rate-1/2 Turbo code
In this simulation, the rate-1/2 convolutional encoder with generator polynomials ao = 7
and b = 5 is used in place of the one in simulation I from Section 4.1.1. The results of
this simulation will provide insight into the performance of the CF-072 component code
relative to the CF-037 component code. The block size is 6144 bits per block, and the
signal set is 4-QAM.
IterationsEJNo 1 2 3 4 8
0.5 1.02E-01 8.59E-02 7.92E-02 7.54E-02 6.91E-011.0 8.77E-02 6.43E-02 5.21E-02 4.47E-02 3.36E-021.5 7.28E-02 4.23E-02 2.63E-02 1.80E-02 9.95E-032.0 5.78E-02 2.33E-02 9.28E-03 4.63E-03 1.59E-032.5 4.38E-02 1.02E-02 2.14E-03 6.76E-04 1.12E-043.0 3.14E-02 3.62E-03 3.49E-04 6.99E-05 7.26E-063.5 2.11 E-02 9.83E-04 3.85E-05 4.78E-06 1.12E-06
Table 4.25. Simulated BER values for simulation 12 after 1,666 blocks
92 CHAPTER FOUR
1.E+00
1.E-01 -
2 2.5 3 3.5 41.5
Figure 4-13. Simulation 12
Eb/No
BER curves for Table 4.25
Figure 4-13 shows that the code with polynomials ao = 7 and bo = 5 performs much
worse than simulation 1, even with a much longer interleaver length. Further, the curves
do not exhibit sharply decreasing BERs. Thus, it is not surprising that simulation 11 did
not perform as well as simulation 1, even though cited results indicate it should.
4.3 Summary of Results
Simulations 1, 3, 6, 8, and 9, used the Turbo encoder structure from Figure 2-9 and the
exact parameters described in [15]. These simulation results matched cited results
relatively well. Simulations 2, 4, 5, 7, 10, used the same Turbo encoder structure but
different parameters. Of these five simulations, all but simulation 4 tested the
1%W-
cc 1.E-02 -
1.E-03
1.E-04
0 0.5 1
- Jfk V _________
1~
________ -7__________________ ______________ ________ ~1~~______________ ______________ - _____________ I _________ ___
______ ______ ______ -----H-
I. I
4.5
92 CHAPTER FOUR
SIMULATION RESULTS 93
performance of different component codes and corresponding puncturing patterns. These
results are summarized below in Table 4.26.
simulation structure details simulated results1 Fig. 2-9 rate-1/2 turbo code matcbed-BA-020RI results2 Fig. 2-9 used RN-027 RSCC and RN-027 RSCC performed
compared to simulation I worse than BA-020R13 Fig. 2-9 rate-2/4 turbo code matched BA-020R1 results4 Fig. 2-9 used longer interleaver and longer interleaver improved
compared to simulation 3 BER performance5 Fig. 2-9 used RN-027 RSCC and RN-027 RSCC performed
compared to simulation 3 worse than BA-02OR1I6 Fig. 2-9 rate-3/4 turbo code matched BA-020R1 results7 Fig. 2-9 used rate-3/4 RSCC and results do not match
compared to simulation 6 expectations and are odd8 Fig. 2-9 rate-3/6 turbo code matched BA-020R1 results9 Fig. 2-9 rate-4/6 turbo code matched BA-020R1 results10 Fig. 2-9 used rate-2/3 RSCC and less puncturing improved
compared to simulation 9 BER performance11 Fig. 3-2 compared to CF-072 results did not match citedrtesuls12 Fig. 2-9 used CF-072 RSCC and CF-072 RSCC performed
Scompared to simulation I worse than BA-020R1
Table 4.26. Summary of simulation results
CHAPTER FIVE
DISCUSSION
The simulation tool was used to evaluate two Turbo code structures: the encoders in
Figure 2-9 and Figure 3-2. Simulation results for those structures were compared to cited
results in [15] and [17], respectively, and only the results in [15] were reproduced. The
other ITU Turbo code proposals listed in section 3.1 were not detailed enough to
simulate. Even so, the twelve simulations shown in Chapter 4 are amply sufficient to
determine the reliability of the simulation tool. The following sections will discuss the
reliability of the simulation tool and will also analyze its performance in terms of
resource consumption.
5.1 Reliability of Simulation Tool
The main purpose of the simulation tool is to measure the performance of different Turbo
codes. The only way to simulate the true performance of a Turbo code using block size N
- 95 -
96 CHAPTER FIVE
is to send all 2 N possible blocks through the code. However, any practical value of N
would be too large to allow the simulation to finish. Thus, to simulate a BER of 10', a
general rule is to send ceil(lO x+2 IN) blocks through the code. A BER produced using
this rule can be considered a good estimate of the performance of the Turbo code.
Simulations 1, 3, 6, 8, and 9, used exact Turbo code parameters from [15] and
produced results that match cited performance curves relatively well. The cited results
were taken from [15], and it was fortunate that the proposal was described in sufficient
detail for simulation. The fact that these simulations were able to match cited results
indicates that Turbo code encoding and decoding algorithms were implemented correctly
in the tool. Simulations 4 and 10 provide further confidence that the tool is able to
produce correct results. The parameter changes in both simulations were meant to
improve BER performance over simulations 3 and 9, respectively, and results indicate
that they did. Thus, the tool was also able to produce uncited results that match intuitive
trends.
5.2 Unexpected Simulation Results
Simulations 7 and 11 produced unexpected results. Simulation 7 used a component
RSCC that had a higher rate than simulation 6, allowing for fewer parity bits to be
punctured. Although the simulation 7 RSCC is different from the simulation 6 RSCC, we
can still reasonably expect this change to improve BER performance over simulation 6.
As results show, not only was performance in simulation 7 worse than in simulation 6,
but the BER also increased at higher iterations. The BER increase at higher iterations is
unlikely a result of overflow errors because program code exists to limit the values of
DISCUSSION 97
MAP decoding parameters. It is possible that some property of the RSCC used in
simulation 7 caused extrinsic information to behave in a manner that diverges towards
greater errors. In contrast, a higher rate RSCC was used in simulation 10 to improve
BER performance over simulation 9, and the results produced in that trial did not exhibit
the abnormalities seen in simulation 7. Simulation 10 suggests that simulation tool
algorithms are indeed correctly implemented.
Simulation II results performed worse than cited results by more than 2 dB.
Simulation 12 used the same component RSCCs as in simulation 11, but on the Figure 2-
9 Turbo code structure. Results indicate that the RSCC used in simulation II yields
performance that is much worse than either of the RSCCs used in simulations I or 2.
Thus, the results generated by simulation 11 are not completely surprising. CF-072 [17]
did not provide complete details on all Turbo code parameters, and it is possible that
simulation I I was incorrectly configured.
5.3 Simulation Speed and Memory Usage
The simulation tool used double precision floating point variables to hold all real values.
Each double variable is 8 bytes. Table 5.1 below shows the approximate memory usage
for each type of module. The variable blockSize refers to the number of information bits
per block. When possible, variables from a module definition are used in the memory
usage equation.
98 CHAPTER FIVE
Module / Memory usage (bytes)data structure
one linked list LL( # of elements, valueLength)=16 + (# of elements) - ( 8 + 17 valueLength)
bit source For a rate-k/(k+1) RSCC: LL( (blockSize 1k), k)
interleaver 4 - ( (blockSize/k) + 2 ) + LL((blockSize/k), k)
convolutional Rate-k/(k+r) code, 2" statesencoder 16 + 5 -2v + 2 v+k+4 + LL(blockSize, r)
puncturer 12 + numInputs - (punctureLength + 4) + LL( # of elements, 1)
symbol mapper 40 + (M + 2) -(log 2M) + 8 -M + LL(# of symbols, 1)
channel 12 + LL(# of symbols, 1)
demodulator 2 -LL(blockSize, 1)
unpuncturer 16 + numOutputs - punctureLength + LL( # of elements, 1)numOutputs
MAP decoder 32 + k -2k + 8 - blockSize -2 k*v + 2 -LL(blockSize, 2 k)
main program 120 + (# of iterations) - LL(blockSize, 1)
Table 5.1. Simulation tool memory usage
Table 5.2 below shows the approximate simulation speed when using a rate-1/2
16-state RSCC, 1024 bits per block, and 8 decoder iterations.
System blocks / minDell Optiplex GX150, P111-1GHz, 512K memory 204Dell Optiplex GX100, PIII-800MHz, 256K memory 143SUN Sunblade 100 workstation 74SUN Ultra 5 workstation 60
Table 5.2. Simulation tool speed
CHAPTER SIX
CONCLUSION
In conclusion, simulation results indicate that the modular simulation tool described in
this thesis can be used with confidence to approximate the performance of Turbo codes
proposed for ADSL. The simulation tool modules are designed to accommodate a wide
range of parameters and should not need to be modified to simulate different Turbo
codes. However, it is likely that new initialization routines need to be written to correctly
configure modules for new Turbo code structures.
The computational power available in current computing systems allows the tool
to simulate BERs on the order of 10-7 in a reasonable amount of time. This BER is
sufficient for ADSL applications. Using the tool to simulate a BER on the order of 10-8
or smaller will require a much longer amount of time.
The main accomplishment of this thesis is the design of a flexible, modular
framework for simulating Turbo codes. The initialization and execution functions listed
-99 -
100 CHAPTER SIX
in Table 3.1 and shown in Appendix C were written to work within this framework.
They comprise only a small portion of possible Turbo code parameters. Barbelescu
describes a "simile" interleave [13] that terminates both component RSCC encoders,
which should improve the performance of the MAP decoder as compared to when one
encoder is left unterminated. The use of non-square-QAM constellations is discussed in
[8] and [16]. Le Goff shows in [8] that certain non-square-QAM constellations yield
better performance. A feature that has not been implemented is the Turbo Trellis-coded
modulation (TTCM) described in [12]. Various contributions have actually proposed
TTCM [18] [19] [20], although details in these proposals are vague. While the parameter
options and systems mentioned above are currently unavailable in the simulation tool,
they are supported by the comprehensive module definitions shown in Chapter 3. The
careful design described in Chapter 3 allows these new features to be implemented
without needing to alter module definitions.
Lastly, although the intent of this thesis is not to compare Turbo codes, simulation
results do indicate that of the different rate-1/2 RSCCs recommended in [14], [1.7], and
[20], the code from [14] with polynomials ao = 35, and b = 238 yields the best
performance.
APPENDIX A
Main Simulation Code
turbo sim-std.c
file: turbo_sim-std.c
This is the main program file that simulates turbo codes.
#include#include#include#include#include#include#include#include#include
"linkedlist.h""source.h""interleave.h"
"conv.h""puncture.h"
"mapper.h""channel.h""demod.h""decoder.h"
#include <math.h>#include <time.h>#include <stdio.h>#include <string.h>#include <stdlib.h>
int main(int argc, char* argv[})
== DECLARE GENERAL VARIABLES
/* general simulation variables */FILE* fp;
int sourceSeed;char filename[80];double EbOverNo, start, finish, delta;int blockSize;long num blocks;int iter;long total-bits;long* total-errors;int terminateBits;
int untermBits;
int numSymbols;
char *patl, *pat2;char *bitmap;
/* misc variables */timet starttime, curr time;float tl, t2, t3;int hrs, mins, secs;int i;int k;int selection;long block;long blocks-left, blocks-done;char error;double
/* charcharchar
temp;tempname[80]; */terminated;notTerminated;
file to write results */seed for random # gen */store file name */Eb/No simulation range */# of bits per block */# of blocks per Eb/No */
/* # of decoder iterationstotal bits per Eb/No */total decode errors per Eb/No */
# of bits to terminate trellis */blockSize - terminateBits */
# of symbols sent thru channel *//* puncture pattern *//* symbol bit mapping */
keeps track of time */scanf variables */printf: time variables */for loop index */selection variables */scanf: code structure */
for loop index */keeps track of progress */error indicator */temporary variable */
== DECLARE SIMULATION MODULES
101 -
/*
MAIN SIMULATION CODE
simulation modules */
* bit linked listslinkListlinkListlinkList*
* ENCODER modulesinterleaverVarsencoderVarsencoderVarspunctureVarstwoDsignalMapVars
*/origBitsLL;uncodedBitsLL;decodedBitsLL;
*/interleaverl;encoderl;encoder2;puncturer;mapper;
/* channel, soft-data modules */channelVars channel;demodulatorvars demodulator;unPunctureVars unpuncturer;
/* systematic buffer/* uncoded bits buffer/* decoded bits buffer
/* interleaver/* encoder 1/* encoder 2/* puncturer/* signal mapper
/* AWGN channel/* demodulator/* unpuncture LLR values
DECODER modulesMAPdecoderVarsMAPdecoderVarsinterleaverVarsinterleaverVarsinterleaverVarsinterleaverVars
MAPl;MAP2;extrinsicinterleaver;extrinsic deinterleaver;Sinterleaver;Dprobdeinterleaver;
MAP decoder 1 */MAP decoder 2 */extrins info interleaver */extrin. info deinterleaver */systematic bits interleaver*/a posteriori prob deinterleaver */
-= INIT GENERAL VARIABLES ==
- 1;= 0;= 171;
= 0;
== INITIALIZE SIMULATION MODULES -=
\n
printf("=printf("= TURBO-CODE SIMULATI
printf("printf("\n");printf("\n");printf(",--------------------------------------printf("\n");printf(" I
printf("I .---------- >------------->-
printf(" Iprintf("I information bits -- > encoderl
printf(" Iprintf('I interleaverl --> encoder2 --.printf(" Iprintf("I punctureprintf(" \n");
printf('----------------------------------------printf("\n");
/* output file name */printf(",--------------------------------------printf("I Enter output file name\n");printf("I >> ");
scanf("%s", filename);printf('--------------------------------------fp = fopen(filename, "a");if (fp == NULL)
printf("\n\nError opening file %s, programelse
fclose(fp);
ON ====\n")
------------------ \n");
s \n");>i \n");
g m \n");n a \n");
a p \n');
|1 p \n");|e \n") ;
r \n');
------------------ \n");
------------------ \n");
------------------ \n");
terminating\n", filename);
/* choices for modules: encoderl, encoder2, puncturer, mapper */
printf("\n\n");printf(",---------------printf("\n");printf(" Iprintf("ll conv codeprintf("' ---------printf(" 1 rate-1/2printf(" Iprintf("I \n");
printf("j 2 rate-1/2printf(" Iprintf("I \n");printf("I 3 rate-1/2printf(" Iprintf("I \n");printf("I 4 rate-3/4
--------------------------------------\n");
parity symbol overall \n");puncture bit map code rate\n");
------------ ---------- --------- \n');10 sp rate-1/2\n");01\n")
1001\n")
010000000010\n");
10
spsp rate-2/4\n");
sssp rate-3/4\n");
sssp rate-3/4\n");
102
terminated
notTerminatedsourceSeedblocks done
printf("I 01\n")printf("I \n");printf("I 0 see more selections...\n");printf("I \n");
printf("j---------------------------------------printf("1 Enter selection\n");
/* check for erroneous input */error = 1;while (error)
printf("I >> ");scanf("%d", &selection);if ((selection >= 0) && (selection <= 4)
error = 0;else
printf(" ** invalid selection **\n");
printf("-----if (selection == 0)
printf("\n\n");
printf(",------printf(" Iprintf(" J cprintf("I -printf("|I 5 rprintf("|printf("I \n")
printf(" [ 6 r
printf("|printf("I \n")printf("| 7 rprintf(" Iprintf("I \n")
printf("I 8 r
printf("|printf("| \n")printf("I 0 sprintf("I \n");
parityonv code puncture
ate-1/2
ate-1/2
ate-2/3
ate-1/2
ee more
- ------------ -1001\n");
10000010\n");
1001\n");
10001001000010010001\n");
selections...\n");
--------------------- \n".);symbol \n");bit map code rate\n");--------- --------- \n");
sspspp rate-3/6\n") ;
sspssp rate-4/6\n");
sspssp rate-4/6\n");
ssspsspp rate-5/8\n");
---------------------Enter selection\n");
/* check for erroneous input */while (error)
printf("I >> ");scanf("%d", &selection);if ((selection == 0) 11 ((selection
error = 0;else
if
>=5) && (selection <= 8)))
printf ("I ** invalid selection **\n");};printf("'---------------------- -----------------
(selection == 0)
printf("\n\n");printf(",-----------------------------------printf(" parityprintf(" conv code punctureprintf("| --------- ------------printf(" I 9 rate-3/4 10printf("I 01\n");printf("j \n");printf("1 10 rate-1/2 00100000printf("| 00000100\n");printf(I \n");printf("j 0 quit\n");printf(I \n");printf("I-----------------------------------printf ("I Enter selection\n");
/* check for erroneous input */error = 1;while (error)
--------------------- \n") ;symbol \n");bit map code rate\n");--------- --------- \n");-
ssspsssp rate-6/8\n");
sssspssssp rate-8/10\n");
printf ("I >> );scanf("%d", &selection);if ((selection == 0) 11 ((selection >=9) && (selection <= 10)))
error = 0;
elseprintf("| ** invalid selection **\n");
printf("'--------------------------------------------------------\n"printf("\n\n");
I;
/* set initialization variables based on selection from menu above */switch (selection)
case 1:k = 1;pati = "10";
turbo sim-std.c 103
printf("printf("Ierror = 1
--- \n");
n") ;
n") ;
104 MAIN SIMULATION CODE
pat2 = "01";bitmap = "sp";break;
case 2:k = 1;patl = "10";
pat2 = "01";bitmap = "spsp";break;
case 3:
k = 1;patl = "010000";
pat2 = "000010";
bitmap = "sssp";break;
case 4:k = 3;
patl = "10";pat2 = "01";bitmap = "sssp";break;
case 5:
k = 1;patl = "10";pat2 = "01";bitmap = "sspspp";break;
case 6:k = 1;pati = "1000";
pat2 = "0010";
bitmap = "sspssp";break;
case 7:
k = 2;
patl = "10";pat2 = "01";bitmap = "sspssp";break;
case 8:
k = 1;patl = "1000100100";
pat2 = "0010010001";
bitmap = "ssspsspp";break;
case 9:k = 3;patl = "10";pat2 = "01";bitmap = "ssspsssp";break;
case 10:k = 1;patl = "00100000";
pat2 = "00000100";
bitmap = "essspssssp";break;
}; /* switch */
Initialize encoders, puncture/unpuncture, signal mapper, interleavers */if (selection != 0)
printf("\n\n");
printf(",--------------------------------------------------------\n")printf("I MODULES: encoderl, encoder2\n");
selectEncoder(&encoderl, k);printf("'--------------------------------------------------------\n");
duplicateEncoder(&encoderl, &encoder2);
we need v bits to terminate, but if code is rate-k/k+1, then v must be
a multiple of k. so we round up v to the next higher multiple of k s/
terminateBits = (int)ceil(encoderl.v / encoderl.k) * encoderl.k;
twoPunctureInitVars(&puncturer, pati, pat2);
unPunctureInitVars(&unpuncturer, &puncturer);
bitMapInitVars(&mapper.bitMapper, bitmap);
printf("\n\n");printf( ",--------------------------------------------------------\n")printf("I MODULE: information bits\n");selectBlockSize(&blockSize, encoderi.k, mapper.bitMapper.numSys); /* select blockSize */
printf("------------------------------------ -------------------- \n");
untermBits = blockSize - terminateBits; /* initialize untermBits s/numSymbols = (int) (blockSize / mapper.bitMapper.numSys);
printf("\n\n");
printf(",--------------------------------------------------------\n");printf("| MODULE: interleaverl\n");
/* if encoder is rate k/(k+l) where k > 1, then we need to interleavegroups of k bits together. Thus, there will be only (blockSize / k)elements in the linked list to interleave s/selectInterleaver(&interleaverl, (int) (blockSize / encoderl.k));
printf("'--
uncomment the code below to write an interleave pattern to file forretreival later. Also uncomment tempname[] in variable section above */
printf("write pattern to file (y/n)?scanf("%s", temp name);
if (tempname[O] == 'y')
printf("enter output file name\n");printf("--> ");scanf ("%s", tempname);fp = fopen(tempname, "w");outputPattern(&interleaverl, fp)fclose(fp);
llistInitVars(&origBitsLL, encoderl.k)
llistInitVars(&uncodedBitsLL, 1);
printf("\n\n");printf(",----------------------------------printf("I MODULE: 2-D signal mapper\n");selectSignalMapper(&mapper);printf("'----------------------------------
channelInitVars(&channel);
demodulatorInitVars (&demodulator);
/* initialize Eb/No simulation range */printf("\n\n");
printf(",----------------------------------printf ("I ENTER:\n");printf("I \n");printf(" Eb/No to start simulation\n");printf(I >> ");scanf("%f", &tl);printf("J Eb/No to end simulation\n");printf("j >> ");scanf("%f", &t2);
printf(" I Eb/No step size\n");printf("I >> ");scanf("%f", &t3);printf("( \n");start = (double)tl;finish = (double)t2;delta = (double)t3;
printf ("I Number of blocks per Eb/No\n");printf ("I >> );scanf("%d", &num blocks);
/* initialize info bits */
/* initialize uncoded bits */
--------------------- \n");
/* initialize signal mapper */--------------------- \n");
/* initialize channel */
/* initialize demodulator */
/* number of blocks per Eb/No *
blocksleft = (long) (floor((finish - start) / delta) + 1) * numblocks;
/* initialize decoder parameters and decoder variables */printf(" 1 Number of decoder iterations per block\n")printf("l >> ");scanf ("%d", &iter); /* select # of decode iterations */printf("'---------------------------------------------------------\n")
deinterleaverInitVars(&extrinsicdeinterleaver, &interleaverl);deinterleaverInitVars(&Dprob_deinterleaver, &interleaverl);deinterleaverInitVars(&extrinsic interleaver, &extrinsic deinterleaver);deinterleaverInitVars(&Sinterleaver, &extrinsicdeinterleaver);
MAPdecoderInitVars(&MAP1, &encoderl, interleaverl.blockSize, &mapper. symbolMapper)MAPdecoderInitVars(&MAP2, &encoder2, interleaverl.blockSize, &mapper. symbolMapper);
totalerrors = (long*)calloc(iter, sizeof (long)); /* init total errors array */
decodedBitsLL = (linkList*)calloc(iter, sizeof(linkList))for (i=O; i < iter; i++)
llistInitVars(&decodedBitsLL[i], 1);
== DEFINE MODULE CONNECTIONS ==
/* ENCODER modules */encoderl.input =interleaverl.input=encoder2.input -
puncturer.input[0]=puncturer.input[1]=mapper.inputU =mapper.inputS -
mapper.inputP -
origBitsLL.output;origBitsLL.output;interleaverl.output;encoderl.output;encoder2.output;uncodedBitsLL.output;origBitsLL.output;puncturer.output;
/* channel, demodulator, unpuncturer */channel.input = mapper.output;demodulator.input = channel.output;
turbosim-std.c 105
-------------- \n".);
-------------------- \n"-);
MAIN SIMULATION CODE
unpuncturer.input = demodulator.outputP;
/* DECODER modules */MAPl.inputA = extrinsic_deinterleaver.output;MAPl.inputS = demodulator.outputS;MAPl.inputP = &unpuncturer.output[0];
Sinterleaver.input= demodulator.outputS;extrinsic interleaver.input = MAPi.output extrinsic;MAP2.inputA = extrinsic interleaver.output;
MAP2.inputS = Sinterleaver.output;MAP2.inputP = &unpuncturer.output[l];
extrinsicdeinterleaver.input = MAP2.output extrinsic;Dprobdeinterleaver.input = MAP2.outputDprob;
== BEGIN SIMULATION PROGRAM ==
time(&starttime);
for (EbOverNo = start; EbOverNo = finish; EbOverNo += delta) { /* this is in dB */
/* initialize bit and error counts to zero */for (i=0; i < iter; i++)
totalerrors[i] = 0;totalbits = 0;
/* calculate channel noise variance for current Eb/No and constellation C/
channel.n variance = mapper.symbolMapper.Eav / (2 * mapper.bitMapper.numSys * pow(10, (EbOverNo/10)));printf("Eb/No = %f, n-variance = %f\n", EbOverNo, channel.n variance);
/* initialize random # generator with same seed for each Eb/No to use same bit sequences C/
srand(sourceSeed);for (block = 0; block < num blocks; block++)
totalbits += blockSize;
genBits(&origBitsLL, untermBits); /* generate one block of bits C/
encodeslock(&encoderl); /* encoder original block */terminateEncoder(&encoderl);doInterleave(&interleaverl); /* do interleavingencodeBlock(&encoder2); /* encode interleaved block C/
punctureBlock(&puncturer); /* puncture parity bitsgenBits(&uncodedBitsLL, (mapper.bitMapper.numUncoded * numSymbols)); /* uncoded bits C/
/* regroup the systematic bits for use by the signal mapper */if (encoderl.k > 1)
regroupKtol(origBitsLL.output, encoderl.k);
mapBlock(&mapper); /* generate symbolssendAWGNblock(&channel); /* send through AWGN channel C/
demodulateTwoDBlock(&demodulator, &mapper, channel.n_variance) ; /* get LLRs */unpunctureBlock(&unpuncturer); /* unpuncture parity LLRs */if (encoderl.k > 1)
/* note: for some reason,bits = (int) (log((*decoder).numInputs) / log(2));
does not give the right number, butbits = (int) (loglO((*decoder).numInputs) / loglo(2));does.
regroupltoK(demodulator.outputS, (int) (loglO(MAPl.numInputs)/loglO(2)));
calcprobS(&MAPl);calcgamma(&MAPl);initprobA(&MAP1, 1);doInterleave(&Sinterleaver); /* only need to interleave L(dk) once */calcgamma(&MAP2);for (i=G; i < iter; i++)
initAB(&MAP1, terminated);
doMAPdecoding(&MAPl);doInterleave(&extrinsicinterleaver);initAB(&MAP2, notTerminated);doMAPdecoding(&MAP2);doInterleave(&extrinsicdeinterleaver);doInterleave(&Dprobdeinterleaver);probDecision(Dprobdeinterleaver.output, &decodedBitsLL[i]);
1;
regroup_Ktol (demodulator.outputS, (int) (loglO(MAPl.numInputs)/loglO(2)));
else
init_probA(&MAPl, 0);calcgammaRl2(&MAPl);doInterleave(&Sinterleaver);calcgammaRl2 (&MAP2);for (i=0; i < iter; i++)
initAB(&MAPl, terminated);
doFastRl2MAPdecoding(&MAPl);doInterleave(&extrinsicinterleaveinitAB(&MAP2, notTerminated);doFastRl2MAPdecoding(&MAP2);
only need to interleave L(dk) once */
106
turbosim-std.c 107
doInterleave(&extrinsicdeinterleaver);doInterleave(&Dprobdeinterleaver);signDecision(Dprob deinterleaver.output, &decodedBitsLL[i]);
};
/ calculate and display decoded bit errors */for (i=0; i < iter; i++)
totalerrors[i] += (long)floor(blockSize * showErrorPercentage(&origBitsLL,&decodedBitsLL[i]));
printf("Eb/No [dB] = %f, block %d / %d\n", EbOverNo, (block+l), num blocks);for (i=0; i < iter; i++)
printf ("iteration %d: %e\n", (i+1), ((double) total errors[ii / totalbits))printf ("\n");
/ regroup origBitsLL from 1 bit per element back to k bits per element */if (encoderl.k > 1)
regroupltoK(origBitsLL.output, encoderl.k);
/* find simulation time remaining */blocksdone++;blocksleft--;time(&curr time);
/* elapsedtime / blocksdone = remaining time / blocksleftremainingtime = elapsedtime / blocksdone blocksleft
*/temp = (double) (blocks left * difftime(currtime, start time)/3600 / blocksdone); /* hours
remaining */hrs = (int)floor(temp);
mins = (int)floor((temp - floor(temp)) * 60);temp *= 60; /* number of minutes remaining */secs = (int)ceil((temp - floor(temp)) * 60);
printf(" total time remaining: %dh %dm %ds\n\n", hrs, mins, secs);
}; /* for loop: blocks */
/* append results for completed Eb/No to the output file */fp = fopen(filename,"a");
fprintf(fp, "sourceSeed=%d\n", sourceSeed);fprintf(fp, "%d-QAM\n", mapper.symbolMapper.M);showTwoDmapping(&mapper.symbolMapper, fp);fprintf(fp, "\nbit map: );for (i=0; i < mapper.bitMapper.b; i++)
fprintf(fp, "%c", mapper.bitMapper.pattern[i]);fprintf(fp, "\nEav = %f\n", mapper.symbolMapper.Eav);fprintf(fp, "Eb/No = %f, nvariance = %f\n", EbOverNo, channel.n variance);fprintf(fp, "\nd bits -- Error probability:\n", totalbits);for (i=0; i < iter; i++)
fprintf(fp, "iteration %d: %e\n", (i+1), ((double)totalerrors[i] / totalbits));fprintf(fp, "\n");temp = (double) (difftime(curr time, start-time)/3600 / (blocks done/num blocks)); /* elapsed for this
Eb/No "hrs = (int)floor(temp);mins = (int)floor((temp - floor(temp)) * 60);temp *= 60; /* number of minutes remaining */secs = (int)ceil((temp - floor(temp)) * 60);printf("simulation time for %d blocks: %dh %dm %ds\n", num blocks, hrs,mins,secs);fprintf(fp, "simulation time for %d blocks: %dh %dm %ds\n\n\n", numblocks, hrs,mins,secs);
fclose(fp);
/* for loop: Eb/No range */
/* free all dynamically allocated variables */
deleteList(&origBitsLL); /* cannot use freeList because list not dynamically allocated */freeTwoDsignalMapVars(&mapper);freeChannelvars(&channel);freeDemodulatorVars(&demodulator);freeEncoderVars(&encoderl);freelnterleaverVars(&interleaverl);freeEncoderVars(&encoder2);freePunctureVars(&puncturer);deleteList(&uncodedBitsLL);
freeUnpunctureVars(&unpuncturer); */ /* causes problems, don't use yet */freeMAPDecoderVars(&MAPl);freeMAPDecoderVars(&MAP2);freeInterleaverVars (&extrinsic_interleaver)freelnterleaverVars(&extrinsic deinterleaver);freeInterleaverVars(&Sinterleaver);freeInterleaverVars(&Dprob_deinterleaver);for (i=0; i < iter; i++)
deleteList(&decodedBitsLL[i);free(decodedBitsLL);
}; /* if selection != 0 */}; /* error opening file */return 0;
/* main */
108 MAIN SIMULATION CODE
turbo sim-icoding.c
file: turbo sim-icoding.c
This is the main program file that simulates turbo codes proposedby ICoding. ICoding only proposes to use rate-l/2 constituentcodes, and full coding of every bit.
*/
#include "StdAfx.h"#include "linkedlist.h"#include "source.h"#include "interleave.h"#include "conv.h"#include "puncture.h"#include "mapper.h"#include "channel.h"#include "demod.h"#include "decoder.h"
#include <math.h>#include <time.h>#include <stdio.h>#include <string.h>#include <stdlib.h>
int main(int argc, char* argv[])
== DECLARE GENERAL VARIABLES ===== == == == == == === == == == == *
/* general simulation variables */FILE* fp;
int sourceSeed;char filename[80;double EbOverNo, start, finish, delta;int blockSize;long numblocks;int iter;long total_bits;long* total_errors;int terminateBits;int untermBits;int numSymbols;char *patl, *pat2, *pat3;char *bitmap;
/* misc variables *timet starttime, currtime;float tl, t2, t3;int hrs, mins, secs;int i;int k;int selection;long block;long blocks_left, blocks_done;char error;double temp;
/* char temp_name[80]; *char terminated;char notTerminated;
file to write results Vseed for random # gen Vstore file name *Eb/No simulation range *# of bits per block *# of blocks per Eb/No *
/* # of decoder iterationstotal bits per Eb/No *total decode errors per Eb/No *
# of bits to terminate trellis *blockSize - terminateBits *
# of symbols sent thru channel */* puncture pattern */* symbol bit mapping /
keeps track of timescanf variablesprintf: time variablesfor loop indexselection variablesscanf: code structurefor loop indexkeeps track of progresserror indicatortemporary variable
VVVVVV
VV
== CREATE SIMULATION MODULES ==
/* simulation modules /
/* bit linked lists *linkList origBitsLL;linkList* decodedBitsLL;
/* ENCODER modules *interleaverVars interleaverl;interleaverVars interleaver2;encoderVars encoderl;encoderVars encoder2;encoderVars encoder3;punctureVars puncturer;
/* systematic buffer/* decoded bits buffer
/* interleaver 1/* interleaver 2/* encoder 1/* encoder 2/* encoder 3/* puncturer
turbosim-icoding.c
twoDsignalMapVars mapper;
channel, soft-data modules */channelVars channel;
demodulatorVars demodulator;unPunctureVars unpuncturer;
DECODER modulesMAPdecoderVarsMAPdecoderVarsMAPdecoderVarsinterleaverVarsinterleaverVars
interleaverVars
interleaverVars
interleaverVars
interleaverVarsinterleaverVars
MAPl;MAP2;MAP3;extrinsic-interleaverl;extrinsic-interleaver2;extrinsicdeinterleaverl;extrinsic deinterleaver2;
Sinterleaverl;Sinterleaver2;Dprob deinterleaver;
/* signal mapper */
/* AWGN channel '/* demodulator '//* unpuncture LLR values */
/* MAP decoder 1 *//* MAP decoder 2 '//* MAP decoder 3/* extrins info interleaver 1 *//* extrins info interleaver 2 *//* extrin. info deinterleaver 1*//* extrin. info deinterleaver 2*//* systematic bits interleaver 1*//* systematic bits interleaver 2*//* a posteriori prob deinterleaver
INIT GENERAL VARIABLES
1;0;171;
0;
= INITIALIZE SIMULATION MODULES ==
printf(I"
printf(printf(" === == ==
printf("\n")printf("\n");printf(",-----------------printf (" \n")printf("
printf("| .-------printf("I Iprintf(" I information bits
printf("|l I Iprintf(I" I interleaverlprintf("i" Iprintf(i)" interleaver2 ---printf(I"
printf(" Iprintf("I\n");printf( "-----------------printf ("\n");
output file name */printf(", ----------------------printf(i" Enter output file naprintf("| >> );scanf("%s", filename);printf("'----------------------fp = fopen(filename, "a");if (fp == NULL)
printf("\n\nError openingelse
fclose(fp);
TURBO-CODE SIMULATION
> encoderl
encoder2 --. |
> encoder3 --. I I
puncture
file %s, program terminating\n", filename);
/* choices for modules: encoderl, encoder2, puncturer, mapper
printf("\n\n");printf(",----------------------printf("I\n");
printf("I pprintf("I conv code pprintf("I --------- ---printf("I 1 rate-1/2 1printf("I 0printf("I 0printf("l \n");printf("I 2 rate-1/2 1printf("I 0printf("I 0printf("I \n");printf("I 3 rate-1/2 0printf("I 0printf("I 0printf("! \n");printf(" o see more selectiprintf("I \n");
printf(i"----------------------printf("I Enter selection\n");
----------------------------------- \n");
arity symbol overall \n");uncture bit map code rate\n");--------- ---------- --------- \n") ;00 sp rate-1/2\n");10\n");01\n");
0010\n")01\n")
1000000000010000\n");00000010\n");
ons ... \n");
spsp rate-2/4\n");
sqsp rate-3/4\n");
109
terminated
notTerminated
sourceSeedblocksdone
= = \n")
a \n");i \n");
g \n");n \n");
.-> a m \n");
1 a \n");p \n");p \n");
e \n");r \n");
---------- \n");
MAIN SIMULATION CODE
/* check for erroneous input */error = 1;while (error)
printf(" >>scanf("%d", &selection);if ((selection >= 0) && (selection <:
error = 0;else
3))
printf("| ** invalid selection **\n");};printf("'-------------------------------------if (selection == 0)
printf ("\n\n");printf(",---------------------------------printf("j parityprintf(" I conv code punctureprintf("I --------- ------------
printf(" l \n");printf("Ul 0 quit\n");printf("| \n");printf("j--------------------------------
printf("| Enter selection\n");
/* check for erroneous input */error = 1;while (error)
printf("I >>scanf("%d", &selection);if ((selection == 0) 11 ((selection
error = 0;else
---------- \n");
---------------------- \n");
symbol \n");bit map code rate\n");
---------- --------- \n");
>=0) && (selection <= 0)))
printf(" ** invalid selection **\n");1;printf("'---------------------------------------printf ("\n\n")
};
switch (selection)
case 1:k = 1;patl =
pat2 =pat3 =bitmapbreak;
case 2:k = 1;patl =
pat2 =pat3 =bitmapbreak;
case 3:
"100";"010";
"001";
= "sp";
"100";
"010";
"001";
= "spsp";
k = 1;patl = "010000000";pat2 = "000010000";
pat3 = "000000010";
bitmap = "sssp";break;
}; /* switch */
/* Initialize encoders, puncture/unpuncture,if (selection != 0)
signal mapper, interleavers */
printf("\n\n");printf(",--------------------------------------------------------\n");
printf(" I MODULES: encoderl, encoder2, encoder3\n");selectEncoder(&encoderl, k);printf("------------------------------------ -------------------- \n");
duplicateEncoder(&encoderl, &encoder2);duplicateEncoder(&encoderl, &encoder3);
we need v bits to terminate, but if code is rate-k/k+l, then v must bea multiple of k. so we round up v to the next higher multiple of k */terminateBits = (int)ceil(encoderl.v / encoderl.k) * encoderl.k;
threePunctureInitVars(&puncturer, patl, pat2, pat3);
unPunctureInitVars(&unpuncturer, &puncturer);
bitMapInitVars(&mapper.bitMapper, bitmap);
printf ("\n\n") ;printf(",---------------------------------------------------------\n");printf("I MODULE: information bits\n");selectBlockSize(&blockSize, encoderl.k, mapper.bitMapper.numSys); /* select blockSizeprintf("'---------------------------------------------------------\n");untermBits = blockSize - terminateBits; /* initialize untermBits s/numSymbols = (int) (blockSize / mapper-bitMapper.numSys);
110
----------- \n");
turbosim-icoding.c 111
printf("\n\n");printf(" --------------------------------------------------------- \n");printf("I MODULE: interleaverl\n");
if encoder is rate k/(k+) where k > 1, then we need to interleavegroups of k bits together. Thus, there will be only (blockSize / k)elements in the linked list to interleave */
selectInterleaver(&interleaverl, (int) (blockSize / encoderl.k)printf(" --------------------- \n");
printf ("\n\n");printf(",-----------------------------------------------------------\n");printf("I MODULE: interleaver2\n");
/* if encoder is rate k/(k+l) where k > 1, then we need to interleavegroups of k bits together. Thus, there will be only (blockSize / k)elements in the linked list to interleave */selectInterleaver(&interleaver2, (int) (blockSize / encoderi.k)printf("'-----------------------------------------------------------\n");
uncomment the code below to write an interleave pattern to file forretreival later. Also uncomment tempname[] in variable section above *
printf("write pattern to file (y/n)?scanf("%s", temp name);if (tempname[O] == 'y')
printf ("enter output file name\n");printf("--> ");scanf("%s", tempname);fp = fopen(tempname, "w");outputPattern(&interleaverl, fp);fclose(fp);
*/
llistInitVars(&origBitsLL, encoderl.k); /* initialize info bits /
printf("\n\n");printf(",---------------------------------------------------- \n")printf("I MODULE: 2-D signal mapper\n");selectSignalMapper(&mapper); /* initialize signal mapper */printf("'--------------------------------------------------------\n");
channelInitVars(&channel); /* initialize channel *
demodulatorInitVars(&demodulator); /* initialize demodulator /
/* initialize Eb/No simulation range /printf("\n\n");printf(", --------------------------------------------------------- \n");printf("I ENTER:\n");printf("I \n");printf ("I Eb/No to start simulation\n");printf("I >> ");scanf("%f", &tl);printf("I Eb/No to end simulation\n");printf("[ >> );scanf("%f", &t2);printf("I Eb/No step size\n");printf("I >> ");scanf("%f", &t3);printf("I \n");start = (double)tl;finish = (double)t2;
delta = (double)t3;
printf("I Number of blocks per Eb/No\n");printf("j >> );scanf("%d", &numhblocks); /* number of blocks per Eb/No *
blocksleft = (long) (floor((finish - start) / delta) + 1) * numblocks;
/* initialize decoder parameters and decoder variables */printf ("I Number of decoder iterations per block\n")printf("j >> );scanf("%d", &iter); /* select # of decode iterations */printf("----------------------------------- ---------------------
deinterleaverInitVars(&extrinsic deinterleaverl, &interleaverl);deinterleaverInitVars(&extrinsicdeinterleaver2, &interleaver2);deinterleaverInitVars(&Dprobdeinterleaver, &interleaver2);deinterleaverInitVars(&extrinsic interleaverl, &extrinsicdeinterleaverl);deinterleaverInitVars(&extrinsicinterleaver2, &extrinsicdeinterleaver2);deinterleaverInitVars(&Sinterleaverl, &extrinsic_deinterleaverl);deinterleaverInitVars(&Sinterleaver2, &extrinsicdeinterleaver2);
MAPdecoderInitVars(&MAP2, &encoderl, interleaverl.blockSize, &mapper.symbolMapper);MAPdecoderInitVars(&MAP2, &encoder2, interleaverl.blockSize, &mapper.symbolMapper);MAPdecoderInitVars(&MAP3, &encoder3, interleaverl.blockSize, &mapper.symbolMapper);
total-errors = (long*)calloc(iter, sizeof(long)); /* init total-errors array */
decodedBitsLL = (linkList*)calloc(iter, sizeof(linkList));for (i=l; i < iter; i++)
llistInitVars(&decodedBitsLL[i}, 1);
MAIN SIMULATION CODE
= DEFINE MODULE CONNECTIONS ==
*--- --- REGULAR TURBO CODE
/* ENCODER modules */encoderl.input =interleaveri.input=encoder2.input =interleaver2.input=encoder3.input =puncturer.input[0] =puncturer.input[11]=puncturer.input[2]=mapper.inputS =mapper.inputP =
origBitsLL.output;origBitsLL.output;interleaverl.output;origBitsLL.output;interleaver2.output;encoderl.output;encoder2.output;encoder3.output;origBitsLL.output;puncturer.output;
/* channel, demodulator, unpuncturer */channel.input = mapper.output;demodulator.input = channel.output;unpuncturer.input = demodulator.outputP;
/* DECODER modules */MAPl.inputA = extrinsic deinterleaver2.output;MAPl.inputS = demodulator.outputS;MAPl.inputP = &unpuncturer.output[0];Sinterleaverl.input= demodulator.outputS;extrinsicinterleaverl.input = MAPI.output extrinsic;MAP2.inputA = extrinsic interleaverl.output;MAP2.inputS = Sinterleaverl.output;MAP2.inputP = &unpuncturer.output[l];Sinterleaver2.input= demodulator.outputS;extrinsic deinterleaverl.input = MAP2.output extrinsic;extrinsic interleaver2.input = extrinsic-deinterleaverl.output;MAP3.inputA = extrinsic-interleaver2output;MAP3.inputS = Sinterleaver2.output;MAP3.inputP = &unpuncturer.output[2];extrinsic deinterleaver2.input = MAP3.output extrinsic;Dprob_deinterleaver.input = MAP3.output Dprob;
/*
== BEGIN SIMULATION PROGRAM ==
time(&start time);for (EbOverNo = start; EbOverNo <= finish; EbOverNo += delta) { /* this is in dB */
/* initialize bit and error counts to zero '/for (i=O; i < iter; i++)
totalerrors[i] = 0;totalbits = 0;
/* calculate channel noise variance for current Eb/No and constellation */channel.n variance = mapper.symbolMapper.Eav / (2 * mapper.bitMapper.numSys * pow(10, (EbOverNo/10)));printf("Eb/No = %f, n-variance = %f\n", EbOverNo, channel.n_variance);
/* initialize random # generator with same seed for each Eb/No to use same bit sequences */srand(sourceSeed);for (block = 0; block < numblocks; block++)
total bits += blockSize;
genBits(&origBitsLL, untermBits);encodeBlock(&encoderl);terminateEncoder(&encoderl);doInterleave(&interleaverl);encodeBlock(&encoder2);doInterleave(&interleaver2);encodeBlock(&encoder3);punctureBlock(&puncturer);
/* generate one block of bits *//* encoder original block */
/* do interleaving *//* encode interleaved block *//* do interleaving *//* encode interleaved block *//* puncture parity bits */
mapBlock(&mapper); /* generate symbolssendAWGNblock(&channel); /* send through AWGN channeldemodulateTwoDBlock(&demodulator, &mapper, channel.n variance); /* getunpunctureBlock(&unpuncturer); /* unpuncture parity LLRs
*/LLRs */
/* all constituent codes are rate-1/2, so use fast-ratel2 decoding functions */initprobA(&MAPl, 0);calc gammaR12(&MAP1);doInterleave(&Sinterleaverl); /* only need to interleave L(dk) once */calc gammaR12(&MAP2);doInterleave(&Sinterleaver2); /* only need to interleave L(dk) once */calc gammaR12(&MAP3);for (i=O; i < iter; i++) {
initAB(&MAP1, terminated);
doFastRl2MAPdecoding(&MAPl);doInterleave(&extrinsicinterleaverl);initAB(&MAP2, notTerminated);
doFastRl2MAPdecoding(&MAP2);
doInterleave(&extrinsic deinterleaverl);doInterleave(&extrinsic interleaver2);
112
turbosim-icoding.c 113
initAB(&MAP3, notTerminated);doFastRl2MAPdecoding(&MAP3);doInterleave(&extrinsic_deinterleaver2);doInterleave(&Dprob_deinterleaver);signDecision(Dprob_deinterleaver.output, &decodedBitsLL[i]);
};
/* calculate and display decoded bit errorsfor (i=0; i < iter; i++)
totalerrorsi] += (long)floor(blockSize * showErrorPercentage(&origBitsLL,&decodedBitsLL[i]));
printf("Eb/No [dB] = %f, block %d / %d\n", EbOverNo, (block+l), num blocks);for (i=0; i < iter; i++)
printf ("iteration %d: %e\n", (i+l), ((double) totalerrors [ii / total-bits));printf ("\n") ;
/* find simulation time remaining */blocks done++;blocksleft--;time(&curr time);/* elapsedtime / blocks-done = remainingtime / blocksleft
remainingtime = elapsedtime / blocksdone blocks-left*/
temp = (double) (blocksleft * difftime(currtime, starttime)/3600 / blocksdone); /* hoursremaining */
hrs = (int)floor(temp);mins = (int)floor((temp - floor(temp)) * 60);temp 60; /* number of minutes remaining */secs (int)ceil((temp - floor(temp)) * 60);
printf(" total time remaining: %dh %dm %ds\n\n", hrs, mins, secs);
}; /* for loop: blocks */
/* append results for completed Eb/No to the output file '/fp = fopen(filename, a");
fprintf(fp, "sourceSeed=%d\n", sourceSeed);fprintf(fp, "%d-QAM\n", mapper.symbolMapper.M);showTwoDmapping(&mapper.symbolMapper, fp);fprintf(fp, "\nbit map: ");for (i=0; i < mapper.bitMapper.b; i++)
fprintf(fp, "%c", mapper.bitMapper.pattern[i]);fprintf(fp, "\nEav = %f\n", mapper.symbolMapper.Eav);fprintf(fp, "Eb/No = %af, n variance = %f\n", EbOverNo, channel.nvariance);fprintf(fp, "\n%d bits -- Error probability:\n", total-bits);for (i=0; i < iter; i++)
fprintf(fp, "iteration %d: %e\n", (i+l), ((double) totalerrors [i] / total-bits));fprintf(fp, "\n");temp = (double) (difftime(curr time, starttime)/3600 / (blocksdone/num blocks)); /* elapsed for this
Eb/No */hrs = (int)floor(temp);mins = (int)floor((temp - floor(temp)) * 60);temp *= 60; /* number of minutes remaining */secs = (int)ceil((temp - floor(temp)) * 60);printf("simulation time for %d blocks: %dh %dm %ds\n", num blocks, hrs,mins,secs);fprintf(fp, "simulation time for %d blocks: %dh %dm %ds\n\n\n", num blocks, hrs,mins,secs);
fclose(fp);
/* for loop: Eb/No range */
/* free all dynamically allocated variables */
deleteList(&origBitsLL); /* cannot use freeList because list not dynamically allocated */freeTwoDsignalMapVars(&mapper);freeChannelVars(&channel);freeDemodulatorVars(&demodulator);freeEncoderVars(&encoderl);freeInterleaverVars(&interleaverl);freeInterleaverVars(&interleaver2);freeEncoderVars(&encoder2);freePunctureVars(&puncturer);
/* freeUnpunctureVars(&unpuncturer); */ * causes problems, don't use yet */freeMAPDecoderVars(&MAP1);
freeMAPDecoderVars(&MAP2);freeMAPDecoderVars(&MAP3);freeInterleaverVars(&extrinsicinterleaverl);freeInterleaverVars(&extrinsic deinterleaveri);freeInterleaverVars(&Sinterleaverl);freeInterleaverVars(&extrinsic_interleaver2);freeInterleaverVars(&extrinsicdeinterleaver2)freeInterleaverVars(&Sinterleaver2);freeInterleaverVars(&Dprob_deinterleaver);for (i=0; i < iter; i++)
deleteList(&decodedBitsLL[i});free(decodedBitsLL);
}; /* if selection != 0 */}; /* error opening file */
return 0;
/* main */
MAIN SIMULATION CODE
file: uncodedsim.c
This is the main programperformance.
*/
#include "linkedlist.h"#include "source.h"#include "interleave.h"#include "conv.h"#include "puncture.h"#include "mapper.h"#include "channel.h"#include "demod.h"#include "decoder.h"
#include#include#include#include#include
int
file that simulates uncoded QAM
<math.h><time.h><stdio.h><string.h><stdlib.h>
main(int argc, char* argv[])
GENERAL VARIABLE DECLARATIONS ==
general simulation variables */int sourceSeed;FILE* fp;
char filename[80];double EbOverNo, start, finish, delta;int blockSize;long num blocks;int iter;
long totalbits;
long* totalerrors;int terminateBits;
int untermBits;
int numSymbols;
/*/*/*/*/*
misc variables */timet starttime, currtime;
int hrs, mins, secs;int i;long block;
floatlongchardouble
tl, t2, t3;
blocks-left, blocks-done;error;temp;
seed for random # gen */file to write results */store file nameEb/No simulation range */# of bits per block */# of blocks per Eb/No */
/* # of decoder iterations */total bits per Eb/No */total decode errors per Eb/No */# of bits to terminate trellis */blockSize - terminateBits */# of symbols sent thru channel */
keeps track of time */printf: time variables */for loop index */for loop index */
scanf variableskeeps track of progresserror indicatortemporary variable
*/*/*/
== CREATE SIMULATION MODULES ==
/* simulation modules */
/* bit linked lists */linkList origBitsLL;
/* ENCODER modules */twoDsignalMapVars mapper;
/* channel, soft-data modules '/channelVars channel;
demodulatorVars demodulator;
/* systematic buffer
/* signal mapper
/* AWGN channel/* demodulator
INITIALIZE SIMULATION MODULES ==
pri==========\n ");
114
turbosim-uncoded.c
print f ( "
printf(" = UNCOprintf ( " -== == == =-=printf("\n");
printf ("\n") ;printf(",-------------------printf("I\n");
printf(" information bitsprintf)(I \n");
printf(" -------------------
printf ("\n")printf ("\n")
/* output file name */printf(",------------------printf("| Enter output fiprintf("I >> ");scanf("%s", filename);printf('------------------fp = fopen(filename, "a");if (fp == NULL)
else
DE SIMULATION
-- > signal mapper
------------------ \n");
--> channel\n");
--------------------------------------- \n");le name\n");
--------------------------------------- \n");
printf("\n\nError opening file %s, program terminating\n", filename);
fclose(fp);
* --------- UNCODED SIMULATION -----------------------------
printf("\n\n");printf(" -------------------------------------------------------- \n");printf("I MODULE: information bits\n");selectBlockSize(&blockSize, 1, 1); /* select blockSizeprintf( '---------------------------------- ---------------------- \n");
printt("\n\n");
printf(",--------------------------------------------------------\n");printf("I MODULE: bit mapper\n");selectBitMapper(&mapper.bitMapper);printf("--------------------------------------- ----------------- \n");numSymbols = (int) (blockSize / mapper.bitMapper.numSys);
llistInitvars(&origBitsLL, 1);
terminateBits = 0;untermBits = blockSize - terminateBits;
printf("\n\n");printf(",---------------------------------printf("F MODULE: 2-D signal mapper\n");selectSignalMapper(&mapper);printf("---------------------------------
channelInitVars(&channel);
demodulatorInitVars(&demodulator);
/* initialize Eb/No simulation range */printf("\n\n") ;printf(",---------------------------------printfQ(I ENTER:\n");printf("| \n");printf("|l Eb/No to start simulation\n");printf("I >> ");scanf("%f", &tl);printf("I Eb/No to end simulation\n");printf("I >> ");scanf("%f", &t2);
printf("I' Eb/No step size\n");printf("I >> ");scanf("%f", &t3);printf(" \n");start = (double)tl;finish = (double)t2;delta = (double)t3;
printf("I Number of blocks per Eb/No\n");printf("I >> ");scanf("%d", &num blocks);
/* initialize info bits */
/* initialize untermBits */
.----------------------\n");
/* initialize signal mapper */---------------------- \n");
/* initialize channel */
/* initialize demodulator */
--------------------- \n");
/* number of blocks per Eb/No */
blocks-left = (long) (floor((finish - start) / delta) + 1) * numblocks;
I* initialize decoder parameters and decoder variables */printf("'---------------------------------------------------------\n")
blocks done = 0;blocksleft = (long) (floor((finish - start) / delta) + 1) * numblocks;
iter = 1;
totalerrors = (long*)calloc(iter, sizeof(long)); /* init totalerrors array */
/*
- DEFINE MODULE CONNECTIONS ==
turbo sim-uncoded.c115115
116 MAIN SIMULATION CODE
/ ----------- UNCODED SIMULATION ----------------------------- *
mapper.inputS = origBitsLL.output;channel.input = mapper.output;
demodulator.input = channel.output;
CHECK SIMULATION PARAMETERS ==
error = 0;if (error == 0)
BEGIN SIMULATION PROGRAM ==
/* showTwoDmapping(&mapper.symbolMapper, NULL);time(&starttime);sourceSeed = 171;for (EbOverNo = start; EbOverNo <= finish; EbOverNo += delta) { /* this is in dB */
/* initialize bit and error counts to zero '/for (i=0; i < iter; i++)
totalerrors[i) = 0;totalbits = 0;
/* calculate channel noise variance for current Eb/No and constellation */channel.n-variance = mapper.symbolMapper.Eav / (2 * mapper.bitMapper.numSys * pow(10, (EbOverNo/10)))printf("Eb/No = %f, n-variance = %f\n", EbOverNo, channel.n_variance);
/* initialize random # generator with same seed for each Eb/No to use same bit sequences */
srand(sourceSeed);for (block = 0; block < num_blocks; block++)
totalbits += blockSize;
/ ----------- UNCODED SIMULATION ----------------------------- *--
genBits(&origBitsLL, blockSize); /* generate one block of bits */
mapBlock(&mapper); /* generate symbols */sendAWGNblock(&channel); /* send through AWGN channel */
decode uncoded(demodulator.outputS, &mapper, channel.output);/* find error rate */
totalerrors[0) += (long)floor(blockSize * showErrorPercentage(&origBitsLL,demodulator.outputS));
/ find simulation time remaining */blocks_done++;blocks_left--;time(&currtime);
/* elapsedtime / blocks-done = remaining time / blocksleftremaining time = elapsed time / blocks-done blocksleft
temp = (double) (blocksleft * difftime(currtime, start_time)/3600 / blocks_done); /* hours
remaining /hrs = (int)floor(temp);
mins = (int)floor((temp - floor(temp)) * 60);
temp 60; /* number of minutes remaining */secs = (int)ceil((temp - floor(temp)) * 60);
1; /* for loop: blocks /
printf("Eb/No [dB] = %f\n", EbOverNo);
printf("BER: %e\n", ((double)totalerrors[0} / total_bits));printf(" total time remaining: %dh %dm %ds\n\n", hrs, mins, secs);
printf("\n");
/* append results for completed Eb/No to the output file */fp = fopen(filename,"a");
fprintf(fp, "sourceSeed=%d\n", sourceSeed);fprintf(fp, "%d-QAM\n", mapper.symbolMapper.M);showTwoDmapping(&mapper.symbolMapper, fp);fprintf(fp, "\nbit map: ");for (i=0; i < mapper.bitMapper.b; i++)
fprintf(fp, "%c", mapper.bitMapper.pattern[il);fprintf(fp, "\nEav = %f\n", mapper.symbolMapper.Eav);fprintf(fp, "Eb/No = %f, nvariance = %f\n", EbOverNo, channel.nvariance);fprintf(fp, "\n%d bits -- Error probability:\n", total_bits);for (i=0; i < iter; i++)
fprintf(fp, "iteration %d: %e\n", (i+l) , ( (double)totalerrors[i / totalbits));fprintf(fp, "\n");temp = (double) (difftime(currtime, start_time)/3600 / (blocksdone/num blocks)); /* elapsed for this
Eb/No */hrs = (int)floor(temp);mins = (int)floor((temp - floor(temp)) * 60);
temp *= 60; /* number of minutes remaining */secs = (int)ceil((temp - floor(temp)) * 60);printf("simulation time for %d blocks: %dh %dm %ds\n\n", num blocks, hrs,mins,secs);fprintf(fp, "simulation time for %d blocks: %dh %dm %ds\n\n\n", numblocks, hrs,mins,secs);
turbosim-uncoded.c 117
fclose(fp);
/* for loop: Eb/No range */
}; /* if !error */
/* free all dynamically allocated variables */
deleteList(&origBitsLL); /* cannot use freeList because list not dynamically allocated */freeTwoDsignalMapVars (&mapper);
freeChannelVars(&channel);
freeDemodulatorVars(&demodulator);
}; /* error opening file */
return 0;
/* main */
APPENDIX B
Sample Output for turbo_ sim-std.c
Screen Output
TURBO-CODE SIMULATION
s----- -- -- > ---- ----- --- > i
information bits -- > encoder -
interleaverl -- > encoder2 --.
puncture
g mn
> a1
Enter output file name>> test.txt
conv code
1 rate-1/2
2 rate-1/2
3 rate-1/2
4 rate-3/4
paritypuncture
1001
1001
010000000010
10
01
symbolbit map
sp
spsp
sssp
sssp
overallcode rate
rate-1/2
rate-2/4
rate-3/4
rate-3/4
0 see more selections...
Enter selection>> 1
-119-
a
pper
120 APPENDIX B
MODULES: encoderi, encoder2
1 fbPoly = 23 ffPoly = 352 fbPoly = 7 ffPoly = 53 fbPoly = 15 ffPoly = 17
select generator polynomials
>> 1
MODULE: information bits
** must be divisible by 1 **
1 10242 4096
3 51204 61445 15844
Select number of bits per block>> 1
MODULE: interleaverl
1 Random permutation2 Two-step semi-random algorithm (AT&T RN-029 standard)3 Read permutation pattern from file
Select interleaver type> 2
** 1024 elements **
S1, S2, seed
1 (16, 6, 151)2 (18, 12, 151)3 (23, 12, 151)4 (25, 15, 151)5 (26, 15, 151)
Select semi-random interleaver parameters
>> 2
generating interleave pattern ...
MODULE: 2-D signal mapper
1 normal bit labeling (00, 01, 10, 11)2 full gray labeling in each dimension (00, 01, 11, 10)3 concatenated gray labeling in each dimension
Select labeling scheme
>> 2
ENTER:
Eb/No to start simulation>> 1Eb/No to end simulation>> 1
Eb/No step size>> 1
Number of blocks per Eb/No>> 5Number of decoder iterations per block>> 8
Eb/No = 1.000000, nvariance = 0.794328Eb/No [dB] = 1.000000, block 1 / 5iteration 1: 1.054688e-01iteration 2: 9.960938e-02iteration 3: 9.082031e-02iteration 4: 9.082031e-02iteration 5: 8.691406e-02iteration 6: 8.789062e-02iteration 7: 8.496094e-02iteration 8: 8.496094e-02
total time remaining: Oh Om 4s
Eb/No [dB] =iteration 1:iteration 2:iteration 3:iteration 4:iteration 5:iteration 6:iteration 7:iteration 8:
Eb/No [dB] =iteration 1:iteration 2:iteration 3:iteration 4:iteration 5:iteration 6:iteration 7:iteration 8:
Eb/No [dB] =iteration 1:iteration 2:iteration 3:iteration 4:iteration 5:iteration 6:iteration 7:iteration 8:
Eb/No [dBI =iteration 1:iteration 2:
1.000000, block 2 / 59.765625e-029.61914le-028.691406e-029.033203e-027.421875e-028.05664le-028.496094e-028.300781e-02
total time remaining: Oh Om 2s
1.000000, block 3 / 57.910156e-026.477865e-025.794271e-026.022135e-024.947917e-025.371094e-025.664062e-025.533854e-02
total time remaining: Oh Om ls
1.000000, block 4 / 58.227539e-026.396484e-025.419922e-025.419922e-024.199219e-024.052734e-024.248047e-024.150391e-02
total time remaining: Oh Om ls
1.000000, block 5 / 58.417969e-026.386719e-02
SAMPLE OUTPUT 121
122 APPENDIX B
iteration 3: 5.019531e-02iteration 4: 4.375000e-02iteration 5: 3.359375e-02iteration 6: 3.242188e-02iteration 7: 3.398437e-02iteration 8: 3.320312e-02
total time remaining: Oh Om Os
simulation time for 5 blocks: Oh Om 2s
SAMPLE OUTPUT
Output File test.txt
sourceSeed=1714-QAM
[point, label]
bit map: spEav = 2.00000Eb/No = 1.000
5120 bitsiterationiterationiterationiterationiterationiterationiterationiteration
1:2:3:4:5:6:
7:
8:
[(-1,-i), 00]
0000, nvariance = 0.794328
Error probability:8.417969e-026.386719e-025.01953le-024.375000e-023.359375e-023.242188e-023.398437e-023.320312e-02
simulation time for 5 blocks: Oh om 2s
123
[(-il), Oi] [(1,-1), 10] [(1,1), 1l]
APPENDIX C
Simulation Code
general.h
file: general.h
This file contains definitionsused by different modules.
of general purpose functions
/* basic functions */double sqr(double a);double min(double a, double b);double max(double a, double b);
/* convert between char[] and int *void intToCharArray(int s, char binary[], int v);int charArrayToInt(char binary], int v);
- 125 -
126 SIMULATION CODE
general.c
/*
file: general.c
This source file contains code for general functions used byother routines.
*/
#include "general.h" /* general.h must come before math.h because max and minare already defined in math.h in some libraries. */
#include <math.h>
/*
function: sqr
This function returns the square of an input double.
Input double a
Output (a * a)
*/double sqr(double a)
return (a * a);
/* sqr /
function: min
This function returns the lesser of two doubles.
Input double adouble b
Output lesser of a and b
*/double min(double a, double b)
return ((a <= b) ? a : b);
} /* min
function: max
This function returns the greater of two doubles.
Input double adouble b
Output greater of a and b
*/double max(double a, double b)
return ((a >= b) ? a : b);
/* max *
function: intToCharArray
This function converts an integer value into binary.binaryt0] is the MSB of the integer, and binarytv-1] is the LSBof the integer.
Input : int s - the integer valuechar binary[] - array to hold binary valueint v - length of the binary array
I Output :
general.c 127
I Modify : binary[]
void intToCharArray(int s, char binary(], int v)
/ if s = 6, v=3binary[] is 1 1 0indices are 0 1 2
so index 0 is MSB and index 2 is LSB
int i;
for (i=0; i < v; i++)binary[v-1-i} = ((s >> i) & 1);
/* intToCharArray /
/*
function: charArrayToInt
This function converts a binary number into an integer.binary[0] is the MSB of the integer, and binary[v-1] is the LSBof the integer.
Input char binary[] - array holding binary valueint v - length of array
Output the integer valueModify
int charArrayToInt(char binary[}, int v)
/* if s = 6, v=3binary[] is 1 1 0indices are 0 1 2
so index 0 is MSB and index 2 is LSB*/
int i, sum = 0;
for (i=0; i < v; i++)
sum += (int)binary[i] * (int)pow(2, (v-1-i));
return sum;
/* charArrayToInt /
128 SIMULATION CODE
Iinkedlist.h
file: linkedList.h
This header file contains variable and function definitionsfor a linked list.
/* type definitions */typedef struct twoDSignalPointStruct
double i;
double q;
} twoDSignalPoint;
typedef struct listElementStructchar *value;twoDSignalPoint *signal;
struct listElementStruct *next, *prev;
listElement;
typedef struct linkListStructint valueLength;
listElement *head, *tail;
struct linkListStruct *output;
linkList;
/* init/deallocation functions */void llistInitVars(linkList* llist,void freeList(linkList* list);
int arrayLength);
/* adding elements */void addElement(linkList* llist, listElement* newEl);void addLLbits(linkList* llist, char bits[]); /* add 1 element with specified bits */void addLLsignal(linkList* llist, twoDSignalPoint points[]); /* add 1 element with specified signals */void addLLdata(linkList* llist, char bits]], twoDSignalPoint points]]); /* add 1 element with specified data */
/* deleting elements */void deleteFirstElement(linkList* llist);void deleteList(linkList* llist);
/* get element pointer */listElement* getElement(linkList* llist, int n);
char* getValue(linkList* llist, int n);twoDSignalPoint* getSignal(linkList* llist, int n);
/* show list contents */void showLLbits(linkList* llist);void showLLsignals(linkList* llist);
/* other functions */char notEmpty(linkList* llist);int getNumElements(linkList* llist);void copyList(linkList* orig, linkList* copy);
linkedlist.c 129
Iinkedlist.c
file: linkedlist.c
This source file contains code for linked list functions.
*/
#include "linkedlist.h"
#include <stdio.h>#include <stdlib.h>
/* -------------- INITIALIZATION / DEALLOCATION FUNCTIONS --------- -----
/*
function: llistInitVars
This function initializes all variables in the input linked list.head and tail pointers are set to NULL, valueLength is set to the
I input variable arrayLength, and output points back to the listitself.
Input linkList *llistint arrayLength
OutputModify llist struct elements
void llistInitVars(linkList* llist, int arrayLength)
(*llist).head = NULL;
(*llist).tail = NULL;
(*llist).valueLength = arrayLength;(*llist).output = llist;
}; / llistInitVars *
function: freeList
Frees all dynamically allocated variables in the input linked list.
Input linkList *list - linked list pointerOutputModify list
void freeList(linkList* list)
deleteList(list);free(list);
S/* freeList */
/* --------- ----- ADDING ELEMENTS -------------------
function: addElement
Add an element to the end of the linked list.
Input linkList *llist - linked list pointerlistElement *newEl - new element pointer
OutputModify : llist, newEl
void addElement(linkList* llist, listElement* newEl)
(*newEl).next = NULL; /* last element, set next to NULL V
SIMULATION CODE
if ((*l1ist).head == NULL)
(*llist).head = newEl;(*llist).tail = newEl;(*newEl).prev =NULL;
else
(*l(*list).tail).next = newEl;
(*newEl).prev = (*llist).tail;
(*l1ist).tail = newEl;
};
/* this is first element in the list *//* both head and tail point to this element */
no previous element */
at least one element in list already */
/* new element now at end of linked list */
/* addElement */
/*
function: addLLbits
Add a new element with the specified bits to the end of thelinked list.
Input linkList* llist - linked list pointerchar bits[] - array of bits
OutputModify llist
*/
void addLLbits(linkList* llist, char bits[])
{int i;
listElement* newEl = (listElement*) calloc(1, sizeof(listElement)); /* allocate memory for new element */
(*newEl) value = (char*) calloc( (*llist) .valueLength, sizeof (char)); /* allocate memory to hold bit values V(*newEl) signal = (twoDSignalPoint*) calloc( (*llist) .valueLength, sizeof (twoDSignalPoint)); /* allocate memory
to hold bit values */
for (i=O; i < (*llist).valueLength; i++)(*newEl).value(ii = bits[i]; '* copy bit values to new element */
addElement(llist, newEl);
/* addLLbits */
/*
function: addLLsignal
Add a new element with the specified points to the end of thelinked list.
Input linkList* llist - linked list pointertwoDSignalPoint points)] - array of 2D points
OutputModify
void addLLsignal(linkList* llist, twoDSignalPoint points[])
int i;
listElement* newEl = (listElement*) calloc(1, sizeof(listElement)); /* allocate memory for new element */
(*newEl) value = (char*) calloc((*llist) .valueLength, sizeof (char)); /* allocate memory to hold bit values */(*newEl) signal = (twoDSignalPoint*) calloc((*llist) .valueLength, sizeof(twoDSignalPoint)); /* allocate memory
to hold bit values s/
for (i=O; i < (*llist).valueLength; i++)(*newEl).signal[i] = points[i];
addElement(llist, newEl);
/* addLLsignal */
function: addLLdata
Add a new element withlinked list.
Input linkList*char
twoDSignalPoirOutputModify
the specified points to the end of the
llist - linked list pointerbits[] - array of bits
t points[] - array of 2D points
130
n
linkedlist.c 131
*/void addLLdata(linkList* llist, char valueBits)], twoDSignalPoint points[])
int i;
listElement* newEl = (listElement*) calloc(1, sizeof(listElement)); /* allocate memory for new element /(*newEl) value = (char*) calloc( (*list) .valueLength, sizeof(char)); /* allocate memory to hold bit values /(*newEl) signal = (twoDSignalPoint*) calloc( (*llist) .valueLength, sizeof(twoDSignalPoint)); /* allocate memory
to hold bit values /
for (i=O; i < (*Ilist).valueLength; i++)
(*newEl).value[i] = valueBits[i]; /* copy bit values to new element V(*newEl).signal[i] = points[i];
addElement(llist, newEl);
/* addLLdata */
/* --------------- DELETING ELEMENTS --------
function: deleteFirstElement
Delete first element of linked list.
Input linkList* llist - linked list pointerOutputModify llist
void deleteFirstElement(linkList* llist)
listElement *temp;
if ((*Ilist).head != NULL)
temp = (*llist).head;(*llist).head = (* (*list).head).next; /* set next element in list as first /if ((*llist).head 1= NULL)
(*(*llist).head).prev = NULL;free((*temp).signal);free((*temp).value);
free(temp); /* delete previous first element *};
} /* deleteFirstElement *
function: deleteList
Delete all elements in the linked list.
Input : linkList* llist - linked list pointerOutputModify : llist
*/
void deleteList(linkList* llist)
while ((*llist).head != NULL)deleteFirstElement(llist);
S/* deleteList */
/* --------------- GETTING ELEMENT POINTERS -------------------
/*
function: getElement
Get nth element from linked list. n=1,2,3,...
Input : linkList* llist - linked list pointerint n - index of element to get
Output : pointer to the list element to returnModify
132 SIMULATION CODE
listElement* getElement(linkList Illist, int n)
* n is from 1 to (# of element in list) */int i;listElement* temp; /* will hold pointer to list element to return */
if (llist == NULL)temp = NULL;
else
temp = (*1list).head; /* begin at first element of list */for (i=O; i<(n-l); i++) /* go down list until we reach nth element */
temp = (*temp).next;
};
return temp; /* return nth element */
/* getElement */
/*
function: getvalue
Get the bit array of an element of the linked list.
Input linkList* llist - linked list pointerint n - index of list element
Output : bit arrayModify
*/
char* getValue(linkList* llist, int n)
return (*(getElement(llist,n))).value;
/* getValue */
/*
function: getSignal
Get the signal point array of an element in the linked list.
Input linkList* llist - linked list pointerint n - index of list element
Output array of 2D pointsModify
twoDSignalPoint* getSignal(linkList* llist, int n)
return (*getElement(llist,n)).signal;
} /* getSignal */
/* ------------- DISPLAY LIST CONTENTS -------------
/*
function: showLLbits
Show the bits in every element of the linked list.
Input linkList* llist - linked list pointerOutputModify
void showLLbits(linkList* llist)
int i;
listElement* temp;
temp = (*llist).head;while (temp != NULL) /* traverse the list */
for (i=G; i < (*llist).valueLength; i++)
printf("%d", (*temp).value i]);temp = (*temp).next;
};printf("\n");
} showLLbits */
function: showLLsignals
Show the signal points stored in every element of the list.
Input linkList* llist - linked listOutputModify
*/void showLLsignals(linkList* llist)
int i;listElement* temp;
temp = (*llist).head;while (temp != NULL) /* traverse the list */
for (i=O; i < (*llist).valueLength; i++)printf(" (%g,%g) ", (*temp).signal[i].i, (*temp).signal[i].q);
temp = (*temp).next;};printf("\n");
} /* showLLsignals */
/* --------------- OTHER FUNCTIONS -------------
/*
function: notEmpty
Test if there are any elements in the linked list
Input linkList* llist - linked list pointerOutput 0 if list is empty, else 1Modify
char notEmpty(linkList* llist)
return ((*llist).head != NULL);} /* notEmpty */
function: getNumElements
Get number of elements in the linked list.
Input : linkList* llist - linked list pointerOutput : number of elements in listModify
getNumElements(linkList* llist)
int count = 0;listElement* tempEl;
tempEl = (*llist).head;while (tempEl != NULL)
tempEl = (*tempEl).next;
count++;1;
return count;
/* getNumElements */
linkedlist.c 133
int{t
134 SIMULATION CODE
function: copyList
Copy all elements in one list to another.
Input linkList* orig - pointer to original linked listlinkLIst* copy - pointer to linked list copy
OutputModify copy
*/void copyList(linkList* orig, linkList* copy)
int num, i;listElement* currEl;
deleteList(copy);
(*copy).valueLength = (*orig).valueLength;num = getNumElements(orig);currEl = getElement(orig, 1);for (i=0; i < num; i++)
addLLdata(copy, (*currEl).value, (*currEl).signal);currEl = (*currEl).next;
};
} /* copyList */
source.h 135
source.h
/*
file: source.h
This header file contains function definitions for generatingbits.
/* selection function */void selectBlockSize(int *blockSize, int k, int numSys);
/* simulation command */void genBits(linkList* llist, int numBits);
/* debug/display function */void showArrayBits(char bits[}, int size);
SIMULATION CODE
file: source.c
This file contains code for modules that generate bits.
#include "linkedlist.h"#include "source.h"
#include <math.h>#include <stdlib.h>#include <stdio.h>
--- SELECTION FUNCTION --------
function: selectBlockSize
Selects the number of bits in an encode/decode block. The blocksize must be divisible by the number of bits, k, used as input toa rate-k/n convolutional code. Further, the block size must alsobe divisible by the number of systematic bits per symbol.
Input int *blockSize - pointer to variable to hold block sizeint k - number of bits to input to a rate-k/n conv. encoderint numSys - number of systematic bits per symbol
OutputModify : blockSize
void selectBlockSize(int *blockSize, int k, int numSys)
int selection;char error;int nl, n2, lcm;
ni = k;n2 = numSys;/* assume k < numSys, so thatlcm = n2;
while ((lcm % nl) != 0)1cm += n2;
k fits onto one symbol */
printf("I----------------------------------------printf("I\n");printf(" ** must be divisible by %d **\n", lcm);printf("I\n");printf("I 1 1024\n");printf("I 2 4096\n");printf("I 3 5120\n");printf("I 4 6144\n");printf("I 5 15488\n");
printf("\n");
printf("I----------------------------------------printf("I Select number of bits per block\n");error = 1;while (error)
printf("j >>scanf("%d", &selection);if ((selection >= 1) & (selection <= 5))
error = 0;switch (selection)case 1:
*blockSize = 1024;break;
case 2:*blockSize = 4096;break;
case 3:
*blockSize = 5120;break;
case 4:*blockSize = 6144;break;
case 5:
};if (
*blockSize = 15488;break;
((blockSize) % lcm)
error = 1;
136
source.c
------------- \n");
0)
------- \n");
source.c 137
printf("I ** error: block size not divisible by %d **\n", lcm);
elseprintf(" ** invalid selection **\n");
};
} /* selectBlockSize */
/* ------------------------ SIMULATION COMMAND FUNCTION ---------- /
function: genBits
Generate bits randomly. If the list is empty when this functionis called, add the new bits to the list. If the list is not emptywhen this function is called, then simply replace the bits in thelist with new bits. Because other functions may have added bitsto the list, delete remaining elements after enough bits aregenerated.
Input linkList* llist - linked list pointerint numBits - number of bits to generate
OutputModify llist
void genBits(linkList* llist, int numBits)
int i, j;char *bits;listElement *currEl, *headPtr, *tailPtr;
/* If list already exists, go through the list andreplace values. This way, we don't have to delete elements,then add elements again.
*/
bits = (char*) calloc((*llist) .valueLength, sizeof (char));currEl = (*llist).head;
for (i=G; i < (numBits/ (*llist) .valueLength); i++)
for (j=O; j < (*llist).valueLength; j++)
bits[ji = (char) (rand)) % 2);if (currEl != NULL)
(*currEl).value[j] = bits[j];I;if (currEl == NULL)
addLLbits(llist, bits);else
currEl = (*currEl).next;};
/* terminateEncoder) function may have appended bits to llist, soset tail to currEl->prev and delete the remaining elements */
if (currEl != NULL)headPtr = (*llist).head;tailPtr = (*currEl).prev;(*tailPtr).next = NULL;(*llist).head = currEl;deleteList(llist);/* only actually deletes elements starting at currEl */(*llist).head = headPtr;(*llist).tail = tailPtr;
};
free(bits);
/* genBits */
/* ----------------------- DISPLAY/DEBUG FUNCTION ----------------------
function: showArrayBits
Show the bits in an array.
Input : char bits[] - array of bitsint size ~ length of array
OutputModify
SIMULATION CODE
showArrayBits(char bits[], int size)
int i;
for (i=0; i<size; i++)printf("%d", (int)bits[i]);
printf ("\n");
} /* showArrayBits */
138
void
interleave.h 139
interleave.h
file: interleave.h
This header file contains variable and function definitions forinterleavers.
#include <stdio.h>
/* type definitions */typedef struct interleaverVarsStruct
int blockSize;int* permutePattern;
linkList* input;linkList* output;
} interleaverVars;
/* selection function */void selectInterleaver(interleaverVars* interleaver, int blockSize);
/* simulation command function */void doInterleave(interleaverVars* interleaver);
/* init/deallocation functions */ -void randomPatternInitVars(interleaverVars* interleaver, int numEl);void SrandomInitVars(interleaverVars* interleaver, int S1, int S2, int blockSize, int seed);int interleaverFileInitVars(interleaverVars* interleaver, FILE* fp, int numEl);void deinterleaverInitVars(interleaverVars* deinterleaver, interleaverVars* interleaver)void freeInterleaverVars(interleaverVars* interleaver);
/* display/debug function */void showPermutePattern(interleaverVars* interleaver)
/* other functions */void regroupltoK(linkList* thelist, int k);void regroup Ktol(linkList* thelist, int k);void outputPattern(interleaverVars* interleaver, FILE* fp);
/* AT&T 2-step semi-random interleaver functions */char canFillRest(int remainingIndices[], int index, interleaverVars* interleaver, int S1, int S2);void updateRemaining(int remainingIndices[], int index, int deltalndex);void genSrandomPattern(interleaverVars* interleaver, int Si, int S2);
SIMULATION CODE
file: interleave.c
This source file contains code for all interleavers.
#include "linkedlist.h"#include "interleave.h"
#include <math.h>#include <stdio.h>#include <stdlib.h>
* ------------ SELECTION FUNCTION - -
function: selectInterleaver
Selects the type of interleaver to usepattern.
Input interleaverVars* interleaver -int numEl
OutputModify interleaver
in generating a permutation
interleaver pointerinterleaver depth
void selectInterleaver(interleaverVars* interleaver, int numEl)
fint selection;char error;int Sl, S2, seed;
char filename[80];FILE* fp;
printf("I---------------------------------------------------------\n");printf("I\n");printf("l 1 Random permutation \n");printf("I 2 Two-step semi-random algorithm (AT&T RN-029 standard)\n");printf("I 3 Read permutation pattern from file\n");printf("\n");
printf(" ---------------------------------------------------------\n");error = 1;while (error)
printf("I Select interleaver type\n");printf("I >> ");scanf("%d", &selection);if ((selection >= 1) & (selection <= 3))
error = 0;switch (selection)case 1:
srand(151);
randomPatternInitVars(interleaver, numEl);
break;
case 2:/* semi-random interleaver
Uses function: SrandomInitVars() to
printf(" ---------------------------------printf("I\n");printf("I ** %d elements **\n", numEl);printf("I\n");printf("I Sl, S2, seed\n");printf("I ------------ \n");printf("I 1 (16, 6, 151)\n");printf("I 2 (18, 12, 151)\n");printf("I 3 (23, 12, 151\n");printf("I 4 (25, 15, 151)\n");printf("I 5 (26, 15, 151)\n");printf(" \n");printf("I---------------------------------printf("I Select semi-random interleavererror = 1;while (error)
init interleaver
---------------
parameters\n");
printf("I >> ");scanf("%d", &selection);if ((selection >= 1) & (selection <= 5))
error = 0;
140
interleave.c
-\n");
interleave.c 141
switch (selection)case 1:
Sl = 16;S2 = 6;seed = 151;break;
case 2:
51 = 18;S2 = 12;
seed = 151;break;
case 3:
Sl = 23;S2 = 12;seed = 151;
break;case 4:
Sl = 25;S2 = 15;seed = 151;
break;case 5:
Sl = 26;
S2 = 15;
seed = 151;break;
}; /* switch semi-random *printf("I generating interleave pattern...\n");printf ("I note: if this takes too long, restart with smaller parameters\n");SrandomInitVars(interleaver, Sl, S2, numEl, seed);
/* if selection ok */else
printf(" I ** invalid selection **\n");
}; /* while error */break;
case 3:/* get interleave pattern from a file
Uses function: interleaverFileInitvars) to init interleaver
printf("I---------------------------------------------------------\n");printf("I Enter input file name for %d elements\n", numEl);printf("I >> ");scanf("%s", filename);fp = fopen(filename, "r");if (fp == NULL)
error = 1;printf(" I * Unable to access file %s **\n", filename);
else
error = interleaverFileInitVars(interleaver, fp, numEl);fclose(fp);
};break;
/* switch selection*/
/* if interleaver selection ok */else
printf("I ** invalid selection **\n");
}; /* while invalid selection, error==l */
) /* selectinterleaver */
* ------------- SIMULATION COMMAND FUNCTION ------------------- f*
/*
function: doInterleave
Performs element by element interleaving on an input linked listand stores the permuted elements in an output linked list. Ifthe output list already exists, simply replace the element arrayswith new values. Otherwise, add new elements to the output list.
This function does not alter the input linked list.
Input : interleaverVars* interleaver - interleaver pointerOutputModify : (*interleaver).output
*/void doInterleave(interleaverVars* interleaver)
int i, j;char* tempchar;twoDSignalPoint* tempPt;listElement **tempEl, *currEl, *outEl;
SIMULATION CODE
/* instead of deleteList((*interleaver).output), traverse list and
replace values
tempEl = (listElement**) calloc((*interleaver).blockSize, sizeof(listElement*));
/* makes sure input and output list valueLengths are the same */
(*(*interleaver).output).valueLength = (*(*interleaver).input).valueLength;
currEl = (*interleaver).input->head;/* get memory locations of individual list elements for input */for (i = 0; i < (*interleaver).blockSize; i++)
tempEl[(*interleaver).permutePattern[i]] = currEl;
currEl = (*currEl).next;
i = 0;outEl = (*interleaver).output->head;
while (i < (*interleaver).blockSize)if (outEl == NULL) /* add value and signal as a new element to list *
tempchar = (*tempEl[i]).value;tempPt = (*tempEl[i]).signal;addLLdata((*interleaver).output, tempchar, tempPt);i++;
else /* replace value and signal of current output element */
{for (j=o; j < (*interleaver).input->valueLength; j++)
(*outEl).value[j](*outEl).signal[j]
};outEl - (*outEl).next;i++;
};
free(tempEl);
I; /* doInterleave */
(*tempEl[i]).value[j];(*tempEl[i]).signal[j];
INIT/DEALLOCATE FUNCTIONS
function: randomPatternInitVars
Input : interleaverVars* interleaverint Sl
OutputModify : *interleaver
void
interleaver pointerminimum permute distance
randomPatternInitVars(interleaverVars* interleaver, int numEl)
int i;int rndNum, numDone;int* numbers;
numbers = (int*)calloc(numEl, sizeof(int));for (i=0; i < numEl; i++)
numbers[i] = i;
(*interleaver).blockSize = numEl;(*interleaver).permutePattern = (int*) calloc((*interleaver).blockSize, sizeof(int));(*interleaver).output = (linkList*) calloc(l, sizeof(linkList));llistInitVars((*interleaver).output, 0);
for (numDone=0; numDone < (numEl-1); numDone++)
rndNum = rand() % (numEl - numDone);
(*interleaver).permutePattern[numDone] = numbers[numDone + rndNum];
numbers[numDone + rndNum] = numbers[numDone];i;(*interleaver) .permutePattern~numEl-l] = numbers (numEl-l];
free(numbers);
} /* randomPatternInitVars *
function: SrandomInitVars
142
*/
Initializes variables and generates an interleave pattern
according to the semi-random algorithm from ITU proposal RN-029.See description for function genSrandomPattern) for details.
Input : interleavervars* interleaver - interleaver pointer
int S1 - minimum permute distance
int S2 - minimum rearranged distance
int blockSize - number of elements to interleaveint seed - random number generator seed
Output :MOdify : (*interleaver).permutePattern
void SrandomInitVars(interleaverVars* interleaver, int Si, int S2, int blockSize, int seed)
(*interleaver).blockSize = blockSize;
(*interleaver) permutePattern = (int*) calloc( (*interleaver) .blockSize, sizeof (int)
(*interleaver) output = (linkList*) calloc(1, sizeof(linkList))
1listInitVars((*interleaver).output, 0);
srand(seed);
genSrandomPattern(interleaver, Sl, S2);
} /* SrandomInitVars */
function: deinterleaverInitVars
Initializes a de-interleaver based on an
permute pattern. The permute pattern of
the inverse of that of the interleaver.
Input interleaverVars* deinterleaver -interleaverVars* interleaver -
OutputModify deinterleaver
existing irterleaverthe de-interleaver is
deinterleaver pointerinterleaver pointer
void deinterleaverInitVars(interleaverVars* deinterleaver, interleaverVars* interleaver)
int i;
(*deinterleaver) .blockSize = (*interleaver) .blockSize;(*deinterleaver) permutePattern = (int*) calloc( (*deinterleaver) .blockSize, sizeof(int)
for (i=O; i < (*interleaver).blockSize; i++)(*deinterleaver) .permutePattern[(* interleaver) .permutePattern[i]] = i;
(*deinterleaver) .output = (linkList*) calloc(1, sizeof(linkList))
llistinitVars((*deinterleaver).output, 0);
} /* deinterleaverInitVars */
function: interleaverFileInitVars
Reads an interleave pattern from a file. The first entry of thefile is the interleaver depth and must match input parameter numEl.The remaining entries are the permutation indices.
interleaverVars* interleaver
FILE* fpint numEl
t :y : interleaver
interleaver pointerpointer of file to read frominterleaver depth
interleaverFileInitVars(interleaverVars* interleaver, FILE* fp, int numEl)
int i=O;
int size;int error;
fscanf(fp, "%d", &size);if (size == numEl) /* file has correct interleaver depth */
error = 0;(*interleaver).blockSize = size;(*interleaver) permutePattern = (int*) calloc( (*interleaver) blockSize, sizeof(int))
for (i=0; i < (*interleaver) blockSize; i++)fscanf(fp, "Id", &(*interleaver) .permutePattern[i]
(*interleaver) .output = (linkList*) calloc(l, sizeof(linkList))llistInitVars((*interleaver).output, 0);
interleave.c 143
Input
OutpuModif
int
144 SIMULATION CODE
else /* file has wrong interleaver depth *
error = 1;printf("\n** Input file contains incorrect interleaver depth **\n\n");
};
return error;
/* interleaverFileInitVars */
function: freeInterleaverVars
Free dynamically allocated memory for interleaver.
Input : interleaverVars* interleaver - interleaver pointer
OutputModify : interleaver
*/void freeInterleaverVars(interleaverVars* interleaver)
free((*interleaver).permutePattern);freeList((*interleaver).output);
/* freeInterleaverVars /
/* ------------- DISPLAY/DEBUG FUNCTIONS -------------------
/*
function: showPermutePattern
Print the permute pattern to the screen.
Input : interleavervars* interleaver - interleaver pointerOutputModify
*/void showPermutePattern(interleaverVars* interleaver)
int i;
printf("Permute pattern: ");for (i=0; i < (*interleaver).blockSize;i++)
printf(" - %d", (*interleaver).permutePattern[i]);
printf(" -\n");
} /* showPermutePattern */
/* ------------- OTHER FUNCTIONS -------------------
function: regroupltoK
The input linked list contains 1 bit per list element. Thisfunction regroups the list so that there are K bits per listelement. The resulting list will have a factor of K lesslist elements.
Input : linkList* thelist - linked list pointerint k - number of bits per list element
OutputModify : thelist
"I
void regroup ltoK(linkList* thelist, int k)
int num, i, j;char *bits;twoDSignalPoint* values;
(*thelist).valueLength = k;bits = (char*) calloc(k, sizeof(char));values = (twoDSignalPoint*) calloc(k, sizeof(twoDSignalPoint));num = (int) (getNumElements(thelist) / k);for (i=O; i < num; i++)
for (j=O; j < k; j++)
bits[j] = *getValue(thelist, 1);values[j] = *getSignal(thelist, 1);deleteFirstElement(thelist);
addLLdata(thelist, bits, values);
1;
free(bits);
/* regroup ltoK *
function: regroupKtol
The input linked list contains K bit perfunction regroups the list so that thereelement. The resulting list will have a
list elements.
Input : linkList* thelistint k
OutputModify : thelist
list element. Thisis 1 bit per listfactor of K more
linked list pointernumber of bits per list element
void{
regroup Ktol(linkList* thelist, int k)
int num, i, j;
char bit;
twoDSignalPoint point;
(*thelist).valueLength = 1;num = getNumElements(thelist);for (i=O; i < num; i++)
ffor (j=0; j < k; j++)
bit = (getValue(thelist, 1)) [IjI;point = (getSignal (thelist, 1)) [j];addLLdata(thelist, &bit, &point);
deleteFirstElement(thelist);
/* regroupKtol s/
/*
function: outputPattern
Prints the interleaver depth and permute pattern to a file.
Input interleaverVars* interleaver
FILE* fp
OutputModify : fp
interleaver pointeroutput file pointer
void outputPattern(interleaverVars* interleaver, FILE* fp)
int i=O;
fprintf (fp, "%d\n", (*interleaver) .blockSize)while (i < (*interleaver).blockSize)
fprintf(fp, "%d\n", (*interleaver) .permutePattern[i++]);
/* outputPattern */
/* ------------- AT&T 2-STEP SEMI-RANDOM INTERLEAVER FUNCTIONS --
function: canFillRest
Determines whether the remaining unused permute indices cansatisfy the semi-random algorithm. If not, then the algorithmwill need to be restarted.
Input : int remainingIndices[] - array to keep track of which permute indices have beenused and which are available
int index - index of remainingIndices[ that divides used and
interleave.c 145
{
--- */
146 SIMULATION CODE
available permute indicesint Sl - element by element minimum separation distanceint S2 - cell by cell minimum separation distanceinterleaverVars* interleaver - interleaver pointer
Output ;1 if s-random algorithm can be completed, 0 otherwise
*/char canFillRest(int remainingIndices[], int index, interleaverVars* interleaver, int S1, int S2)
int i, j, possIndex;char canFilll=O, canFill2=0;
i = index;while ( (!canFilll 11 !canFill2) && (i < (*interleaver).blockSize) ) /* check both Sl and S2 criteria *
possIndex = remainingIndices[i++];canFill2 = (abs(possIndex-index) > S2);if (canFill2)
j = (index <= Sl) ? 0 : (index-Sl);canFilll = 1;while (j < index)
canFilll = canFilll && (abs((*interleaver)
/* check next permute index/* check S2 criterion */
/* compare to Sl previous cells */
/* see if permute index can satisfy */* the semi-random algorithm */.permutePattern[j) - possIndex) > Sl);
1;};
return (canFilll && canFill2);
}; /* canFillRest */
function: updateRemaining
This function is used byhas "blockSize" cells andremainingIndices[O..(indexremainingIndices[index..(bThis function updates rem
Input : int remainingIndi
int index
int deltaIndex
OutputModify remainingIndices
enSrandomPattern. The array remainingIndices[]contains the permute indices.x-1)] contains permute indices that have already been used.blockSize-1)] contains those that haven't been used.iningIndices[] when another permute index is used.
ces [] array to keep track of which permute indices have beenused and which are availableindex of *remainingIndices that divides used andavailable permute indicesremainingIndices[index + deltaIndex] contains the permuteindex just used
void updateRemaining(int remainingIndices[], int index, int deltaIndex)
int swapIndex, swapValue;
swapIndex = index + deltaIndex; /* index of used permute index *swapValue = remainingIndices[swapIndex]; /* the used permute index *remainingIndices[swapIndex] = remainingIndices[index]; /* update *remainingIndices *remainingIndices[index] = swapValue;
}; /* updateRemaining *
function: genSrandomPattern(void)
Generates a semi-random sequence of dist*inct integers between 0 and
(blockSize-1). p(i) denotes the permuted sequence. Excerpt from RN-029:
"Each randomly selected integer p(i) is compared with the previous selectionsp(j) to check that if (i-j) <= S1 then pi(i)-pi(j) > Sl. We alsoinsist that p) must satisfy li-p(i) > S2."
In the end we will need "blockSize" distinct numbers from 0.. (blockSize-1)Thus, we may find that with a few numbers left to choose from, we are unableto satisfy the algorithm criterion and may have to start the process over fromthe beginning. The functions canFillRest() and updateRemaining() are used toperform this check.
InputOutput
void genSrandomPattern(interleaverVars* interleaver, int S1, int S2){
int index, Sindex, j, deltaIndex;
interleave.c 147
int* remainingIndices = (int*) calloc((*interleaver) blockSize, sizeof(int))
while (index < (*interleaver).blockSize) /* don't have all new numbers */
for (j=O; j < (*interleaver) .blockSize;j++)remainingIndices[j]=j; /* initialize *remainingIndices */
index = 0;
while (canFillRest(remainingIndices, index, interleaver, S1, S2))
deltaIndex = rand) % ((*interleaver).blockSize-index); /* choose from remaining permute indices*/
Sindex = remainingIndices[index + deltaIndex]; /* get the unused permute index *if (abs(Sindex - index) > S2) /* check S2 criterion */
j = (index <= Sl) ? 0 : (index-Sl); /* compare with S1 previous indices */while ((abs((*interleaver) .permutePattern[j] - Sindex) > S) && (j < index))
j++;if (j == index) /* new permute index is okay to use /
(*interleaver).permutePattern[index = Sindex;updateRemaining(remainingIndices, index, deltaIndex);index++;
};};
}; /* while we can fill the rest of the permutation pattern */
}; /* while not done generating Sindex's */
free(remainingIndices);
}; /* genSrandomPattern */
148 SIMULATION CODE
conv.h
file: convRoutines.h
This header file contains variable and function definitions forconvolutional encoders.
*/
/* type definitions */
typedef struct branchStructint Sl, S2;int d;
int p;branch;
typedef struct encoderVarsStructbranch** trellis;int* terminator;
char* state;int k;int r;
int V;
linkList* input;linkList* output;
encoderVars;
/* selection function */void selectEncoder(encoderVars* encoder, int kSel);
/* simulation command function */void encodeBlock(encoderVars* encoder);void terminateEncoder(encoderVars* encoder);
/* init/deallocate functions */void duplicateEncoder(encoderVars* encoderl, encoderVars* encoder2);void ratel2initVars(encoderVars* encoder, char fbPoly[], char ffPoly[]);void ratekkllnitVars(encoderVars* encoder, char fbPoly[], char** ffPoly, int k);void CCinitVars(encoderVars* encoder, int degree);void freeEncoderVars(encoderVars* encoder);
/* display/debug function */void showTrellis(encoderVars* encoder);
/* generator polynomial functions */void convertoctal(char octalChar, char binaryRep[]);void convertString(char polyString[}, char coeffArray[], int v);int getDegree(char polyString[]);void setFeedback(char* polyString, char* feedbackCoefficient, int v);void setFeedforwG(int parityNum, int inputNum, char* polyString, char*** forwCoefficient, int v);
/* trellis functions */void ratelnSetBranch(branch* br, char*** ffCoeff, char* fbCoeff, int v, int r)void ratekklSetBranch(branch* br, char*** ffCoeff, char* fbCoeff, int v, int k);int nextState(encoderVars* encoder, listElement* inputEl);
conv.c
file: convRoutines.c
This source file contains code for convolutional encoder.
*/
#include "general.h"#include "linkedlist.h"#include "conv.h"
#include#include#include#include
<math.h><stdio.h><string.h><stdlib.h>
---- ---------- SELECTION FUNCTION -
function: selectEncoder
Called from the main program to selectlist of options.
Input encoderVars* encoderint kSel
OutputModify : encoder
void selectEncoder(encoderVars*
int selection, k;char error;char *fbPoly, **ffPoly;
----------------- */
an encoder from a specified
pointer to encoder structnumber of input bits to encoder
encoder, int kSel)
if ((kSel >= 1) && (kSel <= 3))
/* kSel=1 rate-1/22 rate-2/3
3 rate-3/4
switch (kSel) {case 1: /* rate-1/2 code */
ffPoly = (char**) calloc(1, sizeof(char*));printf("-----------------------------------------printf("j\n");
printf(" I 1 fbPoly = 23 ffPoly = 35\n");printf(" I 2 fbPoly = 7 ffPoly = 5\n");printf(" I 3 fbPoly = 15 ffPoly = 17\n");printf("I\n");printf("|---------------------------------------
printf ("I select generator polynomials\n");error = 1;while (error)
printf("I >> ");scanf("%d", &selection);if ((selection >= 1) & (selection <= 3))
error = 0;switch (selection)case 1:
fbPoly = "23";ffPoly[0] = "35";break;
case 2:fbPoly = "5";ffPoly[O] = "7";break;
case 3:fbPoly = "15";ffPoly[0] = "17";break;
}; /* switch rate-1/2 *//* if rate-1/2 select ok /
elseprintf("I ** invalid selection **\n");
}; /* while select rate-1/2 error */ratel2initVars(encoder, fbPoly, ffPoly[0]);break; /* break case 1: rate-1/2 */
conv.c 149
SIMULATION CODE
case 2: /* rate-2/3 code */ffPoly = (char**) calloc(2, sizeof(char*));printf("I---------------------------------------printf("I\n");printf("I 1 rate-2/3 -- fbPoly = 23, ffPolylprintf("I\n");printf("I---------------------- ------------printf("I Select generator polynomials\n");error = 1;while (error)
printf(" >>"scanf("%d", &selection);if ((selection >= 1) & (selection <= 1))
error = 0;switch (selection)case 1:
fbPoly = "31";
ffPoly[0] = "27";ffPoly[l] = "35";
break;}; /* switch rate-2/3 */
/ if rate-2/3 select ok */else
printf ("I ** invalid selection **\n");}; /* while select rate-2/3 errork = 2;ratekklInitVars(encoder, fbPoly, ffPoly, k);break; /* break case 2: rate-2/3 */
case 3: /* rate-3/4 code */ffPoly = (char**) calloc(3, sizeof(char"));printf("I---------------------------------printf("\n");printf("| 1 rate-3/4 -- fbPoly = 13 ffPolyl
printf(" \n");
printf("I---------------------------------------printf("I Select generator polynomials\n");error = 1;while (error)
printf("j >>scanf("%d", &selection);if ((selection >= 1) & (selection <= 1))
error = 0;switch (selection)case 1:
fbPoly = "15";ffPoly[O] = "11";ffPoly[l] = "13";ffPoly[2] = "17";
break;}; /* switch rate-3/4 */
};
} /* if rate-3/4 select ok */else
printf("I ** invalid selection **\n");/* while select rate-3/4 error */
--------------- \n");
35, ffPoly2 = 27\n") ;
11, ffPoly2 = 15, ffPoly3 = 17\n");
---------------- \n") ;
k = 3;ratekklInitVars(encoder, fbPoly, ffPoly, k);break; /* break case 3: rate-3/4 */
/* switch rate select */
free(ffPoly);
/* if kSel in correct range */
/ selectEncoder */
/* ------------------ SIMULATION COMMAND FUNCTION ----------------
function: encodeBlock
This function encodes an entire block of bits. This functionis called from the simulation main program.
Input : encoderVars* encoder - pointer to encoder structOutputModify : encoder output contains parity bits
void encodeBlock(encodervars* encoder)
int i, j;char* parityBits;listElement *inputEl, *currEl, *headPtr, *tailPtr;
150
conv.c 151
parityBits = (char*)calloc((*encoder).r, sizeof(char));currEl = (*encoder).output->head; /* access output list elements */inputEl = (*encoder).input->head; /* access input list elements */
for (i=0; i < (*encoder).v; i++) /* set initial state to 0 */(*encoder).state[i] = 0;
while (inputEl != NULL) /* go through entire input list */
intToCharArray(nextState(encoder, inputEl), parityBits, (*encoder).r); /* generate parity bits */for (j=0; j < (*encoder).r; j++) /* add parity bits to output list */
if (currEl == NULL)addLLbits ((*encoder) output, &parityBits(j])
else{
(*currEl).value[0] = parityBitsfj;currEl = (*currEl).next;
};inputEl = (*inputEl).next;
};
/* now delete the rest of the output list, which may have extra elements appendedby terminateEncoder() */
if (currEl != NULL)
headPtr = (*encoder).output->head;tailPtr = (*currEl).prev;(*tailPtr).next = NULL;(*encoder).output->head = currEl;deleteList((*encoder).output); /* only actually deletes elements starting at currEl "/(*encoder).output->head = headPtr;(*encoder).output->tail = tailPtr;
1;
}; /* encodeBlock */
/*
function: terminateEncoder
Generates bits to terminate the encoder to zero state. Itdoes this by using the trellis termination tree, stored inarray terminator[]. The terminating bits are added to the encoderinput list, and the corresponding parity bits are added to theencoder output.
Input encoderVars* encoder - pointer to encoder structOutputModify encoder.input, encoder.output
void terminateEncoder(encoderVars* encoder)
int S, d, bit;char* temp = (char*) calloc((*encoder).k, sizeof(char));
/* need v bits to terminate, there are k bits / branch, so v/k branches.now if v/k is not an integer, then we'll have ceil(v/k) branches andceil(v/k) * k bits. */
for (bit = 0; bit < ((*encoder).v / (*encoder) .k); bit++)
S = charArrayToInt((*encoder).state, (*encoder).v);d = (*encoder).terminator[S];intToCharArray((*encoder) trellis[S] [d] .d, temp, (*encoder) .k);addLLbits((*encoder).input, temp);intToCharArray((*encoder) trellis [S] [d] .p, temp, (*encoder) .r)addLLbits((*encoder).output, temp);intToCharArray((*encoder) trellis [S) [d] .S2, (*encoder) state, (*encoder) .v)
/* printf("term state: %d\n", (*encoder) .trellis[S] [d] .S2); *.
free(temp);
}; /* terminateEncoder */
/* ------------------ INIT/DEALLOCATE FUNCTION -------------------- /
function: duplicateEncoder
This function initializes a second encoder using the parameters
SIMULATION CODE
of a first encoder.
Input encoderVars* encoderlencoderVars* encoder2
OutputModify encoder2
void{
pointer to original encoder structpointer to duplicate encoder struct
duplicateEncoder(encoderVars* encoderl, encoderVars* encoder2)
int state, inp;
(*encoder2).k = (*encoderl).k;CCinitVars(encoder2, (*encoderl).v);for (state = 0; state < pow(2, (*encoder2).v) ; state++)
(*encoder2).terminator[state] = (*encoderl).terminator[state];for (inp = 0; inp < pow(2, (*encoder2).k); inp++)
(*encoder2).trellis[state] [inp] = (*encoderl).trellis[state)[inp];
};
/* duplicateEncoder *
function: ratel2initVars
This function initializefor a rate-1/2 encoder.variables, and uses thegenerate the trellis. Erstored in input arrays fl
Input : encoderVars* en;char fbichar ff1
OutputModify : encoder
void
s convolutional encoder variablesIt allocates memory for all structrate-/n encoder structure toncoder generator functions are alreadybPoly[] and ffPoly[].
coderPoly[]
Poly[}
- pointer to encoder struct- string describing feedback polynomial- string describing feedforwrad polynomial
ratel2initVars(encoderVars* encoder, char fbPoly[], char ffPoly[])
int i, j;char*** forwCoefficient;char* feedbackCoefficient;int numStates;int* done;linkList statelist;twoDSignalPoint S, newS;
/* indices *//* holds feedforward coefficients/* holds feedback coefficients */
/* note: will ffPoly always have the correct degree??(*encoder).k = 1;CCinitVars(encoder,getDegree(ffPoly));
/* rate-l/2 encoder, k = one input */
feedbackCoefficienf = (char*) calloc ((*encoder).v + 1, sizeof(char));setFeedbackG(fbPoly, feedbackCoefficient, (*encoder).v);
forwCoefficient = (char***) calloc ((*encoder).r, sizeof(char**));for (i=0; i < (*encoder).r; i++)
/* allocate memeory *
/* allocate memory */
forwCoefficient[ii = (char**) calloc ((*encoder).k, sizeof(char*));for (j=0; j < (*encoder).k; j++)
forwCoefficient [i] [j] = (char*) calloc ( (*encoder) .v + 1, sizeof (char)); /* (v+l) feedforwardcoefficients */
};setFeedforwG(l, 1, ffPoly, forwCoefficient, (*encoder).v);
numStates = (int)pow(2, (*encoder).v);for (i=0; i < numStates; i++)
for (j=0; j < pow(2, (*encoder).k); j++)ratelnSetBranch(&(*encoder) trellis[i] [j], forwCoefficient, feedbackCoefficient, (*encoder) .v,
(*encoder).r);
llistInitVars(&statelist, 1);S.i = 0; /* set first element in statelist to be zero state, then search backwards *addLLsignal(&statelist, &S);done = (int*) calloc(numStates, sizeof(int));for (i=0; i < numStates; i++)
done[i] = 0;
/* find trellis termination path for each state /while(notEmpty(&statelist))
S = getSignal(&statelist, 1) [0];deleteFirstElement(&statelist);/* now find all states that transition to S */for (i=0; i < numStates; i++)
for (j=0; j < pow(2, (*encoder).k); j++)if (((*encoder).trellis[i} [j].S2 == S.i) && (done[i) == 0))
done[i] = 1;
152
conv.c 153
(*encoder).terminator[i] = j;newS.i = i;addLLsignal(&statelist, &newS);
}; /* now know how to terminate trellis from any state-- use (*encoder) terminator[] as encoder input until zero state reached */
for (i=O; i < (*encoder).r; i++)
for (j=G; j < (*encoder).k; j++)free(forwCoefficient[i] [ji);
free(forwCoefficient[i]);
free~feedbackCoefficient);free(done);
S/* rate1nitVars '/
function: ratekklInitVars
This function initializes convolutional encoder variablesfor a rate-k/(k+l) encoder. Encoder generator functions arealready in input arrays fbPoly[] and ffPoly[] [I
Input encoderVars* encoder - pointer to encoder structchar fbPoly[) - string describing feedback polynomialchar ffPoly[] - string describing feedforwrad polynomial
OutputModify encoder
void ratekklInitVars(encoderVars* encoder, char fbPoly[, char** ffPoly, int k){
int i, j; /* indices */int numStates;
int* done;linkList statelist;twoDSignalPoint S, newS;char*** forwCoefficient; /* holds feedforward coefficients *//* each forwCoefficient[r] [k] [] holds the generator coefficient for
parity bit # r and input bit # k.forwCoefficient[r] [k] [0] corresponds to a 1, andforwCoefficient[r] [k] [v] corresponds to D'v
*/
char* feedbackCoefficient; /* holds feedback coefficients */
(*encoder).k = k; /* rate-k/(k+) encoder *//* note: will ffPoly always have the correct degree?? */CCinitVars(encoder,getDegree(ffPoly[o());
feedbackCoefficient = (char*) calloc ((*encoder) .v + 1, sizeof (char)); /* allocate memeory */setFeedbackG(fbPoly, feedbackCoefficient, (*encoder) .v);
forwCoefficient = (char***) calloc ( (*encoder) .r, sizeof (char**)); /* allocate memory */for (i=0; i < (*encoder).r; i++)
{forwCoefficient [i] = (char**) calloc ((*encoder) .k, sizeof (char*)for (j=O; j < (*encoder).k; j++)
forwCoefficient[i] [jI = (char*) calloc ((*encoder) .v + 1, sizeof (char)); /* (v+l) feedforwardcoefficients */
};for (i=O; i < (*encoder).k; i++)
setFeedforwG(l, (i+l) , ffPoly[i] , forwCoefficient, (*encoder) .v)
numStates = (int)pow(2, (*encoder).v);for (i=O; i < numStates; i++)
for (j=0; j < pow(2, (*encoder).k); j++)ratekklSetBranch(&(*encoder) .trellis i] [j , forwCoefficient, feedbackCoefficient, (*encoder) .v,
(*encoder).k);
llistInitVars(&statelist, 1);
S.i = 0; /* set first element in statelist to be zero state, then search backwards '/addLLsignal(&statelist, &S);done = (int*) calloc(numStates, sizeof(int))for (i=0; i < numStates; i++)
done[i] = 0;
/* find trellis termination path for each state */while(notEmpty(&statelist))
S = getSignal(&statelist, 1) [01;deleteFirstElement(&statelist);/* now find all states that transition to S */for (i=0; i < numStates; i++)
for (j=0; j < pow(2, (*encoder).k); j++)if (((*encoder) .trellis[i] [j] .S2 == S.i) && (done[i] == 0))
done[i] = 1;
154 SIMULATION CODE
(*encoder).terminator[i] = j;newS.i = i;addLLsignal(&statelist, &newS);
};/* now know how to terminate trellis from any state
-- use (*encoder) .terminator[] as encoder input until zero state reached */
for (i=O; i < (*encoder).r; i++)
for (j=O; j < (*encoder).k; j++)free(forwCoefficient[i][jl);
free(forwCoefficient[i]);};free(feedbackCoefficient);free(done);
/* ratekklInitVars */
/*
function: CCinitVars
Initializes class variables for any rate-k/(k+l) convolutionalcode. Assumes only 1 parity bit.
Input encoderVars* encoder - pointer to encoder structint degree - highest degree of generator polynomials
OutputModify encoder
void CCinitvars(encoderVars* encoder, int degree)
int i , j, states, branches;
(*encoder).r = 1; /* only 1 parity bit */(*encoder).v = degree;
(*encoder).output = (linkList*) calloc (1, sizeof(linkList));llistInitVars((*encoder).output, 1);
(*encoder) .state = (char*) calloc((*encoder).v, sizeof (char));for (i=O; i < (*encoder).v; i++)
(*encoder).state[i] = 0;
states = (int)pow(2, (*encoder).v);(*encoder).terminator = (int*) calloc(states, sizeof(int));
branches = (int)pow(2, (*encoder).k);(*encoder) .trellis = (branch**) calloc(states, sizeof (branch*))for (i=O; i < states; i++) f
(*encoder) .trellis[i] = (branch*) calloc(branches, sizeof (branch));for (j=0; j < branches; j++)
(*encoder).trellis[i] ][j.Sl =i;(*encoder).trellis[i] [j].d =j;
};};
/*CCinitvars */
function: freeEncoderVars
Deallocates memory for encoder struct variables.
Input : encoderVars* encoderOutputModify : encoder.
void freeEncoderVars(encoderVars* encoder)
int m, states, branches;
free((*encoder).state);
states = (int)pow(2, (*encoder).v);branches = (int)pow(2, (*encoder).k);for (m=0; m < states; m++)
free((*encoder).trellis[m]);free((*encoder).trellis);
freeList((*encoder).output);
/* freeEncoderVars */
---------------- DISPLAY/DEBUG FUNCTION ---------------------- /
function: showTrellis
Prints the trellis description to the screen.
Input encoderVars* encoder - point to encoder struct variablesOutputModify
void showTrellis(encoderVars* encoder)
int S, d, states, branches;
states = (int)pow(2, (*encoder).v);branches = (int)pow(2, (*encoder).k);printf("Sk-1 dk pk Sk\n");printf( "---- -- ------ ---- \n");for (S=O; S < states; S++)
for (d=O; d < branches; d++)printf("%d %d %d
}; /* showTrellis */
/* ------------------- GENERATOR POLYNOMIAL FUNCTIONS
%d\n", (*encoder).trellis[S] [d].SI,(*encoder).trellis(S} [d].d,(*encoder).trellis[S] [d].p,(*encoder).trellis[S] [d].S2);
function: convertOctal
This function converts the string representation of an octalnumber into binary.
Input char octalChar - octal character, so 0 .. 7char binaryRep[] - 3 cell array to hold binary representation
OutputModify binaryRep
*/void convertOctal(char octalChar, char binaryRep[E)
*binaryRep = 0; /* MSB of octal value */*(binaryRep+l) = 0;*(binaryRep+2) = 0; /* LSB of octal value */if ((octalChar == '1') 1 (octalChar == '3') | (octalChar == '5') I (octalChar == '7'))
*(binaryRep+2) = 1;if ((octalChar == '2') 1 (octalChar == '3') ( (octalChar == '6') (octalChar == '7'))
*(binaryRep+l) = 1;if ((octalChar == '4') 1 (octalChar == '5') (octalChar == '6') (octalChar == '7'))
*binaryRep = 1;
} /* convertOctal */
function: convertString
This function converts the string representation of a generatorpolynomial into a char array.
Input char polyString] - string representation of polynomialchar coeffArray] - array of polynomial coefficients, O's and l's
OutputModify : coeffArray
*/
void convertString(char polyString[E, char coeffArray[], int v)
int i, length;char* temp;
length = strlen(polyString) ; /* numbertemp = (char*) calloc (3*length, sizeof(char)); /* allocfor (i=0; ialength; i++)
convertOctal(polyString[i], &(temp[3*i])); /* converfor (i=0; i<(v+l); i++)
of octal digits */ate max number of binary digits */
t each octal digit, store in temp[]
conv.c 155
156 SIMULATION CODE
coeffArray[i) = temp[i+(3*length-(v+l))]; /* transfer last (v+l) values to coeffArray /
free(temp); /* free up memory used by temp[] V
} convertString /
function: getDegree
This function finds the degree of a generator polynomial.The degree of the polynomial is its highest exponent value.
Input char polyString{) - generator polynomial stringOutput (tempDeg-1) - degree of the polynomialModify
*/int getDegree(char polyString[I)
int length, tempDeg;char* temp = (char*) calloc(3, sizeof(char)); /* temporary variable to hold 3 binary values *
length = strlen(polyString); /* number of octal characters in string */tempDeg = 3* (length-1); /* all octal characters except first have 3 bits *convertOctal(polyString[O], temp); /* convert first octal char into binary *if (temp[0) == 1)
tempDeg += 3; /* first octal char has no leading zeros /
else if (temp[l] == 1)tempDeg += 2; /* first octal char has 1 leading zero *
else if (temp)2] == 1)tempDeg++; /* first octal char has 2 leading zeros *
free(temp);
return (tempDeg-1); /* tempDeg = v+l. Return (tempDeg-1) = v *
/* getDegree */
function: setFeedbackG
This function converts the string representation of the feedbackgenerator polynomial into char array.
Input char polyString] - feedback polynomial stringchar feedbackCoefficient[] - array holding binary coefficientsint v - degree of polynomial
OutputModify feedbackCoefficient
*/void setFeedbackG(char polyString[], char feedbackCoefficient[], int v)
convertString(polyString,&feedbackCoefficient[0], v);
/* show conversion results /S int i, length;
length = strlen(polyString);printf("Feedback -- ");for (i=0;i<length;i++)
printf("%d", (int)polyString[i]);printf(" : ");for (i=0;i<(v+l);i++)
printf("%d", (int)feedbackCoefficient[i});printf ("\n")
S/* setFeedbackG *
function: setFeedforwG
This function converts the string representation of a generatorpolynomial into charean and calculates the degree of the polynomial.
Input : int parityNum - indicate which parity bit the polynomial is forint inputNum - indicate which input bit the polynomial is for
char polyString] - the polynomial stringchar*** forwCoefficient - array holding binary coefficientsint v - degree of polynomail
Output :Modify : forwCoefficient
void setFeedforwG(int parityNum, int inputNum, char polyString[] char*** forwCoefficient, int v)
convertString(polyString, &forwCoefficient [parityNum-1] [inputNum-1 [0], v)/* show conversion results */
S int i, length;
length = strlen(polyString);printf("parity bit %d, input bit %d, G%d%d -- " parityNum, inputNum,for (i=O;i<length;i++)
printf("%d", (int)polyString[i]);printf(" : ");for (i=O;i<(v+l);i++)
printf ("%d", (int) forwCoefficient[parityNum-1] [inputNum-1] [i])printf ("\n")
setFeedforwG /
parityNum, inputNum);
TRELLIS FUNCTIONS --------
function: ratekklSetBranch
This function takes in k input bits and an encoder state andfinds 1 parity bit and the next state. The first delayregister corresponds to state[0] and the last state registercorresponds to state[v-1.
Input : branch* br - pointer to a Trellis branchchar*** ffCoeff - the feed-forward generator polynomialschar* fbCoeff - the feedback generator polynomialint v - degreeint k - number of input bits
Output :Modify : br
void ratekklSetBranch(branch* br, char*** ffCoeff, char* fbCoeff, int v, int k)
int i, numInputs;
char* state = (char*) calloc (v, sizeof(char));char* feedbackCoefficient = fbCoeff;char*** forwCoefficient = ffCoeff;char y;char* inputBits;
inputBits = (char*) calloc(k, sizeof(char));
intToCharArray((*br).Sl, state, v);intToCharArray((*br).d, inputBits, k);
/* y = (last state) + sum (all inputs with generator value 1) */y = state[v-1];for (numInputs=0; numInputs < k; numInputs++)
y = y ^ (forwCoefficient[I] [numInputs] [0] & inputBits[numInputs]);// The carrot ^ is the "xor" operator.
// state[i] = (state[i-11) + (y if feedback generator has term D^(v-i))D^ (v-i))
for
1;
+ sum (all inputs with generator value
(i=(V-1); i>O; i--) {state[i] = state[i-1] ^ (y & feedbackCoefficient[v-i]);for (numInputs=0; numInputs < k; numInputs++)
state[i] = state[i] ^ (forwCoefficient [0] [numInputs] [v-i] & inputBits [numInputs]
// first state = (y if feedback generator has term D'v) + sum (all inputs with generator value Dv)state[0] = (y & feedbackCoefficient[v]);for (numInputs=0; numInputs < k; numInputs++)
state [0] = state [0] ^ (forwCoefficient [0] [numInputs] [v] & inputBits [numInputs]
(*br).S2 = charArrayToInt(state, v);(*br).p = Oxl && y;
free(state);free(inputBits);
} // ratekklSetBranch
function: ratelnSetBranch
conv.c 157
*/
--------- */
SIMULATION CODE
This function takes in 1 input bit and an encoder state and
finds (n-1) parity bits and the next state. The first delayregister corresponds to state[0] and the last state register
corresponds to state[v-1].
Input : brchchin
inOutputModify br
anch*ar*
ar*
tt
brffCoefffbCoeffvr
pointer to a Trellis branch
the feed-forward generator polynomialsthe feedback generator polynomialdegreenumber of parity bits
ratelnSetBranch(branch* br, char*** ffCoeff, char* fbCoeff, int v, int r)
int i, numOutputs;
char stateiTemp; /* temporarily hold statel value; *
char* state = (char*) calloc (v, sizeof(char));char* feedbackCoefficient = fbCoeff;char-*- forwCoefficient = ffCoeff;char input;
char* y;
y = (char*) calloc(r, sizeof(char)); '* y[] - hold r parity bit values */
intToCharArray((*br).S1, state, v);input = ((*br).d == 0) ? 0 : 1;
/* first state = (input bit) + sum (all states i for which feedback has term D^i)statelTemp = input;
for (i=l; i<(v+l); i++)stateiTemp = statelTemp ^ (state [i-1] && feedbackCoefficient [i]
/* output y[j] = sum (all states i for which there is a feedforward term D^i in polynomial j) /for (numOutputs = 0; numOutputs < r; numOutputs++)
y[numOutputs] = statelTemp & forwCoefficient[numOutputs] [0] [0]for (i=l; i<(v+l); i++)
y[numOutputs] = y[numOutputs] ^ (state[i-1] && forwCoefficient[numOutputs] [0] [i);
/* state[i] = state[i-1] */for (i=(v-1); i>0; i--)
state[i] = state[i-1};
/* finally set first state to temporary holding value *state[O] = stateOTemp;
(*br).S2 = charArrayToInt(state, v);(*br).p = charArrayToInt(y, r);
free(state);
/* ratelnsetBranch *
function: nextState
This function transstate. It takes inthe encoder, and re
Input encodervar
listElemenOutput parity bitModify encoder.st
itions a convolutional encoder to the nextput bit(s) from the encoder input, transitionsturns the parity bit generated by the transition.
s* encodert* inputElfrom state
ate
point to encoder structpointer to element with input bitstransition
int nextState(encoderVars* encoder, listElement* inputEl)
int S, d;
/a branch: input = d, parity = p
S ---------- > S2 /
S = charArrayToInt((*encoder).state, (*encoder).v);d = charArrayToInt((*inputEl) value, (*(*encoder) input) .valueLength);/* index 0 of value contains MSB, index (valueLength-1) contains LSB */intToCharArray((*encoder) trellis[S] [d].S2, (*encoder).state, (*encoder).v) ; /* update encoder state
return (*encoder).trellis[S] [d].p;
/* nextState */
158
void
puncture.h 159
puncture.h
/*
file: puncture.h
This header file contains variable and function definitions ofpuncturing objects.
/* type definitions *typedef struct punctureVarsStruct
int numInputs;int punctureLength;int currIndex;
char** puncturePattern;
linkList** input;
linkList* output;} puncturevars;
typedef struct unPunctureVarsStructint numOutputs;
int punctureLength;int currIndex;char-- puncturePattern;
linkList* input;linkList* output;
} unPunctureVars;
/* simulation command functions */void punctureBlock(punctureVars* puncturer)void unpunctureBlock(unPunctureVars* unpuncturer);
/* init/deallocate functions */void twoPunctureInitVars(punctureVars* puncturer, char patternl)], char pattern2[]);void threePunctureInitVars(punctureVars* puncturer, char patternl[], char pattern2[], char pattern3[]);void unPunctureInitVars(unPunctureVars* unpunc, punctureVars* punc);void freePunctureVars (punctureVars* puncturer);void freeUnpunctureVars (unPunctureVars* unpuncturer)
/* other functions */char* stringTochar(char theString[], int punctureLength);char punctureBits (punctureVars* puncturer, listElement** inputEl)
SIMULATION CODE
puncture.c
file: puncture.c
This source file contains code for puncture functions.
#include "linkedlist.h"#include "puncture.h"
#include <stdio.h>#include <stdlib.h>#include <string.h>
/* ------------------------ SIMULATION COMMAND FUNCTIONS ----
function: punctureBlock
This function punctures bits at the input linked lists. Thepuncture pattern is stored in the puncturer struct. Thisfunction is called from the main simulation program.
Input : punctureVars* puncturer - pointer to puncturer struct
OutputModify : output linked list
void punctureBlock(punctureVars* puncturer)
char result;int i, j, len;listElement **inputEl, *currEl;
(*puncturer).currIndex = 0;currEl = (*puncturer).output->head;inputEl = (listElement**) calloc((*puncturer).numInputs, sizeof(listElement*));for (j=O; j < (*puncturer).numInputs; j++)
inputEl[j} = (*puncturer).input[j]->head;
lenfor
= getNumElements((*puncturer).input[});(i=0; i < len; i++)
result = punctureBits(puncturer, inputEl);/* result > 1 means that all bits were punctured */
if (result <= 1)it (currEL == NULL)
addLLbits((*puncturer).output, &result);else
(*currEl).value[() = result;currEl = (*currEl).next;
};
for (j=S; j < (*puncturer).numInputs; j++)inputEl[j] = (*inputEl[j]).next;
free(inputEl);
I /* punctureBlock
function: unpunctureBlock
This function unpuncturers the input linked list intomultiple output linked lists. The unpuncture patternthe same as the puncture pattern and is stored in theunpuncturer struct. This function is called from theprogram.
Input : unPunctureVars* unpuncturer
OutputModify : output linked lists
is
main
160
unpunctureBlock (unPunctureVars* unpuncturer)
int i;twoDSignalPoint LLR, puncturedLLR;
listElement **outputEl, *currEl;char done;
outputEl = (listElement**) calloc((*unpuncturer) numOutputs, sizeof(listElement*)for (i=0; i < (*unpuncturer).numOutputs; i++)
outputEl[i] = (&(*unpuncturer) output [i])->head;currEl = (*unpuncturer).input->head;
puncturedLLR.i = 0;puncturedLLR.q = 0;(*unpuncturer).currIndex = 0;
/* The puncture structure could be:
currIndex 0123
10000010
When currIndex = 3 and (*unpuncturer) input is empty, we still need tounpuncturer the last LLR, which will be 0 for both bits. So the whileloop condition must take this case into account.
alternatively currIndex 012 If blockSize=1024, we will be atindex=1 when (*unpuncturer).input
100 runs out of elements.010001
The condition to end is if the input list is already empty and we are stillrequesting an input element.
*/
done = 0;while (done == 0)
for (i = 0; i < (*unpuncturer).numOutputs; i++)
LLR = puncturedLLR;/* at most one bit will be not punctured... no more than one */if ( (*unpuncturer) .puncturePattern[i] [(*unpuncturer) currIndex] == 1)
if (currEl == NULL)done = 1;
else
LLR = (*currEl).signal[0];currEl = (*currEl).next;
};if (done == 0)
if (outputElti] == NULL)addLLsignal(&(*unpuncturer).output[ii, &LLR);
else
*(outputEl[i]->signal) = LLR;outputEl[i] = outputEl[i]->next;
1; /* if */
}; /* for */(*unpuncturer) .currIndex = ((*unpuncturer) .currIndex + 1) % (*unpuncturer) .punctureLength;
currIndex */
); /* while */
free(outputEl);
} /* unpunctureBlock */
------------------------- INIT/DEALLOCATE FUNCTION ------------
function: twoPunctureInitVars
Initializes class variables and sets up puncturing pattern fortwo input linked lists.
Input : punctureVars* puncturer - pointer to puncture structchar patternl[] - string specifying first puchar pattern2[] - string specifying second p
/* update
ncture patternuncture pattern
void
puncture.c 161
------ */
162 SIMULATION CODE
Output :Modify : puncturer
void twoPunctureInitVars(punctureVars* puncturer, char patternl[], char pattern2[])
f(*puncturer).numInputs = 2;
(*puncturer).punctureLength = strlen(patternl);(*puncturer).currIndex = 0;(*puncturer).puncturePattern = (char**) calloc (2, sizeof(char*));(*puncturer) .puncturePattern[0] = stringTochar(patternl, (*puncturer) .punctureLength)(*puncturer) .puncturePattern[1] = stringTochar(pattern2, (*puncturer) .punctureLength)
(*puncturer).input = (linkList**) calloc(2, sizeof(linkList*));
(*puncturer).output = (linkList*) calloc(l, sizeof(linkList));llistInitVars((*puncturer).output, 1);
} /* twoPunctureInitVars */
function: twoPunctureInitVars
Initializes class variables and sets up puncturing pattern fortwo input linked lists.
Input : punctureVars* puncturer - pointer to puncture structchar patterni[] - string specifying first puncture patternchar pattern2[l] - string specifying second puncture patternchar pattern3[] - string specifying third puncture pattern
Output :Modify : puncturer
*/void threePunctureInitVars(punctureVars* puncturer, char patternl[], char pattern2[], char pattern3 []
(*puncturer).numInputs = 3;
(*puncturer).punctureLength = strlen(patternl);(*puncturer).currIndex = 0;(*puncturer).puncturePattern = (char**) calloc (3, sizeof(char*));(*puncturer) .puncturePattern[0] = stringTochar(patternl, (*puncturer) .punctureLength)
(*puncturer) puncturePatternl] = stringTochar(pattern2, (*puncturer) .punctureLength)
(*puncturer) .puncturePattern[2] = stringTochar(pattern3, (*puncturer) .punctureLength)
(*puncturer).input = (linkList**) calloc(3, sizeof(linkList*));
(*puncturer).output = (linkList*) calloc(l, sizeof(linkList));llistInitVars((*puncturer).output, 1);
/* threePunctureInitVars */
function: freePunctureInitVars
Deallocates memory for puncture struct variables.
Input : punctureVars* puncturer - pointer to puncture structOutputModify : puncturer
void freePunctureVars(punctureVars* puncturer)
int i;
for (i=0; i < (*puncturer).numInputs; i++)free((*puncturer).puncturePattern[i]);
free((*puncturer).puncturePattern);freeList((*puncturer).output);
S/* freePunctureVars */
function: unPunctureInitVars
Initializes variables in unpuncturer struct by using variablevalues in puncture struct.
puncture.c 163
Input unPunctureVars* unpunc - pointer to unpuncturer structpunctureVars* punc - pointer to puncturer struct
OutputModify unpunc
*/void unPunctureInitVars(unPunctureVars* unpunc, punctureVars* punc)
int i;
(*unpunc).numOutputs = (*punc).numInputs;
(*unpunc).punctureLength = (*punc).punctureLength;(*unpunc).currIndex = 0;(*unpunc) .puncturePattern = (char**) calloc( (*punc) numInputs, sizeof(char*)(*unpunc) output = (linkList*) calloc( (*unpunc) .numOutputs, sizeof(linkList)
for (i=0; i < (*punc).numInputs; i++) I(*unpunc) .puncturePatterntil = (char*) calloc ((*unpunc) punctureLength, sizeof (char));(*unpunc) .puncturePatternfi] = (*punc) .puncturePattern[i]
llistInitVars(&(*unpunc).outputti], 1);};
/* unPunctureInitVars */
/*
function: freeUnpunctureInitVars
Deallocates memory for unpuncturer struct variables.
Input unPunctureVars* unpuncturer - pointer to unpuncturer structOutputModify unpuncturer
void freeUnpunctureVars(unPunctureVars* unpuncturer)
int i;
/* this routine causes problems -- don't use for now */for (i=0; i < (*unpuncturer).numOutputs; i++)
free((*unpuncturer).puncturePattern[i]);
freeList(&(*unpuncturer).output[ii);
};free((*unpuncturer).puncturePattern);
/* freeUnpunctureVars */
* -------- ---------- ----- OTHER FUNCTIONS ----------------------- /
/*
function: stringTochar
Moves a string of O's and l's into a char array of sizepunctureLength.
Input char theString[] - input puncture pattern stringint punctureLength - size of array
Output array containing O's and l'sModify
*/char* stringTochar(char theString[H, int punctureLength)
char* charPtr = (char*) calloc(punctureLength, sizeof (char));int i;
for (i=O; i<punctureLength; i++)charPtr[i] = (theStringi] == '0') ? 0 : 1; /* decide if the character is a 0 */
return charPtr;
/* stringTochar */
I function: punctureBits
SIMULATION CODE
Performs bit puncturing according to specified pattern.
Input punctureVars* puncturer - pointer to puncturer struct
listElement** inputEl - pointers to input elements
Output value of the puncturing operation (0 or 1)Modify
*/char punctureBits(punctureVars* puncturer, listElement** inputEl)
int index, i;char temp;
char pout;
pout = 0;index = (*puncturer).currIndex;
(*puncturer) currIndex = ((*puncturer) currIndex + 1) % (*puncturer) .punctureLength;
*/
temp = (*puncturer).puncturePattern[0][index];
for (i=1; i < (*puncturer).numInputs; i++)
temp = temp II (*puncturer) .puncturePattern[i] [index];if (temp) /* not all of the bits are punctured */
pout = *(inputEl[0]->value) * (*puncturer).puncturePattern[0][index];for (i=1; i < (*puncturer).numInputs; i++)
pout = pout (* (inputEl[i) ->value) * (*puncturer) .puncturePattern[i[ [index]);
elsepout = 2;
return pout;
/* punctureBits */
/* update currIndex
164
mapper.h 165
mapper.h
file: mapper.h
This header file contains variable and function definitionsfor bit mappers and symbol mappers.
#include <stdio.h>
/* type definitions *typedef struct bitMapVarsStruct
int b;char* pattern;char* symbolBits;int numUncoded, numSys, numParity;
} bitMapVars;
typedef struct oneDsymbolMapVarsStructint M;double* symbols;char** code;double Eav;
} oneDsymbolMapVars;
typedef struct twoDsymbolMapVarsStructint M;
twoDSignalPoint* symbols;char** code;double Eav;
} twoDsymbolMapVars;
typedef struct twoDsignalMapVarsStructbitMapVars bitMapper;twoDsymbolMapVars symbolMapper;
linkList* inputU;
linkList* inputS;linkList* inputP;linkList* output;
} twoDsignalMapvars;
/* selection functions /void selectBitMapper(bitMapVars* map);void selectSignalMapper(twoDsignalMapVars* map);
/* simulation command function */void mapBlock(twoDsignalMapVars* signalMap);
/* init/deallocate functions */void bitMapInitVars(bitMapVars* bitMapper, char* pattern);void normalMappingInitVars(twoDsignalMapVars* signalMapper, int numHalfBits)void QAMgcSignalMapInitVars(twoDsignalMapVars* signalMapper, int InumGBI, int InumGB2, int QnumGB1, int QnumGB2);void freeBitMapVars(bitMapVars* bitMap);void freeTwoDsymbolMapVars(twoDsymbolMapVars* map);void freeTwoDsignalMapVars(twoDsignalMapVars* signalMap);
/* display/debug functions */void showoneDmapping(oneDsymbolMapVars* mapper);void showTwoDmapping(twoDsymbolMapVars* mapper, FILE* fp);
/* bit mapper functions */void getNumBits(bitMapVars* bitMap);
/* symbol mapper functions */void PAMgcSignalSet(oneDsymbolMapVars* mapper, int numdrayBitsl, int numGrayBits2);void QAMSignalSet(twoDsymbolMapVars* symbolMapper, oneDsymbolMapVars tempI, oneDsymbolMapVars tempQ);double* createPAMlevels(int M);twoDSignalPoint formTwoDsymbol (twoDsignalMapVars* signalMapper)double findOneDsymbol(char* bits, oneDsymbolMapVars* map);twoDSignalPoint findTwoDsymbol(char* bits, twoDsymbolMapVars* map);
/* gray code functions */linkList* makeNbitGC(int numBits);linkList* concatCodes(linkList *MSBlist, linkList *LSBlist)char** createGrayCode(int numMSB, int numLSB, int M);
SIMULATION CODE
mapper.c
file: mapper.c
This
#include#include#include#include
#include#include#include#include
source file contains code for the signal mapper.
"general.h""linkedlist.h""source.h""mapper.h"
<stdlib.h><stdio.h><string.h>
<math.h>
SELECTION FUNCTION
function: selectBitMapper
This function is called from the main simulation program toselect a bit map pattern for uncoded simulations.
Input : bitMapVars* map - pointer to bit mapperOutputModify map
void selectBitMapper(bitMapVars* map)
int selection;char error;char *pattern;
printf(" .----------------- -------------
printf("\n");printf("| 1 ss 4-pt uncodecprintf("I 2 ssss 16-pt\n");
printf("I 3 ssssss 64-pt\n");printf("I 4 ssssssss 256-pt\n");printf("I\n");
printf("I------------------------------printf("I select bit map pattern\n");
error = 1;while (error)
printf("j >> );scanf("%d", &selection);if ((selection >= 1) & (selection
I
----- \n");
simulation\n");
----------------
<= 4))
error = 0;switch (selection)case 1:
pattern = "ss";break;
case 2:pattern = "ssss";break;
case 3:pattern = "ssssss";break;
case 4:pattern = "ssssssss";break;
; /* switch selection */
bitMapInitVars(map, pattern);
/* if selection ok */else
printf("| ** invalid selection **\n");/* while error
S/* selectBitMapper */
166
d
function: selectSignalMapper
This function is called from the main simulation program toselect a signal mapping.
Input : twoDsignalMapVars* mapOutputModify map
*/void selectSignalMapper(twoDsignalMapVars* map)
int half, pts, Igcl, Igc2, Qgcl, Qgc2;int selection;char error;
pts = (int)pow(2, (*map).bitMapper.b);half = (int) ((*map).bitMapper.b/2);
printf("-------------------------------------printf("I\n");printf("| 1 normal bit labeling (00, 01, 1
printf(" j 2 full gray labeling in each dimeprintf(" 3 concatenated gray labeling inprintf ("\n");printf("-------------------------------------error = 1;while (error)
printf("I Select labeling scheme\n"printf(I >> ");scanf("%d", &selection);if ((selection >= 1) & (selection <= 3))
{
-------------------- \n"
0, ll)\n");nsion (00, 01, 11, 10)\n");each dimension\n");
error = 0;switch (selection)case 1:
normalMappingInitVars(map, half);break;
case 2:Igcl = half;Igc2 = 0;Qgcl = half;Qgc2 = 0;
QAMgcSignalMapInitVars(map, Igcl, Igc2, Qgcl, Qgc2);break;
case 3:printf(" ------------------------------------------printf("| * number of upper bits in each dimensionprintf("I \n");
printf(I ENTER:\n");
printf(" I Number of upper bits in I dimension\n");printf("I >> ");scanf("%d", &Igcl);
Igc2 = half - Igcl;printf(" I Number of lower bits in I dimension = %d\printf("I \n");printf(I Number of upper bits in Q dimension\n");printf ("I >> );scanf("%d", Qgcl);Qgc2 = half - Qgcl;
printf(" I Number of lower bits in Q dimension = %d\/* Igcl, Qgc2 must each be <= half /if (Igcl > half)
printf("I ** I parameters invalid: Il > %derror = 1;
};if (Qgcl > half) {
printf("I ** Q parameterserror = 1;
};if (error == 0)
QAMgcSignalMapInitVars(map,printf("\n");
break;.
------------- \n");must be <= %d **", half);
n", Igc2)
n", Qgc2);
\n", half);
invalid: Ql > %d **\n", half);
Igcl, Igc2, Qgcl, Qgc2);
};}; /* switch selection /
/* if input ok /else
printf(" invalid selection **\n");}; /* while error *
} /* selectSignalmapper *
SIMULATION COMMAND FUNCTION
mapper.c 167
168 SIMULATION CODE
function: mapslock
The function is called from the main simulation program to
map a block of bits to two-D symbols.
Input twoDsignalMapVars* signalMapperOutputModify signalMapper output linked list
void mapBlock(twoDsignalMapVars* signalMapper)
twoDSignalPoint symbol;listElement *currEl, *Uhead, *Shead, *Phead;
/* function formTwoDsymbol() changes the Iso we temporarily store the real ones I
Shead = (*signalMapper).inputS->head;if ((*signalMapper).inputU != NULL)
Uhead = (*signalMapper).inputU->head;if ((*signalMapper).inputP != NULL)
Phead = (*signalMapper).inputP->head;
ead pointer of each input linked list,ere */
/* no trellis coded modulation *
uncoded simulation no parity bits */
currEl = (*signalMapper).output->head;
while ((*signalMapper).inputS->head 1= NULL)symbol = formTwoDsymbol(signalMapper);if (currEl == NULL)
addLLsignal((*signalMapper).output, &symbol);else
(*currEl).signal[0] = symbol;currEl = (*currEl).next;
};
/* function formTwoDsymbol() changes the head
so we restore the real ones here */(*signalMapper).inputS->head = Shead;if ((*signalMapper).inputU != NULL)
(*signalMapper).inputU->head = Uhead;if ((*signalMapper).inputP != NULL)
(*signalMapper).inputP->head = Phead;
}; /* mapBlock *
pointer of each input linked list,
INIT/DEALLOCATE FUNCTIONS
function: bitM
Initialize bit
Input : DitMachar
OutputModify : bitMa
apInitVars
mapper variables.
pvars* DitMapper -pattern[] -
pper
pointer to nit mapper structarray containing bit map pattern
void bitMapInitVars(bitMapVars* bitMapper, char pattern[])
int i;
(*bitMapper).b = strlen(pattern);(*bitMapper).pattern = (char*) calloc((*bitMapper).b, sizeof(char));for (i=0; i < (*bitMapper).b; i++)
(*bitMapper).pattern[i] = pattern[i];(*bitMapper).symbolBits = (char*) calloc((*bitMapper).b, sizeof(char));getNumBits(bitMapper);
} /* bitMapInitVars *
function: freeBitMapVars
Deallocate memory for bit mapper struct variables.
Input bitMapvars* bitMap - pointer to bit mapper struct
OutputModify bitMap
void freeBitMapVars(bitMapVars* bitMap)
free((*bitMap).pattern);
free((*bitMap).symbolBits);
/* freeBitMapVars */
function: freeTwoDsymbolMapVars
Deallocates memory for symbol mapper struct variables
Input twoDsymbolMapVars* map - pointer to symbol mapper structOutputModify map
void freeTwoDsymbolMapVars(twoDsymbolMapVars* map)
int i;
free((*map).symbols);for (i=O; i < (*map).M; i++)
free((*map).code[i]);free((*map).code);
} /* freeTwoDsymbolMapVars */
function: normalMappingInitVars
Input : twoDsymbolMapVars* signalMapperOutputModify : map
pointer to symbol mapper struct
void normalMappingInitVars(twoDsignalMapVars* signalMapper, int numHalfBits)
int i;
oneDsymbolMapVars tempI, tempQ;
tempI.M = (int)pow(2,numHalfBits);
templ.symbols = createPAMlevels(tempI.M);tempI.code = (char**)calloc(tempI.M, sizeof(char*));tempQ.M = (int)pow(2,numHalfBits);
tempQ.symbols = createPAMlevels(tempQ.M);tempQ.code = (char**)calloc(tempQ.M, sizeof(char*));for (i=0; i < tempI.M; i++)
temp{.code[i] = (char*)callocnumalfgits, sizeofchar)tempQ.code[i] = (char*)calloc(numHalfBits, sizeof(char));intToCharArrayi, temp.code[i], numHalfBits)intToCharArray(i, tempQ.code[i], numHalfBits);
QAMSignalSet(&(*signalMapper).symbolMapper, tempI, tempQ);
/* these might not be initialized in case of uncoded simulation */(*signalMapper).inputU = NULL;(*signalMapper).inputP = NULL;
(*signalMapper) output = (linkList*) calloc(l, sizeof(linkList));llistInitVars((*signalMapper).output, 1);
} /* normalMappingInitVars */
/*
function: QAMgcSignalMapInitVars
This function initializes the signal mapper by usingconcatenated gray labels with a square-QAM signal set.
Input : twoDsignalMapVars* signalMapper - pointer to signal mapper structint InumGB1 - upper gray bits in I channelint InumGB2 - lower gray bits in I channelint QnumGB1 - upper gray bits in Q channelint QnumGB2 - lower gray bits in Q channel
Output :Modify : signalMapper
mapper.c 169
170 SIMULATION CODE
I
void QAMgcSignalMapInitVars(twoDsignalMapVars* signalMapper, int InumGB1, int InumGB2, int QnumGB, int QnumGB2)
oneDsymbolMapVars tempI, tempQ;
PAMgcSignalSet(&tempI, InumGB1, InumGB2);PAMgcSignalSet(&tempQ, QnumGB1, QnumGB2);QAMSignalSet(&(*signalMapper).symbolMapper, tempI, tempQ);
/* these might not be initialized in case of uncoded simulation *(*signalMapper).inputU = NULL;
(*signalMapper).inputP = NULL;
(*signalMapper).output = (linkList*) calloc(l, sizeof(linkList));llistInitVars((*signalMapper).output, 1);
/* QAMgcInitVars *
function: freeTwoDsignalMapVars
Deallocates memeory for variables in signal mapper struct.
Input twoDsignalMapVars* signalMap
OutputModify : signalMap
*/-.void freeTwoDsignalMapVars(twoDsignalMapVars* signalMap)
freeBitMapVars(&(*signalMap).bitMapper);freeTwoDsymbolMapVars(&(*signalMap).symbolMapper);freeList((*signalMap).output);
/* --------------------- DISPLAY/DEBUG FUNCTIONS ---------------------- *
function: showOneDmapping
Shows points and labels for one-dimensional signal sets.
Input : oneDsymbolMapVars* mapper - pointer to signal mapper structOutputModify
*/
void showOneDmapping(oneDsymbolMapVars* mapper)
int i, j, b;
b = (int) (loglO((*mapper).M)/loglo(2));printf(" (amplitude, label) : ");for (i=O; i < (*mapper).M; i++)
printf("(%g,", (*mapper).symbols[i]);for (j=S; j < b; j++)
printf("%d", (int) (*mapper).code[i] j]);printf(") ");
};printf ("\n")
/* showOneDmapping *
function: showTwoDmapping
Shows points and labels for two-dimensional signal sets. Iffp is NULL, then prints to screen. Otherwise prints to file fp.
Input : twoDsymbolMapVars* mapper - pointer to symbol mapper structFILE* fp - pointer to output file
OutputModify : contents of file fp
void showTwoDmapping(twoDsymbolMapVars* mapper, FILE* fp)
int i, j, b;
mapper.c 171
b = (int) (logl0((*mapper).M)/log10(2));if (fp != NULL)
fprintf(fp, "[point, label]for (i=0; i < (*mapper).M; i++)
fprintf(fp, "[(%gg), ", (*mapper) .symbols[i] .i, (*mapper) .symbols[i] .q);for (j=0; j b; j++)
fprintf(fp, "%d", (int) (*mapper) code [i] [j]);fprintf(fp, " "
};fprintf (fp, "\n");
else
printf(" [point, label]for (i=0; i < (*mapper).M; i++)
printf(" [(%g,%g) , ", (*mapper) .symbols[i .i, (*mapper) symbols[i .q)for (j=0; j < b; j++)
printf("%d", (int) (*mapper) .code[i [i);printf("]
};printf ("\n")
}; /* showTwoDmapping /
/* ------- --- ---- BIT MAPPER FUNCTIONS ---------------------- /
function: getNumBits
Find the number of uncoded, systematic, and parity bits persymbol.
Input bitMapVars* bitMap - pointer to bit mapper structOutputModify *bitMap
*/
void getNumBits(bitMapVars* bitMap)
int i;
(*bitMap).numParity = 0;(*bitMap).numSys = 0;(*bitMap).numUncoded = 0;
for (i=0; i < (*bitMap).b; i++) /* initialize symbolPattern[] */if ((*bitMap).pattern[i] == 'u')
(*bitMap).numUncoded += 1; /* count number of uncoded bits per symbol */else if ((*bitMap).pattern[i] == 's')
(*bitMap).numSys += 1; /* count number of systematic bits */else
(*bitMap).numParity += 1; /* count number of parity bits per symbol */
1; /* getNumBits */
/* --- -------- SYMBOL MAPPER FUNCTIONS ----------------------
function: PAMgcSignalSet
Forms a one-dimensional signal set with odd-valued pointscentered evenly about zero.
Input oneDsymbolMapVars* PAMmapper - pointer to symbol map structint numGrayBitsl - upper gray bits for labelsint numGrayBits2 - lower gray bits for labels
OutputModify *PAMmapper
*/void PAMgcSignalSet(oneDsymbolMapVars* PAMmapper, int numGrayBitsl, int numGrayBits2)
(*PAMmapper) .M = (int)pow(2, (numCrayBitsl + numGrayBits2));(*PAMmapper) symbols = createPAMlevels( (*PAMmapper) M);
SIMULATION CODE
(*PAMmapper) code = createGrayCode(numGrayBitsl, numGrayBits2, (*PAMmapper) .M)
/* PAMgcSignalSet */
function: QAMSignalSet
Forms a two-dimensional square signal set with odd-valued pointscentered evenly about zero in each direction.
Input twoDsymbolMapVars* symbolMapper - pointer to symbol map structoneDsymbolMapVars tempI - 1-D signal set for I channeloneDsymbolMapVars tempQ - 1-D signal set for Q channel
OutputModify *symbolMapper
void QAMSignalSet(twoDsymbolMapVars* symbolMapper, oneDsymbolMapVars tempI, oneDsymbolMapVars tempQ)
int L1, L2, L;
int i, j, k, pos;
(*symbolMapper).Eav = 0;(*symbolMapper).M = tempI.M * tempQ.M;(*symbolMapper) code = (char**) calloc ( (*symbolMapper) M, sizeof (char*))(*symbolMapper) symbols = (twoDSignalPoint*) calloc( (*symbolMapper) .M, sizeof (twoDSignalPoint)L = (int) (loglO((*symbolMapper).M)/loglO(2));Ll = (int) (logb (tempI.M)/logl (2));L2 = (int)(log10(tempQ.M)/log10(2));for (i=0; i < tempI.M; i++)
for (j=O; j < tempQ.M; j++)
(*symbolMapper).code[i*tempQ.M + j) = (char*) calloc(L, sizeof(char));
(*symbolMapper).symbols[i*tempQ.M + j .i = tempI.symbols[i];(*symbolMapper) .symbols [i*tempQ.M + j.q = tempQ.symbols[j];
(*symbolMapper).Eav += (sqr(tempI.symbols[i}) + sqr(tempQ.symbols[j]));
pos = 0;for (k=O; k < Ll; k++)
(*symbolMapper).code[i*tempQ.M + ji [pos++] = tempI.code[i] [k];for (k=O; k < L2; k++)
(*symbolMapper).code[i*tempQ.M + ji[pos++] = tempQ.code[j] [ki;
};};(*symbolMapper).Eav /= (*symbolMapper).M;
/* QAMSignalSet */
function: findOneDsymbol
Finds the signal point in a one-D signal set with bit labelmatching the input bits.
Input : char bits[] - array containing input bitsoneDsymbolMapVars* map - signal set points and labels
Output : one-dimensional pointModify
double findOneDsymbol(char bits[], oneDsymbolMapVars* map)
int i, j, componentBits;char* tempElement; .char done=O, bitsEqual;
componentBits = (int) (log)((*map).M)/logl(2));i = -1;
while (!done) /* keep on looking for the match */
i++;tempElement = (*map).code[i]; /* get next Gray code element */bitsEqual = 1;for (j=O; j<componentBits; j++) /* check each bit for the match */
bitsEqual = bitsEqual && (tempElementji == bits[j]);done = bitsEqual;
};
return (*map).symbols[i];
} /* findOneDsymbol */
/* return the matched PAM level */
172
function: findTwoDsymbol
Finds the point in a two-D signal set that has the same bit
label as the input bit array.
Input char bits[] - input bit arraytwoDsymbolMapVars* map - two-D points and labels
Output two-D point
Modify
*/twoDSignalPoint findTwoDsymbol(char bits[], twoDsymbolMapVars* map)
int i, j, componentBits;char* tempElement;char done=O, bitsEqual;
componentBits = (int) (loglO((*map) .M)/loglO(2));i = -1;
while (!done) /* keep on looking for the match */
i++;
tempElement = (*map).code[i]; /* get next Gray code elementbitsEqual = 1;for (j=O; j<componentBits; j++) /* check each bit for the match *
bitsEqual = bitsEqual && (tempElement[j] == bits[j});
done = bitsEqual;
return (*map).symbols[i];
} /* findTwoDsymbol */
/* return the matched PAM level */
function: createPAMlevels
Creates an array of odd-valued points centered evenly aboutzero.
Input int M - number of total pointsOutput double PAMlevels[] - arrayModify
*/
double* createPAMlevels(int M){
int i;
double *PAMlevels = (double*) calloc(M, sizeof(double));levels */
for (i=O; i<(M/2); i++) /
{PAMlevels[i) = (double) (-l*(M-1) + 2*i)PAMlevels[M-1-i] = -l*PAMlevels[i]; /* the po
* allocate memory to hold PAM
generate the M PAM levels */
/* the negative (M/2) PAM levels *sitive (M/2) PAM levels */
};
return PAMlevels;
}; /* createPAMlevels */
function: formTwoDsymbol
Takes bits from the input linked lists and maps them to asignal point.
Input twoDsignalMapVars* signalMapper - pointer to signal mapperOutputModify output linked list
*/twoDSignalPoint formTwoDsymbol(twoDsignalMapVars* signalMapper)
bitMapVars* map = &(*signalMapper) .bitMapper;int i;
for (i=0; i < (*map).b; i++)if ((*map).pattern[i == 'u')
(*map) .symbolBits[i] = (*signalMapper) .inputU->head->value [0](*signalMapper).inputU->head = (*signalMapper) .inputU->head->next;
else if ((*map).pattern[i] == s')(*map) .symbolBits[i] = (*signalMapper) .inputS->head->value [0];(*signalMapper) inputS->head = (*signalMapper) .inputS->head->next;
mapper.c 173
SIMULATION CODE
else
(*map).symbolBits[i] = (*signalMapper) .inputP->head->value [0;(*signalMapper).inputP->head = (*signalMapper).inputP->head->next;
1;
return findTwoDsymbol ((*map) symbolBits, &(*signalMapper) symbolMapper)
/* formTwoDsymbol */
- - GRAY CODE FUNCTIONS ------------- */
function: makeNbitGC
Make a full gray code with the specified number of bits. Gray codescan be formed by a recursive algorithm starting with the 1-bit code0,1. In general, a n-bit gray code can be formed from the (n-l)-bitcode by prepending a '0' to the (n-l)-bit code, followed by prependinga 'l' to the (n-l)-bit code in reverse order.0,1 -- > 0 + (0,I) and 1 + (1,0) = 00,01,11,1000,01,11,10 -- > 0 + (00,01,11,10) and 1 + (10,11,01,00)
= 000,001,011,010,110,111,101,100and so on...
Input int numBits - number of bits in the full gray code.Output *theList - the linked list of gray codesModify
*/linkList* makeNbitGC(int numBits)
linkList *theList = (linkList*) calloc(1, sizeof(linkList)); /*linkList *tempList; /* temporary variableslistElement *tempElement;char *tempchar;int i;
llistInitVars(theList, numBits);
if (numBits == 1)
} /*else
allocate memory for the gray code */*/
make a 2 element linked list with just */* 0 and 1 */
recurse -- first make a (n-l)-bit gray code */
/* base case of recursive algorithm */
tempchar = (char*) calloc(l, sizeof(char));*tempchar = 0; /*
addLLbits(theList, tempchar);*tempchar = 1;
addLLbits(theList, tempchar);free(tempchar);numBits = 1 */
tempList = makeNbitGC(numBits-1); /*
tempcnar = (cnar-) caliocnumBits, sizeot(cnar));tempElement = getElement(tempList, 1); /* now prepend the 0 to the (n-l)-bit gray code */tempchar[0] = 0; /* the prepended 0 */while (tempElement != NULL)
for (i=l; i<numBits; i++) /* copy the remaining (n-1) bits */tempchar[i] = (*tempElement).valueli-1];
addLLbits(theList, tempchar); /* add this n-bit code to the final linked list '/tempElement = (*tempElement).next;
};/* get the last element of the (n-i)-bit gray code -- now prepend the 1 */tempElement = getElement(tempList, (int)pow(2, (*tempList) .valueLength));tempchar[O] = 1; /* the prepended 1 */while (tempElement != NULL)
{for (i=l; i<numBits; i++) /* copy the remaining (n-1) bits */
tempchar[i] = (*tempElement).value[i-1];addLLbits(theList, tempchar); /* add this n-bit code to the final linked list */tempElement = (*tempElement).prev; /* go in reverse order */
deleteList(tempList);free(tempchar);
}; /* numBits >1 *
return theList;
/* makeNbitGC */
/* free up temporary memory allocations */
174
function: concatCodes
Concatenate two separate codes contained in separate linked listsThe elements of the second code are appended to each element ofthe first code.Ex.: 0,1 concatenated with 00,01,11,10 becomes
000,001,011,010,100,101,111,110, which is not the same asa 3-bit full gray code.
Input linkList *MSBlist - the first list of codeslinkList *LSBlist - the second list of codes
Output :theList - the list for the concatenated codeModify
*/linkList* concatCodes(linkList *MSBlist, linkList *LSBlist)
linkList *theList = (linkList*) calloc(l, sizeof(linkList));
listElement *tempEll, *tempEl2;int b = (*MSBlist) .valueLength+(*LSBlist) valuEchar *tempchar = (char*) calloc(b, sizeof(charint j;
llistInitVars(theList, b);tempEll = getElement(MSBlist, 1);while (tempEll != NULL)
* allocate memory for concat. list
/* temporary variables */?Length;
/* get first element of first list *//* continue concat until thru first list */
for (j=0; j<(*MSBlist) .valueLength; j++) /* get bits from first codetempchar~j] = (*tempEll).value[j];
tempEl2 = getElement(LSBlist, 1); - /while (tempEl2 != NULL)
for (j=0; j<(*LSBlist).valueLength; j++)tempchar[(*MSBlist).valueLength + j]
addLLbits(theList, tempchar);
tempEl2 = (*tempEl2).next;
}; /* go through LSB gray code list */
tempEll = (*tempEll).next;
}; /* go through MSB gray code list */
deleteList(MSBlist);
deleteList(LSBlist);
return theList;
} /* concatCodes */
go through entire second code */
/* get bits from second code */= (*tempEl2).value[j];
/* add the new code to the final list
go to next element in first code */
function: createGrayCode
Determine whether to create a full gray code (numMSB=O or numLSB=O) ora 2-level concatenated Gray code. The final Gray code is stored in alinked list
Input int numMSB - number of bits in the upper level of the 2-level gray codeint numLSB - number of bits in the lower level of the 2-level gray code
Output : two-D array containing the gray codeModify
*/char** createGrayCode(int numMSB, int numLSB, int M)
linkList *MSBGC, *LSBGC, *finalGC;char** retArray = (char**) calloc(M, sizeof(char*))listElement *element;int i=O, j;
if (numMSB == 0)finalGC = makeNbitGC(numLSB);
else if (numLSB == 0)finalGC = makeNbitGC(numMSB);
else
/* make a full (b/2)-bit gray code */
/* make a full (b/2)-bit gray code */
MSBGC = makeNbitGC(numMSB); /* gray code for upper bits */LSBGC = makeNbitGC(numLSB); /* gray code for lower bits */finalGC = concatCodes(MSBGC,LSBGC); /* concatenate the two codes */
element = (*finalGC).head;while (element != NULL)
retArray[i] = (char*) calloc(numMSB+numLSB, sizeof(char))for (j=O; j < (*finalGC) .valueLength; j++)
retArray[i] [j] = (*element) .value[j];
mapper.c 175
SIMULATION CODE
i++;
element = (*element).next;
1;
return retArray;
S/* createGrayCode */
/* return the final gray code *
176
channel.h 177
channel.h
file: channel.h
This header file contains definitions for simulation functionsrelated to sending signals through channels, includingAWGN channels.
*/
/* type definitions */typedef struct channelVarsStruct
double nvariance;
linkList* input;linkList* output;
} channelVars;
/* simulation command function s/
void sendAWGNblock(channelVars* channel);
/* init/deallocate functions */void channelInitVars(channelVars* channel);void freeChannelvars(channelVars* channel);
/* other functions */twoDSignalPoint sendAWGNpoint(channelVars* channel, twoDSignalPoint origPt);void Gauss32(double*, double*);
178 SIMULATION CODE
channel.c
file: channel.c
This source file contains code for simulation functionsrelated to sending signals through channels, includingAWGN channels.
*/
#include "linkedlist.h"#include "channel.h"
#include <math.h>#include <stdio.h>#include <stdlib.h>
SIMULATION COMMAND FUNCTION
function: sendAWGNblock
This function takes all signal points from the channel input,sends them through an AWGN channel, and adds them to the channeloutput list. This function is called from the main simulationprogram
void sendAWGNblock(channelVars* channel)
int i, len;twoDSignalPoint point;listElement *inputEl, *currEl;
inputEl = (*channel).input->head;currEl = (*channel).output->head;
len = getNumElements((*channel).input);for (i=O; i < len; i++)
point = sendAWGNpoint(channel, (*inputEl).signal[0));if (currEl == NULL)
addLLsignal((*channel).output, &point);else
(*currEl).signal[0) = point;currEl = (*currEl).next;
inputEl = (*inputEl).next;
1;
/ senoAWUnoIock -/
/* ----------------------- INIT/DEALLOCATE FUNCTIONS
function: channelInitVars
This function initializes channel variables.
void channelInitVars(channelVars* channel)
(*channel).n variance = 1;
(*channel).output = (linkList*) calloc (1,llistInitVars((*channel).output, 1);
sizeof(linkList));
S/* channelInitVars */
function: freechannelVars
This function deallocates channel variable memory.
}
void freeChannelVars(channelVars* channel)
freeList((*channel).output);
/* freeChannelvars */
OTHER FUNCTIONS ---
function: sendAWGNpoint
This function takes a 2D signal point fromsends it through an AWGN channel, and adds
output list.
the channel input,it to the channel
*/twoDSignalPoint sendAWGNpoint(channelVars* channel, twoDSignalPoint origPt)
twoDSignalPoint point;
Gauss32(&(point.i), &(point.q));point.i *= sqrt((*channel).n variance);point.i origPt.i;point.q sqrt((*channel).nvariance);
point.q += origPt.q;
return point;
/* sendAWGNpoint */
Function: Guass32
Description: Generate two Gaussian
32 bit arithmetic.
*/void Gauss32(double *x, double *y)f
random variables. Assumes
long temp;double ul,u2,r,theta,PI=3.1415;
temp = rand();
/* rand) gen an integer between 0 and RANDMAX '/temp = temp % RAND MAX;/* modulus operation to make sure value of TEMP is less than
Ox7fffffff - which is the greatest value of a LONG data typeul = (double) temp / (double) RANDMAX;/* now convert range to 0 <= ul <1 'temp = rand));
temp = temp % RAND MAX;u2 = (double) temp / (double) RAND MAX;
/* ul must be double because log) takes a double as an argumentr = sqrt(-2.0 * log(l.0-ul)); /* 0 <= r < sqrt(-2*ln(l/RAND M
theta = u2 * 2
t */AX)) */
/* with 0 < (1-ul) <= 1 (no zero) */.0 * PI; /* 0 <= theta < 2pi */
*x = or * cos(theta));*y = or * sin(theta));
}/* Gauss32 */
channel.c 179
180 SIMULATION CODE
demod.h
file: demod.h
This header file contains definitions for functions that generatesoft-values from received signal points for input to the MAP decoder.
/* type definitions */typedef struct demodulatorVarsStruct
linkList* input;linkList* outputS;linkList* outputP;
} demodulatorVars;
/* simulation command function */void demodulateTwoDBlock(demodulatorVars* dem, twoDsignalMapVars* mapper, double noisevar);void decode uncoded(linkList* decodedLL, twoDsignalMapVars* mapper, linkList* points);
/* init/deallocate functions */void demodulatorInitVars(demodulatorVars* dem);void freeDemodulatorVars(demodulatorVars* dem);
/* other functions */double calcBitLLR(twoDSignalPoint point, int pos, twoDsymbolMapVars symbolMapper, double noisevar)
demod.c 181
demod.c
file: demod.c
This source file contains code for generating soft-values fromreceived signal points for input to the MAP decoder.
#include "general.h"#include "linkedlist.h"#include "mapper.h"#include "demod.h"
#include <stdlib.h>#include <stdio.h>#include <math.h>
- --------------------- SIMULATION COMMAND FUNCTIONS ----------------------
function: demodulateTwuDBlock
This function calculates the LLR of each bit in the received
symbols.
Input demodulatorVars* dem - pointer to demodulator structtwoDsignalMapVars* mapper - pointer to signal mapperdouble noise var - channel noise variance
OutputModify dem
void demodulateTwoDBlock(demodulatorVars* dem, twoDsignalMapVars* mapper, double noise var)
int i, j, num;twoDSignalPoint LLR;listElement *outP, *outS, *ElPtr;
outP = (*dem).outputP->head;
outS = (*dem).outputS->head;ElPtr = (*dem).input->head;
num = getNumElements((*dem).input);for (i=O; i < num; i++)
for (j=O; j < (*mapper).bitMapper.b; j++)if ((*mapper).bitMapper.pattern[j] != 'u')
LLR.i = calcBitLLR((*ElPtr).signal[0], j, (*mapper).symbolMapper, noise var);LLR.q = LLR.i;
if ((*mapper).bitMapper.pattern[j] == 's')
if (outS == NULL)addLLsignal((*dem).outputS, &LLR);
else
(*outS).signal[0] = LLR;outS = (*outS).next;
else if ((*mapper).bitMapper.pattern[j] == 'p')if (outP == NULL)
addLLsignal((*dem).outputP, &LLR);else
(*outP).signal[0] = LLR;outP = (*outP).next;
};}; /* if s or p */
}; /* for loop: bits in a symbol */
ElPtr = (*ElPtr).next;
1;
/* demodulateTwoDBlock */
function: decode_uncoded
This function is used with uncoded QAM to get the upper bound
182 SIMULATION CODE
for the QAM bit error rate. It chooses the constellation pointnearest to the received symbol as the point that was sent.There is no struct associated with this operation.
Input linkList* decodedLL - list where decoded bits will be stored
twoDsignalMapVars* mapper - pointer to signal mapperlinkList* points - list of symbol at output of channel
OutputModify decodedLL
void decode uncoded(linkList* decodedLL, twoDsignalMapVars* mapper, linkList* points)
int i, min;double minD, D;twoDSignalPoint signal;
deleteList(decodedLL);
while (notEmpty(points))
signal = getSignal(points, 1) [0];deleteFirstElement(points);min = 0;minD = sqrt(sqr(signal.i - (*mapper).symbolMapper.symbols[0) .i) +
sqr(signal.q - (*mapper).symbolMapper.symbols [0].q))for (i=l; i < (*mapper).symbolMapper.M; i++)
D = sqrt(sqr(signal.i - (*mapper).symbolMapper.symbols[i] .i) +sqr(signal.q - (*mapper) .symbolMapper.symbols[i] .q))
if (D < minD)
minD = D;
min = i;
};
for (i=0; i < (*mapper).bitMapper.b; i++)addLLbits(decodedLL, &(*mapper).symbolMapper.code[min [i]);
};
/* decodeuncoded */
/* --------------------- INIT/DEALLOCATE FUNCTIONS ----------------------
/*
function: demodulatorInitVars
Initializes demodulator struct variables.
Input demodulatorVars* dem - pointer to demodulator structOutputModify dem
void demodulatorInitVars(demodulatorVars* dem)
(*dem).outputS = (linkList*) calloc(1, sizeof(linkList));llistInitVars((*dem).outputS, 1); /* linked list of real values, not bits */
(*dem).outputP = (linkList*) calloc(, sizeof(linkList));llistInitVars((*dem).outputP, 1); /* linked list of real values, not bits *
}/* demodulatorInitVars */
function: freeDemodulatorVars
Deallocates memory for demodulator variables.
Input demodulatorVars* dem - pointer to demodulator sturctOutput
Modify *dem
void freeDemodulatorVars(demodulatorVars* dem)
freeList((*dem).outputP);
freeList((*dem).outputS);
/* freeDemodulatorVars */
---- OTHER FUNCTIONS --------
function: calcBitLLR
This function calculates the log-likehood ratio for a bit ina received symbol.
Input : twoDSignalPoint point - received pointint pos - bit to calculate LLR fortwoDsymbolMapVars symbolMapper - symbol mapper structdouble noise var - channel noise variance
Output LLR for the specified bitModify
double calcBitLLR(twoDSignalPoint point, int pos, twoDsymbolMapVars symbolMapper,
int i, half;double metricl=0, metricl=O;double maxlog = 40;double result;
half = (int)floor(loglO(symbolMapper.M)/logl1(2)for (i=0; i < symbolMapper.M; i++)
if (symbolMapper.code[i] [pos] == 0)
if (pos < half)metricO += exp(-1.0/(2*noisevar)
else
else
double noise var)
/2); /* number of bits per dimension in QAM */
* sqr~point.i - symbolMapper.symbols[i].i));
metricO += exp(-l.0/(2*noise var) * sqr(point.q - symbolMapper.symbols[i].q));
if (pos < half)metricl += exp(-1.0/(2*noisevar) * sqr(point.i - symbolMapper.symbols[i].i));
elsemetricl += exp(-l.O/(2*noise var) * sqr(point.q - symbolMapper.symbols[i}.q));
limit magnitude of LLR so it won't cause computational errors later on *(fabs(metricl) < exp(-l*maxlog))metricO = exp(-l * maxlog);
(fabs(metricl) < exp(-l*maxlog))metricl = exp(-l * max_log);
result = log(metricl/metric);if (fabs(result) > maxlog)
result = (result/fabs(result)) * maxlog;
return result;
} /* calcBitLLR */
demod.c 183
if
if
184 SIMULATION CODE
decoder.h
file: decoder.h
/* type definitions */
typedef struct MAPdecoderVarsStructint blockSize, numStates, numInputs;double explimit;double ***gamma; /* gamma [k] [dk] [pk] / probA[k] [dk] */double **alpha, **beta; /* alpha[k] [m], beta[k] [m] */
char **bitValue;branch** trellis;
/* twoDsymbolMapVars* symbolMapper; */
linkList* inputS;linkList* inputP;linkList* inputA;
linkList* output_Dprob;linkList* output extrinsic;
MAPdecoderVars;
/* simulation command function */void doMAPdecoding(MAPdecoderVars* decoder);void doFastRl2MAPdecoding(MAPdecoderVars* decoder);
/* init/deallocate functions */void MAPdecoderInitVars(MAPdecoderVars* decoder, encoderVars* convCode, int blockSize, twoDsymbolMapVars*symbolMapper);void freeMAPDecoderVars(MAPdecoderVars* decoder);
/* display/debug functions */float showErrorPercentage(linkList* origBits, linkList* decodedBits)
/* general rate-k/(k+l) RSCC MAP decoder functions */void calc probS(MAPdecoderVars* decoder);void init probA(MAPdecoderVars* decoder, int factor);void calc gamma(MAPdecoderVars* decoder);void calcalpha(MAPdecoderVars* decoder);void calcbeta(MAPdecoderVars* decoder);void initAB(MAPdecoderVars* decoder, char terminated);void initB usingA(MAPdecoderVars* decoder);void probDecision(linkList *input, linkList* output);
/* fast rate-1/2 RSCC MAP decoder functions */void calcgammaR12(MAPdecoderVars* decoder);void calcalphaRl2(MAPdecoderVars* decoder);void calc_betaRl2(MAPdecoderVars* decoder);void signoecision)1inkList* input, iinkList* output);
decoder.c 185
decoder.c
/*
file: decoder.c
This source file contains code for turbo decoding, MAP decoding,and the log variants of MAP decoding.
*/
#include "general.h"#include "linkedlist.h"#include "interleave.h"#include "conv.h"#include "mapper.h"#include "demod.h"#include "decoder.h"
#include <math.h>#include <stdio.h>#include <stdlib.h>
/* ------------------------- SIMULATION COMMAND FUNCTION ------ ---
S-------------------------- INIT/DEALLOCATE FUNCTIONS ------ --
/*
function: MAPdecoderInitVars
This function initializes variables used for MAP decoding.
Input : MAPdecodervars* decoder - pointer to MAP structencoderVars* convCode - convolutional code to decodeint blockSize - number of k-bit inputstwoDsymbolMapVars* symbolMapper - pointer to symbol mapper struct
Output :Modify : *decoder
*/
void MAPdecoderInitVars(MAPdecoderVars* decoder, encoderVars* convCode, int blockSize, twoDsymbolMapVars* symbolMapper)
int k, i;
(*decoder).blockSize = blockSize;(*decoder) .numStates = (int)pow(2, (*convCode) .v);(*decoder) numInputs = (int)pow(2, (*convCode) .k);(*decoder).trellis = (*convCode).trellis;
/* (*decoder).symbolMapper = symbolMapper; */(*decoder).explimit = 40;
(*decoder) .gamma = (double***) calloc (blockSize+l, sizeof (double**))
/* betaEkE [m]beta[0] Em] not usedbeta[l... blockSize] [m] hold decoding infobeta[blockSize] [m] holds initialization info
(*decoder) beta = (double**) calloc (blockSize+1, sizeof (double*));
/* alpha~k] [m]alpha[E] [m] hold initialization infoalpha[l... blockSize] [m] hold decoding info
*/(*decoder) alpha = (double**) calloc (blockSize+1, sizeof (double*))
for (k=O; k <= blockSize; k++)(*decoder) .alpha[k] = (double*) calloc( (*decoder) numStates, sizeof(double));(*decoder).beta[k = (double*) calloc ((*decoder) .numStates, sizeof (double));
(*decoder) .gamma[k] = (double") calloc((*decoder) numInputs, sizeof (double*));for (i=; i < (*decoder) numInputs; i++)
(*decoder) gamma[k] il = (double*) calloc (2, sizeof (double));/* assume that all encoders are rate-k/(k+l) -- only 1 parity bit */
/* bitValue[2^k] [k] holds the bit values for an integerfor k=2:
E0] [ = 00El] [] = 01[2] [ = 10
186 SIMULATION CODE
[3] [1 = 11
(*decoder).bitValue = (char**) calloc((*decoder).numInputs, sizeof(char*));
for (i=0; i (*decoder).numInputs; i++)
(*decoder).bitValue[i] = (char*) calloc((*convCode).k, sizeof(char));intToCharArray(i, (*decoder).bitValue[i], (*convCode).k);
1;
/* if (*convCode).k = 1, then it is a rate-1/2 code, and we usedoFastRl2decodeBlockO, which uses bit LLR's. Thus, we only needthe MAP module output list to have valueLength = 1.
if (*convCode).k > 1, then it is a rate-k/(k+l) code, and we use
doMAPdecoding(), which uses a posteriori probabilities. Thus, weneed the MAP module output list to have valueLength = 2^ *
k = ((*convCode).k == 1) ? 1 : (*decoder).numInputs;
(*decoder).output_Dprob = (linkList*) calloc (1, sizeof(linkList));llistInitVars((*decoder).output_Dprob, k);
(*decoder).output-extrinsic = (linkList*) calloc (1, sizeof(linkList));llistInitVars((*decoder).output_extrinsic, k);
/* MAPdecoderInitVars */
function: freeMAPDecoderVars
Deallocates memory for decoder struct variables
Input MAPdecodervars* decoderOutputModify *decoder
*/
void freeMAPDecoderVars(MAPdecoderVars* decoder)
int k, i;
for (k=O; k < (*decoder).blockSize; k++)
free((*decoder).alpha[k]);free((*decoder).beta[k]);for (i=0; i < (*decoder).numInputs; i++)
free((*decoder).gamma[k] [i]);free((*decoder).gamma[k]);
1;for (i=0; i < (*decoder).numInputs; i++)
free((*decoder).bitValue[i]);free((*decoder).alpha);free((*decoder).beta);free((*decoder).gamma);free((*decoder).bitValue);deleteList((*decoder).output_Dprob);free((*decoder).output Dprob);deleteList((*decoder).outputextrinsic);free((adecoder).ourput extrinsic);
} /* freeMAPDecoderVars */
/* ------------------------- DISPLAY/DEBUG FUNCTION ------------------ /
/*
function: showErrorPercentage
This function compares the values of two linked lists andcalculates the percentage of values that are different.
Input : linkList* origBits - list of original bitslinkList* decodedBits - list of decoded bits
Output % of values that are differentModify
*/float showErrorPercentage(linkList* origBits, linkList* decodedBits)
float per = 0.0;int i, num;listElement *currEll, *currEl2;
num = getNumElements(origBits);currEll = origBits->head;currE12 = decodedBits->head;
decoder.c 187
for (i=0; i < num; i++)
if (* (*currEll) value = (*currEl2) value)per++;
currEll = (*currEll).next;currE12 = (*currE12).next;
};
return (per / (float)num);
/* showErrorPercentage */
/* ---- -------- RATE-K/ (K+1) RSCC MAP DECODER FUNCTIONS ------------------ /
/*
function: calc_probS
Takes an input linked list with bit LLR's and changes thosevalues to Pr(b=O) = 1/(1 + exp(LLR)), and Pr(b=1) =exp(LLR) / (1 + exp(LLR)) . The LLR value is held in an inputelement's signal[].i variable. After Pr(b=O) is calculatedit is stored in signal[] .i, and Pr(b=l) is stored in signal[] .q
LLR is limited to -40 and 40, so probabilities range from1 / (1 + e^40) = e^(-40) to about 1.
Input MAPdecoderVars* decoder - pointer to decoder structOutputModify *decoder
void calc_probS(MAPdecoderVars* decoder)
int k, i, num;
double expval;listElement* currS;
currS = (*decoder).inputS->head;num = getNumElements((*decoder) inputS);for (k=0; k , num; k++)
for (i=0; i < (*(*decoder).inputS).valueLength; i++)
expval = exp((*currS).signal[i].i);(*currS) signal [i].i = 1.0 / (1 + exp val);(*currS) signal [i].q = exp val * (*currS) .signal [ii.i;
};currS =(*currS).next;
} /* calc_probS */
function: calcgamma
This function calculates part of the gamma parameter used in MAPI decoding. gamma][][1 is a three dimensional array. TheI first index is the time index k, the second index is theI input bits integer value i, and the third index is the parityI bit p. If Ak is the LLR associated with the input (systematic)I bits, and Bk is the LLR for the parity bit, then
input i gamma [k] [i] [p]S(k-1) ---------- > S(k) = Pr(Ak) * Pr(Bk)
parity p
In the actual BCJR algorithm, gamma = Pr(AkI...) Pr(Bkj ...) Pr(dk=i).Pr(dk=i) is "a priori" information supplied by the other MAPmodule, and is the only probability in gamma that changes witheach iteration. Thus, the part of gamma calculated here is thepart that does not change between iterations.
Input : MAPdecoderVars* decoderOutputModify
*/void calcgamma(MAPdecoderVars* decoder)
kint k, i, b, bits;
SIMULATION CODE
double exp_val;twoDSignalPoint probP;listElement *currElementS, *currElementP;
bits = (int) (loglO((*decoder).numInputs)/ioglO(2));
currElementS = (*decoder).inputS->head;currElementP = (*decoder).inputP->head;for (k=l; k <= (*decoder).blockSize; k++)
exp val = exp((*currElementP).signal[0].i);probP.i = 1.0 / (1 + exp_val); /* pk = 0 */
probP.q = probP.i * exp val; /* pk = 1 *//* ranges from e^(-40) to 1 *//* ranges from e^(-40) to 1 */
for (i=0; i < (*decoder).numInputs; i++)
(*decoder).gamma[k][i] [0] = probPi;(*decoder).gamma[k] [i] [1] = probP.q;
for (b=0; b < bits; b++)
/*
in currElementS, there are valueLength LLR valuessignal[o] corresponds to the MSB LLR, andsignal[valueLenght-1] corresponds to the LSB LLR
This ordering is consistent with ordering used by intToCharArray,so bitValue[i] [b] corresponds to (*currElementS).signal[b].i
(*decoder).gamma[k][i][0] ((*decoder).bitValue[i][b] ==(*currElementS).signal[b.q;
(*decoder).gamma1k][i][1] *= ((*decoder).bitValue[i][bi ==
(*currElemenmtS) signal[b].q;
if ((*decoder).gamma[k][i][01 < (exp(-l* (*decoder).exp_(*decoder).gamma[k] [i] [0] = exp(-l* (*decoder).exp_
if ((*decoder).gamma[k [i][1} < (exp(-l* (*decoder).exp_(*decoder).gamma[k] [i [1] = exp(-l* (*decoder).exp_
};
currElementS = (*currElementS).next;
currElementP = (*currElementP).next;
}; /* for k */
/* calc-gamma s/
0) ? (*currElementS).signal[b].i
0) ? (*currElementS).signal[b].i
limit)limit);limit)))limit)
function: init_probA
This function initializes an empty "a priori" linked listby filling it with equiprobable values if we're decodingrate-k/(k+l), and with O's if we're decoding rate-1/2.The former uses actual "a priori" probabilities, and thelatter uses bit log-likehood ratios.
Input : MAPdecoderVars* decoder - pointer to decoder structint factor - determines if using "a priori" or LLR
OutputModify : decoder->inputA
void init probA(MAPdecoderVars* decoder, int factor)
int k, i, num, vlen;twoDSignalPoint* equiprob;listElement* currEl;
currEl = (*decoder).inputA->head;
equiprob = (twoDSignalPoint*) calloc ((*decoder).numInputs, sizeof(twoDSignalPoint));for (i=0; i < (*decoder).numInputs; i++)
equiprob i].i = 1.0 / (*decoder).numInputs * factor;/* factor is either 0 or 1, depending on if we're using
doMAPdecoding) or doFastR12MAPdecoding(). The former usesprobabilities (factor = 1) and the latter uses LLR's (factor = 0).
num = getNumElements((*decoder).inputS);vlen = (factor == 0) ? 1 : (*decoder).numInputs;(*(*decoder).inputA).valueLength = vlen;for (k=0; k < num; k++)
if (currEl == NULL)addLLsignal((*decoder).inputA, equiprob);
else
for (i=0; i < vlen; i++)
188
{
decoder.c 189
(*currEl) signal[i] .i = equiprob[i] .i;currEl = currEl->next;
};
free(equiprob);
4 /* initprobA */
function: calcalpha
This function calculates all the alpha parameters needed inMAP decoding.
Input MAPdecoderVars* decoder - pointer to decoder structOutputModify decoder->alpha
*/void calc alpha()MAPdecoderVars* decoder)
int k, dk, Sk; 7* alpha indices -- alpha[k] [Sk) */int Skprev; /* summation indices */int pk;double sum;listElement* probA;
probA = (*decoder).inputA->head;
for (k-l; k - (*decoder).blockSize; k++)
for (Sk = 0; Sk < (*decoder) numStates; Sk++)(*decoder).alphaik] [Sk] = 0;
/* now loop through branches: each trellis[Sk-1] [dk] is a branch */for (Sk_prev = 0; Skprev < (*decoder) .numStates; Skprev++)
for (dk = 0; dk < (*decoder) numlnputs; dk++)
Sk = (*decoder).trellis[Sk_prev] [dk].S2; /* branch: Sk-l --> Sk, input dk */pk = (*decoder) trellis [Sk prev] [dk].p;(*decoder) .alpha[k] [Sk] += (*decoder) gamma (k] [dk] [pk * (*probA) .signal [dk].i *
(*decoder).alpha[k-l1] [Sk prev;}; /* for Sk-prev *
/* alpha[k] [Sk] is supposed to equal numerator[k] [Sk] / denominator[k]however, because denominator[k] is the same for every state at a time k,it acts like a constant for a time k and divides out in the finalcalculation of L(dk). However, this means that alpha will accumulatefaster with each k, so it'll need to be normalized */
sum = 0;for (Sk=0; Sk < (*decoder) .numStates; Sk++)
sum += (*decoder).alpha[k][Sk];
for (Sk=0; Sk a (-decoder) .numStates; Sk++)
(*decoder).alpha[k] [Sk] /= sum;/* if ((*decoder) .alpha[k] [Sk] < exp(-l*(*decoder) explimit))
(*decoder) .alphalk] [Sk] = exp(-l* (*decoder) explimit);*/
};
probA = (*probA).next;
}; /* for k */
} /* calcalpha */
function: calc_beta
This function calculates all the beta values used in MAPdecoding
Input MAPdecoderVars* decoder - pointer to MAP decoder structOutputModify decoder->beta
*/
void calcbeta()MAPdecoderVars* decoder)
int k, Sk; /* beta indices -- beta[k] [Sk] */int dkfuture, Sk-future; /* summation indices */int pk;double sum;listElement* probA;
SIMULATION CODE
probA = (* (*decoder).inputA).tail;for (k = ((*decoder).blockSize - 1); k >= 1; k--)
for (Sk = 0; Sk < (*decoder).numStates; Sk++)(*decoder).beta[k] [Sk] = 0;
/* loop through branches: each trellis[Sk-1] [dk] is a branch */for (Sk = 0; Sk < (*decoder).numStates; Sk++)
for (dkfuture = 0; dk-future < (*decoder).numInputs; dkfuture++)
pk = (*decoder).trellis[Sk] [dk future.p;Skfuture = (*decoder).trellis[Sk]]dkfuture].S2;(*decoder) .beta[k] [Sk] += (*decoder) .gamma[k+1] [dk future] [pk] (*probA) .signal dk future] .i
(*decoder).beta[k+l][Skfuture];
}; /* for dk+l */
sumfor
for
= 0;(Sk=O; Sk < (*decoder).numStates; Sk++)sum += (*decoder).beta]k]]Sk];(Sk=O; Sk < (*decoder).numStates; Sk++)
(*decoder).beta[k] [Sk] /= sum;if ((*decoder).beta[k] [Sk < exp(-l*(*decoder).explimit))
(*decoder).beta[k] [Sk] = exp(-l* (*decoder).explimit);
};probA = (*probA).prev;
}; /* for k */
} /* calcbeta */
function: doMAPdecoding
This function performs MAP decoding.
Input : MAPdecoderVars* decoder - pointerOutputModify *decoder
doMAPdecoding(MAPdecoderVars* decoder)
int k, Skprev, Sk, dk;int pk, b, bits;double *lambda;double probS, sum;twoDSignalPoint *prob;listElement *currElementA, *currElementS,
to decoder struct
*currOutA, *currOutD;
lambda = (double*) calloc((*decoder).numInputs, sizeof(double));prob = (twoDSignalPoint*) calloc((*decoder).numInputs, sizeof(twoDSignalPoint));
/* note: for some reason,bits = (int) (log((*decoder).numInputs) / log(2));
does not give the right number, butbits = (int) (logoO((-decoder).numonputs) / logiu(2));
does.
bits = (int) (logl0((*decoder).numInputs) / logiO(2));calcalpha(decoder);if ((*decoder).beta[(*decoder).blockSize][0] != 1) /* trellis
initB usingA(decoder);calc_beta(decoder);
currElementA = (* (*decoder).inputA).head;currElementS = (*(*decoder).inputS).head;currOutD = (* (*decoder).output_Dprob).head;currOutA = (* (*decoder).output_extrinsic).head;
for (k=i; k <= (*decoder).blockSize; k++)
for (dk=O; dk < (*decoder).numInputs; dk++)lambda[dk] = 0;
for (Skprev=O; Sk prev < (*decoder).numStates; Skprev++)for (dk=O; dk < (*decoder).numInputs; dk++)
is not terminated */
Sk = (*decoder).trellis[Skprev] [dk].S2;pk = (*decoder).trellis[Skprev] [dk].p;lambda[dk] += (*decoder). gamma[k] [dk [pk] * (*currElementA) .signal[dk] .i * (*decoder). alpha[k-
1] [Sk prev] * (*decoder).beta[k] [Sk;};
sum = 0;
for (dk=O; dk < (*decoder).numInputs; dk++)sum += lambda[dk];
for (dk=O; dk < (*decoder).numInputs; dk++)
190
void{
f
};if
prob[dk].i = lambda[dk] / sum;/* limit magnitude of probability. prob < 1, so log(prob) < 0if (fabs(log(prob[dk .i)) > (*decoder) .exp_limit)
prob[dk.i = exp(-l (*decoder).explimit);
(currOutD == NULL)
addLLsignal((*decoder).outputDprob, prob);if currOut is NULL, it will remain NULL throughout this MAPdecoding round, and bit probabilities will be added to theoutput list */
else
for (dk=0; dk < (*decoder).numInputs; dk++)(*currOutD).signal[dk].i = prob[dk].i;
currOutD = (*currOutD).next;};
for (dk=0; dk < (*decoder).numInputs; dk++)prob[dk].i /= (*currElementA).signal[dk].i;
for (dk=0; dk < (*decoder).numInputs; dk++)for (b=0; b < bits; b++)
probS = ((*decoder) .bitValue[dk] [b] == 0)(*currElementS).signal[b}.q;
prob[dkl.i /= probS;};
sumfor
for
? (*currElementS).signal[b].i :
= 0;(dk=; dk < (*decoder).numInputs; dk++)
sum += prob[dk].i;(dk=0; dk < (*decoder).numInputs; dk++)
prob[dk].i /= sum;/* limit magnitude of probability. prob < 1, so log(prob) <0 /if (fabs(log(prob[dk].i)) > (*decoder).exp_limit)
prob[dk].i = exp(-l * (*decoder).explimit);
if (currOutA != NULL)(*currOutA).signal[dk].i = prob[dk].i;
if (currOutA == NULL)
addLLsignal((*decoder).output extrinsic, prob);else
currOutA = (*currOutA).next;
currElementA = (*currElementA).next;currElementS = (*currElementS).next;
};
free(lambda);free(prob);
} /* doMAPdecoding */
function: initAB
Initializes alpha and beta parameters
Input : MAPdecoderVars* decoder -char terminated -
OutputModify decoder.alpha, decoder.beta
used in MAP decoding.
pointer to MAP decoder varswhether trellis is terminated
void initAB(MAPdecoderVars* decoder, char terminated)
int m;double equiprob;
(*decoder).alpha[0] [0] = 1;for (m = 1; m < (*decoder).numStates; m++)
(*decoder).alpha[0] [m] = 0;
equiprob = 1.0 / (*decoder).numStates;(*decoder) .beta[(*decoder) .blockSize] [0] = (terminated) ? 1 : equiprob;for (m = 1; m < (*decoder).numStates; m++)
(*decoder) .beta[(*decoder) .blockSize] [m] = (terminated) ? 0 : equiprob;
/* initAB */
/*
Ifunction: initB usingA
decoder.c 191
192 SIMULATION CODE
Initializes beta parameters in the case that the trellis isnot terminated.
Input MAPdecoderVars* decoder - pointer to decoderOutputModify (*decoder).beta
*/void initBusingA(MAPdecoderVars* decoder)
int m;
for (m=O; m < (*decoder).numStates; m++)(*decoder) .beta[(*decoder) .blockSize] [m] = (*decoder) .alpha[(*decoder) .blockSize [m];
/* initB_usingA *
/*,
function: probDecision
Choose maximum a posteriori probability.
Input linkList* input - list of the a posteriori probabilitieslinkList* output - list of the decoded bits
OutputModify output list
*/void probDecision(linkList* input, linkList* output)
int i, numEl, bits, j, max;
char b;listElement *currEl, *currOut;
/* in this case, valueLength holds the number of array indices, which foroutput probabilities is already numInputs */
bits = (int) (logl ((*input).valueLength) / log1O(2));numEl = getNumElements(input);currEl = (*input).head;currOut = (*output).head;
for (i=O; i < numEl; i++)
max = 0;/* look for highest probability */
for (j = 1; j < (*input).valueLength; j++)if ((*currEl).signal[j].i > (*currEl).signal[max].i)
max = j;/* add bits for dk with highest probability to output list *
for (j=0; j < bits; j++)
b = (max >> (bits-1 - j)) & Oxl;if (currOut == NULL)
addLLbits(output, &b);else
(*currdut).value[o] = b;currOut = (*currOut).next;
};};
currEl = (*currEl).next;
1;
/* probDecision /
/* ------------------- FAST RATE-1/2 RSCC MAP DECODER FUNCTIONS ------------------ */
/*
function: doFastRl2MAPdecoding
This function performs fast MAP decoding of rate-1/2 RSCC.
Input MAPdecoderVars* decoder - pointer to decoder structOutputModify *decoder
void doFastRl2MAPdecoding(MAPdecoderVars* decoder)
int k, Skprev, Sk;int pk;
double lambdal, lambdao;double Ls, La;twoDSignalPoint LLR, Z;const double infinite = le308;double probA[2];listElement *currElementA, *currElementS, *currOutA, *currOutD;
calcalphaRl2(decoder);if ((*decoder) .beta[(*decoder) blockSize] [0] != 1)
initB usingA(decoder);calcbetaRi2(decoder);
currOutD = (* (*decoder).output_Dprob).head;currOutA = (* (*decoder) outputextrinsic) .head;currElementA = getElement (*decoder) inputA, 1)currElementS = getElement (*decoder) inputS, 1)
for (k=l; k <= (*decoder).blockSize; k++)
probA[0] = 1.0 / (1 + exp((*currElementA) signal [0}.i));probA[1] = exp((*currElementA).signal[0].i) * probA[0];
lambdal = 0;lambdaO = 0;for (Sk_prev=0; Sk_prev < (*decoder) .numStates; Skprev++)
Sk = (*decoder) .trellis[Sk_prev] [0) .S2;pk = (*decoder) trellis [Skprev) [0].p;lambdaO += (*decoder) gamma[k] [0] [pkl * probA[0] *
(*decoder).beta[k] [Ski;if (lambdaO > infinite)
pk = 0;Sk = (*decoder) trellis [Sk_prev] [1}.S2;pk = (*decoder) trellis [Sk_prev] [1].p;lambdal i= (*decoder) gamma[k] [1] [pk] * probA[l] (
(*decoder).beta[k][Sk];if (lambdal > infinite)
pk = 0;
decoder).alpha[k-l] [Sk_prev *
decoder).alpha[k-i] [Sk_prcv] *
};
LLR.i = log(lambdal/lambda0);LLR.q = LLR.i; /* set q = i in case accidentally use the q part */if (currOutD == NULL)
addLLsignal((*decoder) .outputDprob, &LLR);/* if currOut is NULL, it will remain NULL throughout this MAP
decoding round, and bit probabilities will be added to theoutput list */
else
(*currOutD).signal(O] = LLR;currOutD = (*currOutD).next;
};
La = (*currElementA).signal[0].i;currElementA = (*currElementA).next;
Ls = (*currElementS).signal[0].i;currElementS = (*currElementS).next;
Z.i = (LLR.i - La - Ls);
/* we need to limit the magnitude of the extrinsic LLR, or a priori information.an LLR of explimit or -explimit means that we are VERY certain that thebit is a 1 or 0, respectively. There's no need to further increase ordecrease the extrinsic LLR because at this point, we are already certain whatthe bit is. This is a non-linear operation, but it should not affect thecorrection power of the turbo code or the performance.
*/if (fabs(Z.i) > (*decoder).explimit)
Z.i = (Z.i)/fabs(Z.i) * (*decoder) .exp limit;Z.q = Z.i;
if (currOutA == NULL)addLLsignal((*decoder)
else
I
.output extrinsic, &Z);
(*currOutA).signal[O] = Z;currOutA = (*currOutA).next;
};
} /* doFastRl2MAPdecoding */
function: calcgammaR12
Calculates the gamma parameter used
Input MAPdecoderVars* decoderOutputModify
in MAP decoding.
decoder.c 193
{
194 SIMULATION CODE
void calcgammaR12(MAPdecoderVars* decoder)
int k, a, b;
double expval;twoDSignalPoint probP, probS;listElement *currElementS, *currElementP;
currElementS = (*decoder).inputS->head;currElementP = (*decoder).inputP->head;for (k=1; k <= (*decoder).blockSize; k++)
expval = exp((*currElementP).signal[0[.i);probP.i = 1.0 / (1 + expval); /* pk = 0 *probP.q = probP.i * exp_val; /* pk = 1 *
expval = exp((*currElementS).signal[0].i);
probS.i = 1.0 / (1 + exp_val);probS.q = probS.i * exp_val;
(*decoder).gamma[k][0] [0] = probS.i * probP.i;(*decoder).gamma[k][0][1] = probS.i * probP.q;(*decoder).gamma[k} [1][0] = probS.q * probPi;(*decoder).gamma[k} [1][1] = probS.q * probP.q;
for (a=0; a<2; a++)
for (b=0; b<2; b++)
if (* decoder) .gamma[k] [a] [b] < (exp(-1* (*decoder) .explimit)))(*decoder) gamma[k] [a] [b] = exp(-1* (*decoder) .exp-limit);
currElementS = (*currElementS).next;currElementP = (*currElementP).next;
}; /* for k */
/* calcgammaR12 */
/*
function: calc alphaRi2
This function calculates all the alpha parameters needed inMAP decoding.
Input
OutputModify
void calc alphaRl2(MAPdecoderVars* decoder)
int k, dk, Sk; /* alpha indices -- alpha[k] [dk] [Sk] *int Skprev; /* summation indices */int pk;double sum;listElement* currA;
double probA[2[;
currA = (*decoder).inputA->head;
tor k=1; k -= (*decoder).blockSize; k++)
probA[0] = 1.0 / (1 + exp((*currA).signal[0].i));probA[1] = exp((*currA).signal[0[.i) * probA[0];
for (Sk = 0; Sk < (*decoder).numStates; Sk++)(*decoder).alpha[k] [Sk] = 0;
/* now loop through branches: each trellis[Sk-1] [dk] is a branch */for (Skprev = 0; Skprev < (*decoder).numStates; Skprev++)
for (dk = 0; dk < (*decoder).numInputs; dk++)
{Sk = (*decoder) trellis [Sk_prev] [dk] .S2; /* branch: Sk-1 -- > Sk, input dk */pk = (*decoder) .trellis [Skjprev] [dkj .p;(*decoder) .alpha [k] [Sk] += (*decoder) .gamma[k] [dk] [pk] * probA[dk] (*decoder) .alpha[k-
1] [Skprev;; /* for Skprev /
/* alpha[k] [Sk] is supposed to equal numerator[k] [Sk] / denominator[k]however, because denominator[k] is the same for every state at a time k,it acts like a constant for a time k and divides out in the finalcalculation of L(dk). However, this means that alpha will accumulatefaster with each k, so it'll need to be normalized */
sum = 0;for (Sk=0; Sk < (*decoder).numStates; Sk++)
sum += (*decoder).alpha[k[ [Sk];for (Sk=0; Sk < (*decoder).numStates; Sk++)
(*decoder).alpha[k][Sk] /= sum;/* if ((*decoder) .alpha[k] [Sk] < exp(-l* (*decoder) .exp_limit))
(*decoder) .alpha [k] [Sk] = exp(-1* (*decoder) .exp_limit);*/
};
currA = (*currA).next;}; / for k /
S/* calcalphaR12 *
function: calc_betaRl2
This function calculatesdecoding
Input
OutputModify
all the beta values used in MAP
void calcbetaR12(MAPdecoderVars* decoder)
int k, Sk; /* beta indices -- beta[k][Sk] /int dk future, Sk future; /* summation indices /int pk;double sum;listElement* currA;double probA[2];
currA = (*(*decoder).inputA).tail;for (k = ((*decoder).blockSize - 1); k >= 1; k--)
probA[0] = 1.0 / (1 + exp((*currA).signal[O].i));probAil] = exp((*currA).signal[0].i) * probA[0];
for (Sk = 0; Sk < (*decoder).numStates; Sk++)(*decoder).beta[k][Sk] = 0;
/* loop through branches: each trellis[Sk-1] [dk] is a branch *for (Sk = 0; Sk < (*decoder).numStates; Sk++)
for (dkfuture = 0; dkfuture < (*decoder).numInputs; dkfuture++)
pk = (*decoder) trellis [Sk] [dk_future .p;Skfuture = (*decoder).trellis[Sk) [dk future].S2;(*decoder) beta[k] [Sk] += (*decoder) gamma[k+l] [dk future] [pk probA[dk future]
(*decoder).beta[k+l][Skfuture];
}; /* for dk+l */
sumfor
for{
= 0;(Sk=0;
SUM +=(Sk=0;
Sk < (*decoder).numStates; Sk++)(*decoder).beta[k] [Sk];
Sk < (*decoder).numStates; Sk++)
(*decoder).beta[k] [Sk] /= sum;if ((*decoder) .beta[k] [Sk] < exp(-l* (*decoder) explimit))
(*decoder) beta [k] [Sk] = exp(-l*(*decoder) exp-limit);
};
currA = (*currA).prev;
}; /* for k *
} /* calc_betaR12 */
function: signDecision
Performs a sign decision ongenerate the decoded bits.
Input
OutputModify
LLR's used in MAP decoding to
void signDecision(linkList* input, linkList* output)
int i, numEl;
char b;listElement *currEl, *currOut;
numEl = getNumElements(input);currEl = getElement(input, 1);currOut = (*output).head;for (i=O; i a numEl; i++)
b = ((*currEl).signal[0].i >= 0);
decoder.c 195
196 SIMULATION CODE
if (currOut == NULL)addLLbits(output, &b);
else
(*currOut).value[O] = b;currOut = (*currOut).next;
}1;
currEl = (*currEl).next;
};
} /* signoecision */
REFERENCES
[1] P. Melsa, "Application of Programmable DSPs for DMT and ADSL", in DSPWorld Spring Design Conference, April 1998.
[2] C. Berrou, A. Glavieux, and P. Thitimajshima, "Near shannon limit error-correctingcoding and decoding: Turbo-codes", in Proc. ICC '93, pp. 1064-1070, May 1993.
[3] MIT, "Lecture 10: Introduction to Modems", in 6.401/6.450 Introduction to DigitalCommunications, Fall 2000.
[4] P. Robertson, "Illuminating the structure of code and decoder of parallelconcatenated recursive systematic (Turbo) codes", in Proc. GLOBECOM '94, pp.1298-1303, December 1994.
[5] Stanford University, "Chapter 11: Code Concatenation and Low-Density ParityCheck Codes", in EE379B - Digital Communication H1: Coding, Spring 2001.
[6] S. Le Goff, A. Glavieux, and C. Berrou, "Turbo-codes and high spectral efficiencymodulation", in Proc. ICC '94, pp. 645-649, May 1994.
[7] P. Robertson and T. W6rz, "A novel bandwidth efficient coding scheme employingTurbo codes", in Proc. ICC '96, pp. 962-967, June 1996.
[8] S. Le Goff and F. 0. Al-Ayyan, "Design of bit-interleaved turbo-codedmodulations", Electronic Letters, vol. 37, no. 16, pp. 1030-1031, August 2001.
[9] S. Benedetto, D. Divsalar, G. Montorsi, and F. Pollara, "Bandwidth efficientparallel concatenated coding schemes", Electronic Letters, vol. 31, no. 24, pp.2067-2069, November 1995.
[10] S. Benedetto and Guido Montorsi, "Design of parallel concatenated convolutionalcodes", IEEE Trans. On Communications, vol. 44, no. 5, pp. 591-600, May, 1996.
[11] L. R. Bahl, J. Cocke, F. Jelinek, and J. Raviv, "Optimal decoding of linear codes forminimizing symbol error rate", IEEE Trans. On Information Theory, vol. IT-20, pp.284-287, March 1974.
- 197 -
198 REFERENCES
[12] P. Robertson and T. W6rz, "Bandwidth efficient Turbo Trellis-coded modulationusing punctured component codes", IEEE J. on Selected Areas of Comm., vol. 16,no. 2, February 1998.
[13] A. A. Barbalescu and S. S. Pietrobon, "Terminating the trellis of turbo-codes in thesame state", Electronic Letters, vol. 31, no. 1, pp. 22-23, January 1995.
[14] J. Torres, F. Hirzel, and V. Demjanenko, (VOCAL Technologies Ltd), "G.gen: Newproposal of Turbo codes for ADSL modems", ITU standard contribution BA-020R1at Antwerp, Belgium, 19-23 June 2000.
[15] S. A. Barbulescu, J. A. Torres, F. Hirzel, and V. Demjanenko, (VOCALTechnologies Ltd), "G.gen: G.vdsl: G.dmt.bis: G.lite.bis: : Text to include a Turboencoder as mandatory in the transmitter for G.922.1.bis and G.992.2.bis followingthe proposal given in BA-020R1 and HC-037", ITU standard contribution CF-037at Clearwater, Florida, 8-12 January 2001.
[16] F. Hirzel, J. A. Torres, and V. Demjanenko, (VOCAL Technologies), "G.gen:G.vdsl, G.dmt.bis: G.lite.bis: : Method for using non-square QAM constellationswith independent I&Q for Receiver soft-Decision Decoding Techniques", ITUstandard contribution CF-038 at Clearwater, Florida, 8-12 January 2001
[17] W. Farrell, (iCODING Technology), "G.gen : G.dmt.bis : G.lite.bis : Lowcomplexity Turbo coding for the ADSL DMT channel", ITU standard contributionCF-072 at Clearwater, Florida, 8-12 January 2001.
[18] D. V. Bruyssel, (Alcatel), "G.gen: G.dmt.bis: G.lite.bis: Multilevel Turbo SCCCcode: proposal, performance and complexity", ITU standard contribution RN-079 atRed Bank, New Jersey, 21-25 May 2001.
[19] B. I in and A Deczky, (Catena Networks Inc), "G.gen: G.dmt.bis: (.lite hisProposing 'Multi-level" Turbo TCM concatenated with Reed-Solomon codes as theadvanced coding method for G.dmt.bis and G.lite.bis", ITU standard contributionIC-024 at Irvine, California, 9-13 April 2001.
[20] H. Sadjadpour, (AT&T), "G.gen: G.dmt.bis: G.lite.bis: : Encoder structure of Multi-tone Turbo Trellis coded modulation proposal", ITU standard contribution RN-027at Redbank, New Nersey, 21-25 May 2001.
[21] H. Sadjadpour, (AT&T), "G.gen: G.dmt.bis: G.lite.bis: : Interleaver design formulti-tone Turbo Trellis coded modulation scheme for G.dmt.bis and G.lite.bis",ITU standard contribution RN-029 at Redbank, New Jersey, 21-25 May 2001.