# comm.TurboDecoder

Decode input signal using parallel concatenated decoding scheme

## Description

The `comm.TurboDecoder` System object™ uses a parallel concatenated decoding scheme to decode a coded input signal. The input signal is typically the soft-decision output from the baseband demodulation operation. For more information, see Parallel Concatenated Convolutional Decoding Scheme.

To decode an input signal using a parallel concatenated decoding scheme:

1. Create the `comm.TurboDecoder` object and set its properties.

2. Call the object with arguments, as if it were a function.

## Creation

### Syntax

``turbodec = comm.TurboDecoder``
``turbodec = comm.TurboDecoder(trellis,interlvrindices,numiter)``
``turbodec = comm.TurboDecoder(___,Name,Value)``

### Description

````turbodec = comm.TurboDecoder` creates a turbo decoder System object. This object uses the a-posteriori probability (APP) constituent decoder to iteratively decode the parallel-concatenated convolutionally encoded input data.```

example

````turbodec = comm.TurboDecoder(trellis,interlvrindices,numiter)` creates a turbo decoder System object with the `TrellisStructure`, `InterleaverIndices`, and `numiter`, respectively. The `trellis` input must be specified as described by the `TrellisStructure` property. The `interlvrindices` input must be specified as described by the `InterleaverIndices` property. The `numiter` input must be specified as described by the `NumIterations` property.```

example

````turbodec = comm.TurboDecoder(___,Name,Value)` sets properties using one or more name-value pairs in addition to any input argument combination from previous syntaxes. Enclose each property name in quotes. For example, ```comm.TurboDecoder('InterleaverIndicesSource','Input port')``` configures a turbo decoder System object with the interleaver indices to be supplied as an input argument to the System object when it is called.```

## Properties

expand all

Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the `release` function unlocks them.

If a property is tunable, you can change its value at any time.

Trellis description of the constituent convolutional code, specified as a structure that contains the trellis description for a rate KN code. K is the number of input bit streams, and N is the number of output bit streams.

Note

K must be 1 for the turbo coder. For more information, see Coding Rate.

You can either use the `poly2trellis` function to create the trellis structure or create it manually. For more about this structure, see Trellis Description of a Convolutional Code and the `istrellis` function.

The trellis structure contains these fields.

Number of symbols input to the encoder, specified as an integer equal to 2K, where K is the number of input bit streams.

Data Types: `double`

Number of symbols output from the encoder, specified as an integer equal to 2N, where N is the number of output bit streams.

Data Types: `double`

Number of states in the encoder, specified as a power of 2.

Data Types: `double`

Next states for all combinations of current states and current inputs, specified as a matrix of integers. The matrix size must be `numStates`-by-2K.

Data Types: `double`

Outputs for all combinations of current states and current inputs, specified as a matrix of octal numbers. The matrix size must be `numStates`-by-2K.

Data Types: `double`

Data Types: `struct`

Source of interleaver indices, specified as `'Property'` or `'Input port'`.

• When you set this property to `'Input port'`, the object executes using the input argument `interlvrindices` when you call the object. The vector length and values for the interleaver indices and coded input signal can change with each call to the object.

• When you set this property to `'Property'`, the object executes using the interleaver indices that you specified with the `InterleaverIndices` property when configuring the object.

Data Types: `char` | `string`

Interleaver indices that define the mapping used to permute the codeword bits input to the decoder, specified as a column vector of integers. The vector must be of length L. Each element of the vector must be an integer in the range [1, L] and must be unique. L is the length decoded output message, `decmsg`. Each element of the vector must be an integer in the range [1, L] and must be unique.

#### Dependencies

To enable this property, set the `InterleaverIndicesSource` property to `'Property'`.

Data Types: `double`

Source of input indices, specified as `'Auto'`, `'Property'`, or ```'Input port'```.

• When you set this property to `'Auto'`, the object computes input indices that assume the second systematic stream is punctured and all tail bits are included in the input.

• When you set this property to `'Property'`, the object uses the input indices that you specify for the `InputIndices` property.

• When this property is set to `'Input port'`, the object executes using the input indices specified by the input argument `inindices`. The vector length and values for the input indices and the coded input signal can change with each call to the object.

