From 5dbc48abc0bc8886e2ac77bf7b6cd90fa769832e Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Mon, 11 Aug 2025 07:42:04 +0200 Subject: [PATCH] Many changes here and there. I lost track... :-( Current work is on MLSE and SD Decoding etc. MLSE is currently not 100% working, the scalings are maybe off?! --- Classes/00_signals/Signal.m | 44 ++-- Classes/01_transmit/M8199B.m | 2 +- Classes/01_transmit/PAMsource.m | 7 + Classes/02_optical/Fiber.m | 220 ++++++++-------- Classes/04_DSP/Sequence Detection/MLSE.m | 65 +++-- Classes/04_DSP/Sequence Detection/MLSE_new.m | 152 +++++++++++ Classes/DataBaseHandler/DBHandler.m | 4 +- Functions/EQ_structures/dsp_runid.m | 34 +-- Functions/EQ_structures/duobinary_target.m | 6 +- .../EQ_structures/vnle_postfilter_mlse.m | 17 +- Functions/EQ_visuals/showEQNoisePSD.m | 3 +- Functions/EQ_visuals/showEQfilter.m | 8 +- Functions/EQ_visuals/showLevelHistogram.m | 1 + .../loadAndSyncSignalDataFromDb.m | 2 +- Functions/Job_Processing/preprocessSignal.m | 6 +- Functions/Job_Processing/submitJobs.m | 2 +- Functions/Metrics/calc_air.m | 4 +- Functions/Metrics/calc_gmi_bitwise.m | 94 +++++++ Functions/Metrics/calc_ngmi.m | 32 +-- Functions/Metrics/calc_snr.m | 48 ++-- Functions/Theory/dispersion_contour.m | 54 ++++ Functions/getFigureSize.m | 33 +++ .../Auswertung_JLT/ber_vs_dispersion.m | 111 ++++++++ .../Auswertung_JLT/ber_vs_rate.m | 86 +++++++ .../ber_vs_rate_only_best_configs.m | 117 +++++++++ .../Auswertung_JLT/gmi_vs_rate.m | 84 +++++++ .../Auswertung_JLT/power_vs_wavelength.m | 96 +++++++ .../Auswertung_JLT/run_dsp_from_db.m | 14 +- .../Auswertung_JLT/simulate_and_dsp.m | 236 ++++++++++++++++++ .../auswertung/only_show_precomp.m | 7 +- .../bias_evaluation.m | 4 +- .../db_auswertung/rate_vs_ber.m | 6 +- projects/IMDD_base_system/imdd_model.m | 2 +- projects/IMDD_base_system/simulation_bwl.m | 234 +++++++++-------- projects/Job_Processing/run_offline_dsp.m | 117 --------- .../Job_Processing/run_offline_dsp_script.m | 116 --------- .../load_n_plot_transfer_characteristic.m | 8 + 37 files changed, 1506 insertions(+), 570 deletions(-) create mode 100644 Classes/04_DSP/Sequence Detection/MLSE_new.m create mode 100644 Functions/Metrics/calc_gmi_bitwise.m create mode 100644 Functions/Theory/dispersion_contour.m create mode 100644 Functions/getFigureSize.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_dispersion.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate_only_best_configs.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/gmi_vs_rate.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/power_vs_wavelength.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/simulate_and_dsp.m delete mode 100644 projects/Job_Processing/run_offline_dsp.m delete mode 100644 projects/Job_Processing/run_offline_dsp_script.m diff --git a/Classes/00_signals/Signal.m b/Classes/00_signals/Signal.m index eb41f39..9b0c3e5 100644 --- a/Classes/00_signals/Signal.m +++ b/Classes/00_signals/Signal.m @@ -269,6 +269,7 @@ classdef Signal SignalPower = [obj.power]; Nase = [0]; SignalCopy = obj.signal; + SignalCopy = []; ModifierName = class(CallingModifier); @@ -365,7 +366,7 @@ classdef Signal if options.normalizeTo0dB p_lin = p_lin./ max(p_lin); p_dbm = 10*log10(p_lin); % normalized to 0 dB - ylab = "normalized to 0 dB"; + ylab = "Normalized PSD"; else p_dbm = 10*log10(p_lin); ylab = "Power (dB/Hz)"; @@ -395,7 +396,7 @@ classdef Signal if options.normalizeToNyquist == 0 xlabel("Frequency in GHz"); edgetick = 2^(nextpow2(obj.fs*1e-9)); - xticks(-edgetick:16:edgetick); + xticks(-edgetick:32:edgetick); xlim([100*round(min(w)/100,1)-10, 100*round(max(w)/100,1)+10]) xlim([-128 128]);%256GSa/s else @@ -406,13 +407,20 @@ classdef Signal ylabel(ylab); try - ylim([max(min(floor(min(p_dbm))-3, ax.YLim(1)),-40), min(max(ceil(max(p_dbm))+3, ax.YLim(2)),10)]); + ylim([max(min(floor(min(p_dbm))-3, ax.YLim(1)),-40), min(max(ceil(max(p_dbm))+3, ax.YLim(2)),10)]); catch - ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]); + ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]); end - ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]); + + if options.normalizeTo0dB + % ylim([-40, 3]); + ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]); + else + ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]); + end + yticks(-200:10:10); - grid on; grid minor; + grid on;% grid minor; legend % legend('Interpreter','none'); @@ -912,8 +920,8 @@ classdef Signal elseif mode == 1 % generate eye diagram using histogram - maxA = max(sig(100:end-100))*2; - minA = min(sig(100:end-100))*2; + maxA = max(sig(100:end-100))*1.3; + minA = min(sig(100:end-100))*1.3; % maxA = 0.0015; % minA = 0; @@ -926,8 +934,8 @@ classdef Signal nn=histcounts(data_ind_y(n,:),1:histpoints+1); hist_data(:,n)=flip(nn.'); %without flip, the eye is upside down :-( end - - ax = gca; + + plot_data = 20*log10(hist_data); plot_data(plot_data==-Inf) = 0; @@ -944,27 +952,29 @@ classdef Signal if isa(obj,'Opticalsignal') title(['Optical Eye ',options.displayname]) ylabel("Power in mW"); - y_tickstring = string(linspace(maxA.*1e3,minA.*1e3,16)); + y_tickstring = string(linspace(maxA.*1e3,minA.*1e3,6)); min_ = min(abs(obj.signal(100:end-100)).^2); max_ = abs(max(obj.signal(100:end-100)).^2); elseif isa(obj,'Electricalsignal') title(['Electrical Eye ',options.displayname]) ylabel("Voltage in V"); - y_tickstring = string(linspace(maxA,minA,16)); + y_tickstring = string(linspace(maxA,minA,6)); min_ = min(obj.signal(100:end-100)); max_ = abs(max(obj.signal(100:end-100))); else title(['Digital Eye ',options.displayname]) ylabel("Digital Signal Amplitude"); - y_tickstring = string(linspace(maxA,minA,16)); + y_tickstring = string(linspace(maxA,minA,6)); min_ = min(obj.signal(100:end-100)); max_ = abs(max(obj.signal(100:end-100))); end xlabel('Time in ps') + + % add information - if 0 + if 1 pwr_dbm = round(obj.power,3); pwr_lin = obj.power("unit",power_notation.W); @@ -1073,13 +1083,15 @@ classdef Signal end - yticks(linspace(0,histpoints,16)); + yticks(linspace(0,histpoints,6)); y_tickstring = sprintfc('%.2f', y_tickstring); yticklabels(y_tickstring); - xticks(linspace(0,histpoints_horizontal,8)) + xticks(linspace(0,histpoints_horizontal,6)) x_tickstring = sprintfc('%.2f', linspace(0, 2/fsym, 8) .* 1e12); xticklabels(x_tickstring); + + grid off end diff --git a/Classes/01_transmit/M8199B.m b/Classes/01_transmit/M8199B.m index 2519453..7a2a34e 100644 --- a/Classes/01_transmit/M8199B.m +++ b/Classes/01_transmit/M8199B.m @@ -17,7 +17,7 @@ classdef M8199B < AWG fdac = 256e9; - Lp_awg = Filter('filtdegree',4,"f_cutoff",75e9,"fs",fdac*options.kover,"filterType",filtertypes.butterworth,"active",true); + Lp_awg = Filter('filtdegree',3,"f_cutoff",75e9,"fs",fdac*options.kover,"filterType",filtertypes.gaussian,"active",true); obj = obj@AWG("fdac",fdac,"dac_min",dac_min,"dac_max",dac_max,"lpf_active",1,"H_lpf",Lp_awg,"kover",options.kover,... "bit_resolution",5.5,"normalize2dac",1,"upsampling_method","samplehold"); diff --git a/Classes/01_transmit/PAMsource.m b/Classes/01_transmit/PAMsource.m index dd77f89..d29f7f7 100644 --- a/Classes/01_transmit/PAMsource.m +++ b/Classes/01_transmit/PAMsource.m @@ -136,6 +136,13 @@ classdef PAMsource %%%%%% Duobinary %%%%%%%%%%% + if obj.db_precode + obj.duobinary_mode = db_mode.db_precoded; + end + if obj.db_encode + obj.duobinary_mode = db_mode.db_encoded; + end + switch obj.duobinary_mode case db_mode.no_db diff --git a/Classes/02_optical/Fiber.m b/Classes/02_optical/Fiber.m index 55f8ec2..fbdca1b 100644 --- a/Classes/02_optical/Fiber.m +++ b/Classes/02_optical/Fiber.m @@ -1,189 +1,171 @@ classdef Fiber - %FIBER Summary of this class goes here - % Detailed explanation goes here + % Fiber: Simulate optical fiber signal propagation using + % the split-step Fourier method (SSFM). properties + % Simulation sampling frequency [Hz] fsimu + % Fiber length [m] fiber_length + % Attenuation coefficient [dB/km] alpha + % Dispersion parameter D [s/m^2] D + % Dispersion slope [s/m^3] Dslope + % Reference wavelength [m] lambda0 + % Nonlinear coefficient [1/(W·m)] gamma + % Maximum allowed nonlinear phase change per step [rad] dphimax + % Derived parameters: + % Second-order dispersion coefficient β2 [s^2/m] b2 + % Third-order dispersion coefficient β3 [s^3/m] b3 + % Linear attenuation constant [1/m] alpha_lin + % Frequency-domain linear operator per unit length linstep end methods function obj = Fiber(options) - %FIBER Construct an instance of this class - % Detailed explanation goes here + % Constructor: initialize fiber physical and simulation parameters. arguments - options.fsimu - options.fiber_length = 0 - options.alpha = 0.2 - options.D = 17 - options.Dslope = 0.06 - options.lambda0 = 1550 - options.gamma = 0 - options.dphimax = 5e-3 + options.fsimu % Sampling frequency [Hz] + options.fiber_length = 0 % Fiber length [km] + options.alpha = 0.2 % Attenuation [dB/km] + options.D = 17 % Dispersion D parameter [ps/(nm·km)] + options.Dslope = 0.06 % Dispersion slope [ps/(nm^2·km)] + options.lambda0 = 1550 % Reference wavelength [nm] + options.gamma = 0 % Nonlinear coefficient [1/(W·km)] + options.dphimax = 5e-3 % Max phase step [rad] end - obj.fsimu = options.fsimu; - obj.fiber_length = options.fiber_length*1000; %km - obj.alpha = options.alpha; - obj.D = options.D*1e-6; - obj.Dslope = options.Dslope*1e3; - obj.lambda0 = options.lambda0*1e-9; - obj.gamma = options.gamma; - obj.dphimax = options.dphimax; - - - + % Assign inputs to object properties, converting units to SI. + obj.fsimu = options.fsimu; + obj.fiber_length = options.fiber_length * 1e3; % km → m + obj.alpha = options.alpha; + obj.D = options.D * 1e-6; % ps/(nm·km) → s/(m·m) + obj.Dslope = options.Dslope * 1e3; % ps/(nm^2·km) → s/m^2 + obj.lambda0 = options.lambda0 * 1e-9; % nm → m + obj.gamma = options.gamma; % 1/(W·km) (assumed → 1/(W·m) internally) + obj.dphimax = options.dphimax; end - function signalclass_out = process(obj,signalclass_in) + function signalclass_out = process(obj, signalclass_in) + % process: Apply fiber propagation to input signal class. + % Calls the internal SSFM routine and logs the operation. - % actual processing of the signal (steps 1. - 3.) - signalclass_in = obj.process_(signalclass_in); + % Run internal split-step propagation + signalclass = obj.process_(signalclass_in); - % append to logbook - lbdesc = 'Fiber '; - signalclass_in = signalclass_in.logbookentry(lbdesc); - - % write to output - signalclass_out = signalclass_in; + % Add entry to logbook for tracking + signalclass = signalclass.logbookentry('Fiber '); + % Return processed signal class + signalclass_out = signalclass; end - function opt_sig = process_(obj,opt_sig) - %METHOD1 Summary of this method goes here - % Detailed explanation goes here + function opt_sig = process_(obj, opt_sig) + % process_: Internal routine for one-step fiber propagation. + % Computes linear and (optionally) nonlinear effects. - signal = opt_sig.signal; + % Extract time-domain field and wavelength + signal = opt_sig.signal; lambda_signal = opt_sig.lambda; - obj.D = obj.D + (lambda_signal-obj.lambda0)*obj.Dslope; - - obj.b2 = -obj.D*lambda_signal^2/(2*pi*Constant.LightSpeed); - obj.b3 = ((lambda_signal.^2/(2*pi*Constant.LightSpeed)).^2*obj.Dslope); - obj.alpha_lin = obj.alpha/10*log(10)/1000; - + % Update dispersion parameter D for current wavelength + obj.D = obj.D + (lambda_signal - obj.lambda0) * obj.Dslope; + + % Compute dispersion coefficients (β2, β3) + obj.b2 = -obj.D * lambda_signal^2 / (2 * pi * Constant.LightSpeed); + obj.b3 = (lambda_signal^2 / (2 * pi * Constant.LightSpeed))^2 * obj.Dslope; + + % Convert attenuation from dB/km to linear 1/m + obj.alpha_lin = obj.alpha / 10 * log(10) / 1e3; + + % Build frequency axis for FFT operations N = length(signal); - faxis = linspace(-obj.fsimu/2,obj.fsimu/2,N+1); - faxis = ifftshift(faxis(:,1:end-1)); - faxis = faxis'; - - obj.linstep = -obj.alpha_lin/2 - 2*1j*pi^2*obj.b2*faxis.^2 - 4/3*1j*pi^3*obj.b3*faxis.^3; + faxis = linspace(-obj.fsimu/2, obj.fsimu/2, N+1); + faxis = faxis(1:end-1); % drop redundant endpoint + faxis = ifftshift(faxis)'; % center zero frequency - if 0 - H = exp((obj.linstep)*obj.fiber_length); - - figure(222) - hold on - plot(faxis.*1e-9,abs(real(Y)),'LineStyle','-','DisplayName','Abs(real) part of complex TF'); - xlabel("Frequency in GHz") - ylabel("$ R|(H(\omega, L))|$") - end + % Define linear operator per meter in frequency domain + obj.linstep = -obj.alpha_lin/2 ... % half-step loss + - 1j*2*pi^2*obj.b2 .* faxis.^2 ... % second-order dispersion + - 1j*(4/3)*pi^3*obj.b3 .* faxis.^3; % third-order dispersion + % Choose linear-only or nonlinear SSFM based on gamma if obj.gamma ~= 0 + % Full adaptive SSFM with nonlinear Schrödinger solver opt_out = obj.NLSE(signal); else - opt_out = ifft( fft(signal) .* exp(obj.linstep*obj.fiber_length) ); % only one linear step + % Single-step linear propagation in frequency domain + opt_out = ifft( fft(signal) .* exp(obj.linstep * obj.fiber_length) ); end - %TODO: attenuate nase ... - + % Update output field in signal class opt_sig.signal = opt_out; - end - function [yout] = NLSE(obj, xin) - - maxPow = obj.gamma.*max(abs(xin).^2); - - Leff = obj.dphimax / maxPow ; - - dz = Leff; + function yout = NLSE(obj, xin) + % NLSE: Solve nonlinear Schrödinger equation by adaptive split-step + % xin: input time-domain field + % Returns yout: output time-domain field after propagation + % Initial estimate of effective length per step + maxPow = obj.gamma * max(abs(xin).^2); + Leff = obj.dphimax / maxPow; + dz = Leff; z_prop = 0; - yout = fft(xin); - - yout = ((yout).*exp(obj.linstep*dz/2)); + % Apply initial half-step linear operator + yout = fft(xin) .* exp(obj.linstep * dz/2); + % Loop until full fiber length is reached while true - + % Inverse FFT to time domain for nonlinear phase shift yout = ifft(yout); - Leff = dz; - + % Nonlinear phase rotation per segment power = abs(yout).^2; - Hnl = exp( -1j*obj.gamma*power*Leff); - yout = yout .* Hnl; + Hnl = exp(-1j * obj.gamma * power * dz); + yout = yout .* Hnl; + % Accumulate propagation distance z_prop = z_prop + dz; - maxPow = obj.gamma*max(abs(yout).^2); - Leff = obj.dphimax/maxPow; - - dz_new = Leff; + % Compute adaptive step for next interval + maxPow = obj.gamma * max(abs(yout).^2); + dz_new = obj.dphimax / maxPow; + % If remaining length shorter than new step, finish loop if z_prop + dz_new > obj.fiber_length dz_new = obj.fiber_length - z_prop; - break + break; end - yout = fft(yout); - - yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2))); - - dz = dz_new; - + % Half-step linear operator bridging segments + yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2))); + dz = dz_new; end - yout = fft(yout); - - yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2))); - + % Final propagation segment: combine half-steps and nonlinear + yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2))); yout = ifft(yout); - Leff = dz; - + % Last nonlinear phase shift power = abs(yout).^2; + Hnl = exp(-1j * obj.gamma * power * dz_new); + yout = yout .* Hnl; - Hnl = exp( -1j*obj.gamma*power*Leff); - - yout = yout .* Hnl; - - yout = fft(yout); - - yout = ((yout).*exp(obj.linstep*(dz/2))); - + % Final half-step linear operator to complete SSFM + yout = fft(yout) .* exp(obj.linstep * (dz_new/2)); yout = ifft(yout); - - end - - end end - - - - - - - - - - - - - - - diff --git a/Classes/04_DSP/Sequence Detection/MLSE.m b/Classes/04_DSP/Sequence Detection/MLSE.m index c453e18..e9d99dc 100644 --- a/Classes/04_DSP/Sequence Detection/MLSE.m +++ b/Classes/04_DSP/Sequence Detection/MLSE.m @@ -83,6 +83,14 @@ classdef MLSE < handle % impulse respnse to remove from signal obj.DIR = flip(obj.DIR); %i.e. -0.2676 -0.0478 1.0000 + % % make the combined impulse-response have net gain = 1 + % h = obj.DIR(:); + % h = h / sum(h); + % obj.DIR = h.'; + + % Normalize the Trellis states to =1 RMS + obj.trellis_states = obj.trellis_states ./ rms(obj.trellis_states); + % seems to be the only way to use combvec for a flexible amount % of vectors. 'combs' contains all trellis states pre_comb_mat = repmat(obj.trellis_states,length(obj.DIR)-1,1); @@ -116,6 +124,7 @@ classdef MLSE < handle % first: RMS normalization of input data (rms==1) data_in = data_in ./ rms(data_in); + data_in = data_in - mean(data_in); % then, match amplitude levels of input signal to those of the calculated ideal symbols % i.e. match the rms values of data_in to noise_free_received (rms=1.xx) @@ -125,6 +134,10 @@ classdef MLSE < handle end end + y_clean = conv( data_ref, flip(obj.DIR), "same" ); + sigma2 = var( data_in - y_clean ); + inv2s2 = 1/(2*sigma2); + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% FORWARD PASS (VITERBI -Alpha's) %%%%% @@ -134,7 +147,7 @@ classdef MLSE < handle % first start is evaluated without ISI/ wihout the full Impulse response % so simply use the constellation here - bm = -(data_in(1) - last_sym).^2 ; + bm = -(data_in(1) - last_sym).^2 * inv2s2; pm = pm + bm; [alpha(:,1),pm_survivor_fw_idx(:,1)] = max(pm,[],2); pm = repmat(alpha(:,1).',nStates,1); @@ -143,10 +156,10 @@ classdef MLSE < handle % Forward Recursion (FSM Computation) for n = 2:length(data_in) - bm = -(data_in(n) - noise_free_received).^2 ; + bm = -(data_in(n) - noise_free_received).^2 * inv2s2; pm = pm + bm; - [alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state - pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state) + [alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state + pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state) bm_fw(:,:,n) = bm; @@ -177,7 +190,7 @@ classdef MLSE < handle % predecessor for h = length(data_in)-1:-1:1 - bm = -(data_in(h+1) - noise_free_received).^2 ; + bm = -(data_in(h+1) - noise_free_received).^2 * inv2s2; pm = pm + bm.'; [beta(:,h),pm_survivor_bw_idx(:,h)] = max(pm,[],2); % choose lowest path metric as new state pm = repmat(beta(:,h).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state) @@ -214,10 +227,22 @@ classdef MLSE < handle %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% FORWARD PASS PAM2,4,8 %%%%% - nml_LLP = LLP - max(LLP); - expLLP = exp(nml_LLP); %subtract highst value for better numerical stability, LLP's are not always close to zero - state_prob = expLLP ./ sum(expLLP); + nml_LLP = LLP - max(LLP); %subtract highest value for better numerical stability, LLP's are not always close to zero + expLLP = exp(nml_LLP); + state_prob = expLLP ./ sum(expLLP); % sums to one (or numerically close to one) + % compute symbol‐posteriors from LLP in the log‐domain: + amax = max(LLP,[],1); + logZ = amax + log(sum(exp(LLP - amax), 1)); + logPstate = LLP - logZ; % still in log‐domain + state_prob = exp(logPstate); % exact, sums to 1 + + % figure + % hold on; + % for i = 1:obj.M + % scatter(1:length(expLLP),expLLP(i,:),1,'.'); + % end + % scatter(1:length(expLLP),max(expLLP(:,:)),3,'.'); if obj.M == 6 @@ -305,8 +330,8 @@ classdef MLSE < handle % Number of symbols and bits per symbol num_bits = log2(length(obj.trellis_states)); % 2 bits per symbol - bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).demap(first_sym./rms(first_sym)); - + % bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).demap(first_sym./rms(first_sym)); + bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).showBitMapping; % Initialize LLR storage LLR_maxlogmap = zeros(length(data_in),num_bits); LLR_exact = zeros(length(data_in),num_bits); @@ -343,8 +368,8 @@ classdef MLSE < handle llr1 = LLR_exact(idx_bit_0,k); % Calculate mutual information for bit position k - I0 = mean(log2(1 + exp(llr0(100:end-100)))); % exp(--LLR) = exp(positive) > 1 - I1 = mean(log2(1 + exp(-llr1(100:end-100)))); % exp(-+LLR) = exp(negative) < 1 + I0 = mean(log2(1 + exp(llr0))); % exp(--LLR) = exp(positive) > 1 + I1 = mean(log2(1 + exp(-llr1))); % exp(-+LLR) = exp(negative) < 1 MI(k) = 1 - 0.5 * (I0 + I1); end @@ -354,8 +379,7 @@ classdef MLSE < handle VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS); - - debug = 0; + debug = 1; if debug %%% DEBUG PLOT LIKELIHOOD RATIOS %%% figure(115);clf @@ -380,6 +404,7 @@ classdef MLSE < handle if debug tx_bits = reshape(tx_bits',[],1); + disp('Start DEBUG MLSE:') % DECIDE based on Viterbi traceback VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS); rx_bits = PAMmapper(obj.M,0,"eth_style",0).demap(VITERBI_ESTIMATION_SYMBOLS'); @@ -417,13 +442,19 @@ classdef MLSE < handle rx_bits = reshape(rx_bits',[],1); [~,~,ber_fw,~] = calc_ber(rx_bits,tx_bits,"skip_front",100,"skip_end",150,"returnErrorLocation",1); fprintf('FW BER: %.2e \n',ber_fw); - + disp('Stop DEBUG MLSE:') + disp('') end end - end - methods (Access=private) + function s = logsumexp(a,dim) + % returns log(sum(exp(a),dim)) safely + amax = max(a,[],dim); + s = amax + log(sum(exp(a - amax), dim)); + end + end + end diff --git a/Classes/04_DSP/Sequence Detection/MLSE_new.m b/Classes/04_DSP/Sequence Detection/MLSE_new.m new file mode 100644 index 0000000..ef7a1e2 --- /dev/null +++ b/Classes/04_DSP/Sequence Detection/MLSE_new.m @@ -0,0 +1,152 @@ +classdef MLSE_new < handle + %MLSE: BCJR‐based soft‐output for PAM‐M sequence estimation & GMI + + properties + M % PAM order (e.g. 4) + DIR % channel impulse response + trellis_states % PAM constellation levels (e.g. [-3 -1 1 3]) + end + + methods + function obj = MLSE_new(opts) + arguments + opts.M double = 4; + opts.DIR double = 1; + opts.trellis_states double = [-3 -1 1 3]; + end + obj.M = opts.M; + obj.DIR = opts.DIR; + obj.trellis_states = opts.trellis_states; + end + + function [hd_out, LLR, NGMI] = process(obj, signalclass,ref_symbolclass) + % rx, tx: column vectors of equalized and reference symbols + data_in = signalclass.signal; + shape_in = size(data_in); + data_ref = ref_symbolclass.signal; + + [data_out_hd,LLR,GMI] = obj.bcjr_soft(data_in,data_ref); + try + data_out_hd = reshape(data_out_hd,shape_in(1),shape_in(2)); + catch + warning('output reshaping failed after MLSE'); + end + + signalclass_hd = signalclass; + signalclass_hd.signal = data_out_hd; + + + + + [hd_out, LLR, NGMI] = obj.bcjr_soft(rx, tx); + end + end + + methods (Access=private) + function [hd_sym, LLR, NGMI] = bcjr_soft(obj, y, x) + %--- build trellis states & branch outputs --- + DIR = flip(obj.DIR(:)); + S = combvec(obj.trellis_states, obj.trellis_states)'; + prev = S(:,1); cur = S(:,2); + branch_out = prev*DIR(1) + cur*DIR(2); % for 2‐tap + + N = numel(y); + M = obj.M; + m = log2(M); + + %--- forward/backward metrics (max‐log) --- + nStates = numel(obj.trellis_states); + alpha = -inf(nStates,N); + beta = -inf(nStates,N); + bm_fw = zeros(nStates,nStates,N); + + % branch metrics + sigma2 = var(y - x); + inv2sigma2 = 1/(2*sigma2); + for n=1:N + bm = -((y(n)-branch_out).^2)* inv2sigma2; + bm = reshape(bm, nStates, nStates); + bm_fw(:,:,n) = bm; + end + % forward + alpha(:,1) = max(bm_fw(:,:,1),[],2); + for n=2:N + mat = alpha(:,n-1) + bm_fw(:,:,n); + alpha(:,n) = max(mat,[],2); + end + % backward + beta(:,N) = 0; + for n=N-1:-1:1 + mat = beta(:,n+1).' + bm_fw(:,:,n+1); + beta(:,n) = max(mat,[],2); + end + + % Precompute the “zero‐th” forward metric + alpha0 = zeros(nStates,1); + + LLP = -inf(nStates,nStates,N); + for n = 1:N + % Select the correct previous alpha column + if n == 1 + a_prev = alpha0; + else + a_prev = alpha(:,n-1); + end + + % Combine α, branch metric, and β + mat = a_prev + bm_fw(:,:,n) + beta(:,n).'; + LLP(:,:,n) = mat; + end + + %--- compute LLRs symbol‐wise via log‐sum‐exp over branches --- + levels = obj.trellis_states; + bit_map = PAMmapper(M,0).demap(levels'); + LLR = zeros(N,m); + for n=1:N + % sum branch posteriors per symbol + llp_n = LLP(:,:,n); + logZ = logsumexp(llp_n(:)); + post = exp(llp_n - logZ); + % aggregate per symbol index + Psym = zeros(M,1); + for i=1:nStates + for j=1:nStates + % branch (i->j) emits symbol 'cur(j)' + idx = find(levels==cur(j)); + Psym(idx) = Psym(idx) + post(i,j); + end + end + % bit‐LLR from symbol posterior + for k=1:m + idx1 = bit_map(:,k)==1; + idx0 = ~idx1; + P1 = sum(Psym(idx1)); + P0 = sum(Psym(idx0)); + LLR(n,k) = log(P1/P0); + end + end + + %--- hard decisions --- + [~,symIdx] = max(LLR,[],2); + hd_sym = levels(symIdx); + + %--- GMI via Alvarado Eq.(30) --- + tx_bits = PAMmapper(M,0).demap(x); + MI = zeros(1,m); + for k=1:m + r0 = LLR(tx_bits(:,k)==0,k); + r1 = LLR(tx_bits(:,k)==1,k); + I0 = mean(log2(1+exp(-r0))); + I1 = mean(log2(1+exp(+r1))); + MI(k) = 1 - 0.5*(I0+I1); + end + GMI = sum(MI); + NGMI = GMI/m; + end + end +end + +function s = logsumexp(a) + m = max(a(:)); + s = m + log(sum(exp(a-m), 'all')); +end diff --git a/Classes/DataBaseHandler/DBHandler.m b/Classes/DataBaseHandler/DBHandler.m index 7e2105a..d21d3be 100644 --- a/Classes/DataBaseHandler/DBHandler.m +++ b/Classes/DataBaseHandler/DBHandler.m @@ -44,8 +44,6 @@ classdef DBHandler < handle % datasource = "jdbc:mysql://134.245.243.254:3306/labor"; - - obj.conn = database( ... string(obj.dataBase), ... % Database name "silas", ... % Username @@ -645,7 +643,7 @@ classdef DBHandler < handle cleanedTable.(varNames{i}) = numCol; else % Clean double-quoted SQL literals (e.g., ""no_db"") - cleanedTable.(varNames{i}) = strrep(string(col), '""', '"'); + cleanedTable.(varNames{i}) = strrep(string(col), '"', ''); end end end diff --git a/Functions/EQ_structures/dsp_runid.m b/Functions/EQ_structures/dsp_runid.m index 50dfc46..a698314 100644 --- a/Functions/EQ_structures/dsp_runid.m +++ b/Functions/EQ_structures/dsp_runid.m @@ -26,13 +26,15 @@ try % Initialize database connection database = DBHandler("dataBase", [options.dataBase], "type", options.database_type ); - % 2. Check if an equalizer configuration with the same hash exists - queryStr = sprintf('SELECT COUNT(DISTINCT eq_id) AS unique_eq_count, COUNT(*) AS entries_for_run FROM `Results` WHERE run_id = %d', run_id); - existing_results = database.fetch(queryStr); - - if existing_results.unique_eq_count >= 6 - if (existing_results.entries_for_run / existing_results.unique_eq_count) > 8 - return + if 0 + % 2. Check if an equalizer configuration with the same hash exists + queryStr = sprintf('SELECT COUNT(DISTINCT eq_id) AS unique_eq_count, COUNT(*) AS entries_for_run FROM `Results` WHERE run_id = %d', run_id); + existing_results = database.fetch(queryStr); + + if existing_results.unique_eq_count >= 6 + if (existing_results.entries_for_run / existing_results.unique_eq_count) > 5 + return + end end end @@ -94,8 +96,8 @@ try adaption= 1; use_dd_mode = 1; - use_ffe = 1; - use_dfe = 1; + use_ffe = 0; + use_dfe = 0; use_vnle_mlse = 1; use_dbtgt = 1; use_dbenc = 1; @@ -139,6 +141,10 @@ try % Preprocess signal Scpe_sig = preprocessSignal(Scpe_cell{r}, Symbols, fsym); + % Scpe_sig.spectrum("fignum",2223,"normalizeTo0dB",1,"displayname",'Rx'); + % Scpe_sig.spectrum("fignum",22233,"normalizeTo0dB",0,"displayname",'Rx'); + % Scpe_sig.eye(fsym,M,"fignum",1024); + if duob_mode ~= db_mode.db_encoded if use_ffe @@ -146,19 +152,19 @@ try ffe_order = [50, 0, 0]; eq_dfe = EQ("Ne",ffe_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",0,"ideal_dfe",0); - dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,... + ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,... "precode_mode",duob_mode,... 'showAnalysis',0,... "postFFE",[],... "eth_style_symbol_mapping",0); - output.ffe_package{r} = dfe_results; + output.ffe_package{r} = ffe_results; - dfe_results.metrics.print; - dfe_results.config.equalizer_structure = "ffe"; + ffe_results.metrics.print; + ffe_results.config.equalizer_structure = "ffe"; if options.append_to_db - database.addProcessingResult(run_id, dfe_results.metrics, dfe_results.config); + database.addProcessingResult(run_id, ffe_results.metrics, ffe_results.config); end end diff --git a/Functions/EQ_structures/duobinary_target.m b/Functions/EQ_structures/duobinary_target.m index 22257d7..687d6ca 100644 --- a/Functions/EQ_structures/duobinary_target.m +++ b/Functions/EQ_structures/duobinary_target.m @@ -110,12 +110,14 @@ if options.showAnalysis rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum"); - Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",250,"displayname","DB encoded reference"); + Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",10,"displayname","DB encoded reference"); showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization'); - fprintf('DB tgt BER: %.2e \n',ber); + fprintf('DB tgt BER: %.2e \n',ber_db); + figure(341); clf; + showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341); end diff --git a/Functions/EQ_structures/vnle_postfilter_mlse.m b/Functions/EQ_structures/vnle_postfilter_mlse.m index 6610221..2ad8ea2 100644 --- a/Functions/EQ_structures/vnle_postfilter_mlse.m +++ b/Functions/EQ_structures/vnle_postfilter_mlse.m @@ -43,6 +43,7 @@ end % Hard decision on VNLE output eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd); +eq_signal_hd.spectrum("displayname",'after full response FFE','fignum',2025,'normalizeTo0dB',1); % Process through postfilter and MLSE [mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); @@ -216,10 +217,24 @@ end function displayAnalysis(eq_noise, whitened_noise, eq_signal_sd, rx_signal, eq_, pf_, mlse_, tx_symbols, M, postFFE) + +% rx_signal.spectrum("displayname",'Rx Signal','fignum',100,'normalizeTo0dB',1); + % Display analysis plots and metrics figure(336); +hold on; +eq_signal_sd.spectrum("displayname",'Equalized Signal','fignum',336,'normalizeTo0dB',0); +eq_noise.spectrum("displayname",'Equalized Signal','fignum',336,'normalizeTo0dB',0); showEQNoisePSD(eq_noise, "fignum", 336, "displayname", 'Residual Noise after VNLE', 'postfilter_taps', pf_.coefficients); +for t = 1:4 + pf_.ncoeff = t; + [~,~] = pf_.process(eq_signal_sd, eq_noise); + showEQNoisePSD(eq_noise, "fignum", 3388, "displayname", 'Residual Noise after VNLE', 'postfilter_taps', pf_.coefficients); +end + + +tx_symbols.spectrum("displayname",'Equalized Signal','fignum',1234,'normalizeTo0dB',1); if ~isempty(postFFE) showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338); end @@ -234,7 +249,7 @@ showLevelHistogram(eq_signal_sd, tx_symbols, "fignum", 341); warning off showLevelScatter(eq_signal_sd, tx_symbols, "fignum", 400); -showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 401); +% showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 401); drawnow; warning on diff --git a/Functions/EQ_visuals/showEQNoisePSD.m b/Functions/EQ_visuals/showEQNoisePSD.m index a10fb15..64f002d 100644 --- a/Functions/EQ_visuals/showEQNoisePSD.m +++ b/Functions/EQ_visuals/showEQNoisePSD.m @@ -22,7 +22,7 @@ end % Ensure the figure is ready before calling spectrum eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color); - title('Noise of soft decision signal (not MLSE)') + title('EEN') if ~isnan(options.postfilter_taps) % Hold on to the figure for further plotting @@ -43,5 +43,6 @@ end end xlim([-eq_noise.fs/2* 1e-9 eq_noise.fs/2* 1e-9]); + ylim([-15, 0]); end diff --git a/Functions/EQ_visuals/showEQfilter.m b/Functions/EQ_visuals/showEQfilter.m index 3e0f4b0..4b0f403 100644 --- a/Functions/EQ_visuals/showEQfilter.m +++ b/Functions/EQ_visuals/showEQfilter.m @@ -20,6 +20,12 @@ end f = f(1:half_nfft); H = H(1:half_nfft); + H_mag = abs(H); + H_norm = H_mag ./ max(H_mag); + + H_db = 20*log10(H_norm); + H_db = H_db - min(H_db); + % Determine the figure number to use or create a new figure if isnan(options.fignum) fig = figure; % Create a new figure and get its handle @@ -30,7 +36,7 @@ end % Magnitude response (in dB) subplot(2,1,1); hold on - plot(f.*1e-9, 20*log10(abs(1./H)),'DisplayName',options.displayname); + plot(f.*1e-9, H_db,'DisplayName',options.displayname); title('(Inverted) Magnitude Response of FFE Filter'); xlabel('Frequency (GHz)'); ylabel('Magnitude (dB)'); diff --git a/Functions/EQ_visuals/showLevelHistogram.m b/Functions/EQ_visuals/showLevelHistogram.m index 0f31bdc..ef88791 100644 --- a/Functions/EQ_visuals/showLevelHistogram.m +++ b/Functions/EQ_visuals/showLevelHistogram.m @@ -27,6 +27,7 @@ end received_sd = NaN(numel(constellation),length(ref_symbols)); lvlcol = cbrewer2('Paired',numel(constellation)*2); lvlcol = lvlcol(2:2:end,:); + lvlcol = linspecer(numel(constellation)); % lvlcol = cbrewer2('Set1',numel(constellation)); for lvl = 1:numel(constellation) %Separate the equalized signal into the diff --git a/Functions/Job_Processing/loadAndSyncSignalDataFromDb.m b/Functions/Job_Processing/loadAndSyncSignalDataFromDb.m index db2812c..1b76fd4 100644 --- a/Functions/Job_Processing/loadAndSyncSignalDataFromDb.m +++ b/Functions/Job_Processing/loadAndSyncSignalDataFromDb.m @@ -1,7 +1,7 @@ function [Bits, Symbols, Scpe_cell, found_sync] = loadAndSyncSignalDataFromDb(dataTable, options) % LOADSIGNALDATA Loads and synchronizes signal data from storage % -% Inputs: +% Inputs:d % dataTable - Table with file paths and configuration % options - Struct with storage_path and max_occurences % diff --git a/Functions/Job_Processing/preprocessSignal.m b/Functions/Job_Processing/preprocessSignal.m index 4828bba..8725ed3 100644 --- a/Functions/Job_Processing/preprocessSignal.m +++ b/Functions/Job_Processing/preprocessSignal.m @@ -16,9 +16,9 @@ Scpe_sig = Scpe_sig.resample("fs_out", 2*fsym); [Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0); % Apply Gaussian filter -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 = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ... +% "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ... +% "active", true).process(Scpe_sig); % Remove DC offset Scpe_sig = Scpe_sig - mean(Scpe_sig.signal); diff --git a/Functions/Job_Processing/submitJobs.m b/Functions/Job_Processing/submitJobs.m index d667cc8..321032a 100644 --- a/Functions/Job_Processing/submitJobs.m +++ b/Functions/Job_Processing/submitJobs.m @@ -120,7 +120,7 @@ switch submit_mode % fetchNext has already set Read=true on the errored future. % Find the one Read==true that we have _not_ yet consumed. readMask = arrayfun(@(f) f.Read, futures); - idxErr = find(readMask & ~consumedIdx, 1); + idxErr = find(readMask & ~consumedIdx', 1); consumedIdx(idxErr) = true; % Pull the _real_ exception out of the future object diff --git a/Functions/Metrics/calc_air.m b/Functions/Metrics/calc_air.m index c42ab2f..2b10827 100644 --- a/Functions/Metrics/calc_air.m +++ b/Functions/Metrics/calc_air.m @@ -1,5 +1,5 @@ function [ach_inf_rate] = calc_air(test_signal,reference_signal,options) -% Calculation of AIR acc. to J. Kozesnik, „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5. +% „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5. % Implementation is not accessible, I mailed TUM to get the code... arguments(Input) @@ -26,7 +26,7 @@ end % TRIM [test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end); -% CALC EVM +% CALC AIR %%% new implementation of AIR constellation = unique(reference_signal); reference_idx = arrayfun(@(x) find(constellation == x, 1), reference_signal); diff --git a/Functions/Metrics/calc_gmi_bitwise.m b/Functions/Metrics/calc_gmi_bitwise.m new file mode 100644 index 0000000..1ce8847 --- /dev/null +++ b/Functions/Metrics/calc_gmi_bitwise.m @@ -0,0 +1,94 @@ +function [GMI,NGMI] = calc_gmi_bitwise(test_signal,reference_signal,options) +% https://cioffi-group.stanford.edu/doc/book/AppendixG.pdf + +arguments(Input) + test_signal; + reference_signal; + options.skip_front = 0; + options.skip_end = 0; + options.returnErrorLocation = 0; +end + +options.skip_end = abs(options.skip_end); +options.skip_front = abs(options.skip_front); + +assert((options.skip_end+options.skip_front); +% % Retrieve current size of the active (or any) figure: +% [wCur, hCur] = getFigureSize(); +% % Set the other figure H to match that size, preserving its position: +% posH = get(H, 'Position'); % [left, bottom, width, height] +% newPos = [posH(1), posH(2), wCur, hCur]; +% set(H, 'Position', newPos); +% +% Note: +% - Position vector is given as [left, bottom, width, height] in pixels. +% - If you want to specify a custom size directly, you can replace wCur/hCur +% with desired values. + +function [width, height] = getFigureSize() + % Ensure a figure is available + fig = gcf; + % Get the position vector: [left, bottom, width, height] + pos = get(fig, 'Position'); + % Extract width and height + width = pos(3); + height = pos(4); +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_dispersion.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_dispersion.m new file mode 100644 index 0000000..447daac --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_dispersion.m @@ -0,0 +1,111 @@ + +database_type = 'mysql'; +dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; +db = DBHandler("dataBase", [dataBase], "type", database_type); + +fp = QueryFilter(); +% fp.where('Runs', 'run_id','EQUALS', 987); +M = 6; +fp.where('Runs', 'pam_level','EQUALS', M); +baudrate = 162e9; +fp.where('Runs', 'symbolrate','EQUALS', baudrate); +% fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'is_mpi','EQUALS', 0); +% fp.where('Runs', 'interference_path_length','EQUALS', 1000); +% fp.where('Runs', 'loop_id','GREATER_THAN', 11); +% fp.where('Runs', 'sir','EQUALS',18); +% fp.where('Runs', 'wavelength','EQUALS', 1310); +fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis +fp.where('Runs', 'rop_attenuation','EQUALS', 0); + + +fields = db.getTableFieldNames('power_state_info'); +fields = [fields; db.getTableFieldNames('dashboard_ungrouped')]; +[dataTable,~] = db.queryDB(fp, fields); + +eqstructures = unique(dataTable.equalizer_structure); +fiber_len = unique(dataTable.fiber_length); +cnt = 1; +f=figure(); +clf +hold on + +markers = {'o', 's', 'd', '^', 'v', '>', '<', 'p', 'h'}; % Define marker styles + +for fl = 1:numel(fiber_len) + + fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:); + + for eqs = [equalizer_structure.vnle_pf_mlse] + + eq_choice = equalizer_structure(eqs); + if sum(eqstructures == eq_choice)~=1 + disp(eq_choice) + continue + end + + eq_filtered = fl_filtered(fl_filtered.equalizer_structure == eq_choice,:); + + dispersion_sorted = sortrows(eq_filtered, {'accumulated_dispersion'}, 'ascend'); + % dispersion_sorted = dispersion_sorted(dispersion_sorted.wavelength <= 1320,:); + % dispersion_sorted = dispersion_sorted(dispersion_sorted.BER < 0.02,:); + % pull out your vectors + accumulated_dispersion = dispersion_sorted.accumulated_dispersion; + ber = dispersion_sorted.BER; + % ber = dispersion_sorted.BER_precoded; + run_ids = dispersion_sorted.run_id; % <-- this is what we want in the datatip + len = dispersion_sorted.fiber_length; + lambda = dispersion_sorted.wavelength; + cols = cbrewer2('Set1',8); + % cols = flip(cbrewer2('RdYlGn',14)); + cols = linspecer(8); + + ber_wavelen_grouped = groupsummary( ... + dispersion_sorted, ... % input table + "wavelength", ... % grouping variable + "min", ... % which summary statistic + "BER_precoded"); + + dname = sprintf('%s; %d km',eq_choice, fiber_len(fl)); + h1 = plot(ber_wavelen_grouped.wavelength, ber_wavelen_grouped.min_BER_precoded,'LineWidth', 2, 'MarkerSize', 5,'Marker',markers(cnt),'LineStyle','-','Color',cols(cnt,:),'MarkerEdgeColor','auto','MarkerFaceColor','white','DisplayName',dname); + + + plotallscatters=0; + if plotallscatters + % plot the two curves and capture their Line handles + dname = sprintf('%s; %d km',eq_choice, fiber_len(fl)); + h1 = plot(lambda, ber,'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','none','Color',cols(cnt,:),'MarkerFaceColor',cols(cnt,:),'DisplayName',dname); + % —————— Add run_id as a datatip row —————— + % For each line, tell the datatip template where to find the run_id: + h1.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('run\_id', run_ids); + h1.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('len', len); + h1.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('lambda', lambda); + end + + xticks(sort(unique(lambda))); + xticklabels(sort(unique(lambda))); + + grid on; + + % Labels, scales, legend, etc. + xlabel('Wavelength in nm','FontSize',12); + ylabel('BER','FontSize',12); + tit = sprintf('%d GBd PAM-%d',baudrate.*1e-9, M); + title(tit,'FontSize',14,'FontWeight','bold'); + set(gca, 'XScale','linear','YScale','log','FontSize',11); + legend + + xlim([min(lambda)-2, max(lambda)+2]); + ylim([1e-4, 0.2]); + + cnt = cnt+1; + end +end + +yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off'); +posH = get(f, 'Position'); % [left, bottom, width, height] +newPos = [posH(1), posH(2), 750, 300]; +set(f, 'Position', newPos); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate.m new file mode 100644 index 0000000..7039713 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate.m @@ -0,0 +1,86 @@ + +database_type = 'mysql'; +dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; +db = DBHandler("dataBase", [dataBase], "type", database_type); + +fp = QueryFilter(); +% fp.where('Runs', 'run_id','EQUALS', 987); +M = 8; +fp.where('Runs', 'pam_level','EQUALS', M); +% fp.where('Runs', 'bitrate','LESS_THAN', 310e9); +fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'is_mpi','EQUALS', 0); +% fp.where('Runs', 'interference_path_length','EQUALS', 1000); +% fp.where('Runs', 'loop_id','GREATER_THAN', 11); +% fp.where('Runs', 'sir','EQUALS',18); +fp.where('Runs', 'wavelength','EQUALS', 1310); +% fp.where('Runs', 'db_mode','EQUALS', 1); +fp.where('Runs', 'rop_attenuation','EQUALS', 0); + +% [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard')); + +eqstructures = unique(dataTable.equalizer_structure); +% Create the figure +figure(10); +hold on +for pre_emph = [1] + + dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); + + for eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse , equalizer_structure.vnle_db_mlse] + + eq_choice = equalizer_structure(eqs); + + if sum(eqstructures == eq_choice)~=1 + disp(eq_choice) + continue + end + + eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); + + symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend'); + [~, ia] = unique(symbolrate_sorted.symbolrate, 'first'); + symbolrate_sorted = symbolrate_sorted(ia, :); + + % Example data (replace these with your real vectors) + symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud + bitrate = symbolrate * floor(log2(M)*10)/10; + ber = symbolrate_sorted.min_BER; % BER + ber_precoded = symbolrate_sorted.min_BER_precoded; % BER + cols = cbrewer2('Paired',12); + cols = [0.4660 0.6740 0.1880 ; 0.9290 0.6940 0.1250 ; 0 0.4470 0.7410; 0.4940 0.1840 0.5560]; %VNLE; PF ; DFE ; DB tgt + + dname = [char(eq_choice)]; + if pre_emph + dname = [dname,' with pre-emph.']; + else + dname = [dname,' w/o pre-emph.']; + end + + plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname]); + plot(bitrate, ber_precoded, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','square','LineStyle',':','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname,'; pre-coded']); + grid on; + + % Axis labels and title + xlabel('Baud Rate GBaud', 'FontSize', 12); + ylabel('BER', 'FontSize', 12); + title('BER vs. Baud Rate', 'FontSize', 14, 'FontWeight', 'bold'); + + % Improve tick formatting + set(gca, 'XScale', 'linear', ... + 'YScale', 'log', ... + 'TickLabelInterpreter', 'latex', ... + 'FontSize', 11); + legend + + xticks(bitrate); + + % Optional: tighten axis limits + xlim([min(bitrate), max(bitrate)]); + ylim([5e-5, 0.5]); + + end + +end + +yline([4.85e-3, 2e-2],'LineWidth',1,'LineStyle','--','HandleVisibility','off'); beautifyBERplot(); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate_only_best_configs.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate_only_best_configs.m new file mode 100644 index 0000000..58ef10d --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/ber_vs_rate_only_best_configs.m @@ -0,0 +1,117 @@ + +database_type = 'mysql'; +dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; +db = DBHandler("dataBase", [dataBase], "type", database_type); + +fp = QueryFilter(); +% fp.where('Runs', 'run_id','EQUALS', 987); +M = 8; +fp.where('Runs', 'pam_level','EQUALS', M); +% fp.where('Runs', 'bitrate','LESS_THAN', 310e9); +fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'is_mpi','EQUALS', 0); +% fp.where('Runs', 'interference_path_length','EQUALS', 1000); +% fp.where('Runs', 'loop_id','GREATER_THAN', 11); +% fp.where('Runs', 'sir','EQUALS',18); +fp.where('Runs', 'wavelength','EQUALS', 1310); +% fp.where('Runs', 'db_mode','EQUALS', 1); +fp.where('Runs', 'rop_attenuation','EQUALS', 0); + +[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard')); + +eqstructures = unique(dataTable.equalizer_structure); + +% Create the figure +f=figure(4); +hold on + +eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse , equalizer_structure.vnle_db_mlse]; +cols = [0.4660 0.6740 0.1880 ; 0.9290 0.6940 0.1250 ; 0 0.4470 0.7410; 0.4940 0.1840 0.5560]; %VNLE; PF ; DFE ; DB tgt + +eq_choice = equalizer_structure.vnle; +pre_emph = 1; +dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); +eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); +symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend'); +[~, ia] = unique(symbolrate_sorted.symbolrate, 'first'); +symbolrate_sorted = symbolrate_sorted(ia, :); +symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud +bitrate = symbolrate * floor(log2(M)*10)/10; +ber = symbolrate_sorted.min_BER; % BER +ber_precoded = symbolrate_sorted.min_BER_precoded; % BER +plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','v','LineStyle',':','Color',cols(1,:),'MarkerEdgeColor',cols(1,:),'MarkerFaceColor',cols(1,:),'DisplayName',['Tx pre-emphasis + VNLE']); + +eq_choice = equalizer_structure.vnle_pf_mlse; +pre_emph = 0; +dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); +eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); +symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend'); +[~, ia] = unique(symbolrate_sorted.symbolrate, 'first'); +symbolrate_sorted = symbolrate_sorted(ia, :); +symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud +bitrate = symbolrate * floor(log2(M)*10)/10; +ber = symbolrate_sorted.min_BER; % BER +ber_precoded = symbolrate_sorted.min_BER_precoded; % BER +plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','diamond','LineStyle',':','Color',cols(2,:),'MarkerEdgeColor',cols(2,:),'MarkerFaceColor',cols(2,:),'DisplayName',['VNLE+2-tap post-filter+MLSE']); + +% eq_choice = equalizer_structure.dfe; +% pre_emph = 1; +% dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); +% eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); +% symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend'); +% [~, ia] = unique(symbolrate_sorted.symbolrate, 'first'); +% symbolrate_sorted = symbolrate_sorted(ia, :); +% symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud +% bitrate = symbolrate * floor(log2(M)*10)/10; +% ber = symbolrate_sorted.min_BER; % BER +% ber_precoded = symbolrate_sorted.min_BER_precoded; % BER +% plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols(3,:),'MarkerEdgeColor',cols(3,:),'MarkerFaceColor',cols(3,:),'DisplayName',[char(eq_choice)]); + +eq_choice = equalizer_structure.vnle_db_mlse; +pre_emph = 0; +dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); +eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); +symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend'); +[~, ia] = unique(symbolrate_sorted.symbolrate, 'first'); +symbolrate_sorted = symbolrate_sorted(ia, :); +symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud +bitrate = symbolrate * floor(log2(M)*10)/10; +ber = symbolrate_sorted.min_BER; % BER +ber_precoded = symbolrate_sorted.min_BER_precoded; % BER +plot(bitrate, ber_precoded, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','square','LineStyle',':','Color',cols(4,:),'MarkerEdgeColor',cols(4,:),'MarkerFaceColor',cols(4,:),'DisplayName',['DB precoding + DB tgt. + MLSE']); + + +% Axis labels and title with Arial font +xlabel('Gross bitrate [Gb/s]', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none'); +ylabel('BER', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none'); +title('', 'FontSize', 14, 'FontWeight', 'bold', 'FontName', 'Arial', 'Interpreter', 'none'); + +% Improve tick formatting +set(gca, 'XScale', 'linear', ... + 'YScale', 'log', ... + 'TickLabelInterpreter', 'none', ... + 'FontSize', 11, ... + 'FontName', 'Arial'); + +% Legend with Arial font +% legend('FontName', 'Arial', 'Interpreter', 'none','Location','best'); + +xticks(bitrate); + +% Optional: tighten axis limits +xlim([min(bitrate), max(bitrate)]); +ylim([5e-4, 0.05]); + +yline([3.8e-3], 'LineWidth', 2, 'LineStyle', '--', ... + 'HandleVisibility', 'off', 'LabelHorizontalAlignment', 'left'); + +posH = get(f, 'Position'); % [left, bottom, width, height] +newPos = [posH(1), posH(2), 350, 200]; +set(f, 'Position', newPos); + +annotation(f,'textbox',... + [0.398095238095238 0.273381294964029 0.491428571428572 0.140287769784173],... + 'String',{'PAM-8; 2 km; 1293 nm'},... + 'LineWidth',0.5,... + 'FitBoxToText','off',... + 'BackgroundColor',[1 1 1]); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/gmi_vs_rate.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/gmi_vs_rate.m new file mode 100644 index 0000000..7f84f62 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/gmi_vs_rate.m @@ -0,0 +1,84 @@ + +database_type = 'mysql'; +dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; +db = DBHandler("dataBase", [dataBase], "type", database_type); + +M = 8; +fp = QueryFilter(); +% fp.where('Runs', 'run_id','EQUALS', 987); +fp.where('Runs', 'pam_level','EQUALS', M); +% fp.where('Runs', 'symbolrate','EQUALS', 165e9); +fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'is_mpi','EQUALS', 0); +% fp.where('Runs', 'interference_path_length','EQUALS', 1000); +% fp.where('Runs', 'loop_id','GREATER_THAN', 11); +% fp.where('Runs', 'sir','EQUALS',18); +fp.where('Runs', 'wavelength','EQUALS', 1310); +% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis +fp.where('Runs', 'rop_attenuation','EQUALS', 0); + +[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard')); + +eqstructures = unique(dataTable.equalizer_structure); + +% Create the figure +figure(18); +hold on + +for pre_emph = [0,1] + + dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:); + + for eqs = [equalizer_structure.vnle] + + eq_choice = equalizer_structure(eqs); + if sum(eqstructures == eq_choice)~=1 + disp(eq_choice) + continue + end + + eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:); + if eqs ==equalizer_structure.vnle_pf_mlse + eq_filtered = eq_filtered(eq_filtered.DIR == "1",:); + end + symbolrate_sorted = sortrows(eq_filtered,{'symbolrate'}, 'ascend'); + + % Example data (replace these with your real vectors) + symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud + bitrate = symbolrate * 2; + gmi = symbolrate_sorted.max_GMI; % BER + snr = symbolrate_sorted.max_SNR; % BER + cols = cbrewer2('Paired',12); + + dname = [char(eq_choice)]; + dname = strrep(dname,'_','+'); + if pre_emph + dname = [dname,'; w/ pre-emph.']; + else + dname = [dname,'; w/o pre-emph.']; + end + + plot(symbolrate, snr, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname]); + grid on; + + % Axis labels and title + xlabel('Bit Rate Gbps', 'FontSize', 12); + ylabel('GMI', 'FontSize', 12); + title('GMI vs. Bit Rate', 'FontSize', 14, 'FontWeight', 'bold'); + + % Improve tick formatting + set(gca, 'XScale', 'linear', ... + 'YScale', 'linear', ... + 'TickLabelInterpreter', 'none', ... + 'FontSize', 11); + legend + + xticks(symbolrate); + + % Optional: tighten axis limits + xlim([min(symbolrate), max(symbolrate)]); + % ylim([log2(M)-1, log2(M)]); + + end + +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/power_vs_wavelength.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/power_vs_wavelength.m new file mode 100644 index 0000000..d018b47 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/power_vs_wavelength.m @@ -0,0 +1,96 @@ + +database_type = 'mysql'; +dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; +db = DBHandler("dataBase", [dataBase], "type", database_type); + +fp = QueryFilter(); +fp.where('power_state_info', 'pam_level','EQUALS', 4); +fp.where('power_state_info', 'db_mode','EQUALS', 1); +% fp.where('power_state_info', 'fiber_length','EQUALS', 1); +fp.where('power_state_info', 'is_mpi','EQUALS', 0); + +fields = db.getTableFieldNames('power_state_info'); +% [dataTable,~] = db.queryDB(fp, fields); + +fiber_len = unique(dataTable.fiber_length); +cnt = 0; + +y_variable = 'power_mzm'; +x_variable = "wavelength"; +f = figure(3); +clf +hold on +for fl = 1:numel(fiber_len) + + + fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:); + [~, ia] = unique(fl_filtered.run_id, 'first'); + fl_filtered = fl_filtered(ia, :); + + fl_filtered_ = groupsummary( ... + fl_filtered, ... % input table + x_variable, ... % grouping variable + "mean", ... % which summary statistic + y_variable); % which column to average + + wavelength_sorted = sortrows(fl_filtered, {'wavelength'}, 'ascend'); + + % pull out your vectors + lambda = wavelength_sorted.wavelength; + power_laser = wavelength_sorted.power_laser; + power_mzm = wavelength_sorted.power_mzm; + power_rop = wavelength_sorted.power_rop; + power_pd = wavelength_sorted.power_pd_in; + voa = wavelength_sorted.voa_atten; + len = wavelength_sorted.fiber_length; + run_ids = wavelength_sorted.run_id; % <-- this is what we want in the datatip + cols = linspecer(8); + + + % plot the two curves and capture their Line handles + % h1 = plot(lambda, power_laser,'LineWidth', 0.5, 'MarkerSize', 4,'Marker','o','LineStyle','none','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName','Laser Output'); + % % —————— Add run_id as a datatip row —————— + % % For each line, tell the datatip template where to find the run_id: + % h1.DataTipTemplate.DataTipRows(end+1) = ... + % dataTipTextRow('run\_id', run_ids); + % h1.DataTipTemplate.DataTipRows(end+1) = ... + % dataTipTextRow('len', run_ids); + % h1.DataTipTemplate.DataTipRows(end+1) = ... + % dataTipTextRow('voaatten', voa); + + % + dname = sprintf('%s; %d km',y_variable, fiber_len(fl)); + h2 = plot(fl_filtered_.(x_variable), fl_filtered_.(['mean_',y_variable]), 'LineWidth', 1, 'MarkerSize', 4,'Marker','o','LineStyle','-','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName',dname); + + h2.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('run\_id', run_ids); + h2.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('len', len); + h2.DataTipTemplate.DataTipRows(end+1) = ... + dataTipTextRow('voaatten', voa); + + grid on; + xticks(sort(unique(lambda))); + xticklabels(sort(unique(lambda))); + + % Labels, scales, legend, etc. + xlabel('Wavelength in nm','FontSize',12); + ylabel('Power in dB','FontSize',12); + title('Power ','FontSize',14,'FontWeight','bold'); + set(gca, 'XScale','linear','YScale','linear','FontSize',11); + legend + + xlim([min(lambda)-2, max(lambda)+2]); + ylim([floor(min(fl_filtered_.(['mean_',y_variable])))-1 12]); + ylim([-12 12]); + + cnt = cnt+1; + + yline(8,'HandleVisibility','off'); + +end + +yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off'); +posH = get(f, 'Position'); % [left, bottom, width, height] +newPos = [posH(1), posH(2), 750, 300]; +set(f, 'Position', newPos); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m index d34ec2c..ad75339 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m @@ -1,6 +1,6 @@ % === SETTINGS === -dsp_options.append_to_db = 1; -dsp_options.max_occurences = 15; +dsp_options.append_to_db = 0; +dsp_options.max_occurences = 1; experiment = "highspeed_2024"; dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files' @@ -41,14 +41,14 @@ end fp = QueryFilter(); % fp.where('Runs', 'run_id','EQUALS', 987); fp.where('Runs', 'pam_level','EQUALS', 4); -% fp.where('Runs', 'bitrate','LESS_THAN', 310e9); -% fp.where('Runs', 'fiber_length','EQUALS', 1); +fp.where('Runs', 'bitrate','EQUALS', 360e9); +fp.where('Runs', 'fiber_length','EQUALS', 2); fp.where('Runs', 'is_mpi','EQUALS', 0); % fp.where('Runs', 'interference_path_length','EQUALS', 1000); % fp.where('Runs', 'loop_id','GREATER_THAN', 11); % fp.where('Runs', 'sir','EQUALS',18); -% fp.where('Runs', 'wavelength','EQUALS', 1310); -% fp.where('Runs', 'db_mode','EQUALS', 1); +fp.where('Runs', 'wavelength','EQUALS', 1310); +fp.where('Runs', 'db_mode','EQUALS', 0); fp.where('Runs', 'rop_attenuation','EQUALS', 0); % fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); @@ -75,7 +75,7 @@ wh.addStorage("dbenc_package"); % === RUN IT === -[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true); +[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true); % wh.getStoValue('ffe_package',0.005); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/simulate_and_dsp.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/simulate_and_dsp.m new file mode 100644 index 0000000..772f110 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/simulate_and_dsp.m @@ -0,0 +1,236 @@ + +precomp_mode = 0; +precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT"; +precomp_fn = "precomp_simulated.mat"; + +% TX +M = 4; +fsym = 72e9; +f_nyquist = fsym/2; +apply_pulsef = 1; +fdac = 256e9; +fadc = 256e9; +% fdac = 2*fsym; +% fadc = 2*fsym; +random_key = 1; + +duob_mode = db_mode.no_db; + +tx_bwl = 0.8.*f_nyquist; +rx_bwl = 0.8.*f_nyquist; + +rcalpha = 0.05; +kover = 16; +vbias_rel = 0.5; +u_pi = 2.9; +vbias = -vbias_rel*u_pi; +laser_wavelength = 1293; +laser_linewidth = 0; + + +% Channel +link_length = 60000; + +% RX +rop = -8; + +% EQ +eq_mode = equalizer_structure.vnle_pf_mlse; +ffe_order=[50,0,0]; +vnle_order=[50,5,5]; +dfe_order = [0 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; + +Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha); + +[Digi_sig,Symbols,Tx_bits] = PAMsource(... + "fsym",fsym,"M",M,"order",18,"useprbs",0,... + "fs_out",fdac,... + "applyclipping",0,"clipfactor",1.5,... + "applypulseform",apply_pulsef,"pulseformer",Pform,... + "randkey",random_key,... + "duobinary_mode",duob_mode).process(); + +if precomp_mode == 1 % measure channel + precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',fdac); + Digi_sig = precomp_est.buildOFDM(); +elseif precomp_mode == 2 % apply precomp + precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs); + Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',-50,'loadPath',precomp_path,'fileName',precomp_fn); +end + +% Symbols.spectrum("displayname",'Tx Symbols','fignum',10,'normalizeTo0dB',1); + +Digi_sig.eye(fsym,M,"fignum",1234567); +%%%%% AWG +%El_sig = M8199B("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"); +El_sig.spectrum("displayname",'Tx Signal','fignum',10,'normalizeTo0dB',0); +%%%%% Low-pass el. components %%%%%% + +El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.gaussian,"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_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.bessel_inp,"active",true).process(Rx_sig); + +% %%%%%% Low-pass Scope %%%%%% +Lp_scpe = Filter('filtdegree',4,"f_cutoff",35e9,"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_sig.spectrum("displayname",'Rx Signal','fignum',10,'normalizeTo0dB',1); +Scpe_sig.eye(fsym,M,"fignum",1973763) + +%%%%% Precompensation Routine %%%%%% +if precomp_mode == 1 + Scpe_sig_resampled = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym); + precomp_est.estimate(Scpe_sig_resampled,"save",false,"savePath",precomp_path,"fileName",precomp_fn); + precomp_est.plot(); + precomp_est.save(); +end + +% Preprocess signal +Scpe_sig = preprocessSignal(Scpe_sig, Symbols, fsym); +Scpe_sig.signal = Scpe_sig.signal(1:2*Symbols.length); +use_ffe = 0; +use_dfe = 0; +use_vnle_mlse = 1; +use_dbtgt = 1; +use_dbenc = 1; + + +if duob_mode ~= db_mode.db_encoded + + if use_ffe + + ffe_order = [50, 0, 0]; + eq_dfe = EQ("Ne",ffe_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",0,"ideal_dfe",0); + + ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,... + "precode_mode",duob_mode,... + 'showAnalysis',1,... + "postFFE",[],... + "eth_style_symbol_mapping",0); + + disp('FFE:') + ffe_results.metrics.print; + + + end + + if use_dfe + + ffe_order = [50, 5, 5]; + eq_dfe = EQ("Ne",ffe_order,"Nb",[2,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",0,"ideal_dfe",0); + + dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,... + "precode_mode",duob_mode,... + 'showAnalysis',0,... + "postFFE",[],... + "eth_style_symbol_mapping",0); + + disp('DFE:') + dfe_results.metrics.print; + + + end + + if use_vnle_mlse + + if 0 + pf_ncoeffs = 1; + eq_ = 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); + pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); + % mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); + mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); + + [ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode,... + 'showAnalysis', 1, ... + "postFFE", [],... + "eth_style_symbol_mapping", 0); + + disp('VNLE:') + ffe_results.metrics.print; + disp('MLSE:') + mlse_results.metrics.print; + end + + pf_ncoeffs = 2; + eq_ = 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); + pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); + % mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); + mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); + + [ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode,... + 'showAnalysis', 1, ... + "postFFE", [],... + "eth_style_symbol_mapping", 0); + + disp('VNLE:') + ffe_results.metrics.print; + disp('MLSE:') + mlse_results.metrics.print; + + + end + + if use_dbtgt + eq_ = 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); + + mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels); + + dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode, ... + 'showAnalysis',1 ,... + "postFFE", []); + + disp('DB:') + dbt_results.metrics.print; + + end +end + +if duob_mode == db_mode.db_encoded + + eq_db_enc = 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); + + mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels); + + db_results = duobinary_signaling(eq_db_enc, mlse_db_enc, M, Scpe_sig, Symbols, Tx_bits, "precode_mode",duob_mode, "showAnalysis",1,"postFFE",[]); + + db_results.metrics.print; +end \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m b/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m index 9902b03..2a8ee51 100644 --- a/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m +++ b/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m @@ -5,7 +5,7 @@ precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active db_precode = 0; db_coding_approach = 0; -fsym = 224e9; +fsym = 160e9; fdac = 256e9; random_key = 0; M = 4; @@ -58,8 +58,7 @@ end rcalpha = 0.05; -Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha); - +Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha); Pamsource = PAMsource(... "fsym",fsym,"M",M,"order",19,"useprbs",1,... @@ -83,7 +82,9 @@ Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',pr Digi_sig = Digi_sig.normalize("mode","rms"); Digi_sig = Digi_sig.resample("fs_out",fdac); + Digi_sig= Digi_sig.normalize("mode","rms"); + Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0); diff --git a/projects/HighSpeedExperiment_2024/bias_evaluation.m b/projects/HighSpeedExperiment_2024/bias_evaluation.m index babd881..3fe8d9d 100644 --- a/projects/HighSpeedExperiment_2024/bias_evaluation.m +++ b/projects/HighSpeedExperiment_2024/bias_evaluation.m @@ -1,5 +1,5 @@ -filename = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\bias_5km\PAMX_5km_20241025_204334_wh.mat"; +filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_5km\PAMX_5km_20241025_204334_wh.mat"; a = load(filename); wh = a.obj; @@ -95,7 +95,7 @@ end -filename = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\bias_testing_and_b2b\PAM4_b2b_bias_sweep_20241023_191202_wh_BB_BIAS_FINAL.mat"; +filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_testing_and_b2b\PAM4_b2b_bias_sweep_20241023_191202_wh_BB_BIAS_FINAL.mat"; a = load(filename); wh = a.obj; diff --git a/projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m b/projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m index a42bad8..9e527cf 100644 --- a/projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m +++ b/projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m @@ -1,12 +1,12 @@ basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\'; -database = DBHandler("pathToDB",[basePath,'silas_labor.db'],"type",'sqlite'); +database = DBHandler("dataBase",[basePath,'silas_labor.db'],"type",'sqlite'); filterParams = database.tables; filterParams.Configurations = struct( ... - 'bitrate', [], ... %[224,336,360,390,420,448] - 'db_mode', [], ... + 'bitrate', [390e9], ... %[224,336,360,390,420,448] + 'db_mode', 1, ... 'fiber_length', 1, ... 'interference_attenuation', [], ... 'interference_path_length', [], ... diff --git a/projects/IMDD_base_system/imdd_model.m b/projects/IMDD_base_system/imdd_model.m index 70b7b29..d400350 100644 --- a/projects/IMDD_base_system/imdd_model.m +++ b/projects/IMDD_base_system/imdd_model.m @@ -1,6 +1,6 @@ function [output] = imdd_model(varargin) -simulation_mode = 0; +simulation_mode = 1; %%% Change folder curFolder = pwd; diff --git a/projects/IMDD_base_system/simulation_bwl.m b/projects/IMDD_base_system/simulation_bwl.m index e1477a7..f47b0aa 100644 --- a/projects/IMDD_base_system/simulation_bwl.m +++ b/projects/IMDD_base_system/simulation_bwl.m @@ -1,33 +1,24 @@ %%% Run parameters % TX M = 4; -fsym = 180e9; +fsym = 112e9; apply_pulsef = 1; fdac = 256e9; fadc = 256e9; -random_key = 1; - -db_precode = 0; -db_encode = 0; +random_key = 2; rcalpha = 0.05; kover = 16; vbias_rel = 0.5; u_pi = 2.9; vbias = -vbias_rel*u_pi; -laser_wavelength = 1310; +laser_wavelength = 1290; laser_linewidth = 0; -tx_bw_nyquist = 0.6; -rx_bw_nyquist = 0.6; % Channel -link_length = 1; - -% RX -rop = -8; - +link_length = 10000; vnle_order1 = 50; vnle_order2 = 3; @@ -49,55 +40,13 @@ 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.no_db; - -Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha); - -db_precode = 0; -db_encode = 0; -duob_mode = db_mode.no_db; -apply_pulsef = 1; -[Digi_sig,Symbols,Tx_bits] = PAMsource(... - "fsym",fsym,"M",M,"order",18,"useprbs",0,... - "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,"duobinary_mode",duob_mode).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 %%%%%% -f_nyquist = fsym/2; -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 = [-10]; +rop = [-8]; +bwl = [0.5:0.1:1.5]; +fsym = [128:16:170].*1e9; ber_vnle = []; ber_mlse = []; ber_viterbi = []; @@ -107,71 +56,121 @@ gmi_vnle = []; gmi_mlse = []; gmi_mlse_db = []; -for r = 1:length(rop) +for r = 1:length(fsym) + Pform = Pulseformer("fsym",fsym(r),"fdac",4*fsym(r),"pulse","rc","pulselength",16,"alpha",rcalpha); + + db_precode = 0; + db_encode = 0; + duob_mode = db_mode.no_db; + apply_pulsef = 1; + + [Digi_sig,Symbols,Tx_bits] = PAMsource(... + "fsym",fsym(r),"M",M,"order",18,"useprbs",0,... + "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,"duobinary_mode",duob_mode).process(); + + % Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',0); + + + %%%%% AWG + % El_sig = M8199A("kover",kover).process(Digi_sig); + El_sig = AWG("fdac",fdac,"f_cutoff",fsym(r),"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 %%%%%% + % f_nyquist = fsym/2; + % tx_bwl = tx_bw_nyquist.*f_nyquist; + tx_bwl = 50e9; + 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(r)).process(Opt_sig); + 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_bwl = rx_bw_nyquist.*f_nyquist; + rx_bwl = 50e9; 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); + "adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',0,'H_lpf',Lp_scpe).process(Rx_sig); - Scpe_sig_resampled = Scpe_sig.resample("fs_out",2*fsym); - - [~, Scpe_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1); + Scpe_sig_resampled = Scpe_sig.resample("fs_out",2*fsym(r)); + % Scpe_sig_resampled.signal = Scpe_sig_resampled.signal(1:2*length(Symbols)); + [~, Scpe_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym(r), "debug_plots", 1); + % Scpe_cell = cell(1); + % Scpe_cell{1} = Scpe_sig_resampled; + + Scpe_cell{1}.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1); eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"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); mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels); - %Duobinary Targeting if 0 - db_ref_sequence = Duobinary().encode(Symbols); - db_ref_constellation = unique(db_ref_sequence.signal); - [eq_signal, eq_noise] = eq_.process(Scpe_cell{1},db_ref_sequence); - - mlse_.DIR = [1,1]; - [mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols); - - mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd); - mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M); - mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M); - - tx_symbols_precoded = Duobinary().encode(Symbols); - tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded); - - tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded); - - rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded); - [~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); - - %B) Just determine BER - rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); - [bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); + %Duobinary Targeting + db_ref_sequence = Duobinary().encode(Symbols); + db_ref_constellation = unique(db_ref_sequence.signal); + [eq_signal, eq_noise] = eq_.process(Scpe_cell{1},db_ref_sequence); + + mlse_.DIR = [1,1]; + [mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols); + + mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd); + mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M); + mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M); + + tx_symbols_precoded = Duobinary().encode(Symbols); + tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded); + + tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded); + + rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded); + [~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); + + %B) Just determine BER + rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); + [bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); end % FFE or VNLE eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"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_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols); - [gmi_vnle(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100); + [gmi_gomez(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100); + [gmi_vnle(r)] = calc_ngmi(eq_signal_sd,Symbols); + [gmi_bitwise(r)] = calc_gmi_bitwise(eq_signal_sd,Symbols); + + snr_vnle(r) = calc_snr(Symbols, eq_signal_sd-Symbols); eq_signal_sd.plot("displayname",'bla','fignum',118); + % Hard decision on VNLE output eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd); @@ -180,19 +179,21 @@ for r = 1:length(rop) fprintf('BER VNLE: %.2e \n',ber_vnle(r)); fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M)); - + if 1 + % Process through postfilter and MLSE pf_ncoeffs = 1; pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); [mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); mlse_.DIR = pf_.coefficients; + alpha(r) = pf_.coefficients(2); [signalclass_hd,LLR,gmi_mlse(r)] = mlse_.process(mlse_sig_sd,Symbols); mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(signalclass_hd); rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); [~,~,ber_mlse(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); fprintf('BER: %.2e \n',ber_mlse(r)); - fprintf('NGMI MLSE: %.2f \n',gmi_mlse(r)./log2(M)); + fprintf('GMI MLSE: %.5f \n',gmi_mlse(r)); % Process through postfilter and MLSE @@ -205,23 +206,48 @@ for r = 1:length(rop) mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd); rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); [~,~,ber_viterbi(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); - fprintf('FW BER: %.2e \n',ber_viterbi(r)); + fprintf('Viterbi BER: %.2e \n',ber_viterbi(r)); + end + + end +cols = cbrewer2('Paired',8); +d = 1; -figure();hold on -plot(rop,gmi_mlse,'DisplayName','MLSE','Marker','*'); -plot(rop,gmi_vnle,'DisplayName','VNLE','Marker','*'); -plot(rop,gmi_mlse_db,'DisplayName','MLSE DB Tgt','Marker','*'); +figure(11);hold on +plot(fsym.*1e-9,alpha,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:)); +xlabel('Baudrate in GBd'); +ylabel('alpha'); + +figure(15);hold on +plot(fsym.*1e-9,gmi_gomez,'DisplayName','gomez','Marker','x','LineStyle','-','Color',cols(1+d,:)); +plot(fsym.*1e-9,gmi_vnle,'DisplayName','vnle other','Marker','x','LineStyle','-','Color',cols(3+d,:)); +plot(fsym.*1e-9,gmi_bitwise,'DisplayName','bitwise','Marker','x','LineStyle','--','Color',cols(5+d,:)); +plot(fsym.*1e-9,gmi_mlse,'DisplayName','MLSE','Marker','*'); ylim([0 2.6]); +xlabel('Baudrate in GBd'); +ylabel('GMI'); -figure();hold on -plot(rop,ber_vnle,'DisplayName','VNLE'); -plot(rop,ber_mlse,'DisplayName','MLSE','Marker','*'); -plot(rop,ber_viterbi,'DisplayName','Viterbi','Marker','*'); -plot(rop,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','*'); -plot(rop,ber_db,'DisplayName','MLSE db','Marker','*'); +figure(13);hold on +plot(fsym.*1e-9,ber_vnle,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:)); +plot(fsym.*1e-9,ber_mlse,'DisplayName','MLSE','Marker','x','LineStyle','-','Color',cols(3+d,:)); +plot(fsym.*1e-9,ber_viterbi,'DisplayName','Viterbi','Marker','x','LineStyle','--','Color',cols(5+d,:)); +% plot(bwl,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','.','MarkerSize',15,'LineStyle','-'); +% plot(bwl,ber_db,'DisplayName','MLSE db','Marker','.','MarkerSize',15,'LineStyle','-'); +xlabel('Baudrate in GBd'); +ylabel('BER'); set(gca, 'yscale', 'log'); +% ylim([1e-6 0.1]); legend + + + +% Auxiliary nested helper for numerically stable log-sum-exp +function s = logsumexp(a) + % LOGSUMEXP Compute log(sum(exp(a))) in a numerically stable way + m = max(a); + s = m + log(sum(exp(a - m))); +end diff --git a/projects/Job_Processing/run_offline_dsp.m b/projects/Job_Processing/run_offline_dsp.m deleted file mode 100644 index 335b57b..0000000 --- a/projects/Job_Processing/run_offline_dsp.m +++ /dev/null @@ -1,117 +0,0 @@ -% === SETTINGS === - -dsp_options.append_to_db = 1; -dsp_options.max_occurences = 15; -dsp_options.database_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\'; -dsp_options.database_name = 'silas_labor_newdsp_newstructure.db'; -dsp_options.storage_path = 'Z:\2024\sioe_labor\'; -dsp_options.parameters = struct(); -dsp_options.parameters.mu_dc = [0.005]; - -% === Get Run ID's === -db = DBHandler("pathToDB", [dsp_options.database_path, dsp_options.database_name], "type", "sqlite"); -fp = QueryFilter(); -% fp.where('Runs', 'run_id','EQUALS', 5108); -fp.where('Runs', 'is_mpi','EQUALS', 0); -% fp.where('Runs', 'fiber_length','EQUALS', 10); -fp.where('Runs', 'wavelength','EQUALS', 1310); -fp.where('Runs', 'db_mode','EQUALS', 1); -fp.where('Runs', 'rop_attenuation','EQUALS', 0); -fp.where('Runs', 'pam_level','EQUALS', 4); -% fp.where('Runs', 'bitrate','EQUALS', 360e9); -% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); -[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); - -% === Initialize DataStorage === -wh = DataStorage(dsp_options.parameters); -wh.addStorage("ffe_package"); -wh.addStorage("mlse_package"); -wh.addStorage("vnle_package"); -wh.addStorage("dbtgt_package"); -wh.addStorage("dbenc_package"); - -% === RUN IT === - -[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true); -% wh.getStoValue('ffe_package',0.005); -% wh.getStoValue('mlse_package',0.005); - -[dataTable,~] = db.queryDB(fp, [db.getTableFieldNames('Runs');db.getTableFieldNames('Results');db.getTableFieldNames('Equalizer')]); - -dataTable = cleanUpTable(dataTable); - -% === Look at it === -y_var = 'BER_precoded'; -x_var = 'bitrate'; -fixedVars = {'equalizer_structure', x_var}; - -[dataTableClean, outliersTable] = removeGroupOutliers(dataTable, fixedVars, y_var); - -% --- Group and aggregate --- -dataTableGrpd_mean = groupIt(fixedVars, dataTableClean, @mean); -dataTableGrpd_min = groupIt(fixedVars, dataTableClean, @min); -dataTableGrpd_max = groupIt(fixedVars, dataTableClean, @max); - -% Choose a color map -cols = linspecer(numel(unique(dataTableGrpd_mean.equalizer_structure))); - -figure; -hold on; - -% Get unique equalizer structures for grouping -unique_eq = unique(dataTableGrpd_mean.equalizer_structure); - -for i = 1:numel(unique_eq) - eq_val = unique_eq(i); - - % Filter grouped data for this equalizer structure - filt = dataTableGrpd_mean.equalizer_structure == eq_val; - - x = dataTableGrpd_mean.(x_var)(filt); - y_mean = dataTableGrpd_mean.(y_var)(filt); - y_min = dataTableGrpd_min.(y_var)(filt); - y_max = dataTableGrpd_max.(y_var)(filt); - - % Bounds for boundedline (distance from mean) - y_lower = y_mean - y_min; - y_upper = y_max - y_mean; - y_bounds = [y_lower, y_upper]; - - % --- Bounded line (mean ± min/max) --- - if exist('boundedline', 'file') - [hl, hp] = boundedline(x, y_mean, y_bounds, ... - 'alpha', 'transparency', 0.1, ... - 'cmap', cols(i,:), ... - 'nan', 'fill', ... - 'orientation', 'vert'); - set(hl, 'LineWidth', 1.2, 'DisplayName', sprintf('Eq %s', eq_val)); - set(hp, 'HandleVisibility', 'off'); - else - % If boundedline is not available, use errorbar - errorbar(x, y_mean, y_lower, y_upper, ... - 'o-', 'Color', cols(i,:), 'LineWidth', 1.2, ... - 'DisplayName', sprintf('Eq %d', eq_val),'HandleVisibility', 'off'); - end - - % --- Normal line (mean only) --- - plot(x, y_mean, '-', 'Color', cols(i,:), 'LineWidth', 1.5, ... - 'DisplayName', sprintf('Mean Eq %s', eq_val),'HandleVisibility', 'off'); - - % --- Scatter plot for individual points (from original data) --- - % Filter original data for this group - orig_filt = dataTableClean.equalizer_structure == eq_val; - x_scatter = dataTableClean.(x_var)(orig_filt); - y_scatter = dataTableClean.(y_var)(orig_filt); - - scatter(x_scatter, y_scatter, 10,cols(i,:), 'filled', ... - 'MarkerFaceAlpha', 0.5, 'DisplayName', sprintf('Scatter Eq %s', eq_val),'HandleVisibility', 'off'); -end - -yline([2.2e-4,4.85e-3,2e-2],'HandleVisibility', 'off','LineWidth',1,'LineStyle','--'); -set(gca, 'YScale', 'log'); % BER is usually plotted log-scale -xlabel(x_var, 'Interpreter', 'none'); -ylabel(y_var, 'Interpreter', 'none'); -legend('show', 'Location', 'best'); -grid on; -title(sprintf('%s vs. %s', y_var, x_var), 'Interpreter', 'none'); -hold off; \ No newline at end of file diff --git a/projects/Job_Processing/run_offline_dsp_script.m b/projects/Job_Processing/run_offline_dsp_script.m deleted file mode 100644 index a75b3bc..0000000 --- a/projects/Job_Processing/run_offline_dsp_script.m +++ /dev/null @@ -1,116 +0,0 @@ -dsp_options.append_to_db = false; -dsp_options.max_occurences = 1; -dsp_options.mode = "load_run_id"; -experiment = "highspeed_2024"; - -if dsp_options.mode == "load_run_id" - - dsp_options.load_file_path = []; - if experiment == 'highspeed_2024' - - dsp_options.database_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db'; - dsp_options.storage_path = 'Z:\2024\sioe_labor\'; - db = DBHandler("pathToDB", [dsp_options.database_path], "type", "sqlite"); - - elseif 'mpi_ecoc_2025' - - dsp_options.database_path = []; %sqlite im netzwerk - dsp_options.storage_path = 'Z:\2025\ECOC Silas\ecoc_2025\'; - db = DBHandler("pathToDB", [dsp_options.database_path], "type", "mysql"); - - end - - -elseif dsp_options.mode == "load_files" - - dsp_options.load_file_path.tx_bits_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_bits.mat"'; - dsp_options.load_file_path.tx_symbols_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_symbols.mat"'; - dsp_options.load_file_path.rx_raw_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091525_PAM_4_R_112_rec01_rx_signal_raw.mat"'; - -elseif dsp_options.mode == "simulate" - - error('Not yet implemented') - -end - - -%% === Define Database Filters === - -if experiment == 'highspeed_2024' - - fp = QueryFilter(); - db = db.getDistinctValues; - %fp.where('Runs', 'run_id','EQUALS', 3); - fp.where('Runs', 'pam_level','EQUALS', 4); - allrates = string(num2str(sort(db.distinctValues.Runs.bitrate.*1e-9))); - fp.where('Runs', 'bitrate','EQUALS',390e9); - alllengths = string(num2str(sort(db.distinctValues.Runs.fiber_length))); - fp.where('Runs', 'fiber_length','EQUALS', 1); - fp.where('Runs', 'is_mpi','EQUALS', 0); - % fp.where('Runs', 'interference_path_length','EQUALS', 1000); - % fp.where('Runs', 'loop_id','GREATER_THAN', 11); - % fp.where('Runs', 'sir','EQUALS',18); - fp.where('Runs', 'wavelength','EQUALS', 1310); - fp.where('Runs', 'db_mode','EQUALS', 0); - % fp.where('Runs', 'rop_attenuation','EQUALS', 0); - fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); - -elseif experiment == 'mpi_ecoc_2025' - - fp = QueryFilter(); - %fp.where('Runs', 'run_id','EQUALS', 3); - fp.where('Runs', 'pam_level','EQUALS', 4); - fp.where('Runs', 'bitrate','EQUALS',224e9); - fp.where('Runs', 'is_mpi','EQUALS', 1); - fp.where('Runs', 'interference_path_length','EQUALS', 1000); - % fp.where('Runs', 'loop_id','GREATER_THAN', 11); - fp.where('Runs', 'sir','EQUALS',18); - fp.where('Runs', 'wavelength','EQUALS', 1310); - fp.where('Runs', 'db_mode','EQUALS', 0); - % fp.where('Runs', 'rop_attenuation','EQUALS', 0); - fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); - % fp.where('Runs', 'loop_id','EQUALS', 14); - -end - - -% === Queue from DB === -[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); - -% === Adapt or filter Matlab Table === -% [~, unique_indices] = unique(dataTable.sir, 'first'); -% dataTable = dataTable(unique_indices, :); - - -% === Set LOOPS & Initialize DataStorage === -dsp_options.parameters = struct(); -% dsp_options.parameters.adaption = [3]; -% dsp_options.parameters.mu_tr = 0.999;%[0,logspace(-4,0,10)]; -% dsp_options.parameters.mu_dd = [logspace(-0.004,0,20)]; -% dsp_options.parameters.use_dd_mode = [1]; - -wh = DataStorage(dsp_options.parameters); -wh.addStorage("ffe_package"); -wh.addStorage("mlse_package"); -wh.addStorage("vnle_package"); -wh.addStorage("dbtgt_package"); -wh.addStorage("dbenc_package"); - - -% === RUN IT === -% run this function: dsp_runid(run_id, options) -[results,wh] = submitJobs(dataTable.run_id, dsp_options, "serial", 'wh', wh, 'waitbar', false); - - -%% -BERs = cellfun(@(c) c.ffe_package{1,1}.metrics.BER, results); -figure -hold on -plot(dsp_options.parameters.mu_dd,BERs,'Marker','+') -yline([2.2e-4,4.85e-3,2e-2],'HandleVisibility', 'off','LineWidth',1,'LineStyle','--'); -set(gca, 'YScale', 'log'); % BER is usually plotted log-scale -xlabel('$\mu$ DD', 'Interpreter', 'latex'); -ylabel('BER', 'Interpreter', 'latex'); -legend('show', 'Location', 'best'); -grid on; -hold off; \ No newline at end of file diff --git a/projects/Lab_2024/offline_dsp_analysis/load_n_plot_transfer_characteristic.m b/projects/Lab_2024/offline_dsp_analysis/load_n_plot_transfer_characteristic.m index 17d04f5..533892a 100644 --- a/projects/Lab_2024/offline_dsp_analysis/load_n_plot_transfer_characteristic.m +++ b/projects/Lab_2024/offline_dsp_analysis/load_n_plot_transfer_characteristic.m @@ -6,3 +6,11 @@ precomp_filename = "lab_high_speed"; freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9); freqresp.load('loadPath',precomp_path,'fileName',precomp_filename); freqresp.plot(); + + +freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',256e9); +precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT"; +precomp_fn = "precomp_simulated.mat"; + +freqresp.load('loadPath',precomp_path,'fileName',precomp_fn); +freqresp.plot(); \ No newline at end of file