function Detectors(varargin)
% -- set up default/custom parameters
if isempty(varargin)
disp('using default simulation settings and parameters...')
par.simName = 'ERR_128x16_64QAM'; % simulation name (used for saving results)
par.runId = 0; % simulation ID (used to reproduce results)
par.MR = 128; % receive antennas
par.MT = 16; % transmit antennas (set not larger than MR!)
par.mod = '64QAM'; % modulation type: 'BPSK','QPSK','16QAM','64QAM'
par.trials = 1e3; % number of Monte-Carlo trials (transmissions)
par.SNRdB_list = 0:2:20; % list of SNR [dB] values to be simulated
par.detector = {'MMSE', 'SOR', }
par.maxiter = 3; % max number of iterations n = 1 to any integer
par.omega = 2; % relaxation parameter for SOR
alpha = 1/par.omega;
else
disp('use custom simulation settings and parameters...')
par = varargin{1}; % only argument is par structure
end
% -- initialization
% use runId random seed (enables reproducibility)
rng('default');
% set up Gray-mapped constellation alphabet (according to IEEE 802.11)
switch (par.mod)
case 'BPSK',
par.symbols = [ -1 1 ];
case 'QPSK',
par.symbols = [ -1-1i,-1+1i, ...
+1-1i,+1+1i ];
case '16QAM',
par.symbols = [ -3-3i,-3-1i,-3+3i,-3+1i, ...
-1-3i,-1-1i,-1+3i,-1+1i, ...
+3-3i,+3-1i,+3+3i,+3+1i, ...
+1-3i,+1-1i,+1+3i,+1+1i ];
case '64QAM',
par.symbols = [ -7-7i,-7-5i,-7-1i,-7-3i,-7+7i,-7+5i,-7+1i,-7+3i, ...
-5-7i,-5-5i,-5-1i,-5-3i,-5+7i,-5+5i,-5+1i,-5+3i, ...
-1-7i,-1-5i,-1-1i,-1-3i,-1+7i,-1+5i,-1+1i,-1+3i, ...
-3-7i,-3-5i,-3-1i,-3-3i,-3+7i,-3+5i,-3+1i,-3+3i, ...
+7-7i,+7-5i,+7-1i,+7-3i,+7+7i,+7+5i,+7+1i,+7+3i, ...
+5-7i,+5-5i,+5-1i,+5-3i,+5+7i,+5+5i,+5+1i,+5+3i, ...
+1-7i,+1-5i,+1-1i,+1-3i,+1+7i,+1+5i,+1+1i,+1+3i, ...
+3-7i,+3-5i,+3-1i,+3-3i,+3+7i,+3+5i,+3+1i,+3+3i ];
end
% extract average symbol energy
par.Es = mean(abs(par.symbols).^2);
% precompute bit labels
par.Q = log2(length(par.symbols)); % number of bits per symbol
par.bits = de2bi(0:length(par.symbols)-1,par.Q,'left-msb');
% track simulation time
time_elapsed = 0;
% -- start simulation
% initialize result arrays (detector x SNR)
res.VER = zeros(length(par.detector),length(par.SNRdB_list)); % vector error rate
res.SER = zeros(length(par.detector),length(par.SNRdB_list)); % symbol error rate
res.BER = zeros(length(par.detector),length(par.SNRdB_list)); % bit error rate
% generate random bit stream (antenna x bit x trial)
bits = randi([0 1],par.MT,par.Q,par.trials);
% trials loop
tic
for t=1ar.trials
t
% generate transmit symbol
idx = bi2de(bits,:,t),'left-msb')+1;
s1 = par.symbols(idx).';
% generate iid Gaussian channel matrix & noise vector
n = sqrt(0.5)*(randn(par.MR,1)+1i*randn(par.MR,1));
H = sqrt(0.5)*(randn(par.MR,par.MT)+1i*randn(par.MR,par.MT));
% transmit over noiseless channel (will be used later)
x = H*s1;
% SNR loop
for k=1:length(par.SNRdB_list)
% compute noise variance (average SNR per receive antenna is: SNR=MT*Es/N0)
N0 = par.MT*par.Es*10^(-par.SNRdB_list(k)/10);
% transmit data over noisy channel
y = x+sqrt(N0)*n;
for d=1:length(par.detector)
switch (par.detector{d}) % select algorithms
case 'MMSE', % MMSE detector
[idxhat,bithat] = MMSE(par,H,y,N0);
case 'SOR' % SOR
[idxhat,bithat] = SOR(par,H,y,N0,alpha);
otherwise,
error('par.detector type not defined.')
end
% -- compute error metrics
err = (idx~=idxhat);
res.VER(d,k) = res.VER(d,k) + any(err);
res.SER(d,k) = res.SER(d,k) + sum(err)/par.MT;
res.BER(d,k) = res.BER(d,k) + sum(sum(bits,:,t)~=bithat))/(par.MT*par.Q);
end % algorithm loop
end % SNR loop
% keep track of simulation time
if toc>10
time=toc;
time_elapsed = time_elapsed + time;
fprintf('estimated remaining simulation time: %3.0f min.\n',time_elapsed*(par.trials/t-1)/60);
tic
end
end % trials loop
% normalize results
res.VER = res.VER/par.trials;
res.SER = res.SER/par.trials;
res.BER = res.BER/par.trials;
res.time_elapsed = time_elapsed
% -- save final results (par and res structure)
% -- show results (generates fairly nice Matlab plot)
marker_style = {'mo-','ks-','kv-.','rp:','r*-','c>--','cx:','b-.','bo--', 'yd-', 'yh-.', 'g>-.', 'gp-'};
figure(1)
for d=1:length(par.detector)
if d==1
semilogy(par.SNRdB_list,res.BER(d,,marker_style{d},'LineWidth',2)
hold on
else
semilogy(par.SNRdB_list,res.BER(d,,marker_style{d},'LineWidth',2)
end
end
hold off
grid on
%xlabel('average SNR per receive antenna [dB]','FontSize',12)
xlabel('SNR [dB]','FontSize',12)
ylabel('BER','FontSize',12)
axis([min(par.SNRdB_list) max(par.SNRdB_list) 1e-5 1])
legend(par.detector,'FontSize',12)
set(gca,'FontSize',12)
title(['Performance comparison in ' int2str(par.MT) ' x ' int2str(par.MR) ', n = ' int2str(par.maxiter)]);
end
%% MMSE detector (MMSE)
function [idxhat,bithat] = MMSE(par,H,y,N0)
W = (H'*H+(N0/par.Es)*eye(par.MT))\(H');
xhat = W*y;
G = real(diag(W*H));
[~,idxhat] = min(abs(xhat*ones(1,length(par.symbols))-G*par.symbols).^2,[],2);
bithat = par.bits(idxhat,;
end
%% SOR
% omega is the relaxation parameter 0<w<2
function [idxhat,bithat] = SOR(par,H,y,N0,alpha)
A = H'*H+(N0/par.Es)*eye(par.MT);
MF = H'*y;
D = diag(diag(A)); %D
E = -triu(A,1); %L=-(tril(HH)-D);
F = -tril(A,-1); %U=-(triu(HH)-D);
xhat = diag(inv(D));% inv(D)*MF;
for i = 0ar.maxiter %par.alg.maxiter
xhat = inv(D-alpha*E)*(alpha*MF+((1-alpha)*D + alpha*F)*xhat);
end
[~,idxhat] = min(abs(xhat*ones(1,length(par.symbols))-ones(par.MT,1)*par.symbols).^2,[],2);
bithat = par.bits(idxhat,;
end