Data Types: `char` | `string`

Input indices for the bit ordering and puncturing used on the fully encoded data, specified as a column vector of integers. The length of this property must equal the length of the input data vector `codeword`.

#### Dependencies

To enable this property, set the `InputIndicesSource` property to `'Property'`.

Data Types: `double`

Decoding algorithm, specified as `'True APP'`, `'Max*'`, or `'Max'`. When you set this property to `'True APP'`, the object implements true APP decoding. When you set this property to `'Max*'` or `'Max'`, the object uses approximations to increase the speed of the computations. For more information, see APP Decoder.

Data Types: `char` | `string`

Number of scaling bits, specified as an integer in the range [0, 8]. This property sets the number of bits the constituent decoders use to scale the input data to avoid losing precision during computations. The constituent decoders multiply the input by 2 `NumScalingBits` and divide the pre-output by the same factor. For more information, see APP Decoder.

#### Dependencies

This enable this property, set the Algorithm property to `'Max*'`.

Data Types: `double`

Number of decoding iterations, specified as a positive integer. This property sets the number of decoding iterations used for each call to the object. The object iterates and provides updates to the log-likelihood ratios (LLR) of the uncoded output bits. The output of the object is the hard-decision output of the final LLR update.

Data Types: `double`

## Usage

### Syntax

``decmsg = turbodec(codeword)``
``decmsg = turbodec(codeword,interlvrindices)``
``decmsg = turbodec(codeword,interlvrindices,inindices)``

### Description

example

````decmsg = turbodec(codeword)` decodes the input codeword using the parallel concatenated convolutional decoding scheme that is specified by the trellis structure and interleaver indices. `turbodec` returns the binary decoded data. For more information, see Parallel Concatenated Convolutional Decoding Scheme.```

example

````decmsg = turbodec(codeword,interlvrindices)` additionally specifies the interleaver indices. To enable this syntax, set the InterleaverIndicesSource property to ```'Input port'```. The interleaver indices define the mapping used to permute the input at the decoder.```
````decmsg = turbodec(codeword,interlvrindices,inindices)` additionally specifies the bit ordering and puncturing used on the fully encoded data. To enable this syntax, set the InputIndicesSource property to `'Input port'`. The input indices vector values must be relative to the fully encoded data, including the tail bits for the coding scheme for all streams.```

### Input Arguments

expand all

Parallel concatenated codeword, specified as a column vector of length M, where M is the length of the parallel concatenated codeword.

Data Types: `double` | `single`

Interleaver indices, specified as a column vector of integers. The vector must be of length L, where L is the length of the decoded output message, `decmsg`. Each element of the vector must be an integer in the range [1, L] and must be unique. The interleaver indices define the mapping used to permute the input bits at the decoder.

Tunable: Yes

#### Dependencies

To enable this property, set the `InterleaverIndicesSource` property to `'Input port'`.

Data Types: `double`

Input indices for the bit ordering and puncturing used on the fully encoded data, specified as a column vector of integers. The length of the `inindices` vector must equal the length of the input data vector `codeword`. Element values in the `inindices` vector must be relative to the fully encoded data, including the tail bits for the coding scheme for all streams.

#### Dependencies

To enable this argument, set the `InputIndicesSource` property to `'Input port'`.

Data Types: `double`

### Output Arguments

expand all

Decoded message, returned as a binary column vector of length L, where L is the length of the decoded output message. This output signal is the same as data type of the `codeword` input.

## Object Functions

To use an object function, specify the System object as the first input argument. For example, to release system resources of a System object named `obj`, use this syntax:

`release(obj)`

expand all

 `step` Run System object algorithm `release` Release resources and allow changes to System object property values and input characteristics `reset` Reset internal states of System object

## Examples

collapse all

Define output indices by using the `OutputIndices` property for turbo encoding and define the input indices by using the `InputIndices` property for turbo decoding. Show full-length punctured encoding and decoding for a rate 1/2 code and 10-bit block length.

Initialize Parameters

Define parameters to initialize the encoder.

