Robochameleon  v1.0
error_counter_v7b.m
1 function [ber,ser,ber_block,ser_block,blockmap,err_bits,totalbits,err_symb,totalsymb,ORIG_SYMBOLS] = error_counter_v7b(RECEIVED_DATA,REFERENCE_DATA,param)
2 
3 L_block_s = param.L; % Error counter block length, symbols; set to inf for one block
4 M = param.M;
5 coding = param.coding;
6 %TODO Parametrize
7 ber_th = 0.1; % BER threshold above which contribution of a block is rejected
8 % err_th_rot = (0.25/ber_th-1)/2; % Tolerance (%) for BER increase between consecutive blocks, not requiring to try all de-map permutations
9 
10 if nargout<10
11  RETURN_REFERENCE_SEQUENCE = 0;
12 else
13  RETURN_REFERENCE_SEQUENCE = 1;
14 end
15 
16 %% Reference data
17 if ~isvector(REFERENCE_DATA)
18  error('Reference data must be a vector.');
19 end
20 if islogical(REFERENCE_DATA)
21  % Binary sequence -- binary delay & add mode
22  mode = 0;
23  fprintf(1,'Error counter mode: binary delay & add.\n');
24  D_tx_b = REFERENCE_DATA(:)';
25  [~,demap] = constmap('QAM',M,'linear');
26 elseif isa(REFERENCE_DATA,'uint16')
27  % Integer sequence -- synchronized symbols
28  mode = 1;
29  fprintf(1,'Error counter mode: symbols.\n');
30  D_tx_b = symb2bits(REFERENCE_DATA,M); % D_tx_b is recreated from symbols
31  % TODO Any map can be used here
32  [~,demap] = constmap('QAM',M, coding); % Create Gray constellation map/demap
33 else
34  error('Reference data can be of type logical (binary delay & add) or uint16 (symbols).');
35 end
36 
37 % FIXME AUTOMATIC MAP
38 automap = false; % DO NOT SET TO TRUE FOR NOW
39 if automap, demap = demap(:,1); end
40 N_demap = size(demap,2);
41 
42 
43 L_rx_s = size(RECEIVED_DATA,1);
44 if RETURN_REFERENCE_SEQUENCE
45  ORIG_SYMBOLS = zeros(size(RECEIVED_DATA),'uint16');
46 end
47 L_tx_s = size(D_tx_b,2);
48 L_tx_b = numel(D_tx_b); %L_tx_s*log2M==L_tx_b
49 
50 log2M_ = log2M(M);
51 L_block_s = min(L_block_s,L_rx_s); % In case of L_block = inf
52 
53 N_loop = round(L_rx_s/L_block_s); % Number of error counter loop iterations
54 
55 [c,P] = constref('QAM',M); % Generate reference constellation for symbol decisions
56 c = c/sqrt(P);
57 decision = @hd_euclid; % Symbol decision function: hd_euclid, sd_kmeans
58 
59 
60 
61 badbits = nan(N_demap,N_loop);
62 % badsymb = nan(N_loop,N_demap);
63 badsymb = nan(1,N_loop);
64 
65 
66 err_bits = nan(1,N_loop);
67 err_symb = nan(1,N_loop);
68 totalsymb = repmat(L_block_s,1,N_loop-1);
69 totalsymb = [totalsymb L_rx_s-sum(totalsymb)];
70 totalbits = log2M_*totalsymb; % Total number of bits
71 
72 % Repeat tx data to account for possible wrap-around in the rx data.
73 % Take maximum of first and last block length to take into account
74 % possible variation in the last block length.
75 N_tx = ceil(max(totalsymb(1),totalsymb(end))/(L_tx_s-1))+1;
76 D_tx_b_rep = repmat(D_tx_b,1,N_tx);
77 
78 perm = nan(N_loop,1);
79 
80 fprintf(1,'Error counter: %d block(s), %d de-map permutation(s).\n',N_loop,N_demap);
81 %% Error counter loop
82 idx_markers = [0 cumsum(totalsymb)];
83 for i=1:N_loop % For each block
84  %fprintf(1,' Block %d, de-map permutation',i);
85  fprintf('.');
86 
87  idx = idx_markers(i)+1:idx_markers(i+1); % Sliding data indices
88  rx_points = decision(RECEIVED_DATA(idx),c); % Make decision on the received signal
89 
90  if ~automap % Fixed constellation map
91 
92  switch mode
93  case 0
94  delay = nan(log2M_,N_demap);
95  case 1
96  delay = nan(1,N_demap);
97  end
98 
99  if i==1 %% FIXME Added for parfor
100  jj = 1:N_demap; % On first iteration try all possible map rotations
101  end
102  for j=jj % Try different constellation rotations
103  %fprintf(1,' %d',j);
104  demap_ = demap(:,j); % Select one of the de-maps
105  rx_symbols = demap_(rx_points); % De-map received symbols
106  rx_bits = symb2bits(rx_symbols,M); % Convert to bits
107 
108  switch mode
109  case 0 % Binary delay & add mode
110  rx_bits = rx_bits'; % Transpose for faster column access
111  badbits(j,i) = 0;
112  for k=1:log2M_ % For each column (no. of columns == log2M)
113  tmp = sumbitxor(D_tx_b_rep,rx_bits(:,k)); % Check BER
114  [badbits_,delay(k,j)] = min(tmp);
115  badbits(j,i) = badbits(j,i) + badbits_;
116  end
117 
118  case 1 % Symbols mode
119  tmp = sumbitxor(D_tx_b_rep(:),rx_bits(:));
120  tmp = tmp(1:log2M_:end); % Step by log2M_ (one symbol)
121  [badbits(j,i),delay(j)] = min(tmp);
122  end
123 
124  if i>1 && badbits(j,i)/totalbits(i)<=ber_th
125  % If iteration>1 and number of errors does not exceed
126  % err_th_rot then do not try remaining map rotations.
127  break
128  end
129  end
130  %fprintf(1,'.\n');
131 
132  % On subsequent iterations order rotations according to the
133  % number of incorrect bits in the previous iteration. In
134  % this way we can reduce the number of rotations to try.
135  [~,jj] = sort(badbits(:,i)'); %#ok<TRSRT>
136 
137  perm(i) = jj(1);
138  demap_ = demap(:,perm(i));
139  rx_symbols = demap_(rx_points); % De-map received symbols
140  rx_bits = symb2bits(rx_symbols,M); % Convert to bits
141 
142  err_bits(i) = badbits(perm(i),i);
143  delay = delay(:,perm(i));
144  switch mode
145  case 0
146  D_tx_b_ref = false(totalsymb(i),log2M_); % Create transposed for faster column access
147  for k=1:log2M_
148  D_tx_b_ref(:,k) = D_tx_b_rep(delay(k)+(0:totalsymb(i)-1));
149  end
150  D_tx_b_ref = D_tx_b_ref';
151  case 1
152  D_tx_b_ref = D_tx_b_rep(:,delay+(0:totalsymb(i)-1));
153  end
154 
155  if RETURN_REFERENCE_SEQUENCE
156  [~,mp] = sort(demap_);
157  ORIG_SYMBOLS(idx) = mp(bits2symb(D_tx_b_ref,M));
158  end
159 
160  ber_map = sparse(xor(D_tx_b_ref,rx_bits)); % BER error map
161  ser_map = logical(sum(ber_map,1)); % SER error map
162 % [err_distances,err_lengths] = count_binary_runs(ser_map); % Error statistics: runs of errors/no errors
163 % figure,hist(err_distances,25)
164 % title('Distance between errorneous symbols (symbol error bursts)');
165 % figure,hist(err_lengths,25)
166 % title('Lengths of symbol error bursts');
167  err_symb(i) = nnz(ser_map); % Number of symbol errors
168 
169 
170  end
171 
172 
173 % else % Auto map
174 % data_out_s = demap(rx_symbols);
175 % [~,data_out_b] = symb2bits(data_out_s,M);
176 % %size(D_tx_b2,2)==size(data_out_b)
177 %
178 % for j=1:size(D_tx_b2,2);
179 % x = sumbitxor(D_tx_b2(:,j),data_out_b(:,j));
180 % [badbits_pos,loc_pos] = min(x);
181 % [badbits_neg,loc_neg] = max(x); % negative logic detector
182 % badbits_neg = L_block-badbits_neg;
183 % if badbits_neg<badbits_pos % Negative logic detected
184 % fprintf('Bit %d is inverted. Updating constellation de-map.\n',j);
185 % demap = bitxor(demap-1,2^(j-1))+1; % Flip j-th bit for every symbol in the map
186 % data_out_b(:,j) = ~data_out_b(:,j); % Flip j-th bit for every symbol in the received data (optional)
187 % badbits_ = badbits_neg; % Assign number of bits
188 % % loc_ =
189 % else
190 % badbits_ = badbits_pos;
191 % end
192 % badbits(i) = badbits(i) + badbits_;
193 % end
194 % end
195 
196 
197 
198 end
199 fprintf(1,'.\n');
200 %perm % Constellation permutations
201 
202 ber_block = err_bits./totalbits;
203 blockmap = ber_block<ber_th;
204 ber = sum(err_bits(blockmap))/sum(totalbits(blockmap));
205 
206 
207 ser_block = err_symb./totalsymb;
208 ser = sum(err_symb(blockmap))/sum(totalsymb(blockmap));
function hd_euclid(in X, in c)
Euclidean metric hard decision digital demodulation.