Many changes
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
function [eq_signal,eq_noise,ber,numErrors] = duobinary_signaling(EQ, MLSE,M ,rx_signal, tx_symbols, tx_bits)
|
||||
function [eq_package] = duobinary_signaling(eq_, mlse_,M ,rx_signal, tx_symbols, tx_bits)
|
||||
%Duobinary Signaling
|
||||
|
||||
[eq_signal, eq_noise] = EQ.process(rx_signal,tx_symbols);
|
||||
[eq_signal, eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||
|
||||
eq_signal = MLSE.process(eq_signal);
|
||||
eq_signal = mlse_.process(eq_signal);
|
||||
|
||||
eq_signal = Duobinary().encode(eq_signal);
|
||||
eq_signal = Duobinary().decode(eq_signal);
|
||||
|
||||
% M = numel(unique(eq_signal.signal));
|
||||
@@ -12,4 +13,6 @@ function [eq_signal,eq_noise,ber,numErrors] = duobinary_signaling(EQ, MLSE,M ,rx
|
||||
|
||||
[~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
eq_package.ber = ber;
|
||||
|
||||
end
|
||||
@@ -1,17 +1,77 @@
|
||||
function [eq_signal,eq_noise,ber,numErrors] = duobinary_target(EQ, MLSE,M, rx_signal, tx_symbols, tx_bits)
|
||||
function [eq_package] = duobinary_target(eq_, mlse_,M, rx_signal, tx_symbols, tx_bits, options)
|
||||
|
||||
arguments
|
||||
eq_
|
||||
mlse_
|
||||
M
|
||||
rx_signal
|
||||
tx_symbols
|
||||
tx_bits
|
||||
options.precode_mode db_mode
|
||||
options.showAnalysis = 0;
|
||||
end
|
||||
|
||||
%Duobinary Targeting
|
||||
|
||||
[eq_signal, eq_noise] = EQ.process(rx_signal,Duobinary().encode(tx_symbols));
|
||||
[eq_signal, eq_noise] = eq_.process(rx_signal,Duobinary().encode(tx_symbols));
|
||||
|
||||
% dir = [1,1];
|
||||
eq_signal = MLSE.process(eq_signal);
|
||||
mlse_sig_sd = mlse_.process(eq_signal);
|
||||
|
||||
eq_signal = Duobinary().decode(eq_signal);
|
||||
mlse_sig_hd = PAMmapper(M,0).quantize(mlse_sig_sd);
|
||||
|
||||
% precoding to mitigate error propagation, most prominently used in
|
||||
% combination with duobinary signaling to avoid catastrophic error
|
||||
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
||||
|
||||
% takes:
|
||||
% -> eq_signal_hd: hard decision signal after eq
|
||||
% -> tx_symbols: that where used as reference for eq
|
||||
|
||||
switch options.precode_mode
|
||||
case db_mode.db_emulate
|
||||
|
||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
||||
|
||||
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols_precoded);
|
||||
|
||||
case db_mode.db_discard
|
||||
|
||||
% normal dsp for precoded sequence == discard/omit/ignore precode
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols);
|
||||
|
||||
case db_mode.db_encoded
|
||||
|
||||
% normal DB encoded data (only for 10KM)
|
||||
|
||||
case db_mode.db_precoded
|
||||
|
||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
||||
|
||||
end
|
||||
|
||||
% M = numel(unique(tx_symbols.signal));
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||
rx_bits = PAMmapper(M,0).demap(mlse_sig_hd);
|
||||
|
||||
[~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
|
||||
eq_package.ber = ber;
|
||||
|
||||
if options.showAnalysis
|
||||
eq_noise = eq_noise - mean(eq_noise.signal);
|
||||
|
||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250);
|
||||
|
||||
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise');
|
||||
|
||||
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",250);
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
function [eq_signal,eq_noise,ber,numErrors] = vnle(EQ,M,rx_signal,tx_symbols,tx_bits,emulate_precode)
|
||||
function [eq_package] = vnle(eq_,M,rx_signal,tx_symbols,tx_bits,options)
|
||||
%VNLE Apply an equalization algorithm to the received signal and calculate BER
|
||||
% This function takes an equalizer object, a received signal, and the
|
||||
% transmitted symbols to apply equalization, map the received signal back to bits,
|
||||
@@ -14,23 +14,73 @@ function [eq_signal,eq_noise,ber,numErrors] = vnle(EQ,M,rx_signal,tx_symbols,tx_
|
||||
% ber - Bit error rate after equalization
|
||||
% numErrors - Number of bit errors detected
|
||||
|
||||
%FFE or VNLE
|
||||
[eq_signal,eq_noise] = EQ.process(rx_signal,tx_symbols);
|
||||
|
||||
eq_signal = PAMmapper(M,0).quantize(eq_signal);
|
||||
|
||||
if emulate_precode
|
||||
eq_signal = Duobinary().encode(eq_signal);
|
||||
eq_signal = Duobinary().decode(eq_signal);
|
||||
|
||||
tx_symbols= Duobinary().encode(tx_symbols);
|
||||
tx_symbols = Duobinary().decode(tx_symbols);
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols);
|
||||
arguments
|
||||
eq_
|
||||
M
|
||||
rx_signal
|
||||
tx_symbols
|
||||
tx_bits
|
||||
options.precode_mode db_mode
|
||||
options.showAnalysis = 0
|
||||
end
|
||||
|
||||
% M = numel(unique(tx_symbols.signal));
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||
|
||||
%FFE or VNLE
|
||||
[eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||
|
||||
eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd);
|
||||
|
||||
% precoding to mitigate error propagation, most prominently used in
|
||||
% combination with duobinary signaling to avoid catastrophic error
|
||||
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
||||
|
||||
% takes:
|
||||
% -> eq_signal_hd: hard decision signal after eq
|
||||
% -> tx_symbols: that where used as reference for eq
|
||||
|
||||
switch options.precode_mode
|
||||
case db_mode.db_emulate
|
||||
% re
|
||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
||||
|
||||
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols_precoded);
|
||||
|
||||
case db_mode.db_discard
|
||||
|
||||
% normal dsp for precoded sequence == discard/omit/ignore precode
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols);
|
||||
|
||||
case db_mode.db_encoded
|
||||
|
||||
% normal DB encoded data (only for 10KM)
|
||||
|
||||
case db_mode.db_precoded
|
||||
|
||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
||||
|
||||
end
|
||||
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal_hd);
|
||||
|
||||
[~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
[evm_total,evm_lvl] = calc_evm(eq_signal_sd,tx_symbols);
|
||||
[inf_rate] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000);
|
||||
|
||||
eq_package.ber_vnle = ber;
|
||||
eq_package.evm_total = evm_total;
|
||||
eq_package.evm_lvl = evm_lvl;
|
||||
eq_package.inf_rate_vnle = inf_rate;
|
||||
|
||||
if options.showAnalysis
|
||||
|
||||
fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl);
|
||||
|
||||
fprintf('VNLE BER: %.2e \n',ber);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,21 +1,125 @@
|
||||
function [eq_signal,eq_noise,ber,numErrors] = vnle_postfilter_mlse(eq_,pf_,mlse_,M,rx_signal,tx_symbols,tx_bits)
|
||||
|
||||
function [eq_package] = vnle_postfilter_mlse(eq_,pf_,mlse_,M,rx_signal,tx_symbols,tx_bits,options)
|
||||
|
||||
arguments
|
||||
eq_
|
||||
pf_
|
||||
mlse_
|
||||
M
|
||||
rx_signal
|
||||
tx_symbols
|
||||
tx_bits
|
||||
options.precode_mode db_mode
|
||||
options.showAnalysis = 0;
|
||||
end
|
||||
|
||||
%FFE or VNLE
|
||||
[eq_signal,eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||
[eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||
|
||||
% eq_noise.signal = eq_noise.signal - movmean(eq_noise.signal,[5000,0]);
|
||||
eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd);
|
||||
|
||||
eq_signal = pf_.process(eq_signal,eq_noise);
|
||||
mlse_sig_sd = pf_.process(eq_signal_sd,eq_noise);
|
||||
|
||||
%M = numel(unique(tx_symbols.signal));
|
||||
mlse_.DIR = pf_.burg_coeff;
|
||||
mlse_.trellis_states = PAMmapper(M,0).levels;
|
||||
mlse_.M = M;
|
||||
mlse_.DIR = pf_.coefficients;
|
||||
% [mlse_sig_hd,mlse_sig_sd] = mlse_.process(mlse_sig_sd,tx_symbols);
|
||||
mlse_sig_sd = mlse_.process(mlse_sig_sd);
|
||||
|
||||
eq_signal = mlse_.process(eq_signal);
|
||||
mlse_sig_hd = PAMmapper(M,0).quantize(mlse_sig_sd);
|
||||
|
||||
% precoding to mitigate error propagation, most prominently used in
|
||||
% combination with duobinary signaling to avoid catastrophic error
|
||||
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
||||
|
||||
% takes:
|
||||
% -> M
|
||||
% -> eq_signal_hd: hard decision signal after eq
|
||||
% -> tx_symbols: that where used as reference for eq
|
||||
|
||||
switch options.precode_mode
|
||||
case db_mode.db_emulate
|
||||
% re
|
||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
||||
|
||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
||||
|
||||
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols_precoded);
|
||||
|
||||
case db_mode.db_discard
|
||||
|
||||
% normal dsp for precoded sequence == discard/omit/ignore precode
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols);
|
||||
|
||||
case db_mode.db_encoded
|
||||
|
||||
% normal DB encoded data (only for 10KM)
|
||||
|
||||
case db_mode.db_precoded
|
||||
|
||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
||||
|
||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
||||
|
||||
end
|
||||
|
||||
% METRICS OF VNLE %
|
||||
rx_bits_vnle = PAMmapper(M,0).demap(eq_signal_hd);
|
||||
[~,~,ber_vnle,~] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||
% correct TUM implementation of AIR
|
||||
[inf_rate_vnle] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000);
|
||||
[evm_vnle_total,evm_vnle_lvl] = calc_evm(eq_signal_sd,tx_symbols);
|
||||
|
||||
% METRICS OF MLSE (HD-VITERBI)
|
||||
rx_bits_mlse = PAMmapper(M,0).demap(mlse_sig_hd);
|
||||
[~,~,ber_mlse,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
|
||||
eq_package.ber_mlse = ber_mlse;
|
||||
eq_package.ber_vnle = ber_vnle;
|
||||
eq_package.evm_vnle_total = evm_vnle_total;
|
||||
eq_package.evm_vnle_lvl = evm_vnle_lvl;
|
||||
eq_package.air = inf_rate_vnle;
|
||||
|
||||
eq_package.eq = eq_;
|
||||
eq_package.pf = pf_;
|
||||
eq_package.mlse = mlse_;
|
||||
|
||||
|
||||
if options.showAnalysis
|
||||
|
||||
% fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl);
|
||||
|
||||
fprintf('VNLE BER: %.2e \n',ber_vnle);
|
||||
|
||||
fprintf('MLSE BER: %.2e \n',ber_mlse);
|
||||
|
||||
showEQNoisePSD(eq_noise,"fignum",336,"displayname",'VNLE+DFE','postfilter_taps',pf_.coefficients);
|
||||
|
||||
|
||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",337,"displayname",'Rx Signal');
|
||||
|
||||
tx_symbols.spectrum("normalizeTo0dB",1,"fignum",337,'displayname','Tx Signal');
|
||||
|
||||
showLevelHistogram(eq_signal_sd,tx_symbols)
|
||||
% showLevelHistogram(mlse_sig_sd,tx_symbols)
|
||||
|
||||
showEQcoefficients(eq_.e,eq_.e2,eq_.e3,"displayname",'Coefficients');
|
||||
|
||||
showEQNoiseSNR(tx_symbols,eq_noise,"displayname",'vnle snr','fignum',101);
|
||||
|
||||
%%% EQ SNR Spectrum %230
|
||||
%snr
|
||||
snr_vnle = snr(tx_symbols.signal,eq_noise.signal);
|
||||
|
||||
% showErrorBurstCount(eq_signal_sd,tx_symbols)
|
||||
|
||||
|
||||
end
|
||||
|
||||
[~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
end
|
||||
@@ -1,9 +1,5 @@
|
||||
function beautifyBERplot()
|
||||
% BEAUTIFYBERPLOT Enhances a BER plot for publication-quality figures.
|
||||
%
|
||||
% This function automatically adjusts the aesthetics of an existing plot.
|
||||
% It sets limits based on the data already plotted and modifies the
|
||||
% appearance for publication-ready figures.
|
||||
|
||||
% Set line properties for all current plot lines
|
||||
lines = findall(gca, 'Type', 'Line');
|
||||
@@ -11,10 +7,10 @@ function beautifyBERplot()
|
||||
num_markers = length(markers);
|
||||
|
||||
for i = 1:length(lines)
|
||||
lines(i).LineWidth = 1.5; % Set a thicker line width
|
||||
lines(i).LineStyle = '-'; % Solid lines for simplicity
|
||||
lines(i).LineWidth = 1.3; % Thicker line width
|
||||
%lines(i).LineStyle = '-'; % Solid lines for simplicity
|
||||
lines(i).Marker = markers{mod(i-1, num_markers) + 1}; % Assign markers cyclically
|
||||
lines(i).MarkerSize = 6; % Set marker size
|
||||
lines(i).MarkerSize = 4; % Marker size
|
||||
lines(i).MarkerFaceColor = 'auto'; % Use line color for marker face
|
||||
end
|
||||
|
||||
@@ -24,34 +20,16 @@ function beautifyBERplot()
|
||||
% Set figure background to white
|
||||
set(gcf, 'Color', 'w');
|
||||
|
||||
% Set axis labels with LaTeX
|
||||
xlabel('Bit Rate in Gbps', 'Interpreter', 'latex');
|
||||
ylabel('Bit Error Rate', 'Interpreter', 'latex');
|
||||
|
||||
% Determine x and y limits from the data in the plot
|
||||
x_data = [];
|
||||
y_data = [];
|
||||
for i = 1:length(lines)
|
||||
x_data = [x_data; lines(i).XData(:)]; %#ok<AGROW> % Append x data
|
||||
y_data = [y_data; lines(i).YData(:)]; %#ok<AGROW> % Append y data
|
||||
end
|
||||
x_min = min(x_data);
|
||||
x_max = max(x_data);
|
||||
y_min = 1e-4; % Ensure no negative or zero values for log scale
|
||||
y_max = 0.5;
|
||||
|
||||
% Adjust axis ranges
|
||||
xlim([x_min, x_max]);
|
||||
ylim([y_min, y_max]);
|
||||
|
||||
% Set logarithmic scale for y-axis
|
||||
set(gca, 'YScale', 'log');
|
||||
|
||||
% Set logarithmic scale for y-axis, but only if it makes sense.
|
||||
% If this is not always desired, you could condition this on the presence of lines or data.
|
||||
% set(gca, 'YScale', 'log');
|
||||
|
||||
% Customize grid and box appearance
|
||||
set(gca, 'Box', 'on', 'LineWidth', 1.2); % Add a thicker border
|
||||
set(gca, 'Box', 'on', 'LineWidth', 0.8); % Thicker border
|
||||
grid on;
|
||||
grid minor;
|
||||
% grid minor;
|
||||
|
||||
% Adjust font size and style for better readability
|
||||
set(gca, 'FontSize', 12, 'FontName', 'Times New Roman');
|
||||
set(gca, 'FontSize', 10, 'FontName', 'Times New Roman');
|
||||
end
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
function [bits,errors,ber,errorIndice] = calc_ber(data_in,data_ref,options)
|
||||
|
||||
arguments(Input)
|
||||
data_in;
|
||||
data_ref;
|
||||
options.skip_front = 0;
|
||||
options.skip_end = 0;
|
||||
options.returnErrorLocation = 0;
|
||||
end
|
||||
options.skip_end = abs(options.skip_end);
|
||||
options.skip_front = abs(options.skip_front);
|
||||
|
||||
assert((options.skip_end+options.skip_front)<length(data_in),"You can not skip more bits than overall length of data! Set skip_front or skip_end to lower value or check data_in");
|
||||
|
||||
bits = 0;
|
||||
errors= 0;
|
||||
ber= 0;
|
||||
errorIndice= [];
|
||||
|
||||
% trim sequence to given start; stop. trim reference if signal is shorter
|
||||
[data_in,data_ref]=trimseq(data_in,data_ref,options.skip_front,options.skip_end);
|
||||
|
||||
if length(data_ref) == length(data_in)
|
||||
|
||||
bits = 0;
|
||||
bits = bits+numel(data_in(:,options.skip_front+1:end));
|
||||
|
||||
try
|
||||
if options.returnErrorLocation == 0
|
||||
errors = sum( data_in ~= data_ref,"all" );
|
||||
else
|
||||
errorIndice = sum(data_in ~= data_ref,1);
|
||||
errors = sum(errorIndice ,"all" );
|
||||
[~,errorIndice] = find(errorIndice~=0);
|
||||
end
|
||||
|
||||
catch
|
||||
warning('BER calculation not optimal: Arrays have incompatible sizes for this operation.')
|
||||
errors = NaN;
|
||||
end
|
||||
|
||||
% Determine BER
|
||||
ber = sum(errors)/sum(bits);
|
||||
|
||||
else
|
||||
error('Sequence length does not match');
|
||||
end
|
||||
|
||||
function [data_,reference_]=trimseq(data,reference,skipstart,skip_end)
|
||||
|
||||
data_ = logical(data(skipstart+1:end-skip_end,:))';
|
||||
|
||||
delta_bits = length(reference) - length(data);
|
||||
|
||||
% skip_end = max(skip_end,delta_bits);
|
||||
skip_end = delta_bits + skip_end;
|
||||
|
||||
reference_ = logical(reference(skipstart+1:end-skip_end,:))';
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
function [evm,stdev] = calc_evm(vector_received,vector_ideal)
|
||||
|
||||
error_vector = (vector_received-vector_ideal);
|
||||
|
||||
k = unique(vector_ideal);
|
||||
|
||||
error = repmat(zeros(size(vector_ideal)),1,length(k));
|
||||
|
||||
for lvl = 1:length(k)
|
||||
error(vector_ideal==k(lvl),lvl) = error_vector(vector_ideal==k(lvl));
|
||||
end
|
||||
|
||||
error(error==0) = NaN;
|
||||
|
||||
stdev = std(error,"omitnan");
|
||||
|
||||
error = sqrt(error.^2);
|
||||
evm = sqrt( 1/length(error) .* sum(error.^2,1,'omitnan') ) ;
|
||||
end
|
||||
Reference in New Issue
Block a user