1 function [ber,ser,ber_block,ser_block,blockmap,err_bits,totalbits,err_symb,totalsymb,ORIG_SYMBOLS, RX_SYMBOLS] = error_counter_v7c(RECEIVED_DATA,REFERENCE_DATA,param)
2 %Note:
this function operates the same as way as error_counter_v7b, but allows user-specified constellation type (see const_ref.m
for options) and
3 %user-specified decision type (
'hard',
'soft')
4 %defaults to QAM and hard decision
5 L_block_s = param.L; % Error counter block length, symbols;
set to inf
for one block
8 if isfield(param,
'const_type'), const_type=param.const_type;
9 else const_type=
'QAM'; end
10 if isfield(param,
'decision_type'), decision_type=param.decision_type;
11 else decision_type=
'hard'; end
13 if isfield(param,
'ber_th'), ber_th=param.ber_th;
15 % err_th_rot = (0.25/ber_th-1)/2; % Tolerance (%) for BER increase between consecutive blocks, not requiring to try all de-map permutations
18 RETURN_REFERENCE_SEQUENCE = 0;
20 RETURN_REFERENCE_SEQUENCE = 1;
24 RETURN_RECEIVED_SEQUENCE = 0;
26 RETURN_RECEIVED_SEQUENCE = 1;
30 if ~isvector(REFERENCE_DATA)
31 error('Reference data must be a vector.');
33 if islogical(REFERENCE_DATA)
34 % Binary sequence -- binary delay & add mode
36 robolog('Error counter mode: binary delay & add.');
37 D_tx_b = REFERENCE_DATA(:)';
38 [~,demap] = constmap(const_type,M,'linear');
39 elseif isa(REFERENCE_DATA,'uint16')
40 % Integer sequence -- synchronized symbols
42 robolog('Error counter mode: symbols.');
43 D_tx_b = symb2bits(REFERENCE_DATA,M); % D_tx_b is recreated from symbols
44 % TODO Any map can be used here
45 [~,demap] = constmap(const_type,M, coding); % Create Gray constellation map/demap
47 error('Reference data can be of type logical (binary delay & add) or uint16 (symbols).');
51 automap = false; % DO NOT SET TO TRUE FOR NOW
52 if automap, demap = demap(:,1); end
53 N_demap = size(demap,2);
56 L_rx_s = size(RECEIVED_DATA,1);
57 if RETURN_REFERENCE_SEQUENCE
58 ORIG_SYMBOLS = zeros(size(RECEIVED_DATA),'uint16');
60 if RETURN_RECEIVED_SEQUENCE
61 RX_SYMBOLS = zeros(size(RECEIVED_DATA),'uint16');
63 L_tx_s = size(D_tx_b,2);
64 L_tx_b = numel(D_tx_b); %L_tx_s*log2M==L_tx_b
67 L_block_s = min(L_block_s,L_rx_s); % In case of L_block = inf
69 N_loop = round(L_rx_s/L_block_s); % Number of error counter loop iterations
71 [c,P] = constref(const_type,M); % Generate reference constellation for symbol decisions
75 decision = @
hd_euclid; % Symbol decision function: hd_euclid, sd_kmeans
77 decision = @sd_kmeans;
79 robolog('Unrecognized decision type', 'ERR')
84 badbits = nan(N_demap,N_loop);
85 % badsymb = nan(N_loop,N_demap);
86 badsymb = nan(1,N_loop);
89 err_bits = nan(1,N_loop);
90 err_symb = nan(1,N_loop);
91 totalsymb = repmat(L_block_s,1,N_loop-1);
92 totalsymb = [totalsymb L_rx_s-sum(totalsymb)];
93 totalbits = log2M_*totalsymb; % Total number of bits
95 % Repeat tx data to account for possible wrap-around in the rx data.
96 % Take maximum of first and last block length to take into account
97 % possible variation in the last block length.
98 N_tx = ceil(max(totalsymb(1),totalsymb(end))/(L_tx_s-1))+1;
99 D_tx_b_rep = repmat(D_tx_b,1,N_tx);
101 perm = nan(N_loop,1);
103 robolog('Error counter: %d block(s), %d de-map permutation(s).',N_loop,N_demap);
104 %% Error counter loop
105 idx_markers = [0 cumsum(totalsymb)];
106 for i=1:N_loop % For each block
107 %fprintf(1,' Block %d, de-map permutation',i);
110 idx = idx_markers(i)+1:idx_markers(i+1); % Sliding data indices
111 rx_points = decision(RECEIVED_DATA(idx),c); % Make decision on the received signal
113 if ~automap % Fixed constellation map
117 delay = nan(log2M_,N_demap);
119 delay = nan(1,N_demap);
122 if i==1 %% FIXME Added for parfor
123 jj = 1:N_demap; % On first iteration try all possible map rotations
125 for j=jj % Try different constellation rotations
127 demap_ = demap(:,j); % Select one of the de-maps
128 rx_symbols = demap_(rx_points); % De-map received symbols
129 rx_bits = symb2bits(rx_symbols,M); % Convert to bits
132 case 0 % Binary delay & add mode
133 rx_bits = rx_bits'; % Transpose for faster column access
135 D_tx_b_ref = false(totalsymb(i),log2M_); % Create transposed for faster column access
136 for k=1:log2M_ % For each column (no. of columns == log2M)
137 tmp = sumbitxor(D_tx_b_rep,rx_bits(:,k)); % Check BER
138 [tmp_badbits(1), tmp_idx(1)] = min(tmp); % not negated
139 [tmp_badbits(2), tmp_idx(2)] = max(tmp); % negated
140 tmp_badbits(2) = totalsymb(i) - tmp_badbits(2);
141 [badbits_, which] = min(tmp_badbits);
142 delay(k,j)=tmp_idx(which);
144 %[badbits_,delay(k,j)] = min(tmp);
145 badbits(j,i) = badbits(j,i) + badbits_;
147 D_tx_b_ref(:,k) = logical(which - 1 - D_tx_b_rep(delay(k, j)+(0:totalsymb(i)-1)));
151 case 1 % Symbols mode
152 tmp = sumbitxor(D_tx_b_rep(:),rx_bits(:));
153 tmp = tmp(1:log2M_:end); % Step by log2M_ (one symbol)
154 [badbits(j,i),delay(j)] = min(tmp);
157 if i>1 && badbits(j,i)/totalbits(i)<=ber_th
158 % If iteration>1 and number of errors does not exceed
159 % err_th_rot then do not try remaining map rotations.
165 % On subsequent iterations order rotations according to the
166 % number of incorrect bits in the previous iteration. In
167 % this way we can reduce the number of rotations to try.
168 [~,jj] = sort(badbits(:,i)'); %
#ok<TRSRT> 171 demap_ = demap(:,perm(i));
172 rx_symbols = demap_(rx_points); % De-map received symbols
173 rx_bits = symb2bits(rx_symbols,M); % Convert to bits
175 err_bits(i) = badbits(perm(i),i);
176 delay = delay(:,perm(i));
179 %use correct reference bit sequence, not the most recent
183 D_tx_b_ref(:,k) = logical(which - 1 - D_tx_b_rep(delay(k)+(0:totalsymb(i)-1)))
'; 186 D_tx_b_ref = D_tx_b_ref';
188 D_tx_b_ref = D_tx_b_rep(:,delay+(0:totalsymb(i)-1));
191 if RETURN_REFERENCE_SEQUENCE
192 [~,mp] = sort(demap_);
193 ORIG_SYMBOLS(idx) = mp(bits2symb(D_tx_b_ref,M));
195 if RETURN_RECEIVED_SEQUENCE
196 RX_SYMBOLS(idx) = rx_symbols;
199 ber_map = sparse(xor(D_tx_b_ref,rx_bits)); % BER error map
200 ser_map = logical(sum(ber_map,1)); % SER error map
201 % [err_distances,err_lengths] = count_binary_runs(ser_map); % Error statistics: runs of errors/no errors
202 % figure,hist(err_distances,25)
203 % title(
'Distance between errorneous symbols (symbol error bursts)');
204 % figure,hist(err_lengths,25)
205 % title(
'Lengths of symbol error bursts');
206 err_symb(i) = nnz(ser_map); % Number of symbol errors
213 % data_out_s = demap(rx_symbols);
214 % [~,data_out_b] = symb2bits(data_out_s,M);
215 % %size(D_tx_b2,2)==size(data_out_b)
217 %
for j=1:size(D_tx_b2,2);
218 % x = sumbitxor(D_tx_b2(:,j),data_out_b(:,j));
219 % [badbits_pos,loc_pos] = min(x);
220 % [badbits_neg,loc_neg] = max(x); % negative logic detector
221 % badbits_neg = L_block-badbits_neg;
222 %
if badbits_neg<badbits_pos % Negative logic detected
223 % fprintf(
'Bit %d is inverted. Updating constellation de-map.\n',j);
224 % demap = bitxor(demap-1,2^(j-1))+1; % Flip j-th bit
for every symbol in the map
225 % data_out_b(:,j) = ~data_out_b(:,j); % Flip j-th bit
for every symbol in the received data (optional)
226 % badbits_ = badbits_neg; % Assign number of bits
229 % badbits_ = badbits_pos;
231 % badbits(i) = badbits(i) + badbits_;
239 %perm % Constellation permutations
241 ber_block = err_bits./totalbits;
242 blockmap = ber_block<ber_th;
243 ber = sum(err_bits(blockmap))/sum(totalbits(blockmap));
246 ser_block = err_symb./totalsymb;
247 ser = sum(err_symb(blockmap))/sum(totalsymb(blockmap));
function robolog(in msg, in varargin)
This function allows the user to print log messages in a standard way.
function hd_euclid(in X, in c)
Euclidean metric hard decision digital demodulation.