Skip to content

Commit

Permalink
Added demodulation.
Browse files Browse the repository at this point in the history
  • Loading branch information
robmaunder committed Sep 8, 2020
1 parent a50ebe1 commit 6362e1c
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.m~
.DS_Store

45 changes: 4 additions & 41 deletions jac.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,10 @@

function C = jac(A,B)

mode = 0; % Exact Jacobian logarithm
% mode = 1; % Jacobian logarithm using a lookup table
% mode = 2; % Approximate Jacobian logarithm
C = max(A,B) + log(1+exp(-abs(A-B)));
% C = max(A,B);



if(A == -inf && B == -inf)
C = -inf;
else
if mode == 0

C = max(A,B) + log(1+exp(-abs(A-B)));

elseif mode == 1

difference = abs(A-B);
if difference >= 4.5
C = max(A,B);
elseif difference >= 2.252
C = max(A,B) + 0.05;
elseif difference >= 1.508
C = max(A,B) + 0.15;
elseif difference >= 1.05
C = max(A,B) + 0.25;
elseif difference >= 0.71
C = max(A,B) + 0.35;
elseif difference >= 0.433
C = max(A,B) + 0.45;
elseif difference >= 0.196
C = max(A,B) + 0.55;
else % difference >= 0
C = max(A,B) + 0.65;
end

elseif mode == 2

C = max(A,B);

else

error('Invalid Jacobian mode');

end
end
end

2 changes: 1 addition & 1 deletion main_inner.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
IA_count=11;

% Channel SNR in dB
SNR = -6;
SNR = -4;

% Noise variance
N0 = 1/10^(SNR/10);
Expand Down
88 changes: 88 additions & 0 deletions main_mod.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
% EXIT function for a soft-input soft-output demodulator
% Copyright (C) 2008 Robert G. Maunder

% This program is free software: you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation, either version 3 of the License, or (at your
% option) any later version.

% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.

% The GNU General Public License can be seen at http://www.gnu.org/licenses/.



% Number of bits to encode
bit_count=100000;

% Number of a priori mutual informations to consider
IA_count=11;

% Channel SNR in dB
SNR = 0;

% Noise variance
N0 = 1/10^(SNR/10);

% A priori mutual informations to consider
IA = 0.999*(0:1/(IA_count-1):1);

% Initialise results
IE_av=zeros(1,IA_count);
IE_hist=zeros(1,IA_count);
area=0.0;

% Consider each a priori mutual information
for IA_index = 1:IA_count

% Generate some random bits
bits = round(rand(1,bit_count));

% Encode using a half-rate systematic recursive convolutional code having a single memory element
tx = modulate(bits);

% Rayleigh fading
h = sqrt(1/2)*(randn(size(tx))+1i*randn(size(tx)));

% Noise
n = sqrt(N0/2)*(randn(size(tx))+1i*randn(size(tx)));

% Uncorrelated narrowband Rayleigh fading channel
rx = h.*tx + n;


% Generate the a priori LLRs having the a priori mutual information considered
apriori_llrs = generate_llrs(bits, IA(IA_index));

% Do the BCJR
extrinsic_llrs = soft_demodulate(rx, h, N0, apriori_llrs);

% Measure the mutual information of the extrinsic LLRs
IE_hist(IA_index) = measure_mutual_information_histogram(extrinsic_llrs, bits);
IE_av(IA_index) = measure_mutual_information_averaging(extrinsic_llrs);

% Update the area beneath the EXIT function
if(IA_index > 1)
area = area + (IE_av(IA_index)+IE_av(IA_index-1))*(IA(IA_index)-IA(IA_index-1))/2;
end
end


% Plot EXIT function
figure
xlim([0 1]);
ylim([0 1]);
xlabel('Quality of input LLRs (a priori mutual information I_A)');
ylabel('Quality of output LLRs (extrinsic mutual information I_E)');
title(['EXIT function for SNR = ', num2str(SNR), ' dB']);
hold on
plot(IA,IE_hist,'r');
plot(IA,IE_av,'b');
legend({'True quality','Claimed quality'},'Location','northwest');

% Display the area beneath the EXIT function
annotation('textbox','String',{['Area = ', num2str(area)]},'LineStyle','none','Position',[0.7 0.1 0.2 0.1]);