```blkLen = 10; trellis = poly2trellis(4,[13 15],13); n = log2(trellis.numOutputSymbols); mLen = log2(trellis.numStates);```

Full-length Encoding and Decoding

Initialize variables and turbo encoding and decoding System objects for full-length coding. Turbo encode and decode the message. Display the turbo coding rate. Check the length of the coded output versus the length of the output indices vector.

```fullOut = (1:(mLen+blkLen)*2*n)'; outLen = length(fullOut); netRate = blkLen/outLen; data = randi([0 1],blkLen,1); intIndices = randperm(blkLen); turboEnc = comm.TurboEncoder('TrellisStructure',trellis); turboEnc.InterleaverIndices = intIndices; turboEnc.OutputIndicesSource = 'Property'; turboEnc.OutputIndices = fullOut; turboDec = comm.TurboDecoder('TrellisStructure',trellis); turboDec.InterleaverIndices = intIndices; turboDec.InputIndicesSource = 'Property'; turboDec.InputIndices = fullOut; encMsg = turboEnc(data); % Encode disp(['Turbo coding rate: ' num2str(netRate)])```
```Turbo coding rate: 0.19231 ```
`encOutLen = length(encMsg) % Display encoded length`
```encOutLen = 52 ```
`isequal(encOutLen,outLen) % Check lengths`
```ans = logical 1 ```
```rxMsg = turboDec(2*encMsg-1); % Decode isequal(data, rxMsg) % Compare bits with decoded bits```
```ans = logical 1 ```

Punctured Encoding and Decoding

Specify the output indices for puncturing of the second systematic stream by using the `getTurboIOIndices` function. Initialize variables and turbo encoding and decoding System objects for punctured coding. Turbo encode and decode the message. Display the turbo coding rate. Check the length of the coded output versus the length of the output indices vector.

```puncOut = getTurboIOIndices(blkLen,n,mLen); outLen = length(puncOut); netRate = blkLen/outLen; data = randi([0 1],blkLen,1); intIndices = randperm(blkLen); turboEnc = comm.TurboEncoder('TrellisStructure',trellis); turboEnc.InterleaverIndices = intIndices; turboEnc.OutputIndicesSource = 'Property'; turboEnc.OutputIndices = puncOut; turboDec = comm.TurboDecoder('TrellisStructure',trellis); turboDec.InterleaverIndices = intIndices; turboDec.InputIndicesSource = 'Property'; turboDec.InputIndices = puncOut; encMsg = turboEnc(data); % Encode disp(['Turbo coding rate: ' num2str(netRate)])```
```Turbo coding rate: 0.25641 ```
`encOutLen = length(encMsg) % Display encoded length`
```encOutLen = 39 ```
`isequal(encOutLen, outLen) % Check lengths`
```ans = logical 1 ```
```rxMsg = turboDec(2*encMsg-1); % Decode isequal(data, rxMsg) % Compare bits with decoded bits```
```ans = logical 1 ```

Compare Full and Punctured Outputs

The output of the encoder interlaces the individual bit streams. The third bit of every 4-bit tuple is removed from the full-length code to produce the punctured code. This third output bit stream corresponds to the second systematic bit stream. Display the indices of the full-length code and the indices of the punctured code to show that the third bit of every 4-bit tuple is punctured.

`fullOut'`
```ans = 1×52 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ```
`puncOut'`
```ans = 1×39 1 2 4 5 6 8 9 10 12 13 14 16 17 18 20 21 22 24 25 26 28 29 30 32 33 34 36 37 38 40 41 42 44 45 46 48 49 50 52 ```

Simulate the transmission and reception of BPSK data over an AWGN channel by using turbo encoding and decoding.

Specify simulation parameters, and then compute the effective coding rate and noise variance. For BPSK modulation, ${\mathit{E}}_{\mathrm{S}}/{\mathit{N}}_{0}$ equals ${\mathit{E}}_{\mathrm{b}}/{\mathit{N}}_{0}$ because the number of bits per symbol (bps) is 1. To ease reuse of this code for other modulation schemes, calculations in this example include the bps terms. Define the packet length, trellis structure, and number of iterations. Calculate the noise variance using ${\mathit{E}}_{\mathrm{S}}/{\mathit{N}}_{0}$ and the code rate. Set the random number generator to its default state to ensure that the results are repeatable.

