Many changes for 400G DSP

Minimal Example
...
This commit is contained in:
sioe
2024-12-17 16:17:58 +01:00
parent 397cfa61dd
commit e47a4dbbbe
68 changed files with 2749 additions and 2948 deletions

View File

@@ -1,70 +0,0 @@
clear
%% Set Simulation Variables
O = 18; %order of prbs
N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs
% Modulation
M = 4; %PAM-M
bitpattern = zeros(N,log2(M));
% Symbol Rate
fsym = 112e9;
% DAC Rate
fdac = 120e9;
% Simulation oversampling rate "k";
kover = 16;
% ADC Rate
fadc = 256e9;
% Simulation frequency in "analog domain"
fsimu = kover * fdac ;
%% CONSTRUCT ALL CLASSES
digimod = PAMmapper(M,0);
pulsef = Pulseformer("pulseform","rrc","fdac",fdac,"fsym",fsym,"pulselength",32,"rrcalpha",0.05);
awg = AWG('preset','M8199B','fdac',fdac,'kover',kover,'lpf_active',1,'f_cutoff',56e9,'lpf_type',filtertypes.gaussian,'bit_resolution',5.5);
lp_laser = Filter('filtdegree',1,"f_cutoff",30e9,"fsamp",fdac,"filterType",filtertypes.bessel_inp);
%% PROCESS
% PRBS Generation
for i = 1:log2(M)
[bitpattern(:,i),seed] = prbs(O,N,seed);
end
% Build Inf. signal class
bits = Informationsignal(bitpattern);
% Digi Mod
mod_out = digimod.map(bits);
% merken für EQ training
reference = mod_out;
% shape shape
mod_out = pulsef.process(mod_out);
test = applyPulseShaping(reference.signal,fsym,fdac);
% AWG -> ELECTRICAL DOMAIN
X = lp_laser.process(mod_out);
%X.spectrum(fsimu,"displayname",'AWG out','figurename','after AWG');

View File

@@ -0,0 +1,220 @@
function [ber] = imdd_example(varargin)
% BASIC IMDD Model...
% varargin is either empty or a struct, i.e.:
%
curFolder = pwd;
funcFolder=fileparts(mfilename('fullpath'));
if ~isempty(funcFolder)
cd(funcFolder);
end
% TX
M = 4;
fsym = 180e9;
f_nyquist = fsym/2;
apply_pulsef = 0;
fdac = 2*fsym;%256e9;
fadc = 2*fsym;%256e9;
fdac = 256e9;
fadc = 256e9;
random_key = 1;
db_precode = 0;
emulate_precode = 0;
discard_precode = 0;
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 = 1.5;
% 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;
% Parse optional input arguments
if ~isempty(varargin)
var_s = varargin{1};
if isstruct(var_s)
fields = fieldnames(var_s);
for i = 1:numel(fields)
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
end
else
error('Optional variables should be passed as a struct.');
end
end
%%%% TX Signal
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
[Digi_sig,Symbols,Bits] = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.5,...
"applypulseform",apply_pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_encode,...
"mrds_code",0,"mrds_blocklength",512).process();
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 = El_sig.setPower(0,"dBm");
%%%%% Low-pass el. components %%%%%%
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bw_nyquist.*f_nyquist,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
%%%%% Electrical Driver Amplifier %%%%%%
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
El_sig = El_sig.normalize("mode","oneone");
%%%%% 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).process(El_sig);
%%%%%% Fiber %%%%%%
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);
%%%%%% ROP %%%%%%
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
%%%%%% PD Square Law %%%%%%
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bw_nyquist.*f_nyquist,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig);
% %%%%%% Low-pass Scope %%%%%%
%dactivated in scope module!
Lp_scpe = Filter('filtdegree',4,"f_cutoff",10e9,"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,...
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',0,'H_lpf',Lp_scpe).process(Rx_sig);
% Scpe_sig.spectrum("displayname",'Digital (256 GSa/s) Rx Spectrum','fignum',100,'normalizeTo0dB',1);
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym);
%%%%%% Sync Rx signal with reference %%%%%%
[Scpe_sig,S] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym);
Scpe_sig.spectrum("displayname",'Prior DSP (2x fsym) Spectrum','fignum',100,'normalizeTo0dB',1);
%%% EQUALIZING
ber = struct();
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.ber_ffe,totalErrors] = vnle( eq_ffe,M,Scpe_sig ,Symbols, Bits_);
eq_noise.spectrum("displayname",'Noise Spectrum after FFE','fignum',41,'normalizeTo0dB',0);
case equalizer_structure.vnle
if db_precode
Bits_ = PAMmapper(M,0).demap(Symbols);
else
Bits_ = Bits;
end
%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",1);
[eq_sig,eq_noise,ber.ber_vnle,totalErrors] = vnle(eq_vnle,M,Scpe_sig ,Symbols, Bits_);
eq_noise.spectrum("displayname",'Noise Spectrum after VNLE','fignum',41,'normalizeTo0dB',0);
case equalizer_structure.vnle_pf_mlse
if db_precode
Bits_ = PAMmapper(M,0).demap(Symbols);
else
Bits_ = Bits;
end
%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",512,"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);
pf_ = Postfilter("ncoeff",1);
mlse_ = MLSE("DIR",[0,0],"duobinary_output",0,"M",[],"trellis_states",[]);
[eq_sig,eq_noise,ber.ber_mlse,totalErrors] = vnle_postfilter_mlse(eq_mlse , pf_, mlse_,M, Scpe_sig ,Symbols, Bits_);
pf_.showFilter(eq_noise);
eq_noise.spectrum("displayname",'Noise Spectrum after VNLE+PF','fignum',41,'normalizeTo0dB',0);
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.ber_db,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
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.ber_db_enc,totalErrors] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Bits);
%->append BER to DB
end
% fprintf('BER FFE: %.2e \n',ber.ber_mlse);
% % El_sig.spectrum("displayname",'Tx Spectrum','fignum',10,'normalizeTo0dB',1);
% Scpe_sig.spectrum("displayname",'Rx Spectrum','fignum',100,'normalizeTo0dB',1);
if ~isempty(curFolder)
cd(curFolder);
end
end