40 changes: 40 additions & 0 deletions modulate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
% QPSK modulator using natural mapping
% Copyright (C) 2010 Robert G. Maunder

% This program is free software: you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation, either version 3 of the License, or (at your
% option) any later version.

% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.

% The GNU General Public License can be seen at http://www.gnu.org/licenses/.

% bits is a k*n vector of bits
% tx is a vector of complex symbols
function tx = modulate(bits)

% Specify the constellation points and the bit mapping here
constellation_points = [+1+1i; -1+1i; -1-1i; +1-1i]/sqrt(2);
bit_labels = [0,0; 0,1; 1,1; 1,0];

% Determine the number of bits per symbol and the number of constellation points here
k = size(bit_labels,2);
M = 2^k;
N = length(bits)/k;


% Check that all the vectors and matrices have the correct dimensions
if ~isequal(size(constellation_points),[M,1]) || ~isequal(size(bit_labels),[M,k])
error('wrong dimensions');
end

symbols = bin2dec(num2str(reshape(bits,[k,N])'))'+1;
tx = constellation_points(symbols);


end

90 changes: 90 additions & 0 deletions soft_demodulate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
% Soft QPSK demodulator using natural mapping
% Copyright (C) 2010 Robert G. Maunder

% This program is free software: you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation, either version 3 of the License, or (at your
% option) any later version.

% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.

% The GNU General Public License can be seen at http://www.gnu.org/licenses/.

% apriori_llrs is a 1xk vector of a priori LLRs
% rx is a complex symbol
% channel is a complex channel coefficient
% N0 is the noise power spectral density
% extrinsic_llrs is a 1xk vector of extrinsic LLRs
function extrinsic_llrs = soft_demodulate(rx, channel, N0, apriori_llrs)

% Specify the constellation points and the bit mapping here
constellation_points = [+1+1i; -1+1i; -1-1i; +1-1i]/sqrt(2);
bit_labels = [0,0; 0,1; 1,0; 1,1];

% Determine the number of bits per symbol and the number of constellation points here
k = size(bit_labels,2);
M = 2^k;
N = length(rx);

% Check that all the vectors and matrices have the correct dimensions
if ~isequal(size(constellation_points),[M,1]) || ~isequal(size(bit_labels),[M,k])
error('wrong dimensions');
end

if length(channel) ~= length(rx) && length(channel) ~= 1
error('wrong dimensions');
end



aposteriori_symbol_LLRs = zeros(M,N);

% Put the influence of the received signals into the symbol LLRs
for perm_index = 1:M
aposteriori_symbol_LLRs(perm_index,:) = -abs(rx-channel*constellation_points(perm_index)).^2./N0;
end

if exist('apriori_llrs','var')
% Put the influence of the apriori LLRs into the symbol LLRs
for bit_index = 1:k
% aposteriori_symbol_LLRs(:,bit_permutations(bit_index,:) == 0) = aposteriori_symbol_LLRs(:,bit_permutations(bit_index,:) == 0) + repmat(apriori_llrs(bit_index:bits_per_symbol:end),[1,permutations/2]);

for perm_index = 1:M
if bit_labels(perm_index,bit_index) == 0
aposteriori_symbol_LLRs(perm_index,:) = aposteriori_symbol_LLRs(perm_index,:) + apriori_llrs(bit_index:k:end);
end
end
end
end

% Extract the aposteriori LLRs from the symbol LLRs
aposteriori_llrs = zeros(1,N*k);
for bit_index = 1:k
p0 = -inf(1,N);
p1 = -inf(1,N);

for perm_index = 1:M
if bit_labels(perm_index,bit_index) == 0
p0 = jac(p0, aposteriori_symbol_LLRs(perm_index,:));
else
p1 = jac(p1, aposteriori_symbol_LLRs(perm_index,:));
end
end

aposteriori_llrs(bit_index:k:end) = p0-p1;
end

if exist('apriori_llrs','var')
% Remove the apriori from the aposteriori to get the extrinsic
extrinsic_llrs = aposteriori_llrs - apriori_llrs;
else
extrinsic_llrs = aposteriori_llrs;
end




end

0 comments on commit 6362e1c

Please sign in to comment.