function mixedm_msfcn(block)
%MIXEDM_MSFCN An example integrator followed by unit delay MATLAB file S-function 
%   Example MATLAB file S-function implementing a hybrid system consisting
%   of a continuous integrator (1/s) in series with a unit delay (1/z).
    
%   Copyright 1990-2022 The MathWorks, Inc.
    setup(block);
end

function setup(block)

    % Sampling period and offset for unit delay.
    dperiod = 1;
    doffset = 0;
    
    mdlInitializeSizes(block, dperiod, doffset);
    block.RegBlockMethod('PostPropagationSetup', @mdlSetWorkWidths);
    block.RegBlockMethod('InitializeConditions',@mdlInitConditions);
    block.RegBlockMethod('Derivatives', @mdlDerivatives);
    block.RegBlockMethod('Outputs', @(block)mdlOutputs(block, dperiod, doffset));
    block.RegBlockMethod('Update', @(block)mdlUpdate(block, dperiod, doffset));
    block.RegBlockMethod('SetInputPortSampleTime', @mdlSetInputPortSampleTime);
    block.RegBlockMethod('SetOutputPortSampleTime', @mdlSetOutputPortSampleTime);
end

%
%=============================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=============================================================================
%
function mdlInitializeSizes(block, dperiod,doffset)
    % Register number of ports
    block.NumInputPorts = 1;
    block.NumOutputPorts = 1;
        
    % Override port properties
    block.InputPort(1).DatatypeID = 0;
    block.InputPort(1).DirectFeedthrough = false;
    block.OutputPort(1).DatatypeID = 0;

    % Register number of states
    block.NumContStates = 1;

    block.SimStateCompliance = 'DefaultSimState';
    
    % sample time
    block.InputPort(1).SampleTime = [0, 0];
    block.OutputPort(1).SampleTime = [dperiod doffset];
end
  
%
%=============================================================================
% mdlSetInputPortSampleTime
% Register input port sample times.
%=============================================================================
%
function mdlSetInputPortSampleTime(block, port, time)
end

%
%=============================================================================
% mdlSetOutputPortSampleTime
% Register output port sample times.
%=============================================================================
%
function mdlSetOutputPortSampleTime(block, port, time)
end


%
%=============================================================================
% mdlSetWorkWidths
% Register discrete states
%=============================================================================
%
function mdlSetWorkWidths(block)
    block.NumDworks = 1;
    block.Dwork(1).Name = 'x0';
    block.Dwork(1).Dimensions = 1;
    block.Dwork(1).DatatypeID = 0;
    block.Dwork(1).Complexity = 'Real';
    block.Dwork(1).UsedAsDiscState = true;
end

%
%=============================================================================
% mdlInitConditions
% Initialize states
%=============================================================================
%
function mdlInitConditions(block)
    % Initial conditions    
    block.ContStates.Data = 1;
    block.Dwork(1).Data = 1;
end

%
%=============================================================================
% mdlDerivatives
% Compute derivatives for continuous states.
%=============================================================================
%
function mdlDerivatives(block)
    block.Derivatives.Data = block.InputPort(1).Data; 
end

%
%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================
%
function mdlUpdate(block,dperiod,doffset)
    t = block.CurrentTime;
    % next discrete state is output of the integrator
    if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-8
      block.Dwork(1).Data = block.ContStates.Data;
    end
end

%
%=============================================================================
% mdlOutputs
% Return the output vector for the S-function
%=============================================================================
%
function mdlOutputs(block,dperiod,doffset)
    if block.IsMajorTimeStep
        t = block.CurrentTime;
        % Return output of the unit delay if we have a 
        % sample hit within a tolerance of 1e-8. If we
        % don't have a sample hit then output shouldn't change.
        if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-8
          block.OutputPort(1).Data = block.Dwork(1).Data;
        end
    end
end
