classdef Photodiode
    %PGOTODIODE Summary of this class goes here
    %   Detailed explanation goes here

    properties
        fsimu
        responsivity
        dark_current
        temperature

        randomkey
        randomstream

    end

    methods
        function obj = Photodiode(options)
            %PHOTODIODE Construct an instance of this class
            %   Detailed explanation goes here
            arguments
                options.fsimu
                options.responsivity = 1;
                options.dark_current = 0;
                options.temperature  = 20;
                options.randomkey    = 1;
            end

            fn = fieldnames(options);
            for l = 1:numel(fn)
                obj.(fn{l}) = options.(fn{l});
            end
            
            obj.randomstream = RandStream('mlfg6331_64','Seed',obj.randomkey);
        end

        function signalclass_out = process(obj,signalclass_in)

             % actual processing of the signal (steps 1. - 3.)
            signalclass_in.signal = obj.process_(signalclass_in.signal); 

             % cast the inform. signal to electrical signal 
            [signalclass_in, nase, lambda] = Electricalsignal(signalclass_in,"fs",obj.fsimu,"logbook",signalclass_in.logbook);

             % append to logbook
             lbdesc = ['Photo Diode '];
            signalclass_in  = signalclass_in.logbookentry(lbdesc);

             % write to output
            signalclass_out = signalclass_in;

        end

        function yout = process_(obj,xin)
            %METHOD1 Summary of this method goes here
            %   Detailed explanation goes here

            k = Constant.Boltzmann;
            q = Constant.ElementaryCharge;

            T = obj.temperature + 273.15 ; %celsius + 273 = kelvin
            R = 50; %resistance of phdiode (50ohm is typical value)

            % Magnitude squared detection (sum over pols)
            yout = sum( abs(xin) .^2 * obj.responsivity, 2 ) ;
            
            % Shot Noise
            shot_noise = sqrt(q * obj.fsimu .* yout) .* randn(obj.randomstream,size(yout,1),1);

            yout = yout + shot_noise;

            % Thermal Noise
            therm_current_psd = (2 * k * T / R ) ; %squared

            Bw = obj.fsimu; %is this correct? shouldnt it be the bandwidth of the actual component? e.g. 70GHz?
            therm_noise_pow = therm_current_psd * 2 * Bw; %squared

            therm_noise = sqrt(therm_noise_pow) .* randn(obj.randomstream,size(yout,1),1);

            yout = yout + therm_noise;

            % Dark Current
            yout = yout + obj.dark_current ;

        end
    end
end

