MATLAB Script
%% TURBO CODE SIMULATION: BPSK BIT-STREAM
% This script demonstrates Turbo Coding gain on a random bit-stream.
clear; clc; close all;
%% 1. Parameters and Signal Generation
num_bits = 10000; % Total number of bits to simulate
data_bits = randi([0 1], 1, num_bits); % Generate random 0s and 1s
%% 2. Turbo Encoding
key = 123; % Interleaver seed
puncture = 0; % 0 = Rate 1/3
len = length(data_bits);
fprintf('Encoding %d bits... ', len);
[encoded_bits, alpha] = turbo_encode(data_bits, len, key, puncture);
fprintf('Done.\n');
%% 3. Noisy Channel (AWGN)
snr_db = 4;
sigma = sqrt(1 / (2 * 10^(snr_db/10) * (1/3)));
% Add Gaussian noise to BPSK modulated signal (-1, +1)
noisy_signal = encoded_bits + sigma * randn(size(encoded_bits));
%% 4. Turbo Decoding
fprintf('Decoding bits (5 Iterations SOVA)... \n');
decoded_bits = turbo_decode(noisy_signal, key, puncture, len);
%% 5. Reconstruction (Simple Comparison)
% In BPSK bit-stream, reconstruction is just the decoded bits themselves
reconstructed_bits = decoded_bits;
% Create unencoded BPSK noisy version for comparison
unencoded_bpsk_signal = (2*data_bits - 1) + sigma * randn(size(data_bits));
unencoded_decoded = (sign(unencoded_bpsk_signal) + 1) / 2;
%% 6. Results and Plotting
errs = sum(data_bits ~= reconstructed_bits);
raw_errs = sum(data_bits ~= unencoded_decoded);
fprintf('Finished.\n');
fprintf('-----------------------------------\n');
fprintf('Unencoded BER: %.4f\n', raw_errs/num_bits);
fprintf('Turbo Coded BER: %.4f\n', errs/num_bits);
fprintf('-----------------------------------\n');
figure('Color', 'w', 'Name', 'Turbo Code Performance', 'Position', [100, 100, 1000, 700]);
% Plot first 100 bits for visual clarity
plot_range = 1:100;
subplot(3,1,1);
stairs(plot_range, data_bits(plot_range), 'b', 'LineWidth', 1.5);
title('1. Original Data Bits (First 100)');
grid on; ylim([-0.2 1.2]); ylabel('Bit Value');
subplot(3,1,2);
plot(plot_range, unencoded_bpsk_signal(plot_range), 'r');
hold on; stairs(plot_range, unencoded_decoded(plot_range), 'k', 'LineWidth', 1);
title(['2. Raw Noisy BPSK Signal (Unencoded) at ', num2str(snr_db), ' dB']);
grid on; ylabel('Amplitude'); legend('Noisy Signal', 'Hard Decision');
subplot(3,1,3);
stairs(plot_range, reconstructed_bits(plot_range), 'Color', [0 0.5 0], 'LineWidth', 1.5);
title('3. Decoded Bits (After Turbo Decoding)');
grid on; ylim([-0.2 1.2]); ylabel('Bit Value'); xlabel('Bit Index');
%% --- TURBO FUNCTIONS (NO CHANGES NEEDED) ---
function [seqout, alpha] = turbo_encode(seqin, len, key, puncture)
g = [1 1 1; 1 0 1];
m = size(g,2)-1;
L_total = len + m;
rng(key);
alpha = randperm(L_total);
out1 = rsc_encode(g, seqin, 1);
s = out1(1:2:end);
p1 = out1(2:2:end);
s_int = s(alpha);
out2 = rsc_encode(g, s_int, -1);
p2 = out2(2:2:end);
seqout = zeros(1, 3*L_total);
seqout(1:3:end) = s;
seqout(2:3:end) = p1;
seqout(3:3:end) = p2;
seqout = 2*seqout - 1;
end
function seqout = turbo_decode(seqin, key, puncture, original_len)
g = [1 1 1; 1 0 1];
L_total = length(seqin)/3;
rng(key);
alpha = randperm(L_total);
[~, inv_alpha] = sort(alpha);
s = seqin(1:3:end);
p1 = seqin(2:3:end);
p2 = seqin(3:3:end);
L_e = zeros(1, L_total);
Lc = 4;
for iter = 1:5
La1 = L_e(inv_alpha);
rec1 = zeros(1, 2*L_total);
rec1(1:2:end) = s; rec1(2:2:end) = p1;
L_all1 = sova_decoder(rec1*Lc, g, La1);
L_e = L_all1 - s*Lc - La1;
La2 = L_e(alpha);
rec2 = zeros(1, 2*L_total);
rec2(1:2:end) = s(alpha); rec2(2:2:end) = p2;
L_all2 = sova_decoder(rec2*Lc, g, La2);
L_e = L_all2 - s(alpha)*Lc - La2;
end
final_llr = L_all2(inv_alpha);
seqout = (sign(final_llr) + 1)/2;
seqout = seqout(1:original_len);
end
function L_all = sova_decoder(rec_s, g, L_a)
[~,K] = size(g); m = K-1; nstates = 2^m;
L_total = length(L_a);
[~, ~, lo, ls] = get_trellis(g);
pm = ones(nstates, L_total+1) * -1e10; pm(1,1) = 0;
Mdiff = zeros(nstates, L_total+1);
prev_bit = zeros(nstates, L_total+1);
for t = 1:L_total
y = rec_s(2*t-1:2*t);
for s = 1:nstates
s0 = ls(s,1); s1 = ls(s,2);
m0 = y*lo(s,1:2)' - L_a(t)/2 + pm(s0,t);
m1 = y*lo(s,3:4)' + L_a(t)/2 + pm(s1,t);
if m0 > m1
pm(s,t+1) = m0; Mdiff(s,t+1) = m0-m1; prev_bit(s,t+1) = 0;
else
pm(s,t+1) = m1; Mdiff(s,t+1) = m1-m0; prev_bit(s,t+1) = 1;
end
end
end
ml = zeros(1, L_total+1);
[~, ml(end)] = max(pm(:, end));
est = zeros(1, L_total);
for t = L_total:-1:1
est(t) = prev_bit(ml(t+1), t+1);
ml(t) = ls(ml(t+1), est(t)+1);
end
L_all = (2*est - 1) .* Mdiff(sub2ind(size(Mdiff), ml(2:end), 2:L_total+1));
end
function [next_out, next_state, last_out, last_state] = get_trellis(g)
m = size(g,2)-1; nstates = 2^m;
next_state = zeros(nstates, 2); next_out = zeros(nstates, 4);
for s = 1:nstates
st_vec = dec2bin(s-1, m) - '0';
for bit = 0:1
v = mod(bit + sum(g(1,2:end).*st_vec), 2);
p = mod(sum(g(2,:).*[v st_vec]), 2);
ns_vec = [v st_vec(1:end-1)];
ns_dec = bin2dec(char(ns_vec+'0')) + 1;
next_state(s, bit+1) = ns_dec;
next_out(s, bit*2+1:bit*2+2) = 2*[bit p]-1;
end
end
last_state = zeros(nstates, 2); last_out = zeros(nstates, 4);
for b = 0:1
for s = 1:nstates
target = next_state(s, b+1);
last_state(target, b+1) = s;
last_out(target, b*2+1:b*2+2) = next_out(s, b*2+1:b*2+2);
end
end
end
function y = rsc_encode(g, x, term)
m = size(g,2)-1; L = length(x);
if term > 0, L_total = L + m; else, L_total = L; end
state = zeros(1,m); y = zeros(1, 2*L_total);
for i = 1:L_total
u = 0; if i <= L, u = x(i); else, u = mod(sum(g(1,2:end).*state), 2); end
v = mod(u + sum(g(1,2:end).*state), 2);
p = mod(sum(g(2,:).*[v state]), 2);
y(2*i-1:2*i) = [u p];
state = [v state(1:end-1)];
end
end
Output
Encoding 10000 bits... Done.
Decoding bits (5 Iterations SOVA)...
Finished.
-----------------------------------
Unencoded BER: 0.0969
Turbo Coded BER: 0.0000
-----------------------------------