Compare commits
1 Commits
b068400cb5
...
silas_wip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18ccaf8c12 |
@@ -462,10 +462,19 @@ classdef PAMmapper
|
||||
|
||||
end
|
||||
|
||||
function [Signal_out] = quantize(obj,Signal_in)
|
||||
function [Signal_out] = quantize(obj,Signal_in,options)
|
||||
arguments
|
||||
obj
|
||||
Signal_in
|
||||
options.custom_const = []
|
||||
end
|
||||
|
||||
constellation = obj.get_levels();
|
||||
constellation = constellation ./ obj.scaling;
|
||||
if isempty(options.custom_const)
|
||||
constellation = obj.get_levels();
|
||||
constellation = constellation ./ obj.scaling;
|
||||
else
|
||||
constellation = options.custom_const;
|
||||
end
|
||||
|
||||
issignalclass = 0;
|
||||
if isa(Signal_in,'Signal')
|
||||
|
||||
@@ -7,11 +7,11 @@ classdef Metricstruct
|
||||
eqParam_id (1,1) double {mustBeNumeric} = NaN
|
||||
date_of_processing (1,1) datetime = datetime('now')
|
||||
|
||||
numBits (1,1) double {mustBeInteger, mustBeNonnegative} = 0
|
||||
BER (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||||
numBitErr (1,1) double {mustBeInteger, mustBeNonnegative} = 0
|
||||
BER_precoded (1,1) double {mustBeNumeric, mustBeNonnegative} = 0
|
||||
numBitErr_precoded (1,1) double {mustBeInteger, mustBeNonnegative} = 0
|
||||
numBits (1,1) double = 0
|
||||
BER (1,1) double = 0
|
||||
numBitErr (1,1) double = 0
|
||||
BER_precoded (1,1) double = 0
|
||||
numBitErr_precoded (1,1) double = 0
|
||||
|
||||
SNR (1,1) double {mustBeNumeric} = NaN
|
||||
SNR_level (:,1) double {mustBeNumeric} = []
|
||||
|
||||
8
Datatypes/db_decoder.m
Normal file
8
Datatypes/db_decoder.m
Normal file
@@ -0,0 +1,8 @@
|
||||
classdef db_decoder < int32
|
||||
|
||||
enumeration
|
||||
sequencedetection (0) % use MLSE for decoding
|
||||
memoryless (1) % use modulo
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,153 +1,171 @@
|
||||
function [db_results] = 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;
|
||||
options.eth_style_symbol_mapping = 0;
|
||||
options.postFFE = [];
|
||||
end
|
||||
arguments
|
||||
eq_
|
||||
mlse_
|
||||
M
|
||||
rx_signal
|
||||
tx_symbols
|
||||
tx_bits
|
||||
options.precode_mode db_mode
|
||||
options.showAnalysis = 0;
|
||||
options.eth_style_symbol_mapping = 0;
|
||||
options.postFFE = [];
|
||||
options.decoding_mode db_decoder = db_decoder.sequencedetection;
|
||||
end
|
||||
|
||||
|
||||
%Duobinary Targeting
|
||||
db_ref_sequence = Duobinary().encode(tx_symbols);
|
||||
db_ref_constellation = unique(db_ref_sequence.signal);
|
||||
[eq_signal, eq_noise] = eq_.process(rx_signal,db_ref_sequence);
|
||||
|
||||
if ~isempty(options.postFFE)
|
||||
[eq_signal,eq_noise] = options.postFFE.process(eq_signal,db_ref_sequence);
|
||||
end
|
||||
%
|
||||
|
||||
switch options.decoding_mode
|
||||
case db_decoder.sequencedetection %MLSE
|
||||
mlse_.DIR = [1,1];
|
||||
if isa(mlse_,'MLSE_viterbi')
|
||||
pam_sig_sd = mlse_.process(eq_signal);
|
||||
else
|
||||
[pam_sig_sd,LLR,GMI_MLSE] = mlse_.process(eq_signal,tx_symbols);
|
||||
end
|
||||
pam_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).quantize(pam_sig_sd);
|
||||
case db_decoder.memoryless %DB Target FFE
|
||||
% Hard decision on FFE output
|
||||
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal,'custom_const',db_ref_constellation.');
|
||||
eq_signal_hd = Duobinary().decode(eq_signal_hd);
|
||||
pam_sig_hd = eq_signal_hd;
|
||||
end
|
||||
|
||||
% 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)
|
||||
switch options.precode_mode
|
||||
|
||||
case db_mode.no_db
|
||||
% TX Data is not precoded:
|
||||
|
||||
% A) Emulate diff precoding
|
||||
if options.decoding_mode == db_decoder.sequencedetection
|
||||
pam_sig_hd_precoded = Duobinary().encode(pam_sig_hd,"M",M);
|
||||
pam_sig_hd_precoded = Duobinary().decode(pam_sig_hd_precoded,"M",M);
|
||||
else
|
||||
pam_sig_hd_precoded = pam_sig_hd;
|
||||
end
|
||||
|
||||
%Duobinary Targeting
|
||||
db_ref_sequence = Duobinary().encode(tx_symbols);
|
||||
db_ref_constellation = unique(db_ref_sequence.signal);
|
||||
[eq_signal, eq_noise] = eq_.process(rx_signal,db_ref_sequence);
|
||||
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||
tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
||||
|
||||
if ~isempty(options.postFFE)
|
||||
[eq_signal,eq_noise] = options.postFFE.process(eq_signal,db_ref_sequence);
|
||||
end
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(pam_sig_hd_precoded);
|
||||
|
||||
[bits_db,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
%B) Just determine BER
|
||||
if options.decoding_mode == db_decoder.sequencedetection
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(pam_sig_hd);
|
||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
||||
[bits_mlse,errors_mlse,ber_db,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
else
|
||||
ber_db = NaN;
|
||||
errors_db = NaN;
|
||||
end
|
||||
|
||||
case db_mode.db_precoded
|
||||
|
||||
% Daten SIND TATSÄCHLICH precoded auf TX Seite:
|
||||
|
||||
% A) Decode at Rx if no DB targeting was applied (we are in VNLE or MLSE EQ structure here!
|
||||
if options.decoding_mode == db_decoder.sequencedetection
|
||||
pam_sig_hd_decoded = Duobinary().encode(pam_sig_hd,"M",M);
|
||||
pam_sig_hd_decoded = Duobinary().decode(pam_sig_hd_decoded,"M",M);
|
||||
else
|
||||
pam_sig_hd_decoded = pam_sig_hd;
|
||||
end
|
||||
|
||||
mlse_.DIR = [1,1];
|
||||
%
|
||||
rx_bits_mlse_decoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(pam_sig_hd_decoded);
|
||||
[bits_db,errors_db_diff_precoded,ber_db_diff_precoded,a] = calc_ber(rx_bits_mlse_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db_precoded = count_error_bursts(a, 40);
|
||||
|
||||
if isa(mlse_,'MLSE_viterbi')
|
||||
mlse_sig_sd = mlse_.process(eq_signal);
|
||||
else
|
||||
[mlse_sig_sd,LLR,GMI_MLSE] = mlse_.process(eq_signal,tx_symbols);
|
||||
end
|
||||
|
||||
mlse_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).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)
|
||||
switch options.precode_mode
|
||||
|
||||
case db_mode.no_db
|
||||
% TX Data is not precoded:
|
||||
|
||||
% A) Emulate diff precoding
|
||||
mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
|
||||
|
||||
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||
|
||||
tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_precoded);
|
||||
|
||||
[~,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
%B) Just determine BER
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||
[bits_mlse,errors_mlse,ber_db,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
case db_mode.db_precoded
|
||||
|
||||
% Daten SIND TATSÄCHLICH precoded auf TX Seite:
|
||||
|
||||
% A) Decode at Rx if no DB targeting was applied (we are in VNLE or MLSE EQ structure here!
|
||||
mlse_sig_hd_decoded = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd_decoded = Duobinary().decode(mlse_sig_hd_decoded,"M",M);
|
||||
rx_bits_mlse_decoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_decoded);
|
||||
[~,errors_db_diff_precoded,ber_db_diff_precoded,a] = calc_ber(rx_bits_mlse_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db_precoded = count_error_bursts(a, 40);
|
||||
% B) Omit the Coding by comparing with demapped TX symbol sequence
|
||||
|
||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||
[bits_db,errors_db,ber_db,a] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db = count_error_bursts(a, 40);
|
||||
|
||||
cols = linspecer(8);
|
||||
figure();hold on;
|
||||
stem(1:40,burst_db,'LineWidth',1,'Color',cols(4,:),'Marker','_','DisplayName','w/o diff. precoder');
|
||||
stem(1:40,burst_db_precoded,'LineWidth',1,'Color',cols(3,:),'Marker','.','LineStyle','-','DisplayName','w diff. precoder');
|
||||
xlabel('Bit Error Burst Length')
|
||||
ylabel('Occurence')
|
||||
set(gca, 'yscale', 'log');
|
||||
end
|
||||
|
||||
% M = numel(unique(tx_symbols.signal));
|
||||
rx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||
|
||||
[bits_db,errors_db,ber_db,errorIndice_db] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
alpha = arburg(eq_noise.signal,1);%pf_.coefficients(2);
|
||||
alpha = alpha(2);
|
||||
if isa(mlse_,'MLSE_viterbi')
|
||||
gmi_mlse = NaN;
|
||||
air_mlse = NaN;
|
||||
else
|
||||
gmi_mlse = GMI_MLSE;
|
||||
air_mlse = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi_mlse ./ log2(double(M));
|
||||
end
|
||||
|
||||
db_results = struct();
|
||||
db_results.metrics = Metricstruct;
|
||||
db_results.metrics.result_id = NaN;
|
||||
db_results.metrics.run_id = NaN;
|
||||
db_results.metrics.eqParam_id = NaN;
|
||||
db_results.metrics.date_of_processing = datetime('now');
|
||||
db_results.metrics.BER = ber_db;
|
||||
db_results.metrics.numBits = bits_db;
|
||||
db_results.metrics.numBitErr = errors_db;
|
||||
db_results.metrics.BER_precoded = ber_db_diff_precoded;
|
||||
db_results.metrics.numBitErr_precoded = errors_db_diff_precoded;
|
||||
db_results.metrics.GMI = gmi_mlse;
|
||||
db_results.metrics.AIR = air_mlse;
|
||||
db_results.metrics.MLSE_dir = mlse_.DIR;
|
||||
db_results.metrics.Alpha = alpha;
|
||||
|
||||
% Create DB results structure
|
||||
db_results.config = Equalizerstruct();
|
||||
eq_.e = [];
|
||||
eq_.e2 = [];
|
||||
eq_.e3 = [];
|
||||
db_results.config.eq = jsonencode(eq_);
|
||||
% mlse_.DIR = [];
|
||||
db_results.config.mlse = jsonencode(mlse_);
|
||||
db_results.config.equalizer_structure = int32(equalizer_structure.vnle_db_mlse);
|
||||
db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)';
|
||||
|
||||
if options.showAnalysis
|
||||
|
||||
eq_signal.eye(eq_signal.fs,M,"fignum",249);
|
||||
|
||||
|
||||
eq_noise = eq_noise - mean(eq_noise.signal);
|
||||
|
||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
||||
|
||||
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",10,"displayname","DB encoded reference");
|
||||
|
||||
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization');
|
||||
|
||||
fprintf('DB tgt BER: %.2e \n',ber_db);
|
||||
|
||||
figure(341); clf;
|
||||
showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341);
|
||||
|
||||
end
|
||||
% B) Omit the Coding by comparing with demapped TX symbol sequence
|
||||
if options.decoding_mode == db_decoder.sequencedetection
|
||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(pam_sig_hd);
|
||||
[bits_db,errors_db,ber_db,a] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db = count_error_bursts(a, 40);
|
||||
else
|
||||
ber_db = NaN;
|
||||
errors_db = NaN;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
switch options.decoding_mode
|
||||
case db_decoder.sequencedetection %MLSE
|
||||
if isa(mlse_,'MLSE_viterbi')
|
||||
gmi_mlse = NaN;
|
||||
air_mlse = NaN;
|
||||
else
|
||||
gmi_mlse = GMI_MLSE;
|
||||
air_mlse = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi_mlse ./ log2(double(M));
|
||||
end
|
||||
case db_decoder.memoryless %DB Target FFE
|
||||
% [gmi] = calc_air(eq_signal_sd, tx_symbols, "skip_front", 10000, "skip_end", 10000);
|
||||
[gmi] = calc_ngmi(eq_signal,tx_symbols);
|
||||
gmi_mlse = NaN;
|
||||
air_mlse = NaN;
|
||||
end
|
||||
|
||||
db_results = struct();
|
||||
db_results.metrics = Metricstruct;
|
||||
db_results.metrics.result_id = NaN;
|
||||
db_results.metrics.run_id = NaN;
|
||||
db_results.metrics.eqParam_id = NaN;
|
||||
db_results.metrics.date_of_processing = datetime('now');
|
||||
db_results.metrics.BER = ber_db;
|
||||
db_results.metrics.numBits = bits_db;
|
||||
db_results.metrics.numBitErr = errors_db;
|
||||
db_results.metrics.BER_precoded = ber_db_diff_precoded;
|
||||
db_results.metrics.numBitErr_precoded = errors_db_diff_precoded;
|
||||
db_results.metrics.GMI = gmi_mlse;
|
||||
db_results.metrics.AIR = air_mlse;
|
||||
db_results.metrics.MLSE_dir = mlse_.DIR;
|
||||
db_results.metrics.Alpha = NaN;
|
||||
|
||||
% Create DB results structure
|
||||
db_results.config = Equalizerstruct();
|
||||
eq_.e = [];
|
||||
eq_.e2 = [];
|
||||
eq_.e3 = [];
|
||||
db_results.config.eq = jsonencode(eq_);
|
||||
% mlse_.DIR = [];
|
||||
db_results.config.mlse = jsonencode(mlse_);
|
||||
db_results.config.equalizer_structure = int32(equalizer_structure.vnle_db_mlse);
|
||||
db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)';
|
||||
|
||||
if options.showAnalysis
|
||||
|
||||
eq_signal.eye(eq_signal.fs,M,"fignum",249);
|
||||
|
||||
|
||||
eq_noise = eq_noise - mean(eq_noise.signal);
|
||||
|
||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
||||
|
||||
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",10,"displayname","DB encoded reference");
|
||||
|
||||
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization');
|
||||
|
||||
fprintf('DB tgt BER: %.2e \n',ber_db);
|
||||
|
||||
figure(341); clf;
|
||||
showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341);
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -4,11 +4,11 @@ if 1
|
||||
|
||||
uloops = struct;
|
||||
uloops.precomp = [1];
|
||||
uloops.bitrate = [300].*1e9; %[300,330,360,390,420,450,480] [224,336,360,390,420,448] for MPI
|
||||
uloops.bitrate = [360].*1e9; %[300,330,360,390,420,450,480] [224,336,360,390,420,448] for MPI
|
||||
% uloops.laser_wavelength = [1293,1297.5,1302,1306.5,1310,1313.4,1318,1322.7,1327.4];
|
||||
uloops.laser_wavelength = [1293];
|
||||
uloops.laser_wavelength = [1290];
|
||||
uloops.M = [4];
|
||||
uloops.link_length = [0:2:10]; % 1,2,3,5,6,8,10
|
||||
uloops.link_length = [0]; % 1,2,3,5,6,8,10
|
||||
uloops.alpha = [0];
|
||||
|
||||
wh = DataStorage(uloops);
|
||||
@@ -19,21 +19,23 @@ if 1
|
||||
end
|
||||
|
||||
%%
|
||||
figure
|
||||
hold on
|
||||
for alpha = uloops.alpha
|
||||
a=wh.getStoValue('ber',1, [300].*1e9 , 1293, 4, uloops.link_length,alpha);
|
||||
ffe = cellfun(@(x) x.ffe_results.metrics.BER, a);
|
||||
plot(uloops.link_length,ffe,'DisplayName',sprintf('Alpha: %d',alpha),'LineStyle','-','HandleVisibility','on');
|
||||
end
|
||||
|
||||
set(gca, 'YScale', 'log');
|
||||
ylim([5e-5 0.4]);
|
||||
yline([3.8e-3, 2e-2],'HandleVisibility','off');
|
||||
legend
|
||||
beautifyBERplot()
|
||||
ylabel('BER');
|
||||
|
||||
% figure
|
||||
% hold on
|
||||
%
|
||||
% a=wh.getStoValue('ber',1, [360].*1e9 , 1290, 4, uloops.link_length,alpha);
|
||||
% ffe = cellfun(@(x) x.ffe_results.metrics.BER, a);
|
||||
% plot(uloops.link_length,ffe,'DisplayName',sprintf('FFE'),'LineStyle','-','HandleVisibility','on');
|
||||
% dbt = cellfun(@(x) x.dbt_results.metrics.BER, a);
|
||||
% plot(uloops.link_length,dbt,'DisplayName',sprintf('DBt'),'LineStyle','-','HandleVisibility','on');
|
||||
%
|
||||
%
|
||||
% set(gca, 'YScale', 'log');
|
||||
% ylim([5e-5 0.4]);
|
||||
% yline([3.8e-3, 2e-2],'HandleVisibility','off');
|
||||
% legend
|
||||
% beautifyBERplot()
|
||||
% ylabel('BER');
|
||||
%
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,66 +3,59 @@ function [output] = imdd_model(varargin)
|
||||
simulation_mode = 1;
|
||||
|
||||
%%% Change folder
|
||||
curFolder = pwd;
|
||||
funcFolder=fileparts(mfilename('fullpath'));
|
||||
if ~isempty(funcFolder)
|
||||
cd(funcFolder);
|
||||
end
|
||||
% curFolder = pwd;
|
||||
% funcFolder=fileparts(mfilename('fullpath'));
|
||||
% if ~isempty(funcFolder)
|
||||
% cd(funcFolder);
|
||||
% end
|
||||
|
||||
%%% Run parameters
|
||||
% TX
|
||||
M = 4;
|
||||
fsym = 180e9;
|
||||
|
||||
apply_pulsef = 1;
|
||||
fdac = 256e9;
|
||||
fadc = 256e9;
|
||||
% --- TX Architecture ---
|
||||
M = 4; % PAM order
|
||||
fsym = 180e9; % Symbol rate
|
||||
apply_pulsef = 1; % Pulse shaping flag
|
||||
fdac = 256e9; % DAC sampling rate
|
||||
fadc = 256e9; % ADC sampling rate
|
||||
random_key = 1;
|
||||
rcalpha = 0.05; % Roll-off factor
|
||||
kover = 16; % Oversampling factor
|
||||
duob_mode = db_mode.db_precoded;
|
||||
|
||||
rcalpha = 0.05;
|
||||
kover = 16;
|
||||
|
||||
% --- TX Optics (EML / Laser) ---
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 3;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
|
||||
vbias = -vbias_rel * u_pi;
|
||||
laser_wavelength = 1293;
|
||||
laser_linewidth = 0;
|
||||
tx_bw_nyquist = 0.8;
|
||||
|
||||
% Channel
|
||||
% --- Channel ---
|
||||
link_length = 1;
|
||||
alpha = 0;
|
||||
|
||||
% RX
|
||||
rop = -8;
|
||||
rx_bw_nyquist = 0.8;
|
||||
% --- RX & Equalization ---
|
||||
rop = -2;
|
||||
rx_bw_nyquist = 0.8;
|
||||
len_tr = 4096 * 2;
|
||||
|
||||
vnle_order1 = 50;
|
||||
vnle_order2 = 7;
|
||||
vnle_order3 = 7;
|
||||
% VNLE / FFE / DFE Orders
|
||||
vnle_order1 = 50;
|
||||
vnle_order2 = 7;
|
||||
vnle_order3 = 7;
|
||||
vnle_order = [vnle_order1, vnle_order2, vnle_order3];
|
||||
dfe_order = [0, 0, 0];
|
||||
dfe_ = sum(dfe_order) > 0;
|
||||
|
||||
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
|
||||
dfe_order = [0 0 0];
|
||||
pf_ncoeffs = 1;
|
||||
|
||||
pf_ncoeffs = 1;
|
||||
|
||||
alpha = 0;
|
||||
|
||||
len_tr = 4096*2;
|
||||
|
||||
mu_ffe1 = 0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_dc = 0.005;
|
||||
% mu_dc = 0;
|
||||
|
||||
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
|
||||
dfe_ = sum(dfe_order)>0;
|
||||
|
||||
duob_mode = db_mode.no_db;
|
||||
% Equalizer Step Sizes
|
||||
mu_ffe1 = 0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_ffe = [mu_ffe1, mu_ffe3, mu_ffe3];
|
||||
mu_dfe = 0.0004;
|
||||
mu_dc = 0.005;
|
||||
|
||||
%%% change specific parameter if given in varargin
|
||||
% Parse optional input arguments
|
||||
@@ -109,12 +102,12 @@ Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",1
|
||||
'duobinary_mode',duob_mode,...
|
||||
"mrds_code",0,"mrds_blocklength",512).process();
|
||||
|
||||
Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',1);
|
||||
% Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',1);
|
||||
|
||||
%%%%% AWG
|
||||
% El_sig = M8199A("kover",kover).process(Digi_sig);
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
||||
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
|
||||
El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||
% El_sig = El_sig.setPower(0,"dBm");
|
||||
|
||||
%%%%% Low-pass el. components %%%%%%
|
||||
@@ -132,7 +125,7 @@ El_sig = El_sig .* scaling;
|
||||
%%%%% MODULATE E/O CONVERSION %%%%%%
|
||||
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1,"alpha",alpha).process(El_sig);
|
||||
|
||||
Opt_sig.spectrum("displayname",'Opt Spectrum','fignum',10,'normalizeTo0dB',1);
|
||||
% Opt_sig.spectrum("displayname",'Opt Spectrum','fignum',10,'normalizeTo0dB',1);
|
||||
|
||||
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
|
||||
|
||||
@@ -150,7 +143,6 @@ Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",fi
|
||||
% %%%%%% Low-pass Scope %%%%%%
|
||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||
|
||||
% Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||
|
||||
%%%%%% Scope %%%%%%
|
||||
Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
|
||||
@@ -165,15 +157,18 @@ Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
|
||||
Scpe_sig.signal = Scpe_sig.signal(1:2*length(Symbols));
|
||||
|
||||
%%%%%% Sync Rx signal with reference %%%%%%
|
||||
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",1);
|
||||
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",0);
|
||||
|
||||
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
|
||||
|
||||
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
||||
|
||||
Scpe_sig.spectrum("displayname",'Filtered Digital Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||
|
||||
|
||||
%%% EQUALIZING
|
||||
|
||||
|
||||
if 0
|
||||
% -------------------- FFE --------------------
|
||||
ffe_order = [50, 0, 0];
|
||||
eq_ffe = EQ("Ne",ffe_order,"Nb",[0,0,0], ...
|
||||
@@ -186,7 +181,8 @@ output.ffe_results = ffe(eq_ffe,M,Scpe_sig,Symbols,Tx_bits, ...
|
||||
"eth_style_symbol_mapping",0);
|
||||
|
||||
output.ffe_results.metrics.print
|
||||
|
||||
end
|
||||
if 0
|
||||
% -------------------- DFE --------------------
|
||||
eq_dfe = EQ("Ne",ffe_order,"Nb",[2,0,0], ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
@@ -198,33 +194,36 @@ output.dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits, ...
|
||||
"eth_style_symbol_mapping",0);
|
||||
|
||||
output.dfe_results.metrics.print("description",'DFE');
|
||||
end
|
||||
if 0
|
||||
|
||||
% -------------------- VNLE + MLSE --------------------
|
||||
pf_ncoeffs = 1;
|
||||
ffe_order3 = [50, 5, 5];
|
||||
eq_v = EQ("Ne",ffe_order3,"Nb",dfe_order, ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
|
||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||
|
||||
[output.vnle_results, output.mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [], "eth_style_symbol_mapping", 0);
|
||||
output.mlse_results.metrics.print("description",'MLSE');
|
||||
end
|
||||
if 1
|
||||
|
||||
% -------------------- VNLE + MLSE --------------------
|
||||
pf_ncoeffs = 1;
|
||||
ffe_order3 = [50, 5, 5];
|
||||
eq_v = EQ("Ne",ffe_order3,"Nb",dfe_order, ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
|
||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||
|
||||
[output.vnle_results, output.mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [], "eth_style_symbol_mapping", 0);
|
||||
|
||||
|
||||
% -------------------- DB target --------------------
|
||||
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
|
||||
ffe_order = [50, 5, 5];
|
||||
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
output.dbt_results = duobinary_target(eq_,mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", []);
|
||||
|
||||
output.dbt_results.metrics.print("description",'Duobinary');
|
||||
|
||||
%% -------------------- DB target --------------------
|
||||
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
|
||||
ffe_order = [50, 5, 5];
|
||||
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1,"DB_aim",0);
|
||||
output.dbt_results = duobinary_target(eq_,mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [],"decoding_mode","memoryless");
|
||||
|
||||
output.dbt_results.metrics.print("description",'Duobinary');
|
||||
end
|
||||
|
||||
disp('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ')
|
||||
fprintf('\n')
|
||||
|
||||
@@ -4,7 +4,7 @@ freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",70,"f_ref",256e9);
|
||||
%
|
||||
Digi_sig = freqresp.buildOFDM();
|
||||
|
||||
Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]);
|
||||
Digi_sig.spectrum("fignum",1112);
|
||||
|
||||
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.butterworth,"active",true).process(Digi_sig);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
M = 6;
|
||||
apply_precode = 1;
|
||||
M = 4;
|
||||
apply_precode = 0;
|
||||
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
@@ -29,12 +29,12 @@ else
|
||||
end
|
||||
|
||||
show2Dconstellation(symbols_tx,symbols_tx,"displayname",'VNLE Out','fignum',2241);
|
||||
|
||||
|
||||
|
||||
if apply_precode
|
||||
% Entschiedene Symbole codieren: d_DB(n) = d(n) + d(n-1) (im Fall von PAM4 7 level [0 1 2 3 4 5 6])
|
||||
symbols_db = Duobinary().encode(symbols_tx);
|
||||
|
||||
|
||||
% Entschiedene codierte Symbole decodieren: d_dec(n) = d_DB(n) mod4
|
||||
symbols_rx = Duobinary().decode(symbols_db);
|
||||
else
|
||||
@@ -51,6 +51,8 @@ disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
figure(200)
|
||||
clf
|
||||
hold on
|
||||
start = 100;
|
||||
burstwidth = 10;
|
||||
idxs = start-10:start+burstwidth+10;
|
||||
scatter(idxs,d.signal(idxs),'DisplayName',['Orig Signal'],'Marker','o');
|
||||
scatter(idxs,d_burst.signal(idxs),'DisplayName',['Error Signal'],'Marker','x');
|
||||
|
||||
75
test/memoryless_decoding.m
Normal file
75
test/memoryless_decoding.m
Normal file
@@ -0,0 +1,75 @@
|
||||
% einstellungen
|
||||
M = 4;
|
||||
apply_precode_at_tx = 0;
|
||||
emulate_precode = 1;
|
||||
|
||||
% daten erzeugen
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
for i = 1:log2(M)
|
||||
N = 2^(17-1); %length of prbs
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
tx_bits = Informationsignal(bitpattern);
|
||||
tx_symbols = PAMmapper(M,0).map(tx_bits);
|
||||
|
||||
if apply_precode_at_tx
|
||||
|
||||
tx_symbols = Duobinary().precode(tx_symbols);
|
||||
|
||||
if emulate_precode
|
||||
% ansatz 1B) Omit precode (einfach precoded empfangen, nichts weiter machen und normal prozessieren - möglich weil konstellation sich nicht ändert)
|
||||
rx_symbols = tx_symbols;
|
||||
bits_rx = PAMmapper(M,0).demap(rx_symbols);
|
||||
% beachten, dass man die tx_bits anpassen muss, da man ja mit precoded symbolen vergleicht
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols);
|
||||
else
|
||||
% ansatz 1A) Precode normal:
|
||||
% Entschiedene Symbole codieren: d_DB(n) = d(n) + d(n-1) (im Fall von PAM4 7 level [0 1 2 3 4 5 6])
|
||||
symbols_db = Duobinary().encode(tx_symbols);
|
||||
% Entschiedene codierte Symbole decodieren: d_dec(n) = d_DB(n) mod4
|
||||
rx_symbols = Duobinary().decode(symbols_db);
|
||||
bits_rx = PAMmapper(M,0).demap(rx_symbols);
|
||||
end
|
||||
|
||||
[~,~,ber,~] = calc_ber(tx_bits.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
disp(['BER: ',sprintf('%.1E',ber)]);
|
||||
assert(ber == 0)
|
||||
|
||||
else
|
||||
|
||||
if emulate_precode
|
||||
% emulate precode:
|
||||
% Entschiedene Symbole codieren: d_DB(n) = d(n) + d(n-1) (im Fall von PAM4 7 level [0 1 2 3 4 5 6])
|
||||
symbols_db = Duobinary().encode(tx_symbols); % das wäre der FFE mit db target
|
||||
|
||||
% Entschiedene codierte Symbole decodieren: d_dec(n) = d_DB(n) mod4
|
||||
rx_symbols = Duobinary().decode(symbols_db); % modulo
|
||||
bits_rx = PAMmapper(M,0).demap(rx_symbols); % demappen
|
||||
|
||||
% ref symbole precoden, auch hier muss man wieder etwas fummeln wegen der emulation:
|
||||
% encode + decode == remove precoding (mathematisch die gleiche operation)
|
||||
tx_symbols_ref = Duobinary().encode(tx_symbols);
|
||||
tx_symbols_ref = Duobinary().decode(tx_symbols_ref);
|
||||
tx_bits = PAMmapper(M,0).demap(tx_symbols_ref);
|
||||
|
||||
else
|
||||
% normal detection without any precode stuff
|
||||
symbols_db = Duobinary().encode(tx_symbols);
|
||||
|
||||
rx_symbols = tx_symbols;
|
||||
bits_rx = PAMmapper(M,0).demap(rx_symbols);
|
||||
end
|
||||
|
||||
|
||||
[~,~,ber,~] = calc_ber(tx_bits.signal,bits_rx.signal,"skip_front",1,"skip_end",1,"returnErrorLocation",1);
|
||||
disp(['BER: ',sprintf('%.1E',ber)]);
|
||||
assert(ber == 0)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user