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)
3 L_block_s = param.L; % Error counter block length, symbols; set to inf for one block
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
11 RETURN_REFERENCE_SEQUENCE = 0;
13 RETURN_REFERENCE_SEQUENCE = 1;
17 if ~isvector(REFERENCE_DATA)
18 error('Reference data must be a vector.');
20 if islogical(REFERENCE_DATA)
21 % Binary sequence -- binary delay & add mode
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
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
34 error('Reference data can be of type logical (binary delay & add) or uint16 (symbols).');
38 automap = false; % DO NOT SET TO TRUE FOR NOW
39 if automap, demap = demap(:,1); end
40 N_demap = size(demap,2);
43 L_rx_s = size(RECEIVED_DATA,1);
44 if RETURN_REFERENCE_SEQUENCE
45 ORIG_SYMBOLS = zeros(size(RECEIVED_DATA),'uint16');
47 L_tx_s = size(D_tx_b,2);
48 L_tx_b = numel(D_tx_b); %L_tx_s*log2M==L_tx_b
51 L_block_s = min(L_block_s,L_rx_s); % In case of L_block = inf
53 N_loop = round(L_rx_s/L_block_s); % Number of error counter loop iterations
55 [c,P] = constref('QAM',M); % Generate reference constellation for symbol decisions
57 decision = @
hd_euclid; % Symbol decision function: hd_euclid, sd_kmeans
61 badbits = nan(N_demap,N_loop);
62 % badsymb = nan(N_loop,N_demap);
63 badsymb = nan(1,N_loop);
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
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);
80 fprintf(1,'Error counter: %d block(s), %d de-map permutation(s).\n',N_loop,N_demap);
82 idx_markers = [0 cumsum(totalsymb)];
83 for i=1:N_loop % For each block
84 %fprintf(1,' Block %d, de-map permutation',i);
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
90 if ~automap % Fixed constellation map
94 delay = nan(log2M_,N_demap);
96 delay = nan(1,N_demap);
99 if i==1 %% FIXME Added for parfor
100 jj = 1:N_demap; % On first iteration try all possible map rotations
102 for j=jj % Try different constellation rotations
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
109 case 0 % Binary delay & add mode
110 rx_bits = rx_bits'; % Transpose for faster column access
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_;
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);
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.
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> 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
142 err_bits(i) = badbits(perm(i),i);
143 delay = delay(:,perm(i));
146 D_tx_b_ref =
false(totalsymb(i),log2M_); % Create transposed
for faster column access
148 D_tx_b_ref(:,k) = D_tx_b_rep(delay(k)+(0:totalsymb(i)-1));
150 D_tx_b_ref = D_tx_b_ref
'; 152 D_tx_b_ref = D_tx_b_rep(:,delay+(0:totalsymb(i)-1)); 155 if RETURN_REFERENCE_SEQUENCE 156 [~,mp] = sort(demap_); 157 ORIG_SYMBOLS(idx) = mp(bits2symb(D_tx_b_ref,M)); 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 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) 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 190 % badbits_ = badbits_pos; 192 % badbits(i) = badbits(i) + badbits_; 200 %perm % Constellation permutations 202 ber_block = err_bits./totalbits; 203 blockmap = ber_block<ber_th; 204 ber = sum(err_bits(blockmap))/sum(totalbits(blockmap)); 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.