function [Rx_sig_2sps,Symbols,Tx_bits] = standard_link_model(options) % STANDARD_LINK_MODEL Basic IM/DD link simulation % Rx_sig_2sps = standard_link_model(...optional args...) % % All arguments are optional and default to standard parameters % if not provided. arguments % --- Transmitter settings --- options.M (1,1) double = 4 options.apply_pulsef (1,1) logical = true options.fdac (1,1) double = 256e9 options.fadc (1,1) double = 256e9 options.random_key (1,1) double = 2 options.rcalpha (1,1) double = 0.05 options.kover (1,1) double = 8 options.vbias_rel (1,1) double = 0.5 options.u_pi (1,1) double = 3.2 options.laser_wavelength (1,1) double = 1310 options.laser_linewidth (1,1) double = 1e6 % --- Channel parameters --- options.link_length_km (1,1) double = 0 options.rop (1,:) double = -5 options.fsym (1,:) double = (212:16:256)*1e9 options.doub_mode (1,1) db_mode = db_mode.no_db % --- Debug --- options.debug (1,1) logical = false end % --- Pulse former --- Pform = Pulseformer("fsym",options.fsym,"fdac",4*options.fsym, ... "pulse","rc","pulselength",16,"alpha",options.rcalpha); % --- Transmitter source --- [Digi_sig,Symbols,Tx_bits] = PAMsource( ... "fsym",options.fsym,"M",options.M,"order",18,"useprbs",0, ... "fs_out",options.fdac,"applyclipping",0,"clipfactor",1.5, ... "applypulseform",options.apply_pulsef,"pulseformer",Pform, ... "randkey",options.random_key,"db_precode",0,"db_encode",0, ... "mrds_code",0,"mrds_blocklength",512, ... "duobinary_mode",options.doub_mode).process(); % --- AWG driver --- El_sig = M8199B("kover",options.kover).process(Digi_sig); El_sig = El_sig.normalize("mode","oneone"); % --- E/O Modulation --- vbias = -options.vbias_rel*options.u_pi; Opt_sig = EML("mode",eml_mode.im_cosinus,"power",3, ... "fsimu",El_sig.fs,"lambda",options.laser_wavelength, ... "bias",vbias,"u_pi",options.u_pi,"linewidth",options.laser_linewidth, ... "randomkey",options.random_key+1).process(El_sig); % --- Fiber --- Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",options.link_length_km, ... "alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig); % --- Amplifier (ROP set) --- Opt_sig = Amplifier("amp_mode","ideal_no_noise", ... "gain_mode","output_power","amplification_db",options.rop).process(Opt_sig); % --- Photodiode --- PD_sig = Photodiode("fsimu",options.fdac*options.kover,"dark_current",2e-8, ... "responsivity",1,"temperature",20,"nep",1.8e-11, ... "randomkey",options.random_key).process(Opt_sig); % --- Electrical LPF (receiver frontend) --- rx_bwl = 70e9; PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl, ... "fs",options.fdac*options.kover,"filterType",filtertypes.butterworth, ... "active",true).process(PD_sig); % --- Scope low-pass and sampling --- Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",options.fadc, ... "filterType",filtertypes.butterworth,"active",true); Scpe_sig = Scope("fsimu",options.fdac*options.kover,"fadc",options.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(PD_sig); % --- Downsample to 2 sps --- Scpe_sig_2sps = Scpe_sig.resample("fs_out",2*options.fsym); [~,Scpe_cell,~,found_sync] = Scpe_sig_2sps.tsynch( ... "reference",Symbols,"fs_ref",options.fsym,"debug_plots",0); try Rx_sig_2sps = Scpe_cell{1}.normalize("mode","rms"); catch Rx_sig_2sps = Scpe_sig_2sps.normalize("mode","rms"); end end