function [output] = imdd_model(simulation_mode,varargin) %%% Change folder 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; random_key = 1; precomp = 0; db_precode = 0; 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 = 0.8; % Channel link_length = 1; % RX rop = -8; rx_bw_nyquist = 0.8; vnle_order1 = 50; vnle_order2 = 7; vnle_order3 = 7; vnle_order=[vnle_order1,vnle_order2,vnle_order3]; dfe_order = [0 0 0]; alpha = 0; len_tr = 4096*2; mu_ffe1 = 0.0001; mu_ffe2 = 0.0008; mu_ffe3 = 0.001; mu_dc = 0.005; mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3]; mu_dfe = 0.0004; dfe_ = sum(dfe_order)>0; doub_mode = db_mode.db_precoded; %%% 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 if doub_mode ~= db_mode.db_encoded if precomp == 0 && db_precode == 1 doub_mode = db_mode.db_precoded; db_precode = 1; % preceded data (in my measurement set, this corresponds to low precomp too!) discard_precode = 0; % emulate_precode = 0; legendentry = 'low precomp; precoded'; disp('low precomp; precoded') elseif precomp == 1 && db_precode == 1 doub_mode = db_mode.db_emulate; db_precode = 0; % preceded data (in my measurement set, this corresponds to low precomp too!) discard_precode = 0; % emulate_precode = 1; legendentry = 'high precomp; precoded'; disp('high precomp; precoded') elseif precomp == 0 && db_precode == 0 doub_mode = db_mode.db_discard; db_precode = 1; % preceded data (in my measurement set, this corresponds to low precomp too!) discard_precode = 1; % emulate_precode = 0; legendentry = 'no precomp; not precoded'; disp('no precomp; not precoded') elseif precomp == 1 && db_precode == 0 doub_mode = db_mode.no_db; db_precode = 0; % preceded data (in my measurement set, this corresponds to low precomp too!) discard_precode = 0; % emulate_precode = 0; legendentry = 'high precomp; not precoded'; disp('high precomp; not precoded') end else end 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 f_nyquist = fsym/2; %%% run the simulation or measurement or ... if simulation_mode Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha); [Digi_sig,Symbols,Tx_bits] = PAMsource(... "fsym",fsym,"M",M,"order",17,"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 %%%%%% tx_bwl = tx_bw_nyquist.*f_nyquist; % tx_bwl = 80e9; El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig); % El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1); %%%%% 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); 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_bwl = rx_bw_nyquist.*f_nyquist; % rx_bwl = 80e9; Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"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); Scpe_cell{1} = Scpe_sig; else profile on basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\'; database = DBHandler("pathToDB",[basePath,'silas_labor.db']); profile off 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', laser_wavelength ... ); 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','Measurements.power_rop','Configurations.v_bias'}; [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(end))]); Tx_bits = Tx_bits.Bits; Symbols = load([basePath, char(dataTable.tx_symbols_path(end))]); Symbols = Symbols.Symbols; Scpe_load = load([basePath, char(dataTable.rx_sync_path(end))]); Scpe_cell = Scpe_load.S; % Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]); % Raw_signal = Raw_signal.Scpe_sig_raw; % % Raw_signal = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.55,"fs",Raw_signal.fs,"filterType",filtertypes.gaussian,"active",true).process(Raw_signal); % Scpe_cell{1}.eye(fsym,M,"displayname",'eye','fignum',227); % % Raw_signal.spectrum("normalizeTo0dB",0,"fignum",336,"fft_length",2^12); % Raw_signal.move_it_spectrum("fignum",334); % Raw_signal.move_it_spectrum("fignum",334); fsym = Symbols.fs; end if db_precode Symbols_precoded = Symbols; end output = struct(); vnle_pf_package = {}; vnle_dfe_package = {}; dbtgt_package = {}; proc_occ = min(1,length(Scpe_cell)); for occ = 1:proc_occ 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,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym); 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); %%% EQUALIZING % 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); mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3]; % %%%%% VNLE + DFE %%%% if 1 eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"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",1,"ideal_dfe",0); [result] = vnle(eq_vnle_dfe,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",doub_mode,"showAnalysis",1); vnle_dfe_package{occ} = result; end %%%%% VNLE + PF + MLSE %%%% if 1 % len_tr = length(Symbols)-1000; 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_vnle_ = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",vnle_order,"sps",2,"decide",0); pf_ = Postfilter("ncoeff",1,"useBurg",1); mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); [result] = vnle_postfilter_mlse(eq_vnle_,pf_,mlse_,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",doub_mode,'showAnalysis',1); vnle_pf_package{occ} = result; end %%%%% Duobinary Targeting %%%% if 1 mlse_db = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels); eq_db = 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); [result] = duobinary_target(eq_db, mlse_db, M, Scpe_sig, Symbols, Tx_bits, "precode_mode", doub_mode,'showAnalysis',1); dbtgt_package{occ} = result; end %%%%%% %db signaling => db encoded %%%%% if 0 mlse_db_enc = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"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); [result] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Tx_bits); dbenc_package{occ} = result; end % autoArrangeFigures; disp('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ') fprintf('\n') end output.vnle_dfe_package = vnle_dfe_package; output.vnle_pf_package = vnle_pf_package; output.dbtgt_package = dbtgt_package; if ~isempty(curFolder) cd(curFolder); end end