function capacitorsf(block)
%CAPACITORSIMPLESF Implementation of capacitor model as an s-funcion
% This model allows "multiple channels" of forces so the degrees of freedom
% (DOFs) are uncoupled.
% A Capacitor instance must be initialized in the matlab code to deal with the
% initialization of the block.
%
% Parameters:
%     nChannels - Number of channels (DoFs), got from the connected electrode;
%     eps0      - dielectric constant, got from the connected electrode;
%     posOffset - position of the a "pseudo electrode", user defined in wrapper;
%     forceNormal - vector to define force direction, user defined in wrapper;
%
% Block Inputs:
%     TM pos - instantaneous position of TM, m, [1x3] double;
%     TM rot - instantaneous orientation of TM, rad,[1x3] double;
%     A   - effective area of the capacitor, m2, [1x1] double;
%     VDC - voltage bias, v, [1x1] double;
%     V_  - control signal amplitude, [1x1] double for each channel;
%
% Block Outputs:
%     C   - instantaneous capacitance, F, [1x1] double;
%     gap - instantaneous gap between TM "pseudo electrode" and electrode, m,
%     [1x1] double;
%     pos - point where the force is applied?  todo: review
%              position + offset #todo: is this necessary;
%     F_  - electrostatic control force, [1x3] double for each channel;
%
% Author: Arthur Reis
% email: arthur.reis@aei.mpg.de
% Last revision: 11.08.2023;

setup(block);


function setup(block)
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;
block.NumDialogPrms     = 4;
%nChannels, eps0, posOffset, forceNormal
nChannels = block.DialogPrm(1).Data;

% INPUT PORTS
block.NumInputPorts  = 5 + nChannels;
% TM position
block.InputPort(1).Dimensions  =  3;
block.InputPort(1).DatatypeID  =  0;
block.InputPort(1).Complexity  = 'Real';
block.InputPort(1).DirectFeedthrough = true;

% TM rotation
block.InputPort(2).Dimensions  =  3;
block.InputPort(2).DatatypeID  =  0;
block.InputPort(2).Complexity  = 'Real';
block.InputPort(2).DirectFeedthrough = true;

% Electrode position
block.InputPort(3).Dimensions  =  3;
block.InputPort(3).DatatypeID  =  0;
block.InputPort(3).Complexity  = 'Real';
block.InputPort(3).DirectFeedthrough = true;

% Area
block.InputPort(4).Dimensions  =  1;
block.InputPort(4).DatatypeID  =  0;
block.InputPort(4).Complexity  = 'Real';
block.InputPort(4).DirectFeedthrough = true;

% V_DC
block.InputPort(5).Dimensions  =  1;
block.InputPort(5).DatatypeID  =  0;
block.InputPort(5).Complexity  = 'Real';
block.InputPort(5).DirectFeedthrough = true;


% V channels inputs
for i=1:nChannels
    block.InputPort(5+i).Dimensions =  1;
    block.InputPort(5+i).DatatypeID =  0;
    block.InputPort(5+i).Complexity = 'Real';
    block.InputPort(5+i).DirectFeedthrough = true;
end

% OUTPUT PORTS
%     NumOutputPorts = C + gap + pos + nChannels;
block.NumOutputPorts = 3 + nChannels;
% C
block.OutputPort(1).Dimensions  = 1;
block.OutputPort(1).DatatypeID  = 0;  % double
block.OutputPort(1).Complexity  = 'Real';
block.OutputPort(1).SamplingMode = 'Sample';
% gap
block.OutputPort(2).Dimensions  = 1;
block.OutputPort(2).DatatypeID  = 0;  % double
block.OutputPort(2).Complexity  = 'Real';
block.OutputPort(2).SamplingMode = 'Sample';
% Position
block.OutputPort(3).Dimensions  = 3;
block.OutputPort(3).DatatypeID  = 0;  % double
block.OutputPort(3).Complexity  = 'Real';
block.OutputPort(3).SamplingMode = 'Sample';

%block.OutputPort(1).DirectFeedthrough = false;
for i=1:nChannels
    block.OutputPort(i+3).Dimensions  = 3;
    block.OutputPort(i+3).DatatypeID  = 0;  % double
    block.OutputPort(i+3).Complexity  = 'Real';
end
% Register parameters

