CLEANUP - changes to folder structure
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
classdef TestRand_examplecode < matlab.unittest.TestCase
|
||||
properties (ClassSetupParameter)
|
||||
generator = {'twister','combRecursive','multFibonacci'};
|
||||
end
|
||||
|
||||
properties (MethodSetupParameter)
|
||||
seed = {0,123,4294967295};
|
||||
end
|
||||
|
||||
properties (TestParameter)
|
||||
dim1 = struct('small',1,'medium',2,'large',3);
|
||||
dim2 = struct('small',2,'medium',3,'large',4);
|
||||
dim3 = struct('small',3,'medium',4,'large',5);
|
||||
type = {'single','double'};
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
function classSetup(testCase,generator)
|
||||
orig = rng;
|
||||
testCase.addTeardown(@rng,orig)
|
||||
rng(0,generator)
|
||||
end
|
||||
end
|
||||
|
||||
methods (TestMethodSetup)
|
||||
function methodSetup(testCase,seed)
|
||||
orig = rng;
|
||||
testCase.addTeardown(@rng,orig)
|
||||
rng(seed)
|
||||
end
|
||||
end
|
||||
|
||||
methods (Test, ParameterCombination = 'sequential')
|
||||
function testSize(testCase,dim1,dim2,dim3)
|
||||
testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3])
|
||||
end
|
||||
end
|
||||
|
||||
methods (Test, ParameterCombination = 'pairwise')
|
||||
function testRepeatable(testCase,dim1,dim2,dim3)
|
||||
state = rng;
|
||||
firstRun = rand(dim1,dim2,dim3);
|
||||
rng(state)
|
||||
secondRun = rand(dim1,dim2,dim3);
|
||||
testCase.verifyEqual(firstRun,secondRun)
|
||||
end
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
function testClass(testCase,dim1,dim2,type)
|
||||
testCase.verifyClass(rand(dim1,dim2,type),type)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
if 0
|
||||
|
||||
AWG = AwgKeysight("model","M8196A","fdac",92e9,"scaletodac",[1,1,1,1],"skews",[0,0,0,0],"voltages",[0,0,0,0.6]);
|
||||
|
||||
tx_sig = Electricalsignal(clip_out,"fs",92e9);
|
||||
|
||||
tic
|
||||
AWG.upload("signal4",clip_out);
|
||||
toc
|
||||
|
||||
end
|
||||
|
||||
SCP = ScopeKeysight("model","DSAZ634A",'autoscale',1,"fadc",'GSa_160',"channel",[1],"recordLen",2000000);
|
||||
signals = SCP.read();
|
||||
@@ -1,219 +0,0 @@
|
||||
%% Bayesian Optimization for FFE Parameter Tuning
|
||||
% This script uses bayesopt to find optimal mu_dd and mu_tr values
|
||||
% that minimize BER for the FFE equalizer.
|
||||
|
||||
clear; clc;
|
||||
|
||||
%% Setup - Same as gpu_processing_dpfiber.m
|
||||
s.wavelengthplan = calcWavelengthPlan(4, 400e9, 1310);
|
||||
link_length = 10;
|
||||
s.pmd = 0.1;
|
||||
s.gamma = 0.0023;
|
||||
|
||||
s.M = 4;
|
||||
fsym = 112e9;
|
||||
fdac = 2*fsym;
|
||||
fadc = 120000000000;
|
||||
s.random_key = 1;
|
||||
|
||||
% Laser / Modulator
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 4.6;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
laser_linewidth = 0e6;
|
||||
|
||||
duob_mode = db_mode.no_db;
|
||||
rcalpha = 0.05;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
s.chirpalpha = 0;
|
||||
s.p_launch = 3;
|
||||
s.p = "co";
|
||||
|
||||
N = numel(s.wavelengthplan);
|
||||
|
||||
switch s.p
|
||||
case "co"
|
||||
pol_rot = 100.*ones(1,N);
|
||||
d_local = 0;
|
||||
end
|
||||
|
||||
f_plan = physconst('lightspeed')./(s.wavelengthplan.*1e-9);
|
||||
margin = 25e12;
|
||||
f_span = (max(f_plan)+margin)-(min(f_plan)-margin);
|
||||
f_nyq = f_span/2;
|
||||
|
||||
kover = 4;
|
||||
upsample_required = f_nyq./(fdac*kover/2);
|
||||
upsample_pow = 2^nextpow2(upsample_required);
|
||||
|
||||
s.f_opt = fdac*kover*upsample_pow;
|
||||
s.f_opt_nyq = s.f_opt/2;
|
||||
|
||||
s.rop = -8; % Fixed ROP for optimization
|
||||
|
||||
%% Generate TX signals (run once)
|
||||
fprintf('Generating TX signals...\n');
|
||||
for l = 1:N
|
||||
[Digi_sig,Symbols{l},Tx_bits{l}] = PAMsource( ...
|
||||
"fsym",fsym,"M",s.M,"order",15,"useprbs",0, ...
|
||||
"fs_out",fdac, ...
|
||||
"applyclipping",0,"clipfactor",1.5, ...
|
||||
"applypulseform",1,"pulseformer",Pform, ...
|
||||
"randkey",s.random_key+l, ...
|
||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode ...
|
||||
).process();
|
||||
|
||||
Lp_awg = Filter('filtdegree',3,"f_cutoff",56e9,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.gaussian,"active",true);
|
||||
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",1,"kover",kover, ...
|
||||
"bit_resolution",6,"upsampling_method","samplehold","precomp_sinc_rolloff",0, ...
|
||||
"H_lpf",Lp_awg,"dac_max",0.6,"dac_min",-0.6).process(Digi_sig);
|
||||
|
||||
El_sig = El_sig.normalize("mode","oneone");
|
||||
scaling = 0.6*(u_pi/2-abs(vbias-u_pi/2));
|
||||
El_sig = El_sig .* scaling;
|
||||
|
||||
Eml_out = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs, ...
|
||||
"lambda",s.wavelengthplan(l),"bias",vbias,"u_pi",u_pi, ...
|
||||
"linewidth",laser_linewidth,"randomkey",s.random_key+l,"alpha",s.chirpalpha).process(El_sig);
|
||||
|
||||
signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",pol_rot(l)).process(Eml_out);
|
||||
end
|
||||
|
||||
%% WDM mux + launch
|
||||
Opt_sig_wdm = Optical_Multiplex("fs_in",fdac*kover,"fs_out",upsample_pow*fdac*kover, ...
|
||||
"lambda_center",1310,"random_key",0,"filtype",1,"B",120e9).process(signal_cell);
|
||||
|
||||
Opt_sig_wdm = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",s.p_launch+10*log10(N)).process(Opt_sig_wdm);
|
||||
|
||||
%% Fiber propagation
|
||||
segment_length = 1;
|
||||
nSegments = link_length/segment_length;
|
||||
nSegments = round(nSegments);
|
||||
|
||||
zdw = 1310;
|
||||
randomize_D = true;
|
||||
Dvec = getDispersionVector(nSegments, d_local, zdw, randomize_D, s.random_key);
|
||||
|
||||
Opt_sig_wdm_fib = Opt_sig_wdm;
|
||||
fprintf('Running fiber propagation...\n');
|
||||
for seg = 1:nSegments
|
||||
fprintf('Segment %d/%d\n', seg, nSegments);
|
||||
Opt_sig_wdm_fib = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07, ...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0, ...
|
||||
"gamma",s.gamma,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01, ...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1,"useGPU",true,"useSingle",true).process(Opt_sig_wdm_fib);
|
||||
end
|
||||
|
||||
%% Pre-process to get Rx_sig (do demux once)
|
||||
fprintf('Pre-processing receiver chain...\n');
|
||||
l = 1; % Use channel 1 for optimization
|
||||
|
||||
Opt_sig_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1, ...
|
||||
"fs_out",fdac*kover,"fs_in",fdac*kover*upsample_pow,"lambda_center",1310).process(Opt_sig_wdm_fib);
|
||||
|
||||
Opt_sig_rx = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",s.rop).process(Opt_sig_demux{l});
|
||||
|
||||
PD_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20, ...
|
||||
"nep",1.8e-11,"randomkey",s.random_key+l).process(Opt_sig_rx);
|
||||
|
||||
rx_bwl = 100e9;
|
||||
PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.butterworth,"active",true).process(PD_sig);
|
||||
|
||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",80e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||
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',0,'H_lpf',Lp_scpe).process(PD_sig);
|
||||
|
||||
Scpe_sig_2sps = Scpe_sig.resample("fs_out",2*fsym);
|
||||
|
||||
[~, Scpe_cell, ~, ~] = Scpe_sig_2sps.tsynch("reference", Symbols{l}, "fs_ref", fsym, "debug_plots", 0);
|
||||
Rx_sig = Scpe_cell{1};
|
||||
Rx_sig = Rx_sig.normalize("mode","rms");
|
||||
|
||||
fprintf('Receiver pre-processing complete. Ready for optimization.\n\n');
|
||||
|
||||
%% Define the objective function for bayesopt
|
||||
function ber = ffe_objective(params, Rx_sig, Symbols_l, Tx_bits_l, M, duob_mode)
|
||||
mu_dd = params.mu_dd;
|
||||
mu_tr = params.mu_tr;
|
||||
|
||||
try
|
||||
eq_ffe = FFE("epochs_tr", 5, "epochs_dd", 2, "len_tr", 2^13, ...
|
||||
"mu_dd", mu_dd, "mu_tr", mu_tr, ...
|
||||
"order", 50, "sps", 2, "decide", 0, ...
|
||||
"adaption", adaption_method.nlms, "dd_mode", 1);
|
||||
|
||||
ffe_results = ffe(eq_ffe, M, Rx_sig, Symbols_l, Tx_bits_l, ...
|
||||
"precode_mode", duob_mode, ...
|
||||
'showAnalysis', 0, ...
|
||||
"postFFE", [], ...
|
||||
"eth_style_symbol_mapping", 0);
|
||||
|
||||
ber = ffe_results.metrics.BER;
|
||||
|
||||
if ber == 0
|
||||
ber = 1e-10;
|
||||
end
|
||||
|
||||
if ~isfinite(ber)
|
||||
ber = 0.5;
|
||||
end
|
||||
|
||||
fprintf(' mu_dd=%.4e, mu_tr=%.4e -> BER=%.4e\n', mu_dd, mu_tr, ber);
|
||||
|
||||
catch ME
|
||||
fprintf(' mu_dd=%.4e, mu_tr=%.4e -> FAILED (%s)\n', mu_dd, mu_tr, ME.message);
|
||||
ber = 0.5;
|
||||
end
|
||||
end
|
||||
|
||||
%% Define optimizable variables
|
||||
mu_dd_var = optimizableVariable('mu_dd', [1e-5, 0.1], 'Transform', 'log');
|
||||
mu_tr_var = optimizableVariable('mu_tr', [1e-5, 0.1], 'Transform', 'log');
|
||||
|
||||
%% Run Bayesian Optimization
|
||||
fprintf('========== Starting Bayesian Optimization ==========\n');
|
||||
fprintf('Optimizing mu_dd and mu_tr to minimize BER\n');
|
||||
fprintf('Search range: mu_dd=[1e-5, 0.1], mu_tr=[1e-5, 0.1]\n\n');
|
||||
|
||||
objective_fn = @(params) ffe_objective(params, Rx_sig, Symbols{l}, Tx_bits{l}, s.M, duob_mode);
|
||||
|
||||
results = bayesopt(objective_fn, [mu_dd_var, mu_tr_var], ...
|
||||
'MaxObjectiveEvaluations', 30, ...
|
||||
'AcquisitionFunctionName', 'expected-improvement-plus', ...
|
||||
'IsObjectiveDeterministic', false, ...
|
||||
'ExplorationRatio', 0.5, ...
|
||||
'Verbose', 1, ...
|
||||
'PlotFcn', []);
|
||||
|
||||
%% Display Results
|
||||
fprintf('\n========== FFE Optimization Complete ==========\n');
|
||||
fprintf('Best FFE parameters found:\n');
|
||||
fprintf(' mu_dd = %.6e\n', results.XAtMinObjective.mu_dd);
|
||||
fprintf(' mu_tr = %.6e\n', results.XAtMinObjective.mu_tr);
|
||||
fprintf(' BER = %.6e\n', results.MinObjective);
|
||||
|
||||
%% Verify with optimal parameters
|
||||
fprintf('\nVerifying optimal FFE parameters...\n');
|
||||
best_mu_dd = results.XAtMinObjective.mu_dd;
|
||||
best_mu_tr = results.XAtMinObjective.mu_tr;
|
||||
|
||||
eq_ffe_best = FFE("epochs_tr", 5, "epochs_dd", 2, "len_tr", 2^13, ...
|
||||
"mu_dd", best_mu_dd, "mu_tr", best_mu_tr, ...
|
||||
"order", 50, "sps", 2, "decide", 0, ...
|
||||
"adaption", adaption_method.nlms, "dd_mode", 1);
|
||||
|
||||
ffe_results_best = ffe(eq_ffe_best, s.M, Rx_sig, Symbols{l}, Tx_bits{l}, ...
|
||||
"precode_mode", duob_mode, ...
|
||||
'showAnalysis', 1, ...
|
||||
"postFFE", [], ...
|
||||
"eth_style_symbol_mapping", 0);
|
||||
|
||||
fprintf('\nFinal FFE BER with optimal parameters: %.6e\n', ffe_results_best.metrics.BER);
|
||||
@@ -1,555 +0,0 @@
|
||||
classdef bcjr_pam < handle
|
||||
%MLSE calculates the most probable sequence for an input signal with given/ known channel impulse response of any length
|
||||
|
||||
properties(Access=public)
|
||||
M %PAM-M
|
||||
DIR
|
||||
trellis_states
|
||||
duobinary_output
|
||||
end
|
||||
|
||||
methods (Access=public)
|
||||
|
||||
function obj = bcjr_pam(options)
|
||||
%NAME Construct an instance of this class
|
||||
% Detailed explanation goes here
|
||||
|
||||
arguments
|
||||
options.M double = 4;
|
||||
options.DIR double = [1];
|
||||
options.trellis_states double = [-3 -1 1 3];
|
||||
options.duobinary_output logical = false;
|
||||
|
||||
end
|
||||
|
||||
%
|
||||
fn = fieldnames(options);
|
||||
for n = 1:numel(fn)
|
||||
try
|
||||
obj.(fn{n}) = options.(fn{n});
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function [VITERBI_ESTIMATION_SYMBOLS,LLR_exact,GMI] = process(obj,data_in,data_ref,tx_bits,bit_mapping)
|
||||
|
||||
|
||||
debug = 0;
|
||||
|
||||
% States should match the target states of the prev. EQ (EQ's job was to reduce the error between signal and the target)
|
||||
trellis_state_mode = 2;
|
||||
% 0 = use provided states (MUST provide the correct states);
|
||||
% 1 = normalize to = 1 rms;
|
||||
% 2 = use target symbols;
|
||||
% 3 = use statistical levels
|
||||
% 3 analyzes avg of rx signal levels - can help with nonlinear impairments
|
||||
|
||||
trellis_exclusion = 1; % PAM-6 only (only if data is NOT precoded!)
|
||||
|
||||
% Additional scaling between states, expected output (noiseless_received) and the noisy, filtered input signal
|
||||
scale_mode = 2; % scale_mode:
|
||||
% 0 = no scaling,
|
||||
% 1 = use RMS to scale MODEL,
|
||||
% 2 = use MMSE/time-corr to scale MODEL, -> This best to get the GMI right -> sometimes the LLP's are not centered around zero...
|
||||
% 3 = use RMS to scale DATA,
|
||||
% 4 = use MMSE/time-corr to scale DATA
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%% PREPARATIONS %%%%%%%%
|
||||
|
||||
% remove unnecessary zeros at start of impulse response to keep
|
||||
% number of trellis states minimal
|
||||
DIR_nonzero = find(obj.DIR ~= 0);
|
||||
if DIR_nonzero(1) > 1
|
||||
obj.DIR(1:DIR_nonzero(1)-1) = [];
|
||||
end
|
||||
|
||||
if isscalar(obj.DIR)
|
||||
obj.DIR = [0 obj.DIR];
|
||||
end
|
||||
|
||||
% impulse respnse to remove from signal
|
||||
obj.DIR = flip(obj.DIR); %i.e. -0.2676 -0.0478 1.0000
|
||||
|
||||
% Trellis States
|
||||
obj.trellis_states = reshape(obj.trellis_states,1,[]);
|
||||
if trellis_state_mode == 1 % Normalize the Trellis states to =1 RMS
|
||||
|
||||
obj.trellis_states = obj.trellis_states ./ rms(obj.trellis_states);
|
||||
|
||||
elseif trellis_state_mode == 2 %simply use the states from the ref signal (should be a robust option)
|
||||
|
||||
obj.trellis_states = reshape(unique(data_ref),size(obj.trellis_states));
|
||||
|
||||
elseif trellis_state_mode == 3 %use_statistical_levels
|
||||
|
||||
%%%% Separate the equalized signal into the respective levels based on the actually transmitted level
|
||||
constellation = unique(data_ref);
|
||||
|
||||
% find actual levels from rx signal
|
||||
symbols_for_lvl = NaN(numel(constellation),length(data_ref));
|
||||
for l = 1:numel(constellation)
|
||||
level_amplitude = constellation(l);
|
||||
symbols_for_lvl(l,data_ref==level_amplitude) = data_in(data_ref==level_amplitude);
|
||||
end
|
||||
|
||||
%replace the trellis states
|
||||
avg_levels = mean(symbols_for_lvl,2,'omitnan');
|
||||
obj.trellis_states = sort(avg_levels)';
|
||||
|
||||
%also replace the whole ref signal (PAM-M) levels
|
||||
[~, idx] = ismember(data_ref, unique(data_ref));
|
||||
data_ref = avg_levels(idx);
|
||||
|
||||
end
|
||||
|
||||
|
||||
% 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);
|
||||
pre_comb_cell = mat2cell(pre_comb_mat,ones(1,size(pre_comb_mat,1)),size(pre_comb_mat,2));
|
||||
combs = fliplr(combvec(pre_comb_cell{:}).');
|
||||
first_sym = combs(:,1); % das ist das älteste/ trailing Symbol aus der sequenz
|
||||
last_sym = combs(:,end); %hiermit wird entschieden/ das ist das cursor symbol am ende der sequenz
|
||||
nStates = length(last_sym);
|
||||
|
||||
% % Calculate all possible input symbols for the desired impulse
|
||||
% % response. Row number is the index of the previous state,
|
||||
% % column number is the index of the next state
|
||||
% % noise free received == branch metrics
|
||||
% assumes: last_sym = combs(:,end); % already defined earlier
|
||||
levels = sort(unique(obj.trellis_states(:)).');
|
||||
edges = [levels(1) levels(end)]; % edge levels (0 and 5 in PAM6)
|
||||
|
||||
noise_free_received = inf(nStates,nStates); % rows: to, cols: from
|
||||
edge_edge_mask = false(nStates,nStates); % rows: to, cols: from
|
||||
|
||||
for from = 1:nStates
|
||||
for to = 1:nStates
|
||||
% valid transition if shift-register overlap holds
|
||||
if all(combs(to,2:end) == combs(from,1:end-1))
|
||||
% noiseless sample for the 'to' state reached from 'from'
|
||||
noise_free_received(to,from) = ...
|
||||
dot(combs(to,:), obj.DIR(end:-1:2)) + last_sym(from)*obj.DIR(1);
|
||||
|
||||
% mark edge→edge candidate (to be excluded only on even→odd steps)
|
||||
edge_edge_mask(to,from) = ...
|
||||
(last_sym(from)==edges(1) || last_sym(from)==edges(2)) && ...
|
||||
(last_sym(to) ==edges(1) || last_sym(to) ==edges(2));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
h = flip(obj.DIR(:)).';
|
||||
data_in = data_in(:);
|
||||
y_ideal = conv(data_ref(:), h, "same");
|
||||
|
||||
switch scale_mode
|
||||
case 0
|
||||
g = 1; b = 0;
|
||||
case 1 % RMS: scale model to data
|
||||
g = rms(data_in)/rms(y_ideal); b = mean(data_in) - g*mean(y_ideal);
|
||||
case 2 % MMSE/time-corr: scale states to data
|
||||
[c,lags] = xcorr(data_in(:), y_ideal, 64);
|
||||
[~,ix] = max(abs(c));
|
||||
lag = lags(ix);
|
||||
y_ideal = circshift(y_ideal, lag);
|
||||
mu_y = mean(data_in(:));
|
||||
mu_i = mean(y_ideal);
|
||||
y_c = data_in(:)-mu_y;
|
||||
yi_c = y_ideal-mu_i;
|
||||
g = (yi_c'*y_c)/(yi_c'*yi_c);
|
||||
b = mu_y - g*mu_i;
|
||||
case 3 % RMS flipped: scale data to model
|
||||
gd = rms(y_ideal)/rms(data_in); bd = mean(y_ideal) - gd*mean(data_in);
|
||||
data_in = gd*data_in + bd;
|
||||
g = 1; b = 0;
|
||||
case 4 % MMSE/time-corr flipped: scale data to states
|
||||
[c,lags] = xcorr(data_in(:), y_ideal(:), 64);
|
||||
[~,ix] = max(abs(c));
|
||||
lag = lags(ix);
|
||||
y_ideal = circshift(y_ideal(:), lag);
|
||||
mu_y = mean(data_in(:));
|
||||
mu_i = mean(y_ideal);
|
||||
y_c = data_in(:) - mu_y; % data_in centered
|
||||
yi_c = y_ideal - mu_i; % ideal centered
|
||||
g = (y_c' * yi_c) / (y_c' * y_c);
|
||||
b = mu_i - g * mu_y;
|
||||
data_in = g * data_in(:) + b;
|
||||
g = 1; b = 0;
|
||||
end
|
||||
|
||||
% apply (g,b) to states/ expected values
|
||||
noise_free_received = g*noise_free_received + b;
|
||||
last_sym = g*last_sym + b;
|
||||
|
||||
% calculate noise power
|
||||
sigma2 = mean(abs(data_in - (g*y_ideal + b)).^2); %noise = mean(abs((RX Signal - IDEAL Signal)))^2
|
||||
inv2s2 = 1/(2*sigma2);
|
||||
|
||||
if debug
|
||||
figure(100); clf; hold on
|
||||
obj.showLevelScatter_(data_in, data_ref);
|
||||
yline(noise_free_received(:), 'DisplayName','Transition States','Color','red','HandleVisibility','off');
|
||||
yline(obj.trellis_states(:), 'DisplayName','Transition States','Color','green','LineWidth',2,'HandleVisibility','off')
|
||||
end
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%% FORWARD PASS (VITERBI -Alpha's) %%%%%
|
||||
|
||||
% Initialize the output vector
|
||||
pm = zeros(nStates,nStates);
|
||||
bm_fw = zeros(nStates,nStates,length(data_in));
|
||||
|
||||
% first start is evaluated without ISI/ wihout the full Impulse response
|
||||
% so simply use the constellation here
|
||||
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);
|
||||
bm_fw(:,:,1) = pm;
|
||||
|
||||
% Forward Recursion (FSM Computation)
|
||||
for n = 2:length(data_in)
|
||||
|
||||
bm = -(data_in(n) - noise_free_received).^2 * inv2s2;
|
||||
|
||||
% exclude edge to edge transitions only for even->odd steps && PAM-6
|
||||
if mod(n,2) == 0 && obj.M == 6 && trellis_exclusion
|
||||
bm(edge_edge_mask) = -Inf;
|
||||
end
|
||||
|
||||
pm = pm + bm;
|
||||
[alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state (get min distance for all state transitions towards a new state)
|
||||
pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
|
||||
|
||||
bm_fw(:,:,n) = bm;
|
||||
|
||||
end
|
||||
|
||||
% we can now get the best path as min
|
||||
viterbi_path = NaN(1,length(data_in));
|
||||
|
||||
% find ideal trellis path by going through the trellis backwards
|
||||
[~,viterbi_path(length(data_in))] = max(alpha(:,length(data_in)));
|
||||
for n = length(data_in):-1:2
|
||||
viterbi_path(n-1) = pm_survivor_fw_idx(viterbi_path(n),n);
|
||||
end
|
||||
|
||||
|
||||
if debug
|
||||
alpha_ = alpha - min(alpha) + eps;
|
||||
figure();hold on;
|
||||
n = 10;
|
||||
scatter(1:n,obj.trellis_states(repmat([1:numel(obj.trellis_states)]',1,n)),abs(alpha_(:,end-n+1:end)),'Marker','o','LineWidth',1);
|
||||
scatter(1:n,obj.trellis_states(viterbi_path(end-n+1:end)),500,'Marker','x','LineWidth',1,'MarkerEdgeColor','green');
|
||||
% scatter(1:n,data_ref(end-n+1:end),500,'Marker','x','LineWidth',1,'MarkerEdgeColor','red');
|
||||
yticks(obj.trellis_states);
|
||||
ylim([min(obj.trellis_states)-1 max(obj.trellis_states)+1]);
|
||||
end
|
||||
|
||||
VITERBI_ESTIMATION_SYMBOLS(1:length(data_in)) = first_sym(viterbi_path);
|
||||
VITERBI_ESTIMATION_SYMBOLS = reshape(VITERBI_ESTIMATION_SYMBOLS,size(data_in));
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%% BACKWARD (Beta's) %%%%%
|
||||
|
||||
% Initialize the output vector
|
||||
pm = zeros(nStates,nStates);
|
||||
beta = zeros(nStates,length(data_in));
|
||||
pm_survivor_bw_idx = zeros(nStates,length(data_in));
|
||||
bm_bw = zeros(nStates,nStates,length(data_in));
|
||||
|
||||
% starting with the state that has the lowest sum path
|
||||
% metric, follow the stored information about the
|
||||
% predecessor
|
||||
for h = length(data_in)-1:-1:1
|
||||
|
||||
bm = -(data_in(h+1) - noise_free_received).^2 * inv2s2;
|
||||
|
||||
% exclude edge to edge transitions for even->odd steps && PAM-6
|
||||
if mod(h+1, 2) == 0 && obj.M == 6 && trellis_exclusion
|
||||
bm(edge_edge_mask) = -Inf;
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
bm_bw(:,:,h) = bm;
|
||||
|
||||
end
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%% FORWARD (Combine Alpha and Beta to yield LLP's) %%%%%
|
||||
|
||||
%calc the log probabilities (llp's)
|
||||
|
||||
for k = 1:length(data_in)
|
||||
|
||||
if k == 1
|
||||
|
||||
alpha_ = repmat(alpha(:,k)',[nStates,1])';
|
||||
beta_ = beta(:,k);
|
||||
|
||||
LLP(:,k) = max(alpha_ + beta_,[],2);
|
||||
|
||||
else
|
||||
|
||||
alpha_ = repmat(alpha(:,k-1)',[nStates,1])';
|
||||
gamma_ = bm_fw(:,:,k)';
|
||||
beta_ = beta(:,k);
|
||||
|
||||
LLP(:,k) = max(alpha_ + gamma_,[],1) + beta_';
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%% Calc LLR's %%%%%
|
||||
|
||||
% These are interchangeable...
|
||||
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
|
||||
|
||||
if obj.M == 6
|
||||
|
||||
num_bits = 5;
|
||||
|
||||
% all possible transitions (for now 36, including the "edges"
|
||||
% of the QAM 32 constellation)
|
||||
states = [-5 -3 -1 1 3 5];
|
||||
pam6transitions = combvec(states,states)'; % pam6transitions =
|
||||
% [-5 -5;
|
||||
% -3 -5;
|
||||
% -1 -5; ...
|
||||
|
||||
[~, idx_sym_1] = ismember(pam6transitions(:,1), states);
|
||||
[~, idx_sym_2] = ismember(pam6transitions(:,2), states);
|
||||
pam6ind = [idx_sym_1, idx_sym_2];
|
||||
|
||||
numPairs = floor(size(LLP,2)/2);
|
||||
LLR_exact = zeros(numPairs,5);
|
||||
LLR_maxlogmap = zeros(numPairs,5);
|
||||
|
||||
for k = 1:numPairs
|
||||
symbol1 = 2*k-1;
|
||||
symbol2 = 2*k;
|
||||
|
||||
LLP1 = LLP(:,symbol1);
|
||||
LLP2 = LLP(:,symbol2);
|
||||
prob1 = state_prob(:,symbol1);
|
||||
prob2 = state_prob(:,symbol2);
|
||||
|
||||
% All 36 Combinations: M = LLP Symbol 1 + LLP Symbol 2
|
||||
Mij = LLP1(pam6ind(:,1)) + LLP2(pam6ind(:,2));
|
||||
pij = prob1(pam6ind(:,1)) .* prob2(pam6ind(:,2));
|
||||
|
||||
% for each of the 5 bits sum exact-probs or max-log
|
||||
for b = 1:num_bits
|
||||
idx_sym_1 = bit_mapping(:,b)==1;
|
||||
idx_bit_1 = bit_mapping(:,b)==0;
|
||||
|
||||
% exact LLR from probabilities
|
||||
P1 = sum(pij(idx_sym_1)); %prob that bit == 1
|
||||
P0 = sum(pij(idx_bit_1));
|
||||
LLR_exact(k,b) = log(P1./P0); %ratio by multiplication
|
||||
|
||||
% max-log:
|
||||
LLR_maxlogmap(k,b) = max( Mij(idx_sym_1) ) - max( Mij(idx_bit_1) ); % ratio by subtraction
|
||||
end
|
||||
end
|
||||
|
||||
% GMI calc includes the Tx-bitstream
|
||||
tx_bits_pam6_reshaped = reshape(tx_bits',5,[])'; % N x 5
|
||||
MI = zeros(1, num_bits);
|
||||
for k = 1:num_bits
|
||||
|
||||
idx_bit_1 = (tx_bits_pam6_reshaped(:,k) == 0); %wo sind die 1en
|
||||
idx_sym_1 = (tx_bits_pam6_reshaped(:,k) == 1); %wo sind die 0en
|
||||
|
||||
%LLR's for all actually transmitted ones or zeros
|
||||
llr0 = LLR_exact(idx_bit_1,k);
|
||||
llr1 = LLR_exact(idx_sym_1,k);
|
||||
|
||||
% Calculate mutual information for bit position k
|
||||
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
|
||||
|
||||
GMI = sum(MI); % Total mutual information per symbol
|
||||
GMI = GMI/2; % GMI per single symbol not per two symbols
|
||||
|
||||
else
|
||||
|
||||
% 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).showBitMapping;
|
||||
|
||||
% Initialize LLR storage
|
||||
LLR_maxlogmap = zeros(length(data_in),num_bits);
|
||||
LLR_exact = zeros(length(data_in),num_bits);
|
||||
|
||||
% Compute bit-wise LLRs
|
||||
for bit_idx = 1:num_bits
|
||||
|
||||
% Find indices where bit is 0 and where it is 1
|
||||
idx_bit_0 = bit_mapping(:,bit_idx) == 0;
|
||||
idx_bit_1 = bit_mapping(:,bit_idx) == 1;
|
||||
|
||||
% Sum over log-probabilities
|
||||
% Max-Log approximation uses the single max LLP value
|
||||
% instead of sum over all LLP's
|
||||
LLR_maxlogmap(:,bit_idx) = max(LLP(idx_bit_1,:), [], 1) - max(LLP(idx_bit_0,:), [], 1);
|
||||
|
||||
% Sum probabilities over states for which the bit is 1 and 0, respectively.
|
||||
P0 = sum(state_prob(idx_bit_0, :),1);
|
||||
P1 = sum(state_prob(idx_bit_1, :),1);
|
||||
LLR_exact(:,bit_idx) = log(P1./P0); % N x num_bits
|
||||
|
||||
|
||||
end
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%% CALC NGMI %%%%%
|
||||
|
||||
MI = zeros(1, num_bits);
|
||||
for k = 1:num_bits
|
||||
|
||||
idx_bit_0 = (tx_bits(:,k) == 0); %wo sind die 1en
|
||||
idx_bit_1 = (tx_bits(:,k) == 1); %wo sind die 0en
|
||||
|
||||
%LLR's for all actually transmitted ones or zeros
|
||||
llr0 = LLR_exact(idx_bit_0,k);
|
||||
llr1 = LLR_exact(idx_bit_1,k);
|
||||
|
||||
% mutual information for bit position k
|
||||
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); % assumes equally distributed ones and zeros
|
||||
end
|
||||
|
||||
GMI = sum(MI); % Total bitwise mutual information
|
||||
|
||||
end
|
||||
|
||||
|
||||
if debug
|
||||
%%% DEBUG PLOT LIKELIHOOD RATIOS %%%
|
||||
figure(115);clf
|
||||
subplot(2,1,1)
|
||||
for bit = 1:num_bits
|
||||
hold on;
|
||||
histogram(LLR_exact(:,bit),1000,"DisplayName",sprintf('Actual LLR of Bit Pos %d',bit),'LineStyle','none','FaceAlpha',0.4);
|
||||
end
|
||||
legend
|
||||
|
||||
subplot(2,1,2)
|
||||
for bit = 1:num_bits
|
||||
hold on;
|
||||
histogram(LLR_maxlogmap(:,bit),1000,"DisplayName",sprintf('Max Log LLR of Bit Pos %d',bit),'LineStyle','none','FaceAlpha',0.4);
|
||||
end
|
||||
legend
|
||||
|
||||
if obj.M == 6
|
||||
pairs = reshape(VITERBI_ESTIMATION_SYMBOLS,2,[]).';
|
||||
levels = sort(unique(VITERBI_ESTIMATION_SYMBOLS));
|
||||
isedge = ismember(pairs, [levels(1) levels(end)]);
|
||||
isforbidden = sum(isedge,2)==2;
|
||||
fprintf('Found %d forbidden transitions (even -> odd ; edge -> edge).\n', nnz(isforbidden));
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function [symbols_for_lvl,avg_for_lvl] = showLevelScatter_(~,eq_signal,ref_symbols)
|
||||
|
||||
figure()
|
||||
|
||||
rx_symbols = eq_signal; %./ rms(eq_signal);
|
||||
correct_symbols = ref_symbols;
|
||||
|
||||
% col = cbrewer2('Paired',numel(unique(correct_symbols))*2);
|
||||
col = ...
|
||||
[0.6510 0.8078 0.8902; ...
|
||||
0.1216 0.4706 0.7059; ...
|
||||
0.6980 0.8745 0.5412; ...
|
||||
0.2000 0.6275 0.1725; ...
|
||||
0.9843 0.6039 0.6000; ...
|
||||
0.8902 0.1020 0.1098; ...
|
||||
0.9922 0.7490 0.4353; ...
|
||||
1.0000 0.4980 0; ...
|
||||
0.7922 0.6980 0.8392; ...
|
||||
0.4157 0.2392 0.6039; ...
|
||||
1.0000 1.0000 0.6000; ...
|
||||
0.6941 0.3490 0.1569; ...
|
||||
0.6510 0.8078 0.8902; ...
|
||||
0.1216 0.4706 0.7059; ...
|
||||
0.6980 0.8745 0.5412; ...
|
||||
0.2000 0.6275 0.1725];
|
||||
ccnt = -1;
|
||||
|
||||
levels = unique(correct_symbols);
|
||||
symbols_for_lvl = NaN(numel(levels),length(correct_symbols));
|
||||
start = 1;
|
||||
ende = length(correct_symbols);
|
||||
|
||||
for l = 1:numel(levels)
|
||||
ccnt = ccnt+2;
|
||||
|
||||
level_amplitude = levels(l);
|
||||
|
||||
symbols_for_lvl(l,correct_symbols==level_amplitude) = rx_symbols(correct_symbols==level_amplitude);
|
||||
std_lvl(l) = std(symbols_for_lvl(l,:),'omitnan');
|
||||
xax = 1:length(correct_symbols);
|
||||
|
||||
scatter(xax(start:ende),symbols_for_lvl(l,start:ende),10,'.','MarkerFaceAlpha',0.5,'MarkerEdgeAlpha',0.5,'MarkerEdgeColor',col(ccnt,:));
|
||||
hold on;
|
||||
|
||||
|
||||
end
|
||||
|
||||
std_lvl = round(std_lvl,2);
|
||||
|
||||
ccnt = 0;
|
||||
avg_for_lvl = NaN(numel(levels),length(correct_symbols));
|
||||
% Add the windowed/ smoothed curves
|
||||
for l = 1:numel(levels)
|
||||
ccnt = ccnt+2;
|
||||
level_amplitude = levels(l);
|
||||
|
||||
L = 500;
|
||||
movmean = 1/L .* movsum(rx_symbols(correct_symbols==level_amplitude),[L/2,L/2], 'Endpoints', 'fill');
|
||||
|
||||
avg_for_lvl(l,correct_symbols==level_amplitude) = movmean;
|
||||
|
||||
nanx = isnan(avg_for_lvl(l,:));
|
||||
t = 1:numel(avg_for_lvl(l,:));
|
||||
avg_for_lvl(l,nanx) = interp1(t(~nanx), avg_for_lvl(l,~nanx), t(nanx));
|
||||
|
||||
plot(xax(start:ende),avg_for_lvl(l,start:ende),'Color',col(ccnt,:));
|
||||
|
||||
hold on
|
||||
end
|
||||
|
||||
% yline(levels);
|
||||
xlabel('Samples');
|
||||
ylabel('Amplitude');
|
||||
ylim([-3 3]);
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
|
||||
%%%%% SETTINGS %%%%%%
|
||||
useprbs = 1;
|
||||
M = 8;
|
||||
randkey = 1;
|
||||
fsym = 112e9;
|
||||
viewresults = 0;
|
||||
|
||||
%%%%% Mapping %%%%%
|
||||
M = 6;
|
||||
data = 0:M-1;
|
||||
bitpersymbol = log2(M);
|
||||
|
||||
s = RandStream('twister','Seed',1);
|
||||
bitpattern = randi(s,[0 1], 2^18, 1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
|
||||
bits_tx = Informationsignal(bitpattern);
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
|
||||
pam6transitions = combvec(PAMmapper(M,0).levels,PAMmapper(M,0).levels)';
|
||||
|
||||
pam6bits = PAMmapper(6,0,"eth_style",0).demap(reshape(pam6transitions',[],1)./sqrt(10));
|
||||
symbols_rx = PAMmapper(M,0).map(pam6bits).*sqrt(10);
|
||||
|
||||
pam6bits = reshape(pam6bits',5,[])';
|
||||
|
||||
figure; hold on
|
||||
scatter(pam6transitions(:,1), pam6transitions(:,2), 'x', 'LineWidth', 1);
|
||||
n = size(pam6transitions,1);
|
||||
labels = cellstr(char(pam6bits + '0')); % -> N x 1 cell array of char rows
|
||||
text(pam6transitions(:,1), pam6transitions(:,2), labels, ...
|
||||
'HorizontalAlignment','left', 'VerticalAlignment','bottom');
|
||||
|
||||
|
||||
|
||||
bits_rx = PAMmapper(M,0).demap(symbols);
|
||||
|
||||
[~,error_num,ber,error_pos] = calc_ber(bits_tx.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
|
||||
PAMmapper(8,0).showBitMapping
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
db = DBHandler("type","mysql");
|
||||
|
||||
db.tableNames
|
||||
currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss');
|
||||
newRun = db.tables.Runs;
|
||||
newRun.run_id = NaN;
|
||||
newRun.loop_id = 82;
|
||||
newRun.date_of_run = datetime(currentTime, 'InputFormat', 'yyyyMMdd_HHmmss');
|
||||
newRun.tx_bits_path = 'pathtohell';
|
||||
newRun.tx_symbols_path = 'pathtohell2';
|
||||
newRun.rx_sync_path = ""; % Leave empty for now
|
||||
newRun.rx_raw_path = 'pathtohell4';
|
||||
newRun.filename = 'filenametohell';
|
||||
newRun.tx_signal_path = 'pathtohell';
|
||||
|
||||
run_id = db.appendToTable('Runs', newRun);
|
||||
@@ -1,68 +0,0 @@
|
||||
|
||||
|
||||
M = 4;
|
||||
apply_precode = 1;
|
||||
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
for i = 1:log2(M)
|
||||
N = 2^(17-1); %length of prbs
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
bits = Informationsignal(bitpattern);
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
|
||||
bits_rx = PAMmapper(M,0).demap(symbols);
|
||||
[~,~,ber_direct,~] = calc_ber(bits.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
|
||||
if apply_precode
|
||||
symbols_tx = Duobinary().precode(symbols);
|
||||
else
|
||||
symbols_tx = symbols;
|
||||
end
|
||||
disp(['Tx Sequenz: -- RMS:',sprintf('%.1f',rms(symbols_rx.signal)),' - - Levels -',num2str(numel(unique(symbols_rx.signal)))]);
|
||||
unique(symbols_tx.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
|
||||
show2Dconstellation(symbols_tx,symbols_tx,"displayname",'VNLE Out','fignum',2241);
|
||||
|
||||
|
||||
if apply_precode
|
||||
% Entschiedene Symbole codieren: d_DB(n) = d(n) + d(n-1) (im Fall von PAM4 7 level [0 1 2 3 4 5 6])
|
||||
symbols_db = Duobinary().encode(symbols_tx);
|
||||
|
||||
disp(['DB encoded -- RMS:',sprintf('%.1f',rms(symbols_db.signal)),' - - Levels -',num2str(numel(unique(symbols_db.signal)))]);
|
||||
unique(symbols_db.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
% Entschiedene codierte Symbole decodieren: d_dec(n) = d_DB(n) mod4
|
||||
symbols_rx = Duobinary().decode(symbols_db);
|
||||
else
|
||||
symbols_rx = symbols_tx;
|
||||
end
|
||||
|
||||
% Vergleichen von b(n) und d_dec(n)
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx);
|
||||
disp(['Wieder normal -- RMS:',sprintf('%.1f',rms(symbols_rx.signal)),' - - Levels -',num2str(numel(unique(symbols_rx.signal)))]);
|
||||
unique(symbols_rx.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
|
||||
[~,~,ber,~] = calc_ber(bits.signal,bits_rx.signal,"skip_front",10,"skip_end",10,"returnErrorLocation",1);
|
||||
|
||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
|
||||
figure()
|
||||
subplot(1,2,1)
|
||||
histogram(symbols_tx.signal,100,'Normalization','count')
|
||||
|
||||
subplot(1,2,2)
|
||||
histogram(symbols_db.signal,100,'Normalization','count')
|
||||
@@ -1,139 +0,0 @@
|
||||
useprbs = 1;
|
||||
M = 2;
|
||||
randkey = 1;
|
||||
datarate = 448e9;
|
||||
fsym = round(datarate / log2(M)) ;
|
||||
|
||||
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||
O = 16; %O of prbs
|
||||
N = 2^(O); %length of prbs
|
||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||
bitpattern=[];
|
||||
|
||||
state = struct();
|
||||
|
||||
para = struct();
|
||||
|
||||
if M == 6
|
||||
para.bl = 2^(O-2);
|
||||
para.dimension = 5;
|
||||
else
|
||||
para.bl = 2^(O-1);
|
||||
para.dimension = log2(M); %2.5bits/sym -> 2 bit/sym
|
||||
end
|
||||
|
||||
para.rand = 0;
|
||||
|
||||
para.order = floor(O / log2(M));
|
||||
para.skip =0;
|
||||
para.bruijn = 0;
|
||||
para.reset_prms = 0;
|
||||
para.method = 1;
|
||||
|
||||
data_in = [];
|
||||
global loop;
|
||||
loop = 0;
|
||||
[data_out,state_] = prms(data_in, state, para);
|
||||
loop = 1;
|
||||
[data_out,state_out] = prms(data_in, state_, para);
|
||||
bitpattern = data_out';
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
Tx_bits = Informationsignal(bitpattern);
|
||||
|
||||
%%%%% Duobinary %%%%%%
|
||||
close all
|
||||
Symbols_tx = PAMmapper(M,0,"eth_style",0).map(Tx_bits);
|
||||
Symbols_tx.fs = fsym;
|
||||
|
||||
precode = db_mode.db_precoded;
|
||||
|
||||
%%% precode
|
||||
switch precode
|
||||
case db_mode.db_precoded
|
||||
Symbols_tx = Duobinary().precode(Symbols_tx);
|
||||
case db_mode.db_encoded
|
||||
Symbols_tx = Duobinary().precode(Symbols_tx);
|
||||
Symbols_tx = Duobinary().encode(Symbols_tx);
|
||||
case db_mode.no_db
|
||||
|
||||
end
|
||||
|
||||
for n = 10
|
||||
|
||||
Symbols_rx = Symbols_tx;
|
||||
|
||||
pos = 1;
|
||||
if n~=0
|
||||
for pos = 1:n
|
||||
po = randi(100);
|
||||
a = Symbols_rx.signal(100+pos) == Symbols_tx.signal(100+po);
|
||||
while a == 1
|
||||
po = po+1;
|
||||
po = randi(100);
|
||||
a = Symbols_rx.signal(100+pos) == Symbols_tx.signal(100+po);
|
||||
end
|
||||
Symbols_rx.signal(100+pos) = Symbols_tx.signal(100+po);
|
||||
end
|
||||
end
|
||||
|
||||
error_positions = ~(Symbols_rx.signal == Symbols_tx.signal);
|
||||
error_positions = find(error_positions==1);
|
||||
|
||||
switch precode
|
||||
|
||||
case db_mode.db_precoded
|
||||
Symbols_rx = Duobinary().encode(Symbols_rx);
|
||||
Symbols_rx = Duobinary().decode(Symbols_rx);
|
||||
case db_mode.db_encoded
|
||||
Symbols_rx = Duobinary().decode(Symbols_rx);
|
||||
|
||||
end
|
||||
|
||||
Rx_bits = PAMmapper(M,0).demap(Symbols_rx);
|
||||
|
||||
%%%%% Check BER of Bit Sequence %%%%%%
|
||||
|
||||
[~,error_num(n+1),ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",10,"skip_end",10,"returnErrorLocation",1);
|
||||
|
||||
% disp(['BER: ',sprintf('%.1E',ber),sprintf(' - Num. Err: %.1d',error_num(n+1)-2),' - - PAM-',num2str(M)]);
|
||||
fprintf('n: %d - Num. Err: %.1d \n',n,error_num(n+1));
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
figure(3);
|
||||
clf
|
||||
%sgtitle(['BER: ',num2str(ber),' // Error is at position: ',num2str(error_pos),''])
|
||||
subplot(2,2,1)
|
||||
hold on
|
||||
title('First Bits')
|
||||
stairs(Tx_bits.signal(100:150,1),'LineStyle','-','LineWidth',2,'DisplayName','Tx Bits');
|
||||
stairs(Rx_bits.signal(100:150,1),'LineWidth',2,'DisplayName','Rx Bits','LineStyle',':')
|
||||
legend
|
||||
|
||||
subplot(2,2,2)
|
||||
title('Last Bits')
|
||||
hold on
|
||||
stairs(Tx_bits.signal(end-50:end,1),'LineStyle','-','LineWidth',2,'DisplayName','Tx Bits');
|
||||
stairs(Rx_bits.signal(end-50:end,1),'LineWidth',2,'DisplayName','Rx Bits','LineStyle',':')
|
||||
legend
|
||||
|
||||
subplot(2,2,3)
|
||||
hold on
|
||||
title('First Symbols Compare')
|
||||
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle','-')
|
||||
stairs(Symbols_rx.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
||||
legend
|
||||
|
||||
subplot(2,2,4)
|
||||
hold on
|
||||
title('Last Symbols Compare')
|
||||
stairs(Symbols_tx.signal(end-50:end,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle','-')
|
||||
stairs(Symbols_rx.signal(end-50:end,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
||||
legend
|
||||
@@ -1,32 +0,0 @@
|
||||
function output = exampleFunction(varargin)
|
||||
|
||||
% Default values for optional variables
|
||||
var_1 = 1;
|
||||
var_2 = 2;
|
||||
var_4 = 10; % Default value for var4
|
||||
var_5 = 20; % Default value for var5
|
||||
var_6 = 30; % Default value for var6
|
||||
var_7 = 40; % Default value for var7
|
||||
var_8 = 50; % Default value for var8
|
||||
var_9 = 60; % Default value for var9
|
||||
var_10 = 70; % Default value for var10
|
||||
|
||||
% Parse optional input arguments
|
||||
if ~isempty(varargin)
|
||||
var_s = varargin{1};
|
||||
if isstruct(var_s)
|
||||
fields = fieldnames(var_s);
|
||||
for i = 1:numel(fields)
|
||||
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
|
||||
fprintf("%s <-- %.2f \n",fields{i},var_s.(fields{i}))
|
||||
end
|
||||
else
|
||||
error('Optional variables should be passed as a struct.');
|
||||
end
|
||||
end
|
||||
|
||||
output = var_4+var_10+var_9+var_8+var_1+var_2;
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
%% GPU vs CPU Comparison Test for DP_Fiber
|
||||
% This script runs the fiber simulation with and without GPU acceleration
|
||||
% and compares the numerical results.
|
||||
|
||||
% clear; clc;
|
||||
|
||||
%% Setup (same as gpu_processing_dpfiber.m but simplified)
|
||||
s.wavelengthplan = calcWavelengthPlan(4, 400e9, 1310);
|
||||
link_length = 10;
|
||||
s.pmd = 0.1;
|
||||
s.gamma = 0.0023;
|
||||
|
||||
s.M = 4;
|
||||
fsym = 112e9;
|
||||
fdac = 2*fsym;
|
||||
fadc = 120000000000;
|
||||
s.random_key = 1;
|
||||
|
||||
% Laser / Modulator
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 4.6;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
laser_linewidth = 0e6;
|
||||
|
||||
% DB Stuff
|
||||
duob_mode = db_mode.no_db;
|
||||
|
||||
rcalpha = 0.05;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
s.chirpalpha = 0;
|
||||
s.p_launch = 3;
|
||||
s.p = "co";
|
||||
|
||||
N = numel(s.wavelengthplan);
|
||||
|
||||
switch s.p
|
||||
case "co"
|
||||
pol_rot = 100.*ones(1,N);
|
||||
d_local = 0;
|
||||
case "pair"
|
||||
pol_rot = repmat([100,100,0,0],1,N/4);
|
||||
d_local = 0;
|
||||
case "alt"
|
||||
pol_rot = repmat([100,0,100,0],1,N/4);
|
||||
d_local = 0;
|
||||
case "seg"
|
||||
pol_rot = 100.*ones(1,N);
|
||||
d_local = 3;
|
||||
otherwise
|
||||
error('Unknown fwm_mitigation_technique: %s', string(s.p));
|
||||
end
|
||||
|
||||
f_plan = physconst('lightspeed')./(s.wavelengthplan.*1e-9);
|
||||
margin = 5e12;
|
||||
f_span = (max(f_plan)+margin)-(min(f_plan)-margin);
|
||||
f_nyq = f_span/2;
|
||||
|
||||
kover = 4;
|
||||
upsample_required = f_nyq./(fdac*kover/2);
|
||||
upsample_pow = 2^nextpow2(upsample_required);
|
||||
|
||||
s.f_opt = fdac*kover*upsample_pow;
|
||||
s.f_opt_nyq = s.f_opt/2;
|
||||
|
||||
%% TX per channel
|
||||
for l = 1:N
|
||||
[Digi_sig,Symbols{l},Tx_bits{l}] = PAMsource( ...
|
||||
"fsym",fsym,"M",s.M,"order",15,"useprbs",0, ...
|
||||
"fs_out",fdac, ...
|
||||
"applyclipping",0,"clipfactor",1.5, ...
|
||||
"applypulseform",1,"pulseformer",Pform, ...
|
||||
"randkey",s.random_key+l, ...
|
||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode ...
|
||||
).process();
|
||||
|
||||
Lp_awg = Filter('filtdegree',3,"f_cutoff",56e9,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.gaussian,"active",true);
|
||||
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",1,"kover",kover, ...
|
||||
"bit_resolution",6,"upsampling_method","samplehold","precomp_sinc_rolloff",0, ...
|
||||
"H_lpf",Lp_awg,"dac_max",0.6,"dac_min",-0.6).process(Digi_sig);
|
||||
|
||||
clear Digi_sig
|
||||
|
||||
El_sig = El_sig.normalize("mode","oneone");
|
||||
scaling = 0.6*(u_pi/2-abs(vbias-u_pi/2));
|
||||
El_sig = El_sig .* scaling;
|
||||
|
||||
Eml_out = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs, ...
|
||||
"lambda",s.wavelengthplan(l),"bias",vbias,"u_pi",u_pi, ...
|
||||
"linewidth",laser_linewidth,"randomkey",s.random_key+l,"alpha",s.chirpalpha).process(El_sig);
|
||||
|
||||
clear El_sig
|
||||
|
||||
signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",pol_rot(l)).process(Eml_out);
|
||||
|
||||
clear Eml_out Lp_awg
|
||||
end
|
||||
|
||||
disp('Signal generated for all channels.');
|
||||
|
||||
%% WDM mux + launch
|
||||
Opt_sig_wdm = Optical_Multiplex("fs_in",fdac*kover,"fs_out",upsample_pow*fdac*kover, ...
|
||||
"lambda_center",1310,"random_key",0,"filtype",1,"B",120e9).process(signal_cell);
|
||||
|
||||
Opt_sig_wdm = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",s.p_launch+10*log10(N)).process(Opt_sig_wdm);
|
||||
|
||||
% Save input for both runs
|
||||
Opt_sig_input = Opt_sig_wdm;
|
||||
|
||||
segment_length = 1;
|
||||
nSegments = link_length/segment_length;
|
||||
if abs(nSegments - round(nSegments)) > 1e-12
|
||||
error('fiber_length_km=%g must be an integer multiple of segment_length=%g km.', link_length, segment_length);
|
||||
end
|
||||
nSegments = round(nSegments);
|
||||
|
||||
zdw = 1310;
|
||||
randomize_D = true;
|
||||
|
||||
if nSegments > 0
|
||||
Dvec = getDispersionVector(nSegments, d_local, zdw, randomize_D, s.random_key);
|
||||
else
|
||||
Dvec = [];
|
||||
end
|
||||
|
||||
%% Run WITHOUT GPU
|
||||
fprintf('\n========== Running WITHOUT GPU (CPU) ==========\n');
|
||||
Opt_sig_cpu = Opt_sig_input;
|
||||
|
||||
tic;
|
||||
for seg = 1:nSegments
|
||||
fprintf('CPU Segment %d/%d \n',seg, nSegments);
|
||||
|
||||
Opt_sig_cpu = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07, ...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0, ...
|
||||
"gamma",s.gamma,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01, ...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1,"useGPU",false).process(Opt_sig_cpu);
|
||||
end
|
||||
time_cpu = toc;
|
||||
fprintf('CPU Time: %.3f seconds\n', time_cpu);
|
||||
|
||||
%% Run WITH GPU (Double Precision)
|
||||
fprintf('\n========== Running WITH GPU (Double Precision) ==========\n');
|
||||
Opt_sig_gpu_double = Opt_sig_input;
|
||||
|
||||
tic;
|
||||
for seg = 1:nSegments
|
||||
fprintf('GPU-Double Segment %d/%d \n',seg, nSegments);
|
||||
|
||||
Opt_sig_gpu_double = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07, ...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0, ...
|
||||
"gamma",s.gamma,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01, ...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1,"useGPU",true,"useSingle",false).process(Opt_sig_gpu_double);
|
||||
end
|
||||
time_gpu_double = toc;
|
||||
fprintf('GPU Double Time: %.3f seconds\n', time_gpu_double);
|
||||
|
||||
%% Run WITH GPU (Single Precision)
|
||||
fprintf('\n========== Running WITH GPU (Single Precision) ==========\n');
|
||||
Opt_sig_gpu_single = Opt_sig_input;
|
||||
|
||||
tic;
|
||||
for seg = 1:nSegments
|
||||
fprintf('GPU-Single Segment %d/%d \n',seg, nSegments);
|
||||
|
||||
Opt_sig_gpu_single = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07, ...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0, ...
|
||||
"gamma",s.gamma,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01, ...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1,"useGPU",true,"useSingle",true).process(Opt_sig_gpu_single);
|
||||
end
|
||||
time_gpu_single = toc;
|
||||
fprintf('GPU Single Time: %.3f seconds\n', time_gpu_single);
|
||||
|
||||
%% Compare Results
|
||||
fprintf('\n========== Numerical Comparison ==========\n');
|
||||
|
||||
sig_cpu = Opt_sig_cpu.signal;
|
||||
sig_gpu_double = Opt_sig_gpu_double.signal;
|
||||
sig_gpu_single = Opt_sig_gpu_single.signal;
|
||||
|
||||
% Check dimensions
|
||||
fprintf('CPU signal size: [%d x %d]\n', size(sig_cpu,1), size(sig_cpu,2));
|
||||
fprintf('GPU Double signal size: [%d x %d]\n', size(sig_gpu_double,1), size(sig_gpu_double,2));
|
||||
fprintf('GPU Single signal size: [%d x %d]\n', size(sig_gpu_single,1), size(sig_gpu_single,2));
|
||||
|
||||
% CPU vs GPU Double
|
||||
fprintf('\n--- CPU vs GPU Double ---\n');
|
||||
diff_cpu_double = abs(sig_cpu - sig_gpu_double);
|
||||
max_diff_cpu_double = max(diff_cpu_double(:));
|
||||
mean_diff_cpu_double = mean(diff_cpu_double(:));
|
||||
rel_diff_cpu_double = max_diff_cpu_double / max(abs(sig_cpu(:)));
|
||||
fprintf('Max absolute difference: %.6e\n', max_diff_cpu_double);
|
||||
fprintf('Mean absolute difference: %.6e\n', mean_diff_cpu_double);
|
||||
fprintf('Max relative difference: %.6e\n', rel_diff_cpu_double);
|
||||
|
||||
% CPU vs GPU Single
|
||||
fprintf('\n--- CPU vs GPU Single ---\n');
|
||||
diff_cpu_single = abs(sig_cpu - sig_gpu_single);
|
||||
max_diff_cpu_single = max(diff_cpu_single(:));
|
||||
mean_diff_cpu_single = mean(diff_cpu_single(:));
|
||||
rel_diff_cpu_single = max_diff_cpu_single / max(abs(sig_cpu(:)));
|
||||
fprintf('Max absolute difference: %.6e\n', max_diff_cpu_single);
|
||||
fprintf('Mean absolute difference: %.6e\n', mean_diff_cpu_single);
|
||||
fprintf('Max relative difference: %.6e\n', rel_diff_cpu_single);
|
||||
|
||||
% GPU Double vs GPU Single
|
||||
fprintf('\n--- GPU Double vs GPU Single ---\n');
|
||||
diff_double_single = abs(sig_gpu_double - sig_gpu_single);
|
||||
max_diff_double_single = max(diff_double_single(:));
|
||||
mean_diff_double_single = mean(diff_double_single(:));
|
||||
rel_diff_double_single = max_diff_double_single / max(abs(sig_gpu_double(:)));
|
||||
fprintf('Max absolute difference: %.6e\n', max_diff_double_single);
|
||||
fprintf('Mean absolute difference: %.6e\n', mean_diff_double_single);
|
||||
fprintf('Max relative difference: %.6e\n', rel_diff_double_single);
|
||||
|
||||
% Check tolerances
|
||||
fprintf('\n--- Tolerance Check ---\n');
|
||||
tol_double = 1e-10;
|
||||
tol_single = 1e-5; % Single precision has ~7 significant digits
|
||||
|
||||
if max_diff_cpu_double < tol_double
|
||||
fprintf('✓ CPU vs GPU Double: EQUIVALENT (diff < %.0e)\n', tol_double);
|
||||
else
|
||||
fprintf('✗ CPU vs GPU Double: DIFFER beyond tolerance (%.0e)\n', tol_double);
|
||||
end
|
||||
|
||||
if max_diff_cpu_single < tol_single
|
||||
fprintf('✓ CPU vs GPU Single: ACCEPTABLE (diff < %.0e)\n', tol_single);
|
||||
else
|
||||
fprintf('⚠ CPU vs GPU Single: Precision loss detected (diff = %.2e, tol = %.0e)\n', max_diff_cpu_single, tol_single);
|
||||
end
|
||||
|
||||
% Performance comparison
|
||||
fprintf('\n========== Performance Summary ==========\n');
|
||||
fprintf('CPU Time: %.3f s\n', time_cpu);
|
||||
fprintf('GPU Double Time: %.3f s\n', time_gpu_double);
|
||||
fprintf('GPU Single Time: %.3f s\n', time_gpu_single);
|
||||
fprintf('\n');
|
||||
fprintf('Speedup (GPU Double vs CPU): %.2fx\n', time_cpu/time_gpu_double);
|
||||
fprintf('Speedup (GPU Single vs CPU): %.2fx\n', time_cpu/time_gpu_single);
|
||||
fprintf('Speedup (GPU Single vs GPU Double): %.2fx\n', time_gpu_double/time_gpu_single);
|
||||
|
||||
%% ========== BER Comparison ==========
|
||||
% Process each fiber output through simplified receiver to check if
|
||||
% single-precision affects actual BER performance
|
||||
|
||||
fprintf('\n========== BER Comparison ==========\n');
|
||||
fprintf('Processing signals through receiver chain...\n');
|
||||
|
||||
% Receiver parameters
|
||||
rop = -7; % Received optical power [dBm]
|
||||
len_tr = 4096; % Training length
|
||||
mu_dc = 0.005;
|
||||
mu_ffe = [0.0001 0.0008 0.001];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
% Helper function to process through receiver and get BER
|
||||
function ber = process_receiver(Opt_sig_fib, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop, s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode)
|
||||
|
||||
% Demux single channel
|
||||
Opt_sig_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1, ...
|
||||
"fs_out",fdac*kover,"fs_in",fdac*kover*upsample_pow,"lambda_center",1310).process(Opt_sig_fib);
|
||||
|
||||
% ROP amplifier
|
||||
Opt_sig_rx = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",rop).process(Opt_sig_demux{l});
|
||||
|
||||
% Photodiode
|
||||
PD_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20, ...
|
||||
"nep",1.8e-11,"randomkey",s.random_key+l).process(Opt_sig_rx);
|
||||
|
||||
% Low-pass filter
|
||||
rx_bwl = 100e9;
|
||||
PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.butterworth,"active",true).process(PD_sig);
|
||||
|
||||
% Scope
|
||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",80e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||
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',0,'H_lpf',Lp_scpe).process(PD_sig);
|
||||
|
||||
% Resample to 2 sps
|
||||
Scpe_sig_2sps = Scpe_sig.resample("fs_out",2*fsym);
|
||||
|
||||
% Time sync
|
||||
[~, Scpe_cell, ~, ~] = Scpe_sig_2sps.tsynch("reference", Symbols{l}, "fs_ref", fsym, "debug_plots", 0);
|
||||
Rx_sig = Scpe_cell{1};
|
||||
Rx_sig = Rx_sig.normalize("mode","rms");
|
||||
|
||||
% FFE Equalizer
|
||||
ffe_order = [50, 0, 0];
|
||||
eq_ffe = 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_ffe,s.M,Rx_sig,Symbols{l},Tx_bits{l}, ...
|
||||
"precode_mode",duob_mode, ...
|
||||
'showAnalysis',0, ...
|
||||
"postFFE",[], ...
|
||||
"eth_style_symbol_mapping",0);
|
||||
|
||||
ber = ffe_results.metrics.BER;
|
||||
end
|
||||
|
||||
% Process each mode for channel 1
|
||||
l = 4; % Use first channel for comparison
|
||||
|
||||
fprintf('Processing CPU result...\n');
|
||||
ber_cpu = process_receiver(Opt_sig_cpu, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop, s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode);
|
||||
|
||||
fprintf('Processing GPU Double result...\n');
|
||||
ber_gpu_double = process_receiver(Opt_sig_gpu_double, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop, s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode);
|
||||
|
||||
fprintf('Processing GPU Single result...\n');
|
||||
ber_gpu_single = process_receiver(Opt_sig_gpu_single, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop, s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode);
|
||||
|
||||
% Display BER results
|
||||
fprintf('\n========== BER Results (Channel %d, ROP = %d dBm) ==========\n', l, rop);
|
||||
fprintf('CPU: BER = %.4e\n', ber_cpu);
|
||||
fprintf('GPU Double: BER = %.4e\n', ber_gpu_double);
|
||||
fprintf('GPU Single: BER = %.4e\n', ber_gpu_single);
|
||||
|
||||
fprintf('\n--- BER Comparison ---\n');
|
||||
if ber_cpu == 0 && ber_gpu_double == 0 && ber_gpu_single == 0
|
||||
fprintf('✓ All BERs are zero (no errors detected)\n');
|
||||
else
|
||||
ber_diff_double = abs(ber_cpu - ber_gpu_double);
|
||||
ber_diff_single = abs(ber_cpu - ber_gpu_single);
|
||||
fprintf('|BER_cpu - BER_gpu_double| = %.4e\n', ber_diff_double);
|
||||
fprintf('|BER_cpu - BER_gpu_single| = %.4e\n', ber_diff_single);
|
||||
|
||||
if ber_diff_double < 1e-6 && ber_diff_single < 1e-6
|
||||
fprintf('✓ BER differences are negligible\n');
|
||||
elseif ber_diff_single > ber_diff_double * 10
|
||||
fprintf('⚠ Single precision shows measurable BER impact\n');
|
||||
else
|
||||
fprintf('✓ BER differences within acceptable range\n');
|
||||
end
|
||||
end
|
||||
|
||||
fprintf('\n========== Test Complete ==========\n');
|
||||
@@ -1,265 +0,0 @@
|
||||
|
||||
|
||||
s.wavelengthplan = calcWavelengthPlan(16, 400e9, 1310);
|
||||
N = numel(s.wavelengthplan);
|
||||
link_length = 10;
|
||||
s.pmd = 0.1;%0.1;
|
||||
s.gamma = 0.0023;
|
||||
|
||||
s.M = 4;
|
||||
fsym = 112e9;
|
||||
fdac = 2*fsym;
|
||||
fadc = 120000000000;
|
||||
s.random_key = 1;
|
||||
|
||||
% Laser / s.Modulator
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 4.6;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
laser_linewidth = 0e6;
|
||||
|
||||
% DB Stuff
|
||||
duob_mode = db_mode.no_db;
|
||||
|
||||
rcalpha = 0.05;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
s.chirpalpha = 0;
|
||||
|
||||
s.p_launch = 3;
|
||||
s.p = "co";
|
||||
|
||||
switch s.p
|
||||
case "co"
|
||||
pol_rot = 100.*ones(1,N);
|
||||
d_local = 0;
|
||||
case "pair"
|
||||
pol_rot = repmat([100,100,0,0],1,N/4);
|
||||
d_local = 0;
|
||||
case "alt"
|
||||
pol_rot = repmat([100,0,100,0],1,N/4);
|
||||
d_local = 0;
|
||||
case "seg"
|
||||
pol_rot = 100.*ones(1,N);
|
||||
d_local = 3;
|
||||
otherwise
|
||||
error('Unknown fwm_mitigation_technique: %s', string(s.p));
|
||||
end
|
||||
|
||||
f_plan = physconst('lightspeed')./(s.wavelengthplan.*1e-9);
|
||||
margin = 25e12; % some THz left and right
|
||||
f_span = (max(f_plan)+margin)-(min(f_plan)-margin);
|
||||
f_nyq = f_span/2;
|
||||
|
||||
kover = 4;
|
||||
upsample_required = f_nyq./(fdac*kover/2);
|
||||
upsample_pow = 2^nextpow2(upsample_required);
|
||||
|
||||
s.f_opt = fdac*kover*upsample_pow;
|
||||
s.f_opt_nyq = s.f_opt/2;
|
||||
|
||||
s.rop = -10:1:0;
|
||||
|
||||
profile on
|
||||
|
||||
%% ---------- TX per channel ----------
|
||||
for l = 1:N
|
||||
|
||||
[Digi_sig,Symbols{l},Tx_bits{l}] = PAMsource( ...
|
||||
"fsym",fsym,"M",s.M,"order",17,"useprbs",0, ...
|
||||
"fs_out",fdac, ...
|
||||
"applyclipping",0,"clipfactor",1.5, ...
|
||||
"applypulseform",1,"pulseformer",Pform, ...
|
||||
"randkey",s.random_key+l, ...
|
||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode ...
|
||||
).process();
|
||||
|
||||
Lp_awg = Filter('filtdegree',3,"f_cutoff",56e9,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.gaussian,"active",true);
|
||||
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",1,"kover",kover, ...
|
||||
"bit_resolution",6,"upsampling_method","samplehold","precomp_sinc_rolloff",0, ...
|
||||
"H_lpf",Lp_awg,"dac_max",0.6,"dac_min",-0.6).process(Digi_sig);
|
||||
|
||||
% Digi_sig not needed after AWG
|
||||
clear Digi_sig
|
||||
|
||||
% Electrical Driver Amplifier
|
||||
El_sig = El_sig.normalize("mode","oneone");
|
||||
scaling = 0.6*(u_pi/2-abs(vbias-u_pi/2));
|
||||
El_sig = El_sig .* scaling;
|
||||
|
||||
% E/O Conversion
|
||||
Eml_out = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs, ...
|
||||
"lambda",s.wavelengthplan(l),"bias",vbias,"u_pi",u_pi, ...
|
||||
"linewidth",laser_linewidth,"randomkey",s.random_key+l,"alpha",s.chirpalpha).process(El_sig);
|
||||
|
||||
% El_sig not needed after EML
|
||||
clear El_sig
|
||||
|
||||
signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",pol_rot(l)).process(Eml_out);
|
||||
|
||||
% Eml_out not needed after pol controller
|
||||
clear Eml_out Lp_awg
|
||||
end
|
||||
|
||||
disp('Signal generated for all channels.');
|
||||
|
||||
%% ---------- WDM mux + launch ----------
|
||||
Opt_sig_wdm = Optical_Multiplex("fs_in",fdac*kover,"fs_out",upsample_pow*fdac*kover, ...
|
||||
"lambda_center",1310,"random_key",0,"filtype",1,"B",120e9).process(signal_cell);
|
||||
|
||||
Opt_sig_wdm.spectrum();
|
||||
|
||||
Opt_sig_wdm = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",s.p_launch+10*log10(N)).process(Opt_sig_wdm);
|
||||
|
||||
Opt_sig_wdm_fib = Opt_sig_wdm;
|
||||
|
||||
segment_length = 1;
|
||||
nSegments = link_length/segment_length;
|
||||
if abs(nSegments - round(nSegments)) > 1e-12
|
||||
error('fiber_length_km=%g must be an integer multiple of segment_length=%g km.', link_length, segment_length);
|
||||
end
|
||||
nSegments = round(nSegments);
|
||||
|
||||
zdw = 1310;
|
||||
randomize_D = true;
|
||||
|
||||
% Guard for 0 km: avoid calling getDispersionVector(0,...) if it doesn't support it
|
||||
if nSegments > 0
|
||||
Dvec = getDispersionVector(nSegments, d_local, zdw, randomize_D, s.random_key);
|
||||
else
|
||||
Dvec = [];
|
||||
end
|
||||
|
||||
for seg = 1:nSegments
|
||||
|
||||
fprintf('Segment %d/%d \n',seg, nSegments);
|
||||
|
||||
Opt_sig_wdm_fib = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07, ...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0, ...
|
||||
"gamma",s.gamma,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01, ...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1,"useGPU",true,"useSingle",1).process(Opt_sig_wdm_fib);
|
||||
|
||||
end
|
||||
|
||||
profile off
|
||||
profile viewer
|
||||
|
||||
Opt_sig_wdm_fib.spectrum();
|
||||
|
||||
%% ========== BER Evaluation ==========
|
||||
fprintf('\n========== BER Evaluation ==========\n');
|
||||
fprintf('Processing signals through receiver chain...\n');
|
||||
|
||||
% Receiver parameters
|
||||
len_tr = 4096; % Training length
|
||||
mu_dc = 0.005;
|
||||
mu_ffe = [0.0001 0.0008 0.001];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
% Helper function to process through receiver and get BER
|
||||
function ber = process_receiver(Opt_sig_fib, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop, s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode)
|
||||
|
||||
% Demux single channel
|
||||
Opt_sig_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1, ...
|
||||
"fs_out",fdac*kover,"fs_in",fdac*kover*upsample_pow,"lambda_center",1310).process(Opt_sig_fib);
|
||||
|
||||
% ROP amplifier
|
||||
Opt_sig_rx = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power", ...
|
||||
"amplification_db",rop).process(Opt_sig_demux{l});
|
||||
|
||||
% Photodiode
|
||||
PD_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20, ...
|
||||
"nep",1.8e-11,"randomkey",s.random_key+l).process(Opt_sig_rx);
|
||||
|
||||
% Low-pass filter
|
||||
rx_bwl = 100e9;
|
||||
PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover, ...
|
||||
"filterType",filtertypes.butterworth,"active",true).process(PD_sig);
|
||||
|
||||
% Scope
|
||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",80e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||
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',0,'H_lpf',Lp_scpe).process(PD_sig);
|
||||
|
||||
% Resample to 2 sps
|
||||
Scpe_sig_2sps = Scpe_sig.resample("fs_out",2*fsym);
|
||||
|
||||
% Time sync
|
||||
[~, Scpe_cell, ~, ~] = Scpe_sig_2sps.tsynch("reference", Symbols{l}, "fs_ref", fsym, "debug_plots", 0);
|
||||
Rx_sig = Scpe_cell{1};
|
||||
Rx_sig = Rx_sig.normalize("mode","rms");
|
||||
|
||||
% FFE Equalizer
|
||||
ffe_order = [50, 0, 0];
|
||||
eq_ffe = 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);
|
||||
eq_ffe = FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",6.624e-05,"mu_tr",0.058136,"order",50,"sps",2,"decide",0, "adaption",adaption_method.nlms,"dd_mode",1);
|
||||
|
||||
ffe_results = ffe(eq_ffe,s.M,Rx_sig,Symbols{l},Tx_bits{l}, ...
|
||||
"precode_mode",duob_mode, ...
|
||||
'showAnalysis',0, ...
|
||||
"postFFE",[], ...
|
||||
"eth_style_symbol_mapping",0);
|
||||
|
||||
ber = ffe_results.metrics.BER;
|
||||
end
|
||||
|
||||
% Process each ROP value for selected channels using parfor
|
||||
ber_results = zeros(length(s.rop), N);
|
||||
|
||||
% Flatten loop for parfor: iterate over all (ROP, channel) combinations
|
||||
num_rop = length(s.rop);
|
||||
rop_vals = s.rop;
|
||||
ber_flat = zeros(num_rop * N, 1);
|
||||
|
||||
parfor idx = 1:(num_rop * N)
|
||||
% Convert linear index to (ri, l) subscripts
|
||||
ri = ceil(idx / N);
|
||||
l = mod(idx - 1, N) + 1;
|
||||
|
||||
fprintf('ROP %d dBm, Channel %d/%d\n', rop_vals(ri), l, N);
|
||||
ber_flat(idx) = process_receiver(Opt_sig_wdm_fib, l, Symbols, Tx_bits, ...
|
||||
fdac, kover, upsample_pow, fsym, fadc, rop_vals(ri), s, len_tr, mu_dc, mu_ffe, mu_dfe, duob_mode);
|
||||
end
|
||||
|
||||
% Reshape back to [num_rop × N] matrix
|
||||
ber_results = reshape(ber_flat, [N, num_rop]).';
|
||||
|
||||
|
||||
%% Display BER Results
|
||||
fprintf('\n========== BER Results ==========\n');
|
||||
fprintf('ROP [dBm] | ');
|
||||
for l = 1:N
|
||||
fprintf('Ch%d | ', l);
|
||||
end
|
||||
fprintf('\n');
|
||||
|
||||
for ri = 1:length(s.rop)
|
||||
fprintf('%8d | ', s.rop(ri));
|
||||
for l = 1:N
|
||||
fprintf('%.2e | ', ber_results(ri, l));
|
||||
end
|
||||
fprintf('\n');
|
||||
end
|
||||
|
||||
% Plot BER vs ROP
|
||||
figure;
|
||||
semilogy(s.rop, mean(ber_results, 2), '-o', 'LineWidth', 2);
|
||||
hold on;
|
||||
for l = 1:N
|
||||
semilogy(s.rop, ber_results(:, l), '--', 'LineWidth', 1);
|
||||
end
|
||||
hold off;
|
||||
xlabel('ROP [dBm]');
|
||||
ylabel('BER');
|
||||
title('BER vs Received Optical Power (GPU Single Precision)');
|
||||
legend(['Mean', arrayfun(@(x) sprintf('Ch%d', x), 1:N, 'UniformOutput', false)]);
|
||||
grid on;
|
||||
|
||||
fprintf('\n========== Test Complete ==========\n');
|
||||
@@ -1,70 +0,0 @@
|
||||
% 1. Setup Data OUTSIDE the timer
|
||||
d = gpuDevice;
|
||||
N = 10000;
|
||||
|
||||
fprintf('Preparing data...\n');
|
||||
A_cpu_double = rand(N, N); % Create double on CPU
|
||||
A_cpu_single = single(A_cpu_double); % Create single on CPU
|
||||
|
||||
% Warmup run (wakes up the GPU from idle state)
|
||||
A_warm = gpuArray.rand(1000, 1000, 'single');
|
||||
B_warm = A_warm * A_warm;
|
||||
wait(d);
|
||||
|
||||
fprintf('------------------------------------------------\n');
|
||||
|
||||
% TEST 1: Double Precision (The "Slow" way)
|
||||
% We move data to GPU first so we only measure calculation time
|
||||
A_gpu_double = gpuArray(A_cpu_double);
|
||||
wait(d); % Ensure transfer is done before starting timer
|
||||
|
||||
fprintf('Running DOUBLE precision test... ');
|
||||
tic;
|
||||
B_gpu = A_gpu_double * A_gpu_double;
|
||||
wait(d); % FORCE MATLAB TO WAIT FOR GPU
|
||||
time_double = toc;
|
||||
fprintf('Done.\n');
|
||||
fprintf('Double Precision Time: %.4f seconds\n', time_double);
|
||||
|
||||
% TEST 2: Single Precision (The "Fast" way)
|
||||
A_gpu_single = gpuArray(A_cpu_single);
|
||||
wait(d); % Ensure transfer is done
|
||||
|
||||
fprintf('Running SINGLE precision test... ');
|
||||
tic;
|
||||
B_gpu = A_gpu_single * A_gpu_single;
|
||||
wait(d); % FORCE MATLAB TO WAIT FOR GPU
|
||||
time_single = toc;
|
||||
fprintf('Done.\n');
|
||||
fprintf('Single Precision Time: %.4f seconds\n', time_single);
|
||||
|
||||
% Calculate Speedup
|
||||
fprintf('------------------------------------------------\n');
|
||||
fprintf('Speedup Factor using single precision: %.2fx\n', time_double / time_single);
|
||||
|
||||
%
|
||||
% Create 10,000 small matrices (10x10) stacked in a 3D array
|
||||
A_stack = gpuArray.rand(10, 10, 10000, 'single');
|
||||
B_stack = gpuArray.rand(10, 10, 10000, 'single');
|
||||
|
||||
% BAD: Looping (GPU overhead kills you)
|
||||
tic;
|
||||
for i=1:10000
|
||||
C(:,:,i) = A_stack(:,:,i) * B_stack(:,:,i);
|
||||
end
|
||||
wait(d);
|
||||
loop_time = toc;
|
||||
|
||||
% GOOD: Pagefun (Executes all 10,000 mults simultaneously)
|
||||
tic;
|
||||
C_stack = pagefun(@mtimes, A_stack, B_stack);
|
||||
wait(d);
|
||||
pagefun_time = toc;
|
||||
|
||||
fprintf('------------------------------------------------\n');
|
||||
fprintf('Speedup Factor using pagefun: %.2fx\n', loop_time / pagefun_time);
|
||||
|
||||
|
||||
fprintf('Total VRAM: %.2f GB\n', d.TotalMemory / 1e9);
|
||||
fprintf('Available VRAM: %.2f GB\n', d.AvailableMemory / 1e9);
|
||||
fprintf('Usage: %.1f%%\n', 100 * (1 - d.AvailableMemory / d.TotalMemory));
|
||||
@@ -1,47 +0,0 @@
|
||||
x = -10:2:25; % Input power [dBm]
|
||||
|
||||
y1 = 1e-5 * 10.^(0.12*x); % Dispersion-only
|
||||
y2 = 1e0 ./ (1 + exp(-0.4*(x-12))); % NLPN
|
||||
y3 = 1e-6 * 10.^(0.45*x); % RP on gamma
|
||||
y4 = 1e-2 * 10.^(0.18*(x-8)); % RP on beta2
|
||||
|
||||
cmap = WesPalette.AsteroidCity1.rgb(4);
|
||||
cmap = linspecer(4);
|
||||
figure1=figure(202998);clf;hold on
|
||||
lw = 0.8; ms = 3;
|
||||
plot(x,y1,'LineWidth',lw,'Color',cmap(1,:),'Marker','o','MarkerEdgeColor',cmap(1,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||
plot(x,y2,'LineWidth',lw,'Color',cmap(2,:),'Marker','square','MarkerEdgeColor',cmap(2,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||
plot(x,y3,'LineWidth',lw,'Color',cmap(3,:),'Marker','o','MarkerEdgeColor',cmap(3,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||
plot(x,y4,'LineWidth',lw,'Color',cmap(4,:),'Marker','o','MarkerEdgeColor',cmap(4,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||
yline(3.8e-3,'HandleVisibility','off')
|
||||
|
||||
grid on
|
||||
xlabel('Input power [dBm]')
|
||||
ylabel('NSD ($\%$)')
|
||||
legend({'Dispersion','NLPN','RP','RP on $\beta_2$'}, ...
|
||||
'Location','best')
|
||||
|
||||
grid off
|
||||
set(gca,'MinorGridLineWidth',0.5);
|
||||
set(gca,'GridLineWidth',0.5,'GridLineStyle','--','GridColor',[0.9,0.9,0.9]);
|
||||
|
||||
set(gca,'FontSize',12,'YScale','log');
|
||||
ylim([1e-6 1e3])
|
||||
xlim([-10 23])
|
||||
|
||||
|
||||
|
||||
fig_path = 'C:\Users\Silas\Documents\Dissertation\00_Examples\tikz\textfig.tikz';
|
||||
matlab2tikz(fig_path, ...
|
||||
'width','\fwidth', ...
|
||||
'height','\fheight', ...
|
||||
'showInfo',false, ...
|
||||
'extraAxisOptions',{ ...
|
||||
'legend style={font=\footnotesize}', ...
|
||||
'xlabel style={font=\color{white!15!black},font=\small},',...
|
||||
'ylabel style={font=\color{white!15!black},font=\small},',...
|
||||
'legend columns=1', ...
|
||||
'every axis/.append style={font=\scriptsize}',...
|
||||
'legend columns=2',...
|
||||
'legend style={at={(0.02,0.98)},font=\footnotesize,draw=black!60,rounded corners=2pt,inner sep=1pt,fill=white,column sep=6pt,anchor= north west}',...
|
||||
});
|
||||
@@ -1,118 +0,0 @@
|
||||
|
||||
|
||||
%%%%% SETTINGS %%%%%%
|
||||
useprbs = 1;
|
||||
M = 8;
|
||||
randkey = 1;
|
||||
fsym = 112e9;
|
||||
viewresults = 0;
|
||||
|
||||
%%%%% Mapping %%%%%
|
||||
M = 8;
|
||||
data = 0:M-1;
|
||||
bitpersymbol = log2(M);
|
||||
|
||||
%Bits
|
||||
bits = int2bit(data,bitpersymbol, true);
|
||||
|
||||
%Integers
|
||||
ints = bit2int(bits,bitpersymbol, true);
|
||||
|
||||
Tx_bits = Informationsignal(bits');
|
||||
Digi_Mod = PAMmapper(M,0);
|
||||
Symbols = Digi_Mod.map(Tx_bits);
|
||||
moveitgray = Symbols.signal;
|
||||
|
||||
%Gray Symbol Mapping
|
||||
matlabgray = pammod(ints,M,0,'gray');
|
||||
scaling_factor = rms(unique(matlabgray));
|
||||
matlabgray = matlabgray ./ scaling_factor;
|
||||
|
||||
|
||||
%Demod
|
||||
moveitgray = moveitgray.* scaling_factor;
|
||||
matlabgray = matlabgray .* scaling_factor;
|
||||
ints_demap = pamdemod(matlabgray,M,0,'gray');
|
||||
|
||||
bits_demap = int2bit(ints_demap,bitpersymbol, true);
|
||||
|
||||
% for i = 1:M
|
||||
% fprintf('%d , %d , %d --> %d \n',bits(1,i),bits(2,i),bits(3,i),matlabgray(i));
|
||||
% end
|
||||
%
|
||||
% for i = 1:M
|
||||
% fprintf('%d , %d , %d --> %d \n',bits(1,i),bits(2,i),bits(3,i),moveitgray(i));
|
||||
% end
|
||||
|
||||
scatterplot(matlabgray,1,0,'b*');
|
||||
for k = 1:M
|
||||
text(real(matlabgray(k)),imag(matlabgray(k))+0.6,num2str(ints_demap(k)),"Color",[1 1 1]);
|
||||
|
||||
text(real(matlabgray(k)),imag(matlabgray(k))-1.6,num2str(bits(:,k)),"Color",'blue');
|
||||
text(real(moveitgray(k)),imag(moveitgray(k))-3,num2str(bits(:,k)),"Color",'green');
|
||||
end
|
||||
axis([-M M -3 2])
|
||||
|
||||
|
||||
symbols = bit2int(bitGroups',bitpersymbol, true);
|
||||
|
||||
|
||||
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||
O = 10; %order of prbs
|
||||
N = 2^(O-1); %length of prbs
|
||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||
bitpattern=[];
|
||||
if useprbs
|
||||
for i = 1:log2(M)
|
||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||
end
|
||||
else
|
||||
s = RandStream('twister','Seed',randkey);
|
||||
for i = 1:log2(M)
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
end
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern,[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
Tx_bits = Informationsignal(bitpattern);
|
||||
|
||||
%%%%% ACTUAL TEST: Back to Back Mapping: Bits -> Symbols and Symbols -> Bits %%%%%%
|
||||
|
||||
Digi_Mod = PAMmapper(M,0);
|
||||
|
||||
symbols = bitMapper(bitpattern, M, 'PAM');
|
||||
|
||||
|
||||
Symbols = Digi_Mod.map(Tx_bits);
|
||||
|
||||
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||
|
||||
|
||||
%%%%% VALIDATION: BER is required to be zero %%%%%%
|
||||
|
||||
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
|
||||
|
||||
%%%%% For User: Show Debug Info and Results %%%%%%
|
||||
|
||||
if viewresults
|
||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
|
||||
|
||||
figure
|
||||
subplot(1,2,1)
|
||||
hold on
|
||||
title('Symbols Out')
|
||||
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols')
|
||||
legend
|
||||
grid
|
||||
subplot(1,2,2)
|
||||
u = unique(Symbols_tx.signal);
|
||||
scatter(0,u,'filled','o','LineWidth',2,'MarkerFaceColor',linspecer(1));
|
||||
grid
|
||||
end
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
%%% Run parameters
|
||||
% TX
|
||||
M = 4;
|
||||
fsym = 32e9;
|
||||
|
||||
apply_pulsef = 1;
|
||||
fdac = 256e9;
|
||||
fadc = 256e9;
|
||||
random_key = 1;
|
||||
|
||||
precomp = 0;
|
||||
db_precode = 0;
|
||||
|
||||
db_encode = 0;
|
||||
|
||||
kover = 16;
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 2.9;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
laser_wavelength = 1293;
|
||||
laser_linewidth = 0;
|
||||
tx_bw_nyquist = 0.8;
|
||||
|
||||
% 1) PRBS Generation
|
||||
O = 18; %order of prbs
|
||||
N = 2^(O-1); %length of prbs
|
||||
|
||||
%%%%% MOVE-IT PRMS %%%%
|
||||
Mi_prms = Moveit_wrapper("prms");
|
||||
if M == 6
|
||||
Mi_prms.para.bl = 2^(O-2);
|
||||
Mi_prms.para.dimension = 5;
|
||||
else
|
||||
Mi_prms.para.bl = 2^(O-1);
|
||||
Mi_prms.para.dimension = log2(M); %2.5bits/sym -> 2 bit/sym
|
||||
end
|
||||
Mi_prms.para.rand = 0;
|
||||
Mi_prms.para.order = floor(O / log2(M));
|
||||
Mi_prms.para.skip =0;
|
||||
Mi_prms.para.bruijn = 0;
|
||||
Mi_prms.para.reset_prms = 0;
|
||||
Mi_prms.para.method = 1;
|
||||
bitpattern = Mi_prms.process([]);
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
bits = Informationsignal(bitpattern.');
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
symbols.fs = fsym;
|
||||
|
||||
symbols.spectrum("displayname",'Symbols','fignum',1);
|
||||
|
||||
|
||||
%% RRC Shaping
|
||||
|
||||
for rcalpha = 0.1:0.2:1
|
||||
% rcalpha = 0.5;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
Digi_sig = Pform.process(symbols);
|
||||
% Digi_sig.spectrum("displayname",'Signal after pluse shaping','fignum',1);
|
||||
Digi_sig.eye(fsym,M,"fignum",0.1*10,"mode",1);
|
||||
end
|
||||
|
||||
%% RRC Matched Filtering
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||
Rx_sig = Pform.process(Digi_sig);
|
||||
Rx_sig.spectrum("displayname",'Signal after matched filter','fignum',1);
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
|
||||
M_format = [2,4,6,8];
|
||||
|
||||
for m = 1:length(M_format)
|
||||
% --- Parameters ---
|
||||
M = M_format(m); % PAM order (e.g., 2,4,8)
|
||||
Nsym = 1e5; % number of symbols
|
||||
h = [1, 0.5]; % Impulse response to remove
|
||||
|
||||
b = log2(M);
|
||||
if M == 6 b = 5; end
|
||||
rng(1);
|
||||
bits_tx = logical(randi([0 1], Nsym, b, 'uint8'));
|
||||
|
||||
tx_symbols = pammap(bits_tx,M);
|
||||
|
||||
if M == 6
|
||||
states = unique(tx_symbols);
|
||||
pam6transitions = combvec(states',states')'; % pam6transitions =
|
||||
bitmapping = pamdemap(reshape(pam6transitions',1,[])',M);
|
||||
else
|
||||
bitmapping = pamdemap(unique(tx_symbols),M);
|
||||
end
|
||||
|
||||
scaling = sqrt(sum(unique(tx_symbols).^2)/numel(unique(tx_symbols)));
|
||||
tx_symbols = tx_symbols ./ scaling;
|
||||
|
||||
% apply impulse response to signal
|
||||
y_filt = filter(h, 1, tx_symbols);
|
||||
|
||||
sir = 10:25;
|
||||
for s = 1:length(sir)
|
||||
|
||||
% apply noise
|
||||
y = awgn(y_filt,sir(s),"measured",1);
|
||||
|
||||
% apply bcjr
|
||||
BCJR = bcjr_pam("DIR",h,"duobinary_output",0,"M",M,"trellis_states",unique(tx_symbols));
|
||||
[viterbi_estimate,LLR,GMI(m,s)] = BCJR.process(y,tx_symbols,bits_tx,bitmapping);
|
||||
|
||||
% decode LLR's
|
||||
bits_LLR = LLR > 0;
|
||||
|
||||
% demap viterbi symbols sequence
|
||||
rx_symbols = viterbi_estimate .* scaling;
|
||||
bits_rx = pamdemap(rx_symbols,M);
|
||||
|
||||
% BER calc
|
||||
BER_vit(m,s) = nnz(bits_tx ~= bits_LLR) / numel(bits_tx);
|
||||
fprintf('BER LLR = %.2e \n', BER_vit);
|
||||
|
||||
BER_llr(m,s) = nnz(bits_tx ~= bits_rx) / numel(bits_tx);
|
||||
fprintf('BER = %.2e \n', BER_llr);
|
||||
end
|
||||
end
|
||||
|
||||
figure();hold on
|
||||
for m = 1:length(M_format)
|
||||
plot(sir,BER_llr(m,:),'DisplayName',sprintf('PAM %d',M_format(m)))
|
||||
% plot(sir,BER_vit(m,:),'DisplayName',sprintf('PAM %d',M_format(m)),'LineStyle',':','LineWidth',0.1,'HandleVisibility','off');
|
||||
end
|
||||
ylabel('BER');
|
||||
xlabel('SNR')
|
||||
title('BER vs. SNR');
|
||||
set(gca, 'XScale', 'linear', ...
|
||||
'YScale', 'log', ...
|
||||
'TickLabelInterpreter', 'latex', ...
|
||||
'FontSize', 11);
|
||||
|
||||
|
||||
figure();hold on
|
||||
for m = 1:length(M_format)
|
||||
plot(sir,GMI(m,:),'DisplayName',sprintf('GMI PAM %d',M_format(m)))
|
||||
end
|
||||
ylabel('GMI');
|
||||
xlabel('SNR')
|
||||
title('GMI vs. SNR');
|
||||
set(gca, 'XScale', 'linear', ...
|
||||
'YScale', 'linear', ...
|
||||
'TickLabelInterpreter', 'latex', ...
|
||||
'FontSize', 11);
|
||||
|
||||
function symbols = pammap(bits,M)
|
||||
bits = logical(bits);
|
||||
if M == 2
|
||||
symbols = bits;
|
||||
elseif M == 4
|
||||
symbols= 2*bits(:,1) + (bits(:,1)==bits(:,2));
|
||||
symbols=2*symbols-3;
|
||||
|
||||
elseif M == 6
|
||||
|
||||
m = 1;
|
||||
|
||||
if size(bits,2)>size(bits,1)
|
||||
bits = bits'; %vector aufrecht stellen
|
||||
end
|
||||
bits = reshape(bits',1,[])';
|
||||
thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1];
|
||||
% LUT based mapping
|
||||
for k = 1:5:fix(length(bits)/5)*5
|
||||
symbols(m:m+1,1) = thres(bin2dec(int2str(bits(k:k+4)'))+1,:);
|
||||
m = m+2;
|
||||
end
|
||||
|
||||
elseif M == 8
|
||||
x1 = bits(:,1);
|
||||
x2 = (bits(:,1)==bits(:,3));
|
||||
x3 = x2~=bits(:,2);
|
||||
|
||||
symbols = 4*x1 + 2*x2 + x3;
|
||||
symbols=2*symbols-7;
|
||||
end
|
||||
end
|
||||
|
||||
function bits = pamdemap(symbols,M)
|
||||
|
||||
if M == 2
|
||||
thres=0;
|
||||
elseif M == 4
|
||||
thres=[-2,0,2];
|
||||
elseif M == 6
|
||||
thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1];
|
||||
elseif M == 8
|
||||
thres=-6:2:6;
|
||||
end
|
||||
|
||||
if M ~= 6
|
||||
symbols = symbols';
|
||||
a = squeeze(repmat(real(symbols),[1 1 length(thres)])); %Eingangssignal in 3 spalten
|
||||
b = squeeze(repmat(reshape(thres(:).',[1 1 length(thres)]),[1 length(symbols) 1])); %Threshold in 3 Spalten
|
||||
comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3
|
||||
comp_real=repmat(real(symbols),[1 1 length(thres)]) > repmat(reshape(thres(:).',[1 1 length(thres)]),[1 length(symbols) 1]);
|
||||
s1=size(comp_real,1);
|
||||
s2=size(comp_real,2);
|
||||
end
|
||||
|
||||
if M == 2
|
||||
data_out=abs(comp_real(:,:,1));
|
||||
elseif M == 4
|
||||
data_out=[comp_real(:,:,2); ones(s1,s2) - comp_real(:,:,1) + comp_real(:,:,3)];
|
||||
elseif M == 6
|
||||
|
||||
if size(symbols,2) > 1
|
||||
symbols = symbols.';
|
||||
end
|
||||
|
||||
if length(symbols)/2 ~= round(length(symbols)/2)
|
||||
symbols = [symbols;0];
|
||||
end
|
||||
|
||||
m = 1;
|
||||
for n = 1:2:length(symbols)
|
||||
dist = sqrt((symbols(n)-thres(:,1)).^2+(symbols(n+1)-thres(:,2)).^2);
|
||||
[~,dd_idx] = min(dist);
|
||||
% dec_out(n:n+1) = LUT(dd_idx,:);
|
||||
data_out(m:m+4) = bitget(dd_idx-1,5:-1:1);
|
||||
m = m+5;
|
||||
end
|
||||
|
||||
data_out = reshape(data_out',5,[]);
|
||||
|
||||
elseif M == 8
|
||||
data_out=[comp_real(:,:,4);
|
||||
comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7);
|
||||
1-comp_real(:,:,2)+comp_real(:,:,6)];
|
||||
end
|
||||
|
||||
bits = data_out';
|
||||
|
||||
end
|
||||
@@ -1,80 +0,0 @@
|
||||
useprbs = 0;
|
||||
M = 4;
|
||||
randkey = 2;
|
||||
fsym = 112e9;
|
||||
|
||||
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||
O = 18; %order of prbs
|
||||
N = 2^(O-1); %length of prbs
|
||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||
bitpattern=[];
|
||||
|
||||
if useprbs
|
||||
for i = 1:log2(M)
|
||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||
end
|
||||
else
|
||||
s = RandStream('twister','Seed',randkey);
|
||||
for i = 1:log2(M)
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern,[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
Tx_bits = Informationsignal(bitpattern);
|
||||
|
||||
Digi_Mod = PAMmapper(M,0);
|
||||
Symbols_tx = Digi_Mod.map(Tx_bits);
|
||||
Symbols_tx.fs = fsym;
|
||||
|
||||
if 0
|
||||
|
||||
Symbols = Duobinary().precode(Symbols_tx);
|
||||
|
||||
Symbols = Duobinary().encode(Symbols);
|
||||
|
||||
Symbols = MLSE("DIR",[1 1],"duobinary_output",1,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols);
|
||||
|
||||
Symbols = Duobinary().decode(Symbols);
|
||||
|
||||
else
|
||||
cnt = 1;
|
||||
|
||||
Symbols = Symbols_tx;
|
||||
|
||||
coeff = [1,0.5,0.2,0.1];
|
||||
|
||||
Symbols.signal = filter(coeff, 1, Symbols.signal);
|
||||
|
||||
Symbols.spectrum("fignum",129,"displayname",['coeff:',num2str(coeff)]);
|
||||
|
||||
Symbols = MLSE("DIR",coeff,"duobinary_output",0,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols);
|
||||
|
||||
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||
|
||||
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
|
||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
|
||||
end
|
||||
|
||||
|
||||
%
|
||||
figure(494)
|
||||
clf
|
||||
subplot(2,1,1)
|
||||
title('Bits Compare')
|
||||
hold on
|
||||
stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits')
|
||||
stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits');
|
||||
legend
|
||||
subplot(2,1,2)
|
||||
hold on
|
||||
title('Symbols Compare')
|
||||
stairs(Symbols.signal(1:100,1),'LineStyle','-','LineWidth',2,'DisplayName','Rx Symbols');
|
||||
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle',':')
|
||||
legend
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
% datarate = 128e9;
|
||||
M = 4;
|
||||
laser_linewidth = 0;
|
||||
kover = 32;
|
||||
fsym = 170e9;%round(datarate*1e-9 / log2(M))*1e9;
|
||||
fdac = 256e9;
|
||||
|
||||
% 1) PRBS Generation
|
||||
O = 18; %order of prbs
|
||||
N = 2^(O-1); %length of prbs
|
||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||
bitpattern=[];
|
||||
|
||||
for i = 1:log2(M)
|
||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||
end
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern,[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
bits = Informationsignal(bitpattern);
|
||||
|
||||
% 2) Digi modulation -> PAM-M signal
|
||||
digimod_out = PAMmapper(M,0).map(bits);
|
||||
digimod_out.fs = fsym;
|
||||
|
||||
% 3) Pulseform Raised Cosine
|
||||
X = Pulseformer("fsym",fsym,"fdac",fdac,"pulse","rrc","pulselength",16,"rrcalpha",0.01).process(digimod_out);
|
||||
|
||||
% Implememt Precompensation
|
||||
|
||||
% Implement Precoding
|
||||
|
||||
% 4) AWG (lowpass, quantization, sample and hold)
|
||||
|
||||
LP_awg = Filter('filtdegree',4,"f_cutoff",75e9,"fs",fdac*kover,"filterType",filtertypes.gaussian);
|
||||
|
||||
|
||||
AWG_=AWG("fdac",fdac,"dac_min",-1,"dac_max",1,"H_lpf",LP_awg,"kover",kover,"bit_resolution",16,"lpf_active",1,"normalize2dac",1,"upsampling_method","samplehold");
|
||||
X = AWG_.process(X);
|
||||
|
||||
disp(['El. power: ',num2str(X.power),' dBm (into 50 Ohm)']);
|
||||
disp(['El. RMS voltage: ',num2str(sqrt(mean(X.signal.^2))),' V']);
|
||||
disp(['max voltage: ',num2str(max(X.signal)),' V']);
|
||||
|
||||
|
||||
% 5) Lowpass behavior before laser
|
||||
LP_modulator= Filter('filtdegree',4,"f_cutoff",70e9,"fs",fdac*kover,"filterType",filtertypes.butterworth);
|
||||
X = LP_modulator.process(X);
|
||||
|
||||
% 6) Laser; Modulation -> OPTICAL DOMAIN
|
||||
u_pi = 4;
|
||||
vbias = 2;
|
||||
extmodlaser = EML("mode",eml_mode.im_cosinus,"power",0,"fsimu",X.fs,"lambda",1290,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",5);
|
||||
[Opt,extmodlaser] = extmodlaser.process(X);
|
||||
|
||||
if 1
|
||||
f = figure(120);
|
||||
f.Name = 'bla';
|
||||
tiledlayout(2,4);
|
||||
|
||||
nexttile
|
||||
rms_ = rms(X.signal);
|
||||
max_ = max(X.signal);
|
||||
min_ = min(X.signal);
|
||||
hold on
|
||||
plot(X.signal,'LineWidth',0.1);
|
||||
yline([max_, min_],'LineWidth',2,'LineStyle','--');
|
||||
yline([rms_, -rms_],'LineWidth',2,'LineStyle',':');
|
||||
ylim([-3 3]);
|
||||
title(['AWG output: ',num2str(X.power), 'dBm']);
|
||||
|
||||
% Add text boxes for MIN, MAX, and RMS voltage
|
||||
text(0.5, min_-0.3, ['MIN: ', num2str(min_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left');
|
||||
text(0.5, max_+0.3, ['MAX: ', num2str(max_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left');
|
||||
text(0.5, rms_+0.22, ['RMS: ', num2str(rms_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left');
|
||||
text(0.5, -rms_-0.22, ['RMS: ', num2str(rms_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left');
|
||||
|
||||
nexttile
|
||||
plot_eye(X.signal,X.fs,fsym);
|
||||
ylabel('Signal in V')
|
||||
|
||||
nexttile
|
||||
hold on
|
||||
v_in_curve = [-u_pi*1.5/2:0.1:u_pi*1.5/2];
|
||||
field=sqrt(10^(extmodlaser.power/10-3));
|
||||
mzm_curve = ((field.*cos(pi/2*(real(v_in_curve)+vbias)/u_pi)).^2)*1e3;
|
||||
scatter(v_in_curve+vbias,mzm_curve,10,'o','filled','DisplayName','Modulator TF complete');
|
||||
scatter(X.signal(1:100000)+vbias,(abs(Opt.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF')
|
||||
scatter(min_+vbias,((field.*cos(pi/2*(real(min_)+vbias)/u_pi)).^2)*1e3,50,'x','LineWidth',2);
|
||||
scatter(max_+vbias,((field.*cos(pi/2*(real(max_)+vbias)/u_pi)).^2)*1e3,50,'x','LineWidth',2);
|
||||
xlim([-u_pi*1.5/2+vbias, u_pi*1.5/2+vbias]);
|
||||
ylim([min(mzm_curve),max(mzm_curve)]);
|
||||
xlabel('Input in V')
|
||||
ylabel('Output in mW')
|
||||
title("MZM input (v) to output (w)");
|
||||
|
||||
nexttile
|
||||
plot_eye(abs(Opt.signal.^2).*1e3 ,Opt.fs,fsym);
|
||||
ylabel('Opt. Signal in mW')
|
||||
|
||||
|
||||
nexttile([1 2])
|
||||
spectrum_plot( Opt.signal,Opt.fs, 'bla');
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
M = 6;
|
||||
data = [1,2,3,4,5,6];
|
||||
|
||||
M = 6;
|
||||
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
for i = 1:log2(M)
|
||||
N = 2^(12-1); %length of prbs
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
bits = Informationsignal(bitpattern);
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
symbols_tx_prec = Duobinary().precode(symbols);
|
||||
|
||||
% all possible transitions (for now 36, including the "edges"
|
||||
% of the QAM 32 constellation)
|
||||
states = PAMmapper(6,0,"eth_style",0).levels;
|
||||
pam6transitions = combvec(states,states)'; % pam6transitions =
|
||||
% [-5 -5;
|
||||
% -3 -5;
|
||||
% -1 -5; ...
|
||||
pam6transitions_serial = reshape(pam6transitions',[],1);
|
||||
|
||||
data = pam6transitions_serial;
|
||||
data = round(data);
|
||||
b = min(data);
|
||||
data = data - b;
|
||||
data = data ./ 2;
|
||||
% THIS WAS USED!
|
||||
bk = zeros(size(data));
|
||||
for k = 2:numel(data)
|
||||
bk(k) = mod(data(k)-bk(k-1),M);
|
||||
end
|
||||
|
||||
|
||||
%% State Analysis
|
||||
x = bk;%symbols_tx_prec.signal;
|
||||
levels = sort(unique(x)).'; % or provide known 1x6 level values
|
||||
|
||||
[~,ix] = min(abs(x - levels),[],2);
|
||||
x = levels(ix); % snapped/quantized
|
||||
|
||||
%% TRANSITION COUNTS & PROBABILITIES
|
||||
K = numel(levels);
|
||||
% map to state indices 1..K
|
||||
[tf, idx] = ismember(x, levels);
|
||||
idx = idx(:);
|
||||
from = idx(1:end-1);
|
||||
to = idx(2:end);
|
||||
from = idx(1:2:end);
|
||||
to = idx(2:2:end);
|
||||
|
||||
% counts C(from,to)
|
||||
C = accumarray([from,to], 1, [K K], @sum, 0);
|
||||
% row-stochastic transition matrix P(to|from)
|
||||
rowSums = sum(C,2);
|
||||
P = C ./ max(rowSums,1);
|
||||
|
||||
%% 1) HEATMAP (which transitions are more probable?)
|
||||
figure('Name','Transition Probabilities (to | from)');
|
||||
h = heatmap(levels, levels, P, 'Colormap', parula, 'ColorbarVisible','on');
|
||||
colormap(gca,[[1,1,1];flip(cbrewer2('Spectral',100))]);clim([0,ceil(max(P(:))*10)/10]);
|
||||
h.XLabel = 'From state (level)';
|
||||
h.YLabel = 'To state (level)';
|
||||
h.Title = 'P(to | from)';
|
||||
|
||||
%% 2) WEIGHTED TRANSITION GRAPH
|
||||
% Use dtmc if you have Econometrics Toolbox:
|
||||
mc = dtmc(P, 'StateNames', string(levels));
|
||||
figure('Name','Markov Graph (dtmc)');
|
||||
gp = graphplot(mc, 'ColorEdges',true, 'LabelEdges',true);
|
||||
@@ -1,212 +0,0 @@
|
||||
|
||||
|
||||
M = 6;
|
||||
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
for i = 1:log2(M)
|
||||
N = 2^(17-1); %length of prbs
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
bits = Informationsignal(bitpattern);
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
|
||||
bits_rx = PAMmapper(M,0).demap(symbols);
|
||||
[~,~,ber_direct,~] = calc_ber(bits.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
assert(ber_direct==0,'Mapping is wrong');
|
||||
|
||||
nBursts = 0;
|
||||
% No Precoding %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%SEND DIRECTLY
|
||||
symbols_tx = symbols;
|
||||
|
||||
symbols_rx = introduce_symbol_errors(symbols_tx, 1, 10, nBursts, 42);
|
||||
|
||||
%RECEIVE BRANCH (do nothing special)
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx);
|
||||
|
||||
[~,~,ber,errpos] = calc_ber(bits.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
disp(['BER normal: - ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
bursts_normal = count_error_bursts(errpos, 20);
|
||||
|
||||
|
||||
% Precode Emulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%SEND DIRECTLY
|
||||
symbols_tx = symbols;
|
||||
|
||||
symbols_rx = introduce_symbol_errors(symbols_tx, 1, 10, nBursts, 42);
|
||||
|
||||
%REFERENCE BRACH
|
||||
symbols_db = Duobinary().encode(symbols_tx);
|
||||
symbols_tx_emu = Duobinary().decode(symbols_db);
|
||||
bits_tx_emu = PAMmapper(M,0).demap(symbols_tx_emu);
|
||||
|
||||
% symbols_rx = introduce_symbol_errors(symbols_tx, 1, 10, 200, 42);
|
||||
|
||||
%RECEIVE BRANCH
|
||||
symbols_db = Duobinary().encode(symbols_rx);
|
||||
symbols_rx_emu = Duobinary().decode(symbols_db);
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx_emu);
|
||||
|
||||
[~,~,ber_precode_emulation,errpos_precode_emulation] = calc_ber(bits_tx_emu.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
disp(['BER precode emulation: ',sprintf('%.1E',ber_precode_emulation),' - - PAM-',num2str(M)]);
|
||||
bursts_precode_emulation = count_error_bursts(errpos_precode_emulation, 20);
|
||||
|
||||
|
||||
|
||||
|
||||
% Precode at Tx %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%SEND PRECODED DATA
|
||||
symbols_tx_prec = Duobinary().precode(symbols);
|
||||
|
||||
symbols_rx_prec = introduce_symbol_errors(symbols_tx_prec, 1, 10, nBursts, 42);
|
||||
|
||||
%RECEIVE BRANCH
|
||||
symbols_db = Duobinary().encode(symbols_rx_prec);
|
||||
symbols_rx_prec = Duobinary().decode(symbols_db);
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx_prec);
|
||||
|
||||
[~,~,ber_precoded,errpos_precoded] = calc_ber(bits.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
disp(['BER precoded: ',sprintf('%.1E',ber_precoded),' - - PAM-',num2str(M)]);
|
||||
burst_precoded = count_error_bursts(errpos_precoded, 20);
|
||||
|
||||
|
||||
% Precode at Tx but omit at Rx %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%SEND PRECODED DATA
|
||||
symbols_tx_prec = Duobinary().precode(symbols);
|
||||
bits_tx_prec = PAMmapper(M,0).demap(symbols_tx_prec);
|
||||
|
||||
symbols_rx_omit = introduce_symbol_errors(symbols_tx_prec, 1, 10, nBursts, 42);
|
||||
|
||||
%RECEIVE BRANCH
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx_omit);
|
||||
|
||||
[~,~,ber_omit,errpos_omit] = calc_ber(bits_tx_prec.signal,bits_rx.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||
disp(['BER (omit precode): ',sprintf('%.1E',ber_omit),' - - PAM-',num2str(M)]);
|
||||
burst_omit = count_error_bursts(errpos_omit, 20);
|
||||
|
||||
if 0
|
||||
cols = linspecer(8);
|
||||
figure();hold on;
|
||||
stem(1:20,bursts_normal,'LineWidth',2,'Color',cols(4,:),'Marker','_','DisplayName','w/o diff. precoder');
|
||||
stem(1:20,bursts_precode_emulation,'LineWidth',2,'Color',cols(3,:),'Marker','.','LineStyle','-','DisplayName','emulated precoder');
|
||||
stem(1:20,burst_precoded,'LineWidth',1,'Color',cols(6,:),'Marker','_','DisplayName','w/ diff. precoder');
|
||||
stem(1:20,burst_omit,'LineWidth',1,'Color',cols(5,:),'Marker','.','LineStyle',':','DisplayName','omit precoder');
|
||||
xlabel('Bit Error Burst Length')
|
||||
ylabel('Occurence')
|
||||
set(gca, 'yscale', 'log');
|
||||
end
|
||||
|
||||
|
||||
%% State Analysis
|
||||
signal_to_analyze = symbols_tx_emu;
|
||||
x = signal_to_analyze.signal(:);
|
||||
levels = sort(unique(x)).'; % or provide known 1x6 level values
|
||||
|
||||
[~,ix] = min(abs(x - levels),[],2);
|
||||
x = levels(ix); % snapped/quantized
|
||||
|
||||
%% TRANSITION COUNTS & PROBABILITIES
|
||||
K = numel(levels);
|
||||
% map to state indices 1..K
|
||||
[tf, idx] = ismember(x, levels);
|
||||
idx = idx(:);
|
||||
from = idx(1:end-1);
|
||||
to = idx(2:end);
|
||||
from = idx(1:2:end);
|
||||
to = idx(2:2:end);
|
||||
|
||||
% counts C(from,to)
|
||||
C = accumarray([from,to], 1, [K K], @sum, 0);
|
||||
% row-stochastic transition matrix P(to|from)
|
||||
rowSums = sum(C,2);
|
||||
P = C ./ max(rowSums,1);
|
||||
|
||||
%% 1) HEATMAP (which transitions are more probable?)
|
||||
figure('Name','Transition Probabilities (to | from)');
|
||||
h = heatmap(levels, levels, P, 'Colormap', parula, 'ColorbarVisible','on');
|
||||
colormap(gca,[[1,1,1];flip(cbrewer2('Spectral',100))]);clim([0,ceil(max(P(:))*10)/10]);
|
||||
h.XLabel = 'From state (level)';
|
||||
h.YLabel = 'To state (level)';
|
||||
h.Title = 'P(to | from)';
|
||||
|
||||
%% 2) WEIGHTED TRANSITION GRAPH
|
||||
% Use dtmc if you have Econometrics Toolbox:
|
||||
mc = dtmc(P, 'StateNames', string(levels.*PAMmapper(M,0).get_scaling));
|
||||
figure('Name','Markov Graph (dtmc)');
|
||||
gp = graphplot(mc, 'ColorEdges',true, 'LabelEdges',true);
|
||||
|
||||
|
||||
function symbols = introduce_symbol_errors(symbols, j, maxBurstLen, nBursts, seed)
|
||||
%INTRODUCE_SYMBOL_ERRORS injects bursty level errors into symbols.signal.
|
||||
% symbols.signal : column/row vector of quantized levels (exactly one of 6 values)
|
||||
% j : max level step per sample (default 1)
|
||||
% maxBurstLen : maximum burst length (default 8)
|
||||
% nBursts : number of bursts to insert (default ~1% of length)
|
||||
% seed : RNG seed (optional)
|
||||
|
||||
if nargin < 2 || isempty(j), j = 1; end
|
||||
if nargin < 3 || isempty(maxBurstLen), maxBurstLen = 8; end
|
||||
x = symbols.signal(:);
|
||||
N = numel(x);
|
||||
if nargin < 4 || isempty(nBursts), nBursts = max(1, round(0.01*N)); end
|
||||
if nargin >= 5 && ~isempty(seed), rng(seed); end
|
||||
|
||||
% known levels and index mapping
|
||||
lvls = sort(unique(x)).';
|
||||
K = numel(lvls);
|
||||
|
||||
[~, idx] = ismember(x, lvls); % idx in 1..6
|
||||
|
||||
used = false(N,1); % avoid overlapping bursts
|
||||
burst_ranges = zeros(nBursts,2);
|
||||
|
||||
for b = 1:nBursts
|
||||
% pick start not inside an existing burst
|
||||
s = randi(N);
|
||||
while used(s), s = randi(N); end
|
||||
L = randi(maxBurstLen);
|
||||
e = min(N, s+L-1);
|
||||
|
||||
% mark used range
|
||||
used(s:e) = true;
|
||||
burst_ranges(b,:) = [s e];
|
||||
|
||||
% choose one direction for the whole burst: -1 (down) or +1 (up)
|
||||
dir = randi([0 1])*2 - 1;
|
||||
|
||||
% apply level errors within the burst
|
||||
for t = s:e
|
||||
k = idx(t); % current level index (1..6)
|
||||
|
||||
% force inward movement at edges; prevents "flipping" to opposite edge
|
||||
if k == 1 && dir == -1, dir = +1; end
|
||||
if k == K && dir == +1, dir = -1; end
|
||||
|
||||
step = randi([1 j]); % 1..j steps
|
||||
kNew = k + dir*step;
|
||||
|
||||
% clamp to [1,K], no wrap-around
|
||||
if kNew < 1, kNew = 1; elseif kNew > K, kNew = K; end
|
||||
|
||||
% if clamped to the same edge repeatedly, flip direction to keep changing
|
||||
if kNew == k
|
||||
dir = -dir;
|
||||
kNew = max(1, min(K, k + dir*step));
|
||||
end
|
||||
|
||||
idx(t) = kNew;
|
||||
end
|
||||
end
|
||||
|
||||
x_err = lvls(idx);
|
||||
symbols.signal = reshape(x_err, size(symbols.signal)); % preserve original shape
|
||||
|
||||
end
|
||||
@@ -1,100 +0,0 @@
|
||||
% Define ranges for variables to iterate over
|
||||
var1_range = [1, 2, 3, 4, 6];
|
||||
var2_range = [10, 20];
|
||||
var3_range = [100, 200];
|
||||
|
||||
% Prepare the parallel pool
|
||||
if isempty(gcp('nocreate'))
|
||||
parpool; % Start a parallel pool if not already running
|
||||
end
|
||||
|
||||
% Array to hold measurement futures
|
||||
measurements = parallel.FevalFuture.empty();
|
||||
|
||||
% Array to hold DSP results
|
||||
dsp_results = parallel.Future.empty();
|
||||
|
||||
% Nested for loops for all parameter combinations
|
||||
lin_idx = 1;
|
||||
for v1 = var1_range
|
||||
for v2 = var2_range
|
||||
for v3 = var3_range
|
||||
% Construct the struct of optional variables for this iteration
|
||||
optionalVars = struct('var_4', v1, 'var_5', v2, 'var_6', v3);
|
||||
|
||||
% Submit the measurement function to the parallel pool
|
||||
measurements(lin_idx) = parfeval(@measurement, 1, optionalVars);
|
||||
|
||||
% Link DSP function to run after measurement completes
|
||||
dsp_results(lin_idx) = afterEach(measurements(lin_idx), @(output) rundsp(output, optionalVars), 1);
|
||||
|
||||
lin_idx = lin_idx + 1; % Increment linear index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% Fetch and display DSP results
|
||||
final_results = cell(numel(dsp_results), 1);
|
||||
for i = 1:numel(dsp_results)
|
||||
fprintf('Fetching DSP result for job %d...\n', i);
|
||||
final_results{i} = fetchOutputs(dsp_results(i)); % Fetch each DSP result individually
|
||||
end
|
||||
|
||||
fprintf('All DSP evaluations completed.\n');
|
||||
disp('Final Results:');
|
||||
disp(final_results);
|
||||
|
||||
% --- Measurement Function ---
|
||||
function output = measurement(varargin)
|
||||
|
||||
% Default values for optional variables
|
||||
var_1 = 1;
|
||||
var_2 = 2;
|
||||
var_4 = 10; % Default value for var4
|
||||
var_5 = 20; % Default value for var5
|
||||
var_6 = 30; % Default value for var6
|
||||
var_7 = 40; % Default value for var7
|
||||
var_8 = 50; % Default value for var8
|
||||
var_9 = 60; % Default value for var9
|
||||
var_10 = 70; % Default value for var10
|
||||
|
||||
% Parse optional input arguments
|
||||
if ~isempty(varargin)
|
||||
var_s = varargin{1};
|
||||
if isstruct(var_s)
|
||||
fields = fieldnames(var_s);
|
||||
for i = 1:numel(fields)
|
||||
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
|
||||
fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
|
||||
end
|
||||
else
|
||||
error('Optional variables should be passed as a struct.');
|
||||
end
|
||||
end
|
||||
|
||||
% Simulate output with a random delay
|
||||
output = randi(5); % Random result
|
||||
pause(output); % Simulate processing time
|
||||
end
|
||||
|
||||
% --- DSP Function ---
|
||||
function output = rundsp(measurement_output, varargin)
|
||||
|
||||
% Parse optional input arguments
|
||||
if ~isempty(varargin)
|
||||
var_s = varargin{1};
|
||||
if isstruct(var_s)
|
||||
fields = fieldnames(var_s);
|
||||
for i = 1:numel(fields)
|
||||
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
|
||||
fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
|
||||
end
|
||||
else
|
||||
error('Optional variables should be passed as a struct.');
|
||||
end
|
||||
end
|
||||
|
||||
% Simulate DSP processing based on measurement output
|
||||
output = measurement_output + 10; % Add 10 to measurement output
|
||||
pause(measurement_output); % Simulate DSP processing time
|
||||
end
|
||||
@@ -1,65 +0,0 @@
|
||||
|
||||
M = 4;
|
||||
apply_precode_at_tx = 1;
|
||||
|
||||
bitpattern = [];
|
||||
s = RandStream('twister','Seed',1);
|
||||
for i = 1:log2(M)
|
||||
N = 2^(17-1); %length of prbs
|
||||
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
bits = Informationsignal(bitpattern);
|
||||
|
||||
symbols = PAMmapper(M,0).map(bits);
|
||||
|
||||
if apply_precode_at_tx
|
||||
symbols_tx = Duobinary().precode(symbols);
|
||||
else
|
||||
symbols_tx = symbols;
|
||||
end
|
||||
disp(['Tx Sequenz: -- RMS:',sprintf('%.1f',rms(symbols_tx.signal)),' - - Levels -',num2str(numel(unique(symbols_tx.signal)))]);
|
||||
unique(symbols_tx.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
symbols_tx.signal = awgn(symbols_tx.signal,20,"measured",1);
|
||||
% show2Dconstellation(symbols_tx,symbols_tx,"displayname",'VNLE Out','fignum',2241);
|
||||
|
||||
|
||||
if apply_precode_at_tx
|
||||
% Entschiedene Symbole codieren: d_DB(n) = d(n) + d(n-1) (im Fall von PAM4 7 level [0 1 2 3 4 5 6])
|
||||
symbols_db = Duobinary().encode(symbols_tx);
|
||||
|
||||
disp(['DB encoded -- RMS:',sprintf('%.1f',rms(symbols_db.signal)),' - - Levels -',num2str(numel(unique(symbols_db.signal)))]);
|
||||
unique(symbols_db.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
% Entschiedene codierte Symbole decodieren: d_dec(n) = d_DB(n) mod4
|
||||
symbols_rx = Duobinary().decode(symbols_db);
|
||||
else
|
||||
symbols_db = Duobinary().encode(symbols_tx);
|
||||
symbols_rx = Duobinary().decode(symbols_db);
|
||||
end
|
||||
|
||||
% Vergleichen von b(n) und d_dec(n)
|
||||
bits_rx = PAMmapper(M,0).demap(symbols_rx);
|
||||
disp(['Wieder normal -- RMS:',sprintf('%.1f',rms(symbols_rx.signal)),' - - Levels -',num2str(numel(unique(symbols_rx.signal)))]);
|
||||
unique(symbols_rx.signal)
|
||||
disp('- - - - - - - - - -');
|
||||
|
||||
|
||||
[~,~,ber,~] = calc_ber(bits.signal,bits_rx.signal,"skip_front",10,"skip_end",10,"returnErrorLocation",1);
|
||||
|
||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||
|
||||
figure()
|
||||
subplot(1,2,1)
|
||||
histogram(symbols_tx.signal,100,'Normalization','count')
|
||||
|
||||
subplot(1,2,2)
|
||||
histogram(symbols_db.signal,100,'Normalization','count')
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
% Setup PRBS parameters
|
||||
O = 6;
|
||||
M = 6;
|
||||
N = 2^(O-1); % Length of PRBS
|
||||
randkey = 1; % Random key for random stream
|
||||
use_eth_mapping =1;
|
||||
|
||||
if M ~= 6
|
||||
dimension = log2(M);
|
||||
else
|
||||
dimension = 5;
|
||||
end
|
||||
|
||||
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
|
||||
bitpattern = [];
|
||||
|
||||
s = RandStream('twister', 'Seed', randkey);
|
||||
for i = 1:dimension
|
||||
bitpattern(:, i) = randi(s, [0 1], N, 1);
|
||||
end
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern',[],1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||
end
|
||||
|
||||
Tx_bits = Informationsignal(bitpattern);
|
||||
|
||||
Digi_Mod = PAMmapper(M, 0,"eth_style",use_eth_mapping);
|
||||
|
||||
% Map bits to symbols
|
||||
Symbols = Digi_Mod.map(Tx_bits);
|
||||
|
||||
% Demap symbols back to bits
|
||||
Rx_bits = Digi_Mod.demap(Symbols);
|
||||
|
||||
[~, error_num, ber, ~] = calc_ber(Tx_bits.signal(1:length(Rx_bits.signal)), Rx_bits.signal,"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
|
||||
|
||||
fprintf('BER: %.1E \n',ber);
|
||||
@@ -1,74 +0,0 @@
|
||||
classdef test_modulation < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
Tx_bits
|
||||
Digi_Mod
|
||||
end
|
||||
|
||||
properties (MethodSetupParameter)
|
||||
% Define method-level parameters for PRBS and bit pattern
|
||||
useprbs = struct('false', 0, 'true', 1); % variations: {0, 1}
|
||||
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
|
||||
O = struct('O10', 10, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
|
||||
end
|
||||
|
||||
properties (TestParameter)
|
||||
% Define test-level parameters for M and O
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodSetup)
|
||||
|
||||
function setupModulation(testCase, useprbs, M, O)
|
||||
% Setup PRBS and bit pattern for the test case using parameters
|
||||
|
||||
% Setup PRBS parameters
|
||||
N = 2^(O-1); % Length of PRBS
|
||||
randkey = 1; % Random key for random stream
|
||||
|
||||
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
|
||||
bitpattern = [];
|
||||
if useprbs
|
||||
for i = 1:log2(M)
|
||||
[bitpattern(:, i), seed] = prbs(O, N, seed);
|
||||
end
|
||||
else
|
||||
s = RandStream('twister', 'Seed', randkey);
|
||||
for i = 1:log2(M)
|
||||
bitpattern(:, i) = randi(s, [0 1], N, 1);
|
||||
end
|
||||
end
|
||||
|
||||
if M == 6
|
||||
bitpattern = reshape(bitpattern, [], 1);
|
||||
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
|
||||
end
|
||||
|
||||
testCase.Tx_bits = Informationsignal(bitpattern);
|
||||
testCase.Digi_Mod = PAMmapper(M, 0);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test, ParameterCombination = 'sequential')
|
||||
% Test with sequential combination of parameters
|
||||
function testBackToBackMapping(testCase, M, useprbs, O)
|
||||
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
|
||||
|
||||
% Map bits to symbols
|
||||
Symbols = testCase.Digi_Mod.map(testCase.Tx_bits);
|
||||
|
||||
% Demap symbols back to bits
|
||||
Rx_bits = testCase.Digi_Mod.demap(Symbols);
|
||||
|
||||
% Validate BER is zero
|
||||
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, Rx_bits.signal, ...
|
||||
"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
|
||||
|
||||
% Assert that BER is zero
|
||||
testCase.verifyEqual(ber, 0, 'BER should be zero');
|
||||
testCase.verifyEqual(error_num, 0, 'No errors should occur in the mapping process');
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,27 +0,0 @@
|
||||
%% Target source entropy for PS-PAM8
|
||||
clear; clc;
|
||||
|
||||
M = 8;
|
||||
a = -(M-1):2:(M-1); % PAM-8 amplitude levels: [-7 -5 -3 -1 1 3 5 7]
|
||||
H_target = 2.79; % desired entropy [bits/symbol]
|
||||
|
||||
% Objective: find nu such that H(PA) = H_target
|
||||
f = @(nu) entropy_MB(a,nu) - H_target;
|
||||
nu_opt = fzero(f, [0, 2]); % search ν in reasonable range
|
||||
|
||||
% Compute final distribution
|
||||
P = exp(-nu_opt*a.^2);
|
||||
P = P/sum(P);
|
||||
H = -sum(P .* log2(P));
|
||||
|
||||
fprintf('Shaping parameter ν = %.4f\n', nu_opt);
|
||||
fprintf('Entropy H(A) = %.3f bits/symbol\n', H);
|
||||
disp('Probability vector (P_A):');
|
||||
disp(P.');
|
||||
|
||||
%% Helper: entropy function
|
||||
function H = entropy_MB(a,nu)
|
||||
P = exp(-nu*a.^2);
|
||||
P = P/sum(P);
|
||||
H = -sum(P .* log2(P));
|
||||
end
|
||||
@@ -1,89 +0,0 @@
|
||||
%% ============================================================
|
||||
% IM/DD Fading Notch – λ_null vs. Bandwidth (Fixed 10 km)
|
||||
% ============================================================
|
||||
|
||||
clear; clc;
|
||||
|
||||
%% Fiber and dispersion parameters
|
||||
lambda0 = 1310e-9; % Zero-dispersion wavelength [m]
|
||||
S0 = 0.09; % Dispersion slope at ZDW [ps/(nm²·km)]
|
||||
L = 10e3; % Fiber length [m]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
%% Frequency sweep (defines the desired first-fading notch)
|
||||
f_targets = linspace(40e9, 150e9, 200); % [Hz]
|
||||
f_GHz = f_targets / 1e9;
|
||||
|
||||
%% Compute wavelength λ_null for each target f_null
|
||||
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
||||
lambda_nm = lambda_vec * 1e9; % Convert to nm
|
||||
Dacc = Dacc_vec; % [ps/nm]
|
||||
|
||||
%% ------------------------------------------------------------
|
||||
% Plot λ_null vs. f_null for 10 km fiber
|
||||
% ------------------------------------------------------------
|
||||
cols = cbrewer2('Paired',10);
|
||||
figure('Color','w'); hold on;
|
||||
|
||||
hLine = plot(lambda_nm, f_GHz, ...
|
||||
'LineWidth', 2, ...
|
||||
'DisplayName', sprintf('L = %.1f km', L/1000), ...
|
||||
'Color', cols(2,:));
|
||||
|
||||
xlabel('Wavelength λ [nm]');
|
||||
ylabel('First fading notch f_{null} [GHz]');
|
||||
title('IM/DD Fading Notch Position vs. Wavelength');
|
||||
grid on; box on;
|
||||
|
||||
lim = (lambda0.*1e9) - [8, 40];
|
||||
xlim([lim(2) lim(1)]);
|
||||
yticks([56,75,90,112]);
|
||||
|
||||
%% ------------------------------------------------------------
|
||||
% Custom DataTip Template
|
||||
% ------------------------------------------------------------
|
||||
% Add accumulated dispersion value to the DataTip
|
||||
hLine.DataTipTemplate.DataTipRows(1).Label = 'λ [nm]';
|
||||
hLine.DataTipTemplate.DataTipRows(2).Label = 'f_{null} [GHz]';
|
||||
|
||||
% Create a new row for Dacc
|
||||
dRow = dataTipTextRow('D_{acc} [ps/nm]', Dacc);
|
||||
hLine.DataTipTemplate.DataTipRows(end+1) = dRow;
|
||||
|
||||
%% ------------------------------------------------------------
|
||||
% Helper function: lambda_for_first_null_full
|
||||
% ------------------------------------------------------------
|
||||
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
|
||||
c = physconst('lightspeed');
|
||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
||||
|
||||
lambda_min = 1260e-9;
|
||||
lambda_max = 1360e-9;
|
||||
|
||||
f_target = f_target(:);
|
||||
N = numel(f_target);
|
||||
|
||||
lambda_vec = zeros(N,1);
|
||||
Dacc_vec = zeros(N,1);
|
||||
|
||||
for k = 1:N
|
||||
RHS = c * 0.5 / (f_target(k)^2 * L);
|
||||
|
||||
fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS;
|
||||
|
||||
try
|
||||
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
||||
catch
|
||||
lambda_sol = lambda_min;
|
||||
end
|
||||
|
||||
lambda_sol = min(max(lambda_sol, lambda_min), lambda_max);
|
||||
lambda_vec(k) = lambda_sol;
|
||||
|
||||
D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km)
|
||||
Dacc_val = D_lambda * (L/1000); % ps/nm
|
||||
Dacc_val = min(max(Dacc_val, -100), 100);
|
||||
|
||||
Dacc_vec(k) = Dacc_val;
|
||||
end
|
||||
end
|
||||
@@ -1,77 +0,0 @@
|
||||
% Festen Betriebsparameter
|
||||
lambda = 1290; % nm
|
||||
L = 1; % km
|
||||
|
||||
mu_zwd = 1317; % nm
|
||||
sigma_zwd = 2; % nm
|
||||
mu_s0 = 0.0872; % ps / nm2 km
|
||||
sigma_s0 = 0.0012; % ps / nm2 km
|
||||
rho = -0.5; % Korrelation
|
||||
|
||||
% Gitter für lambda0 und S0
|
||||
lambda0_vec = linspace(mu_zwd-10, mu_zwd+10, 100);
|
||||
S0_vec = linspace(mu_s0-0.01, mu_s0+0.01, 100);
|
||||
|
||||
% Korrigierte meshgrid Reihenfolge
|
||||
[S0, Lambda0] = meshgrid(S0_vec, lambda0_vec);
|
||||
|
||||
% Dispersion berechnen
|
||||
D = (S0./4) .* ( lambda - (Lambda0.^4)./(lambda^3) ) * L;
|
||||
|
||||
%% 2D-Konturplot
|
||||
figure('Color','w');
|
||||
hold on
|
||||
|
||||
% --- 1. Hintergrund: Dispersions-Konturlinien (Gerundet für TikZ) ---
|
||||
numLevels_D = 10;
|
||||
% Erzeuge glatte, auf 1 Nachkommastelle gerundete Werte
|
||||
|
||||
levels_D = round(linspace(min(D(:)), max(D(:)), numLevels_D), 1);
|
||||
levels_D = unique(levels_D); % Falls durch Rundung doppelte Werte entstehen
|
||||
|
||||
% Colormap in der Länge der verbliebenen Level erstellen
|
||||
cmap_bg = cbrewer2('Blues', length(levels_D));
|
||||
|
||||
for i = 1:length(levels_D)
|
||||
% WICHTIG: Das Level als [Wert, Wert] übergeben!
|
||||
[C,h] = contour(S0, Lambda0, D, [levels_D(i), levels_D(i)], ...
|
||||
'Color', cmap_bg(i,:),...
|
||||
'LineWidth', 1.5, ...
|
||||
'ShowText', 'on', ...
|
||||
'LabelFormat', '%0.1f');
|
||||
h.LabelColor = [0,0,0];
|
||||
end
|
||||
|
||||
% --- NEU: Parameter für die Verteilungen ---
|
||||
mu_zwd = 1317; % nm
|
||||
sigma_zwd = 2; % nm
|
||||
mu_s0 = 0.0872; % ps / nm2 km
|
||||
sigma_s0 = 0.0012; % ps / nm2 km
|
||||
rho = -0.5; % Korrelation
|
||||
|
||||
% --- 3. Randverteilungen (1D Gauss) an den Achsen ---
|
||||
s0_vals = linspace(min(S0_vec), max(S0_vec), 500);
|
||||
gauss_s0 = exp(-0.5*((s0_vals - mu_s0)/sigma_s0).^2);
|
||||
scale_s0 = 4; % Skalierung für die Höhe in der Ansicht
|
||||
plot(s0_vals, min(lambda0_vec) + gauss_s0 * scale_s0, 'k', 'LineWidth', 2);
|
||||
|
||||
zwd_vals = linspace(min(lambda0_vec), max(lambda0_vec), 500);
|
||||
gauss_zwd = exp(-0.5*((zwd_vals - mu_zwd)/sigma_zwd).^2);
|
||||
scale_zwd = 0.005; % Skalierung für die Auslenkung in der Ansicht
|
||||
plot(min(S0_vec) + gauss_zwd * scale_zwd, zwd_vals, 'k', 'LineWidth', 2);
|
||||
|
||||
% Hilfslinien für die Mittelwerte
|
||||
xline(mu_s0, '--k', 'Alpha', 0.4);
|
||||
yline(mu_zwd, '--k', 'Alpha', 0.4);
|
||||
|
||||
% --- Achsenbeschriftung, Titel & Formatierung ---
|
||||
xlabel('S0 ', 'FontSize', 12);
|
||||
ylabel('ZDW [nm]', 'FontSize', 12);
|
||||
% title(sprintf('Dispersion: %d km; %d nm', L, lambda), 'FontSize', 14);
|
||||
|
||||
axis([min(S0_vec) max(S0_vec) min(lambda0_vec) max(lambda0_vec)]);
|
||||
grid on
|
||||
hold off
|
||||
|
||||
%% Für den LaTeX Export
|
||||
mat2tikz_improved("C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/02_IMDD_System/tikz/dispersion/dispersion_contour.tikz")
|
||||
@@ -1,38 +0,0 @@
|
||||
%% ------------------------------------------------------------
|
||||
% Plot: Maximum usable IM/DD bandwidth vs wavelength
|
||||
% ------------------------------------------------------------
|
||||
|
||||
% Fiber and dispersion parameters
|
||||
lambda0 = 1310e-9; % [m]
|
||||
S0 = 0.08; % [ps/(nm²·km)]
|
||||
L = 10000; % [m]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
% Wavelength range around ZDW
|
||||
lambda_vec = linspace(1250e-9, 1350e-9, 200); % [m]
|
||||
|
||||
% Compute D(lambda) using full model
|
||||
lambda_nm = lambda_vec * 1e9;
|
||||
lambda0_nm = lambda0 * 1e9;
|
||||
D_lambda = (S0/4) .* (lambda_nm - (lambda0_nm.^4) ./ (lambda_nm.^3)); % [ps/(nm·km)]
|
||||
|
||||
% Convert D to [s/m²]
|
||||
D_si = D_lambda * 1e-6;
|
||||
|
||||
% Compute first null frequency (f₀) for each wavelength
|
||||
f_null = sqrt(c*(0.5) ./ (abs(D_si).*lambda_vec.^2*L)); % [Hz]
|
||||
|
||||
% Plot
|
||||
figure('Color','w');
|
||||
plot(lambda_vec*1e9, f_null/1e9, 'LineWidth', 1.6);
|
||||
grid on; box on;
|
||||
xlabel('Wavelength [nm]');
|
||||
ylabel('First Fading Null Frequency [GHz]');
|
||||
title(sprintf('IM/DD Bandwidth Limit vs. Wavelength (L = %.1f km)', L/1000));
|
||||
|
||||
% Highlight useful bandwidth thresholds
|
||||
yline(25, '--', '25 GHz','Color',[0.4 0.4 0.4],'LabelHorizontalAlignment','left');
|
||||
yline(50, '--', '50 GHz','Color',[0.2 0.6 0.2],'LabelHorizontalAlignment','left');
|
||||
yline(100,'--', '100 GHz','Color',[0.6 0.2 0.2],'LabelHorizontalAlignment','left');
|
||||
|
||||
legend('First fading notch (f_{null})','Location','best');
|
||||
@@ -1,165 +0,0 @@
|
||||
%% Chromatic Dispersion Power Fading Demonstration
|
||||
% ------------------------------------------------------------
|
||||
% This script computes and visualizes power fading after
|
||||
% photodiode detection caused by chromatic dispersion in IM/DD links.
|
||||
%
|
||||
% It also determines the wavelength λ that produces the first
|
||||
% fading null at a specified RF frequency f_target using the
|
||||
% full physical dispersion model:
|
||||
%
|
||||
% D(λ) = (S0/4) * (λ - λ0^4 / λ^3)
|
||||
%
|
||||
% and compares the analytic null frequency with simulation.
|
||||
% ------------------------------------------------------------
|
||||
|
||||
% clear; close all; clc;
|
||||
|
||||
%% Fiber and wavelength parameters
|
||||
lambda0 = 1310e-9; % Zero-dispersion wavelength (ZDW) [m]
|
||||
S0 = 0.08; % Dispersion slope at ZDW [ps/(nm^2·km)]
|
||||
L = 10000; % Fiber length [m]
|
||||
alpha_dB = 0; % Attenuation [dB/m] (ignored here)
|
||||
|
||||
%% Target null frequency
|
||||
f_targets = linspace(55e9,58e9,10);
|
||||
f_targets = 56e9;
|
||||
% f_targets = 80e9;
|
||||
% Compute wavelength that gives the first null at f_target
|
||||
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
||||
% lambda_vec = 1293e-9;
|
||||
|
||||
|
||||
fprintf('\n----------------------------------------------\n');
|
||||
fprintf(' f_null [GHz] lambda [nm] Dacc [ps/nm]\n');
|
||||
fprintf('----------------------------------------------\n');
|
||||
fprintf('%10.1f %8.2f %+8.3f\n',[f_targets(:)/1e9, lambda_vec(:)*1e9, Dacc_vec(:)].');
|
||||
fprintf('----------------------------------------------\n\n');
|
||||
|
||||
%% Frequency grid
|
||||
f_simu = 500e9; % Simulation bandwidth [Hz]
|
||||
N_freq = 500000;
|
||||
faxis = linspace(-f_simu/2, f_simu/2, N_freq);
|
||||
|
||||
%% Derived fiber parameters
|
||||
c = physconst('lightspeed');
|
||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/m³
|
||||
|
||||
% Convert wavelengths to nm for the D(lambda) model
|
||||
lambda_nm = lambda_vec(end) * 1e9;
|
||||
lambda0_nm = lambda0 * 1e9;
|
||||
|
||||
% Dispersion parameter [ps/(nm·km)]
|
||||
D_lambda = (S0/4) * (lambda_nm - (lambda0_nm^4)/(lambda_nm^3));
|
||||
|
||||
% Convert to [s/m²]
|
||||
D_si = D_lambda * 1e-6;
|
||||
|
||||
% β2 in [s²/m]
|
||||
b2 = -D_si * lambda_vec(end)^2 / (2*pi*c);
|
||||
|
||||
%% IM/DD intensity response (simulation)
|
||||
phi = 2*pi^2*b2*faxis.^2*L;
|
||||
H_field_pos = exp(-1j*phi); % +f sideband
|
||||
H_field_neg = exp(+1j*phi); % -f sideband
|
||||
H_intensity = 0.5 * (H_field_pos + H_field_neg); % PD beating term
|
||||
H_sim = abs(H_intensity);
|
||||
|
||||
%% Theoretical analytical IM/DD response
|
||||
phi = 2*pi^2 * abs(b2) * faxis.^2 * L;
|
||||
H_theoretical = abs(cos(phi));
|
||||
|
||||
%% Analytic first null (for verification)
|
||||
f_null_analytic = sqrt(c*(0.5)/(abs(D_si)*lambda_vec(end)^2*L));
|
||||
fprintf('Analytic first null from D,λ,L: %.2f GHz\n\n', f_null_analytic/1e9);
|
||||
|
||||
%% Plot
|
||||
cols = linspecer(5);
|
||||
figure('Color','w'); hold on; grid on; box on;
|
||||
plot(faxis*1e-9, 10*log10(H_sim), 'DisplayName','$|H_{sim}|$ (IM/DD simulation)','Color',cols(1,:));
|
||||
plot(faxis*1e-9, 10*log10(H_theoretical), 'DisplayName','|cos($\phi$)| (theory)','Color',cols(2,:),'LineStyle','--');
|
||||
xline(f_targets(end)/1e9,'k:','LineWidth',1.2,'DisplayName','Target null (56 GHz)');
|
||||
xline(f_null_analytic/1e9,'Color',[0.2 0.6 0.2],'LineStyle','-.','LineWidth',1.2,'DisplayName','Analytic null');
|
||||
xlabel('Frequency [GHz]');
|
||||
ylabel('Magnitude [dB]');
|
||||
title(sprintf('Power Fading for %.2f nm, L = %.1f km',lambda_nm,L/1000));
|
||||
legend('Location','best'); ylim([-30 0]);
|
||||
|
||||
%% Plot Bandwidth vs Lambda max
|
||||
|
||||
figure();
|
||||
hold on;
|
||||
plot(lambda_vec.*1e6,f_targets.*1e-9)
|
||||
xlabel('wavelength');
|
||||
ylabel('max. Bandwidth')
|
||||
|
||||
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
|
||||
% lambda_for_first_null_full (stable, single-branch + validity checks)
|
||||
% --------------------------------------------------------------------
|
||||
% Computes the wavelength(s) at which the first IM/DD fading null
|
||||
% occurs at frequency/ies f_target using the full dispersion model:
|
||||
%
|
||||
% D(lambda) = (S0/4)*(lambda - lambda0^4 / lambda^3)
|
||||
%
|
||||
% Restricted to the NORMAL-dispersion branch (λ < λ0),
|
||||
% and valid only in the O-band (1260–1360 nm).
|
||||
%
|
||||
% Inputs:
|
||||
% f_target - scalar or vector of target null frequencies [Hz]
|
||||
% L - fiber length [m]
|
||||
% lambda0 - zero-dispersion wavelength (ZDW) [m]
|
||||
% S0 - dispersion slope at ZDW [ps/(nm²·km)]
|
||||
%
|
||||
% Outputs:
|
||||
% lambda_vec - wavelength(s) [m] where first null occurs (clamped to O-band)
|
||||
% Dacc_vec - accumulated dispersion(s) [ps/nm] (NaN if out of valid range)
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
c = physconst('lightspeed');
|
||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
||||
|
||||
% Define O-band boundaries (in meters)
|
||||
lambda_min = 1255e-9;
|
||||
lambda_max = 1361e-9;
|
||||
|
||||
% Force column vector
|
||||
f_target = f_target(:);
|
||||
N = numel(f_target);
|
||||
|
||||
lambda_vec = NaN(N,1);
|
||||
Dacc_vec = NaN(N,1);
|
||||
|
||||
for k = 1:N
|
||||
RHS = c * 0.5 / (f_target(k)^2 * L);
|
||||
|
||||
% Normal-dispersion branch (λ < λ0)
|
||||
fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS;
|
||||
|
||||
% Limit the search to [λ_min, λ0)
|
||||
try
|
||||
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
||||
catch
|
||||
% If the zero is not within bounds, skip this point
|
||||
lambda_sol = NaN;
|
||||
end
|
||||
|
||||
% Validate solution
|
||||
if isnan(lambda_sol) || lambda_sol < lambda_min || lambda_sol > lambda_max
|
||||
lambda_vec(k) = NaN;
|
||||
Dacc_vec(k) = NaN;
|
||||
continue
|
||||
end
|
||||
|
||||
% Compute D(lambda) and accumulated dispersion
|
||||
D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km)
|
||||
Dacc_val = D_lambda * (L/1000); % ps/nm
|
||||
|
||||
% Sanity bound on dispersion (avoid unphysical > ±100 ps/nm)
|
||||
if abs(Dacc_val) > 100
|
||||
lambda_vec(k) = NaN;
|
||||
Dacc_vec(k) = NaN;
|
||||
else
|
||||
lambda_vec(k) = lambda_sol;
|
||||
Dacc_vec(k) = Dacc_val;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,32 +0,0 @@
|
||||
%% Dependency f_null vs Delta_lambda
|
||||
lambda0 = 1310e-9;
|
||||
S0 = 0.09; % ps/(nm²·km)
|
||||
L = 10e3; % m
|
||||
c = physconst('lightspeed');
|
||||
|
||||
% Convert slope to SI
|
||||
S0_si = S0 * 1e3; % s/m³
|
||||
|
||||
Delta_lambda = linspace(5e-9, 80e-9, 300); % [m] detuning
|
||||
|
||||
cols = [0.3467 0.5360 0.6907;...
|
||||
0.9153 0.2816 0.2878;...
|
||||
0.4416 0.7490 0.4322];
|
||||
figure('Color','w');hold on
|
||||
cnt = 1;
|
||||
for L = [2,10,40]
|
||||
f_null_10 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L*1e3) );
|
||||
plot(1310-Delta_lambda*1e9, f_null_10/1e9, 'LineWidth',2,'DisplayName',sprintf('%d km',L),'Color',cols(cnt,:));
|
||||
cnt = cnt+1;
|
||||
end
|
||||
% yticks([56,75,90,112])
|
||||
% tickse = 1310-[7.5, 12, 17, 31.5];
|
||||
% xticks(flip(tickse));
|
||||
|
||||
xlabel('$\Delta \lambda$ from ZDW [nm]');
|
||||
ylabel('$F_{null}$ [GHz]');
|
||||
grid on; box on;
|
||||
lim=1310-[5,60];
|
||||
xlim([lim(2) lim(1)]);
|
||||
ylim([10,130])
|
||||
legend
|
||||
@@ -1,111 +0,0 @@
|
||||
%% ============================================================
|
||||
% IM/DD Fading Notch Design Map
|
||||
% Shows λ_null vs. bandwidth (f_target) and fiber length (L)
|
||||
% ============================================================
|
||||
|
||||
clear; close all; clc;
|
||||
|
||||
%% Parameters
|
||||
lambda0 = 1310e-9; % Zero-dispersion wavelength [m]
|
||||
S0 = 0.08; % Dispersion slope at ZDW [ps/(nm²·km)]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
% Frequency and length sweep
|
||||
f_targets = linspace(20e9, 140e9, 80); % [Hz] → x-axis
|
||||
L_values = linspace(0.5e3, 12e3, 80); % [m] → y-axis
|
||||
|
||||
% Preallocate result matrices
|
||||
lambda_surface = zeros(numel(L_values), numel(f_targets));
|
||||
Dacc_surface = zeros(numel(L_values), numel(f_targets));
|
||||
|
||||
%% Compute λ_null and Dacc for each (f_target, L)
|
||||
for iL = 1:numel(L_values)
|
||||
L = L_values(iL);
|
||||
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
||||
lambda_surface(iL, :) = lambda_vec; % [m]
|
||||
Dacc_surface(iL, :) = Dacc_vec; % [ps/nm]
|
||||
end
|
||||
|
||||
%% Convert to display units
|
||||
lambda_surface_nm = lambda_surface * 1e9; % [nm]
|
||||
L_km = L_values / 1000; % [km]
|
||||
f_GHz = f_targets / 1e9; % [GHz]
|
||||
|
||||
%% ------------------------------------------------------------
|
||||
% Contour plot (λ_null as function of f_null and L)
|
||||
% ------------------------------------------------------------
|
||||
figure('Color','w');
|
||||
|
||||
% Define wavelength contour levels [nm]
|
||||
lambda_levels = [1260:10:1290, 1290:5:1300, 1300:2:1310];
|
||||
|
||||
contourf(f_GHz, L_km, lambda_surface_nm, lambda_levels, ...
|
||||
'LineWidth', 1.5, ...
|
||||
'ShowText', 'on', ...
|
||||
'LabelFormat', '%1.1d nm');
|
||||
|
||||
% Colormap and colorbar
|
||||
colormap(flip(cbrewer2('RdYlGn',100)));
|
||||
clim([1260 1310]);
|
||||
% c = colorbar;
|
||||
% ylabel(c, 'λ_{null} [nm]', 'Rotation', 90);
|
||||
|
||||
% Axis formatting
|
||||
xlabel('Signal Bandwidth [GHz]');
|
||||
ylabel('Fiber length L [km]');
|
||||
% X-axis ticks (every 16 GHz starting at 56 GHz)
|
||||
xticks(56:8:120);
|
||||
xlim([56,120])
|
||||
grid on; box on;
|
||||
|
||||
%% Optional overlay: accumulated dispersion contours
|
||||
hold on;
|
||||
[CS, h] = contour(f_GHz, L_km, Dacc_surface, 10, 'k--', 'LineWidth', 0.8);
|
||||
clabel(CS, h, 'Color','k', 'FontSize',8);
|
||||
legend('λ_{null} contours','|D_{acc}| [ps/nm]','Location','best');
|
||||
|
||||
%% ============================================================
|
||||
% Helper function: lambda_for_first_null_full
|
||||
% Stable, single-branch, clamped to O-band
|
||||
% ============================================================
|
||||
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
|
||||
c = physconst('lightspeed');
|
||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
||||
|
||||
% Define O-band boundaries (in meters)
|
||||
lambda_min = 1260e-9;
|
||||
lambda_max = 1360e-9;
|
||||
|
||||
% Force column vector
|
||||
f_target = f_target(:);
|
||||
N = numel(f_target);
|
||||
|
||||
lambda_vec = zeros(N,1);
|
||||
Dacc_vec = zeros(N,1);
|
||||
|
||||
for k = 1:N
|
||||
RHS = c * 0.5 / (f_target(k)^2 * L);
|
||||
|
||||
% Normal-dispersion branch (λ < λ0)
|
||||
fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS;
|
||||
|
||||
% Solve within the normal-dispersion range
|
||||
try
|
||||
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
||||
catch
|
||||
lambda_sol = lambda_min;
|
||||
end
|
||||
|
||||
% Clamp to O-band range
|
||||
lambda_sol = min(max(lambda_sol, lambda_min), lambda_max);
|
||||
lambda_vec(k) = lambda_sol;
|
||||
|
||||
% Compute D(lambda) and accumulated dispersion
|
||||
D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km)
|
||||
Dacc_val = D_lambda * (L/1000); % ps/nm
|
||||
|
||||
% Clamp to physical range
|
||||
Dacc_val = min(max(Dacc_val, -100), 100);
|
||||
Dacc_vec(k) = Dacc_val;
|
||||
end
|
||||
end
|
||||
@@ -1,68 +0,0 @@
|
||||
%% ============================================================
|
||||
% IM/DD Power Fading Evolution GIF (1 km -> 20 km)
|
||||
% Uses the provided GifWriter (serial mode)
|
||||
% ============================================================
|
||||
|
||||
clear; close all; clc;
|
||||
|
||||
%% Fiber and system parameters
|
||||
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||
lambda = 1275e-9; % operating wavelength [m]
|
||||
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
%% Derived quantities (length-independent)
|
||||
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
|
||||
D_si = D_lambda * 1e-6; % s/m^2
|
||||
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
|
||||
|
||||
%% Frequency grid
|
||||
f_max = 150e9;
|
||||
f = linspace(0, f_max, 4000); % [Hz]
|
||||
|
||||
%% Figure setup (keep it stable for nicer GIFs)
|
||||
fig = figure('Color','w');
|
||||
ax = axes(fig); %#ok<LAXES>
|
||||
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
|
||||
xlabel(ax,'Frequency [GHz]');
|
||||
ylabel(ax,'Magnitude [dB]');
|
||||
ylim(ax,[-30 0]);
|
||||
xlim(ax,[0 f_max/1e9]);
|
||||
|
||||
%% GIF writer (serial mode; simplest)
|
||||
g = GifWriter('Name','power_fading_evolution', 'DelayTime',0.12, 'Parallel',false);
|
||||
|
||||
%% Loop: 1 km to 20 km
|
||||
L = [1:20,19:-1:1];
|
||||
for L_km = L
|
||||
L_meter = L_km * 1e3; % [m]
|
||||
|
||||
% IM/DD transfer function (power fading)
|
||||
phi = 2*pi^2 * b2 * f.^2 * L_meter;
|
||||
H = abs(cos(phi));
|
||||
HdB = 10*log10(max(H, 1e-12)); % avoid -Inf for deep notches
|
||||
|
||||
% Clear and redraw (stable axes)
|
||||
cla(ax);
|
||||
|
||||
plot(ax, f/1e9, HdB, 'LineWidth', 1.8, 'Color','black');
|
||||
|
||||
% Analytic first-null frequency marker
|
||||
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L_meter));
|
||||
xline(ax, f_null/1e9, 'r--', 'LineWidth', 1.2, ...
|
||||
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||
'LabelOrientation','horizontal', ...
|
||||
'LabelVerticalAlignment','bottom');
|
||||
|
||||
title(ax, sprintf('Power Fading for: %.0f km @ 1275 nm', L_km));
|
||||
|
||||
drawnow;
|
||||
|
||||
% Add frame to GIF
|
||||
g.addFrame(fig);
|
||||
end
|
||||
|
||||
%% Done
|
||||
g.compile(fig.Number);
|
||||
|
||||
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));
|
||||
@@ -1,69 +0,0 @@
|
||||
%% ============================================================
|
||||
% IM/DD Power Fading Evolution vs Wavelength (L = 10 km)
|
||||
% ============================================================
|
||||
|
||||
clear; close all; clc;
|
||||
|
||||
%% Fixed fiber parameters
|
||||
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
|
||||
L = 10e3; % fiber length FIXED [m]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
%% Frequency grid
|
||||
f_max = 150e9;
|
||||
f = linspace(0, f_max, 4000); % [Hz]
|
||||
|
||||
%% Figure setup (stable axes for clean GIF)
|
||||
fig = figure('Color','w');
|
||||
ax = axes(fig);
|
||||
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
|
||||
xlabel(ax,'Frequency [GHz]');
|
||||
ylabel(ax,'Magnitude [dB]');
|
||||
ylim(ax,[-30 0]);
|
||||
xlim(ax,[0 f_max/1e9]);
|
||||
|
||||
%% GIF writer
|
||||
g = GifWriter('Name','power_fading_vs_wavelength', ...
|
||||
'DelayTime',0.12, ...
|
||||
'Parallel',false);
|
||||
|
||||
%% Wavelength sweep (around ZDW)
|
||||
lambda_vec = linspace(1260e-9, 1360e-9, 25); % 1260–1360 nm
|
||||
|
||||
for k = 1:length(lambda_vec)
|
||||
|
||||
lambda = lambda_vec(k);
|
||||
|
||||
%% Dispersion for current wavelength
|
||||
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
|
||||
D_si = D_lambda * 1e-6; % s/m^2
|
||||
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
|
||||
|
||||
%% Power fading transfer function
|
||||
phi = 2*pi^2 * b2 * f.^2 * L;
|
||||
H = abs(cos(phi));
|
||||
HdB = 10*log10(max(H, 1e-12));
|
||||
|
||||
cla(ax)
|
||||
plot(ax, f/1e9, HdB, 'LineWidth',1.8,'Color','black');
|
||||
|
||||
%% First-null frequency
|
||||
if abs(D_si) > 0
|
||||
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L));
|
||||
xline(ax, f_null/1e9, 'r--', 'LineWidth',1.2, ...
|
||||
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||
'LabelOrientation','horizontal', ...
|
||||
'LabelVerticalAlignment','bottom');
|
||||
end
|
||||
|
||||
title(ax, sprintf('Power Fading for: 10 km @ %.0f nm', lambda*1e9));
|
||||
|
||||
drawnow;
|
||||
g.addFrame(fig);
|
||||
end
|
||||
|
||||
%% Compile GIF
|
||||
g.compile(fig.Number);
|
||||
|
||||
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
||||
1271; 0,3822390561953123
|
||||
1271,5; 0,38419930758242105
|
||||
1272; 0,3863702270698115
|
||||
1272,5; 0,38866381361008207
|
||||
1273; 0,3879395121421424
|
||||
1273,5; 0,3908144071258651
|
||||
1274; 0,38941324484667683
|
||||
1274,5; 0,3886482390643653
|
||||
1275; 0,3871744844466787
|
||||
1275,5; 0,3819131706099883
|
||||
1276; 0,3825696588771148
|
||||
1276,5; 0,38164278490690173
|
||||
1277; 0,3793811681135283
|
||||
1277,5; 0,3810969321121832
|
||||
1278; 0,38561783928242943
|
||||
1278,5; 0,38908016962932246
|
||||
1279; 0,3960805723111348
|
||||
1279,5; 0,39776514973186317
|
||||
1280; 0,3983882080762364
|
||||
1280,5; 0,3989277489532531
|
||||
1281; 0,3953941895319796
|
||||
1281,5; 0,39648781234375075
|
||||
1282; 0,3966742531971841
|
||||
1282,5; 0,4002652938704556
|
||||
1283; 0,40694867274287283
|
||||
1283,5; 0,41253621540584107
|
||||
1284; 0,42331258033724095
|
||||
1284,5; 0,43077624043193397
|
||||
1285; 0,4393232961230962
|
||||
1285,5; 0,44562110387213405
|
||||
1286; 0,4486108628977331
|
||||
1286,5; 0,4511055411347422
|
||||
1287; 0,4470620968166301
|
||||
1287,5; 0,4429754327671611
|
||||
1288; 0,4369760292430348
|
||||
1288,5; 0,4313232143283202
|
||||
1289; 0,4297225921323986
|
||||
1289,5; 0,42752981686391456
|
||||
1290; 0,42755873451486015
|
||||
1290,5; 0,42838607683209784
|
||||
1291; 0,4301647938813945
|
||||
1291,5; 0,430252773791754
|
||||
1292; 0,42983642955282675
|
||||
1292,5; 0,43082456782130385
|
||||
1293; 0,43010358194135434
|
||||
1293,5; 0,4286564203011507
|
||||
1294; 0,427551350387675
|
||||
1294,5; 0,4262216680056993
|
||||
1295; 0,4248061879636029
|
||||
1295,5; 0,42323824957412115
|
||||
1296; 0,42606502803639024
|
||||
1296,5; 0,42771450181627213
|
||||
1297; 0,4321631047010831
|
||||
1297,5; 0,43498514011363654
|
||||
1298; 0,43784261304613636
|
||||
1298,5; 0,4407749972159394
|
||||
1299; 0,4418422146980885
|
||||
1299,5; 0,44599734720216344
|
||||
1300; 0,44682291369874283
|
||||
1300,5; 0,44591438239702175
|
||||
1301; 0,4467439544276042
|
||||
1301,5; 0,4476723529309602
|
||||
1302; 0,44945964164622887
|
||||
1302,5; 0,451298649370644
|
||||
1303; 0,4555133819899133
|
||||
1303,5; 0,45932593779132214
|
||||
1304; 0,4641282326427819
|
||||
1304,5; 0,4660504121662704
|
||||
1305; 0,4672659916854359
|
||||
1305,5; 0,46826040808978875
|
||||
1306; 0,4672565627341473
|
||||
1306,5; 0,46494462666243797
|
||||
1307; 0,4614228682537902
|
||||
1307,5; 0,4594403315234107
|
||||
1308; 0,4567366055619595
|
||||
1308,5; 0,4543323943556662
|
||||
1309; 0,4531865329043713
|
||||
1309,5; 0,4531463334993213
|
||||
1310; 0,4549753124500232
|
||||
1310,5; 0,4563928182609638
|
||||
1311; 0,45807413408326114
|
||||
1311,5; 0,46008646903182826
|
||||
1312; 0,4625724677767604
|
||||
1312,5; 0,4642585362150724
|
||||
1313; 0,46443821082811676
|
||||
1313,5; 0,46431357981151344
|
||||
1314; 0,46266595309664715
|
||||
1314,5; 0,4634382042743632
|
||||
1315; 0,46336655819789074
|
||||
1315,5; 0,46220084770212755
|
||||
1316; 0,4621345192553813
|
||||
1316,5; 0,4619581088515051
|
||||
1317; 0,4622449432593938
|
||||
1317,5; 0,4634433901557192
|
||||
1318; 0,46570049058443497
|
||||
1318,5; 0,46746148714378144
|
||||
1319; 0,47051648811702607
|
||||
1319,5; 0,4736426053778652
|
||||
1320; 0,4752061192279773
|
||||
1320,5; 0,47672990706900487
|
||||
1321; 0,4792517016402914
|
||||
1321,5; 0,4804619217778243
|
||||
1322; 0,48045944968999643
|
||||
1322,5; 0,48044446341935276
|
||||
1323; 0,48033475585370833
|
||||
1323,5; 0,48149717921878865
|
||||
1324; 0,4825722899403748
|
||||
1324,5; 0,4815908698039817
|
||||
1325; 0,47971434550698255
|
||||
1325,5; 0,47939560128213987
|
||||
1326; 0,47928833048577313
|
||||
1326,5; 0,4780400467999897
|
||||
1327; 0,47648974188994153
|
||||
1327,5; 0,47504778426945493
|
||||
1328; 0,4767823647690562
|
||||
1328,5; 0,4796497575996306
|
||||
1329; 0,48149796255153543
|
||||
1329,5; 0,48293054311361827
|
||||
1330; 0,48577046817752123
|
||||
1330,5; 0,4879484457550308
|
||||
1331; 0,4890100791953129
|
||||
1331,5; 0,49009094527466934
|
||||
1332; 0,49064503921138825
|
||||
1332,5; 0,4912120163422964
|
||||
1333; 0,49112778494545795
|
||||
1333,5; 0,49082017761106833
|
||||
1334; 0,4891140575382411
|
||||
1334,5; 0,48897830241499407
|
||||
1335; 0,49041975188209885
|
||||
1335,5; 0,49289447360952865
|
||||
1336; 0,4941116428265213
|
||||
1336,5; 0,49433827868707936
|
||||
1337; 0,49545156946075475
|
||||
1337,5; 0,4964012858510567
|
||||
1338; 0,4976037918135337
|
||||
1338,5; 0,4975359556660308
|
||||
1339; 0,49750995144010873
|
||||
1339,5; 0,4979126497053521
|
||||
1340; 0,497475232138574
|
||||
1340,5; 0,49759401707965406
|
||||
1341; 0,4969075828334858
|
||||
1341,5; 0,49790859550840155
|
||||
1342; 0,4995926776094223
|
||||
1342,5; 0,5020720343160757
|
||||
1343; 0,5055918669106463
|
||||
1343,5; 0,5084877122557891
|
||||
1344; 0,5109238856077332
|
||||
1344,5; 0,5133476480224053
|
||||
1345; 0,5141099804906323
|
||||
1345,5; 0,5128794457064829
|
||||
1346; 0,5123127905211531
|
||||
1346,5; 0,5113593533744085
|
||||
1347; 0,5104375198088649
|
||||
1347,5; 0,5085465423276292
|
||||
1348; 0,5051624771364174
|
||||
1348,5; 0,5027410542553522
|
||||
1349; 0,5024260057256427
|
||||
1349,5; 0,5006762680057522
|
||||
1350; 0,4993251970666754
|
||||
1350,5; 0,49851742723413256
|
||||
1351; 0,4997497443709538
|
||||
1351,5; 0,5007398590455319
|
||||
1352; 0,5007983935913018
|
||||
1352,5; 0,49955251820707475
|
||||
1353; 0,4995544623158038
|
||||
1353,5; 0,5007503896118954
|
||||
1354; 0,500737054751544
|
||||
1354,5; 0,5007708386435341
|
||||
1355; 0,49980743334640554
|
||||
1355,5; 0,49964682618339445
|
||||
1356; 0,5007641635781113
|
||||
1356,5; 0,5010692724813779
|
||||
1357; 0,5017795860327432
|
||||
1357,5; 0,5018051896000885
|
||||
1358; 0,5018027877181053
|
||||
1358,5; 0,5024950398138555
|
||||
1359; 0,5037205512345401
|
||||
1359,5; 0,503981020991427
|
||||
1360; 0,50290329982148
|
||||
1360,5; 0,5017820667010949
|
||||
1361; 0,5029651424174117
|
||||
1361,5; 0,5021824944534237
|
||||
1362; 0,5007892395452416
|
||||
1362,5; 0,4997500743708827
|
||||
1363; 0,5006844796799776
|
||||
1363,5; 0,5020955167671433
|
||||
1364; 0,5059166193037108
|
||||
1364,5; 0,5043160514940865
|
||||
1365; 0,4996516521717823
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,336 +0,0 @@
|
||||
-7,105427357601002e-15; -0,20522295068752294
|
||||
0,19999999999999574; -0,030254119194939477
|
||||
0,39999999999998437; -0,06262230958084825
|
||||
0,5999999999999943; -0,044750988038462225
|
||||
0,79999999999999; -0,010697832675218066
|
||||
0,9999999999999929; -0,007716070877040071
|
||||
1,1999999999999886; -0,0034636603575668445
|
||||
1,3999999999999915; -0,0031910951680633737
|
||||
1,5999999999999943; -0,018902533473217353
|
||||
1,79999999999999; -0,053402356238265725
|
||||
1,9999999999999858; -0,016020039340308045
|
||||
2,1999999999999957; -0,03803455116762944
|
||||
2,3999999999999915; -0,027441706124275544
|
||||
2,5999999999999943; -0,011772163020613569
|
||||
2,799999999999997; -0,009307744420832709
|
||||
2,999999999999993; -0,004522003719798828
|
||||
3,1999999999999957; -0,004428713345979496
|
||||
3,3999999999999986; -0,004366538233070205
|
||||
3,6000000000000014; -0,004332966081604717
|
||||
3,8000000000000043; -0,004325484592115458
|
||||
3,999999999999993; -0,00434158146513397
|
||||
4,200000000000003; -0,004378744401192236
|
||||
4,3999999999999915; -0,004434461100823572
|
||||
4,599999999999994; -0,004506219264559075
|
||||
4,800000000000004; -0,004691539083670371
|
||||
5; -0,003991004145723398
|
||||
5,200000000000003; -0,003246645775397461
|
||||
5,3999999999999915; -0,0037896250865734338
|
||||
5,599999999999994; -0,023040865733948923
|
||||
5,799999999999997; -0,01989208568211387
|
||||
5,999999999999993; -0,0010096736725997424
|
||||
6,199999999999996; -0,013640471154773515
|
||||
6,399999999999999; -0,022016055829107817
|
||||
6,599999999999994; -0,02380673595648508
|
||||
6,799999999999997; -0,010201242210113204
|
||||
7; -0,004611668103098321
|
||||
7,200000000000003; -0,006761186983221812
|
||||
7,399999999999999; -0,014690649105665976
|
||||
7,600000000000001; -0,00390457347586759
|
||||
7,799999999999997; -0,045710767178201106
|
||||
8; -0,051072792534853306
|
||||
8,199999999999996; -0,07115209529133537
|
||||
8,399999999999991; -0,08208254896261469
|
||||
8,599999999999994; -0,03145294469160209
|
||||
8,799999999999997; -0,05983935104068827
|
||||
8,999999999999993; -0,03242609227466575
|
||||
9,199999999999996; -0,08006336213732856
|
||||
9,399999999999999; -0,07616115793078393
|
||||
9,599999999999994; -0,06914618045986609
|
||||
9,79999999999999; -0,0980170516533656
|
||||
9,999999999999979; -0,09444267414680585
|
||||
10,199999999999996; -0,1296597291950028
|
||||
10,399999999999999; -0,11722924677565816
|
||||
10,599999999999987; -0,1261332014641745
|
||||
10,799999999999983; -0,14295450195563753
|
||||
10,999999999999986; -0,13583779081780678
|
||||
11,199999999999989; -0,13655730701500968
|
||||
11,399999999999991; -0,1528394332576566
|
||||
11,59999999999998; -0,1455635480829094
|
||||
11,799999999999983; -0,15279717820688443
|
||||
11,999999999999986; -0,10865677433838528
|
||||
12,199999999999982; -0,08239755649864788
|
||||
12,39999999999997; -0,09832039720463737
|
||||
12,59999999999998; -0,09759344817184923
|
||||
12,799999999999983; -0,08609094120940997
|
||||
12,999999999999986; -0,13125303885294937
|
||||
13,199999999999982; -0,17127202835872835
|
||||
13,399999999999977; -0,17693756228526825
|
||||
13,599999999999987; -0,17588170560175698
|
||||
13,799999999999976; -0,21097131291045912
|
||||
13,999999999999979; -0,19723442280681303
|
||||
14,199999999999974; -0,17157649801758756
|
||||
14,399999999999977; -0,18397126413186138
|
||||
14,599999999999973; -0,22900338921732688
|
||||
14,799999999999969; -0,2093816161727191
|
||||
14,999999999999972; -0,19030766934459553
|
||||
15,199999999999974; -0,1930304944542227
|
||||
15,39999999999997; -0,16656555782418714
|
||||
15,599999999999959; -0,17578057654064638
|
||||
15,799999999999962; -0,18022738188194465
|
||||
15,999999999999964; -0,20411747466271102
|
||||
16,199999999999967; -0,24005694593094873
|
||||
16,39999999999997; -0,2409966294337953
|
||||
16,59999999999996; -0,23769655914941312
|
||||
16,79999999999996; -0,2461254200795704
|
||||
16,999999999999964; -0,18731174872333556
|
||||
17,199999999999967; -0,2088294036646947
|
||||
17,39999999999997; -0,26222359684914354
|
||||
17,59999999999996; -0,2627551021676209
|
||||
17,799999999999976; -0,23263650093640598
|
||||
17,99999999999995; -0,25096659518845055
|
||||
18,199999999999967; -0,28136295333973704
|
||||
18,399999999999956; -0,26386838346721
|
||||
18,599999999999945; -0,2697397873853724
|
||||
18,79999999999996; -0,27151761208872793
|
||||
18,99999999999995; -0,30006432628995094
|
||||
19,199999999999953; -0,32687710754417765
|
||||
19,39999999999997; -0,34133822014109505
|
||||
19,599999999999945; -0,35107178825199314
|
||||
19,79999999999996; -0,3207896032858475
|
||||
19,999999999999964; -0,3126066108279488
|
||||
20,199999999999953; -0,3015988268627865
|
||||
20,399999999999956; -0,32309268875395514
|
||||
20,59999999999996; -0,29037807883314093
|
||||
20,79999999999996; -0,2922929925308506
|
||||
20,99999999999995; -0,34985423889611633
|
||||
21,199999999999953; -0,36118780832491426
|
||||
21,399999999999956; -0,3251998242712628
|
||||
21,599999999999945; -0,2462767056035915
|
||||
21,799999999999933; -0,24441110825428503
|
||||
21,99999999999995; -0,2563960865160375
|
||||
22,19999999999994; -0,2437759650962339
|
||||
22,399999999999956; -0,22035942863831393
|
||||
22,59999999999996; -0,18593789159821306
|
||||
22,799999999999947; -0,1580165418909094
|
||||
22,99999999999995; -0,16755721915183486
|
||||
23,19999999999994; -0,20252844881319776
|
||||
23,399999999999913; -0,22661159302112166
|
||||
23,599999999999945; -0,24267584629923267
|
||||
23,799999999999933; -0,29043098079506846
|
||||
23,999999999999936; -0,32759458048731993
|
||||
24,19999999999994; -0,35261052927411507
|
||||
24,39999999999994; -0,4205920563168606
|
||||
24,599999999999945; -0,40505099517955756
|
||||
24,799999999999947; -0,39978925053876324
|
||||
24,999999999999936; -0,4143117703519099
|
||||
25,19999999999994; -0,4219338489372779
|
||||
25,399999999999928; -0,4610014796748456
|
||||
25,59999999999993; -0,47018850098853804
|
||||
25,799999999999947; -0,4491839028784197
|
||||
25,999999999999936; -0,4458017205576206
|
||||
26,199999999999925; -0,5003597628349712
|
||||
26,39999999999994; -0,5150256066968306
|
||||
26,599999999999916; -0,5045451019191436
|
||||
26,799999999999933; -0,5133285112874519
|
||||
26,999999999999922; -0,527155709897416
|
||||
27,19999999999994; -0,5140685424201781
|
||||
27,399999999999928; -0,49851201964752834
|
||||
27,599999999999916; -0,5137853037079538
|
||||
27,79999999999992; -0,5372179267072128
|
||||
27,999999999999936; -0,5680498018750453
|
||||
28,199999999999925; -0,5098792124208722
|
||||
28,399999999999928; -0,5261932637134765
|
||||
28,59999999999993; -0,5420533092094892
|
||||
28,799999999999933; -0,5905815675266202
|
||||
28,999999999999936; -0,6278889530493021
|
||||
29,19999999999991; -0,6751232569663901
|
||||
29,399999999999913; -0,6417648030574505
|
||||
29,599999999999916; -0,6296852646307589
|
||||
29,79999999999992; -0,6731708512242238
|
||||
29,999999999999908; -0,6766999836256802
|
||||
30,199999999999925; -0,6439858043186271
|
||||
30,399999999999928; -0,6626801183278261
|
||||
30,599999999999916; -0,6575261415486628
|
||||
30,79999999999992; -0,5997705615017357
|
||||
30,999999999999908; -0,5811412251277055
|
||||
31,19999999999994; -0,6232767821070331
|
||||
31,399999999999913; -0,6936652252154754
|
||||
31,599999999999902; -0,7251977840976562
|
||||
31,79999999999992; -0,756817987398668
|
||||
31,999999999999908; -0,7626095276161258
|
||||
32,199999999999925; -0,6998981751538662
|
||||
32,39999999999991; -0,6934363825152801
|
||||
32,599999999999916; -0,7182913332333944
|
||||
32,79999999999992; -0,6821687933338616
|
||||
32,99999999999992; -0,6663845829793131
|
||||
33,19999999999991; -0,6790941839387248
|
||||
33,399999999999956; -0,7261666896639514
|
||||
33,59999999999993; -0,7451168856292525
|
||||
33,79999999999995; -0,7934809742704192
|
||||
33,999999999999936; -0,7510223153439268
|
||||
34,19999999999994; -0,7443418303903386
|
||||
34,39999999999994; -0,7371085317015025
|
||||
34,599999999999945; -0,7272823230638554
|
||||
34,79999999999995; -0,7718051044043159
|
||||
34,99999999999995; -0,8073906768142964
|
||||
35,19999999999994; -0,7385956882940454
|
||||
35,399999999999956; -0,7160082880884686
|
||||
35,59999999999996; -0,7288095360695297
|
||||
35,79999999999996; -0,7236002865254121
|
||||
35,999999999999964; -0,7334442970172868
|
||||
36,19999999999997; -0,8346252066934827
|
||||
36,39999999999997; -0,8358944542314521
|
||||
36,59999999999996; -0,8009380638643022
|
||||
36,79999999999995; -0,7673865510270743
|
||||
36,99999999999998; -0,7199971905956084
|
||||
37,19999999999997; -0,7007463840971893
|
||||
37,399999999999984; -0,7387659310023729
|
||||
37,59999999999997; -0,721690739663293
|
||||
37,799999999999976; -0,657816129243038
|
||||
37,999999999999964; -0,6495576293842058
|
||||
38,20000000000001; -0,6597731574058532
|
||||
38,399999999999984; -0,672563855947323
|
||||
38,6; -0,6904033318178788
|
||||
38,79999999999999; -0,689336430830561
|
||||
39,00000000000002; -0,6117300762411118
|
||||
39,199999999999996; -0,5639205810793819
|
||||
39,40000000000001; -0,5983607766144563
|
||||
39,6; -0,5559212159038944
|
||||
39,80000000000002; -0,42213980065065204
|
||||
40,00000000000001; -0,41577016450588733
|
||||
40,20000000000004; -0,41077502582773695
|
||||
40,40000000000001; -0,4494641339488026
|
||||
40,600000000000044; -0,5314018055872878
|
||||
40,80000000000002; -0,641785834906464
|
||||
41,00000000000005; -0,7108648438969745
|
||||
41,200000000000024; -0,6859741311599707
|
||||
41,400000000000055; -0,7017068191441105
|
||||
41,60000000000003; -0,6791477498478518
|
||||
41,80000000000005; -0,653540590898162
|
||||
42,00000000000005; -0,6660836110606962
|
||||
42,20000000000007; -0,6129974635842999
|
||||
42,400000000000055; -0,5886674503992548
|
||||
42,60000000000007; -0,5864375705241724
|
||||
42,80000000000006; -0,5934101604542863
|
||||
43,000000000000064; -0,5971640717600168
|
||||
43,20000000000005; -0,687945370263789
|
||||
43,400000000000084; -0,826010895068702
|
||||
43,60000000000007; -0,8402202033545532
|
||||
43,80000000000009; -0,8155286496095027
|
||||
44,00000000000008; -0,7732529679765467
|
||||
44,20000000000008; -0,7804047850500297
|
||||
44,400000000000084; -0,7186911944635885
|
||||
44,6000000000001; -0,6952708619187691
|
||||
44,80000000000009; -0,6796908471847463
|
||||
45,00000000000011; -0,6791911674601883
|
||||
45,20000000000008; -0,750294196595163
|
||||
45,400000000000084; -0,8751930740148532
|
||||
45,6000000000001; -0,9276382447045544
|
||||
45,800000000000104; -0,9719742530818682
|
||||
46,00000000000011; -1,036079323202311
|
||||
46,20000000000011; -1,1181471052790317
|
||||
46,4000000000001; -1,0958490215727856
|
||||
46,60000000000013; -1,0625635604160188
|
||||
46,80000000000012; -1,0681184335495777
|
||||
47,00000000000011; -1,0491794786564261
|
||||
47,20000000000011; -1,0004949273189419
|
||||
47,40000000000013; -1,0264013117471569
|
||||
47,600000000000115; -0,9884102239645856
|
||||
47,80000000000013; -0,9894223247725593
|
||||
48,00000000000012; -1,0796700017398213
|
||||
48,20000000000014; -1,099628578912291
|
||||
48,40000000000011; -0,9509643943244526
|
||||
48,60000000000016; -0,9037231717547249
|
||||
48,80000000000013; -0,8528339219613446
|
||||
49,000000000000135; -0,858999004045224
|
||||
49,20000000000014; -0,9168300378510152
|
||||
49,400000000000155; -0,9577590379052632
|
||||
49,60000000000013; -0,999788695384078
|
||||
49,80000000000016; -1,0093627559760772
|
||||
50,00000000000015; -1,0138490875975479
|
||||
50,200000000000166; -1,0664495148931095
|
||||
50,400000000000155; -1,2154632152797502
|
||||
50,60000000000017; -1,1788818515429793
|
||||
50,800000000000146; -1,050269845638372
|
||||
51,00000000000019; -1,0622383145312964
|
||||
51,200000000000166; -1,1841450735158365
|
||||
51,4000000000002; -1,139376215918372
|
||||
51,60000000000017; -1,119440531745798
|
||||
51,8000000000002; -1,187468605994586
|
||||
52,00000000000018; -1,1953550362808736
|
||||
52,20000000000021; -1,269604124857581
|
||||
52,40000000000018; -1,3849421747096078
|
||||
52,6000000000002; -1,3718481353189649
|
||||
52,80000000000019; -1,3954600140641764
|
||||
53,00000000000022; -1,3942562465749204
|
||||
53,20000000000021; -1,4042931940245014
|
||||
53,400000000000226; -1,3795400304760106
|
||||
53,600000000000215; -1,4371475323268652
|
||||
53,80000000000023; -1,4680470055475139
|
||||
54,00000000000022; -1,4956152610708555
|
||||
54,20000000000024; -1,4599173760734971
|
||||
54,400000000000226; -1,3804207925357423
|
||||
54,60000000000023; -1,4209447553401664
|
||||
54,80000000000023; -1,4696589593832408
|
||||
55,00000000000025; -1,3473971465483299
|
||||
55,20000000000024; -1,2804811618109628
|
||||
55,40000000000024; -1,1931187716667573
|
||||
55,60000000000023; -1,1499753811035252
|
||||
55,80000000000026; -1,1787726888220313
|
||||
56,000000000000234; -1,1932811246412953
|
||||
56,20000000000025; -1,259756294621234
|
||||
56,40000000000024; -1,2340584671567725
|
||||
56,60000000000027; -1,1917426282230785
|
||||
56,800000000000246; -1,2255018834858493
|
||||
57,00000000000026; -1,2903085954845714
|
||||
57,200000000000266; -1,3799715177434764
|
||||
57,40000000000027; -1,4961435623060653
|
||||
57,60000000000026; -1,5184418601914111
|
||||
57,800000000000274; -1,4156967177433764
|
||||
58,00000000000025; -1,4701539637874377
|
||||
58,200000000000266; -1,545782763600434
|
||||
58,40000000000027; -1,5486404166502283
|
||||
58,600000000000286; -1,607511180291636
|
||||
58,80000000000026; -1,5918971528251729
|
||||
59,00000000000028; -1,7420918696456886
|
||||
59,20000000000028; -1,8688832280161232
|
||||
59,4000000000003; -1,9018553915656242
|
||||
59,600000000000286; -1,9313949044976835
|
||||
59,8000000000003; -1,7488759443354804
|
||||
60,000000000000306; -1,5879219632492743
|
||||
60,20000000000031; -1,5322688722554756
|
||||
60,40000000000028; -1,4779441671503282
|
||||
60,600000000000314; -1,3053954056727393
|
||||
60,8000000000003; -1,161200232220056
|
||||
61,00000000000032; -1,0852609076693227
|
||||
61,20000000000031; -1,039861302109443
|
||||
61,400000000000325; -1,0938817679702129
|
||||
61,600000000000314; -1,2827795990288489
|
||||
61,80000000000032; -1,4418988356213176
|
||||
62,000000000000306; -1,4887272875332065
|
||||
62,20000000000034; -1,3858016155912871
|
||||
62,400000000000325; -1,4386165299344782
|
||||
62,60000000000034; -1,623474266607849
|
||||
62,800000000000345; -1,6269465129654068
|
||||
63,00000000000035; -1,4835041232913464
|
||||
63,20000000000034; -1,4192369875578938
|
||||
63,40000000000037; -1,393348402668435
|
||||
63,60000000000036; -1,46529616679921
|
||||
63,800000000000374; -1,500508185495117
|
||||
64,00000000000037; -1,6190473360126991
|
||||
64,20000000000036; -1,7519875508476201
|
||||
64,40000000000035; -1,7562809083561022
|
||||
64,60000000000036; -1,969973816098435
|
||||
64,80000000000035; -2,0604805496803844
|
||||
65,00000000000037; -2,0818983868245247
|
||||
65,20000000000036; -2,096459467198311
|
||||
65,40000000000038; -2,2014641556121233
|
||||
65,60000000000039; -1,996828898735267
|
||||
65,80000000000038; -1,6692235197112448
|
||||
66,00000000000037; -1,4111710117485514
|
||||
66,20000000000039; -1,4616886686912545
|
||||
66,40000000000038; -1,6079210184093582
|
||||
66,60000000000039; -1,5839852165659427
|
||||
66,80000000000038; -1,583493358599156
|
||||
67,0000000000004; -1,3918025284299995
|
||||
|
@@ -1,166 +0,0 @@
|
||||
1270,8549581839902; 0,5258998226950353
|
||||
1270,743369175627; 0,5221430916732335
|
||||
1271,0781362007167; 0,5309982433674809
|
||||
1271,3013142174432; 0,5350233123194115
|
||||
1271,5244922341694; 0,5385117054110848
|
||||
1271,747670250896; 0,5428051122931441
|
||||
1271,9708482676224; 0,5468301812450749
|
||||
1272,305615292712; 0,5498713444532002
|
||||
1272,9751493428912; 0,5484402088258471
|
||||
1273,5330943847073; 0,5470985191752036
|
||||
1273,7562724014335; 0,5441468019437876
|
||||
1273,867861409797; 0,5398533950617284
|
||||
1274,0910394265231; 0,5377066916206987
|
||||
1274,3142174432496; 0,5337710686454775
|
||||
1274,8721624850657; 0,5309982433674809
|
||||
1275,4301075268816; 0,526615390508712
|
||||
1276,0996415770608; 0,5275098502758077
|
||||
1276,76917562724; 0,5296565537168374
|
||||
1277,4387096774192; 0,5305510134839331
|
||||
1278,1082437275984; 0,5325188249715436
|
||||
1278,7777777777776; 0,5350233123194115
|
||||
1279,4473118279568; 0,5344866364591541
|
||||
1280,116845878136; 0,5348444203659923
|
||||
1280,674790919952; 0,5369016778303125
|
||||
1281,1211469534048; 0,5409267467822432
|
||||
1281,5675029868578; 0,5438784640136589
|
||||
1281,790681003584; 0,5465618433149462
|
||||
1282,0510553564316; 0,5502291283600385
|
||||
1282,5718040621266; 0,554701427195517
|
||||
1283,2413381123058; 0,5545225352420978
|
||||
1283,910872162485; 0,553449183521583
|
||||
1284,5804062126642; 0,5489768846861045
|
||||
1285,13835125448; 0,5454884915944312
|
||||
1285,6962962962962; 0,5425367743630154
|
||||
1286,2542413381123; 0,5422684364328867
|
||||
1286,8121863799283; 0,5459357214779792
|
||||
1287,3701314217442; 0,5495135605463619
|
||||
1287,7792911190759; 0,553449183521583
|
||||
1288,0396654719234; 0,557832036380352
|
||||
1288,2628434886499; 0,5615887674021538
|
||||
1288,4860215053764; 0,5653454984239559
|
||||
1288,7463958582237; 0,5695494593293056
|
||||
1289,1555555555556; 0,5742006501182033
|
||||
1289,7135005973714; 0,5784940570002626
|
||||
1290,3830346475506; 0,5781362730934243
|
||||
1290,9409796893667; 0,5752740018387181
|
||||
1291,1641577060932; 0,57071225702653
|
||||
1291,3873357228194; 0,5672238639348568
|
||||
1291,610513739546; 0,5640038087733122
|
||||
1291,9452807646355; 0,5606048616583486
|
||||
1292,5032258064516; 0,555953670869451
|
||||
1293,0611708482675; 0,554701427195517
|
||||
1293,7307048984467; 0,5570270225899658
|
||||
1294,2886499402628; 0,5586370501707381
|
||||
1294,8465949820788; 0,5618571053322825
|
||||
1295,4045400238947; 0,5645404846335697
|
||||
1295,9624850657108; 0,5672238639348568
|
||||
1296,63201911589; 0,5672238639348568
|
||||
1297,3015531660692; 0,5654349444006653
|
||||
1297,9710872162484; 0,5627515650993782
|
||||
1298,6406212664276; 0,5614993214254442
|
||||
1299,3101553166068; 0,5625726731459592
|
||||
1299,979689366786; 0,5640038087733122
|
||||
1300,6492234169652; 0,5656138363540846
|
||||
1301,3187574671445; 0,5656138363540846
|
||||
1301,9882915173237; 0,5652560524472463
|
||||
1302,6578255675029; 0,5618571053322825
|
||||
1303,327359617682; 0,5584581582173189
|
||||
1303,9968936678613; 0,5563114547762892
|
||||
1304,6664277180405; 0,5543436432886787
|
||||
1305,3359617682197; 0,5539858593818404
|
||||
1305,8939068100358; 0,555953670869451
|
||||
1306,3402628434885; 0,5589053881008668
|
||||
1306,7866188769412; 0,56239378119254
|
||||
1307,2329749103942; 0,5656138363540846
|
||||
1307,679330943847; 0,5693705673758864
|
||||
1308,237275985663; 0,5722328386305927
|
||||
1308,9068100358422; 0,5713383788634969
|
||||
1309,464755077658; 0,5691022294457577
|
||||
1309,911111111111; 0,5658821742842133
|
||||
1310,3574671445638; 0,5634671329130548
|
||||
1310,8038231780165; 0,560515415681639
|
||||
1311,3617682198326; 0,5579214823570615
|
||||
1312,0313022700118; 0,5582792662638998
|
||||
1312,700836320191; 0,5604259697049294
|
||||
1313,3703703703702; 0,5627515650993782
|
||||
1313,9283154121863; 0,5645404846335697
|
||||
1314,374671445639; 0,5674922018649855
|
||||
1315,1557945041816; 0,5704439190964012
|
||||
1315,8253285543608; 0,5708017030032395
|
||||
1316,49486260454; 0,5715172708169162
|
||||
1317,1643966547192; 0,5722328386305927
|
||||
1317,8339307048984; 0,5727695144908501
|
||||
1318,5034647550776; 0,5715172708169162
|
||||
1319,1729988052568; 0,5711594869100779
|
||||
1319,842532855436; 0,5693705673758864
|
||||
1320,5120669056153; 0,5693705673758864
|
||||
1321,1816009557945; 0,5686549995622099
|
||||
1321,8511350059737; 0,5679394317485333
|
||||
1322,5206690561529; 0,5650771604938272
|
||||
1323,190203106332; 0,5645404846335697
|
||||
1323,8597371565113; 0,566150512214342
|
||||
1324,5292712066905; 0,5682972156553716
|
||||
1325,0872162485064; 0,5712489328867874
|
||||
1325,6451612903224; 0,5747373259784607
|
||||
1326,2031063321385; 0,5779573811400052
|
||||
1326,7610513739544; 0,5811774363015497
|
||||
1327,4305854241336; 0,5833241397425795
|
||||
1328,100119474313; 0,5861864109972856
|
||||
1328,7696535244922; 0,5858286270904474
|
||||
1329,4391875746715; 0,5833241397425795
|
||||
1330,1087216248507; 0,5822507880220645
|
||||
1330,7782556750299; 0,5833241397425795
|
||||
1331,447789725209; 0,5833241397425795
|
||||
1332,1173237753883; 0,5843974914630943
|
||||
1332,7868578255675; 0,5869019788109622
|
||||
1333,4563918757467; 0,5876175466246387
|
||||
1334,125925925926; 0,5883331144383153
|
||||
1334,7954599761051; 0,5895853581122492
|
||||
1335,4649940262843; 0,5901220339725066
|
||||
1336,1345280764635; 0,5883331144383153
|
||||
1336,8040621266427; 0,5869019788109622
|
||||
1337,473596176822; 0,5843974914630943
|
||||
1338,1431302270012; 0,5811774363015497
|
||||
1338,8126642771804; 0,5801040845810348
|
||||
1339,4821983273596; 0,5808196523947114
|
||||
1340,1517323775388; 0,5831452477891602
|
||||
1340,821266427718; 0,5849341673233517
|
||||
1341,3792114695339; 0,58734920869451
|
||||
1341,93715651135; 0,5903009259259259
|
||||
1342,6066905615291; 0,5919109535066981
|
||||
1343,2762246117084; 0,5919109535066981
|
||||
1343,9457586618876; 0,592984305227213
|
||||
1344,6152927120668; 0,5936998730408896
|
||||
1345,284826762246; 0,5944154408545661
|
||||
1345,9543608124252; 0,5962043603887575
|
||||
1346,6238948626044; 0,599424415550302
|
||||
1347,0702508960571; 0,6004977672708168
|
||||
1347,9629629629628; 0,5997821994571403
|
||||
1348,632497013142; 0,6012133350844935
|
||||
1349,3020310633212; 0,6033600385255231
|
||||
1349,9715651135004; 0,6033600385255231
|
||||
1350,6410991636797; 0,6037178224323614
|
||||
1351,3106332138589; 0,605864525873391
|
||||
1351,980167264038; 0,6078323373610015
|
||||
1352,6497013142173; 0,6094423649417738
|
||||
1353,3192353643965; 0,6112312844759653
|
||||
1353,9887694145757; 0,6123046361964801
|
||||
1354,658303464755; 0,6123046361964801
|
||||
1355,3278375149341; 0,6135568798704141
|
||||
1355,8857825567502; 0,6168663810086681
|
||||
1356,332138590203; 0,6206231120304702
|
||||
1356,890083632019; 0,6241115051221433
|
||||
1357,5596176821982; 0,626258208563173
|
||||
1358,2291517323774; 0,6248270729358198
|
||||
1358,8986857825566; 0,6230381534016285
|
||||
1359,4566308243727; 0,619818098240084
|
||||
1360,0145758661886; 0,6171347189387969
|
||||
1360,6841099163678; 0,617313610892216
|
||||
1361,353643966547; 0,6176713947990543
|
||||
1362,0231780167262; 0,61856585456615
|
||||
1362,6927120669054; 0,6192814223798266
|
||||
1363,1390681003584; 0,6225014775413711
|
||||
1363,585424133811; 0,626258208563173
|
||||
1364,2549581839903; 0,6284049120042028
|
||||
1364,8129032258064; 0,630014939584975
|
||||
|
@@ -1,66 +0,0 @@
|
||||
opts = delimitedTextImportOptions("NumVariables", 2);
|
||||
|
||||
% Specify range and delimiter
|
||||
opts.DataLines = [1, Inf];
|
||||
opts.Delimiter = ";";
|
||||
|
||||
% Specify column names and types
|
||||
opts.VariableNames = ["x0_03203105428566744", "x_0_09762908467719589"];
|
||||
opts.VariableTypes = ["double", "double"];
|
||||
|
||||
% Specify file level properties
|
||||
opts.ExtraColumnsRule = "ignore";
|
||||
opts.EmptyLineRule = "read";
|
||||
|
||||
% Specify variable properties
|
||||
opts = setvaropts(opts, ["x0_03203105428566744", "x_0_09762908467719589"], "DecimalSeparator", ",");
|
||||
opts = setvaropts(opts, ["x0_03203105428566744", "x_0_09762908467719589"], "ThousandsSeparator", ".");
|
||||
|
||||
% Import the data
|
||||
x70ghz_pd_resp = readtable("C:\Users\Silas\Documents\MATLAB\imdd_simulation\Functions\Theory\Dissertation\PD\70ghz_pd_responsivity.csv", opts);
|
||||
x70ghz_pd_bandwidth = readtable("C:\Users\Silas\Documents\MATLAB\imdd_simulation\Functions\Theory\Dissertation\PD\70ghz_pd_bandwidth.csv", opts);
|
||||
x100ghz_pd_resp = readtable("C:\Users\Silas\Documents\MATLAB\imdd_simulation\Functions\Theory\Dissertation\PD\100ghz_pd_responsivity.csv", opts);
|
||||
x100ghz_pd_bandwidth = readtable("C:\Users\Silas\Documents\MATLAB\imdd_simulation\Functions\Theory\Dissertation\PD\100ghz_pd_bandwidth.csv", opts);
|
||||
|
||||
% sort bandwidth based on first table column
|
||||
x70ghz_pd_bandwidth = sortrows(x70ghz_pd_bandwidth, "x0_03203105428566744");
|
||||
|
||||
x70ghz_pd_bandwidth.(2) = movmean(x70ghz_pd_bandwidth.(2),3);
|
||||
%smooth data for plotting
|
||||
|
||||
x100ghz_pd_bandwidth = sortrows(x100ghz_pd_bandwidth, "x0_03203105428566744");
|
||||
|
||||
|
||||
|
||||
%%
|
||||
|
||||
figure(); hold on
|
||||
plot(x100ghz_pd_resp.(1),x100ghz_pd_resp.(2))
|
||||
plot(x70ghz_pd_resp.(1),x70ghz_pd_resp.(2))
|
||||
% beautify
|
||||
xlabel('Frequency (GHz)');
|
||||
ylabel('Responsivity (A/W)');
|
||||
legend('100GHz PD', '70GHz PD');
|
||||
grid on;
|
||||
|
||||
%%
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\pd\responsivity.tikz')
|
||||
|
||||
%%
|
||||
|
||||
figure(); hold on
|
||||
plot(x100ghz_pd_bandwidth.(1),x100ghz_pd_bandwidth.(2))
|
||||
plot(x70ghz_pd_bandwidth.(1),x70ghz_pd_bandwidth.(2))
|
||||
% beautify
|
||||
xlabel('Frequency (GHz)');
|
||||
ylabel('Relative S21');
|
||||
legend('100GHz PD', '70GHz PD');
|
||||
grid on;
|
||||
|
||||
ylim([-3.5, 0.1])
|
||||
xlim([0 100]);
|
||||
|
||||
%%
|
||||
mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\pd\bandwidth_.tikz')
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
%% plot_dispersion_final_for_tikz
|
||||
lambda_nm = linspace(1240, 1360, 400);
|
||||
|
||||
% 1. Statistical & Specification Parameters
|
||||
p01_L = norminv(0.01, 1317, 2);
|
||||
p99_L = norminv(0.99, 1317, 2);
|
||||
p01_S = norminv(0.01, 0.0872, 0.0012);
|
||||
p99_S = norminv(0.99, 0.0872, 0.0012);
|
||||
|
||||
% Scenarios: [ZDW_min, ZDW_max], [S0_min, S0_max], [Color RGB]
|
||||
scenarios = { ...
|
||||
[1303, 1325], [0.075, 0.0925], [0.6510, 0.8078, 0.8902]; ... % 1. Wide Spec (Gray)
|
||||
[p01_L, p99_L], [p01_S, p99_S], [0.6, 0.6, 0.6] ... % 2. 98% Stats (Blue)
|
||||
};
|
||||
|
||||
figure('Color','w'); hold on;
|
||||
hp_handles = [];
|
||||
|
||||
% 2. Calculate and Plot Envelopes
|
||||
for k = 1:size(scenarios, 1)
|
||||
Zr = scenarios{k,1};
|
||||
Sr = scenarios{k,2};
|
||||
col = scenarios{k,3};
|
||||
|
||||
[S_mesh, Z_mesh] = meshgrid(Sr, Zr);
|
||||
D_all = zeros(length(lambda_nm), 4);
|
||||
for i = 1:4
|
||||
D_all(:,i) = (S_mesh(i)/4) .* (lambda_nm - (Z_mesh(i)^4)./(lambda_nm.^3));
|
||||
end
|
||||
|
||||
D_min_env = min(D_all, [], 2);
|
||||
D_max_env = max(D_all, [], 2);
|
||||
|
||||
[hl, hp] = boundedline(lambda_nm, (D_min_env+D_max_env)/2, (D_max_env-D_min_env)/2, ...
|
||||
'cmap','alpha', col);
|
||||
|
||||
hp_handles(k) = hp;
|
||||
set(hl, 'Visible', 'off');
|
||||
|
||||
|
||||
if k == 1
|
||||
D_wide_min = D_min_env;
|
||||
D_wide_max = D_max_env;
|
||||
% ho = outlinebounds(hl, hp);
|
||||
% % Change properties
|
||||
% set(ho, 'Color', 'k', ... % Make it black
|
||||
% 'LineStyle', '--', ... % Make it dashed
|
||||
% 'LineWidth', 1, ... % Make it thin
|
||||
% 'HandleVisibility', 'off'); % Hide from legend
|
||||
% Capture Wide Spec (k=1) bounds for the TikZ measurement lines
|
||||
hp.FaceAlpha = 0.5;
|
||||
% ho = outlinebounds(hl, hp);
|
||||
% % Change properties
|
||||
% set(ho, 'Color', 'k', ... % Make it black
|
||||
% 'LineStyle', '--', ... % Make it dashed
|
||||
% 'LineWidth', 1, ... % Make it thin
|
||||
% 'HandleVisibility', 'off'); % Hide from legend
|
||||
% Capture Wide Spec (k=1) bounds for the TikZ measurement lines
|
||||
hp.FaceAlpha = 0.5;
|
||||
else
|
||||
hp.FaceAlpha = 0.8;
|
||||
end
|
||||
end
|
||||
|
||||
% 3. Nominal Line
|
||||
D_nom = (0.0872/4) .* (lambda_nm - (1317^4)./(lambda_nm.^3));
|
||||
h_nom = plot(lambda_nm, D_nom, 'k', 'LineWidth', 1,'LineStyle','-');
|
||||
|
||||
% 4. Minimal Lines for TikZ (Measuring Wide Spec)
|
||||
lambda_v = 1290;
|
||||
[~, idx_v] = min(abs(lambda_nm - lambda_v));
|
||||
% Vertical line showing full Wide Spec dispersion range at 1290nm
|
||||
line([lambda_v, lambda_v], [D_wide_min(idx_v), D_wide_max(idx_v)], 'Color', 'k', 'Tag', 'VertArrow','LineWidth', 1);
|
||||
% Horizontal line showing Wide Spec ZDW range at D=0
|
||||
% line([1303, 1325], [0, 0], 'Color', 'k', 'Tag', 'HorizArrow','LineWidth', 1);
|
||||
|
||||
% 5. Aesthetics & Legend
|
||||
xlabel('Wavelength $\lambda$ [nm]', 'Interpreter', 'latex');
|
||||
ylabel('$D(\lambda)$ [ps/(nm km)]', 'Interpreter', 'latex');
|
||||
grid on; box on;
|
||||
xlim([1240 1360]); ylim([-5 5]);
|
||||
|
||||
leg_labels = { ...
|
||||
'$\lambda_0 \in [1303, 1325], S_0 \in [0.075, 0.0925]$', ...
|
||||
'$\lambda_0 \in [1312, 1322], S_0 \in [0.084, 0.090]$', ...
|
||||
'$\lambda_0 = 1317, S_0 = 0.0872$'};
|
||||
legend([hp_handles, h_nom], leg_labels, 'Location', 'northwest', 'Interpreter', 'latex', 'FontSize', 8);
|
||||
|
||||
% Export command (uncomment to use)
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\dispersion\dispersion_slope.tikz')
|
||||
@@ -1,183 +0,0 @@
|
||||
%% ------------------------------------------------------------
|
||||
% Contour plot: λ_null as function of bandwidth (f_target) and reach (L)
|
||||
% ------------------------------------------------------------
|
||||
|
||||
% Parameters
|
||||
lambda0 = 1310e-9; % [m]
|
||||
S0 = 0.09; % [ps/(nm²·km)]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
% Sweep dimensions
|
||||
f_targets = linspace(50e9, 130e9, 200); % [Hz] (x-axis)
|
||||
L_values = linspace(0.5e3, 15e3, 200); % [m] (y-axis)
|
||||
|
||||
lambda_surface = zeros(numel(L_values), numel(f_targets));
|
||||
Dacc_surface = zeros(numel(L_values), numel(f_targets));
|
||||
|
||||
% Outer loop over fiber length (since L must be scalar)
|
||||
for iL = 1:numel(L_values)
|
||||
L = L_values(iL);
|
||||
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
||||
|
||||
% Store the 1x absolute offset |lambda - lambda0|
|
||||
lambda_surface(iL, :) = abs(lambda0 - lambda_vec);
|
||||
Dacc_surface(iL, :) = Dacc_vec;
|
||||
end
|
||||
|
||||
% Convert for plotting
|
||||
lambda_surface_nm = lambda_surface * 1e9; % [nm]
|
||||
L_km = L_values / 1000; % [km]
|
||||
f_GHz = f_targets / 1e9; % [GHz]
|
||||
|
||||
%% Contour plot
|
||||
figure('Color','w');
|
||||
hold on;
|
||||
|
||||
% Define wavelength contour levels [nm]
|
||||
% Focus on a clean range of 1x offset values
|
||||
lambda_levels = unique([50:-10:30, 30:-5:5]);
|
||||
|
||||
% Contour plot
|
||||
[C,h] = contourf(f_GHz, L_km, lambda_surface_nm, lambda_levels, ...
|
||||
'LineWidth', 1.2, ...
|
||||
'ShowText', 'off');
|
||||
|
||||
% Colormap: Modern Blue palette with light colors removed for visibility
|
||||
cmap_full = cbrewer2('Blues', 40);
|
||||
colormap(cmap_full(10:end, :));
|
||||
clim([min(lambda_levels) max(lambda_levels)]);
|
||||
cb = colorbar;
|
||||
ylabel(cb, '$\Delta \lambda$ [nm]', 'Interpreter', 'latex');
|
||||
|
||||
% --- MANUAL TEXTBOX ANNOTATIONS ---
|
||||
% Find placement along the first-null curve for each level
|
||||
for i = 1:length(lambda_levels)
|
||||
lvl = lambda_levels(i);
|
||||
|
||||
% Re-calculate the specific (f, L) curve for this delta-lambda
|
||||
lambda_target = lambda0 - (lvl * 1e-9);
|
||||
LHS = -( (S0*1e3) / 4 ) * (lambda_target - (lambda0^4)/(lambda_target^3)) * lambda_target^2;
|
||||
const_val = (c*0.5) / LHS;
|
||||
|
||||
f_curve_GHz = linspace(min(f_GHz), max(f_GHz), 500);
|
||||
L_curve_km = const_val ./ (f_curve_GHz * 1e9).^2 / 1000;
|
||||
|
||||
% Filter for points within the plot axes
|
||||
in_bounds = find(L_curve_km >= min(L_km)*1.1 & L_curve_km <= max(L_km)*0.9 & ...
|
||||
f_curve_GHz >= min(f_GHz)*1.1 & f_curve_GHz <= max(f_GHz)*0.9);
|
||||
|
||||
if ~isempty(in_bounds)
|
||||
% Specific alternating pattern for weight to minimize overlapping
|
||||
if i < 9
|
||||
weight = 0.05;
|
||||
else
|
||||
weight = 0.05 + 0.1 * mod(i, 2);
|
||||
end
|
||||
idx = in_bounds(max(1, min(length(in_bounds), round(length(in_bounds) * weight))));
|
||||
|
||||
text(f_curve_GHz(idx), L_curve_km(idx), sprintf('%g nm', lvl), ...
|
||||
'Color', 'k', 'BackgroundColor', 'w', 'Margin', 1.5, ...
|
||||
'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle', ...
|
||||
'EdgeColor', 'k', 'FontSize', 9);
|
||||
end
|
||||
end
|
||||
|
||||
% Axis formatting
|
||||
xlabel('Signal Bandwidth [GHz]', 'FontSize', 11);
|
||||
ylabel('Fiber length [km]', 'FontSize', 11);
|
||||
xticks(min(f_GHz):10:max(f_GHz));
|
||||
yticks(min(L_km):2.5:max(L_km));
|
||||
grid on; box on;
|
||||
axis([min(f_GHz) max(f_GHz) min(L_km) max(L_km)]);
|
||||
|
||||
|
||||
%% Optional: overlay accumulated-dispersion contours
|
||||
if 0
|
||||
hold on;
|
||||
min_D = min(Dacc_surface(:), [], 'omitnan');
|
||||
max_D = max(Dacc_surface(:), [], 'omitnan');
|
||||
% Calculate 3 integer levels well within the data range
|
||||
D_levels = unique(round(linspace(min_D*0.8, max_D*0.8, 3)));
|
||||
|
||||
[CS, h] = contour(f_GHz, L_km, Dacc_surface, D_levels, 'k--', 'LineWidth', 0.8);
|
||||
clabel(CS, h, 'Color','k', 'FontSize',8);
|
||||
end
|
||||
|
||||
|
||||
%% Export
|
||||
% Hier erzwingen wir die rote Colormap für pgfplots, damit mat2tikz es nicht blau exportiert!
|
||||
% mat2tikz_improved("C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/02_IMDD_System/tikz/dispersion/dispersion_power_fading_contour2.tikz");
|
||||
|
||||
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
|
||||
% lambda_for_first_null_full (stable, single-branch + validity checks)
|
||||
% --------------------------------------------------------------------
|
||||
% Computes the wavelength(s) at which the first IM/DD fading null
|
||||
% occurs at frequency/ies f_target using the full dispersion model:
|
||||
%
|
||||
% D(lambda) = (S0/4)*(lambda - lambda0^4 / lambda^3)
|
||||
%
|
||||
% Restricted to the NORMAL-dispersion branch (λ < λ0),
|
||||
% and valid only in the O-band (1260–1360 nm).
|
||||
%
|
||||
% Inputs:
|
||||
% f_target - scalar or vector of target null frequencies [Hz]
|
||||
% L - fiber length [m]
|
||||
% lambda0 - zero-dispersion wavelength (ZDW) [m]
|
||||
% S0 - dispersion slope at ZDW [ps/(nm²·km)]
|
||||
%
|
||||
% Outputs:
|
||||
% lambda_vec - wavelength(s) [m] where first null occurs (clamped to O-band)
|
||||
% Dacc_vec - accumulated dispersion(s) [ps/nm] (NaN if out of valid range)
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
c = physconst('lightspeed');
|
||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
||||
|
||||
% Define O-band boundaries (in meters)
|
||||
lambda_min = 1255e-9;
|
||||
lambda_max = 1361e-9;
|
||||
|
||||
% Force column vector
|
||||
f_target = f_target(:);
|
||||
N = numel(f_target);
|
||||
|
||||
lambda_vec = NaN(N,1);
|
||||
Dacc_vec = NaN(N,1);
|
||||
|
||||
|
||||
|
||||
for k = 1:N
|
||||
RHS = c * 0.5 / (f_target(k)^2 * L);
|
||||
|
||||
% Normal-dispersion branch (λ < λ0)
|
||||
fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS;
|
||||
|
||||
% Limit the search to [λ_min, λ0)
|
||||
try
|
||||
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
||||
catch
|
||||
% If the zero is not within bounds, skip this point
|
||||
lambda_sol = NaN;
|
||||
end
|
||||
|
||||
% Validate solution
|
||||
if isnan(lambda_sol) || lambda_sol < lambda_min || lambda_sol > lambda_max
|
||||
lambda_vec(k) = NaN;
|
||||
Dacc_vec(k) = NaN;
|
||||
continue
|
||||
end
|
||||
|
||||
% Compute D(lambda) and accumulated dispersion
|
||||
D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km)
|
||||
Dacc_val = D_lambda * (L/1000); % ps/nm
|
||||
|
||||
% Sanity bound on dispersion (avoid unphysical > ±100 ps/nm)
|
||||
if abs(Dacc_val) > 100
|
||||
lambda_vec(k) = NaN;
|
||||
Dacc_vec(k) = NaN;
|
||||
else
|
||||
lambda_vec(k) = lambda_sol;
|
||||
Dacc_vec(k) = Dacc_val;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,142 +0,0 @@
|
||||
% Festen Betriebsparameter
|
||||
lambda = 1290; % nm
|
||||
L = 1; % km
|
||||
mu_zwd = 1317; % nm
|
||||
sigma_zwd = 2; % nm
|
||||
mu_s0 = 0.0872; % ps / nm2 km
|
||||
sigma_s0 = 0.0012; % ps / nm2 km
|
||||
rho = -0.5; % Korrelation
|
||||
|
||||
% Gitter für lambda0 und S0
|
||||
lambda0_vec = linspace(mu_zwd-10, mu_zwd+10, 100);
|
||||
S0_vec = linspace(mu_s0-0.01, mu_s0+0.01, 100);
|
||||
|
||||
% Korrigierte meshgrid Reihenfolge
|
||||
[S0, Lambda0] = meshgrid(S0_vec, lambda0_vec);
|
||||
|
||||
% Dispersion berechnen
|
||||
D = (S0./4) .* ( lambda - (Lambda0.^4)./(lambda^3) ) * L;
|
||||
|
||||
% 2D Verteilung (Bivariate Gauss) berechnen
|
||||
Z_x = (S0 - mu_s0) / sigma_s0;
|
||||
Z_y = (Lambda0 - mu_zwd) / sigma_zwd;
|
||||
PDF_2D = exp(-1 / (2 * (1 - rho^2)) * (Z_x.^2 - 2 * rho .* Z_x .* Z_y + Z_y.^2));
|
||||
|
||||
%% Plot zusammenbauen
|
||||
figure('Color','w');
|
||||
hold on % EINZIGES hold on für den gesamten Plot!
|
||||
|
||||
% --- 1. ZUERST: 2D Verteilung (Bivariate Gauss) "ganz unten" ---
|
||||
numLevels_2D = 6;
|
||||
colors_2D = cbrewer2('Greys', numLevels_2D+0);
|
||||
colors_2D = colors_2D(1:numLevels_2D,:);
|
||||
% Nur die Anzahl der Level übergeben!
|
||||
[C2, h2] = contourf(S0, Lambda0, PDF_2D, numLevels_2D);
|
||||
h2.HandleVisibility='off';
|
||||
% Colormap für die rote Fläche setzen
|
||||
|
||||
colormap(gcf, colors_2D(1:end,:));
|
||||
try
|
||||
clim([min(PDF_2D(:)), max(PDF_2D(:))]);
|
||||
catch
|
||||
caxis([min(PDF_2D(:)), max(PDF_2D(:))]);
|
||||
end
|
||||
|
||||
h2.EdgeColor = 'none'; % Keine schwarzen Ränder
|
||||
|
||||
% --- 2. DARÜBER: Dispersions-Konturlinien ---
|
||||
numLevels_D = 9;
|
||||
% Erzeuge glatte, auf 1 Nachkommastelle gerundete Werte
|
||||
levels_D = round(linspace(min(D(:)), max(D(:)), numLevels_D), 1);
|
||||
levels_D = unique(levels_D);
|
||||
cmap_bg = flip(cbrewer2('Blues', length(levels_D)+3));
|
||||
|
||||
for i = 1:length(levels_D)
|
||||
% Konturlinien zeichnen (explizit Schwarz)
|
||||
[C,h] = contour(S0, Lambda0, D, [levels_D(i), levels_D(i)], ...
|
||||
'Color', cmap_bg(i,:),...
|
||||
'LineWidth', 1, ...
|
||||
'ShowText', 'off','handlevisibility','off');
|
||||
if i == 1
|
||||
h.HandleVisibility='on';
|
||||
h.DisplayName='$D(\lambda=1290)$';
|
||||
end
|
||||
end
|
||||
|
||||
% --- 3. MANUELLE TEXTBOXEN AUF DEN LINIEN ---
|
||||
% Wähle eine feste S0-Position für alle Beschriftungen (z.B. bei 0.082)
|
||||
S0_label = 0.095;
|
||||
|
||||
for i = 1:length(levels_D)
|
||||
% Berechne exakte ZDW (Y-Koordinate) durch Umstellen der D-Formel:
|
||||
% Lambda0 = (lambda^3 * (lambda - 4*D / (S0 * L)))^(1/4)
|
||||
zdw_label = (lambda^3 * (lambda - 4*levels_D(i) / (S0_label * L)))^0.25;
|
||||
|
||||
% Nur zeichnen, wenn der Punkt auch im sichtbaren Plot-Bereich liegt
|
||||
if zdw_label >= min(lambda0_vec) && zdw_label <= max(lambda0_vec)
|
||||
text(S0_label, zdw_label, sprintf('%0.1f', levels_D(i)), ...
|
||||
'Color', 'k', ...
|
||||
'BackgroundColor', 'w', ... % Weiße Box überdeckt die schwarze Linie!
|
||||
'Margin', 2, ... % Abstand der Box zum Text
|
||||
'HorizontalAlignment', 'center', ...
|
||||
'VerticalAlignment', 'middle', ...
|
||||
'FontSize', 10);
|
||||
end
|
||||
end
|
||||
|
||||
% --- 3. GANZ OBEN: Randverteilungen (1D Gauss) an den Achsen ---
|
||||
% S0 Verteilung (unten)
|
||||
s0_vals = linspace(min(S0_vec), max(S0_vec), 500);
|
||||
gauss_s0 = exp(-0.5*((s0_vals - mu_s0)/sigma_s0).^2);
|
||||
scale_s0 = 4;
|
||||
y_s0_base = min(lambda0_vec);
|
||||
plot(s0_vals, y_s0_base + gauss_s0 * scale_s0, 'LineWidth', 1,'LineStyle','--','DisplayName','$S_0$','Color',[0,0,0],'HandleVisibility','off');
|
||||
% ANNOTATION S0: Automatisch platziert leicht über dem Peak
|
||||
str_s0 = sprintf('\\mu_{S0} = %.4f\n\\sigma_{S0} = %.4f', mu_s0, sigma_s0);
|
||||
text(0.0915,1308, str_s0, ...
|
||||
'Interpreter', 'tex', ...
|
||||
'HorizontalAlignment', 'left', ... % Entspricht 'right' in TikZ
|
||||
'VerticalAlignment', 'middle', ...
|
||||
'BackgroundColor', 'w', ... % Entspricht 'fill=white'
|
||||
'EdgeColor', 'k', ... % Entspricht 'draw=black'
|
||||
'Margin', 1, ... % Entspricht 'inner sep=1pt'
|
||||
'FontSize', 10);
|
||||
|
||||
% ZDW Verteilung (links)
|
||||
% ZDW Verteilung (links)
|
||||
zwd_vals = linspace(min(lambda0_vec), max(lambda0_vec), 500);
|
||||
gauss_zwd = exp(-0.5*((zwd_vals - mu_zwd)/sigma_zwd).^2);
|
||||
scale_zwd = 0.005;
|
||||
x_zwd_base = min(S0_vec);
|
||||
plot(x_zwd_base + gauss_zwd * scale_zwd, zwd_vals, 'LineWidth', 1,'LineStyle','--','DisplayName','ZDW','Color',[0,0,0],'HandleVisibility','off');
|
||||
|
||||
% ANNOTATION ZDW: Automatisch platziert leicht rechts neben dem Peak
|
||||
str_zwd = sprintf('\\mu_{ZDW} = %.1f\n\\sigma_{ZDW} = %.1f', mu_zwd, sigma_zwd);
|
||||
text(0.079,1312, str_zwd, ...
|
||||
'Interpreter', 'tex', ...
|
||||
'HorizontalAlignment', 'left', ... % Entspricht 'right' in TikZ
|
||||
'VerticalAlignment', 'middle', ...
|
||||
'BackgroundColor', 'w', ... % Entspricht 'fill=white'
|
||||
'EdgeColor', 'k', ... % Entspricht 'draw=black'
|
||||
'Margin', 1, ... % Entspricht 'inner sep=1pt'
|
||||
'FontSize', 10);
|
||||
|
||||
% Hilfslinien für die Mittelwerte
|
||||
% xline(mu_s0,'LineWidth',0.5,'HandleVisibility','off','LineStyle',':');
|
||||
% yline(mu_zwd,'LineWidth',0.5,'HandleVisibility','off','LineStyle',':');
|
||||
|
||||
% --- Achsenbeschriftung, Titel & Formatierung ---
|
||||
xlabel('$S_0$ [$\nicefrac{\text{ps}}{(\text{nm}^2\text{ km})}$]', 'FontSize', 12);
|
||||
ylabel('ZDW [nm]', 'FontSize', 12);
|
||||
% title(sprintf('Dispersion: %d km; %d nm', L, lambda), 'FontSize', 14);
|
||||
|
||||
grid on
|
||||
% Exakte Begrenzung, damit die Randverteilungen bündig anliegen
|
||||
axis([min(S0_vec) max(S0_vec) min(lambda0_vec) max(lambda0_vec)]);
|
||||
|
||||
% legend;
|
||||
hold off % EINZIGES hold off ganz am Ende!
|
||||
|
||||
%% Export
|
||||
% Hier erzwingen wir die rote Colormap für pgfplots, damit mat2tikz es nicht blau exportiert!
|
||||
mat2tikz_improved("C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/02_IMDD_System/tikz/dispersion/dispersion_contour_bi2.tikz");
|
||||
@@ -1,219 +0,0 @@
|
||||
|
||||
|
||||
% Parameters
|
||||
c0 = physconst('lightspeed'); % [m/s]
|
||||
lambda0 = 1310e-9; % [m]
|
||||
omega0 = 2*pi*c0/lambda0;
|
||||
|
||||
L = 5e-3; % [m] effective phase section length (set as needed)
|
||||
n_eff = 2.2; % [-] effective index (set as needed)
|
||||
|
||||
E0 = 1; % field amplitude (arbitrary)
|
||||
Vpi = 3.2; % [V] half-wave voltage (your V_pi)
|
||||
|
||||
% Drive
|
||||
f0 = 1e9; % [Hz]
|
||||
fs = 200e9; % [Hz]
|
||||
Nper = 2; % number of periods
|
||||
Vpp = 0.6*Vpi; % [V] peak-to-peak of v_drive(t)
|
||||
|
||||
biasV = 1.1; % [V] differential bias added to v_drive
|
||||
|
||||
% Time axis + differential drive voltage v_drive(t)
|
||||
T = Nper/f0;
|
||||
t = (0:1/fs:T-1/fs).';
|
||||
|
||||
|
||||
if 1
|
||||
% SINE
|
||||
v_drive = biasV + (Vpp/2)*sin(2*pi*f0*t); % v_drive(t) (peak = Vpp/2)
|
||||
|
||||
else
|
||||
|
||||
% --- Generate PAM-4 Sequence ---
|
||||
symbols = linspace(-0.5, 0.5, 4);
|
||||
num_symbols = 12; % Increased slightly for better visual
|
||||
rng(44);
|
||||
random_data = symbols(randi(4, 1, num_symbols));
|
||||
|
||||
% Create time axis (Note: T is your period from the sine code)
|
||||
sps = round(T * fs);
|
||||
t = (0:1/fs:(num_symbols*T)-1/fs).';
|
||||
|
||||
% Upsample to rectangular waveform
|
||||
v_pam = repelem(random_data, sps).';
|
||||
|
||||
% Apply swing and bias: Resulting range is [biasV-Vpp/2, biasV+Vpp/2]
|
||||
v_drive_rect = biasV + (v_pam * Vpp);
|
||||
|
||||
% --- Round the edges ---
|
||||
filter_span = round(sps/1.5); % Increased span for smoother "rounding"
|
||||
window = gausswin(filter_span);
|
||||
window = window / sum(window);
|
||||
|
||||
% Apply filter (using 'same' to keep vector length, but be aware of edge transients)
|
||||
v_drive = conv(v_drive_rect, window, 'same');
|
||||
|
||||
end
|
||||
|
||||
|
||||
% Analytic
|
||||
v_ = linspace(-1,2, 2001);
|
||||
% Field transfer function (amplitude)
|
||||
Field_mzm_analytic = cos((pi/2)*v_);
|
||||
|
||||
% Power transfer function (intensity)
|
||||
P_mzm_analytic = Field_mzm_analytic.^2;
|
||||
|
||||
% Imbalance factor in YOUR notation:
|
||||
rho = 1;
|
||||
|
||||
% Push-pull branch voltages (consistent with v_drive = v1 - v2)
|
||||
v1 = +0.5*v_drive; % arm 1
|
||||
v2 = -0.5*v_drive; % arm 2
|
||||
|
||||
% Phases phi1, phi2
|
||||
phi1 = pi * v1 / Vpi;
|
||||
phi2 = pi * v2 / Vpi;
|
||||
|
||||
% Fields: E_in and E_out (exactly your Eq. (mzm_e_field))
|
||||
E_in = E0 .* exp(1i*omega0*t);
|
||||
|
||||
common_phase = exp(-1i * (omega0*L*n_eff/c0)); % exp(-j*omega0*L*n_eff/c0)
|
||||
|
||||
E_out = E0 .* exp(1i*omega0*t) .* common_phase .* 0.5 .* ...
|
||||
( exp(-1i*phi1) + rho .* exp(-1i*phi2) );
|
||||
|
||||
% Transfer function (numerical): E_out/E_in
|
||||
H_num = E_out ./ E_in;
|
||||
|
||||
% Power (normalized)
|
||||
Pnorm_num = abs(H_num).^2; % since |E_out/E_in|^2
|
||||
|
||||
% Ideal TF (analytic) for comparison (rho=1, push-pull)
|
||||
H_ideal = common_phase .* cos( (pi/2) * (v_drive./Vpi) );
|
||||
|
||||
Pnorm_ideal = abs(H_ideal).^2;
|
||||
Pnorm_math = cos( (pi/2) * (v_drive./Vpi) ).^2;
|
||||
|
||||
|
||||
set(groot, 'defaultLegendInterpreter', 'tex');
|
||||
set(groot, 'defaultAxesTickLabelInterpreter', 'tex');
|
||||
set(groot, 'defaultTextInterpreter', 'tex');
|
||||
|
||||
% Normalized voltage axis (multiples of Vpi)
|
||||
v_norm = v_drive./Vpi;
|
||||
|
||||
colfield = [0,0,0]; %is black
|
||||
colpow = linspecer(2);
|
||||
colpow = colpow(1,:);
|
||||
colvdrive = linspecer(2);
|
||||
colvdrive = colvdrive(2,:);
|
||||
|
||||
%% SIGNAL IN
|
||||
figure(1); clf
|
||||
plot(v_norm,t*1e9, 'LineWidth', 1.0,'Color',colvdrive); grid on;
|
||||
ylabel('t [ns]'); xlabel('v_{drive}(t)/V_\pi');
|
||||
title('Drive voltage (normalized)');
|
||||
xlim([min(v_) max(v_)]);
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\linear_casee\mzm_input_signal.tex');
|
||||
|
||||
|
||||
%% IN/OUT (static transfer) — normalized x-axis + analytic curve
|
||||
if 0
|
||||
figure(2); clf
|
||||
plot(v_, Field_mzm_analytic, 'LineWidth', 1.2,'LineStyle','--','Color',colfield); hold on;% analytic power TF
|
||||
plot(v_, P_mzm_analytic, 'LineWidth', 1.2, 'Color',colpow); hold on;% analytic power TF
|
||||
% show input time signal
|
||||
plot(v_norm,-1+t*1e9, 'LineWidth', 1.0,'Color',colvdrive); grid on;
|
||||
% show output time signal
|
||||
plot(2+t*1e9, Pnorm_num, 'LineWidth', 1.0,'DisplayName','Intensity', 'Color',colvdrive); hold on;
|
||||
plot(2+t*1e9, real(H_ideal), '--', 'LineWidth', 1.0,'DisplayName','Field','Color',colfield); hold on;
|
||||
scatter(v_norm, Pnorm_num, 12, '.', 'LineWidth', 1,'MarkerEdgeColor',colvdrive);
|
||||
scatter(biasV./Vpi,(cos((pi/2)*biasV./Vpi)^2),10,'Marker','o');
|
||||
line([min(v_drive), min(v_drive)]./Vpi,[(cos((pi/2)*min(v_drive)./Vpi)^2), -2],'linewidth',0.5,'color','black','linestyle','--');
|
||||
line([max(v_drive) max(v_drive)]./Vpi,[(cos((pi/2)*max(v_drive)./Vpi)^2), -2],'linewidth',0.5,'color','black','linestyle','--');
|
||||
xline([min(v_norm) max(v_norm)])
|
||||
|
||||
grid on;
|
||||
xlabel('v_{drive}(t)/V_\pi'); ylabel('|E_{out}/E_{in}|^2');
|
||||
% legend
|
||||
xlim([min(v_) max(v_)+1]);
|
||||
ylim([-1 1]);
|
||||
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\mzm.tex');
|
||||
end
|
||||
%%
|
||||
|
||||
figure(3); clf
|
||||
plot(v_, Field_mzm_analytic, 'LineWidth', 1.2,'LineStyle','--','Color',colfield); hold on;% analytic power TF
|
||||
plot(v_, P_mzm_analytic, 'LineWidth', 1.2, 'Color',colpow); hold on;% analytic power TF
|
||||
|
||||
scatter(v_norm, Pnorm_num, 12, '.', 'LineWidth', 1,'MarkerEdgeColor',colvdrive);
|
||||
scatter(biasV./Vpi,(cos((pi/2)*biasV./Vpi)^2),10,'Marker','o');
|
||||
line([min(v_drive), min(v_drive)]./Vpi,[(cos((pi/2)*min(v_drive)./Vpi)^2), -2],'linewidth',0.5,'color','black','linestyle','--');
|
||||
line([max(v_drive) max(v_drive)]./Vpi,[(cos((pi/2)*max(v_drive)./Vpi)^2), -2],'linewidth',0.5,'color','black','linestyle','--');
|
||||
xline([min(v_norm) max(v_norm)])
|
||||
|
||||
grid on;
|
||||
xlabel('v_{drive}(t)/V_\pi'); ylabel('|E_{out}/E_{in}|^2');
|
||||
% legend
|
||||
xlim([min(v_) max(v_)]);
|
||||
ylim([-1 1]);
|
||||
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\mzm_tramsfer_function_matlab.tex');
|
||||
|
||||
|
||||
%%
|
||||
|
||||
figure(4); clf
|
||||
% plot(v_, Field_mzm_analytic, 'LineWidth', 1.2,'LineStyle','--','Color',colfield); hold on;% analytic power TF
|
||||
plot(v_, P_mzm_analytic, 'LineWidth', 1.2, 'Color','black'); hold on;% analytic power TF
|
||||
input_dots = linspace(min(v_drive),max(v_drive),4)./Vpi;
|
||||
% input_dots = unique(v_drive_rect)./Vpi;
|
||||
output_dots = (cos((pi/2)*input_dots).^2);
|
||||
scatter(input_dots,output_dots,'Marker','x','LineWidth',1,'MarkerEdgeColor','black');
|
||||
scatter(input_dots,zeros(size(input_dots)),'Marker','^','LineWidth',2,'MarkerEdgeColor','black');
|
||||
% scatter(ones(size(input_dots)),output_dots,'Marker','<','LineWidth',2,'MarkerEdgeColor','black');
|
||||
|
||||
for i = 1:numel(input_dots)
|
||||
% Draw the dashed projection lines
|
||||
line([input_dots(i), input_dots(i)], [output_dots(i), 0], 'linewidth', 0.5, 'color', 'black', 'linestyle', '--', 'handlevisibility', 'off');
|
||||
line([input_dots(i), 1], [output_dots(i), output_dots(i)], 'linewidth', 0.5, 'color', 'black', 'linestyle', '--', 'handlevisibility', 'off');
|
||||
|
||||
% Add the level annotation boxes near the output (y-axis)
|
||||
% Adjust the '1.05' to move the box further right or 'output_dots(i)' for height
|
||||
j = 3-(i-1)*2;
|
||||
text(1, output_dots(i), sprintf('Level %d', j), ...
|
||||
'FontSize', 8, ...
|
||||
'EdgeColor', 'black', ...
|
||||
'BackgroundColor', 'white', ...
|
||||
'Margin', 2);
|
||||
end
|
||||
|
||||
xlim([0,1.5]);
|
||||
ylim([0,1])
|
||||
|
||||
% line([min(v_drive), min(v_drive)]./Vpi,[(cos((pi/2)*min(v_drive)./Vpi)^2), 0],'linewidth',0.5,'color','black','linestyle','--');
|
||||
% line([max(v_drive), max(v_drive)]./Vpi,[(cos((pi/2)*max(v_drive)./Vpi)^2), 0],'linewidth',0.5,'color','black','linestyle','--');
|
||||
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\linear_casee\mzm_tf.tex');
|
||||
% xticks(sort(input_dots));
|
||||
% yticks(sort(output_dots));
|
||||
grid off
|
||||
|
||||
|
||||
%%
|
||||
% % FIELD TF (only field here; do not mix power into this figure)
|
||||
figure(5); clf
|
||||
% plot(t*1e9, real(H_num), 'LineWidth', 1.0); hold on;
|
||||
% plot(t*1e9, real(H_ideal), '--', 'LineWidth', 1.0,'DisplayName','Field','Color',colfield); hold on;
|
||||
plot(t*1e9, Pnorm_num, 'LineWidth', 1.0,'DisplayName','Intensity', 'Color',colpow); hold on;
|
||||
grid on;
|
||||
xlabel('t [ns]'); ylabel('Re\{E_{out}/E_{in}\}');
|
||||
legend
|
||||
yticks(sort(output_dots));
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\linear_casee\mzm_output_signal.tex');
|
||||
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
|
||||
|
||||
%MZM demo -> sinus als eingang in MZM intensity TF: 2nd and 3rd roder
|
||||
%nonlinearities in PSD visible
|
||||
|
||||
clear; close all; clc;
|
||||
|
||||
set(groot,'defaultLegendInterpreter','tex');
|
||||
set(groot,'defaultAxesTickLabelInterpreter','tex');
|
||||
set(groot,'defaultTextInterpreter','tex');
|
||||
|
||||
%% Fixed parameters
|
||||
Vpi = 5.2; % [V]
|
||||
f0 = 10e9; % [Hz]
|
||||
fs = 400e9; % [Hz]
|
||||
Nper = 500; % periods for PSD quality
|
||||
|
||||
t = (0:1/fs:(Nper/f0 - 1/fs)).';
|
||||
w = 2*pi*f0;
|
||||
|
||||
% PSD settings
|
||||
nfft = 2^(nextpow2(min(length(t), 2^18))-1);
|
||||
win = hann(2^12);
|
||||
ovl = round(0.5*numel(win));
|
||||
|
||||
N_bessel = 10;
|
||||
|
||||
%% UI defaults (normalized)
|
||||
vb0 = 1.0; % Vbias/Vpi
|
||||
vpp0 = 0.5; % Vpp/Vpi
|
||||
|
||||
%% Figure + layout
|
||||
fig = figure('Color','w','Name','MZM Nonlinearity: Bias & Drive','NumberTitle','off');
|
||||
tl = tiledlayout(fig,1,2,'TileSpacing','compact','Padding','compact');
|
||||
|
||||
axTF = nexttile(tl,1); hold(axTF,'on'); grid(axTF,'on');
|
||||
axPSD = nexttile(tl,2); hold(axPSD,'on'); grid(axPSD,'on');
|
||||
|
||||
% Scatter placeholders
|
||||
hEx = scatter(axTF, nan, nan, 6, '.', 'DisplayName','Exact');
|
||||
hTa = scatter(axTF, nan, nan, 6, '.', 'DisplayName','Taylor (3rd order)');
|
||||
hJa = scatter(axTF, nan, nan, 6, '.', 'DisplayName',sprintf('Jacobi--Anger (N=%d)',N_bessel));
|
||||
hBias = plot(axTF, nan, nan, 'ko', 'MarkerFaceColor','k', 'DisplayName','Bias');
|
||||
|
||||
xlabel(axTF,'v/V_\pi'); ylabel(axTF,'P_{out}/P_0'); % <-- TeX (no $...$)
|
||||
title(axTF,'Transfer characteristic (scatter)');
|
||||
ylim(axTF,[-0.1 1.1]);
|
||||
xlim(axTF,[0 2]);
|
||||
legend(axTF,'Location','best');
|
||||
|
||||
% PSD placeholders
|
||||
hPex = plot(axPSD, nan, nan, 'LineWidth',2.0, 'DisplayName','Exact');
|
||||
hPta = plot(axPSD, nan, nan, '-', 'LineWidth',1.5, 'DisplayName','Taylor (3rd order)');
|
||||
hPja = plot(axPSD, nan, nan, '--', 'LineWidth',0.1, 'DisplayName',sprintf('Jacobi--Anger (N=%d)',N_bessel));
|
||||
|
||||
xlabel(axPSD,'Frequency [GHz]'); ylabel(axPSD,'PSD [dB/Hz]');
|
||||
title(axPSD,'Output spectrum (PSD)');
|
||||
xlim(axPSD,[0 10*f0/1e9]);
|
||||
legend(axPSD,'Location','best');
|
||||
|
||||
%% Sliders + labels
|
||||
sH = 0.05; mL = 0.08; wS = 0.38; y1 = 0.04; dy = 0.06;
|
||||
|
||||
uicontrol(fig,'Style','text','Units','normalized', ...
|
||||
'Position',[mL, y1+dy, wS, 0.03], ...
|
||||
'String','v_{bias}/V_{\pi}','HorizontalAlignment','left');
|
||||
|
||||
sBias = uicontrol(fig,'Style','slider','Units','normalized', ...
|
||||
'Position',[mL, y1+dy-0.02, wS, sH], ...
|
||||
'Min',0,'Max',2,'Value',vb0);
|
||||
|
||||
tBiasVal = uicontrol(fig,'Style','text','Units','normalized', ...
|
||||
'Position',[mL+wS+0.01, y1+dy, 0.08, 0.03], ...
|
||||
'String',sprintf('%.3f',vb0),'HorizontalAlignment','left');
|
||||
|
||||
uicontrol(fig,'Style','text','Units','normalized', ...
|
||||
'Position',[mL, y1, wS, 0.03], ...
|
||||
'String','v_{pp}/V_{\pi}','HorizontalAlignment','left');
|
||||
|
||||
sVpp = uicontrol(fig,'Style','slider','Units','normalized', ...
|
||||
'Position',[mL, y1-0.02, wS, sH], ...
|
||||
'Min',0,'Max',2,'Value',vpp0);
|
||||
|
||||
tVppVal = uicontrol(fig,'Style','text','Units','normalized', ...
|
||||
'Position',[mL+wS+0.01, y1, 0.08, 0.03], ...
|
||||
'String',sprintf('%.3f',vpp0),'HorizontalAlignment','left');
|
||||
|
||||
%% Store handles in fig.UserData (so callback can always access them)
|
||||
S = struct();
|
||||
S.Vpi = Vpi; S.f0 = f0; S.fs = fs; S.w = w; S.t = t;
|
||||
S.win = win; S.ovl = ovl; S.nfft = nfft;
|
||||
S.N_bessel = N_bessel;
|
||||
|
||||
S.axTF = axTF; S.axPSD = axPSD;
|
||||
S.hEx = hEx; S.hTa = hTa; S.hJa = hJa; S.hBias = hBias;
|
||||
S.hPex = hPex; S.hPta = hPta; S.hPja = hPja;
|
||||
|
||||
S.sBias = sBias; S.sVpp = sVpp;
|
||||
S.tBiasVal = tBiasVal; S.tVppVal = tVppVal;
|
||||
|
||||
fig.UserData = S;
|
||||
|
||||
%% Continuous update while dragging
|
||||
addlistener(sBias,'Value','PostSet',@(~,~)updatePlots(fig));
|
||||
addlistener(sVpp ,'Value','PostSet',@(~,~)updatePlots(fig));
|
||||
|
||||
% Initial draw
|
||||
updatePlots(fig);
|
||||
|
||||
%% ===== Callback (separate function at end of script) =====
|
||||
function updatePlots(fig)
|
||||
S = fig.UserData;
|
||||
|
||||
% Read slider values (normalized)
|
||||
vb_n = S.sBias.Value; % Vbias/Vpi
|
||||
vpp_n = S.sVpp.Value; % Vpp/Vpi
|
||||
|
||||
% Update value labels
|
||||
S.tBiasVal.String = sprintf('%.3f', vb_n);
|
||||
S.tVppVal.String = sprintf('%.3f', vpp_n);
|
||||
|
||||
% Convert to volts / amplitude
|
||||
Vpi = S.Vpi;
|
||||
Vbias = vb_n * Vpi;
|
||||
Vpp = vpp_n * Vpi;
|
||||
Vm = Vpp/2;
|
||||
|
||||
t = S.t; w = S.w;
|
||||
|
||||
% Drive
|
||||
v = Vbias + Vm*cos(w*t);
|
||||
x = v./Vpi;
|
||||
|
||||
% Exact intensity
|
||||
P_exact = cos((pi/2)*x).^2;
|
||||
|
||||
% Taylor 3rd order around Vbias
|
||||
k = (pi/2)/Vpi;
|
||||
vb = Vbias;
|
||||
g0 = cos(k*vb)^2;
|
||||
g1 = -k*sin(2*k*vb);
|
||||
g2 = -2*k^2*cos(2*k*vb);
|
||||
g3 = 4*k^3*sin(2*k*vb);
|
||||
dv = v - vb;
|
||||
P_taylor = g0 + g1*dv + 0.5*g2*dv.^2 + (1/6)*g3*dv.^3;
|
||||
|
||||
% Jacobi–Anger / Bessel series (truncated)
|
||||
a = pi*(Vbias/Vpi);
|
||||
b = pi*(Vm/Vpi);
|
||||
N = S.N_bessel;
|
||||
|
||||
P_ja = 0.5*ones(size(t));
|
||||
P_ja = P_ja + 0.5*cos(a)*besselj(0,b);
|
||||
|
||||
for m = 0:floor((N-1)/2)
|
||||
n = 2*m + 1;
|
||||
P_ja = P_ja - (0.5*2)*sin(a)*besselj(n,b).*cos(n*w*t);
|
||||
end
|
||||
for m = 1:floor(N/2)
|
||||
n = 2*m;
|
||||
P_ja = P_ja - (0.5*2)*cos(a)*besselj(n,b).*cos(n*w*t);
|
||||
end
|
||||
|
||||
% Update TF scatter
|
||||
S.hEx.XData = x; S.hEx.YData = P_exact;
|
||||
S.hTa.XData = x; S.hTa.YData = P_taylor;
|
||||
S.hJa.XData = x; S.hJa.YData = P_ja;
|
||||
|
||||
xb = Vbias/Vpi;
|
||||
pb = cos((pi/2)*xb)^2;
|
||||
S.hBias.XData = xb; S.hBias.YData = pb;
|
||||
|
||||
xpad = 0.05*(max(x)-min(x) + eps);
|
||||
% xlim(S.axTF,[min(x)-xpad, max(x)+xpad]);
|
||||
ylim(S.axTF,[-0.1 1.1]);
|
||||
|
||||
% PSDs
|
||||
fs = S.fs;
|
||||
[Se,f] = pwelch(P_exact-mean(P_exact), S.win, S.ovl, S.nfft, fs, 'onesided');
|
||||
[St,~] = pwelch(P_taylor-mean(P_taylor), S.win, S.ovl, S.nfft, fs, 'onesided');
|
||||
[Sj,~] = pwelch(P_ja-mean(P_ja), S.win, S.ovl, S.nfft, fs, 'onesided');
|
||||
|
||||
S.hPex.XData = f/1e9; S.hPex.YData = 10*log10(Se + realmin);
|
||||
S.hPta.XData = f/1e9; S.hPta.YData = 10*log10(St + realmin);
|
||||
S.hPja.XData = f/1e9; S.hPja.YData = 10*log10(Sj + realmin);
|
||||
|
||||
xlim(S.axPSD,[0 10*(S.f0)/1e9]);
|
||||
ylim(S.axPSD,[-180 -80]);
|
||||
|
||||
drawnow limitrate;
|
||||
end
|
||||
@@ -1,66 +0,0 @@
|
||||
% MZM bias sweep (physical coefficients) + field & power transfer functions
|
||||
% Uses your notation:
|
||||
% Pout/Pin = cos^2( (pi/2)*(v/Vpi) ), v = Vbias + Δv
|
||||
% Taylor around Vbias:
|
||||
% Pout/Pin ≈ a0 + a1 Δv + a2 Δv^2 + a3 Δv^3
|
||||
%
|
||||
% Coefficients (physical units):
|
||||
% a0 [-], a1 [1/V], a2 [1/V^2], a3 [1/V^3]
|
||||
%
|
||||
% Also plots:
|
||||
% Field TF amplitude: Eout/Ein = cos( (pi/2)*(Vbias/Vpi) )
|
||||
% Power TF: Pout/Pin = cos^2( (pi/2)*(Vbias/Vpi) )
|
||||
|
||||
clear; close all; clc;
|
||||
|
||||
set(groot,'defaultLegendInterpreter','tex');
|
||||
set(groot,'defaultAxesTickLabelInterpreter','tex');
|
||||
set(groot,'defaultTextInterpreter','tex');
|
||||
|
||||
%% Parameters
|
||||
Vpi = 3; % [V] device half-wave voltage
|
||||
xb = linspace(0, 2, 2001); % x_b = Vbias/Vpi
|
||||
Vbias = xb * Vpi; % [V]
|
||||
|
||||
%% Static transfer functions (at Vbias)
|
||||
H_field = cos((pi/2)*xb); % field amplitude TF (balanced MZM)
|
||||
T_power = H_field.^2; % intensity TF
|
||||
|
||||
%% Taylor coefficients (physical units)
|
||||
a0 = T_power;
|
||||
a1 = -(pi/(2*Vpi)) .* sin(pi*xb); % [1/V]
|
||||
a2 = -(pi^2/(4*Vpi^2)) .* cos(pi*xb); % [1/V^2]
|
||||
a3 = +(pi^3/(12*Vpi^3)) .* sin(pi*xb); % [1/V^3]
|
||||
A0 = a0;
|
||||
A1 = a1 * Vpi;
|
||||
A2 = a2 * Vpi^2;
|
||||
A3 = a3 * Vpi^3;
|
||||
|
||||
%% Plot
|
||||
figure('Color','w'); clf;
|
||||
% --- (1) Field + power TF vs bias ---
|
||||
hold on; grid on;
|
||||
plot(xb, H_field, 'LineWidth', 1.4, 'DisplayName','Field','Color','black','LineStyle','--');
|
||||
% plot(xb, T_power, 'LineWidth', 1.4, 'DisplayName','Intensity','Color','black','LineStyle','-');
|
||||
|
||||
|
||||
% --- (2) Physical Taylor coefficients vs bias ---
|
||||
% nexttile; hold on; grid on;
|
||||
plot(xb, a0, 'LineWidth', 1.4, 'DisplayName','Intensity','Color','black','LineStyle','-');
|
||||
plot(xb, a1, 'LineWidth', 1.4, 'DisplayName','Linear');
|
||||
plot(xb, a2, 'LineWidth', 1.4, 'DisplayName','Even');
|
||||
plot(xb, a3, 'LineWidth', 1.4, 'DisplayName','Odd');
|
||||
|
||||
xlabel('$V/V_\pi$','Interpreter','latex');
|
||||
ylabel('Transfer');
|
||||
title('Static transfer functions vs bias');
|
||||
xlim([min(xb) max(xb)]);
|
||||
ylim([-1.05 1.05]);
|
||||
legend('Location','best');
|
||||
|
||||
% Optional: tighten y-limits to avoid a0 dominating the view
|
||||
% Comment out if you prefer auto-scaling.
|
||||
yl = ylim;
|
||||
ylim([min(yl(1), -max(abs([a1 a2 a3]))*1.1), max(yl(2), max(abs([a1 a2 a3]))*1.1)]);
|
||||
|
||||
xticks([0:0.5:2]);
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
% pmd_vs_length.m
|
||||
% ------------------------------------------------------------
|
||||
% Plots the Foschini-Poole (1991) analytical variance formula for PMD:
|
||||
%
|
||||
% sigma_T^2(z) = 2*(Delta_beta1)^2 * lc^2
|
||||
% * [ exp(-z/lc) + z/lc - 1 ]
|
||||
%
|
||||
% and overlays the two asymptotic regimes:
|
||||
% - Short-reach (z << lc) : sigma_T(z) ~ (Delta_beta1) * z
|
||||
% - Long-haul (z >> lc) : sigma_T(z) ~ Dp * sqrt(z)
|
||||
%
|
||||
% Parameters follow typical SMF values from the literature.
|
||||
% ------------------------------------------------------------
|
||||
|
||||
clear; clc;
|
||||
|
||||
%% ── Parameters ──────────────────────────────────────────────────────────────
|
||||
% Intrinsic local birefringence [ps/km]
|
||||
Delta_beta1 = 1e-1; % typical value, adjust as needed
|
||||
|
||||
% Correlation length [km]
|
||||
lc = 0.01; % ~50 m, typical for G.652 SMF
|
||||
|
||||
% PMD parameter [ps / sqrt(km)] — derived from the two above
|
||||
Dp = Delta_beta1 * sqrt(2 * lc);
|
||||
|
||||
% Distance axis [km]
|
||||
z_max = 10; % maximum distance
|
||||
z = linspace(0.001, z_max, 10000); % avoid z = 0 in log plot
|
||||
|
||||
%% ── Exact Foschini-Poole formula (sigma_T in ps) ────────────────────────────
|
||||
sigma_T_sq = 2 .* Delta_beta1.^2 .* lc.^2 ...
|
||||
.* (exp(-z ./ lc) + z ./ lc - 1);
|
||||
sigma_T = sqrt(sigma_T_sq); % RMS DGD [ps]
|
||||
|
||||
%% ── Asymptotic regimes ───────────────────────────────────────────────────────
|
||||
% Short-reach: linear growth (z << lc)
|
||||
sigma_T_short = Delta_beta1 .* z; % [ps]
|
||||
|
||||
% Long-haul: square-root growth (z >> lc)
|
||||
sigma_T_long = Dp .* sqrt(z); % [ps]
|
||||
|
||||
%% ── Plot ─────────────────────────────────────────────────────────────────────
|
||||
figure('Color','w','Position',[100 100 760 480]);
|
||||
hold on;
|
||||
|
||||
% Color palette (matching dissertation style)
|
||||
c_exact = [0.1216, 0.4706, 0.7059]; % blue – exact
|
||||
c_short = [0.8392, 0.1529, 0.1569]; % red – short-reach asymptote
|
||||
c_long = [0.1961, 0.6314, 0.1725]; % green – long-haul asymptote
|
||||
|
||||
% Exact solution
|
||||
h_exact = plot(z, sigma_T, ...
|
||||
'Color', c_exact, 'LineWidth', 2.0, ...
|
||||
'DisplayName', 'Exact (Foschini \& Poole)');
|
||||
|
||||
% Short-reach asymptote σ_T ≈ Δβ₁ · z
|
||||
h_short = plot(z, sigma_T_short, ...
|
||||
'Color', c_short, 'LineWidth', 1.4, 'LineStyle', '--', ...
|
||||
'DisplayName', '$\sigma_T \approx \Delta\beta_1 \cdot z$ \quad ($z \ll l_c$)');
|
||||
|
||||
% Long-haul asymptote σ_T ≈ D_p √z
|
||||
h_long = plot(z, sigma_T_long, ...
|
||||
'Color', c_long, 'LineWidth', 1.4, 'LineStyle', ':', ...
|
||||
'DisplayName', '$\sigma_T \approx D_p \sqrt{z}$ \quad ($z \gg l_c$)');
|
||||
|
||||
%% ── Axes & decoration ────────────────────────────────────────────────────────
|
||||
ax = gca;
|
||||
set(ax, 'XScale', 'log', 'YScale', 'log');
|
||||
|
||||
% ── X-axis: linear-style tick labels on log scale ────────────────────────
|
||||
x_ticks = [1e-3, 1e-2, 1e-1, 1, 10];
|
||||
ax.XTick = x_ticks;
|
||||
ax.XTickLabel = arrayfun(@(v) sprintf('%g km', v), x_ticks, 'UniformOutput', false);
|
||||
|
||||
% ── Y-axis: linear-style tick labels on log scale ────────────────────────
|
||||
y_ticks = [1e-3, 1e-2, 1e-1, 1, 10];
|
||||
ax.YTick = y_ticks;
|
||||
ax.YTickLabel = arrayfun(@(v) sprintf('%g ps', v), y_ticks, 'UniformOutput', false);
|
||||
|
||||
xlabel('Fiber length $z$ [km]', 'Interpreter', 'latex');
|
||||
ylabel('RMS DGD $\sigma_T$ [ps]', 'Interpreter', 'latex');
|
||||
|
||||
grid on; box on;
|
||||
xlim([min(z) z_max]);
|
||||
|
||||
legend([h_exact, h_short, h_long], ...
|
||||
'Location', 'northwest', 'Interpreter', 'latex', 'FontSize', 9);
|
||||
|
||||
% Parameter annotation
|
||||
anno_str = sprintf( ...
|
||||
['$\\Delta\\beta_1 = %.3g$ ps/km\n' ...
|
||||
'$l_c = %.0f$ m\n' ...
|
||||
'$D_p = \\Delta\\beta_1\\sqrt{2l_c} = %.4g$ ps/$\\sqrt{\\mathrm{km}}$'], ...
|
||||
Delta_beta1, lc*1e3, Dp);
|
||||
|
||||
annotation('textbox', [0.57 0.14 0.38 0.22], ...
|
||||
'String', anno_str, ...
|
||||
'Interpreter', 'latex', ...
|
||||
'FontSize', 8.5, ...
|
||||
'BackgroundColor','w', ...
|
||||
'EdgeColor', [0.5 0.5 0.5], ...
|
||||
'LineWidth', 0.8, ...
|
||||
'FitBoxToText', 'on');
|
||||
|
||||
%% ── Regime transition marker ─────────────────────────────────────────────────
|
||||
% Mark the crossover region around z = lc
|
||||
xline(lc, '--', ...
|
||||
'Color', [0.5 0.5 0.5], 'LineWidth', 0.8, ...
|
||||
'HandleVisibility', 'off');
|
||||
text(lc * 1.15, min(sigma_T)*3, '$l_c$', ...
|
||||
'Interpreter', 'latex', 'Color', [0.4 0.4 0.4], 'FontSize', 9);
|
||||
|
||||
%% ── Export (uncomment to use) ────────────────────────────────────────────────
|
||||
% mat2tikz_improved('C:\...\tikz\pmd\pmd_vs_length.tikz')
|
||||
@@ -1,50 +0,0 @@
|
||||
%% ============================================================
|
||||
% Minimal IM/DD Power Fading Plot
|
||||
% ============================================================
|
||||
|
||||
|
||||
%% Fiber and system parameters
|
||||
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||
lambda = 1290e-9; % operating wavelength [m]
|
||||
S0 = 0.09; % dispersion slope [ps/(nm²·km)]
|
||||
L = 10e3; % fiber length [m]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
%% Derived quantities
|
||||
S0_si = S0 * 1e3; % → s/m³
|
||||
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
|
||||
D_si = D_lambda * 1e-6; % → s/m²
|
||||
b2 = -D_si * lambda^2 / (2*pi*c); % s²/m
|
||||
|
||||
Dacc = D_lambda * L;
|
||||
fprintf('Accumulated Dispersion: %.2f ps/nm \n', Dacc / 1e3);
|
||||
|
||||
%% Frequency grid
|
||||
f_max = 200e9;
|
||||
f = linspace(0, f_max, 5000); % [Hz]
|
||||
|
||||
%% IM/DD transfer function (power fading)
|
||||
phi = 2*pi^2 * b2 * f.^2 * L;
|
||||
H = abs(cos(phi));
|
||||
|
||||
%% Plot
|
||||
figure('Color','w');
|
||||
plot(f/1e9, 10*log10(H), 'LineWidth', 1,'Color','black');
|
||||
grid on; box on;
|
||||
xlabel('Frequency [GHz]');
|
||||
ylabel('Magnitude [dB]');
|
||||
% title(sprintf('IM/DD Power Fading: 10 km; 1275nm', lambda*1e9, L/1000),"Interpreter","latex");
|
||||
ylim([-20 0]);
|
||||
|
||||
%% Mark analytic null frequencies up to order 5
|
||||
max_order = 3;
|
||||
for n = 0:max_order
|
||||
f_null_n = sqrt( c*(2*n + 1)/(2*abs(D_si)*lambda^2*L) );
|
||||
xline(f_null_n/1e9, '--', 'LineWidth', 1.2, ...
|
||||
'Color', [0.1216, 0.4706, 0.7059]);
|
||||
text(f_null_n/1e9, -15, sprintf('$f_{\\mathrm{null}, %d}=%.1f$ GHz', n, f_null_n/1e9), ...
|
||||
'BackgroundColor', 'w', 'EdgeColor', 'k', 'Interpreter', 'latex', ...
|
||||
'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
|
||||
end
|
||||
|
||||
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\dispersion\power_fading.tikz')
|
||||
@@ -1,49 +0,0 @@
|
||||
% Parameters
|
||||
symbols = [0, 1, 2, 3]; % PAM-4 symbols
|
||||
P_X = [0.25, 0.25, 0.25, 0.25]; % Uniform probabilities
|
||||
sigma2 = 0.1; % Noise variance
|
||||
received_samples = [0.2, 1.1, 1.9, 2.8];% Received symbols (example)
|
||||
gray_bits = [0 0; 0 1; 1 1; 1 0]; % Gray coding (bits per symbol)
|
||||
m = size(gray_bits, 2); % Bits per symbol
|
||||
N = length(received_samples); % Number of received samples
|
||||
|
||||
% Conditional probability function for AWGN
|
||||
q_Y_given_X = @(y, x) (1 / sqrt(2 * pi * sigma2)) * exp(-(y - x).^2 / (2 * sigma2));
|
||||
|
||||
% Entropy term
|
||||
H_X = -sum(P_X .* log2(P_X)); % Entropy of input distribution
|
||||
|
||||
% GMI computation
|
||||
noise_impact_term = 0;
|
||||
for k = 1:N
|
||||
y_k = received_samples(k); % Current received sample
|
||||
[~, closest_symbol_idx] = min(abs(symbols - y_k)); % Closest symbol index
|
||||
closest_symbol = symbols(closest_symbol_idx); % Closest symbol
|
||||
|
||||
for i = 1:m
|
||||
% Extract i-th bit for each symbol
|
||||
bit_mask = gray_bits(:, i); % Binary column for i-th bit of all symbols
|
||||
matching_symbols = symbols(bit_mask == gray_bits(closest_symbol_idx, i));
|
||||
|
||||
% Numerator: Sum over x in x_{b_{k, i}}
|
||||
numerator = sum(q_Y_given_X(y_k, matching_symbols) .* P_X(ismember(symbols, matching_symbols)));
|
||||
|
||||
% Denominator: Sum over all x
|
||||
denominator = sum(q_Y_given_X(y_k, symbols) .* P_X);
|
||||
|
||||
% Logarithmic contribution
|
||||
noise_impact_term = noise_impact_term + log2(numerator / denominator);
|
||||
end
|
||||
end
|
||||
|
||||
% Normalize the noise impact term by N
|
||||
noise_impact_term = noise_impact_term / N;
|
||||
|
||||
% GMI
|
||||
GMI = H_X + noise_impact_term;
|
||||
NGMI = GMI / m;
|
||||
|
||||
|
||||
% Display the result
|
||||
fprintf('GMI: %.4f bits\n', GMI);
|
||||
fprintf('NGMI: %.4f bits\n', NGMI);
|
||||
@@ -1,43 +0,0 @@
|
||||
% estimate_entropies.m
|
||||
clear; rng(0);
|
||||
|
||||
%% 1) Parameters
|
||||
M = 1e5; % number of Monte-Carlo samples
|
||||
EbNo_dB = 0; % SNR per bit in dB
|
||||
EbNo = 10^(EbNo_dB/10);
|
||||
sigma2 = 1/(2*EbNo); % noise variance per real dimension
|
||||
|
||||
% 4-QAM constellation (row vector)
|
||||
X = [1+1j, 1-1j, -1+1j, -1-1j];
|
||||
N = numel(X);
|
||||
PX = ones(1,N)/N; % uniform PMF
|
||||
|
||||
%% 2) Generate transmit symbols and AWGN
|
||||
idx = randi(N,1,M); % 1×M random symbol indices
|
||||
s = X(idx); % 1×M transmitted symbols
|
||||
n = sqrt(sigma2)*(randn(1,M) + 1j*randn(1,M));
|
||||
y = s + n; % 1×M received samples
|
||||
|
||||
%% 3) Compute p_{Y|X}(y|x) for each constellation point
|
||||
% Create an N×M matrix where row n is |y - X(n)|^2
|
||||
d2 = abs(bsxfun(@minus, X(:), y)).^2; % N×M
|
||||
pYgX = (1/(pi*sigma2)) * exp(-d2 / sigma2); % N×M
|
||||
|
||||
%% 4) Estimate H(Y) = -E[ log2 p_Y(Y) ]
|
||||
% Mixture density p_Y(y_m) = sum_n PX(n)*pYgX(n,m)
|
||||
pY = PX * pYgX; % 1×M
|
||||
HY = -mean(log2(pY)); % bits
|
||||
|
||||
%% 5) Estimate H(Y|X) = -E[ log2 p(Y|X) ]
|
||||
% For each m, pick the row corresponding to the true idx(m)
|
||||
linearIdx = sub2ind([N, M], idx, 1:M);
|
||||
pYgX_true = pYgX(linearIdx); % 1×M
|
||||
HYgX = -mean(log2(pYgX_true)); % bits
|
||||
|
||||
%% 6) Mutual information
|
||||
I = HY - HYgX;
|
||||
|
||||
%% 7) Display
|
||||
fprintf('Estimated H(Y) = %.4f bits\n', HY);
|
||||
fprintf('Estimated H(Y|X) = %.4f bits\n', HYgX);
|
||||
fprintf('Estimated I(X;Y) = %.4f bits\n', I);
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
if 0
|
||||
pmd = 0.2 * ( 1e-12 / sqrt(1e3) ) ; % 0.1 ps/sqrt(km) -> 1e-9 -> s/sqrt(m)
|
||||
L = 1000; % m
|
||||
corr_len = 100;
|
||||
num_wave_plates = 100;
|
||||
wp_len = L / num_wave_plates; %waveplate length
|
||||
dgd = pmd * sqrt(L);
|
||||
fdac = 120e9; % GHz
|
||||
|
||||
fsim = fdac * 512 ; %oversampled simulation frequency
|
||||
dt = 1/fsim; % sample time
|
||||
nt = 4; % sampled signal length
|
||||
omega = 2*pi*[(0:nt/2-1),(-nt/2:-1)]/(dt*nt) ; %angular frequency vector for optical signal of length nt
|
||||
omega = 2*pi*fsim ; %angular frequency vector for optical signal of length nt
|
||||
|
||||
for rlz = 1:20000
|
||||
|
||||
db0 = [];
|
||||
db1 = [];
|
||||
delta_beta = [];
|
||||
|
||||
db0 = (rand(num_wave_plates,1)*2*pi - pi); % normal distr. between -pi <-> +pi
|
||||
|
||||
db1 = sqrt(3*pi/8)*(dgd/fsim)/ num_wave_plates .* omega; % linear increasing delta beta 1
|
||||
|
||||
%loop over waveplates
|
||||
for n_wp = 1:length(db0)
|
||||
delta_beta(n_wp,:) = (db1+db0(n_wp))./corr_len;
|
||||
end
|
||||
|
||||
dphi = delta_beta*wp_len; %phase shift due to propagation constant = beta * L
|
||||
|
||||
if rlz == 1
|
||||
figure()
|
||||
plot(cumsum( delta_beta ));
|
||||
end
|
||||
|
||||
dphi_end(rlz) = sum( dphi );
|
||||
|
||||
end
|
||||
|
||||
figure;
|
||||
histogram((dphi_end),100);
|
||||
|
||||
deltaT = mean(abs(dphi_end));
|
||||
|
||||
%H = exp(-1j*dphi); % Filter to apply phase shift in freq. domain
|
||||
end
|
||||
|
||||
|
||||
PMD = 0.1 * ( 1e-12 / sqrt(1e3) ); %PMD s/sqrt(m)
|
||||
L = 10e3; %m
|
||||
sigma_dgd = PMD * sqrt(L); % in sec.
|
||||
disp(['variance of DGD in pico seconds: ',num2str(sigma_dgd*1e12)]);
|
||||
disp(['variance of DGD in pico seconds: ',num2str(sigma_dgd*1e12)]);
|
||||
|
||||
dgd = [];
|
||||
for i = 1:4
|
||||
dgd(i,:) = DGD(sigma_dgd,10000);
|
||||
end
|
||||
|
||||
rms = PMD * sqrt(40e3) * 1e12 ; % in sec.
|
||||
t = [0:0.01:100];
|
||||
z2 = sqrt(2/pi).*(t.^2)/(rms.^3).*exp(-t.^2/(2*rms^2)) ;
|
||||
figure;
|
||||
histogram(dgd*1e12,1000,"Normalization","pdf");
|
||||
hold on
|
||||
plot(t(1:200),z2(1:200),'r');
|
||||
hold off
|
||||
|
||||
function z = DGD(sigma_dgd,N)
|
||||
|
||||
%PMD = sqrt( (PMD*1e12)^2/3 );
|
||||
|
||||
% PMD = PMD * 1/( 1e-12 / sqrt(1e3) );
|
||||
|
||||
sigma_dgd = sigma_dgd*1e12;
|
||||
|
||||
x = [0:N];
|
||||
|
||||
almaga = randn(3,N)*sigma_dgd;
|
||||
|
||||
y = almaga.^2;
|
||||
|
||||
z0 = sqrt(sum(y,1));
|
||||
|
||||
|
||||
disp(mean(z0));
|
||||
disp(std(z0));
|
||||
% disp(var(z0));
|
||||
|
||||
z1 = [];
|
||||
|
||||
for l = 0:0.1:N
|
||||
z1 = [z1 sum(z0(1,:)>l & z0(1,:)<l+0.1) / N ];
|
||||
end
|
||||
|
||||
z = z0 *1e-12;
|
||||
|
||||
rms = sigma_dgd;
|
||||
t = [0:0.01:N];
|
||||
z2 = sqrt(2/pi).*(t.^2)/(rms.^3).*exp(-t.^2/(2*rms^2)) ;
|
||||
|
||||
figure;
|
||||
histogram(z0,1000,"Normalization","pdf");
|
||||
hold on
|
||||
plot(t(1:200),z2(1:200),'r');
|
||||
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
|
||||
PMDcoeff = 0.1 * ( 1e-12 / sqrt(1e3) ); %PMD s/sqrt(m)
|
||||
|
||||
|
||||
L_40 = 40e3; %m
|
||||
mean_dgd = PMDcoeff * sqrt(L_40); % in sec. E(tau) == PMD value
|
||||
|
||||
disp(['defined mean of DGD in pico seconds: ',num2str(mean_dgd*1e12)]);
|
||||
|
||||
dgd_40km = [];
|
||||
for i = 1:4000
|
||||
dgd_40km(i,:) = getDGDrealization(mean_dgd,1);
|
||||
end
|
||||
|
||||
disp(['simulated mean of DGD in pico seconds: ',num2str(mean(dgd_40km)*1e12)]);
|
||||
|
||||
%%% 2 test for segmented link %%%%
|
||||
|
||||
L_10 = 10e3; %m
|
||||
mean_dgd = PMDcoeff * sqrt(L_10); % in sec. E(tau) == PMD value
|
||||
|
||||
dgd_10km = [];
|
||||
for j = 1:4
|
||||
for i = 1:1000
|
||||
dgd_10km(i,j) = getDGDrealization(mean_dgd,1);
|
||||
end
|
||||
end
|
||||
|
||||
a = sum(dgd_10km,2) ;
|
||||
|
||||
%%% calc maxwell curve
|
||||
mean_dgd = PMDcoeff * sqrt(L_40) * 1e12 ; % in sec.
|
||||
q = sqrt(pi/8) * mean_dgd;
|
||||
t = [0:0.01:100];
|
||||
|
||||
maxwell = sqrt(2/pi).* (t.^2)/(q.^3) .* exp(-t.^2/(2*q^2)) ;
|
||||
|
||||
|
||||
%%% plot everything
|
||||
|
||||
figure;
|
||||
histogram(dgd_40km*1e12,1000,"Normalization","pdf",'EdgeColor','none','FaceColor','b','FaceAlpha',0.6);
|
||||
hold on
|
||||
histogram(a*1e12,1000,"Normalization","pdf",'EdgeColor','none','FaceColor','g','FaceAlpha',0.6);
|
||||
plot(t(1:200),maxwell(1:200),'r','LineWidth',3);
|
||||
xline(mean_dgd,'LineWidth',3,'Color','magenta')
|
||||
hold off
|
||||
|
||||
function z = getDGDrealization(mean_dgd,N)
|
||||
|
||||
mean_dgd = mean_dgd; %to pico seconds
|
||||
q = sqrt(pi/8) * mean_dgd;
|
||||
threenormaldists = randn(3,N)*q; %3x normal dist around [-1,1] with a deviation of mean_dgd
|
||||
|
||||
y = threenormaldists.^2;
|
||||
|
||||
z = sqrt(sum(y,1));
|
||||
|
||||
end
|
||||
@@ -1,64 +0,0 @@
|
||||
% Parameters
|
||||
N_values = [10 100 1000 4096]; % Different filter lengths to analyze
|
||||
fs = 112e9;
|
||||
|
||||
% Create figure
|
||||
figure;
|
||||
|
||||
% Plot frequency responses
|
||||
subplot(211)
|
||||
hold on
|
||||
grid on
|
||||
ylabel('Magnitude (dB)')
|
||||
title('Frequency Response')
|
||||
yline(-3,'--r')
|
||||
ylim([-40 5])
|
||||
|
||||
subplot(212)
|
||||
hold on
|
||||
grid on
|
||||
xlabel('Frequency (GHz)')
|
||||
ylabel('Phase (rad)')
|
||||
title('Phase Response')
|
||||
|
||||
% Color map for different lines
|
||||
colors = cbrewer2('Set1',length(N_values));
|
||||
|
||||
% Loop through different filter lengths
|
||||
for i = 1:length(N_values)
|
||||
N = N_values(i);
|
||||
|
||||
% Filter coefficients
|
||||
b = ones(1,N)/N;
|
||||
a = 1;
|
||||
|
||||
% Frequency response
|
||||
[h,w] = freqz(b,a,4096*8);
|
||||
freq = (w/(2*pi))*fs;
|
||||
h_db = 20*log10(abs(h));
|
||||
|
||||
% Plot magnitude response
|
||||
subplot(211)
|
||||
plot(freq/1e9, h_db, 'Color', colors(i,:), 'DisplayName', sprintf('N=%d', N),'LineWidth',0.1)
|
||||
|
||||
% Plot phase response
|
||||
subplot(212)
|
||||
plot(freq/1e9, unwrap(angle(h)), 'Color', colors(i,:), 'DisplayName', sprintf('N=%d', N),'LineWidth',0.1)
|
||||
|
||||
% Find -3dB frequency
|
||||
cutoff_idx = find(h_db <= -3, 1);
|
||||
f_cutoff = freq(cutoff_idx)/1e9;
|
||||
fprintf('N=%d: Cutoff frequency (-3dB point): %.2f GHz\n', N, f_cutoff)
|
||||
end
|
||||
|
||||
% Add legend and adjust axes
|
||||
subplot(211)
|
||||
legend('show')
|
||||
xlim([0 16]) % Adjust x-axis limit to better see the differences
|
||||
|
||||
subplot(212)
|
||||
legend('show')
|
||||
xlim([0 16]) % Adjust x-axis limit to better see the differences
|
||||
|
||||
% Analytical approximation
|
||||
f_3db_approx = 0.443 * fs./N_values ./ 1e9;
|
||||
@@ -1,69 +0,0 @@
|
||||
|
||||
|
||||
|
||||
w0 = [1290:2:1290+15*2]';
|
||||
w0 = [1290:2:1290+15*2]';
|
||||
w0 = [ 1302 1304 1306 1308]';
|
||||
%w0 = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]';
|
||||
m = 0.5*(numel(w0)^3 - numel(w0)^2);
|
||||
a = [1,1,1]';
|
||||
|
||||
w = w0;
|
||||
|
||||
|
||||
|
||||
|
||||
for o = 2:3
|
||||
|
||||
p = nchoosek(w,3);
|
||||
|
||||
q = [];
|
||||
parfor i = 1:size(p,1)
|
||||
|
||||
q_ = perms(p(i,:));
|
||||
q = [q;q_];
|
||||
|
||||
end
|
||||
p = q;
|
||||
%p = unique(q,"rows");
|
||||
w_ = p(:,1) + p(:,2) - p(:,3);
|
||||
a_ = ones(size(w_)).* 1/o;
|
||||
|
||||
w = [w ; w_];
|
||||
a = [a ; a_];
|
||||
% w = unique(w);
|
||||
% a = unique(a);
|
||||
|
||||
m(end+1) = 0.5*(numel(w)^3 - numel(w)^2);
|
||||
|
||||
end
|
||||
|
||||
figure(11)
|
||||
hold on
|
||||
|
||||
lambda = min(w):max(w);
|
||||
|
||||
gen = sum(lambda == w,1);
|
||||
gen(gen==0) = NaN;
|
||||
stem(lambda,gen,"filled",'LineWidth',1,'Marker','o','MarkerSize',2,'LineStyle',':')
|
||||
|
||||
initial = sum(lambda == w0,1);
|
||||
initial(initial==0) = NaN;
|
||||
stem(lambda,initial,"filled",'LineWidth',1.5,'MarkerSize',5,'Marker','^');
|
||||
|
||||
xlabel('Wavelength');
|
||||
ylabel('number of FWM products');
|
||||
|
||||
grid minor
|
||||
legend('Generated Products', 'Initial Channel Position')
|
||||
AxesMain = gca;
|
||||
fig = gcf;
|
||||
fontsize(AxesMain,8,"points")
|
||||
|
||||
fig.Units = "centimeters";
|
||||
fig.Position = [2 2 8.5 7];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
%% Laser Offset Statistics
|
||||
|
||||
figure
|
||||
for i = 1
|
||||
res = 1.7e6;
|
||||
n_chann = 16;
|
||||
df_T_exact = (-n_chann/2+0.5:n_chann/2).* 200e9;
|
||||
|
||||
for key = 1:100
|
||||
laser_frequency_imperfection(key,:) = res .* round(randn(1,n_chann)*i*100);
|
||||
df_T(key,:) = df_T_exact + laser_frequency_imperfection(key,:);
|
||||
end
|
||||
|
||||
hold on
|
||||
histogram(laser_frequency_imperfection.*1e-6,100,"Normalization","probability","EdgeColor","none","FaceAlpha",0.3,'DisplayName',['Std. Dev.: ',num2str(mean(std(laser_frequency_imperfection))*1e-6),' MHz']);
|
||||
xlabel('Laser Frequency Offset in MHz');
|
||||
ylabel('Probability');
|
||||
title(['Laser deviations from exact grid.'])
|
||||
|
||||
end
|
||||
|
||||
%% ZDW Statistics
|
||||
|
||||
for k = 1:1000
|
||||
|
||||
% Set parameters
|
||||
meanUniformMin = 1309;
|
||||
meanUniformMax = 1315;
|
||||
meanValue = 1310;
|
||||
sigma = 2;
|
||||
|
||||
% Seed the random number generator (assuming Mersenne Twister)
|
||||
rng(k);
|
||||
|
||||
% Generate normally distributed random numbers
|
||||
randomNumbers(k,:) = normrnd(meanValue, sigma, [n_chann, 1]).';
|
||||
|
||||
end
|
||||
|
||||
figure;
|
||||
histogram(randomNumbers,100,"Normalization","probability","EdgeColor","none");
|
||||
xlabel('ZDW in nm');
|
||||
ylabel('Probability');
|
||||
@@ -1,65 +0,0 @@
|
||||
%%FWM analysis from "Analytical Calculation of the Number of
|
||||
%%Four-Wave-Mixing Products in Optical Multichannel Communication Systems"
|
||||
|
||||
N_ = [4,8,16];
|
||||
|
||||
df_hz = 400e9;
|
||||
center_nm = 1310;
|
||||
|
||||
figure()
|
||||
for i = 1:length(N_)
|
||||
|
||||
vec = (2*N_(i)-1:-1:2-N_(i)) -(N_(i)/2+0.5);
|
||||
channelplan_hz = nm2hz(center_nm) + (vec * df_hz) ;
|
||||
channelplan_nm = hz2nm(channelplan_hz);
|
||||
|
||||
[Mndg,Mdg] = getProducts(N_(i));
|
||||
total(i) = sum(Mndg) + sum(Mdg);
|
||||
subplot(1,length(N_),i)
|
||||
xline(calcWavelengthPlan(N_(i), df_hz, center_nm));
|
||||
hold on
|
||||
stem(channelplan_nm,(Mndg+Mdg),'filled','LineWidth',1,'Marker','o','MarkerSize',2)
|
||||
stem(channelplan_nm,(Mdg),'filled','LineWidth',1,'Marker','none');
|
||||
ylim([0,100])
|
||||
xlim([1260, 1365]);
|
||||
grid off
|
||||
xlabel('O-band wavelength region in nm');
|
||||
ylabel('Number of FWM products');
|
||||
title([num2str(N_(i)),' ch.'])
|
||||
|
||||
end
|
||||
|
||||
|
||||
function [Mndg,Mdg] = getProducts(N)
|
||||
|
||||
s = abs(2-N-1) ;
|
||||
|
||||
for n = 2-N:2*N-1
|
||||
|
||||
if n<-N
|
||||
Mdg(n+s) = 0;
|
||||
elseif (-N <= n)&&(n <= 0)
|
||||
Mdg(n+s) = N - ceil((N-n)/2);
|
||||
elseif (1 <= n)&&(n <= N)
|
||||
Mdg(n+s) = N - 1 - floor(n/2) - ceil((N-n)/2);
|
||||
elseif (N < n)&&(n <= 2*N)
|
||||
Mdg(n+s) = N - floor(n/2);
|
||||
elseif n > 2*N
|
||||
Mdg(n+s) = 0;
|
||||
end
|
||||
|
||||
if n<-N
|
||||
Mndg(n+s) = 0;
|
||||
elseif (-N <= n)&&(n < 1)
|
||||
Mndg(n+s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
|
||||
elseif (1 <= n)&&(n <= N)
|
||||
Mndg(n+s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
|
||||
elseif (N < n)&&(n <= 2*N)
|
||||
Mndg(n+s) = floor(N^2 + n^2 /4 - N*n);
|
||||
elseif n > 2*N
|
||||
Mndg(n+s) = 0;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
function [eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm)
|
||||
% FWM efficiency including phase mismatch and attenuation.
|
||||
% alphaDbPerKm is the power attenuation in dB/km, Lkm is the fiber length in km.
|
||||
|
||||
deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds);
|
||||
|
||||
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
|
||||
Lm = Lkm .* 1e3;
|
||||
|
||||
denominator = alphaNpPerM.^2 + deltaBeta.^2;
|
||||
term1 = alphaNpPerM.^2 ./ denominator;
|
||||
|
||||
loss_term = 1 - exp(-alphaNpPerM .* Lm);
|
||||
|
||||
if abs(alphaNpPerM) < eps
|
||||
term2 = 4 .* sin(deltaBeta .* Lm ./ 2).^2 ./ max((alphaNpPerM .* Lm).^2, eps);
|
||||
else
|
||||
term2 = 1 + 4 .* exp(-alphaNpPerM .* Lm) .* sin(deltaBeta .* Lm ./ 2).^2 ./ (loss_term.^2);
|
||||
end
|
||||
|
||||
eta = term1 .* term2;
|
||||
|
||||
end
|
||||
@@ -1,48 +0,0 @@
|
||||
function [P_fwm, eta, deltaBeta, Leff] = calcFwmPower( ...
|
||||
f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm, ...
|
||||
P_i, P_j, P_k, gammaWInvKmInv, degeneracyFactor)
|
||||
% Calculate FWM power for a fiber with attenuation and phase mismatch.
|
||||
%
|
||||
% Inputs:
|
||||
% f_i, f_j, f_k, f_0 : frequencies in Hz
|
||||
% Ds : dispersion slope in ps / (nm^2 km)
|
||||
% alphaDbPerKm : attenuation in dB/km
|
||||
% Lkm : fiber length in km
|
||||
% P_i, P_j, P_k : launch powers in W
|
||||
% gammaWInvKmInv : nonlinear coefficient in 1/(W km)
|
||||
% degeneracyFactor : typically 3 for degenerate FWM, 6 for non-degenerate
|
||||
|
||||
if nargin < 8 || isempty(P_i)
|
||||
P_i = 1;
|
||||
end
|
||||
if nargin < 9 || isempty(P_j)
|
||||
P_j = P_i;
|
||||
end
|
||||
if nargin < 10 || isempty(P_k)
|
||||
P_k = 1;
|
||||
end
|
||||
if nargin < 11 || isempty(gammaWInvKmInv)
|
||||
gammaWInvKmInv = 1;
|
||||
end
|
||||
if nargin < 12 || isempty(degeneracyFactor)
|
||||
degeneracyFactor = 1;
|
||||
end
|
||||
|
||||
[eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm);
|
||||
|
||||
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
|
||||
Lm = Lkm .* 1e3;
|
||||
gammaWInvMInv = gammaWInvKmInv ./ 1e3;
|
||||
|
||||
if abs(alphaNpPerM) < eps
|
||||
Leff = Lm;
|
||||
else
|
||||
Leff = (1 - exp(-alphaNpPerM .* Lm)) ./ alphaNpPerM;
|
||||
end
|
||||
|
||||
P_fwm = degeneracyFactor .* eta .* ...
|
||||
(gammaWInvMInv .* Leff).^2 .* ...
|
||||
P_i .* P_j .* P_k .* ...
|
||||
exp(-alphaNpPerM .* Lm);
|
||||
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
function deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds)
|
||||
% Approximate phase mismatch for degenerate FWM close to the ZDW.
|
||||
% Inputs are frequencies in Hz.
|
||||
% f_i, f_j : pump frequencies (equal in the degenerate case)
|
||||
% f_k : signal frequency
|
||||
% f_0 : zero-dispersion frequency
|
||||
% Ds : dispersion slope in ps / (nm^2 km)
|
||||
|
||||
c = physconst('LightSpeed');
|
||||
|
||||
pump_frequency = 0.5 .* (f_i + f_j);
|
||||
lambda_zdw_m = c ./ f_0;
|
||||
dispersion_slope_si = Ds .* 1e3;
|
||||
|
||||
deltaBeta = -(2 .* pi .* lambda_zdw_m.^4 ./ c.^2) .* ...
|
||||
dispersion_slope_si .* ...
|
||||
(pump_frequency - f_0) .* ...
|
||||
(pump_frequency - f_k).^2;
|
||||
|
||||
end
|
||||
@@ -1,104 +0,0 @@
|
||||
clear;
|
||||
clc;
|
||||
|
||||
% Sweep the degenerate pump frequency around its nominal wavelength.
|
||||
pump_detuning_hz = (-800:0.01:800) .* 1e9;
|
||||
|
||||
% Degenerate FWM setup: two pump photons at f_p and one signal at f_s
|
||||
% generate an idler at f_i = 2*f_p - f_s.
|
||||
pump_wavelength_nm = 1310;
|
||||
signal_wavelength_nm = 1308;
|
||||
zdw_wavelength_nm = 1310;
|
||||
|
||||
f_pump_nominal = wavelength2frequency(pump_wavelength_nm, 'nm');
|
||||
f_signal_scalar = wavelength2frequency(signal_wavelength_nm, 'nm');
|
||||
f_zdw_scalar = wavelength2frequency(zdw_wavelength_nm, 'nm');
|
||||
|
||||
f_pump = f_pump_nominal + pump_detuning_hz;
|
||||
f_signal = f_signal_scalar .* ones(size(f_pump));
|
||||
f_zdw = f_zdw_scalar .* ones(size(f_pump));
|
||||
f_idler = 2 .* f_pump - f_signal;
|
||||
|
||||
% Fiber parameters
|
||||
dispersion_slope_ps_nm2_km = 0.07;
|
||||
attenuation_db_per_km = 0.21;
|
||||
fiber_length_km = 10;
|
||||
|
||||
% Launch powers and nonlinear coefficient
|
||||
pump_power_dbm = 10;
|
||||
signal_power_dbm = 10;
|
||||
pump_power_w = dbm2watt(pump_power_dbm);
|
||||
signal_power_w = dbm2watt(signal_power_dbm);
|
||||
gamma_w_inv_km_inv = 1.3;
|
||||
degeneracy_factor = 3;
|
||||
|
||||
[P_fwm, eta, delta_beta, L_eff_m] = calcFwmPower( ...
|
||||
f_pump, f_pump, f_signal, f_zdw, ...
|
||||
dispersion_slope_ps_nm2_km, attenuation_db_per_km, fiber_length_km, ...
|
||||
pump_power_w, pump_power_w, signal_power_w, ...
|
||||
gamma_w_inv_km_inv, degeneracy_factor);
|
||||
|
||||
f_pump_thz = f_pump .* 1e-12;
|
||||
f_zdw_thz = f_zdw_scalar .* 1e-12;
|
||||
f_signal_thz = f_signal_scalar .* 1e-12;
|
||||
idler_power_dbm = 10 .* log10(max(P_fwm, realmin) ./ 1e-3);
|
||||
|
||||
figure;
|
||||
tiledlayout(2,1);
|
||||
|
||||
ax1 = nexttile;
|
||||
plot(ax1, f_pump_thz, eta, 'LineWidth', 2);
|
||||
hold(ax1, 'on');
|
||||
xline(ax1, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
|
||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
|
||||
xline(ax1, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
|
||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
|
||||
ylabel(ax1, 'FWM efficiency');
|
||||
grid(ax1, 'on');
|
||||
title(ax1, 'FWM Efficiency and Idler Power versus Pump Frequency');
|
||||
|
||||
ax2 = nexttile;
|
||||
plot(ax2, f_pump_thz, idler_power_dbm, 'LineWidth', 2);
|
||||
hold(ax2, 'on');
|
||||
xline(ax2, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
|
||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
|
||||
xline(ax2, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
|
||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
|
||||
xlabel(ax2, 'Pump frequency (THz)');
|
||||
ylabel(ax2, 'FWM idler power (dBm)');
|
||||
grid(ax2, 'on');
|
||||
|
||||
fprintf('Pump wavelength : %.3f nm -> %.6f THz\n', ...
|
||||
pump_wavelength_nm, f_pump_nominal .* 1e-12);
|
||||
fprintf('Signal wavelength : %.3f nm -> %.6f THz\n', ...
|
||||
signal_wavelength_nm, f_signal_scalar .* 1e-12);
|
||||
fprintf('ZDW wavelength : %.3f nm -> %.6f THz\n', ...
|
||||
zdw_wavelength_nm, f_zdw_scalar .* 1e-12);
|
||||
fprintf('Pump launch power : %.2f dBm -> %.4g W\n', ...
|
||||
pump_power_dbm, pump_power_w);
|
||||
fprintf('Signal launch power : %.2f dBm -> %.4g W\n', ...
|
||||
signal_power_dbm, signal_power_w);
|
||||
fprintf('Peak FWM efficiency : %.4g\n', max(eta));
|
||||
fprintf('Peak FWM idler power : %.4g W (%.2f dBm)\n', ...
|
||||
max(P_fwm), 10 .* log10(max(P_fwm) ./ 1e-3));
|
||||
fprintf('Effective fiber length : %.4f km\n', L_eff_m ./ 1e3);
|
||||
fprintf('Idler wavelength range : %.3f nm to %.3f nm\n', ...
|
||||
min(frequency2wavelength(f_idler, 'nm')), max(frequency2wavelength(f_idler, 'nm')));
|
||||
fprintf('Max |delta beta| : %.4g 1/m\n', max(abs(delta_beta)));
|
||||
|
||||
function wavelength = frequency2wavelength(frequency, outputUnit)
|
||||
c = physconst('LightSpeed');
|
||||
wavelength = c ./ frequency;
|
||||
|
||||
switch lower(outputUnit)
|
||||
case 'm'
|
||||
case 'nm'
|
||||
wavelength = wavelength .* 1e9;
|
||||
otherwise
|
||||
error('Unsupported output unit "%s". Use "m" or "nm".', outputUnit);
|
||||
end
|
||||
end
|
||||
|
||||
function power_w = dbm2watt(power_dbm)
|
||||
power_w = 1e-3 .* 10.^(power_dbm ./ 10);
|
||||
end
|
||||
@@ -1,124 +0,0 @@
|
||||
%% Validate the analytical FWM product count against a brute-force reference
|
||||
% The paper counts channel combinations, not only unique output frequencies:
|
||||
% non-degenerate: i < j, k ~= i, k ~= j, n = i + j - k
|
||||
% degenerate: i == j, k ~= i, n = 2*i - k
|
||||
|
||||
clear;
|
||||
clc;
|
||||
|
||||
N_values = [4, 8, 16];
|
||||
plot_N = 8;
|
||||
|
||||
fprintf('Validating analytical FWM product count from Goebel and Hanik (2008)\n');
|
||||
|
||||
for idxN = 1:numel(N_values)
|
||||
N = N_values(idxN);
|
||||
fprintf('\nN = %d\n', N);
|
||||
|
||||
[Mndg_ana, Mdg_ana] = getProducts(N);
|
||||
[Mndg_brute, Mdg_brute, n_values] = getProductsBruteForce(N);
|
||||
|
||||
diff_ndg = Mndg_ana - Mndg_brute;
|
||||
diff_dg = Mdg_ana - Mdg_brute;
|
||||
|
||||
fprintf(' Analytical total : %d\n', sum(Mndg_ana) + sum(Mdg_ana));
|
||||
fprintf(' Brute-force total : %d\n', sum(Mndg_brute) + sum(Mdg_brute));
|
||||
|
||||
if all(diff_ndg == 0) && all(diff_dg == 0)
|
||||
fprintf(' Match : yes\n');
|
||||
else
|
||||
fprintf(' Match : no\n');
|
||||
fprintf(' Non-degenerate diff: %s\n', mat2str(diff_ndg));
|
||||
fprintf(' Degenerate diff : %s\n', mat2str(diff_dg));
|
||||
end
|
||||
|
||||
if N == plot_N
|
||||
plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N);
|
||||
end
|
||||
end
|
||||
|
||||
function [Mndg, Mdg, n_values] = getProductsBruteForce(N)
|
||||
n_values = (2 - N):(2*N - 1);
|
||||
Mndg = zeros(size(n_values));
|
||||
Mdg = zeros(size(n_values));
|
||||
|
||||
for idx = 1:numel(n_values)
|
||||
n = n_values(idx);
|
||||
|
||||
% Degenerate products: two identical pumps and one different channel.
|
||||
for i = 1:N
|
||||
k = 2*i - n;
|
||||
if isValidChannel(k, N) && (k ~= i)
|
||||
Mdg(idx) = Mdg(idx) + 1;
|
||||
end
|
||||
end
|
||||
|
||||
% Non-degenerate products: unordered pump pair plus one third channel.
|
||||
for i = 1:N
|
||||
for j = (i + 1):N
|
||||
k = i + j - n;
|
||||
if isValidChannel(k, N) && (k ~= i) && (k ~= j)
|
||||
Mndg(idx) = Mndg(idx) + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tf = isValidChannel(channel_idx, N)
|
||||
tf = (channel_idx >= 1) && (channel_idx <= N) && (channel_idx == round(channel_idx));
|
||||
end
|
||||
|
||||
function plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N)
|
||||
figure;
|
||||
|
||||
subplot(1,2,1);
|
||||
stem(n_values, Mndg_ana + Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
|
||||
hold on;
|
||||
stem(n_values, Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'none');
|
||||
title(['Analytical (N=', num2str(N), ')']);
|
||||
xlabel('Product index n');
|
||||
ylabel('Number of FWM products');
|
||||
legend('Total', 'Degenerate');
|
||||
grid on;
|
||||
|
||||
subplot(1,2,2);
|
||||
stem(n_values, Mndg_brute + Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
|
||||
hold on;
|
||||
stem(n_values, Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'none');
|
||||
title(['Brute force (N=', num2str(N), ')']);
|
||||
xlabel('Product index n');
|
||||
ylabel('Number of FWM products');
|
||||
legend('Total', 'Degenerate');
|
||||
grid on;
|
||||
end
|
||||
|
||||
function [Mndg, Mdg] = getProducts(N)
|
||||
s = abs(2 - N - 1);
|
||||
|
||||
for n = 2 - N:2*N - 1
|
||||
if n < -N
|
||||
Mdg(n + s) = 0;
|
||||
elseif (-N <= n) && (n <= 0)
|
||||
Mdg(n + s) = N - ceil((N - n)/2);
|
||||
elseif (1 <= n) && (n <= N)
|
||||
Mdg(n + s) = N - 1 - floor(n/2) - ceil((N - n)/2);
|
||||
elseif (N < n) && (n <= 2*N)
|
||||
Mdg(n + s) = N - floor(n/2);
|
||||
elseif n > 2*N
|
||||
Mdg(n + s) = 0;
|
||||
end
|
||||
|
||||
if n < -N
|
||||
Mndg(n + s) = 0;
|
||||
elseif (-N <= n) && (n < 1)
|
||||
Mndg(n + s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
|
||||
elseif (1 <= n) && (n <= N)
|
||||
Mndg(n + s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
|
||||
elseif (N < n) && (n <= 2*N)
|
||||
Mndg(n + s) = floor(N^2 + n^2/4 - N*n);
|
||||
elseif n > 2*N
|
||||
Mndg(n + s) = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
function frequency = wavelength2frequency(wavelength, inputUnit)
|
||||
% Convert wavelength to optical frequency.
|
||||
% Supported units: m, nm.
|
||||
|
||||
c = physconst('LightSpeed');
|
||||
|
||||
switch lower(inputUnit)
|
||||
case 'm'
|
||||
wavelength_m = wavelength;
|
||||
case 'nm'
|
||||
wavelength_m = wavelength .* 1e-9;
|
||||
otherwise
|
||||
error('Unsupported input unit "%s". Use "m" or "nm".', inputUnit);
|
||||
end
|
||||
|
||||
frequency = c ./ wavelength_m;
|
||||
|
||||
end
|
||||
@@ -1,120 +0,0 @@
|
||||
%% Matched Filter SNR Demonstration (Correct Timing)
|
||||
% clear; close all; clc;
|
||||
|
||||
%% Parameters
|
||||
M = 4; % QPSK
|
||||
numSymbols = 1e6;
|
||||
sps = 25; % samples per symbol
|
||||
rolloff = 0.5;
|
||||
EbNo_dB = 10;
|
||||
|
||||
%% Generate random data
|
||||
data = randi([0 M-1], numSymbols, 1);
|
||||
txSym = qammod(data, M, 'UnitAveragePower', true);
|
||||
|
||||
%% Root Raised Cosine filters
|
||||
span = 64; % filter span in symbols
|
||||
rrcTx = rcosdesign(rolloff, span, sps, 'sqrt');
|
||||
rrcRx = rrcTx; % matched filter
|
||||
|
||||
txSignal2 = ifft(fft(rrcTx).*fft(txSym));
|
||||
|
||||
%% Transmit filtering (includes upsampling)
|
||||
txSignal = upfirdn(txSym, rrcTx, sps, 1);
|
||||
|
||||
%% AWGN channel
|
||||
rxSignal = awgn(txSignal, EbNo_dB + 10*log10(sps), 'measured');
|
||||
|
||||
%% Receiver matched filter
|
||||
rxFilt = conv(rxSignal, rrcRx, 'same');
|
||||
|
||||
%% Symbol timing (group delay compensation)
|
||||
delay = span * sps / 2; % total delay per filter is span*sps/2
|
||||
rxAligned = rxFilt(delay+1 : end-delay);
|
||||
|
||||
%% Downsample to symbol rate
|
||||
rxSampled = rxAligned(1:sps:end);
|
||||
|
||||
%% Align lengths
|
||||
L = min(length(rxSampled), length(txSym));
|
||||
rxSampled = rxSampled(1:L);
|
||||
txSym = txSym(1:L);
|
||||
|
||||
%% Decision and BER
|
||||
rxSym = qamdemod(rxSampled, M, 'UnitAveragePower', true);
|
||||
[~, ber] = biterr(data(1:L), rxSym);
|
||||
|
||||
%% Compute effective SNR
|
||||
snr_meas = 10*log10(mean(abs(txSym).^2) / mean(abs(txSym - rxSampled).^2));
|
||||
|
||||
fprintf('Measured BER: %.3e | Effective SNR: %.2f dB\n', ber, snr_meas);
|
||||
|
||||
|
||||
%% Eye diagrams
|
||||
eyediagram(rxSignal(1:4000), 2*sps);
|
||||
title('Received Signal (Before Matched Filter)');
|
||||
eyediagram(rxFilt(1:4000), 2*sps);
|
||||
title('After Matched Filter (RRC)');
|
||||
|
||||
%% --------------------------------------------------------------
|
||||
%% Spectrum analysis of shaped and filtered signals
|
||||
%% --------------------------------------------------------------
|
||||
|
||||
Fs = sps; % normalized sample rate (symbol rate = 1)
|
||||
Nfft = 2^16; % FFT size for high resolution
|
||||
f = (-Nfft/2:Nfft/2-1)/Nfft * Fs; % normalized frequency axis (symbol-rate units)
|
||||
|
||||
% Spectra
|
||||
S_tx = 20*log10(abs(fftshift(fft(txSignal, Nfft)))/max(abs(fft(txSignal, Nfft))));
|
||||
S_rx = 20*log10(abs(fftshift(fft(rxFilt, Nfft)))/max(abs(fft(rxFilt, Nfft))));
|
||||
|
||||
% Unshaped (rectangular pulse) for comparison
|
||||
txRect_unf = upfirdn(txSym, ones(1, sps), sps, 1);
|
||||
S_rect = 20*log10(abs(fftshift(fft(txRect_unf, Nfft)))/max(abs(fft(txRect_unf, Nfft))));
|
||||
|
||||
% Plot
|
||||
figure('Name','Spectrum after Pulse Shaping');
|
||||
plot(f, S_rect, '--', 'DisplayName','Rectangular pulse');
|
||||
hold on;
|
||||
plot(f, S_tx, 'LineWidth',1.4, 'DisplayName','RRC (TX)');
|
||||
plot(f, S_rx, 'LineWidth',1.4, 'DisplayName','After Matched Filter');
|
||||
grid on;
|
||||
xlabel('Normalized frequency (× symbol rate)');
|
||||
ylabel('Magnitude [dB]');
|
||||
title('Spectra Before and After RRC Pulse Shaping');
|
||||
legend('Location','best');
|
||||
xlim([-1.5 1.5]);
|
||||
ylim([-60 0]);
|
||||
|
||||
|
||||
%% --------------------------------------------------------------
|
||||
%% Visualization: RRC and Raised-Cosine Frequency Responses
|
||||
%% --------------------------------------------------------------
|
||||
|
||||
% Frequency axis for plotting (normalized to symbol rate)
|
||||
Nfft = 4096;
|
||||
H_rrc = fftshift(fft(rrcTx, Nfft));
|
||||
H_rc = H_rrc .* H_rrc; % cascade of TX and RX RRC = full RC
|
||||
|
||||
f = linspace(-0.5, 0.5, Nfft); % normalized frequency (symbol-rate units)
|
||||
|
||||
figure('Name','Raised Cosine Filter Characteristics');
|
||||
|
||||
subplot(2,1,1);
|
||||
plot(f, 20*log10(abs(H_rrc)/max(abs(H_rrc))), 'LineWidth', 1.5);
|
||||
hold on;
|
||||
plot(f, 20*log10(abs(H_rc)/max(abs(H_rc))), '--', 'LineWidth', 1.5);
|
||||
grid on;
|
||||
xlabel('Normalized frequency (× symbol rate)');
|
||||
ylabel('Magnitude [dB]');
|
||||
title(sprintf('RRC (rolloff = %.2f) and Full RC Spectrum', rolloff));
|
||||
legend('Root Raised Cosine','Raised Cosine (TX×RX)','Location','best');
|
||||
ylim([-60 5]);
|
||||
|
||||
subplot(2,1,2);
|
||||
t = (-span*sps/2 : span*sps/2) / sps; % time axis in symbol durations
|
||||
plot(t, rrcTx, 'LineWidth', 1.5);
|
||||
grid on;
|
||||
xlabel('Time [symbols]');
|
||||
ylabel('Amplitude');
|
||||
title('RRC Impulse Response');
|
||||
@@ -1,62 +0,0 @@
|
||||
function tau_error = modifiedGodardTimingRecovery(rx, N, eta, beta)
|
||||
% modifiedGodardTimingRecovery
|
||||
%
|
||||
% This function estimates the symbol timing error using the modified Godard
|
||||
% approach in the frequency domain as described in:
|
||||
%
|
||||
% "Modified Godard Timing Recovery for Non-Integer Oversampling Receivers"
|
||||
% Appl. Sci. 2017, 7, 655. :contentReference[oaicite:0]{index=0}​:contentReference[oaicite:1]{index=1}
|
||||
%
|
||||
% Inputs:
|
||||
% rx - Received time-domain signal (vector)
|
||||
% N - FFT size (should be an even integer)
|
||||
% eta - Effective oversampling factor used for timing recovery (eta > 1)
|
||||
% beta - Roll-off related parameter (0 < beta <= 1)
|
||||
%
|
||||
% Output:
|
||||
% tau_error - Estimated timing error (in sample units)
|
||||
%
|
||||
% Implementation Notes:
|
||||
% 1. The function computes an N-point FFT of the first N samples of rx.
|
||||
% 2. It then determines an offset (Delta) defined as:
|
||||
% offset = round((1 - 1/eta) * N)
|
||||
% 3. To avoid index overflow, the summation is taken over indices k from 1 to
|
||||
% floor(N/2) - offset.
|
||||
% 4. The timing error is estimated as:
|
||||
% tau_error = ( (1+beta)/(2*eta*N - 1) * sum(phase difference) ) / (2*pi)
|
||||
% where the phase difference is (angle(R(k)) - angle(R(k+offset)))
|
||||
%
|
||||
% Make sure that the input signal rx contains at least N samples.
|
||||
|
||||
% Check input length
|
||||
if length(rx) < N
|
||||
error('Input signal length must be at least N.');
|
||||
end
|
||||
|
||||
% Compute the N-point FFT of the first N samples of rx
|
||||
R = fft(rx(1:N), N);
|
||||
|
||||
% Determine the offset based on the oversampling factor (eta)
|
||||
offset = round((1 - 1/eta) * N);
|
||||
|
||||
% Define the summation range to avoid index overflow
|
||||
k_min = 1;
|
||||
k_max = floor(N/2) - offset;
|
||||
if k_max < k_min
|
||||
error('Chosen parameters result in an empty summation range. Adjust N, eta, or beta.');
|
||||
end
|
||||
|
||||
% Compute the sum of phase differences over the selected frequency bins
|
||||
phase_diff_sum = 0;
|
||||
for k = k_min:k_max
|
||||
phase_k = angle(R(k));
|
||||
phase_k_offset = angle(R(k + offset));
|
||||
phase_diff_sum = phase_diff_sum + (phase_k - phase_k_offset);
|
||||
end
|
||||
|
||||
% Normalization factor as per the modified Godard algorithm
|
||||
norm_factor = (1 + beta) / (2 * eta * N - 1);
|
||||
|
||||
% Estimate the timing error in sample units
|
||||
tau_error = (norm_factor * phase_diff_sum) / (2 * pi);
|
||||
end
|
||||
@@ -1,25 +0,0 @@
|
||||
Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
Institute for Communications Engineering (LNT)
|
||||
Technical University of Munich, Germany
|
||||
www.lnt.ei.tum.de
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,24 +0,0 @@
|
||||
## MI-CG: Numerically Computing Achievable Rates of Memoryless Channels
|
||||
|
||||
This repository provides a MATLAB function mi_cg.m to numerically compute achievable rates for memoryless channels. The function uses a conditionally-Gaussian (CG) channel model to obtain a lower bound on the achievable rate of the true channel. The method is well-known, and it is explained in [this short document](https://mediatum.ub.tum.de/node?id=1533663). Two example scripts that compute several achievable rate curves are also provided.
|
||||
|
||||
### Citation
|
||||
|
||||
This software and the accompanying document are meant as a tutorial to get started with mutual information as a numerical figure of merit for a communications channel. The software is provided under the open-source [MIT license](https://opensource.org/licenses/MIT). If you use the software in your academic work, please cite the accompanying [document](https://mediatum.ub.tum.de/node?id=1533663) as follows:
|
||||
|
||||
> F. J. Garcia-Gomez, “Numerically computing achievable rates of memoryless channels,” TUM University Library, 2019. [Online]. Available: https://mediatum.ub.tum.de/node?id=1533663
|
||||
|
||||
The corresponding BibTeX entry is
|
||||
```
|
||||
@article{garcia2019numerically,
|
||||
author = "Francisco Javier Garcia-Gomez",
|
||||
title = "Numerically Computing Achievable Rates of Memoryless Channels",
|
||||
year = "2019",
|
||||
journal="TUM University Library",
|
||||
url={https://mediatum.ub.tum.de/node?id=1533663}
|
||||
}
|
||||
```
|
||||
|
||||
### Acknowledgment
|
||||
|
||||
This work was supported by the German Research Foundation (DFG) under Grant KR 3517/8-2.
|
||||
@@ -1,156 +0,0 @@
|
||||
function air = air(x,r,idx_tx,Px,M_training)
|
||||
|
||||
MAX_MEMORY = 200e6; % maximum allowed size for a matrix
|
||||
|
||||
if nargin == 3
|
||||
Px = [];
|
||||
M_training = [];
|
||||
end
|
||||
|
||||
if nargin == 4
|
||||
M_training = [];
|
||||
end
|
||||
|
||||
|
||||
% if input is complex, separate into real and imaginary parts
|
||||
if any(imag(x(:))~=0) || any(imag(r(:))~=0)
|
||||
x = [real(x); imag(x)];
|
||||
r = [real(r); imag(r)];
|
||||
end
|
||||
|
||||
D = size(x, 1); % D = 2 if complex x
|
||||
N = size(x, 2); % number of constellation points
|
||||
M = size(r, 2); % number of samples
|
||||
|
||||
% set default training set size
|
||||
if isempty(M_training)
|
||||
M_training = ceil(0.3*M);
|
||||
end
|
||||
|
||||
M_testing = M - M_training;
|
||||
|
||||
% Training: estimate parameters of the conditionally Gaussian model
|
||||
% sort according to transmit index
|
||||
[idx_tx_training, idx_sort] = sort(idx_tx(1:M_training));
|
||||
r_training = r(:, idx_sort);
|
||||
i_bounds = zeros(1, N+1);
|
||||
|
||||
% compute conditional means and covariance matrices
|
||||
C_n = zeros(D, D, N);
|
||||
det_n = zeros(1, N);
|
||||
|
||||
for n=1:N
|
||||
% find how many times x(:, n) was transmitted and update i_bounds
|
||||
N_current_x = find(idx_tx_training((i_bounds(n)+1):end)==n, 1, 'last');
|
||||
if isempty(N_current_x), N_current_x=0; end
|
||||
i_bounds(n+1) = i_bounds(n) + N_current_x;
|
||||
|
||||
if N_current_x > 0
|
||||
% Compute mu_n=E[Y|X=x_n] according to Eq. (14) and store it in
|
||||
% x(:, n) to save space
|
||||
x(:, n) = sum(r_training(:, (i_bounds(n)+1):i_bounds(n+1)), 2)/(i_bounds(n+1)-i_bounds(n));
|
||||
|
||||
% compute C_n=cov[Y|X=x_n] according to Eq. (15)
|
||||
r_meanfree = r_training(:, (i_bounds(n)+1):i_bounds(n+1)) - x(:, n);
|
||||
C_n(:, :, n) = (r_meanfree*r_meanfree')/(i_bounds(n+1)-i_bounds(n));
|
||||
% store also the determinant of C(:, :, n)
|
||||
det_n(n) = det(C_n(:, :, n));
|
||||
|
||||
% if the determinant is 0, or if the matrix is badly conditioned,
|
||||
% regularize by adding a small identity matrix. Note that we do
|
||||
% need the check for 0 determinant, in case a cloud has exactly 0
|
||||
% variance according to the training set
|
||||
if det_n(n)==0 || cond(C_n(:, :, n))>1e16
|
||||
C_n(:, :, n) = C_n(:, :, n) + 5 * eps * eye(D);
|
||||
det_n(n) = (5*eps)^D;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
% uniform input pmf Px if not provided
|
||||
if isempty(Px)
|
||||
Px = repmat(1/N, [1, N]);
|
||||
end
|
||||
|
||||
|
||||
% extract testing set and sort it according to transmit index
|
||||
[idx_tx_testing, idx_sort] = sort(idx_tx((M_training+1):M));
|
||||
r_testing = r(:, M_training+idx_sort);
|
||||
|
||||
% computation of h(Y|X)
|
||||
h_Y_X = 0;
|
||||
i_bounds_testing = zeros(1, N+1);
|
||||
% loop over constellation points to compute h(Y|X)
|
||||
for n = 1:N
|
||||
% find how many times x(:, n) was transmitted and update
|
||||
% i_bounds_testing
|
||||
N_current_x = find(idx_tx_testing((i_bounds_testing(n)+1):end)==n, 1, 'last');
|
||||
if isempty(N_current_x), N_current_x=0; end
|
||||
i_bounds_testing(n+1) = i_bounds_testing(n) + N_current_x;
|
||||
% add the corresponding contribution to the mutual information (two
|
||||
% first lines of Eq. (17)). This, together with
|
||||
% D/2*log2(2*pi) after the end of the loop, gives h(Y|X)
|
||||
h_Y_X = h_Y_X + N_current_x * log2(det_n(n))/2+...
|
||||
sum(sum(conj(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)).*(C_n(:, :, n)\(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)))))/2/log(2);
|
||||
|
||||
|
||||
end
|
||||
h_Y_X = D/2*log2(2*pi) + h_Y_X/M_testing;
|
||||
|
||||
% When computing log(py), we might run out of memory. If necessary, we
|
||||
% doe the computation in blocks
|
||||
logpy = zeros(1, M_testing);
|
||||
BLOCK_SIZE = floor(MAX_MEMORY/N);
|
||||
N_blocks = ceil(M_testing/BLOCK_SIZE);
|
||||
|
||||
% loop over blocks of symbols. This loop can be replaced by parfor to allow
|
||||
% parallel computation
|
||||
for i_block = 1:N_blocks
|
||||
|
||||
logpy_cur = zeros(1, M_testing);
|
||||
|
||||
% beginning of block
|
||||
i_start = (i_block-1) * BLOCK_SIZE + 1;
|
||||
% end of block
|
||||
i_end = min(M_testing, i_block*BLOCK_SIZE);
|
||||
% block size
|
||||
current_block_size = i_end-i_start+1;
|
||||
|
||||
% compute exponents of third line of (17)
|
||||
exponents = zeros(N, current_block_size);
|
||||
for n = 1:N
|
||||
exponents(n, :) = -log(det_n(n))/2-real(sum(conj(r_testing(:, i_start:i_end)-x(:, n)).*(C_n(:, :, n)\(r_testing(:, i_start:i_end)-x(:, n))), 1))/2;
|
||||
%sum über 2 einträge von r
|
||||
end
|
||||
|
||||
% compute third line of Eq. (17). Use a custom function
|
||||
% that computes log(sum(exp(x))) avoiding overflow errors
|
||||
logpy_cur(i_start:i_end) = math_logsumexp(log(Px(:))+exponents, 1);
|
||||
logpy = logpy + logpy_cur;
|
||||
end
|
||||
|
||||
% output entropy h(Y)
|
||||
h_Y = D/2*log2(2*pi) - mean(logpy)/log(2);%log basis change
|
||||
|
||||
% compute mutual information
|
||||
air = h_Y - h_Y_X;
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
function [y] = math_logsumexp(x, dim)
|
||||
%[y] = math_logsumexp(x, dim)
|
||||
% Computes log(sum(exp(x), dim)), avoiding overflow errors when one of the
|
||||
% x is large.
|
||||
|
||||
if nargin<2 || isempty(dim)
|
||||
m = max(x);
|
||||
y = m + log(sum(exp(x-m)));
|
||||
else
|
||||
m = max(x, [], dim);
|
||||
y = m + log(sum(exp(x-m), dim));
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
% Institute for Communications Engineering (LNT)
|
||||
% Technical University of Munich, Germany
|
||||
% www.lnt.ei.tum.de
|
||||
%
|
||||
% All rights reserved.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Permission is hereby granted, free of charge, to any person obtaining a
|
||||
% copy of this software and associated documentation files (the
|
||||
% "Software"), to deal in the Software without restriction, including
|
||||
% without limitation the rights to use, copy, modify, merge, publish,
|
||||
% distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
% persons to whom the Software is furnished to do so, subject to the
|
||||
% following conditions:
|
||||
%
|
||||
% The above copyright notice and this permission notice shall be included
|
||||
% in all copies or substantial portions of the Software.
|
||||
%
|
||||
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
% USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Example usage of the function mi_cg to numerically compute mutual
|
||||
% information between two complex sequences. This file simulates a
|
||||
% one-dimensional complex AWGN channel with 16-QAM constellation for
|
||||
% different SNRs, and then plots the achievable rate, which is equal to two
|
||||
% times the 4-PAM curve of Fig. 1 of [1].
|
||||
%
|
||||
% Note that using mi_cg with complex sequences assumes that the channel
|
||||
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
|
||||
% received clouds are circular). This is not the case in a channel with
|
||||
% phase noise: see example_it_mi_cg.m for an example of how to deal with
|
||||
% non-circularly-symmetric channels.
|
||||
%
|
||||
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
|
||||
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
|
||||
% 2384-2415, October 1998
|
||||
%
|
||||
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
|
||||
% Date: 12.12.2019
|
||||
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clear;
|
||||
% close all;
|
||||
|
||||
%%% Simulation parameters
|
||||
M_QAM=16; % QAM size
|
||||
var_w=1; % noise variance
|
||||
SNR_dB_values=(-5):2:25; % SNR values in dB
|
||||
N=8000; % number of Monte-Carlo points
|
||||
|
||||
%%% Derived parameters
|
||||
n_SNR=length(SNR_dB_values);
|
||||
SNR_values=10.^(SNR_dB_values/10);
|
||||
|
||||
%%% Generation of QAM constellation with power 1
|
||||
M_PAM=sqrt(M_QAM); % number of points per real dimension
|
||||
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
|
||||
X=X_1d+1i*X_1d.'; % transform to QAM
|
||||
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
|
||||
X=[real(X); imag(X)]; % separate real and imaginary parts
|
||||
|
||||
%%% Uniformly choose transmit indices
|
||||
idx_tx=randi(M_QAM, [1, N]);
|
||||
|
||||
%%% AWGN noise
|
||||
w=sqrt(var_w)*(randn([2, N]));%+1i*randn([1, N]));
|
||||
|
||||
%%% Loop over the SNR values
|
||||
|
||||
MI_awgn=zeros(1, n_SNR);
|
||||
fig = figure(1);
|
||||
for i_SNR=1:n_SNR
|
||||
|
||||
% transmitted points
|
||||
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
|
||||
|
||||
% AWGN channel
|
||||
r_awgn = s+w;
|
||||
|
||||
%%%%%%%%%%%%
|
||||
clf
|
||||
hold on
|
||||
xlim([-20, 20]);
|
||||
ylim([-20, 20]);
|
||||
%received signal
|
||||
scatter(r_awgn(1,:),r_awgn(2,:),1,"red",'.');
|
||||
%tx signal constellation
|
||||
scatter(s(1,:),s(2,:),4,"black",'o','filled');
|
||||
%uni power transmit constallation
|
||||
scatter(X(1,:),X(2,:),5,'blue','o','filled');
|
||||
drawnow
|
||||
pause(0.1)
|
||||
%%%%%%%%%%%%
|
||||
|
||||
% Compute MI
|
||||
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
|
||||
% The following also works but is slower
|
||||
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
|
||||
end
|
||||
|
||||
|
||||
I_shannon=log2(1+SNR_values);
|
||||
|
||||
figure(2);
|
||||
hold on
|
||||
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
|
||||
hold on;
|
||||
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
|
||||
hold off;
|
||||
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
|
||||
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
|
||||
legend('Location', 'NorthWest');
|
||||
@@ -1,140 +0,0 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
% Institute for Communications Engineering (LNT)
|
||||
% Technical University of Munich, Germany
|
||||
% www.lnt.ei.tum.de
|
||||
%
|
||||
% All rights reserved.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Permission is hereby granted, free of charge, to any person obtaining a
|
||||
% copy of this software and associated documentation files (the
|
||||
% "Software"), to deal in the Software without restriction, including
|
||||
% without limitation the rights to use, copy, modify, merge, publish,
|
||||
% distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
% persons to whom the Software is furnished to do so, subject to the
|
||||
% following conditions:
|
||||
%
|
||||
% The above copyright notice and this permission notice shall be included
|
||||
% in all copies or substantial portions of the Software.
|
||||
%
|
||||
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
% USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%%%%%%%%%%%%%%%% example_mi_cg_real_2D_awgn_vs_phasenoise %%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Example usage of the function mi_cg to numerically compute mutual
|
||||
% information between two sequences. This file simulates a two-dimensional
|
||||
% AWGN channel with 4-PAM constellation (or, equivalently, a complex AWGN
|
||||
% channel with 16-QAM constellation) for different SNRs, and then plots
|
||||
% the achievable rate, reproducing the 4-PAM curve of Fig. 1 of [1]. Note
|
||||
% that this curve can also be reproduced by simulating a 1-dimensional
|
||||
% channel with 4-PAM: this file is an example of how to deal with multiple
|
||||
% dimensions.
|
||||
%
|
||||
% This file also simulates a complex phase-noise channel:
|
||||
% r=s.*exp(1i*theta)+w
|
||||
% where w is complex AWGN and theta is i.i.d. real Gaussian. As q(Y|X) for
|
||||
% this channel is not circularly-symmetric, this complex channel needs to
|
||||
% be separated into two real dimensions to compute the mutual information.
|
||||
% The resulting achievable rate is, as expected, below the rate for the
|
||||
% AWGN channel.
|
||||
%
|
||||
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
|
||||
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
|
||||
% 2384-2415, October 1998
|
||||
%
|
||||
% [2]
|
||||
%
|
||||
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
|
||||
% Date: 12.12.2019
|
||||
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clear;
|
||||
close all;
|
||||
|
||||
%%% Simulation parameters
|
||||
D=1; % number of complex dimensions
|
||||
M_QAM=16; % QAM size
|
||||
var_w=1; % noise variance
|
||||
E_theta=0.2; % phase offset for the phase noise channel
|
||||
var_theta=0.05; % phase noise variance
|
||||
SNR_dB_values=(-5):2:25; % SNR values in dB
|
||||
N=8000; % number of Monte-Carlo points
|
||||
|
||||
%%% Derived parameters
|
||||
n_SNR=length(SNR_dB_values);
|
||||
SNR_values=10.^(SNR_dB_values/10);
|
||||
|
||||
%%% Generation QAM constellation with power 1
|
||||
M_PAM=sqrt(M_QAM); % number of points per real dimension
|
||||
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
|
||||
X=X_1d+1i*X_1d.'; % transform to QAM
|
||||
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
|
||||
X=[real(X); imag(X)]; % separate real and imaginary parts
|
||||
|
||||
%%% Uniformly choose transmit indices
|
||||
idx_tx=randi(M_QAM^D, [1, N]);
|
||||
|
||||
%%% AWGN noise (real and imaginary parts)
|
||||
w=sqrt(var_w/2)*randn([2*D, N]);
|
||||
%%% phase noise
|
||||
theta=E_theta+sqrt(var_theta)*randn([D, N]);
|
||||
|
||||
%%% Loop over the SNR values
|
||||
MI_awgn=zeros(1, n_SNR);
|
||||
MI_phasenoise=zeros(1, n_SNR);
|
||||
fig = figure(1);
|
||||
for i_SNR=1:n_SNR
|
||||
% transmitted points
|
||||
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
|
||||
|
||||
% AWGN channel
|
||||
r_awgn=s+w;
|
||||
|
||||
% Compute MI
|
||||
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx)/D;
|
||||
% The following also works but is slower
|
||||
% MI_awgn(i_SNR)=air(s, r_awgn)/D;
|
||||
|
||||
% Phase-noise channel
|
||||
s_complex=s(1:2:end, :)+1i*s(2:2:end, :); % transform to complex
|
||||
r_phasenoise_complex=s_complex.*exp(1i*theta); % phase noise and AWGN
|
||||
r_phasenoise=zeros(2*D, N); % transform to real
|
||||
r_phasenoise(1:2:end, :)=real(r_phasenoise_complex);
|
||||
r_phasenoise(2:2:end, :)=imag(r_phasenoise_complex);
|
||||
r_phasenoise=r_phasenoise+w; % add AWGN
|
||||
|
||||
clf
|
||||
fig = scatter(r_phasenoise(1,:),r_phasenoise(2,:),1,'.');
|
||||
xlim([-20, 20]);
|
||||
ylim([-20, 20]);
|
||||
drawnow
|
||||
pause(0.1)
|
||||
|
||||
% Compute MI
|
||||
MI_phasenoise(i_SNR)=air(X, r_phasenoise, idx_tx)/D;
|
||||
% The following also works but is slower
|
||||
% MI_phasenoise(i_SNR)=air(s, r_phasenoise)/D;
|
||||
end
|
||||
|
||||
% Shannon capacity of the AWGN channel
|
||||
I_shannon=log2(1+SNR_values);
|
||||
|
||||
figure;
|
||||
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
|
||||
hold on;
|
||||
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', '16-QAM, AWGN');
|
||||
plot(SNR_dB_values, MI_phasenoise, '-.', 'DisplayName', ['16-QAM, Phase noise, \sigma_\Theta^2=' num2str(var_theta)]);
|
||||
hold off;
|
||||
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
|
||||
title(['Achievable rate of 16-QAM in AWGN and in a phase noise channel with \theta~N(' num2str(E_theta) ', ' num2str(var_theta) ')']);
|
||||
legend('Location', 'NorthWest');
|
||||
@@ -1,164 +0,0 @@
|
||||
colored_noise = true;
|
||||
I_shannon=[];
|
||||
for cmplx = [0,1]
|
||||
cnt = 1;
|
||||
for M_PAM = [4,8,16]
|
||||
|
||||
|
||||
complex_constellation = cmplx;
|
||||
|
||||
%%% Simulation parameters
|
||||
% M_PAM=2; % QAM size
|
||||
var_w=1; % noise variance
|
||||
SNR_dB_values=(-5):1:35; % SNR values in dB
|
||||
N=8000; % number of Monte-Carlo points
|
||||
|
||||
%%% Derived parameters
|
||||
n_SNR=length(SNR_dB_values);
|
||||
SNR_values=10.^(SNR_dB_values/10);
|
||||
|
||||
%%% Generation of QAM constellation with power 1
|
||||
M=sqrt(M_PAM); % number of points per real dimension
|
||||
|
||||
if complex_constellation
|
||||
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
|
||||
else
|
||||
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
|
||||
end
|
||||
|
||||
X_ = X_ ./ rms(unique(X_));
|
||||
X_=[real(X_); imag(X_)];
|
||||
|
||||
%%%%%%%%%%%%
|
||||
figure(10);
|
||||
clf
|
||||
hold on
|
||||
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
|
||||
%%%%%%%%%%%%
|
||||
|
||||
%%% Uniformly choose transmit indices
|
||||
idx_tx=randi(M_PAM, [1, N]);
|
||||
|
||||
%%% AWGN noise
|
||||
w=sqrt(var_w)*(randn([2, N]));
|
||||
|
||||
%%% Loop over the SNR values
|
||||
|
||||
MI_awgn=zeros(1, n_SNR);
|
||||
fig = figure(2);
|
||||
|
||||
if colored_noise
|
||||
for i_SNR = 1:n_SNR
|
||||
% Transmitted signal for the given indices
|
||||
signal = X_(:, idx_tx);
|
||||
|
||||
% Generate white Gaussian noise of the same size as the signal
|
||||
noise_white = randn(size(signal));
|
||||
|
||||
% Define the filter coefficient for colored noise (adjust as needed)
|
||||
a = 0; % A higher value gives more correlation
|
||||
|
||||
% Filter the white noise to create colored noise.
|
||||
% Here we filter each row (dimension) independently.
|
||||
noise_colored = zeros(size(signal));
|
||||
noise_colored(1,:) = filter(1, [1, -a], noise_white(1,:));
|
||||
noise_colored(2,:) = filter(1, [1, -a], noise_white(2,:));
|
||||
|
||||
% Compute signal and unscaled noise power for proper scaling.
|
||||
signal_power = mean(abs(signal(:)).^2);
|
||||
noise_power = mean(abs(noise_colored(:)).^2);
|
||||
|
||||
% Convert desired SNR from dB to linear scale.
|
||||
SNR_linear = 10^(SNR_dB_values(i_SNR)/10);
|
||||
|
||||
% Scale the colored noise so that signal_power / noise_power equals SNR_linear.
|
||||
scaling_factor = sqrt(signal_power / (SNR_linear * noise_power));
|
||||
noise_colored_scaled = scaling_factor * noise_colored;
|
||||
|
||||
% Received signal is the sum of the signal and the scaled colored noise.
|
||||
r_colored = signal + noise_colored_scaled;
|
||||
|
||||
% For SNR measurement, compute the noise actually added.
|
||||
measured_noise = r_colored - signal;
|
||||
snr_meas_(i_SNR) = snr(signal(1,:) + 1i*signal(2,:), ...
|
||||
measured_noise(1,:) + 1i*measured_noise(2,:));
|
||||
|
||||
% Plotting the transmitted and received signal
|
||||
clf;
|
||||
hold on;
|
||||
xlim([-4, 4]);
|
||||
ylim([-4, 4]);
|
||||
scatter(signal(1,:), signal(2,:), 3, "black", 'o', 'DisplayName','Tx Constellation');
|
||||
scatter(r_colored(1,:), r_colored(2,:), 1, "red", 'x', 'DisplayName', 'Colored Noise Mapping');
|
||||
drawnow;
|
||||
|
||||
% Compute Mutual Information (or any other metric) with the new channel
|
||||
MI_awgn_(i_SNR) = air(X_, r_colored, idx_tx);
|
||||
end
|
||||
else
|
||||
|
||||
|
||||
for i_SNR=1:n_SNR
|
||||
|
||||
|
||||
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
|
||||
% r_awgn_ = s_ + w;
|
||||
|
||||
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
|
||||
|
||||
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
|
||||
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
|
||||
|
||||
%%%%%%%%%%%%
|
||||
clf
|
||||
hold on
|
||||
xlim([-4, 4]);
|
||||
ylim([-4, 4]);
|
||||
%received signal
|
||||
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
|
||||
|
||||
|
||||
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
|
||||
|
||||
drawnow
|
||||
%%%%%%%%%%%%
|
||||
|
||||
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
|
||||
% The following also works but is slower
|
||||
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
|
||||
end
|
||||
end
|
||||
|
||||
figure(3);
|
||||
hold on
|
||||
|
||||
if isempty(I_shannon)
|
||||
I_shannon=log2(1+db2pow(snr_meas_));
|
||||
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
|
||||
end
|
||||
|
||||
|
||||
cols = [ 0.9047 0.1918 0.1988
|
||||
0.2941 0.5447 0.7494
|
||||
0.3718 0.7176 0.3612
|
||||
1.0000 0.5482 0.1000
|
||||
0.8650 0.8110 0.4330
|
||||
0.6859 0.4035 0.2412];
|
||||
if complex_constellation
|
||||
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
|
||||
else
|
||||
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
|
||||
end
|
||||
|
||||
hold off;
|
||||
ylim([0,8]);
|
||||
xlim([min(SNR_dB_values) max(SNR_dB_values)])
|
||||
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
|
||||
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
|
||||
legend('Location', 'NorthWest');
|
||||
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
|
||||
|
||||
cnt = cnt+1;
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,104 +0,0 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
% Institute for Communications Engineering (LNT)
|
||||
% Technical University of Munich, Germany
|
||||
% www.lnt.ei.tum.de
|
||||
%
|
||||
% All rights reserved.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Permission is hereby granted, free of charge, to any person obtaining a
|
||||
% copy of this software and associated documentation files (the
|
||||
% "Software"), to deal in the Software without restriction, including
|
||||
% without limitation the rights to use, copy, modify, merge, publish,
|
||||
% distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
% persons to whom the Software is furnished to do so, subject to the
|
||||
% following conditions:
|
||||
%
|
||||
% The above copyright notice and this permission notice shall be included
|
||||
% in all copies or substantial portions of the Software.
|
||||
%
|
||||
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
% USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Example usage of the function mi_cg to numerically compute mutual
|
||||
% information between two complex sequences. This file simulates a
|
||||
% one-dimensional complex AWGN channel with 16-QAM constellation for
|
||||
% different SNRs, and then plots the achievable rate, which is equal to two
|
||||
% times the 4-PAM curve of Fig. 1 of [1].
|
||||
%
|
||||
% Note that using mi_cg with complex sequences assumes that the channel
|
||||
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
|
||||
% received clouds are circular). This is not the case in a channel with
|
||||
% phase noise: see example_it_mi_cg.m for an example of how to deal with
|
||||
% non-circularly-symmetric channels.
|
||||
%
|
||||
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
|
||||
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
|
||||
% 2384-2415, October 1998
|
||||
%
|
||||
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
|
||||
% Date: 12.12.2019
|
||||
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clear;
|
||||
close all;
|
||||
|
||||
%%% Simulation parameters
|
||||
M_QAM=16; % QAM size
|
||||
var_w=1; % noise variance
|
||||
SNR_dB_values=(-5):2:25; % SNR values in dB
|
||||
N=8000; % number of Monte-Carlo points
|
||||
|
||||
%%% Derived parameters
|
||||
n_SNR=length(SNR_dB_values);
|
||||
SNR_values=10.^(SNR_dB_values/10);
|
||||
|
||||
%%% Generation of QAM constellation with power 1
|
||||
M_PAM=sqrt(M_QAM); % number of points per real dimension
|
||||
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
|
||||
X=X_1d+1i*X_1d.'; % transform to QAM
|
||||
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
|
||||
|
||||
%%% Uniformly choose transmit indices
|
||||
idx_tx=randi(M_QAM, [1, N]);
|
||||
|
||||
%%% AWGN noise
|
||||
w=sqrt(var_w/2)*(randn([1, N])+1i*randn([1, N]));
|
||||
|
||||
%%% Loop over the SNR values
|
||||
MI_awgn=zeros(1, n_SNR);
|
||||
for i_SNR=1:n_SNR
|
||||
% transmitted points
|
||||
|
||||
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
|
||||
|
||||
% AWGN channel
|
||||
r_awgn = s+w;
|
||||
|
||||
% Compute MI
|
||||
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
|
||||
% The following also works but is slower: MI_awgn(i_SNR)=air(s, r_awgn);
|
||||
end
|
||||
|
||||
|
||||
I_shannon=log2(1+SNR_values);
|
||||
|
||||
figure;
|
||||
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
|
||||
hold on;
|
||||
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
|
||||
hold off;
|
||||
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
|
||||
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
|
||||
legend('Location', 'NorthWest');
|
||||
@@ -1,135 +0,0 @@
|
||||
|
||||
clear;
|
||||
I_shannon=[];
|
||||
for cmplx = [1,0]
|
||||
cnt = 1;
|
||||
for M_PAM = [2,4,8,16]
|
||||
|
||||
% close all;
|
||||
usegarcia = 0;
|
||||
|
||||
complex_constellation = cmplx;
|
||||
|
||||
%%% Simulation parameters
|
||||
% M_PAM=2; % QAM size
|
||||
var_w=1; % noise variance
|
||||
SNR_dB_values=(-5):1:35; % SNR values in dB
|
||||
N=8000; % number of Monte-Carlo points
|
||||
|
||||
%%% Derived parameters
|
||||
n_SNR=length(SNR_dB_values);
|
||||
SNR_values=10.^(SNR_dB_values/10);
|
||||
|
||||
%%% Generation of QAM constellation with power 1
|
||||
M=sqrt(M_PAM); % number of points per real dimension
|
||||
|
||||
if complex_constellation
|
||||
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
|
||||
else
|
||||
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
|
||||
end
|
||||
|
||||
X_ = X_ ./ rms(unique(X_));
|
||||
X_=[real(X_); imag(X_)];
|
||||
|
||||
%%%%%%%%%%%%
|
||||
figure(10);
|
||||
clf
|
||||
hold on
|
||||
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
|
||||
%%%%%%%%%%%%
|
||||
|
||||
%%% Uniformly choose transmit indices
|
||||
idx_tx=randi(M_PAM, [1, N]);
|
||||
|
||||
%%% AWGN noise
|
||||
w=sqrt(var_w)*(randn([2, N]));
|
||||
|
||||
%%% Loop over the SNR values
|
||||
|
||||
MI_awgn=zeros(1, n_SNR);
|
||||
fig = figure(2);
|
||||
for i_SNR=1:n_SNR
|
||||
|
||||
if usegarcia
|
||||
|
||||
|
||||
%scale transmitted points acc. to SNR condition (this is not correct I think, the papaer also show diff results)
|
||||
% s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
|
||||
|
||||
%scale nosie acc. to snr condition
|
||||
noise_power = mean(abs(X_(1, idx_tx)+1i*X_(2, idx_tx)).^2) / SNR_values(i_SNR); % Noise power
|
||||
w_ = sqrt(noise_power) .* w / sqrt(2);
|
||||
|
||||
% AWGN channel
|
||||
r_awgn = X(:, idx_tx)+w_;
|
||||
% snr_meas(i_SNR) = snr(s(1,:)+1i*s(2,:),w(1,:)+1i*w(2,:));
|
||||
snr_meas(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx),w_(1,:)+1i*w_(2,:));
|
||||
end
|
||||
|
||||
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
|
||||
% r_awgn_ = s_ + w;
|
||||
|
||||
if cmplx
|
||||
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
|
||||
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
|
||||
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
|
||||
else
|
||||
r_awgn_ = awgn(X_(1, idx_tx),SNR_dB_values(i_SNR),"measured",10);
|
||||
w_awgn_matlab = r_awgn_ - X_(1,idx_tx);
|
||||
snr_meas_(i_SNR) = snr(X_(1, idx_tx) , w_awgn_matlab(1,:));
|
||||
end
|
||||
|
||||
%%%%%%%%%%%%
|
||||
clf
|
||||
hold on
|
||||
xlim([-4, 4]);
|
||||
ylim([-4, 4]);
|
||||
%received signal
|
||||
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
|
||||
|
||||
|
||||
if cmplx
|
||||
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
|
||||
else
|
||||
scatter(r_awgn_,zeros(size(r_awgn_)),1,"red",'x','DisplayName','Matlab Mapping');
|
||||
end
|
||||
drawnow
|
||||
|
||||
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
|
||||
% The following also works but is slower
|
||||
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
|
||||
end
|
||||
|
||||
figure(4);
|
||||
hold on
|
||||
|
||||
if isempty(I_shannon)
|
||||
I_shannon=log2(1+db2pow(snr_meas_));
|
||||
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
|
||||
end
|
||||
|
||||
if usegarcia
|
||||
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', ['GARCIA ',num2str(M_PAM) '-QAM, AWGN']);
|
||||
end
|
||||
|
||||
cols = linspecer(6);
|
||||
if complex_constellation
|
||||
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
|
||||
else
|
||||
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
|
||||
end
|
||||
|
||||
hold off;
|
||||
ylim([0,8]);
|
||||
xlim([min(SNR_dB_values) max(SNR_dB_values)])
|
||||
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
|
||||
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
|
||||
legend('Location', 'NorthWest');
|
||||
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
|
||||
|
||||
autoArrangeFigures;
|
||||
cnt = cnt+1;
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user