fullFolderPath = fullfile(savePath, current_folder); if ~exist(fullFolderPath, 'dir') mkdir(fullFolderPath); end 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 = 0; %% Configuration conf = confRequest; referenceFields = fieldnames(db.tables.Configurations); % assert(isequal(fieldnames(conf), referenceFields), 'Fieldnames do not match the reference structure!'); %% Lab Automation if run_lab_automation % DC Source if (any(confPrev.v_bias ~= conf.v_bias)) || (~exist('dcs','var')) || (isempty(confPrev.v_bias)) 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(); end % Laser if (any(confPrev.laser_power ~= conf.laser_power)) || (~exist('laser','var')) || (isempty(confPrev.laser_power)) 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(); end % Optical Attenuator if ~exist('voa','var') voa = OptAtten("active",[1,2,1,1],"value",[0,conf.pd_in_desired,conf.signal_attenuation,conf.interference_attenuation],"wavelength",[conf.wavelength,conf.wavelength,conf.wavelength,conf.wavelength]); end voa.set('value',[0,conf.pd_in_desired,conf.signal_attenuation,conf.interference_attenuation]); if voa.power_state(3) > -24 || voa.power_state(1)+ voa.atten_state(4) > -37 holdAndShowValue end % PDFA if ~exist('pdfa','var') pdfa = Thor_PDFA("safety_mode",0,"serialport_number",'COM15'); end end % if conf.symbolrate == 72e9 % if conf.pam_level == 2 % conf.v_awg = 0.55; % conf.pulsef_alpha = 0.6; % elseif conf.pam_level == 4 % conf.v_awg = 0.55; % conf.pulsef_alpha =0.6; % elseif conf.pam_level == 6 % conf.v_awg = 0.55; % conf.pulsef_alpha = 0.6; % elseif conf.pam_level == 8 % conf.v_awg = 0.55; % conf.pulsef_alpha = 0.6; % end % elseif conf.symbolrate == 96e9 % if conf.pam_level == 2 % conf.v_awg = 0.8; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 4 % conf.v_awg = 0.8; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 6 % conf.v_awg = 0.8; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 8 % conf.v_awg = 0.8; % conf.pulsef_alpha = 0.2; % end % elseif conf.symbolrate == 112e9 % if conf.pam_level == 2 % conf.v_awg = 0.85; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 4 % conf.v_awg = 0.85; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 6 % conf.v_awg = 0.85; % conf.pulsef_alpha = 0.2; % elseif conf.pam_level == 8 % conf.v_awg = 0.85; % conf.pulsef_alpha = 0.2; % end % end awg_upload_required = 1; if any(confPrev.pam_level == conf.pam_level) && any(confPrev.symbolrate == conf.symbolrate) awg_upload_required = 0; end %% Signal generation and transmission if awg_upload_required || isempty(loop_id) %%%%% Symbol Generation %%%%%% Pform = Pulseformer("fsym",conf.symbolrate,"fdac",8*conf.symbolrate,"pulse","rc","pulselength",16,"alpha",conf.pulsef_alpha); if conf.symbolrate < 64e9 sequence_order = min(18,sequence_order); end % Construct AWG and Scope Modules %%%%%% fdac = 224e9; fadc = 160e9; Scp = ScopeKeysight("model","DSAZ634A",'autoscale',0,"fadc","GSa_160","channel",[0,0,1,0],"recordLen",recordlen,"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); Pamsource = PAMsource(... "fsym",conf.symbolrate,"M",conf.pam_level,"order",sequence_order,"useprbs",1,... "fs_out",fdac,... "applyclipping",0,... "clipfactor",4,... "applypulseform",1,... "pulseformer",Pform,... "randkey",1,... "duobinary_mode", conf.db_mode); [Digi_sig,Symbols,Bits] = Pamsource.process(); figure(10);clf; Digi_sig.spectrum("displayname",'Tx Pulse Shaped','fignum',10,'normalizeTo0dB',1); %%%%% 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 Pre-Emphasized','fignum',10,'normalizeTo0dB',1); %%%%% Resample to DAC rate %%%%%% Digi_sig = Digi_sig.resample("fs_out",Awg.fdac); Digi_sig.spectrum("displayname",'Tx Resampled','fignum',10,'normalizeTo0dB',1); % [~,~,Scpe_sig_raw,~] = A2S.process("signal2",Digi_sig); Awg.upload("signal2",Digi_sig); end % Precompensation Routine (optional) if precomp_mode == 1 Scpe_sig_raw = Scp.read("channel",[0,0,1,0]); Scpe_sig_raw = Scpe_sig_raw{[0,0,1,0]==1}; precomp_est.estimate(Scpe_sig_raw, "save", true, "savePath", precomp_path, "fileName", precomp_fn); precomp_est.plot(); return; % End routine if precomp mode is active end confPrev = conf; %% Save static TX data (only once) currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss'); timeStr = char(currentTime); base_filename = sprintf('%s_PAM_%d_R_%d', timeStr, conf.pam_level, round(conf.symbolrate.*1e-9)); tx_bits_path = [filesep, current_folder, filesep, base_filename, '_bits']; save([savePath, tx_bits_path], "Bits"); tx_symbols_path = [filesep, current_folder, filesep, base_filename, '_symbols']; save([savePath, tx_symbols_path], "Symbols"); tx_signal_path = [filesep, current_folder, filesep, base_filename, '_signal']; save([savePath, tx_signal_path], "Digi_sig"); for recIdx = 1:n_recording fprintf('Recording %d / %d\n', recIdx, n_recording); %% Acquire Scope Signal Scpe_sig_raw = Scp.read("channel",[0,0,1,0]); Scpe_sig_raw = Scpe_sig_raw{[0,0,1,0]==1}; % Precompensation Routine (optional) if precomp_mode == 1 precomp_est.estimate(Scpe_sig_raw, "save", true, "savePath", precomp_path, "fileName", precomp_fn); precomp_est.plot(); return; % End routine if precomp mode is active end % Plot spectrum and time domain (optional) Scpe_sig_raw.spectrum("displayname", 'Rx Spectrum', 'fignum', 10, 'normalizeTo0dB', 0); Scpe_sig_raw.plot("clear", 1, "displayname", 'Rx Signal', 'fignum', 11); %% Save Routine currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss'); timeStr = char(currentTime); filename = sprintf('%s_PAM_%d_R_%d_rec%02d', timeStr, conf.pam_level, round(conf.symbolrate.*1e-9), recIdx); % Added recIdx rx_raw_path = [filesep, current_folder, filesep, filename, '_rx_signal_raw']; save([savePath, rx_raw_path], "Scpe_sig_raw"); % Check if loop_id is already created if isempty(loop_id) newLoop = db.tables.LoopControl; newLoop.loop_id = NaN; newLoop.date_of_loop = datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss'); newLoop.description = 'Automated parameter sweep'; loop_id = db.appendToTable('LoopControl', newLoop); fprintf('LoopControl entry created: loop_id = %d\n', loop_id); end %% Append to Runs Table newRun = db.tables.Runs; newRun.run_id = NaN; newRun.loop_id = loop_id; 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 = ""; % Leave empty for now newRun.rx_raw_path = rx_raw_path; newRun.filename = filename; newRun.tx_signal_path = tx_signal_path; run_id = db.appendToTable('Runs', newRun); %% Append to Configurations Table conf.configuration_id = NaN; conf.run_id = run_id; conf.bitrate = conf.symbolrate .* floor(log2(6)*10)/10; conf.pam_source = Pamsource; db.appendToTable('Configurations', conf); %% Append to Measurements Table laser.getLaserInfo; meas = db.tables.Measurements; meas.measurement_id = NaN; 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; % Ensure consistency assert(isequal(fieldnames(meas), fieldnames(db.tables.Measurements)), 'Fieldnames of "meas" do not match the reference structure!'); db.appendToTable('Measurements', meas); %% Submit DSP Routine if recIdx == 1 if subimt_DSP [out, a] = submit_dsp(run_id, databasePath, database_name, savePath, ... "parallel", parallel_dsp, "max_occurences", max_occurences); end if awg_upload_required [out, a] = submit_dsp(run_id, databasePath, database_name, savePath, ... "parallel", 0, "max_occurences", 1); end end end