function [mv, Cost, MVopt, Xopt, Yopt, ExitFlag, eopt] = nmpcblock_interface( ...
    blkData, x, ref, lastmv, md, mvtarget, umin, umax, ymin, ymax, dumin, ...
    dumax, xmin, xmax, ywt, uwt, duwt, ecrwt, parameters, mvinit, xinit, einit)
% Inteface between nlmpc block and nlmpcmove calculation, called from the
% ML Function block inside the nlmpc block.

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

% All numerical inputs are guaranteed to have correct sizes
% x, lastmv are column vectors
% umin, umax, ymin, ymax, dumin, dumax, xmin, xmax are row vectors
% r, md, mvtarget, ywt, uwt, duwt, mvinit, xinit are matricies
% ecrwt, einit are scalars

returninfo = blkData.cost_enabled || blkData.mvseq_enabled || blkData.stateseq_enabled || blkData.ovseq_enabled || blkData.status_enabled || blkData.slack_enabled || ~blkData.nlp_initialize;
if blkData.usemex
    % the order of fields in "onlinedata" must be consistent with the order
    % of fields in "generateCodeGenerationData" (required by MEX) 
    onlinedata.ref = ref;
    if blkData.mvtarget_enabled
        onlinedata.MVTarget = mvtarget;
    else
        onlinedata.MVTarget = zeros(1,blkData.nmv);
    end
    if blkData.md_enabled
        onlinedata.md = md;
    end
    if blkData.npara > 0
        onlinedata.Parameters = struct2cell(parameters);
    end
    % Inputs xinit, mvinit, einit contain the solution from the previous
    % sample time.  Use as warm start.  At t=0, these are initialized to
    % x0, mv0, slack0. User can provide custom initialization signals.
    % Here xinit is (p-1)-by-nx from k+1, mvinit is (p-1)-by-nmv from k,
    % einit is a scalar.  We don't have to make them p rows because MEX
    % allows flexible number of rows up to p.
    onlinedata.X0 = xinit;
    onlinedata.MV0 = mvinit;
    onlinedata.Slack0 = einit;
    if blkData.ov_weight
        onlinedata.OutputWeights = ywt;
    end
    if blkData.mv_weight
        onlinedata.MVWeights = uwt;
    end
    if blkData.mvrate_weight
        onlinedata.MVRateWeights = duwt;
    end
    if blkData.ecr_weight
        onlinedata.ECRWeight = ecrwt;
    end
    if blkData.ov_min
        onlinedata.OutputMin = ymin;
    end
    if blkData.ov_max
        onlinedata.OutputMax = ymax;
    end
    if blkData.state_min
        onlinedata.StateMin = xmin;
    end
    if blkData.state_max
        onlinedata.StateMax = xmax;
    end
    if blkData.mv_min
        onlinedata.MVMin = umin;
    end
    if blkData.mv_max
        onlinedata.MVMax = umax;
    end
    if blkData.mvrate_min
        onlinedata.MVRateMin = dumin;
    end
    if blkData.mvrate_max
        onlinedata.MVRateMax = dumax;
    end
    %
    mexfcn = str2func(blkData.mexname);
    if returninfo 
        [mv, ~, Info] = mexfcn(x,lastmv,onlinedata);
        Cost = Info.Cost;
        MVopt = Info.MVopt;
        Xopt = Info.Xopt;
        Yopt = Info.Yopt;
        ExitFlag = Info.ExitFlag;
        eopt = max(Info.Slack,0);
    else
        mv = mexfcn(x,lastmv,onlinedata);
        Cost = zeros(1,1);
        MVopt = zeros(blkData.p+1,blkData.nmv);
        Xopt = zeros(blkData.p+1,blkData.nx);
        Yopt = zeros(blkData.p+1,blkData.ny);
        ExitFlag = zeros(1,1);
        eopt = zeros(1,1);
    end
else
    %% Get @nlmpc object
    nlobj = slResolve(blkData.nlmpcobj,blkData.blk);
    %% Handle optional input signals
    if ~blkData.md_enabled
        md = [];
    end
    %% Populate options with 
    % If optional inputs are being used, place values in an @nlmpcmoveopt
    % object.  This causes them to override the values saved in the @nlmpc
    % object when nlmpcmove is called.
    Options = nlmpcmoveopt;
    if nlobj.Model.NumberOfParameters > 0
        Options.Parameters = struct2cell(parameters);
    end
    if blkData.mvtarget_enabled
        Options.MVTarget = mvtarget;
    end
    if blkData.mv_min
        Options.MVMin = umin;
    end
    if blkData.mv_max
        Options.MVMax = umax;
    end
    if blkData.ov_min
        Options.OutputMin = ymin;
    end
    if blkData.ov_max
        Options.OutputMax = ymax;
    end
    if blkData.state_min
        Options.StateMin = xmin;
    end
    if blkData.state_max
        Options.StateMax = xmax;
    end
    if blkData.mvrate_min
        Options.MVRateMin = dumin;
    end
    if blkData.mvrate_max
        Options.MVRateMax = dumax;
    end
    if blkData.ov_weight
        Options.OutputWeights = ywt;
    end
    if blkData.mv_weight
        Options.MVWeights = uwt;
    end
    if blkData.mvrate_weight
        Options.MVRateWeights = duwt;
    end
    if blkData.ecr_weight
        Options.ECRWeight = ecrwt;
    end
    %% Initialize decision variables
    % Inputs xinit, mvinit, einit contain the solution from the previous sample
    % time.  Use as warm start.  At t=0, these are initialized to x0, mv0,
    % slack0. User can provide custom initialization signals.  Here xinit is
    % [1:p]-by-nx from k+1, mvinit is [1:p]-by-nmv from k, einit is a scalar.
    Options.X0 = xinit;
    Options.MV0 = mvinit;
    Options.Slack0 = einit;
    %% Call the solver
    % Calculate Info argument only when optional outports enabled and/or default warm start is used
    if returninfo 
        % Using try/catch to designate block in which error occurs. Error messages are designed for command-line use.
        try
            [mv, ~, Info] = nlmpcmove(nlobj, x, lastmv, ref, md, Options);
        catch ME
            throw(ME)
        end
        Cost = Info.Cost;
        MVopt = Info.MVopt;
        Xopt = Info.Xopt;
        Yopt = Info.Yopt;
        ExitFlag = Info.ExitFlag;
        eopt = max(Info.Slack,0);
    else
        try
            mv = nlmpcmove(nlobj, x, lastmv, ref, md, Options);
        catch ME
            throw(ME)
        end
        Cost = zeros(1,1);
        MVopt = zeros(blkData.p+1,blkData.nmv);
        Xopt = zeros(blkData.p+1,blkData.nx);
        Yopt = zeros(blkData.p+1,blkData.ny);
        ExitFlag = zeros(1,1);
        eopt = zeros(1,1);
    end
end