function dsfunc_msfcn(block)
%DSFUNC_MSFCN An example MATLAB file S-function for defining a discrete system.  
%   Example MATLAB file S-function implementing discrete equations: 
%      x(n+1) = Ax(n) + Bu(n)
%      y(n)   = Cx(n) + Du(n)
    
%   Copyright 1990-2022 The MathWorks, Inc.
    setup(block);
end

function setup(block)
    
    % Generate a discrete linear system:
    A=[-1.3839   -0.5097
        1.0000         0];
    
    B=[-2.5559         0
             0    4.2382];
    
    C=[      0    2.0761
             0    7.7891];
    
    D=[   -0.8141   -2.9334
           1.2426         0];
    
    mdlInitializeSizes(block, A, B, C, D);
    block.RegBlockMethod('PostPropagationSetup', ...
        @(block)mdlSetWorkWidths(block, A, B, C, D));
    block.RegBlockMethod('Start', ...
        @(block)mdlStart(block, A, B, C, D));
    block.RegBlockMethod('Outputs', ...
        @(block)mdlOutputs(block, A, B, C, D));
    block.RegBlockMethod('Update', ...
        @(block)mdlUpdate(block, A, B, C, D));

end

%
%=======================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=======================================================================
%
function mdlInitializeSizes(block, A, B, C, D)

    % Register number of ports
    block.NumInputPorts = 1;
    block.NumOutputPorts = 1;
        
    % Override port properties
    block.InputPort(1).DatatypeID = 0;
    block.InputPort(1).Dimensions = size(D, 2);
    block.InputPort(1).DirectFeedthrough = true;
    block.OutputPort(1).DatatypeID = 0;
    block.OutputPort(1).Dimensions = size(D, 1);

    block.SimStateCompliance = 'DefaultSimState';
    
    %
    % initialize the array of sample times
    %
    block.SampleTimes = [1 0];
end
%
%=============================================================================
% mdlSetWorkWidths
% Return discrete states specification.
%=============================================================================
%
function mdlSetWorkWidths(block, A, B, C, D)
    % setup dwork as discrete states
    block.NumDworks = 1;
    block.Dwork(1).Name = 'x0';
    block.Dwork(1).Dimensions = size(A, 1);
    block.Dwork(1).DatatypeID = 0;
    block.Dwork(1).Complexity = 'Real';
    block.Dwork(1).UsedAsDiscState = true;
end

%
%=============================================================================
% mdlStart
% Setup simulation.
%=============================================================================
%
function mdlStart(block, A, B, C, D)
    % initialize the initial conditions
    block.Dwork(1).Data = ones(size(A, 1),1);
end

%
%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================
%
function mdlUpdate(block, A, B, C, D)
    u = block.InputPort(1).Data;
    x = block.Dwork(1).Data;
    block.Dwork(1).Data = A*x+B*u;
end

%
%=======================================================================
% mdlOutputs
% Return the output vector for the S-function
%=======================================================================
%
function mdlOutputs(block, A, B, C, D)
    u = block.InputPort(1).Data;
    x = block.Dwork(1).Data;
    block.OutputPort(1).Data = C*x+D*u;
end
