WIP - implementation and debugging of 224 Gbd PAM4 system
This commit is contained in:
@@ -1,155 +1,162 @@
|
||||
classdef Amplifier
|
||||
%UNTITLED Summary of this class goes here
|
||||
% Detailed explanation goes here
|
||||
|
||||
properties
|
||||
type
|
||||
amp_mode
|
||||
amplification_db
|
||||
|
||||
properties
|
||||
amp_mode
|
||||
gain_mode
|
||||
nase_mode
|
||||
|
||||
amplification_db
|
||||
noifig
|
||||
|
||||
saturation_mode
|
||||
saturation_power
|
||||
|
||||
fsimu
|
||||
|
||||
end
|
||||
|
||||
|
||||
methods
|
||||
function obj = Amplifier(options)
|
||||
%UNTITLED Construct an instance of this class
|
||||
% Detailed explanation goes here
|
||||
arguments
|
||||
options.type
|
||||
options.amp_mode
|
||||
options.amplification_db
|
||||
options.amp_mode amp_mode = amp_mode.ideal_no_noise
|
||||
options.gain_mode gain_mode = gain_mode.output_power
|
||||
options.nase_mode nase_mode = nase_mode.pass_ase
|
||||
|
||||
options.nase_mode = 0;
|
||||
options.noifig = 0;
|
||||
|
||||
options.saturation_mode = 0;
|
||||
options.saturation_power = 0;
|
||||
|
||||
options.fsimu = []
|
||||
options.amplification_db double = 0
|
||||
|
||||
options.noifig double = 0;
|
||||
end
|
||||
|
||||
obj.type = options.type;
|
||||
obj.amp_mode = options.amp_mode;
|
||||
obj.amplification_db = options.amplification_db;
|
||||
|
||||
obj.nase_mode = options.nase_mode;
|
||||
obj.noifig = options.noifig;
|
||||
|
||||
obj.saturation_mode = options.saturation_mode;
|
||||
obj.saturation_power = options.saturation_power;
|
||||
|
||||
obj.fsimu = options.fsimu;
|
||||
|
||||
|
||||
obj.saturation_power=1/1000*10^(obj.saturation_power/10);
|
||||
|
||||
fn = fieldnames(options);
|
||||
for n = 1:numel(fn)
|
||||
obj.(fn{n}) = options.(fn{n});
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function signalclass_out = process(obj,signalclass_in)
|
||||
|
||||
% actual processing of the signal (steps 1. - 3.)
|
||||
signalclass_in.signal = obj.process_(signalclass_in.signal);
|
||||
function signalclass_out = process(obj,signalclass_in)
|
||||
|
||||
% append to logbook
|
||||
lbdesc = ['Amp '];
|
||||
% actual processing of the signal
|
||||
signalclass_in = obj.process_(signalclass_in);
|
||||
|
||||
% append to logbook
|
||||
lbdesc = ['Amp '];
|
||||
signalclass_in = signalclass_in.logbookentry(lbdesc);
|
||||
|
||||
% write to output
|
||||
% write to output
|
||||
signalclass_out = signalclass_in;
|
||||
|
||||
end
|
||||
|
||||
function [X_out] = process_(obj,X_in)
|
||||
|
||||
function [y_out,nase] = process_(obj,x_in,optional)
|
||||
|
||||
arguments
|
||||
obj
|
||||
x_in = [];
|
||||
|
||||
optional.nase = 0;
|
||||
end
|
||||
|
||||
%calc gain for output power mode, amp mode and saturated mode
|
||||
a_lin = obj.calculateGain(x_in);
|
||||
a_lin = obj.calculateGain(X_in.signal);
|
||||
|
||||
y_out = a_lin * x_in;
|
||||
%apply amplification
|
||||
X_in.signal = a_lin * X_in.signal;
|
||||
|
||||
% now, optical ase noise:
|
||||
if class(X_in) == "Opticalsignal"
|
||||
|
||||
if obj.type == "ideal"
|
||||
if obj.amp_mode == amp_mode.ideal_no_noise
|
||||
|
||||
%don't add/ remove noise, but scale it accordingly
|
||||
if optional.nase ~= 0
|
||||
nase=state.a^2*optional.nase;
|
||||
%don't add/ remove noise, but scale it accordingly
|
||||
X_in.nase = obj.onlyAmplifyAse(X_in.nase, a_lin);
|
||||
|
||||
elseif obj.amp_mode == amp_mode.edfa_increase_nase
|
||||
|
||||
%calculate ASE-noise
|
||||
X_in.nase = obj.increaseAse(X_in.nase, a_lin, obj.noifig , X_in.lambda );
|
||||
|
||||
elseif obj.amp_mode == amp_mode.edfa_replace_nase
|
||||
|
||||
%calculate ASE-noise
|
||||
X_in.nase = obj.replaceAse(X_in.nase, a_lin, obj.noifig , X_in.lambda );
|
||||
|
||||
end
|
||||
|
||||
elseif obj.type == "edfa"
|
||||
if obj.nase_mode == nase_mode.generate_ase
|
||||
|
||||
nase = X_in.nase;
|
||||
fs = X_in.fs;
|
||||
dimension = size(X_in.signal);
|
||||
|
||||
%calculate ASE-noise
|
||||
if optional.nase ~= 0
|
||||
Nase_old = state.gain^2*optional.nase ;
|
||||
nase_numeric = obj.generateAseNoise(nase, fs, dimension);
|
||||
|
||||
h = Constant.Planck;
|
||||
c = Constant.LightSpeed;
|
||||
[X_in.signal, osnr] = obj.applyAseToSignal(X_in.signal, nase_numeric);
|
||||
|
||||
Nase_new = 0.5* 10^(obj.noifig/10) * h*c/(lambda_T*1e-9) * (a_lin^2-1) ;
|
||||
X_in.nase = 0;
|
||||
|
||||
elseif obj.nase_mode == nase_mode.pass_ase
|
||||
|
||||
X_in.nase = X_in.nase;
|
||||
|
||||
nase = Nase_old + Nase_new ;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
pow_in_lin = mean(abs(x_in.^2)) ;
|
||||
pow_in_dbm = 10*log10(pow_in_lin)+30;
|
||||
pow_out_lin = mean(abs(y_out.^2)) ;
|
||||
pow_out_dbm = 10*log10(pow_out_lin)+30;
|
||||
X_out = X_in;
|
||||
|
||||
if obj.amp_mode == "output_power"
|
||||
seemsright = pow_out_dbm == obj.amplification_db;
|
||||
elseif obj.amp_mode == "gain"
|
||||
seemsright = pow_out_dbm == pow_in_dbm + obj.amplification_db;
|
||||
end
|
||||
|
||||
if ~seemsright
|
||||
% warning("Amplifier output not correct, please check the reason");
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function a_lin = calculateGain(obj,xin)
|
||||
|
||||
if obj.amp_mode == "output_power"
|
||||
if obj.gain_mode == gain_mode.output_power
|
||||
|
||||
%get linear gain for output power mode
|
||||
pow_in = mean(abs(xin.^2)) ; % lin input power
|
||||
pow_out = 10^(obj.amplification_db/10 - 3) ; % dBm to lin
|
||||
a_lin = sqrt(pow_out/pow_in) ;
|
||||
|
||||
elseif obj.amp_mode == "gain"
|
||||
elseif obj.gain_mode == gain_mode.gain
|
||||
|
||||
%get linear gain for classic gain mode
|
||||
%get linear gain for classic gain mode
|
||||
a_lin=10^(obj.amplification_db/20);
|
||||
|
||||
end
|
||||
|
||||
if obj.saturation_mode
|
||||
Pin = sum(mean((abs(xin)).^2, 2)) ;
|
||||
|
||||
gain_power=fzero(inline(['log(G/' num2str(a_lin^2,'%1.16e') ')/(1-G)-log(2)*' num2str(Pin,'%1.16e') '/' ...
|
||||
num2str(obj.saturation_power,'%1.16e')],'G'),[1+eps,a_lin^2]);
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function nase_amped = onlyAmplifyAse(~,nase_old, a_lin)
|
||||
nase_amped = a_lin^2 * nase_old;
|
||||
end
|
||||
|
||||
function nase_new = calculateAseFromThisAmp(~, a_lin, noisefig, lambda)
|
||||
h = Constant.Planck;
|
||||
c = Constant.LightSpeed;
|
||||
nase_new = 0.5* 10^(noisefig/10) * h*c/lambda * (a_lin^2-1) ;
|
||||
end
|
||||
|
||||
function ase_increased = increaseAse(obj,nase_old, a_lin, noisefig, lambda)
|
||||
|
||||
nase_fromThisAmp = obj.calculateAseFromThisAmp(a_lin, noisefig, lambda);
|
||||
|
||||
nase_old = a_lin^2 * nase_old;
|
||||
|
||||
ase_increased = nase_old + nase_fromThisAmp;
|
||||
end
|
||||
|
||||
function nase_new = replaceAse(~,a_lin, noisefig, lambda_nm)
|
||||
|
||||
nase_fromThisAmp = obj.calculateAseFromThisAmp(a_lin, noisefig, lambda_nm);
|
||||
|
||||
nase_new = nase_fromThisAmp;
|
||||
end
|
||||
|
||||
function nase_numeric = generateAseNoise(~, nase, fs, dimension)
|
||||
nase_numeric = (randn(dimension) + 1i*randn(dimension))*sqrt(nase/2*fs) ;
|
||||
end
|
||||
|
||||
function [noisy_sig, osnr] = applyAseToSignal(~, opticalsignal, nase_numeric)
|
||||
noisy_sig = opticalsignal + nase_numeric ;
|
||||
osnr = pow2db(mean(abs(opticalsignal.^2))/mean(abs(nase_numeric.^2)));
|
||||
disp(osnr);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user