/*  File    : csfunc.c
 *  Abstract:
 *
 *      Example C-file S-function for defining a continuous system.  
 *
 *      x' = Ax + Bu
 *      y  = Cx + Du
 *
 *      For more details about S-functions, see simulink/src/sfuntmpl_doc.c.
 * 
 *  Copyright 1990-2004 The MathWorks, Inc.
 *  $Revision: 1.9.4.2 $
 */


#define S_FUNCTION_NAME s_function_model_ding_Cmex_2
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#define ANZ_PARAM 0
#define ANZ_INPUT 1
#define ANZ_OUTPUT 1
#define ANZ_ZUSTAND 2

/*====================*
 * S-function methods *
 *====================*/

/* Function: mdlInitializeSizes ===============================================
 * Abstract:
 *    The sizes information is used by Simulink to determine the S-function
 *    block's characteristics (number of inputs, outputs, states, etc.).
 */
static void mdlInitializeSizes(SimStruct *S)
{
    int_T i;
    
    //Parameter-Ports
    ssSetNumSFcnParams(S, ANZ_PARAM);  /* Number of expected parameters */
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
        return; /* Parameter mismatch will be reported by Simulink */
    }

    ssSetNumContStates(S, ANZ_ZUSTAND);
    ssSetNumDiscStates(S, 0);

    //Input-Ports
    if (!ssSetNumInputPorts(S, ANZ_INPUT)) return; // Anzahl der Input-Ports entspricht der Anzahl der Eingänge
    for (i = 0; i < ANZ_INPUT ; i++)               // Jeder Port muss initialisiert werden
    {
    ssSetInputPortWidth(S, i, 7);
    ssSetInputPortDirectFeedThrough(S, i, 0);
    }
    
    //Output-Ports
    if (!ssSetNumOutputPorts(S, ANZ_OUTPUT)) return;   // Anzahl der Output-Ports entspricht der Anzahl der Ausgänge
    for (i = 0; i < ANZ_OUTPUT; i++)
    {
    ssSetOutputPortWidth(S, i, 2);     //  
    }
    
    ssSetNumSampleTimes(S, 1);
    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);
    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs(S, 0);

    /* Take care when specifying exception free code - see sfuntmpl_doc.c */
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
    
    //mexPrintf("mdlInitializeSizes");
}



/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *    Specifiy that we have a continuous sample time.
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
    ssSetModelReferenceSampleTimeDefaultInheritance(S);         
}

#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ========================================
 * Abstract:
 *    Initialize both continuous states to zero.
 */
static void mdlInitializeConditions(SimStruct *S)
// Hier werden Initialwerte für die Zustände des Modells übermittelt.
{

    real_T *x_init = ssGetContStates(S); //real_T ist ein universeller Variablentyp, wie int_T etc.
    int_T  lp;                           // real_T kann auch durch double und int_T durch int ersetzt werden.

    for (lp = 0; lp < ANZ_ZUSTAND ; lp++) { 
        *x_init++=0.0; 
    }
   // mexPrintf("mdlInitializeConditions");
}



/* Function: mdlOutputs =======================================================
 * Abstract:
 *      y = Cx + Du 
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{   
    
    
    // Ausgaenge
    real_T            *y   = ssGetOutputPortRealSignal( S,0);

    
    //mexPrintf("mdlOutputs Ausgaenge1");
    // Parameter
    //double *p1_in = mxGetPr(ssGetSFcnParams( S,0));
    //double *p1_in = mxGetPr(ssGetSFcnParams( S,1));

    // Zustaende
    real_T            *x    = ssGetContStates(S);
    real_T C = x[0];
    real_T F = x[1];
 
    //mexPrintf("mdlOutputs Zustaende");
      
    UNUSED_ARG(tid); /* not used in single tasking mode */

    /* y=Cx+Du */
    y[0] = C;
    y[1] = F;
    //mexPrintf("mdlOutputs Ausgaenge2");
}



#define MDL_DERIVATIVES
/* Function: mdlDerivatives =================================================
 * Abstract:
 *      xdot = Ax + Bu
 */
static void mdlDerivatives(SimStruct *S)
{
    double tau_1, tau_2, tau_c, k_m, A, t_1, t;
    
    // Ableitungen
    real_T            *dx   = ssGetdX(S);
    real_T dC = dx[0];
    real_T dF = dx[1];
    
    //mexPrintf("mdlDerivatives Ableitungen");
    
    // Zustaende
    real_T            *x    = ssGetContStates(S);
    real_T C = x[0];
    real_T F = x[1];
    
    //mexPrintf("mdlDerivatives Zustaende");

    // Eingaenge
    InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs( S,0);
    
    tau_1 = *uPtrs[0];
    tau_2 = *uPtrs[1];
    tau_c = *uPtrs[2];
    k_m   = *uPtrs[3];
    A     = *uPtrs[4];
    t_1   = *uPtrs[5];
    t     = *uPtrs[6];
    
    //mexPrintf("mdlDerivatives Eingaenge");
    /* xdot=Ax+Bu */
    dC = 1/tau_c*((exp(-(t-t_1)/tau_c))+(exp(-(t-2*t_1)/tau_c))+(exp(-(t-3*t_1)/tau_c))+(exp(-(t-4*t_1)/tau_c))+(exp(-(t-5*t_1)/tau_c))+(exp(-(t-6*t_1)/tau_c))-C/tau_c);
    dF = A*C/(k_m + C) - F/(tau_1 + tau_2*C/(k_m + C));
    
    //mexPrintf("mdlDerivatives dCdF");
}



/* Function: mdlTerminate =====================================================
 * Abstract:
 *    No termination needed, but we are required to have this routine.
 */
static void mdlTerminate(SimStruct *S)
{
    UNUSED_ARG(S); /* unused input argument */
}

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif
