Skip to content

Instantly share code, notes, and snippets.

@sp5wwp
Last active October 27, 2022 10:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sp5wwp/8fe498e831128867690835770f5d0417 to your computer and use it in GitHub Desktop.
Save sp5wwp/8fe498e831128867690835770f5d0417 to your computer and use it in GitHub Desktop.
clear; clc;
G1=23; %G_1 polynomial in octal notation
G2=35; %G_2 -//-
K=5; %convolutional encoder constraint length
symbols=10000; %test message length in symbols
depth=11; %bit resolution of the soft decoder
head=20; %run-up for the root-nyquist filter in symbols
span=8; %rnyq filter span
sps=10; %samples per symbol
alpha=0.5; %bandwidth excess
start=0.0; %start SNR, dB
stop=3.0; %end SNR, dB
step=1.0; %step, dB
%pick one of the filters
%flt=rcosdesign(alpha, span, sps); %tx and rx filter
flt=rNyquistM(span*sps, sps, alpha, 25000, 0.0, 0.0, 10000)';
%generate sample symbol stream
s=randi([0, 3], 1, symbols);
s=(s-1.5)*2.0;
%convert the symbol stream to binary stream
msg=[];
for i=1:symbols
if s(i)==3
msg=[msg 0 1];
elseif s(i)==1
msg=[msg 0 0];
elseif s(i)==-1
msg=[msg 1 0];
elseif s(i)==-3
msg=[msg 1 1];
end
end
%generate the trellis and encode the data with K-1 flushing bits at the end
trel=poly2trellis(K, [G1 G2]);
coded=convenc([msg zeros(1, K-1)], trel); %data with flushing bits
%convert the coded bitstream to symbol stream
coded_symbols=[];
for i=1:2:length(coded)-1
if coded(i)==0 && coded(i+1)==1
coded_symbols=[coded_symbols 3];
elseif coded(i)==0 && coded(i+1)==0
coded_symbols=[coded_symbols 1];
elseif coded(i)==1 && coded(i+1)==0
coded_symbols=[coded_symbols -1];
elseif coded(i)==1 && coded(i+1)==1
coded_symbols=[coded_symbols -3];
end
end
%upsample the symbol stream
%the symbol stream has a 'run-up' part so that the root nyquist filter can
%settle. there's also a tail to flush the filter
s=upsample([ones(1, head) coded_symbols ones(1, span)], sps);
%let's get the party started
%we iterate for SNRs in the given range
n=1;
for snr=start:step:stop
%filter the symbol stream with a root nyquist filter (at the 'transmitter')
%apply some AWGN (that's the 'radio channel')
%filter again (at the 'receiver')
sigf=filter(flt, 1, s);
sigf=awgn(sigf, snr, 'measured');
sigf=filter(flt, 1, sigf);
%recover the encoded message
rx_msg=[];
for i=head+span:length(s)/sps-1
rx_symb=sigf(1+i*sps);
%bit 1
if rx_symb<=-1
rx_msg=[rx_msg 2^depth-1];
elseif rx_symb<=1
rx_msg=[rx_msg floor(-(2^depth-1)/2*rx_symb+(2^depth-1)/2)];
else
rx_msg=[rx_msg 0];
end
%bit 0
if rx_symb<=-3
rx_msg=[rx_msg 2^depth-1];
elseif rx_symb<=-1
rx_msg=[rx_msg floor(-(2^depth-1)/2*rx_symb-(2^depth-1)/2)];
elseif rx_symb<=1
rx_msg=[rx_msg 0];
elseif rx_symb<=3
rx_msg=[rx_msg floor((2^depth-1)/2*rx_symb-(2^depth-1)/2)];
else
rx_msg=[rx_msg 2^depth-1];
end
end
%decode the message using soft viterbi decoder
decoded=vitdec(rx_msg, trel, K-1, 'trunc', 'soft', depth);
%calculate the bit error rate
ber(n)=biterr(msg, decoded(1:symbols*2))/symbols/2;
n=n+1;
end
%plot the BER curve
x=linspace(start, stop, n-1);
semilogy(x, ber);
grid on;
xlabel("SNR (dB)");
ylabel("Bit Error Rate");
yline(0.01, 'red'); %red line at 1% BER
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment