-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathzf_MIMO.m
executable file
·169 lines (125 loc) · 6.68 KB
/
zf_MIMO.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% © All rights reserved. ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE, Switzerland,
% Laboratory Algorithmic Research in Network Information (ARNI), 2015
% AUTHORS: Emre ATSAN
%
% See the LICENSE.TXT file for more details.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ IQNorm_RX_MIMO ] = zf_MIMO( nTXNodes, nsym_OFDM, nsubc_data, CE_TX, Data, h_demod, constellation_scale )
%ZF_MIMO Zero-forcing MIMO decoder with successive interference cancellation.
% Ordering of symbol cancellation is done per stream SNR basis.
IQNorm_RX_MIMO = zeros(nsubc_data,nsym_OFDM,nTXNodes);
%SNR_Estimate_perdatasubc_perOFDMSymbol_perTXdata = zeros(nsubc_data,nsym_OFDM,nTXNodes);
W = zeros(nTXNodes,nTXNodes,nsym_OFDM*nsubc_data);
H = zeros(nTXNodes,nTXNodes,nsym_OFDM*nsubc_data);
y = zeros(nTXNodes,1,nsym_OFDM*nsubc_data);
%snr_sum_rx_antennas = zeros(nsubc_data);
h_mod = modem.qammod(h_demod);
%CM = zeros(nsubc_data,nsym_OFDM);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MIMO ZF-SIC decoder. (with MRC combining after SIC)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for ofdm_symbol=1:nsym_OFDM
for subc=1:nsubc_data
linear_seq_id = ((ofdm_symbol-1)*nsubc_data)+subc;
for stream=1:nTXNodes
for antenna=1:nTXNodes
H(antenna,stream,linear_seq_id) = CE_TX(subc,stream,antenna);
end
y(stream,1,linear_seq_id) = Data(subc,ofdm_symbol,stream);
end
%Condition number check to validate enough diversity / linear
%independence exists for the channel matrix observed.
% CM(subc,ofdm_symbol) = cond(H(1:nTXNodes,1:nTXNodes,linear_seq_id));
% ch_n = mag2db(abs(CM(subc,ofdm_symbol)));
%
% if(ch_n > 15)
% fprintf('SUBC:[%d]/SYM:[%d] -cond(H): %3f dB. \n',subc,ofdm_symbol,ch_n);
% end
% ZF equalizer matrix, W
if (nTXNodes==2)
W(1:nTXNodes,1:nTXNodes,linear_seq_id) = fast_2by2_inverse(H(1:nTXNodes,1:nTXNodes,linear_seq_id)); %pinv(H); %pseudo-inverse of channel matrix for subcarrier,subc.
else
W(1:nTXNodes,1:nTXNodes,linear_seq_id) = pinv(H(1:nTXNodes,1:nTXNodes,linear_seq_id));
end
% if(ofdm_symbol==1)
% snr_sum_rx_antennas(subc) = sum(SNR(subc,1:nTXNodes));
% end
end
end
% Succesive Inteference Cancellation with Optimal Ordering
%
% 1) based on post detection SNR [from book MIMO-OFDM Wireless Communications
% with MATLAB, ebooks folder]. (SNR is computed by computing the
% 1/Norm(rows of W).
%
% 2) Column norm ordering detection
for stream=1:nTXNodes
%1)
% norm_W(stream,:) = sqrt( sum(abs(squeeze(W(stream,1:nTXNodes,:))).^2,1));
%2)
norm_W(stream,:) = sqrt(sum(abs(squeeze(H(:,stream,:))).^2,1));
end
[~,estimation_order]=sort(norm_W,1,'descend');
%estimation_order(end:-1:1,:);
x_hat=zeros(nTXNodes,nsym_OFDM*nsubc_data);
%snr_zf=zeros(nTXNodes,nsym_OFDM*nsubc_data);
for s = 1:nTXNodes
% Spatial stream is detected due to its post-detection SNR (1/W(row)) order or column norm (norm(H(:,col)))detection order.
next_stream(:,1) = squeeze(estimation_order(s,:)).';
%If this is the last pass to estimate the next stream per subcarrier, use MRC.
if(s==nTXNodes)
for i=1:1:nsym_OFDM*nsubc_data
H_tilde = H(:,next_stream(i),i);
% Use MRC to combine the estimated version of the last
% stream from all antennas.
x_hat(next_stream(i),i) = MRC_Equalizer(y(1:nTXNodes,1,i),H_tilde);
% [sbc,~]=ind2sub([nsubc_data,nsym_OFDM],i); % SLOW, NOT
% BUILT-IN FUNCTION.
%sbc = rem(i-1,nsubc_data)+1;
%snr_zf(next_stream(i),i) = (snr_sum_rx_antennas(sbc).*(1/nTXNodes)) * (1/((norm_W(next_stream(i),i)).^2));
end
idx=sub2ind(size(x_hat),next_stream',1:1:(nsubc_data*nsym_OFDM));
x_sliced = QAM_Slicer(h_mod,h_demod,constellation_scale,x_hat(idx));
if(isreal(x_sliced)) %In case of BPSK, output of slicer is not complex number.
x_sliced = complex(x_sliced);
end
%Check the EVM value of the first estimated streams per subcarrier.
rms_evm=step(comm.EVM,squeeze(x_sliced).',squeeze(x_hat(idx)).');
fprintf('EVM of 2nd estimated stream per subcarriers: %4f percent.\n', rms_evm);
else
for i=1:1:nsym_OFDM*nsubc_data
x_hat(next_stream(i),i)= W(next_stream(i),1:nTXNodes,i) * y(1:nTXNodes,1,i);
%[sbc,~]=ind2sub([nsubc_data,nsym_OFDM],i); % SLOW- NOT
%BUILT-IN
%sbc = rem(i-1,nsubc_data)+1;
%snr_zf(next_stream(i),i) = (snr_sum_rx_antennas(sbc).*(1/nTXNodes)) * (1/((norm_W(next_stream(i),i)).^2));
end
idx=sub2ind(size(x_hat),next_stream',1:1:(nsubc_data*nsym_OFDM));
x_sliced = QAM_Slicer(h_mod,h_demod,constellation_scale,x_hat(idx));
%Check the EVM value of the first estimated subcarriers set.
if(isreal(x_sliced)) %In case of BPSK, output of slicer is not complex number.
x_sliced = complex(x_sliced);
end
rms_evm=step(comm.EVM,squeeze(x_sliced).',squeeze(x_hat(idx)).');
fprintf('EVM of 1st estimated stream per subcarriers: %4f percent.\n', rms_evm);
%Make an hard-decision for the symbols of the first estimation
%if rms_evm is below 15% %This should be verified.
% if(rms_evm < 15)
% x_hat(idx) = x_sliced;
% end
for i=1:1:nsym_OFDM*nsubc_data
y(:,:,i) = y(:,:,i)-H(:,next_stream(i),i)*x_sliced(1,i); % Interference subtraction - SIC
end
end
end
for i=1:1:nsym_OFDM*nsubc_data
% [sbc,sym]=ind2sub([nsubc_data,nsym_OFDM],i); %SLOW - NOT BUILT IN
sbc = rem(i-1,nsubc_data)+1;
sym = (i-sbc)/nsubc_data + 1;
IQNorm_RX_MIMO(sbc,sym,1:nTXNodes) = x_hat(:,i);
%SNR_Estimate_perdatasubc_perOFDMSymbol_perTXdata(sbc,sym,1:nTXNodes)=snr_zf(:,i);
end
end