Binary file not shown.

View File

@@ -0,0 +1,26 @@
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
uloops = struct;
uloops.bitrate = [300,330,360,390,420,450,480].*1e9;
uloops.M = 4;
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,db,"parallel",0,"simulation_mode",0);
a = wh.getStoValue('ber', uloops.bitrate,uloops.M);
for i = 1:numel(a)
bers(i) = a{i}.ber_mlse;
end
figure(2024)
hold on
plot(uloops.bitrate.*1e-9,bers);
yline(3.8e-3,'LineWidth',2,'DisplayName','3.8e-3');
yline(2e-2,'LineWidth',2,'LineStyle','--','DisplayName','2e-2');
beautifyBERplot()
legend

View File

@@ -0,0 +1,172 @@
% function [ber] = imdd_labdata_example(varargin)
% TX
M = 4;
fsym = 224e9;
f_nyquist = fsym/2;
apply_pulsef = 0;
fdac = 2*fsym;%256e9;
fadc = 2*fsym;%256e9;
fdac = 256e9;
fadc = 256e9;
random_key = 1;
db_precode = 1;
db_encode = 0;
rcalpha = 0.05;
kover = 16;
vbias_rel = 0.5;
u_pi = 2.9;
vbias = -vbias_rel*u_pi;
laser_wavelength = 1293;
laser_linewidth = 0;
tx_bw_nyquist = 1.5;
% Channel
link_length = 0;
% RX
rop = -7.5;
rx_bw_nyquist = 1.5;
% EQ
eq_mode = equalizer_structure.vnle_pf_mlse;
ffe_order=[50,0,0];
vnle_order=[50,7,7];
dfe_order = [0 0 0];
len_tr = 4096*2;
mu_ffe = [0.0004 0.0004 0.0004];
mu_dfe = 0.0004;
mu_dc = 0.05;
dfe_ = sum(dfe_order)>0;
%
% % Parse optional input arguments
% if ~isempty(varargin)
% var_s = varargin{1};
% if isstruct(var_s)
% fields = fieldnames(var_s);
% for i = 1:numel(fields)
% eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
% fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
% end
% else
% error('Optional variables should be passed as a struct.');
% end
% end
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
useGui = 0;
db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
filterParams = db.tables;
% filterParams.Runs.run_id = 2958; % no db
% filterParams.Runs.run_id = 2937; % no db
filterParams.Configurations = struct( ...
'bitrate', 300e9, ...
'db_mode', 0, ...
'fiber_length', 1, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', 4, ...
'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.fiber_length','Configurations.wavelength','Configurations.precomp_amp','BERs.ber'};
[dataTable,sql_query] = db.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(1))]);
tx_bits = tx_bits.Bits;
tx_symbols = load([basePath, char(dataTable.tx_symbols_path(1))]);
tx_symbols = tx_symbols.Symbols;
rx_sync = load([basePath, char(dataTable.rx_sync_path(1))]);
rx_sync = rx_sync.S;
fsym = tx_symbols.fs;
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig = rx_sync{1}.resample("fs_in",rx_sync{1}.fs,"fs_out",2*fsym);
%%%%%% Sync Rx signal with reference %%%%%%
[Scpe_sig,S] = Scpe_sig.tsynch("reference",tx_symbols,"fs_ref",fsym);
Scpe_sig.spectrum("displayname",'Rx (Scpe+Sync+Resample)','fignum',100,'normalizeTo0dB',0);
Scpe_sig = Filter('filtdegree',4,"f_cutoff",tx_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',100,'normalizeTo0dB',0);
%%% EQUALIZING
ber = struct();
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.ber_ffe,totalErrors] = vnle( eq_ffe,M,Scpe_sig ,Symbols, Bits_);
eq_noise.spectrum("displayname",'Noise Spectrum after FFE','fignum',41,'normalizeTo0dB',0);
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",1);
[eq_sig,eq_noise,ber.ber_vnle,totalErrors] = vnle(eq_vnle,M,Scpe_sig ,Symbols, Bits_);
eq_noise.spectrum("displayname",'Noise Spectrum after VNLE','fignum',41,'normalizeTo0dB',0);
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);
pf_ = Postfilter("ncoeff",1);
mlse_ = MLSE("DIR",[0,0],"duobinary_output",0,"M",[],"trellis_states",[]);
[eq_sig,eq_noise,ber.ber_mlse,totalErrors] = vnle_postfilter_mlse(eq_mlse , pf_, mlse_,M, Scpe_sig ,Symbols, Bits_);
pf_.showFilter(eq_noise);
eq_noise.spectrum("displayname",'Noise Spectrum after VNLE+PF','fignum',41,'normalizeTo0dB',0);
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.ber_db,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
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.ber_db_enc,totalErrors] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Bits);
%->append BER to DB
end
fprintf('BER FFE: %.2e \n',ber.ber_mlse);
% % El_sig.spectrum("displayname",'Tx Spectrum','fignum',10,'normalizeTo0dB',1);
% Scpe_sig.spectrum("displayname",'Rx Spectrum','fignum',100,'normalizeTo0dB',1);
% end

View File

@@ -0,0 +1,353 @@
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

View File

