halfway merged and pulled?!
This commit is contained in:
27
Functions/Theory/CCDM/ccdm_gpt_example.m
Normal file
27
Functions/Theory/CCDM/ccdm_gpt_example.m
Normal file
@@ -0,0 +1,27 @@
|
||||
%% 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
|
||||
64
Functions/Theory/analyze_moving_average_filter.m
Normal file
64
Functions/Theory/analyze_moving_average_filter.m
Normal file
@@ -0,0 +1,64 @@
|
||||
% 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;
|
||||
89
Functions/Theory/dispersion_10km.m
Normal file
89
Functions/Theory/dispersion_10km.m
Normal file
@@ -0,0 +1,89 @@
|
||||
%% ============================================================
|
||||
% 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
|
||||
55
Functions/Theory/dispersion_contour.m
Normal file
55
Functions/Theory/dispersion_contour.m
Normal file
@@ -0,0 +1,55 @@
|
||||
% Gitter für lambda0 und S0
|
||||
lambda0_vec = linspace(1260,1360,200);
|
||||
S0_vec = linspace(0.06,0.1,200);
|
||||
[Lambda0, S0] = meshgrid(lambda0_vec, S0_vec);
|
||||
|
||||
% Festen Betriebsparameter
|
||||
lambda = 1293; % nm
|
||||
L = 1; % km
|
||||
|
||||
% Dispersion berechnen (lineare Näherung)
|
||||
D = S0 .* ( lambda - Lambda0 ) * L;
|
||||
% D = (S0./4) .* ( lambda - (Lambda0.^4)./(lambda^3) ) * L;
|
||||
|
||||
%% 2D-Konturplot nur mit Linien und Text
|
||||
figure('Color','w');
|
||||
hold on
|
||||
|
||||
% Konturlinien
|
||||
numLevels = 10;
|
||||
levels = linspace(min(D(:)), max(D(:)), numLevels);
|
||||
[C,h] = contour(S0, Lambda0, D, levels, ...
|
||||
'LineWidth',1.5, ...
|
||||
'ShowText','on', ...
|
||||
'LabelFormat','%0.1f');
|
||||
|
||||
% cbrewer2-Colormap für die Linien
|
||||
cmap = cbrewer2('div','RdYlGn', numLevels);
|
||||
colormap(cmap);
|
||||
|
||||
% Achsenlinien
|
||||
% yline(1310, '--k','ZDW_{mean}','LabelVerticalAlignment','top','LabelHorizontalAlignment','center');
|
||||
x0 = 0.09;
|
||||
% xline(x0, '--k','S_{0}','LabelHorizontalAlignment','left');
|
||||
|
||||
% Gaussian auf der x-Linie (S0 = 0.09)
|
||||
mu_zwd = 1310; % nm
|
||||
sigma_zwd = 2; % nm
|
||||
zwd_vals = linspace(min(lambda0_vec), max(lambda0_vec), 500);
|
||||
% PDF berechnen
|
||||
gauss_pdf = (1/(sigma_zwd*sqrt(2*pi))) * exp(-0.5*((zwd_vals-mu_zwd)/sigma_zwd).^2);
|
||||
% Normieren und auf eine sichtbare Breite skalieren
|
||||
scale = 0.005; % passt die Maximal-Auslenkung in x-Richtung an
|
||||
x_gauss = x0 + (gauss_pdf/max(gauss_pdf)) * scale;
|
||||
|
||||
% Plot
|
||||
% plot(x_gauss, zwd_vals, 'LineWidth',2);
|
||||
|
||||
% Achsenbeschriftung & Titel
|
||||
% Achsenbeschriftung & Titel
|
||||
xlabel('S0 [ps / nm2 km]', 'FontSize', 12);
|
||||
ylabel('ZDW [nm]', 'FontSize', 12);
|
||||
title (sprintf('Dispersion: %d km; %d nm', L, lambda), 'FontSize', 14);
|
||||
|
||||
grid on
|
||||
hold off
|
||||
146
Functions/Theory/dispersion_contour_bandwidth_lambda.m
Normal file
146
Functions/Theory/dispersion_contour_bandwidth_lambda.m
Normal file
@@ -0,0 +1,146 @@
|
||||
%% ------------------------------------------------------------
|
||||
% Contour plot: λ_null as function of bandwidth (f_target) and reach (L)
|
||||
% ------------------------------------------------------------
|
||||
|
||||
% Parameters
|
||||
lambda0 = 1310e-9; % [m]
|
||||
S0 = 0.08; % [ps/(nm²·km)]
|
||||
c = physconst('lightspeed');
|
||||
|
||||
% Sweep dimensions
|
||||
f_targets = linspace(50e9, 120e9, 100); % [Hz] (x-axis)
|
||||
L_values = linspace(0.5e3, 10e3, 100); % [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);
|
||||
lambda_vec = 2*abs(lambda0 - lambda_vec);
|
||||
|
||||
if 0
|
||||
fprintf('\n- %d km ------------------------------------\n',L);
|
||||
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');
|
||||
end
|
||||
|
||||
lambda_surface(iL, :) = lambda_vec; % λ for each f_target
|
||||
Dacc_surface(iL, :) = Dacc_vec; % corresponding accumulated dispersion
|
||||
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');
|
||||
|
||||
% Define wavelength contour levels [nm]
|
||||
lambda_levels = [1260:10:1290, 1290:5:1300, 1300:2.5:1310];
|
||||
lambda_levels = [100:-20:50, 50:-10:30,30:-5:0];
|
||||
|
||||
% Contour plot
|
||||
contour(f_GHz, L_km, lambda_surface_nm, lambda_levels, ...
|
||||
'LineWidth', 1.5, ...
|
||||
'ShowText', 'on', ...
|
||||
'LabelFormat', '%.0f nm');
|
||||
|
||||
% Colormap and colorbar
|
||||
colormap((cbrewer2('RdYlGn',100)));
|
||||
colorbar;
|
||||
clim([0 100]);
|
||||
|
||||
% Axis formatting
|
||||
xlabel('Signal Bandwidth [GHz]');
|
||||
ylabel('Fiber length [km]');
|
||||
legend('$\Delta \lambda$')
|
||||
|
||||
% X-axis ticks at 56 : 16 : 150 GHz
|
||||
xticks(56:8:150);
|
||||
|
||||
grid on; box on;
|
||||
|
||||
|
||||
%% Optional: overlay accumulated-dispersion contours
|
||||
if 0
|
||||
hold on;
|
||||
[CS, h] = contour(f_GHz, L_km, Dacc_surface, 10, 'k--', 'LineWidth', 0.8);
|
||||
clabel(CS, h, 'Color','k', 'FontSize',8);
|
||||
end
|
||||
|
||||
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
|
||||
38
Functions/Theory/dispersion_first_notch_10km.m
Normal file
38
Functions/Theory/dispersion_first_notch_10km.m
Normal file
@@ -0,0 +1,38 @@
|
||||
%% ------------------------------------------------------------
|
||||
% 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');
|
||||
165
Functions/Theory/dispersion_power_fading.m
Normal file
165
Functions/Theory/dispersion_power_fading.m
Normal file
@@ -0,0 +1,165 @@
|
||||
%% 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
|
||||
32
Functions/Theory/dispersion_wavelength_notch.m
Normal file
32
Functions/Theory/dispersion_wavelength_notch.m
Normal file
@@ -0,0 +1,32 @@
|
||||
%% 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
|
||||
f_null_2 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L) );
|
||||
L = 2e3; % m
|
||||
f_null_10 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L) );
|
||||
|
||||
cols = cbrewer2('Paired',10);
|
||||
figure('Color','w');hold on
|
||||
cnt = 2;
|
||||
for L = 10%[2,5,10]
|
||||
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+2;
|
||||
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,35];
|
||||
xlim([lim(2) lim(1)]);
|
||||
ylim([40,130])
|
||||
111
Functions/Theory/dispersion_wdm.m
Normal file
111
Functions/Theory/dispersion_wdm.m
Normal file
@@ -0,0 +1,111 @@
|
||||
%% ============================================================
|
||||
% 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
|
||||
120
Functions/Theory/matched_filter_rrc.m
Normal file
120
Functions/Theory/matched_filter_rrc.m
Normal file
@@ -0,0 +1,120 @@
|
||||
%% 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');
|
||||
40
Functions/Theory/power_fading.m
Normal file
40
Functions/Theory/power_fading.m
Normal file
@@ -0,0 +1,40 @@
|
||||
%% ============================================================
|
||||
% Minimal IM/DD Power Fading Plot
|
||||
% ============================================================
|
||||
|
||||
|
||||
%% Fiber and system parameters
|
||||
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||
lambda = 1275e-9; % operating wavelength [m]
|
||||
S0 = 0.08; % 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
|
||||
|
||||
%% Frequency grid
|
||||
f_max = 150e9;
|
||||
f = linspace(0, f_max, 4000); % [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.8);
|
||||
grid on; box on;
|
||||
xlabel('Frequency [GHz]');
|
||||
ylabel('Magnitude [dB]');
|
||||
title(sprintf('IM/DD Power Fading |H| for λ = %.1f nm, L = %.1f km', lambda*1e9, L/1000));
|
||||
ylim([-30 0]);
|
||||
|
||||
%% Mark analytic first-null frequency
|
||||
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L));
|
||||
xline(f_null/1e9, 'r--', 'LineWidth', 1.2, ...
|
||||
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
|
||||
11
Functions/Theory/propagation_time.m
Normal file
11
Functions/Theory/propagation_time.m
Normal file
@@ -0,0 +1,11 @@
|
||||
function prop_time = propagation_time(fiber_len_m)
|
||||
|
||||
c = physconst('lightspeed'); % Speed of light in vacuum (m/s)
|
||||
n = 1.46; % Refractive index of the fiber
|
||||
|
||||
% Calculate the propagation speed in the fiber
|
||||
propagation_speed = c / n;
|
||||
|
||||
% Calculate the propagation time
|
||||
prop_time = fiber_len_m ./ propagation_speed;
|
||||
end
|
||||
Reference in New Issue
Block a user