353 lines
13 KiB
Matlab
353 lines
13 KiB
Matlab
function [output] = imdd_model(simulation_mode,database,varargin)
|
|
|
|
|
|
|
|
|
|
%%% Change folder
|
|
curFolder = pwd;
|
|
funcFolder=fileparts(mfilename('fullpath'));
|
|
if ~isempty(funcFolder)
|
|
cd(funcFolder);
|
|
end
|
|
|
|
%%% Run parameters
|
|
% TX
|
|
M = 4;
|
|
fsym = 180e9;
|
|
f_nyquist = fsym/2;
|
|
apply_pulsef = 1;
|
|
fdac = 256e9;
|
|
fadc = 256e9;
|
|
random_key = 1;
|
|
|
|
db_precode = 1;
|
|
emulate_precode = 0;
|
|
discard_precode = 1;
|
|
db_encode = 0;
|
|
% duob_mode = db_mode.db_emulate;
|
|
emulate_db = 1;
|
|
|
|
rcalpha = 0.05;
|
|
kover = 16;
|
|
vbias_rel = 0.5;
|
|
u_pi = 2.9;
|
|
vbias = -vbias_rel*u_pi;
|
|
laser_wavelength = 1310;
|
|
laser_linewidth = 0;
|
|
tx_bw_nyquist = 0.9;
|
|
|
|
% Channel
|
|
link_length = 1;
|
|
|
|
% RX
|
|
rop = -8;
|
|
rx_bw_nyquist = 0.7;
|
|
|
|
% EQ
|
|
eq_mode = equalizer_structure.vnle_pf_mlse;
|
|
ffe_order=[50,0,0];
|
|
vnle_order=[50,7,7];
|
|
dfe_order = [2 0 0];
|
|
|
|
len_tr = 4096*2;
|
|
mu_ffe = [0.0004 0.0004 0.0004];
|
|
mu_dfe = 0.0004;
|
|
mu_dc = 0.00;
|
|
|
|
dfe_ = sum(dfe_order)>0;
|
|
|
|
%%% change specific parameter if given in varargin
|
|
% Parse optional input arguments
|
|
if ~isempty(varargin)
|
|
var_s = varargin{1};
|
|
if isstruct(var_s)
|
|
fields = fieldnames(var_s);
|
|
for i = 1:numel(fields)
|
|
if isnumeric(fields{i})
|
|
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
|
|
fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
|
|
else
|
|
eval([fields{i}, ' = ', 'var_s.(fields{',num2str(i),'})' , ';']);
|
|
end
|
|
|
|
end
|
|
else
|
|
error('Optional variables should be passed as a struct.');
|
|
end
|
|
end
|
|
|
|
%%% run the simulation or measurement or ...
|
|
|
|
|
|
if simulation_mode
|
|
|
|
fsym_ = floor( bitrate*1e-9./log2(M) ).*1e9;
|
|
|
|
if fsym_ ~= fsym
|
|
fsym = fsym_;
|
|
fprintf('Adapted symbolrate to %d GBd, to match provided bitrate of %d GBit/s using PAM %d \n',fsym.*1e-9,bitrate.*1e-9, M);
|
|
end
|
|
|
|
tx_simulation;
|
|
|
|
|
|
|
|
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
|
|
|
|
rx_simulation;
|
|
|
|
Scpe_cell{1} = Scpe_sig;
|
|
|
|
else
|
|
|
|
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
|
useGui = 0;
|
|
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
|
|
filterParams = database.tables;
|
|
% filterParams.Runs.run_id = 2958; % no db
|
|
% filterParams.Runs.run_id = 2937; % no db
|
|
filterParams.Configurations = struct( ...
|
|
'bitrate', bitrate, ...
|
|
'db_mode', db_precode+db_encode, ...
|
|
'fiber_length', link_length, ...
|
|
'interference_attenuation', [], ...
|
|
'interference_path_length', [], ...
|
|
'is_mpi', 0, ...
|
|
'pam_level', M, ...
|
|
'precomp_amp', [], ...
|
|
'rop_attenuation', 0, ...
|
|
'symbolrate', [], ...
|
|
'v_awg', [], ...
|
|
'v_bias', [], ...
|
|
'wavelength', 1310 ...
|
|
);
|
|
|
|
selectedFields = {'Runs.run_id','Runs.tx_bits_path', 'Runs.tx_symbols_path', 'Runs.rx_sync_path','Runs.rx_raw_path',...
|
|
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','BERs.ber'};
|
|
|
|
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
|
|
[~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices
|
|
dataTable = dataTable(uniqueIdx,:); % Extract unique configurations for each run_id
|
|
fprintf('Found %d entries for requested Configuration. IDs are: %s \n \n',size(dataTable,1),jsonencode(dataTable.run_id(1:min(size(dataTable,1),100))));
|
|
|
|
Tx_bits = load([basePath, char(dataTable.tx_bits_path(2))]);
|
|
Tx_bits = Tx_bits.Bits;
|
|
|
|
Symbols = load([basePath, char(dataTable.tx_symbols_path(2))]);
|
|
Symbols = Symbols.Symbols;
|
|
|
|
Scpe_load = load([basePath, char(dataTable.rx_sync_path(2))]);
|
|
Scpe_cell = Scpe_load.S;
|
|
|
|
% Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
|
|
% Raw_signal = Raw_signal.Scpe_sig_raw;
|
|
|
|
fsym = Symbols.fs;
|
|
|
|
end
|
|
|
|
output = struct();
|
|
|
|
for occ = 1:1%length(Scpe_cell)
|
|
|
|
Scpe_sig = Scpe_cell{occ};
|
|
|
|
%%%%%% Sample to 2x fsym %%%%%%
|
|
Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
|
|
|
|
%%%%%% Sync Rx signal with reference %%%%%%
|
|
[Scpe_sig,S] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym);
|
|
|
|
% Scpe_sig.spectrum("displayname",'Rx (Scpe+Sync+Resample)','fignum',100,'normalizeTo0dB',0);
|
|
|
|
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.6,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
|
|
|
|
Scpe_sig.spectrum("displayname",'Rx (Scpe+Sync+Resample+LPF)','fignum',110,'normalizeTo0dB',0);
|
|
|
|
Scpe_sig.plot("displayname",'Filtered Scope Signal','fignum',111,'clear',1);
|
|
|
|
Scpe_sig.eye(fsym,M);
|
|
|
|
|
|
|
|
%%% EQUALIZING
|
|
|
|
switch eq_mode
|
|
|
|
case equalizer_structure.ffe
|
|
|
|
%FFE
|
|
if db_precode
|
|
Bits_ = PAMmapper(M,0).demap(Symbols);
|
|
else
|
|
Bits_ = Bits;
|
|
end
|
|
|
|
eq_ffe = 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);
|
|
% eq_ffe = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0);
|
|
% eq_ffe = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0,"dc_buffer_len",512,"mu_dc",0.05);
|
|
|
|
[eq_sig,Eq_noise,ber_ffe(occ),totalErrors] = vnle( eq_ffe,M,Scpe_sig ,Symbols, Bits_);
|
|
Eq_noise.spectrum("displayname",'Noise Spectrum after FFE','fignum',41,'normalizeTo0dB',0);
|
|
|
|
fprintf('BER FFE: %.2e \n',ber_ffe(occ));
|
|
|
|
case equalizer_structure.vnle
|
|
|
|
|
|
|
|
|
|
|
|
%VNLE
|
|
eq_vnle = EQ("Ne",vnle_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",0);
|
|
|
|
[Eq_sig,Eq_noise] = eq_vnle.process(Scpe_sig,Symbols);
|
|
|
|
Eq_sig = PAMmapper(M,0).quantize(Eq_sig);
|
|
|
|
if emulate_precode && db_precode == 0
|
|
% emulation
|
|
Eq_sig = Duobinary().encode(Eq_sig);
|
|
Eq_sig = Duobinary().decode(Eq_sig);
|
|
|
|
Symbols= Duobinary().encode(Symbols);
|
|
Symbols = Duobinary().decode(Symbols);
|
|
Tx_bits = PAMmapper(M,0).demap(Symbols);
|
|
elseif db_precode == 1 && db_encode == 0 && discard_precode == 1
|
|
% normal dsp for precoded sequence
|
|
Tx_bits = PAMmapper(M,0).demap(Symbols);
|
|
|
|
elseif db_precode == 1 && db_encode == 1
|
|
error('not implemented')
|
|
|
|
elseif db_precode == 1 && db_encode == 0
|
|
Eq_sig = Duobinary().encode(Eq_sig);
|
|
Eq_sig = Duobinary().decode(Eq_sig);
|
|
end
|
|
|
|
% M = numel(unique(tx_symbols.signal));
|
|
Rx_bits = PAMmapper(M,0).demap(Eq_sig);
|
|
|
|
[~,numErrors,ber,~] = calc_ber(Rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
|
|
|
Eq_noise.spectrum("displayname",'Noise Spectrum after VNLE','fignum',41,'normalizeTo0dB',0);
|
|
|
|
output.ber_vnle(occ) = ber;
|
|
|
|
if 1c
|
|
figure(51);
|
|
clf
|
|
title(sprintf('DB coded PAM after EQ ; BER: %1.2e',M, ber ));
|
|
constellation = unique(Symbols.signal);
|
|
received = NaN(numel(constellation),length(Symbols));
|
|
for lvl = 1:numel(constellation)
|
|
%Separate the equalized signal into the
|
|
%respective levels based on the actually
|
|
%transmitted level!
|
|
received(lvl,Symbols.signal==constellation(lvl)) = Eq_sig.signal(Symbols.signal==constellation(lvl));
|
|
intermediate = received(lvl,:);
|
|
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
|
|
hold on
|
|
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
|
|
end
|
|
legend
|
|
end
|
|
|
|
Eq_sig.eye(fsym,M,"displayname",'Eye after EQ','fignum',52);
|
|
Eq_sig.spectrum("displayname",'Spectrum after EQ','fignum',53,'normalizeTo0dB',1);
|
|
Scpe_sig.spectrum("displayname",'Spectrum before EQ','fignum',53,'normalizeTo0dB',1);
|
|
fprintf('BER FFE: %.2e \n',ber);
|
|
|
|
|
|
|
|
|
|
|
|
case equalizer_structure.vnle_pf_mlse
|
|
|
|
|
|
%VNLE + PF + MLSE
|
|
eq_mlse = EQ("Ne",vnle_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);
|
|
% eq_mlse = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0,"dc_buffer_len",1,"mu_dc",0.05);
|
|
% eq_mlse = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0);
|
|
% eq_mlse = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0,"dc_buffer_len",512,"mu_dc",0.05);
|
|
|
|
pf_ = Postfilter("ncoeff",2);
|
|
mlse_ = MLSE("DIR",[0,0],"duobinary_output",0,"M",[],"trellis_states",[]);
|
|
|
|
%FFE or VNLE
|
|
[Eq_sig,Eq_noise] = eq_mlse.process(Scpe_sig,Symbols);
|
|
|
|
Eq_sig = pf_.process(Eq_sig,Eq_noise);
|
|
|
|
%M = numel(unique(tx_symbols.signal));
|
|
mlse_.DIR = pf_.burg_coeff;
|
|
mlse_.trellis_states = PAMmapper(M,0).levels;
|
|
mlse_.M = M;
|
|
|
|
Eq_sig = mlse_.process(Eq_sig);
|
|
pf_.showFilter(Eq_noise);
|
|
% Eq_noise.spectrum("displayname",'Noise Spectrum after VNLE+PF','fignum',41,'normalizeTo0dB',0);
|
|
|
|
if emulate_precode && db_precode == 0
|
|
% emulation
|
|
Eq_sig = Duobinary().encode(Eq_sig);
|
|
Eq_sig = Duobinary().decode(Eq_sig);
|
|
|
|
Symbols= Duobinary().encode(Symbols);
|
|
Symbols = Duobinary().decode(Symbols);
|
|
Tx_bits = PAMmapper(M,0).demap(Symbols);
|
|
elseif db_precode == 1 && db_encode == 0 && discard_precode == 1
|
|
% normal dsp for precoded sequence
|
|
Tx_bits = PAMmapper(M,0).demap(Symbols);
|
|
|
|
elseif db_precode == 1 && db_encode == 1
|
|
error('not implemented')
|
|
|
|
elseif db_precode == 1 && db_encode == 0
|
|
Eq_sig = Duobinary().encode(Eq_sig);
|
|
Eq_sig = Duobinary().decode(Eq_sig);
|
|
end
|
|
|
|
Rx_bits = PAMmapper(M,0).demap(Eq_sig);
|
|
|
|
[~,numErrors,ber,~] = calc_ber(Rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
|
|
|
output.ber_mlse(occ) = ber;
|
|
output.pf_taps(occ,:) = pf_.burg_coeff;
|
|
|
|
|
|
fprintf('BER MLSE: %.2e \n',ber);
|
|
|
|
case equalizer_structure.db_precoded
|
|
|
|
%EQ targets DB => less precompensation; pre-coded
|
|
mlse_db_pre = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
|
eq_db_pre = EQ("Ne",vnle_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);
|
|
[eq_sig,Eq_noise,ber_db(occ),totalErrors] = duobinary_target(eq_db_pre, mlse_db_pre,M, Scpe_sig ,Symbols, Bits);
|
|
Eq_noise.spectrum("displayname",'Noise Spectrum after DB','fignum',41,'normalizeTo0dB',0);
|
|
%->append BER to DB
|
|
|
|
fprintf('BER VNLE+DB: %.2e \n',ber_db(occ));
|
|
|
|
case equalizer_structure.db_encoded
|
|
|
|
%db signaling => db encoded
|
|
mlse_db_enc = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
|
eq_db_enc = EQ("Ne",vnle_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);
|
|
[eq_sig,Eq_noise,ber_db_enc,totalErrors] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Bits);
|
|
%->append BER to DB
|
|
|
|
fprintf('BER DB: %.2e \n',ber_db_enc(occ));
|
|
end
|
|
autoArrangeFigures;
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
if ~isempty(curFolder)
|
|
cd(curFolder);
|
|
end
|
|
|
|
end |