CTC (Convolutional Turbo Code) Basics and MATLAB Implementation

This document provides an overview of CTC encoders and their specifications, along with relevant MATLAB code. It focuses on Convolutional Turbo Code (CTC) encoding.

The following figure illustrates the structure of a CTC encoder, including its constituent encoders.

CTC encoder CTC encoder

The CTC encoder employs a double binary circular recursive systematic convolutional code. The MATLAB code provided below implements the CTC structure depicted in the figure.

For a more general explanation of CTC encoders, refer to the Turbo encoder page, which describes the basics of Convolutional Turbo Encoding with a rate 1/3 example, commonly used for forward error correction.

A key difference between convolutional encoders and turbo encoders is that convolutional encoders do not preserve input bits, while turbo encoders do. In turbo coding, input bits are preserved and multiplexed with altered bits generated by the encoder and (interleaver + encoder) modules.

CTC Encoder MATLAB Code

function OutBits = CTCEncoder(InpBits, N, P)
    CircularStateTable = [
        0   6   4   2   7   1   3   5;
        0   3   7   4   5   6   2   1;
        0   5   3   6   2   7   1   4;
        0   4   1   5   6   2   7   3;
        0   2   5   7   1   3   4   6;
        0   7   6   1   3   4   5   2
    ];
    InitState = [0 0 0];

    [Junk, FinalState] = CTCRSCEncoder(InpBits, N, InitState);

    Ri = mod(N, 7);
    Ci = FinalState(1)*4 + FinalState(2)*2 + FinalState(3);
    CS = CircularStateTable(Ri+1, Ci+1);
    InitState(1) = floor(CS/4);
    CS = mod(CS,4);
    InitState(2) = floor(CS/2);
    CS = mod(CS,2);
    InitState(3) = CS;

    [p1, FS] = CTCRSCEncoder(InpBits, N, InitState);

    if sum(FS == InitState) ~= 3
        disp('P1 mismatch')
        return
    end

    IB = CTCInterleaver(InpBits, N, P);
    InitState = [0 0 0];
    [Junk, FinalState] = CTCRSCEncoder(IB, N, InitState);

    Ri = mod(N, 7);
    Ci = FinalState(1)*4 + FinalState(2)*2 + FinalState(3);
    CS = CircularStateTable(Ri+1, Ci+1);
    InitState(1) = floor(CS/4);
    CS = mod(CS,4);
    InitState(2) = floor(CS/2);
    CS = mod(CS,2);
    InitState(3) = CS;

    [p2, FS] = CTCRSCEncoder(IB, N, InitState);

    if sum(FS == InitState) ~= 3
        disp('P2 mismatch')
        return
    end

    OutBits = zeros(6*N, 1);
    for k = 0:N-1
        OutBits(6*k+1) = InpBits(2*k+1);
        OutBits(6*k+2) = InpBits(2*k+2);
        OutBits(6*k+3) = p1(2*k+1);
        OutBits(6*k+4) = p2(2*k+1);
        OutBits(6*k+5) = p1(2*k+2);
        OutBits(6*k+6) = p2(2*k+2);
    end
end

function [ParityBits, FinState] = CTCRSCEncoder(InpBits, N, InitState)
%[ParityBits, FinState] = CTCRSCEncoder(InpBits, N, InitState)
%InitState = initial state of encoder (0 to 7) in binary
%FinState = final state of encoder (0 to 7) in binary

    load 'CTCEncTable'
    TNxt = CTCEncTable(:, 6:8);
    TOut = CTCEncTable(:, 9:10);
    ParityBits = zeros(2*N, 1);
    CS = InitState;

    for k = 0:N-1
        A = InpBits(2*k+1);
        B = InpBits(2*k+2);
        m = CS(1)*16 + CS(2)*8 + CS(3)*4 + A*2 + B;
        NS = TNxt(m+1, :);
        Pb = TOut(m+1, :);
        ParityBits(2*k+1) = Pb(1);
        ParityBits(2*k+2) = Pb(2);
        CS = NS;
    end
    FinState = NS;
end

function InterleavedBits = CTCInterleaver(InpBits, N, P)
%InterleavedBits = CTCInterleaver(InpBits, N, P)
%N - Length of input bit in pairs
%P - [p0 p1 p2 p3], interleaver parameters

    InterleavedBits = zeros(2*N, 1);
    xI = zeros(N, 2);

    for k = 0:N-1
        m = CTCGetInterleavedAddress(k, N, P);
        A = InpBits(2*m+1);
        B = InpBits(2*m+2);

        if mod(k, 2) == 1
            InterleavedBits(2*k+1) = A;
            InterleavedBits(2*k+2) = B;
        else
            InterleavedBits(2*k+1) = B;
            InterleavedBits(2*k+2) = A;
        end
    end
end