```modOrd = 2; % Modulation order bps = log2(modOrd); % Bits per symbol EbNo = 1; % Energy per bit to noise power spectral density ratio in dB EsNo = EbNo + 10*log10(bps); % Energy per symbol to noise power spectral density ratio in dB L = 256; % Input packet length in bits trellis = poly2trellis(4,[13 15 17],13); numiter = 4; n = log2(trellis.numOutputSymbols); numTails = log2(trellis.numStates)*n; M = L*(2*n - 1) + 2*numTails; % Output codeword packet length rate = L/M; % Coding rate snrdB = EsNo + 10*log10(rate); % Signal to noise ratio in dB noiseVar = 1./(10.^(snrdB/10)); % Noise variance rng default```

Generate random interleaver indices.

`intrlvrIndices = randperm(L);`

Create a turbo encoder and decoder pair. Use the defined trellis structure and random interleaver indices. Configure the decoder to run a maximum of four iterations.

```turboenc = comm.TurboEncoder(trellis,intrlvrIndices); turbodec = comm.TurboDecoder(trellis,intrlvrIndices,numiter);```

Create a BPSK modulator and demodulator pair, where the demodulator outputs soft bits determined using an LLR method.

```bpskmod = comm.BPSKModulator; bpskdemod = comm.BPSKDemodulator('DecisionMethod','Log-likelihood ratio', ... 'Variance',noiseVar);```

Create an AWGN channel object and an error rate object.

```awgnchan = comm.AWGNChannel('NoiseMethod','Variance','Variance',noiseVar); errrate = comm.ErrorRate;```

The main processing loop performs these steps.

1. Generate binary data.

2. Turbo encode the data.

3. Modulate the encoded data.

4. Pass the modulated signal through an AWGN channel.

5. Demodulate the noisy signal by using LLR to output soft bits.

6. Turbo decode the demodulated data. Because the bit mapping from the demodulator is opposite of the mapping expected by the turbo decoder, the decoder input must use the inverse of the demodulated signal.

7. Calculate the error statistics.

```for frmIdx = 1:100 data = randi([0 1],L,1); encodedData = turboenc(data); modSignal = bpskmod(encodedData); receivedSignal = awgnchan(modSignal); demodSignal = bpskdemod(receivedSignal); receivedBits = turbodec(-demodSignal); errorStats = errrate(data,receivedBits); end```

Display the error data.

`fprintf('Bit error rate = %5.2e\nNumber of errors = %d\nTotal bits = %d\n', errorStats)`
```Bit error rate = 2.34e-04 Number of errors = 6 Total bits = 25600 ```

Simulate an end-to-end communication link by using a 16-QAM signal and turbo codes in an AWGN channel. Inside a frame processing loop, packet sizes are randomly selected to be 500, 1000, or 1500 bits. Because the packet size varies, the interleaver indices are provided to the turbo encoder and decoder as an input argument of their associated System object. Compare turbo coded bit error rate results to uncoded bit error rate results.

Initialize Simulation

Set the modulation order and range of ${\mathit{E}}_{\mathrm{b}}/{\mathit{N}}_{0}$ values. Compute the number of bits per symbol and the energy per symbol to noise ratio (${\mathit{E}}_{\mathrm{S}}/{\mathit{N}}_{0}$) based on the modulation order and ${\mathit{E}}_{\mathrm{b}}/{\mathit{N}}_{0}$. To get repeatable results, seed the random number.

```modOrder = 16; % Modulation order bps = log2(modOrder); % Bits per symbol EbNo = (2:0.5:4); % Energy per bit to noise power spectral density ratio in dB EsNo = EbNo + 10*log10(bps); % Energy per symbol to noise power spectral density ratio in dB rng(1963);```

Create a turbo encoder and decoder pair. Because the packet length varies for each frame, specify that the interleaver indices be supplied by an input argument of the System object when executed. Specify that the decoder perform four iterations.

