function measure_run(options) arguments options.parallel (1,1) logical = false options.max_occurences = 1; options.config = []; options.only_record = 0; end savePath = 'Z:\2025\ECOC Silas\ecoc_2025\'; current_folder = 'precomp_optimization_friday'; fullFolderPath = fullfile(savePath, current_folder); if ~exist(fullFolderPath, 'dir') mkdir(fullFolderPath); end basePath = 'C:\Users\sioe\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; database_name='ecoc2025.db'; db = DBHandler("pathToDB",[basePath,database_name]); precomp_path = "C:\Users\sioe\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\"; precomp_fn = "precomp_1km_1mm_cable_70ghz_pd_shf_t850_2p8_bias_shot2"; precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active run_lab_automation = 1; %% Configuration conf = db.tables.Configurations; referenceFields = fieldnames(conf); conf.unique_elab_id = "20250408-842b0a3078172b48dd032795226fbe683190afc4"; conf.symbolrate = 112e9; conf.bitrate = conf.symbolrate .* floor(log2(6)*10)/10; conf.pam_level = 4; conf.db_mode = db_mode.no_db; conf.pulsef_alpha = 0.3; conf.v_bias = 2.8; conf.v_awg = 0.8; conf.precomp_amp = -64; conf.wavelength = 1310; conf.laser_power = 10; conf.fiber_length = 0; conf.pd_in_desired = 7; conf.is_mpi = 1; conf.signal_attenuation = 0; conf.interference_path_length = 0.001; %m conf.interference_attenuation = 40; conf.pam_source = []; % === Optional Override of Conf === if ~isempty(options.config) paramStruct = options.config; paramNames = fieldnames(paramStruct); for i = 1:numel(paramNames) thisName = paramNames{i}; thisValue = paramStruct.(thisName); if isfield(conf, thisName) conf.(thisName) = thisValue; else warning('Unknown parameter: %s', thisName); end end end assert(isequal(fieldnames(conf), referenceFields), 'Fieldnames do not match the reference structure!'); currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss'); timeStr = char(currentTime); filename = sprintf('%s_PAM_%d_R_%d',timeStr,conf.pam_level,conf.symbolrate.*1e-9); %% Lab Automation if run_lab_automation % DC Source dcs = DC_supply("active",[1,1],"voltage",[conf.v_bias, 5]); dcs.set("voltage",[conf.v_bias, 5]); [v_bias_meas,i_bias_meas]=dcs.readVals(); % Laser laser = Exfo_laser("mainframe_channel",1,"safety_mode",0,"connection_id",'10','lab_interface','gpib'); laser.setWavelength(conf.wavelength); laser.setPower(conf.laser_power); laser.enableLaser(); % Optical Attenuator voa = OptAtten("active",[0,2,1,1],"value",[0,conf.pd_in_desired,conf.signal_attenuation,conf.interference_attenuation],"wavelength",[conf.wavelength,conf.wavelength,conf.wavelength,conf.wavelength]); voa.set('value',[0,conf.pd_in_desired,conf.signal_attenuation,conf.interference_attenuation]); % PDFA pdfa = Thor_PDFA("safety_mode",0,"serialport_number",'COM15'); % Construct AWG and Scope Modules %%%%%% fdac = 256e9; fadc = 160e9; Scp = ScopeKeysight("model","DSAZ634A",'autoscale',1,"fadc","GSa_160","channel",[0,0,1,0],"recordLen",2000000,"removeDC",1,"extRef",1); Awg = AwgKeysight("model","M8199A_ILV","fdac",fdac,"scaletodac",[1,1],"skews",[0,0],"voltages",[0,conf.v_awg]); A2S = Awg2Scope(Awg,Scp,[0,0,3,0],"waitUntilClick",0); end %% Signal generation and transmission %%%%% Symbol Generation %%%%%% Pform = Pulseformer("fsym",conf.symbolrate,"fdac",8*conf.symbolrate,"pulse","rc","pulselength",16,"alpha",conf.pulsef_alpha); Pamsource = PAMsource(... "fsym",conf.symbolrate,"M",conf.pam_level,"order",18,"useprbs",1,... "fs_out",fdac,... "applyclipping",0,... "clipfactor",4,... "applypulseform",1,... "pulseformer",Pform,... "randkey",1,... "duobinary_mode", conf.db_mode); conf.pam_source = Pamsource; [Digi_sig,Symbols,Bits] = Pamsource.process(); %%%%% Precompensation Routine %%%%%% if precomp_mode == 1 % measure channel precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',fdac); Digi_sig = precomp_est.buildOFDM(); elseif precomp_mode == 2 % apply precomp precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs); Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',conf.precomp_amp,'loadPath',precomp_path,'fileName',precomp_fn); end Digi_sig.spectrum("displayname",'Tx Spectrum','fignum',10,'normalizeTo0dB',0); %%%%% Resample to DAC rate %%%%%% Digi_sig = Digi_sig.resample("fs_out",Awg.fdac); [~,~,Scpe_sig_raw,~] = A2S.process("signal2",Digi_sig); % Awg.upload("signal2",Digi_sig); % Scpe_sig_raw = Scp.read("channel",[0,0,1,0]); % Scpe_sig_raw = Scpe_sig_raw{[0,0,1,0]==1}; %%%%% Precompensation Routine %%%%%% if precomp_mode == 1 % Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",fadc,"fs_out",2*fsym); precomp_est.estimate(Scpe_sig_raw,"save",true,"savePath",precomp_path,"fileName",precomp_fn); precomp_est.plot(); return; end Scpe_sig_raw.spectrum("displayname",'Rx Spectrum','fignum',10,'normalizeTo0dB',0); Scpe_sig_raw.plot("clear",1,"displayname",'Rx Signal','fignum',11); %% %%%%% Save Routine %%%%%%%%%%%%%%%%%%%%%%%%% tx_bits_path=[filesep,current_folder,filesep,filename,'_bits']; save([savePath,tx_bits_path],"Bits"); tx_symbols_path=[filesep,current_folder,filesep,filename,'_symbols']; save([savePath,tx_symbols_path],"Symbols"); tx_signal_path=[filesep,current_folder,filesep,filename,'_signal']; save([savePath,tx_signal_path],"Digi_sig"); rx_raw_path = [filesep,current_folder,filesep,filename,'_rx_signal_raw']; save([savePath,rx_raw_path],"Scpe_sig_raw"); % Table 1: Append to Runs newRun = db.tables.Runs; newRun.run_id = NaN; newRun.date_of_run = datetime(currentTime, 'InputFormat', 'yyyyMMdd_HHmmss'); newRun.tx_bits_path = tx_bits_path; newRun.tx_symbols_path = tx_symbols_path; newRun.rx_sync_path = []; newRun.rx_raw_path = rx_raw_path; newRun.filename = filename; newRun.tx_signal_path = tx_signal_path; run_id = db.appendToTable('Runs', newRun); % Table 2: Append to Configurations conf.configuration_id = NaN; conf.run_id = run_id; db.appendToTable('Configurations', conf); % Table 3: Append to Measurements meas = db.tables.Measurements; meas.measurement_id = NaN; % Auto-increment, leave empty meas.run_id = run_id; meas.power_laser = laser.cur_power; meas.power_rop = []; meas.power_pd_in = voa.power_state(2); meas.power_mpi_interference = voa.power_state(4); meas.power_mpi_signal = voa.power_state(3); meas.voa_class = voa; meas.pdfa_class = pdfa; meas.laser_class = laser; assert(isequal(fieldnames(meas), fieldnames(db.tables.Measurements)), 'Fieldnames of "meas" do not match the reference structure!'); db.appendToTable('Measurements', meas); %% %%%%% DSP Routine %%%%%%%%%%%%%%%%%%%%%%%%% [out, ~] = submit_dsp(run_id, basePath, database_name, savePath,"parallel",options.parallel,'max_occurences',options.max_occurences); end