function gsm_sfunc_m(block)

% -------------------------------------------------------------------------
%
% Beschreibung: Beispiel einer Gleichstrommaschine m. Propeller
%
% -------------------------------------------------------------------------
%
% Eingaenge:    um(1) ... uGSM
%               dm(1) ... mext
%
% Zustaende:    x(1)  ... iGSM
%               x(2)  ... phiGSMP
%               x(3)  ... wGSM
%               x(4)  ... wP
%
% Ausgaenge:    y1(1)  ... x(1)
%               y1(2)  ... x(2)
%               y1(3)  ... x(3)
%               y1(4)  ... x(4)
%               y2(1)  ... MGSM
%               y2(2)  ... MKopp
%
% Parameter:    p(1)  ... LGSM
%               p(2)  ... RGSM
%               p(3)  ... kGSM
%               p(4)  ... JGSM
%               p(5)  ... dcGSM
%               p(6)  ... dvGSM
%               p(7)  ... JP
%               p(8)  ... dcP
%               p(9)  ... dvP
%               p(10) ... dqP
%               p(11) ... cGSMP
%               p(12) ... dGSMP
%               p(13) ... Vektor der Anfangswerte x0: 
%                           ([x(1),x(2),x(3),x(4)] fuer t=0)
%
% -------------------------------------------------------------------------
% Abtastzeit (sample time): zeitkontinuierlich (continuous)
% -------------------------------------------------------------------------


% Die Funktion setup (s.u.) dient der Initialiserung des Matlab Objektes
% (block). Im Objekt block sind alle fuer die Simulation in Simulink
% notwendigen Eigenschaften (Eingaenge, Zustaende, Ausgaenge, Parameter,
% usw.) des dynamischen Systems (math. Modell) zusammengefasst.
setup(block);

% -------------------------------------------------------------------------
% Initialisierung des Simulationsobjektes block
% -------------------------------------------------------------------------

function setup(block)
  
  % Anzahl der Eingangs- und Ausgangsports
  block.NumInputPorts  = 2;
  block.NumOutputPorts = 2;
  
  % Anzahl der zeitkontinuierlichen Zustaende
  block.NumContStates = 4;

  % Anzahl der Parameter
  block.NumDialogPrms = 13;
  
  % Dimensionen der Eingangsports
  % Flag DirectFeedthrough kennzeichnet, ob ein Eingang direkt an einem
  % Ausgang auftritt, d.h. y=f(u)
  block.InputPort(1).Dimensions        = 1;
  block.InputPort(1).SamplingMode = 'Sample';
  block.InputPort(1).DirectFeedthrough = false;
  block.InputPort(2).Dimensions        = 1;
  block.InputPort(2).SamplingMode = 'Sample';
  block.InputPort(2).DirectFeedthrough = false;

  % Dimensionen der Ausgangsports  
  block.OutputPort(1).Dimensions       = 4;
  block.OutputPort(1).SamplingMode = 'Sample';
  block.OutputPort(2).Dimensions       = 2;
  block.OutputPort(2).SamplingMode = 'Sample'; 
  
  % Einstellen der Abtastzeit: [0 0] wird verwendet fuer die
  % zeitkontinuierliche Simulation.
  block.SampleTimes = [0 0];
  
  % ------------------------------------------------
  % NICHT VERAENDERN
  % ------------------------------------------------
  % 
  % Registrieren der einzelnen Methoden
  % Hier: InitializeConditions ... Initialisierung
  %       Outputs ...       Berechnung der Ausgaenge
  %       Derivatives ...   Berechnung der Zustaende
  %       Terminate ...     Konsistentes Beenden der Simulation

  block.RegBlockMethod('InitializeConditions',    @InitConditions); 
  block.RegBlockMethod('Outputs',                 @Output);  
  block.RegBlockMethod('Derivatives',             @Derivatives);  
  block.RegBlockMethod('Terminate',               @Terminate);


% -------------------------------------------------------------------------
% Setzen der Anfangsbedingungen der Zustaende
% -------------------------------------------------------------------------

function InitConditions(block)
  % Einlesen der Parameter des Systems
  x0 = block.DialogPrm(13).Data;
  
  % Eingabe der Anfangsbedingungen
  x=x0;
  
  % Schreiben auf Objekt block (NICHT VERAENDERN)
  block.ContStates.Data = x;


% -------------------------------------------------------------------------
% Berechnen der Ausgaenge
% -------------------------------------------------------------------------

function Output(block)
  % Shortcut fuer den Zustand
  x = block.ContStates.Data;

  % Berechnung der Ausgaenge
  y1(1) = x(1);
  y1(2) = x(2);
  y1(3) = x(3);
  y1(4) = x(4);
  
  kGSM = block.DialogPrm(3).Data;
  cGSMP= block.DialogPrm(11).Data;
  dGSMP= block.DialogPrm(12).Data;
  iGSM=x(1);
  phiGSMP=x(2);
  wGSM=x(3);
  wP=x(4);
  
  y2(1) = kGSM*iGSM;
  y2(2) = (wGSM-wP)*dGSMP+(phiGSMP)*cGSMP;
  
  % Schreiben auf Objekt block
  block.OutputPort(1).Data = y1;
  block.OutputPort(2).Data = y2;
  

% -------------------------------------------------------------------------
% Berechnen der Zustaende
% -------------------------------------------------------------------------

function Derivatives(block)

  % Einlesen der Parameter des Systems
  LGSM = block.DialogPrm(1).Data;
  RGSM = block.DialogPrm(2).Data;
  kGSM = block.DialogPrm(3).Data;
  JGSM = block.DialogPrm(4).Data;
  dcGSM= block.DialogPrm(5).Data;
  dvGSM= block.DialogPrm(6).Data;
  JP   = block.DialogPrm(7).Data;
  dcP  = block.DialogPrm(8).Data;
  dvP  = block.DialogPrm(9).Data;
  dqP  = block.DialogPrm(10).Data;
  cGSMP= block.DialogPrm(11).Data;
  dGSMP= block.DialogPrm(12).Data;
  
  % Shortcut fuer den Eingang
  um = block.InputPort(1).Data;
  dm = block.InputPort(2).Data;
  
  % Shortcut fuer die Zustaende
  x = block.ContStates.Data;

  iGSM=x(1);
  phiGSMP=x(2);
  wGSM=x(3);
  wP=x(4);
  
  % Berechnen der Zustaende
  dx(1) = (-RGSM * iGSM - kGSM * wGSM + um)/LGSM;
  dx(2) = wGSM - wP;
  dx(3) = (iGSM * kGSM - dvGSM * wGSM - dcGSM - (wGSM - wP) * dGSMP - phiGSMP * cGSMP) / JGSM;
  dx(4) = ((wGSM - wP) * dGSMP + phiGSMP * cGSMP - dqP * wP ^ 2 - dvP * wP - dm - dcP) / JP;
  
  % Schreiben auf Objekt block
  block.Derivatives.Data = dx;


% -------------------------------------------------------------------------
% Operationen am Ende der Simulation
% -------------------------------------------------------------------------

% Die function Terminate wird hier nicht verwendet,
% muss aber vorhanden sein!
function Terminate(block)