% Register sample times
%  [0 offset]            : Continuous sample time
%  [positive_num offset] : Discrete sample time
%
%  [-1, 0]               : Inherited sample time
%  [-2, 0]               : Variable sample time
block.SampleTimes = [0 0];

block.SimStateCompliance = 'DefaultSimState';

block.RegBlockMethod('PostPropagationSetup',    @DoPostPropSetup);
%block.RegBlockMethod('InitializeConditions', @InitializeConditions);
block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs);     % Required
%block.RegBlockMethod('Update', @Update);
%block.RegBlockMethod('Derivatives', @Derivatives);
block.RegBlockMethod('Terminate', @Terminate); % Required

block.RegBlockMethod('SetInputPortSamplingMode', @SetInpPortFrameData);

%end setup

function DoPostPropSetup(block)
  block.NumDworks = 4;

  block.Dwork(1).Name            = 'nChannels';
  block.Dwork(1).Dimensions      = 1;
  block.Dwork(1).DatatypeID      = 7;      % double
  block.Dwork(1).Complexity      = 'Real'; % real
  block.Dwork(1).UsedAsDiscState = false;

  block.Dwork(2).Name            = 'eps0';
  block.Dwork(2).Dimensions      = 1;
  block.Dwork(2).DatatypeID      = 0;      % double
  block.Dwork(2).Complexity      = 'Real'; % real
  block.Dwork(2).UsedAsDiscState = false;

  block.Dwork(3).Name            = 'posOffset';
  block.Dwork(3).Dimensions      = 3;
  block.Dwork(3).DatatypeID      = 0;      % double
  block.Dwork(3).Complexity      = 'Real'; % real
  block.Dwork(3).UsedAsDiscState = false;

  block.Dwork(4).Name            = 'forceNormal';
  block.Dwork(4).Dimensions      = 3;
  block.Dwork(4).DatatypeID      = 0;      % double
  block.Dwork(4).Complexity      = 'Real'; % real
  block.Dwork(4).UsedAsDiscState = false;

%function InitializeConditions(block)

function Start(block)
    block.Dwork(1).Data = uint32(block.DialogPrm(1).Data); %nChannels
    block.Dwork(2).Data = block.DialogPrm(2).Data; %eps0
    block.Dwork(3).Data = block.DialogPrm(3).Data; %posOffset
    block.Dwork(4).Data = block.DialogPrm(4).Data; %forceNormal

function Outputs(block)
    %todo: review the algorithm and calculation
    N    = uint32(block.Dwork(1).Data); %nChannels
    eps0 = block.Dwork(2).Data;
    posOffset   = block.Dwork(3).Data;
    forceNormal = block.Dwork(4).Data;
    TMpos = block.InputPort(1).Data;
    TMrot = block.InputPort(2).Data;
    elPos = block.InputPort(3).Data;
    A     = block.InputPort(4).Data;
    VDC   = block.InputPort(5).Data;
    roll  = TMrot(1);
    pitch = TMrot(2);
    yaw   = TMrot(3);
    dcm = angle2dcm( yaw, pitch, roll );
    posOffset = dcm*posOffset;

    posNow = posOffset + TMpos;
    d = sqrt(sum((posNow - elPos) .^ 2));
    C = eps0 * A/d;


    block.OutputPort(1).Data = C;
    block.OutputPort(2).Data = d;
%     block.OutputPort(3).Data = [posOffset(1)+TMpos(1),...
%                                 posOffset(2)+TMpos(2),...
%                                 posOffset(3)+TMpos(3)]; %TODO: im not sure..
    block.OutputPort(3).Data=posOffset;
    for i=1:N
      VAC = block.InputPort(5+i).Data;
      f = (VDC + VAC)^2 * eps0*A/2/d^2; %todo: review force
      block.OutputPort(i+3).Data = f.*forceNormal;
    end

%function Update(block)

    %block.Dwork(1).Data = block.InputPort(1).Data;

%function Derivatives(block)

function Terminate(block)

function SetInpPortFrameData(block, idx, fd)

  block.InputPort(idx).SamplingMode = fd;
  for i = 1:block.NumOutputPorts
    block.OutputPort(i).SamplingMode  = fd;
  end
Not enough input arguments.

Error in capacitorsf (line 33)
setup(block);