-
Notifications
You must be signed in to change notification settings - Fork 0
/
QCLDPC2.m
229 lines (206 loc) · 7.11 KB
/
QCLDPC2.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
% QCLDPC performance analysis
% modify mydecldpc.decodeSP_layer with mydecldpc.decodeMS_layer to run other algorithm
% check the path of the Base graph:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
bspath = 'C:\Program Files\MATLAB\R2019a\toolbox\5g\5g\+nr5g\+internal\+ldpc\baseGraph';
% parameters
Es = 1; % energy per symbol
max_iter = 15; % max iteration count
bgn = 1; % bbase graph number
C = 1000; % minimun simulation times per SNR
Zc = 32; % lifting size
K = 22*Zc; % message length
thres = 100; % minimun error count per SNR
code_rate = 1/2; % code rate
snrdb = [0:0.2:2.6]; % SNR for simultion (in dB)
ber_res = zeros(2,length(snrdb)); % saving BER(bit error rate)
rng(0); % set random seed
err_limit = 10e-6; % minimun error rate
running = true;
% initailize QCLDPC PCM(partiy check matrix)
[LDPCParityCheckMatrix, B] = getPCM(bgn, K, code_rate, bspath);
% LDPC encode & decoder setting
encldpc = comm.LDPCEncoder(LDPCParityCheckMatrix);
mydecldpc = mydecoder(LDPCParityCheckMatrix, max_iter, Zc);
% simulate per SNR
for jj = 1:length(snrdb)
snr = 10^(snrdb(jj)/10);
% apply PSK modulator and demodulator
pskModulator = comm.PSKModulator(...
'ModulationOrder', 4,...
'BitInput', true, ...
'PhaseOffset', pi / 4, ...
'SymbolMapping', 'Custom', ...
'CustomSymbolMapping', [0 2 3 1]);
pskDemodulator = comm.PSKDemodulator(...
'ModulationOrder', 4, ...
'BitOutput', true, ...
'PhaseOffset', pi /4 , ...
'SymbolMapping', 'Custom', ...
'CustomSymbolMapping', [0 2 3 1], ...
'DecisionMethod', 'Approximate log-likelihood ratio', ...
'Variance', Es/snr);
chan = comm.AWGNChannel(...
'NoiseMethod', 'Variance',...
'Variance', Es/snr);
% Get the constellation
cacheBitInput = pskModulator.BitInput;
pskModulator.BitInput = false;
constellation = pskModulator((0:pskModulator.ModulationOrder-1)');
release(pskModulator);
pskModulator.BitInput = cacheBitInput;
error_cnt = 0;
time_cnt = 0;
% iterate C times
for ii = 1:C
message = randi([0, 1], K, 1);
ldpcEncOut = encldpc(message);
modOut = pskModulator(ldpcEncOut);
chanOut = chan(modOut);
demodOut = pskDemodulator(chanOut);
tic;
ldpcDecOut = mydecldpc.decodeSP_layer(demodOut')';
time_cnt = time_cnt + toc;
error_cnt = error_cnt + sum(message ~= ldpcDecOut, 'all');
end
% iterate to minimun error count
num = 0;
while error_cnt < thres
num = num + 1;
message = randi([0, 1], K, 1);
ldpcEncOut = encldpc(message);
modOut = pskModulator(ldpcEncOut);
chanOut = chan(modOut);
demodOut = pskDemodulator(chanOut);
ldpcDecOut = mydecldpc.decodeSP_layer(demodOut')';
error_cnt = error_cnt + sum(message ~= ldpcDecOut, 'all');
if error_cnt / K / (C+num) < err_limit
running = false;
break;
end
end
% calculate BER & show
ber_res(1,jj) = error_cnt / K / (C+num);
fprintf("(MAT) BER is %.5f at snr %0.1fdB spending %03.2fs\n", ber_res(1,jj), snrdb(jj), time_cnt);
if ~running
break;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [PCM, P] = getPCM(bgn, info_length, code_rate, bspath)
% Check the size & calculate lifting size
% Base graph 1 is 46 * 68
% Base graph 2 is 42 * 52
if bgn == 1
if mod(info_length, 22) ~= 0
error("InValid data length %d, it must be mutiple of 22 for base graph 1", info_length)
end
Zc = info_length / 22;
elseif bgn == 2
if mod(info_length, 10) ~= 0
error("InValid data length %d, it must be mutiple of 10 for base graph 2", info_length)
end
Zc = info_length / 10;
else
error("InValid index: No base graph number %d", bgn)
end
% load base graph
persistent bgs
if isempty(bgs)
bgs = coder.load(bspath);
end
% Get lifting set number
ZSets = {[2 4 8 16 32 64 128 256],... % Set 1
[3 6 12 24 48 96 192 384],... % Set 2
[5 10 20 40 80 160 320],... % Set 3
[7 14 28 56 112 224],... % Set 4
[9 18 36 72 144 288],... % Set 5
[11 22 44 88 176 352],... % Set 6
[13 26 52 104 208],... % Set 7
[15 30 60 120 240]}; % Set 8
for setIdx = 1:8
if any(Zc==ZSets{setIdx})
break;
end
end
switch bgn
case 1
switch setIdx
case 1
V = bgs.BG1S1;
case 2
V = bgs.BG1S2;
case 3
V = bgs.BG1S3;
case 4
V = bgs.BG1S4;
case 5
V = bgs.BG1S5;
case 6
V = bgs.BG1S6;
case 7
V = bgs.BG1S7;
otherwise % 8
V = bgs.BG1S8;
end
switch code_rate
case 1/2
V = V(1:24, 1:46);
case 2/3
V = V(1:13, 1:35);
case 2/5
V = V(1:35, 1:57);
case 1/3
V = V;
otherwise
error("Not supporting code rate")
end
otherwise % bgn = 2
switch setIdx
case 1
V = bgs.BG2S1;
case 2
V = bgs.BG2S2;
case 3
V = bgs.BG2S3;
case 4
V = bgs.BG2S4;
case 5
V = bgs.BG2S5;
case 6
V = bgs.BG2S6;
case 7
V = bgs.BG2S7;
otherwise % 8
V = bgs.BG2S8;
end
switch code_rate
case 1/2
V = V(1:12, 1:22);
case 1/3
V = V(1:22, 1:32);
case 1/5
V = V;
otherwise
error("Not supporting code rate")
end
end
% Get shift values matrix & construct PCM
P = nr5g.internal.ldpc.calcShiftValues(V,Zc);
% construct Full PCM
[row, col] = size(P);
PCM = zeros(row*Zc, col*Zc);
for ii = 1 : row
for jj = 1 : col
if P(ii,jj) ~= -1
row_from = (ii-1)*Zc + 1;
row_to = ii*Zc;
col_from = (jj-1)*Zc + 1;
col_to = jj*Zc;
PCM(row_from:row_to, col_from:col_to) = circshift(eye(Zc), P(ii,jj), 2);
end
end
end
PCM = sparse(PCM);
end