High Rate Convolutional Codes for Turbo Coding

Concatenated convolutional codes offer high reliability and have gained in prominence and usage as turbo codes. The `comm.TurboEncoder` and `comm.TurboDecoder` System objects support rate 1/n convolutional codes only. This example shows the parallel concatenation of two rate 2/3 convolutional codes to achieve an effective rate 1/3 turbo code by using `comm.ConvolutionalEncoder` and `comm.APPDecoder` System objects.

System parameters

```blkLength = 1024; % Block length EbNo = 0:5; % Eb/No values to loop over numIter = 3; % Number of decoding iterations maxNumBlks = 1e2; % maximum number of blocks per Eb/No value```

Convolutional Encoder/Decoder Parameters

```trellis = poly2trellis([5 4],[23 35 0; 0 5 13]); k = log2(trellis.numInputSymbols); % number of input bits n = log2(trellis.numOutputSymbols); % number of output bits intrIndices = randperm(blkLength/k)'; % Random interleaving decAlg = 'True App'; % Decoding algorithm modOrder = 2; % PSK-modulation order```

Initialize System Objects

Initialize Systems object for convolutional encoding, APP Decoding, BPSK modulation and demodulation, AGWN channel, and error rate computation. The demodulation output soft bits using a log-likelihood ratio method.

```cEnc1 = comm.ConvolutionalEncoder('TrellisStructure',... trellis,'TerminationMethod','Truncated'); cEnc2 = comm.ConvolutionalEncoder('TrellisStructure',... trellis,'TerminationMethod','Truncated'); cAPPDec1 = comm.APPDecoder('TrellisStructure',trellis,... 'TerminationMethod','Truncated','Algorithm',decAlg); cAPPDec2 = comm.APPDecoder('TrellisStructure',trellis,... 'TerminationMethod','Truncated','Algorithm',decAlg); bpskMod = comm.BPSKModulator; bpskDemod = comm.BPSKDemodulator('DecisionMethod','Log-likelihood ratio', ... 'VarianceSource','Input port'); awgnChan = comm.AWGNChannel('NoiseMethod','Variance', ... 'VarianceSource','Input port'); bitError = comm.ErrorRate; % BER measurement```

Frame Processing Loop

Loop through a range of ${\mathit{E}}_{\mathrm{b}}/{\mathit{N}}_{0}$ values to generate results for BER performance. The `helperTurboEnc` and `helperTurboDec` helper functions perform the turbo encoding and decoding.

```ber = zeros(length(EbNo),1); bitsPerSymbol = log2(modOrder); turboEncRate = k/(2*n); for ebNoIdx = 1:length(EbNo) % Calculate the noise variance from EbNo EsNo = EbNo(ebNoIdx) + 10*log10(bitsPerSymbol); SNRdB = EsNo + 10*log10(turboEncRate); % Account for code rate noiseVar = 10^(-SNRdB/10); for numBlks = 1:maxNumBlks % Generate binary data data = randi([0 1],blkLength,1); % Turbo encode the data [encodedData,outIndices] = helperTurboEnc(data,cEnc1,cEnc2, ... trellis,blkLength,intrIndices); % Modulate the encoded data modSignal = bpskMod(encodedData); % Pass the modulated signal through an AWGN channel receivedSignal = awgnChan(modSignal,noiseVar); % Demodulate the noisy signal using LLR to output soft bits demodSignal = bpskDemod(receivedSignal,noiseVar); % Turbo decode the demodulated data receivedBits = helperTurboDec(-demodSignal,cAPPDec1,cAPPDec2, ... trellis,blkLength,intrIndices,outIndices,numIter); % Calculate the error statistics errorStats = bitError(data,receivedBits); end ber(ebNoIdx) = errorStats(1); reset(bitError); end```

Display Results

While the practical wireless systems, such as LTE and CCSDS, specify base rate-1/n convolutional codes for turbo codes, the results show use of higher rate convolutional codes as turbo codes is viable.

```figure; semilogy(EbNo, ber, '*-'); grid on; xlabel('E_b/N_0 (dB)'); ylabel('BER'); title('High Rate Convolutional Codes for Turbo Coding'); legend(['N = ' num2str(blkLength) ', ' num2str(numIter) ' iterations']);```

Helper Functions

```function [yEnc,outIndices] = helperTurboEnc(data,hCEnc1,hCEnc2,trellis,blkLength,intrIndices) % Turbo encoding using two parallel convolutional encoders. % No tail bits handling and assumes no output stream puncturing. % Trellis parameters k = log2(trellis.numInputSymbols); n = log2(trellis.numOutputSymbols); cLen = blkLength*n/k; punctrVec = [0;0;0;0;0;0]; % assumes all streams are output N = length(find(punctrVec==0)); % Encode random data bits y1 = step(hCEnc1, data); y2 = step(hCEnc2, reshape(intrlv(reshape(data, k, [])',intrIndices)', [], 1)); y1D = reshape(y1(1:cLen), n, []); y2D = reshape(y2(1:cLen), n, []); yDTemp = [y1D; y2D]; y = yDTemp(:); % Generate output indices vector using puncturing vector idx = 0 : 2*n : (blkLength - 1)*2*(n/k); punctrVecIdx = find(punctrVec==0); dIdx = repmat(idx, N, 1) + punctrVecIdx; outIndices = dIdx(:); yEnc = y(outIndices); end function yDec = helperTurboDec(yEnc,cAPPDec1,cAPPDec2,trellis,blkLength,intrIndices,inIndices,numIter) % Turbo decoding using two a-posteriori probability (APP) decoders % Trellis parameters k = log2(trellis.numInputSymbols); n = log2(trellis.numOutputSymbols); rCodLen = 2*(n/k)*blkLength; typeyEnc = class(yEnc); % Re-order encoded bits according to outIndices x = zeros(rCodLen, 1); x(inIndices) = yEnc; % Generate output of first encoder yD = reshape(x(1:rCodLen), 2*n, []); lc1D = yD(1:n, :); Lc1_in = lc1D(:); % Generate output of second encoder lc2D = yD(n+1:2*n, :); Lc2_in = lc2D(:); % Initialize unencoded data input Lu1_in = zeros(blkLength, 1, typeyEnc); % Turbo Decode out1 = zeros(blkLength/k, k, typeyEnc); for iterIdx = 1 : numIter [Lu1_out, ~] = step(cAPPDec1, Lu1_in, Lc1_in); tmp = Lu1_out(1:blkLength); Lu2_in = reshape(tmp, k, [])'; [Lu2_out, ~] = step(cAPPDec2, ... reshape(Lu2_in(intrIndices, :)', [], 1), Lc2_in); out1(intrIndices, :) = reshape(Lu2_out(1:blkLength), k, [])'; Lu1_in = reshape(out1', [], 1); end % Calculate llr and decoded bits for the final iteration llr = reshape(out1', [], 1) + Lu1_out(1:blkLength); yDec = cast((llr>=0), typeyEnc); end```