classdef Amplifier %UNTITLED Summary of this class goes here % Detailed explanation goes here properties amp_mode gain_mode nase_mode amplification_db noifig fsimu end methods function obj = Amplifier(options) %UNTITLED Construct an instance of this class % Detailed explanation goes here arguments 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.amplification_db double = 0 options.noifig double = 0; end 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 signalclass_in = obj.process_(signalclass_in); % append to logbook lbdesc = ['Amp ']; signalclass_in = signalclass_in.logbookentry(lbdesc); % write to output signalclass_out = signalclass_in; end function [X_out] = process_(obj,X_in) %calc gain for output power mode, amp mode and saturated mode a_lin = obj.calculateGain(X_in.signal); %apply amplification X_in.signal = a_lin * X_in.signal; % now, optical ase noise: if class(X_in) == "Opticalsignal" if obj.amp_mode == amp_mode.ideal_no_noise %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 if obj.nase_mode == nase_mode.generate_ase nase = X_in.nase; fs = X_in.fs; dimension = size(X_in.signal); nase_numeric = obj.generateAseNoise(nase, fs, dimension); [X_in.signal, osnr] = obj.applyAseToSignal(X_in.signal, nase_numeric); X_in.nase = 0; elseif obj.nase_mode == nase_mode.pass_ase X_in.nase = X_in.nase; end end X_out = X_in; end function a_lin = calculateGain(obj,xin) 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.gain_mode == gain_mode.gain %get linear gain for classic gain mode a_lin=10^(obj.amplification_db/20); 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) rng(2023); 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