function impcblock_InitFcn()
% MPC block uses three functions in the following order to initialize:
%
%   InitFcn: collect data from @mpc and @mpcstate objects specified in the
%   block dialog.  Obtain additional inport and outport connection
%   information (i.e. optional ports on/off status, whether an inport is
%   connected to a source block), special mmpc settings, and some scaling
%   data.  Save the structure to block "UserData".
%
%   MaskInitFcn: split into two functions: Parameter and Resize.
%
%       Parameter: when "UserData" is empty (i.e. model opens or no @mpc),
%       initialize the block with correct information for compilation.
%       Otherwise, create mask variables from "UserData" with additional
%       sanity check and memory optimization.
%
%       Resize: modify the block I/O based on dialog settings.  Each
%       constant block (when an optional inport is off) is initialized with
%       correct dimension.
%
%   StartFcn: check signal connectivity to MPC Controller block.  Signal
%   dimensions are already checked in the C S-function blocks connected to
%   the inports.  This function is called after compilation is done.

%   Authors: A. Bemporad, N. L. Ricker, R. Chen
%   Copyright 1986-2017 The MathWorks, Inc.

%% Get parameters from MPC block
blk = gcb;

%% When MPC object is missing, exit after removing structure from UserData
mpcobjname = strtrim(get_param(blk,'mpcobj'));
if isempty(mpcobjname)
    set_param(blk,'Userdata',[]);
    return
end

%% Process MPC object and initial states
[mpcobj, xmpc0] = mpc_chkmpcobjxmpc(blk);

%% Exit if economic mpc is configured (only applied to 17b or 18a object)
if mpcobj.IsEconomicMPC
    ctrlMsgUtils.error('MPC:general:SunsetEconomicMPC');
end

%% Obtain internal data as a structure
[MPCstruct, need_to_update, mpcobj] = getStruct(mpcobj, xmpc0);
if need_to_update && strcmp(get_param(blk,'updateMPCinCallerWorkspace'),'on')
    try %#ok<*TRYNC>
        assignin('caller',mpcobjname,mpcobj);
    end
end

%% Process MMPC information
% The flag "is_multiple" distinguishes between stand-alone MPC blocks and
% blocks that belong to a multiple MPC block set. 
MPCstruct.is_multiple = str2double(strtrim(get_param(blk,'is_multiple')));
% Signal enabling the optimization. QP is NOT formed and solved when
% the switching signal is enabled and connected to the MPC block and
% the switching signal is not equal to the enable_value
% This is used with multiple MPC blocks, to enable one block at the time.
MPCstruct.enable_value = str2double(strtrim(get_param(blk,'enable_value')));

%% Process inports connectivity
if MPCstruct.is_multiple
    MPCstruct = mpc_chkinportinfo('multiple', MPCstruct, blk);
else
    MPCstruct = mpc_chkinportinfo('single', MPCstruct, blk);
end

%% Process custom state estimation (same port as ym)
% Checking for consistency between object and block when custom state
% estimation is on
state_inport = get_param(blk, 'state_inport');
MPCstruct.CustomEstimation = strcmp(state_inport,'on');
EstGain = getEstGain(mpcobj);
if MPCstruct.CustomEstimation
    % error out if port is on but MPC object has default estimation
    if ~strcmpi(EstGain, 'custom')
        ctrlMsgUtils.error('MPC:utility:CustomEstimationOff', blk);
    end
else
    % error out if port is off but MPC object has custom estimation 
    if strcmpi(EstGain, 'custom')
        ctrlMsgUtils.error('MPC:utility:CustomEstimationExpected', blk);
    end
end

%% Process scaling data (inverse of scale factors)
MPCstruct.MVscale = MPCstruct.Uscale(MPCstruct.mvindex);
if MPCstruct.nmd>0
    MPCstruct.MDscale = MPCstruct.Uscale(MPCstruct.mdindex);
else
    MPCstruct.MDscale = 1;
end
    
MPCstruct.RMYscale = 1./MPCstruct.Yscale(MPCstruct.myindex);
MPCstruct.RMVscale = 1./MPCstruct.Uscale(MPCstruct.mvindex);
if MPCstruct.nmd>0
    MPCstruct.RMDscale = 1./MPCstruct.Uscale(MPCstruct.mdindex);
else
    MPCstruct.RMDscale = 1;
end
MPCstruct.RYscale = 1./MPCstruct.Yscale;

%% Process time-varying horizons
% save original p (required if pm_inport is 'on')
MPCstruct.p0 = MPCstruct.p; 
% replace p with the maximum p (required if pm_inport is 'on')
% online p is from external signal and must be less than maximum p.
if strcmp(get_param(blk,'pm_inport'),'on')
    MPCstruct.p = str2double(get_param(blk,'MaximumP'));
end

%% Save data structure in the block's UserData property
set_param(blk,'Userdata',MPCstruct);