```turboEnc = comm.TurboEncoder('InterleaverIndicesSource','Input port'); turboDec = comm.TurboDecoder('InterleaverIndicesSource','Input port','NumIterations',4); trellis = poly2trellis(4,[13 15 17],13); n = log2(turboEnc.TrellisStructure.numOutputSymbols); numTails = log2(turboEnc.TrellisStructure.numStates)*n;```

Create an error rate object.

`errRate = comm.ErrorRate;`

Main Processing Loop

The frame processing loop performs these steps.

1. Select a random packet length, and generate random binary data.

2. Compute the output codeword length and coding rate.

3. Compute the signal to noise ratio (SNR) and noise variance.

4. Generate interleaver indices.

5. Turbo encode the data.

6. Apply 16-QAM modulation, and normalize the average signal power.

7. Pass the modulated signal through an AWGN channel.

8. Demodulate the noisy signal by using an LLR method, output soft bits, and normalize the average signal power.

9. Turbo decode the data. Because the bit mapping order from the demodulator is opposite the mapping order expected by the turbo decoder, the decoder input must use the inverse of the demodulated signal.

10. Calculate the error statistics.

```ber = zeros(1,length(EbNo)); for k = 1:length(EbNo) % numFrames = 100; errorStats = zeros(1,3); %for pktIdx = 1:numFrames L = 500*randi([1 3],1,1); % Packet length in bits M = L*(2*n - 1) + 2*numTails; % Output codeword packet length rate = L/M; % Coding rate for current packet snrdB = EsNo(k) + 10*log10(rate); % Signal to noise ratio in dB noiseVar = 1./(10.^(snrdB/10)); % Noise variance while errorStats(2) < 100 && errorStats(3) < 1e7 data = randi([0 1],L,1); intrlvrIndices = randperm(L); encodedData = turboEnc(data,intrlvrIndices); modSignal = qammod(encodedData,modOrder, ... 'InputType','bit','UnitAveragePower',true); rxSignal = awgn(modSignal,snrdB); demodSignal = qamdemod(rxSignal,modOrder,'OutputType','llr', ... 'UnitAveragePower',true,'NoiseVariance',noiseVar); rxBits = turboDec(-demodSignal,intrlvrIndices); % Demodulated signal is negated errorStats = errRate(data,rxBits); end % Save the BER data and reset the bit error rate object ber(k) = errorStats(1); reset(errRate) end```

Plot Results

Plot the bit error rate and compare it to the uncoded bit error rate.

```semilogy(EbNo,ber,'-o') grid xlabel('Eb/No (dB)') ylabel('Bit Error Rate') uncodedBER = berawgn(EbNo,'qam',modOrder); % Estimate of uncoded BER hold on semilogy(EbNo,uncodedBER) legend('Turbo','Uncoded','location','sw')```

expand all

## References

[1] Benedetto, S., G. Montorsi, D. Divsalar, and F. Pollara. "A Soft-Input Soft-Output Maximum A Posterior (MAP) Module to Decode Parallel and Serial Concatenated Codes." Jet Propulsion Lab TDA Progress Report, 42–127, (November 1996).

[2] Viterbi, A.J. “An Intuitive Justification and a Simplified Implementation of the MAP Decoder for Convolutional Codes.” IEEE Journal on Selected Areas in Communications 16, no. 2 (February 1998): 260–64. https://doi.org/10.1109/49.661114.

[3] Berrou, C., A. Glavieux, and P. Thitimajshima. “Near Shannon Limit Error-Correcting Coding and Decoding: Turbo-Codes.” Proceedings of ICC 93 - IEEE International Conference on Communications, Geneva, Switzerland, May 1993, 1064–70. https://doi.org/10.1109/icc.1993.397441.

[4] Schlegel, Christian, and Lance Perez. Trellis and Turbo Coding. IEEE Press Series on Digital & Mobile Communication. Piscataway, NJ ; Hoboken, NJ: IEEE Press ; Wiley-Interscience, 2004.

[5] 3GPP TS 36.212. "Multiplexing and channel coding." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network; Evolved Universal Terrestrial Radio Access (E-UTRA). https://www.3gpp.org.

## Extended Capabilities

Introduced in R2012a