function utilSatWindupTracking(blk, dlgSett)
% ADDSATWINDUPTRACKING  Adds the appropriate saturation and anti-windup
% circuitry to the block diagram of the PID 1dof and PID 2dof blocks.
%
%   blk:                the masked subsystem where the inport is added

%   Author: A. Zimmerman
%   Copyright 2017-2020 The MathWorks, Inc.

sys = getfullname(blk);
sysInt = [sys '/Integrator'];
blkH = get_param(blk, 'Object');
isBlockTrackingMode = ~isempty(find_system(sys,'MatchFilter', @Simulink.match.allVariants, 'SearchDepth',1,'FollowLinks','on','LookUnderMasks','all','Name','TR'));
isBlockDiscrete = strcmp(blkH.IntegratorVariant,'Discrete') || strcmp(blkH.DerivativeFilterVariant,'');
isDialogProportional = dlgSett.isDialogProportional;
isDialogIntegrator = dlgSett.isDialogIntegral;
isDialogDerivative = dlgSett.isDialogDerivative;
isDialogIntegratorOnly = isDialogIntegrator && ~(isDialogProportional || isDialogDerivative);
isDialogLimitOutput = dlgSett.isDialogLimitOutput;
isDialogUseExtSatLims = dlgSett.isDialogUseExternalSatLimits;
isDialogFormIdeal = dlgSett.Form == 1;
isDialogControlParamSourceInternal = ~dlgSett.isDialogExternal;
dialogIntegratorMethod = dlgSett.IntegratorMethod;
antiWindupMode = dlgSett.AWMethod;

blkMaskType = blkH.MaskType;
if strcmp(blkMaskType,'PID 1dof')
    outStr = 'y';
elseif strcmp(blkMaskType,'PID 2dof')
    outStr = 'u';
else
    error(message('Simulink:blocks:unknownBlockType'));
end

%% Check if feedback blocks are needed
% Below logic checks that the controller must have integral action AND is
% discrete AND is using an integrator method that has direct feed through.
% The PID Controller must also have it's output limited with an anti-windup
% feature enabled OR have tracking mode.  If these conditions are met
% additional blocks are required in the feedback path
if isBlockDiscrete && isDialogIntegrator && (dialogIntegratorMethod==2 || dialogIntegratorMethod==3) ...
    && ((isDialogLimitOutput && (antiWindupMode==2 || antiWindupMode==3)) || isBlockTrackingMode)

    % Enable Feedback Blocks
    set_param(sys,'FdbkBlocksVariant','Feedback')
    
    % Enable Summing junction in feedback path
    if isDialogIntegratorOnly
        set_param(sys,'SumFdbkVariant','Passthrough')
    else
        set_param(sys,'SumFdbkVariant','Enabled')
    end
    
    % Enable state-port in Discrete Integrator
    set_param([sysInt '/Discrete/Integrator'],'ShowStatePort','on')
    set_param([sys '/Integrator/state'],'OutDataTypeStr','Inherit: auto')
    try %#ok<TRYNC>
        delete_line([sysInt '/Discrete'],'Ground_Integrator/1','state/1');
        add_line([sysInt '/Discrete'],'Integrator/State','state/1','autorouting','on')
    end

    % Enable Appropriate Variant for Feedback Proportional Gain
    if ~isDialogIntegratorOnly && isDialogFormIdeal
        if isDialogControlParamSourceInternal
            set_param(sys,'IdealPFdbkVariant','InternalParameters')
        else
            set_param(sys,'IdealPFdbkVariant','ExternalParameters')
        end
    else
        set_param(sys,'IdealPFdbkVariant','Passthrough')
    end
    
    % Enable/Disable Feedback Saturation
    % Only need Feedback Saturation block if knowledge of the post
    % saturation signal is required.  This only occurs for Back Calculation
    % and Tracking Mode
    if (antiWindupMode==2 || isBlockTrackingMode)
        if isDialogUseExtSatLims
            set_param(sys,'SatFdbkVariant','External')
        elseif isDialogLimitOutput
            set_param(sys,'SatFdbkVariant','Enabled')
        else
            set_param(sys,'SatFdbkVariant','Passthrough')
        end
    else
        set_param(sys,'SatFdbkVariant','Passthrough')
    end
else
    set_param(sys,'SumFdbkVariant','Disabled')
    set_param(sys,'FdbkBlocksVariant','Forward')
    set_param(sys,'SatFdbkVariant','Disabled')
    set_param(sys,'IdealPFdbkVariant','Disabled')
    
    if dlgSett.isDialogDiscrete && dlgSett.isDialogIntegral
        % Disable state-port in Discrete Integrator
        try %#ok<TRYNC>
            delete_line([sysInt '/Discrete'],'Integrator/State','state/1')
            add_line([sysInt '/Discrete'],'Ground_Integrator/1','state/1','autorouting','on');
        end
        set_param([sysInt '/Discrete/Integrator'],'ShowStatePort','off')
    end
    
end

%% Enable/Disable Saturation, Anti-windup and Tracking mode features
% Enable Saturation if requested
if isDialogUseExtSatLims
    set_param(sys,'SatVariant','External')
elseif isDialogLimitOutput
    set_param(sys,'SatVariant','Enabled')
else
    set_param(sys,'SatVariant','Disabled')
end
    
%  Enable Anti-windup and Tracking Mode Variants
if isDialogIntegrator
    if isDialogLimitOutput &&  antiWindupMode==2
        % Back Calculation
        % Enable Back Calculation AW Variant
        set_param(sys,'AWVariant','BackCalculation')
        set_param(sys,'PCopyVariant','Disabled')
        
    elseif isDialogLimitOutput &&  antiWindupMode==3
        % Clamping 
        % Enable Clamping AW Variant
        if isBlockDiscrete
            if isDialogFormIdeal
                set_param(sys,'AWVariant','DiscClampingIdeal')
            else
                set_param(sys,'AWVariant','DiscClampingParallel')
            end
        else
            if isDialogFormIdeal
                set_param(sys,'AWVariant','ContClampingIdeal')
            else
                set_param(sys,'AWVariant','ContClampingParallel')
            end
        end

        % If Form is Ideal knowledge of sign(P) is required for clamping
        % logic
        if isDialogFormIdeal && ~isDialogIntegratorOnly
            if isDialogControlParamSourceInternal
                set_param(sys,'PCopyVariant','InternalParamsIdeal')
            else
                set_param(sys,'PCopyVariant','ExternalParamsIdeal')
            end
        else
            set_param(sys,'PCopyVariant','Disabled')
        end
    else
        % Disable Anti-windup features
        set_param(sys,'AWVariant','Passthrough')
        set_param(sys,'PCopyVariant','Disabled')
    end
else
    % Disable Anti-windup features
    set_param(sys,'AWVariant','Disabled')
    set_param(sys,'PCopyVariant','Disabled')
end

%% Tracking Mode
if isDialogIntegrator && isBlockTrackingMode % Check for errors by verifying that strcmp(blkH.TrackingMode,'on'), maybe for P control
    % Enable Back Calculation AW Variant
    set_param(sys,'TRVariant','Enabled')
    set_param(sys,'TRSumVariant','TrackingMode')
else
    % Disable Back Calculation AW Variant
    set_param(sys,'TRVariant','Disabled')
    set_param(sys,'TRSumVariant','Passthrough')
end



end
