Theory stuff from sials work pc; minor stuff here and there

This commit is contained in:
Silas Oettinghaus
2026-02-19 15:11:32 +01:00
parent 1b8d83dec0
commit 2a724b833f
14 changed files with 810 additions and 39 deletions

View File

@@ -0,0 +1,124 @@
%% ============================================================
% SNR vs Optical Input Power (dBm) Shot vs Thermal vs Combined
% - Generate optical field as sine with target RMS power (verified)
% - Magnitude-square detection -> optical power
% - Photocurrent = Rd * P
% - Add shot noise + thermal noise (white, PSD-based)
% - Compute SNR for: shot-only, thermal-only, combined
% ============================================================
% Constants
k = Constant.Boltzmann;
q = Constant.ElementaryCharge;
% Receiver / PD parameters
T = 20 + 273.15; % K
R = 50; % Ohm (front-end/load)
Rd = 0.7; % A/W (responsivity)
Be = 100e9; % Hz (electrical noise bandwidth)
Id = 0; % A (dark current, optional)
% Sampling for time-domain demo (needs to be >> Be)
fs = 1e12; % Hz
N = 2^14; % samples
t = (0:N-1).'/fs;
% Choose an electrical tone within bandwidth (arbitrary for demo)
f0 = 10e9; % Hz
% Thermal current PSD (two-sided) and variance in Be
Si_th = 4*k*T/R; % A^2/Hz (two-sided)
sigma2_th = Si_th * Be; % A^2
sigma_th = sqrt(sigma2_th); % A_rms
% Optical input power sweep (in dBm)
P_dBm = linspace(-40, 10, 300);
P_W = 10.^((P_dBm - 30)/10); % W
% Pre-allocate results
SNR_shot_dB = zeros(size(P_dBm));
SNR_th_dB = zeros(size(P_dBm));
SNR_tot_dB = zeros(size(P_dBm));
% --- Main loop over optical input power
for ii = 1:numel(P_W)
Pavg = P_W(ii);
% Optical field with RMS power = Pavg:
% Let x(t) be the optical field amplitude such that |x|^2 has mean Pavg.
% Use a sinusoid: x(t) = A*sin(2*pi*f0*t), then mean(|x|^2)=A^2/2.
A = sqrt(2*Pavg); % -> mean(|x|^2) = Pavg
x = A * sin(2*pi*f0*t); % "optical field" (real for simplicity)
% Verify RMS/mean power numerically (optional)
P_meas = mean(abs(x).^2); % should be ~ Pavg
a = P_meas - Pavg;
assert(a<1);
% Magnitude-square detection -> optical power waveform
Popt = abs(x).^2; % W (instantaneous)
% Photocurrent waveform (includes DC + 2f0 component for this demo)
I_sig = Rd * Popt; % A
% Define "signal power" as the mean-squared photocurrent due to signal
% (for this sine-squared waveform, it's OK for a demo SNR definition)
P_sig = mean(I_sig.^2);
% -------- Shot noise (white) --------
% Two-sided PSD: Si_shot = 2*q*(I_photo + I_dark)
% For this demo, use average current to set the white-noise level:
Ibar = mean(I_sig) + Id;
Si_shot = 2*q*Ibar; % A^2/Hz
sigma2_sh = Si_shot * Be; % A^2
sigma_sh = sqrt(sigma2_sh); % A_rms
n_sh = sigma_sh * randn(N,1); % time-domain shot noise
% -------- Thermal noise (white Gaussian) --------
n_th = sigma_th * randn(N,1); % time-domain thermal noise
% Noise powers (mean-square) in time domain
Pn_sh = mean(n_sh.^2);
Pn_th = mean(n_th.^2);
Pn_tot = mean((n_sh + n_th).^2); % ~ Pn_sh + Pn_th (independent)
% SNRs
SNR_shot = P_sig / Pn_sh;
SNR_th = P_sig / Pn_th;
SNR_tot = P_sig / Pn_tot;
SNR_shot_dB(ii) = 10*log10(SNR_shot);
SNR_th_dB(ii) = 10*log10(SNR_th);
SNR_tot_dB(ii) = 10*log10(SNR_tot);
% Optional sanity check (can comment out)
% if ii == 1
% fprintf('Check Pavg target/meas: %.3g W / %.3g W\n', Pavg, P_meas);
% end
end
% Plot comparison
figure(1); clf; hold on;
plot(P_dBm, SNR_shot_dB, 'LineWidth', 1.5);
plot(P_dBm, SNR_th_dB, 'LineWidth', 1.5);
plot(P_dBm, SNR_tot_dB, 'LineWidth', 1.5);
grid on;
xlabel('Optical input power [dBm]');
ylabel('SNR [dB]');
title('SNR vs Optical Input Power: Shot vs Thermal vs Combined');
legend('Shot-noise only','Thermal-noise only','Shot + Thermal','Location','best');
% Print example at 0 dBm
[~,idx0] = min(abs(P_dBm - 0));
fprintf('At 0 dBm:\n');
fprintf(' SNR (shot only) = %.2f dB\n', SNR_shot_dB(idx0));
fprintf(' SNR (thermal only) = %.2f dB\n', SNR_th_dB(idx0));
fprintf(' SNR (combined) = %.2f dB\n', SNR_tot_dB(idx0));
% Also print NEP based on thermal PSD (constant NEP_th)
NEP_th = sqrt(Si_th)/Rd; % W/sqrt(Hz)
fprintf('Thermal NEP = %.3g W/sqrt(Hz)\n', NEP_th);