@@ -1,227 +0,0 @@
function output = imddmodel(sir,dcmode)
for realiz = 1:3
rng(realiz);
%% Set Simulation Variables
delay = 0;10+(10*realiz); %mpi delay in meter
fiblen = 0; %main link in km
laser_linewidth =0e6;
O = 18; %order of prbs
N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs
% Modulation
M = 4; %PAM-M
bitpattern = zeros(N,log2(M));
% Symbol Rate
fsym = 112e9;
% DAC Rate
fdac = 120e9;
% Simulation oversampling rate "k";
kover = 16;
% ADC Rate
fadc = 256e9;
% Simulation frequency in "analog domain"
fsimu = kover * fdac ;
%% B) CONSTRUCT ALL CLASSES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
digimod = PAMmapper(M,0);
pulseform = Pulseformer("pulseform","rrc","fdac",fdac,"fsym",fsym,"pulselength",32,"rrcalpha",0.027);
awg = AWG('fdac',fdac,'kover',kover,'lpf_active',1,'f_cutoff',56e9,'lpf_type',filtertypes.gaussian,'bit_resolution',5.5);
lp_laser = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac*kover,"filterType",filtertypes.bessel_inp);
u_pi = 3.5;
vbias = (0.5*u_pi)-u_pi;
extmodlaser = EML("mode",eml_mode.im_cosinus,"power",5,"fsimu",fsimu,"lambda",1550,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth);
fib = Fiber("fsimu",fdac*kover,"fiber_length",fiblen,"alpha",0.2,"D",16,"lambda0",thz2nm(193.1),"gamma",0);
reflectionpoint = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",sir);
reflectionprop = Fiber("fsimu",fdac*kover,"fiber_length",delay/1000,"alpha",0.2,"D",16,"lambda0",1550,"gamma",0);
opticatten = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",-8);
phdiode = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20);
lp_diode = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac*kover,"filterType",filtertypes.bessel_inp);
scp = Scope("fsimu",fdac*kover,"fadc",fadc,...
"delay",0,"fixed_delay",0,"lpf_bw",113e9,"filtertype",filtertypes.butterworth,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",6,"quantbuffer",0.1,'block_dc',1);
eq = EQ("K",2,"plottrain",0,"plotfinal",0,...
"training_length",4096,"training_loops",2,...
"Ne",[50,5,3],"Nb",[3,2,2],...
"DCmu",0.05,"DDmu",[0.0004 0.0005 0.0006 0.0007 ],"DFEmu",0.005,"FFEmu",0.005,...
"dd_loops",2,"epsilon",[10 100 1000 ],"M",2,...
"thres",[0.005 0.004 0.0005 ],"l1act",0,"delay",0,"rho",0.0005,"ideal_dfe",0,"DB_aim",0);
eq2 = EQ_silas("Ne",[20,0,0],"Nb",[3,0,0],"trainlength",4096,"mu_dc_dd",0.005,"mu_dc_train",0.05,...
"mu_ffe_train",0.005,"mu_combined_dd",[0.0004 0.0006 0.0003 0.005],"ddloops",3,"dcmode",dcmode);
%% C) PROCESS TX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) PRBS Generation
for i = 1:log2(M)
[bitpattern(:,i),seed] = prbs(O,N,seed);
end
% 2 ) Build Inf. signal class
bits = Informationsignal(bitpattern);
% 3) Digi modulation -> PAM-M signal
digimod_out = digimod.map(bits);
% 4) Pulse shaping -> racos
X = pulseform.process(digimod_out);
% 5) AWG (lowpass, quantization, sample and hold)
X = awg.process(X);
% 6) Lowpass behavior of laser and hf-cable? why twice?
X = lp_laser.process(X);
X = lp_laser.process(X);
% 7) Normalize signal
X = X.normalize("mode","oneone");
X.signal = X.signal .* 1.3800;
%% D) PROCESS OPTICAL CHANNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Laser; Modulation -> OPTICAL DOMAIN
[X,extmodlaser] = extmodlaser.process(X);
% 2) Main fiber propagation
X = fib.process(X);
if delay ~= 0
% 3) Reflection
% Reflection is just an attenuation
R = reflectionpoint.process(X);
% Propagate back and forth (actual fiber propagation)
R = reflectionprop.process(R);
% Delay the reflected signal
[R,n] = R.delay("delay_meter",delay);
% Add together
X.signal = X.signal(n:end);
R.signal = R.signal(n:end);
%disp(['SIR ',num2str(10*log10(X.power/R.power))]);
X = X+R;
% 4) Equalize
% cut reference signal to correct length (nessecary due to MPI delay)
digimod_out.signal = digimod_out.signal(round(n * fsym/fsimu) : end,:);
bitpattern = bitpattern(round(n * fsym/fsimu):end,:);
end
% 4) Attenuation
X = opticatten.process(X);
% X = edfaamp.process(X);
% 5) Photo Diode -> ELECTRICAL DOMAIN
X = phdiode.process(X);
X = lp_diode.process(X);
%% E) PROCESS RX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Oscilloscope (Sampling to f_adc; Quantization; Bandwidth Limitation)
X = scp.process(X);
% 2) Resample to 2x symbol rate
X = X.resample("fs_out",2*fsym,"fs_in",fadc);
% 3) Normalize
Eq_in = X.normalize("mode","rms");
% MPI reduction DC removal BEFORE EQ
wl = 3000; % symbols
Eq_in.signal = Eq_in.signal - 1/wl .* movsum( Eq_in.signal,[wl/2,wl/2]);
% Equalize Signal
[Eq_out] = eq2.process(Eq_in,digimod_out);
%% A1: MPI reduction DC removal
wl = 1000; % symbols
yk_dcsm = Eq_out;
yk_dcsm.signal = Eq_out.signal - 1/wl .* movsum( Eq_out.signal,[wl/2,wl/2]);
%% A2: MPI reduction Level wise error removal
yk_lvsm = Eq_out;
yk_lvlp = Eq_out;
pre_decision_level_uni = digimod.decide_pamlevel(Eq_out);
pre_decision_level_bi = ( pre_decision_level_uni*2-3 ) .* 1/sqrt(5);
e = Eq_out.signal - pre_decision_level_bi;
lp_mpi = Filter('filtdegree',1,"f_cutoff",2e6,"fsamp",fsym,"filterType",filtertypes.bessel_inp);
filtered = lp_mpi.process(e);
wl = 30; % symbols
smoothed = ( 1/wl .* movsum(e,[wl/2,wl/2]) );
% remove interference
for level = 0:3
yk_lvsm.signal(pre_decision_level_uni==level) = yk_lvsm.signal(pre_decision_level_uni==level) - smoothed(pre_decision_level_uni==level);
yk_lvlp.signal(pre_decision_level_uni==level) = yk_lvlp.signal(pre_decision_level_uni==level) - filtered(pre_decision_level_uni==level);
end
%% PROCESS RX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Digi Demod
d_bm = digimod.demap(Eq_out);
d_dcsm = digimod.demap(yk_dcsm);
d_lvsm = digimod.demap(yk_lvsm);
d_lvlp = digimod.demap(yk_lvlp);
% 2) BER
dbit = length(d_bm.signal)-length(bitpattern);
[~,errors_bm,ber_bm(realiz),loc] = calc_ber(d_bm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",1);
[~,errors_dcsm,ber_dcsm(realiz)] = calc_ber(d_dcsm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
[~,errors_lvsm,ber_lvsm(realiz)] = calc_ber(d_lvsm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
[~,errors_lvlp,ber_lvlp(realiz)] = calc_ber(d_lvlp.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
end
output.ber_bm = mean(ber_bm);
output.ber_dcsm = mean(ber_dcsm);
output.ber_lvsm = mean(ber_lvsm);
output.ber_lvlp = mean(ber_lvlp);
end

View File

@@ -0,0 +1,46 @@
% TX
M = 4;
fsym = 180e9;
f_nyquist = fsym/2;
apply_pulsef = 0;
fdac = 2*fsym;%256e9;
fadc = 2*fsym;%256e9;
fdac = 256e9;
fadc = 256e9;
random_key = 1;
db_precode = 0;
emulate_precode = 0;
discard_precode = 0;
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 = 1.5;
% 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;

View File

@@ -1,208 +0,0 @@
clear
sir_loop = [-25:2:-13];
sir_loop = 0;
lw_loop = [1,2,3];
data = cell(length(sir_loop),length(lw_loop));
iterations=size(data);
parfor ix = 1:numel(data)
[u1,u2] = ind2sub(iterations,ix);
output = imddmodel(sir_loop(u1),lw_loop(u2));
data{ix} = output;
end
for sir = 1:size(data,1)
for lw = 1:size(data,2)
ber_bm(sir,lw) = data{sir,lw}.ber_bm;
ber_dcsm(sir,lw) = data{sir,lw}.ber_dcsm;
ber_lvsm(sir,lw) = data{sir,lw}.ber_lvsm;
ber_lvlp(sir,lw) = data{sir,lw}.ber_lvlp;
end
end
col = [ 0.6510 0.8078 0.8902
0.6980 0.8745 0.5412
0.9922 0.7490 0.4353];
figure(22)
for l = 1:numel(lw_loop)
hold on
plot(sir_loop,ber_bm(:,l),'DisplayName',['DC mode:', num2str(lw_loop(l)),', Linewidth= 50 MHz'],'Marker','o','MarkerFaceColor',col(l,:),'Color',col(l,:),'LineWidth',2,'LineStyle','--');
end
set(gca,'yscale','log');
yline(3.8e-3,'LineWidth',2,'LineStyle','--','HandleVisibility','off');
set(gca,'xdir','reverse');
%% Plot
col = linspecer(8);
figure(1)
hold on
m = ["x","o","pentagram","hexagram","*","+"];
cnt = 1;
for d = 1%:size(data,2)
for dc = 1:size(data,1)
for lw = 1:size(data,3)
ber_bm(dc,d,lw) = (data{dc,d,lw}.ber_bm);
ber_dcsm(dc,d,lw) = data{dc,d,lw}.ber_dcsm;
ber_lvsm(dc,d,lw) = data{dc,d,lw}.ber_lvsm;
ber_lvlp(dc,d,lw) = (data{dc,d,lw}.ber_lvlp);
end
end
i = 1;
comm_dn = [];% ['EQ DC Tap: ',num2str(dc_tap_loop(d)),' m'];
title("Dependency on Laser Linewidth; B2B; Delay : 2*50m")
plot(lw_loop*1e-6,mean(squeeze(ber_bm(1:end,d,:)),1),"LineWidth",1.2,"Marker",m(1),"MarkerSize",5,'Color',col(cnt,:),'DisplayName',[' ',comm_dn]);
plot(lw_loop*1e-6,mean(squeeze(ber_dcsm(1:end,d,:)),1),"LineWidth",1,"Marker",m(1+4),"MarkerSize",5,'LineStyle','--','Color',col(cnt,:),'DisplayName',['DC smoothing ',comm_dn],'HandleVisibility','on');
plot(lw_loop*1e-6,mean(squeeze(ber_lvsm(1:end,d,:)),1),"LineWidth",1.2,"Marker",m(1+1),"MarkerSize",5,'LineStyle',':','Color',col(cnt,:),'DisplayName',['Lvl Smoothing ',comm_dn],'HandleVisibility','on');
plot(lw_loop*1e-6,mean(squeeze(ber_lvlp(1:end,d,:)),1),"LineWidth",1,"Marker",m(1+3),"MarkerSize",5,'LineStyle','-.','Color',col(cnt,:),'DisplayName',['Lvl Lowpass ',comm_dn],'HandleVisibility','on');
set(gca,'yscale','log');
set(gca,'xscale','log');
%xticklabels([10 100 1000 10000]);
grid minor
yline(3.8e-3,'LineWidth',2,'LineStyle','--','HandleVisibility','off');
ylim([1e-3 4e-2]);
ylabel("BER");
xlabel("Linewidth in MHz")
legend
cnt = cnt+1;
end
figure(1)
contour(lw_loop,sir_loop,thres_a0,16:0.4:21,'LineWidth',2,'FaceAlpha',0.3,'ShowText','on',"LabelFormat","%0.1f dB");
clim([16 21]);
ylabel("Bandwidth in Multiples of Linewidth");
xlabel("Linewidth in MHz");
% set(gca,'yscale','log');
grid minor
title("MPI removal - Optimization of Lowpass Filter Bandwidth")
figure(2)
contour(lw_loop,sir_loop([1:10,12:end]),thres_a0([1:10,12:end],:),16:0.3:21,'LineWidth',2,'FaceAlpha',0.3,'ShowText','on',"LabelFormat","%0.1f dB");
clim([16 21]);
ylabel("Window Length");
xlabel("Linewidth in MHz");
set(gca,'yscale','log');
grid minor
title("MPI removal - Optimization of Averaging Window Length")
%% Plot Winlen Contour
hdfec = 3.8e-3.*ones(size(sir_loop));
for dc = 1:size(data,2)
for lw = 1:size(data,3)
for s = 1:size(data,1)
ber_lvlp(s,dc,lw) = data{s,dc,lw}.ber_dcsm;
% ber_dcsm(wl,lw,s) = data{wl,s,lw}.ber_dcsm;
end
a_bm = InterX([sir_loop;squeeze(ber_lvlp(:,dc,lw))'],[sir_loop;hdfec]);
% a_dcsm = InterX([sirloop;squeeze(ber_dcsm(wl,lw,:))'],[sirloop;hdfec]);
try
thres_a0(dc,lw) = -a_bm(1);
%thres_a1(wl,lw) = -a_dcsm(1);
catch
thres_a0(dc,lw) = NaN;
%thres_a1(wl,lw) = NaN;
end
end
end
figure(1)
contour(lw_loop,bw_loop,thres_a0,14:0.2:21,'LineWidth',1.5,'FaceAlpha',0.3,'ShowText','on',"LabelFormat","%0.1f dB");
a = flip(cbrewer2('seq','Spectral',32));
a = [a(1:12,:); a(22:end,:)];
colormap(a);
clim([16 21]);
ylabel("Window Length");
xlabel("Linewidth in MHz");
yticks(bw_loop);
yticklabels(bw_loop);
set(gca,'yscale','log');
set(gca,'xscale','log');
grid minor
%% Plot DC Tap Contour
hdfec = 3.8e-3.*ones(size(bw_loop));
thres_a0 = zeros(size(ber,1),size(ber,3));
thres_a1 = zeros(size(ber,1),size(ber,3));
for dc = 1:size(ber,1)
for lw = 1:size(ber,3)
a_lvsm = InterX([bw_loop;ber(dc,:,lw)],[bw_loop;hdfec]);
thres_a0(dc,lw) = -a_lvsm(1);
a1 = InterX([bw_loop;ber_a1(dc,:,lw)],[bw_loop;hdfec]);
thres_a1(dc,lw) = -a1(1);
end
end
figure(1)
subplot(2,1,1)
contour(lw_loop,sir_loop,thres_a0,16:0.5:21,'LineWidth',3,'FaceAlpha',0.3,'ShowText','on',"LabelFormat","%0.1f dB");
clim([16 21]);
ylabel("DC Tap");
xlabel("Linewidth in MHz");
set(gca,'yscale','log');
grid minor
subplot(2,1,2)
contour(lw_loop,sir_loop,thres_a1,16:0.5:21,'LineWidth',3,'FaceAlpha',0.3,'ShowText','on',"LabelFormat","%0.1f dB");
clim([16 21]);
ylabel("DC Tap");
xlabel("Linewidth in MHz");
set(gca,'yscale','log');
grid minor
%% Plot Curves of required SIR to see the minimum a bit better
col = flip(cbrewer2('seq','Spectral',16));
col = col([1:4, 10:end],:);
figure(2)
hold on
for lw = [size(ber,3):-2:2 2 1]
plot(sir_loop,thres_a0(:,lw),'DisplayName',[' Linewidth: ',num2str(lw_loop(lw)*1e-6), ' MHz'],'Color',col(lw,:),'Marker','o','MarkerFaceColor',col(lw,:),'LineWidth',2);
set(gca,'xscale','log');
end
xlabel("DC Tap Value");
ylabel("Required SIR to rech FEC in dB");
%%
col = linspecer(7);
figure(3)
cnt=1;
for lw = [1,2,11]
for i = 1:length(sir_loop)-1
subplot(1,3,cnt)
hold on
plot(-1.*bw_loop,ber(i,:,lw),"LineWidth",2,"Marker","o","MarkerSize",5,'Color',col(i,:),'DisplayName',['DC tap ',num2str(sir_loop(i))]);
plot(-1.*bw_loop,ber_a1(i,:,lw),"LineWidth",2,"Marker","x","MarkerSize",5,'LineStyle','--','Color',col(i,:),'DisplayName',['A1. DC tap ',num2str(sir_loop(i))]);
yline(3.8e-3,'LineWidth',2,'LineStyle','--','HandleVisibility','off');
set(gca,'yscale','log');
grid minor
xlim([15,30]);
ylim([1e-4,1e-2]);
xlabel("SIR in dB");
ylabel("BER");
title(['BER for different SIR;',' Linewidth: ',num2str(lw_loop(lw)*1e-6), ' MHz'])
text(25,4.2e-3,"FEC $3.8 e^{-3}$");
end
cnt = cnt+1;
end
legend

View File

@@ -0,0 +1,24 @@
%%%%%% ROP %%%%%%
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
%%%%%% PD Square Law %%%%%%
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bw_nyquist.*f_nyquist,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig);
% %%%%%% 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,...
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',1,'H_lpf',Lp_scpe).process(Rx_sig);

View File

@@ -1,399 +0,0 @@
lw = [0.1e6 1e6 10e6];
for lp = 1
rng(9);
%% A) Set Simulation Variables
sir = -18;
delay = 50; %mpi delay in meter
fiblen = 0; %main link in km
laser_linewidth =5e6;
O = 19; %order of prbs
N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs
% Modulation
M = 4; %PAM-M
bitpattern = zeros(N,log2(M));
% Symbol Rate
fsym = 112e9;
% DAC Rate
fdac = 120e9;
% Simulation oversampling rate "k";
kover = 16;
% ADC Rate
fadc = 256e9;
% Simulation frequency in "analog domain"
fsimu = kover * fdac ;
%% B) CONSTRUCT ALL CLASSES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
digimod = PAMmapper(M,0);
pulseform = Pulseformer("pulseform","rrc","fdac",fdac,"fsym",fsym,"pulselength",32,"rrcalpha",0.027);
awg = AWG('fdac',fdac,'kover',kover,'lpf_active',1,'f_cutoff',56e9,'lpf_type',filtertypes.gaussian,'bit_resolution',5.5);
lp_laser = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac*kover,"filterType",filtertypes.bessel_inp);
u_pi = 3.5;
vbias = (0.5*u_pi)-u_pi;
extmodlaser = EML("mode",eml_mode.im_cosinus,"power",5,"fsimu",fsimu,"lambda",1310,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth);
fib = Fiber("fsimu",fdac*kover,"fiber_length",fiblen,"alpha",0.2,"D",16,"lambda0",thz2nm(193.1),"gamma",0);
reflectionpoint = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",sir);
reflectionprop = Fiber("fsimu",fdac*kover,"fiber_length",delay/1000,"alpha",0.2,"D",16,"lambda0",1550,"gamma",0);
opticatten = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",-8);
phdiode = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20);
lp_diode = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac*kover,"filterType",filtertypes.bessel_inp);
scp = Scope("fsimu",fdac*kover,"fadc",fadc,...
"delay",0,"fixed_delay",0,"lpf_bw",113e9,"filtertype",filtertypes.butterworth,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",6,"quantbuffer",0.1,'block_dc',1);
eq = EQ("K",2,"plottrain",0,"plotfinal",0,...
"training_length",4096,"training_loops",2,...
"Ne",[50,5,3],"Nb",[3,0,0],...
"DCmu",0.05,"DDmu",[0.0004 0.0005 0.0006 0.0007 ],"DFEmu",0.005,"FFEmu",0.00,...
"dd_loops",2,"epsilon",[10 100 1000 ],"M",2,...
"thres",[0.005 0.004 0.0005 ],"l1act",0,"delay",0,"rho",0.0005,"ideal_dfe",0,"DB_aim",0);
eq = EQ_silas("Ne",[50,5,3],"Nb",[2,0,0],"trainlength",4096,...
"sps",2,...
"mu_dc_dd",0.05,...
"mu_dc_train",0.05,...
"mu_ffe_train",0,...
"mu_dfe_train",0.005,...
"mu_ffe_dd",[0.0004 0.0004 0.0004],...
"mu_dfe_dd",0.005,...
"ddloops",3,...
"trainloops",4,...
"dcmode",1);
%% C) PROCESS TX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) PRBS Generation
for i = 1:log2(M)
[bitpattern(:,i),seed] = prbs(O,N,seed);
end
% 2 ) Build Inf. signal class
bits = Informationsignal(bitpattern);
% 3) Digi modulation -> PAM-M signal
digimod_out = digimod.map(bits);
% 4) Pulse shaping -> racos
X = pulseform.process(digimod_out);
% 5) AWG (lowpass, quantization, sample and hold)
X = awg.process(X);
% 6) Lowpass behavior of laser and hf-cable? why twice?
X = lp_laser.process(X);
% X = lp_laser.process(X);
% 7) Normalize signal
X = X.normalize("mode","oneone");
X.signal = X.signal .* 1.3800;
%% D) PROCESS OPTICAL CHANNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Laser; Modulation -> OPTICAL DOMAIN
[X,extmodlaser] = extmodlaser.process(X);
% 2) Main fiber propagation
X = fib.process(X);
if delay ~= 0
% 3) Reflection
% Reflection is just an attenuation
R = reflectionpoint.process(X);
% Propagate back and forth (actual fiber propagation)
R = reflectionprop.process(R);
% Delay the reflected signal
[R,n] = R.delay("delay_meter",delay);
% Add together
col = cbrewer2('qual','Paired',8);
xax = (1:X.length);% / fsimu * (physconst("LightSpeed")/1.4677);
xax_sec = (1:X.length) / fsimu .* 1e6;%* (physconst("LightSpeed")/1.4677);
xax_sec = xax_sec(n:end).';
thresh = pi/4;
phaseX = phase(X.signal(n:end));
phaseR = phase(R.signal(n:end));
phasediff = wrapToPi(phaseX-phaseR);
[pos_high] = find(abs(phasediff)>thresh);
[pos_low] = find(abs(phasediff)<=thresh);
figure(6);hold on;histogram(phaseX-phaseR,500,'EdgeAlpha',0)
figure()
subplot(3,1,1)
scatter(xax_sec.',wrapToPi(phaseX),4,'.','MarkerEdgeColor',col(2,:),'DisplayName','Desired Signal')
hold on
scatter(xax_sec,wrapToPi(phaseR),4,'.','MarkerEdgeColor',col(1,:),'DisplayName','Reflected Signal')
hold on
lg = legend;
lg.Location = "southwest";
xlim([xax_sec(1) xax_sec(end)]);
xlabel('time in $\mu$s')
ylim([-pi pi]);
yticks([-pi 0 pi])
yticklabels({'$-\pi$',0, '$\pi$'})
ylabel('$\phi$')
subplot(3,1,2)
scatter(xax_sec(pos_low),phasediff(pos_low),4,'.','MarkerEdgeColor',col(5,:),'DisplayName','Phase Difference')
hold on
scatter(xax_sec(pos_high),phasediff(pos_high),4,'.','MarkerEdgeColor',col(2,:),'HandleVisibility','off')
% yline(thresh,'LineWidth',2,'LineStyle','-','HandleVisibility','off')
% yline(-thresh,'LineWidth',2,'LineStyle','-','HandleVisibility','off')
lg = legend;
lg.Location = "southwest";
xlabel('time in $\mu$s')
xlim([xax_sec(1) xax_sec(end)]);
ylim([-pi pi]);
yticks([-pi 0 pi])
yticklabels({'$-\pi$',0, '$\pi$'})
ylabel('$\Delta \phi$')
X.signal = X.signal(n:end);
R.signal = R.signal(n:end);
X1 = X;
X = X+R;
subplot(3,1,3)
scatter(xax_sec(pos_low),abs(X.signal(pos_low).^2)*1000,4,'.','MarkerEdgeColor',col(5,:),'DisplayName','Constructive Interference');
hold on
scatter(xax_sec(pos_high),abs(X.signal(pos_high).^2)*1000,4,'.','MarkerEdgeColor',col(2,:),'DisplayName','Destructive Interference');
%scatter(xax_sec(pos_high),abs(X1.signal(pos_high).^2)*1000,4,'.','MarkerEdgeColor',col(1,:),'MarkerFaceAlpha',0.3,'DisplayName','Destructive Interference');
xlim([xax_sec(1) xax_sec(end)]);
xlabel('time in $\mu$s')
lg = legend;
lg.Location = "southwest";
ylabel('Optical power in mW');
disp(['SIR ',num2str(10*log10(X.power/R.power))]);
% cut reference signal to correct length (nessecary due to MPI delay)
digimod_out.signal = digimod_out.signal(round(n * fsym/fsimu) : end,:);
bitpattern = bitpattern(round(n * fsym/fsimu):end,:);
end
% plot(angle(R.signal))
% 4) Attenuation
X = opticatten.process(X);
% 5) Photo Diode -> ELECTRICAL DOMAIN
X = phdiode.process(X);
X = lp_diode.process(X);
%% E) PROCESS RX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Oscilloscope (Sampling to f_adc; Quantization; Bandwidth Limitation)
X = scp.process(X);
% 2) Resample to 2x symbol rate
X = X.resample("fs_out",2*fsym,"fs_in",fadc);
% 3) Normalize
Eq_in = X.normalize("mode","rms");
% 4) Equalize
% MPI reduction DC removal BEFORE EQ
wl = 3000; % symbols
Eq_in.signal = Eq_in.signal - 1/wl .* movsum( Eq_in.signal,[wl/2,wl/2]);
% Equalize Signal
[Eq_out] = eq.process(Eq_in,digimod_out);
%% A1: MPI reduction DC removal
wl = 1000; % symbols
yk_dcsm = Eq_out;
yk_dcsm.signal = Eq_out.signal - 1/wl .* movsum( Eq_out.signal,[wl/2,wl/2]);
%% A2: MPI reduction Level wise error removal
yk_lvsm = Eq_out;
yk_lvlp = Eq_out;
pre_decision_level_uni = digimod.decide_pamlevel(Eq_out);
pre_decision_level_bi = ( pre_decision_level_uni*2-3 ) .* 1/sqrt(5);
e = Eq_out.signal - pre_decision_level_bi;
lp_mpi = Filter('filtdegree',1,"f_cutoff",2e6,"fsamp",fsym,"filterType",filtertypes.bessel_inp);
filtered = lp_mpi.process(e);
wl = 30; % symbols
smoothed = ( 1/wl .* movsum(e,[wl/2,wl/2]) );
% remove interference
for level = 0:3
yk_lvsm.signal(pre_decision_level_uni==level) = yk_lvsm.signal(pre_decision_level_uni==level) - smoothed(pre_decision_level_uni==level);
yk_lvlp.signal(pre_decision_level_uni==level) = yk_lvlp.signal(pre_decision_level_uni==level) - filtered(pre_decision_level_uni==level);
end
% Calc EVM
evm_bm = calc_evm(Eq_out.signal, pre_decision_level_bi);
evm_dcsm = calc_evm(yk_dcsm.signal, pre_decision_level_bi);
evm_lsm = calc_evm(yk_lvsm.signal, pre_decision_level_bi);
evm_llp = calc_evm(yk_lvlp.signal, pre_decision_level_bi);
% figure(1);bar([evm_bm' evm_dcsm' evm_llp' evm_lsm']);ylim([0.01 0.1]);set(gca,'yscale','log');
%% PROCESS RX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 1) Digi Demod
d_bm = digimod.demap(Eq_out);
d_dcsm = digimod.demap(yk_dcsm);
d_lvsm = digimod.demap(yk_lvsm);
d_lvlp = digimod.demap(yk_lvlp);
% 2) BER
dbit = length(d_bm.signal)-length(bitpattern);
[~,errors_bm,ber_bm,loc] = calc_ber(d_bm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",1);
[~,errors_dcsm,ber_dcsm] = calc_ber(d_dcsm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
[~,errors_lvsm,ber_lvsm] = calc_ber(d_lvsm.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
[~,errors_lvlp,ber_lvlp] = calc_ber(d_lvlp.signal(1:end-dbit,:) ,bitpattern(1:end,:),"skip",0,"returnErrorLocation",0);
% Display BER
disp(['BER benchmark: ', sprintf('%2E',ber_bm), ' ERRORS: ' ,num2str(sum(errors_bm))]);
disp(['BER dc smooth (A1): ', sprintf('%2E',ber_dcsm), ' ERRORS: ' ,num2str(sum(errors_dcsm))]);
disp(['BER lv smooth (A2): ', sprintf('%2E',ber_lvsm), ' ERRORS: ' ,num2str(sum(errors_lvsm))]);
disp(['BER lv lowpas: ', sprintf('%2E',ber_lvlp), ' ERRORS: ' ,num2str(sum(errors_lvlp))]);
%% Generate some Plots
if 1
% SCATTER
col = cbrewer2('Paired',8);
xax = 1:Eq_out.length;
figure(3)
sgtitle('')
subplot(1,3,1)
hold on
eq_decision = digimod.decide_pamlevel(Eq_out);
true_symbols = digimod.decide_pamlevel(digimod_out);
xindices = 1:Eq_in.length;
errorpos = find(loc~=0)*2;
errorpos(errorpos>length(Eq_in.signal)) = length(Eq_in.signal);
correct = find(loc==0)*2;
correct(correct>length(Eq_in.signal)) = length(Eq_in.signal);
scatter(xindices(correct),Eq_in.signal(correct),4,'.','MarkerEdgeColor',col(4,:),'DisplayName','After EQ');
hold on
scatter(xindices(errorpos),Eq_in.signal(errorpos),6,'x','MarkerEdgeColor',col(6,:),'DisplayName','Wrong Decision');
hold off
xlim([1, xindices(end)]);
ylim([-3 3]);
xlabel('Sampling Index')
ylabel('Amplitude')
a = legend;
a.Location = "best";
subplot(1,3,2)
xindices = 1:Eq_out.length;
xax_sec = (1:Eq_out.length) / fsym .* 1e6;
scatter(xax_sec(loc==0),Eq_out.signal(loc==0),4,'.','MarkerEdgeColor',col(4,:),'DisplayName','After EQ');
hold on
scatter(xindices(loc~=0),Eq_out.signal(loc~=0),8,'x','MarkerEdgeColor',col(6,:),'DisplayName','Wrong Decision');
hold off
xlim([1, xax(end)]);
ylim([-2 2]);
xlabel('Sampling Index')
ylabel('Amplitude')
legend
a = legend;
a.Location = "best";
hold off
subplot(1,3,3)
xindices = 1:yk_lvsm.length;
scatter(xindices(loc==0),yk_lvsm.signal(loc==0),4,'.','MarkerEdgeColor',col(4,:),'DisplayName','After A2');
hold on
scatter(xindices(loc~=0),yk_lvsm.signal(loc~=0),8,'x','MarkerEdgeColor',col(6,:),'DisplayName','Wrong Decision');
hold off
xlim([1, xax(end)]);
ylim([-2 2]);
xlabel('Sampling Index')
ylabel('Amplitude')
legend
a = legend;
a.Location = "best";
hold off
end
if 0
col = cbrewer2('Paired',8);
figure(11)
clf
subplot(2,1,1)
hold on
plot(digimod_out.signal(4150:4175),'DisplayName','Tx','Color',col(1,:),'LineWidth',3);
plot(Eq_out.signal(4150:4175),'DisplayName','Rx after EQ','Color',col(6,:),'LineWidth',1);
title('Modulated Sequence Zoom');
legend
hold off
subplot(2,1,2)
hold on
stem(d_bm.signal(4150:4175,1),'DisplayName','Tx','Color',col(1,:),'LineStyle','-','LineWidth',5)
stem(bitpattern(4150:4175,1)','DisplayName','Rx','Color',col(6,:),'LineStyle','--','LineWidth',2)
title('Bitpattern Tx - Rx');
legend
hold off
end
end

View File

@@ -0,0 +1,74 @@
function wh = submit_simulations(wh,db,options)
arguments
wh
db
options.parallel = 1;
options.simulation_mode = 1;
end
%%% 2) SUBMIT SIMULATION
% Initialize job results
if options.parallel
if isempty(gcp('nocreate'))
parpool;
end
results = parallel.FevalFuture.empty();
else
results = [];
end
lin_idx = 1;
for lin_idx = 1:wh.getLastLinIndice
optionalVars = struct();
if ~isempty(wh.getDimension)
% Build the optionalVars struct
[parametervalues,parameternames]=wh.getPhysIndicesByLinIndex(lin_idx);
for pidx = 1:numel(parameternames)
optionalVars.(parameternames{pidx}) = parametervalues{pidx};
end
end
%%% SIMULATION HERE
if options.parallel
numOutputs = 1;
results(lin_idx) = parfeval(@imdd_model, numOutputs, options.simulation_mode, db, optionalVars);
else
finalresults{lin_idx} = imdd_model(options.simulation_mode,db,optionalVars);
wh.addValueToStorageByLinIdx(finalresults{lin_idx}, 'ber', lin_idx);
end
end
if options.parallel
%%% 4) Setup waitbar
h = waitbar(0, 'Processing Simulations...');
% Helper function to compute progress
updateWaitbar = @(~) waitbar(mean(arrayfun(@(f) strcmp(f.State, 'finished'), results)), h);
fprintf('Fetching results... \n');
% Update the waitbar after each simulation
updateWaitbarFutures = afterEach(results, updateWaitbar, 0);
% Close the waitbar after all simulations complete
afterAll(updateWaitbarFutures, @(~) delete(h), 0);
%%% 7) Fetch final results after all computations
fetchOutputs(results);
for ridx = 1:length(results)
wh.addValueToStorageByLinIdx(results(ridx).OutputArguments{1}, 'ber', ridx);
end
end
end

View File

@@ -0,0 +1,31 @@
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.5,...
"applypulseform",apply_pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_encode,...
"mrds_code",0,"mrds_blocklength",512).process();
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 = El_sig.setPower(0,"dBm");
%%%%% Low-pass el. components %%%%%%
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bw_nyquist.*f_nyquist,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
%%%%% Electrical Driver Amplifier %%%%%%
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
El_sig = El_sig.normalize("mode","oneone");
%%%%% 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).process(El_sig);