/*
 * MIXEDMEX    Example MEX-file for a single-input, single-output system
 *             with mixed continuous and discrete states.
 *             (see manual under Advanced Topics).
 *
 *             Use this as a template for other MEX-file systems
 *             that contain discrete and/or continuous states.
 *
 *             Syntax:  [sys, x0] = mixedmex(t,x,u,flag)
 *
 * Andrew Grace  Oct 11, 1990
 * Copyright (c) 1990-94 The Mathworks, Inc.
 * All Rights Reserved
 */

/*
 * The following #define is used to specify the name of this S-Function.
 */

#define S_FUNCTION_NAME mixedmex

/*
 * need to include simstruc.h for the definition of the SimStruct and
 * its associated macro definitions.
 */
#include "simstruc.h"

/*
 * mdlInitializeSizes - initialize the sizes array
 *
 * The sizes array is used by SIMULINK to determine the S-function block's
 * characteristics (number of inputs, outputs, states, etc.).
 */

static void mdlInitializeSizes(S)
    SimStruct *S;
{
    ssSetNumContStates(    S, 1);      /* number of continuous states */
    ssSetNumDiscStates(    S, 1);      /* number of discrete states */
    ssSetNumInputs(        S, 1);      /* number of inputs */
    ssSetNumOutputs(       S, 1);      /* number of outputs */
    ssSetDirectFeedThrough(S, 0);      /* direct feedthrough flag */
    ssSetNumSampleTimes(   S, 2);      /* number of sample times */
    ssSetNumInputArgs(     S, 0);      /* number of input arguments */
    ssSetNumRWork(         S, 1);      /* number of real work vector elements */
    ssSetNumIWork(         S, 0);      /* number of integer work vector elements */
    ssSetNumPWork(         S, 0);      /* number of pointer work vector elements */
}

/*
 * mdlInitializeSampleTimes - initialize the sample times array
 *
 * This function is used to specify the sample time(s) for your S-function.
 * If your S-function is continuous, you must specify a sample time of 0.0.
 * Sample times must be registered in ascending order.
 */

static void mdlInitializeSampleTimes(S)
    SimStruct *S;
{
    /*
     * This S-function has both continuous and discrete components.
     * Therefore, there is a sample time of 0.0 for the continous
     * component, and 1.0 for the discrete.
     */

    ssSetSampleTimeEvent (S, 0, 0.0);
    ssSetSampleTimeEvent (S, 1, 1.0);

    ssSetOffsetTimeEvent (S, 0, 0.0);
    ssSetOffsetTimeEvent (S, 1, 0.0);
}

/*
 * mdlInitializeConditions - initialize the states
 *
 * In this function, you should initialize the continuous and discrete
 * states for your S-function block.  The initial states are placed
 * in the x0 variable.  You can also perform any other initialization
 * activities that your S-function may require.
 */

static void mdlInitializeConditions(x0, S)
    double *x0;
    SimStruct *S;
{
    double *lasty = ssGetRWork(S);

    /*
     * initialize the continuous state, x0[0], and the discrete state x0[1]
     */
    
    x0[0] = 1.0;
    x0[1] = 1.0;
    
    /*
     * Set initial output to initial value of delay
     */
    
    lasty[0] = 1.; 
}

/*
 * mdlOutputs - compute the outputs
 *
 * In this function, you compute the outputs of your S-function
 * block.  The outputs are placed in the y variable.
 */

static void mdlOutputs(y, x, u, S, tid)
    double *y, *x, *u;
    SimStruct *S;
    int tid;
{
    double *lasty = ssGetRWork(S);

    /*
     * If this is a sample hit, set the output to the value of the
     * discrete state, otherwise, maintain the current output.
     */
    
    if (ssIsSampleHitEvent(S, 1, tid)) {
	y[0] = x[1];
	lasty[0] = x[1];
    } else {
	y[0] = lasty[0];
    }
}

/*
 * mdlUpdate - perform action at major integration time step
 *
 * This function is called once for every major integration time step.
 * Discrete states are typically updated here, but this function is useful
 * for performing any tasks that should only take place once per integration
 * step.
 */

static void mdlUpdate(x, u, S, tid)
    double *x, *u;
    SimStruct *S;
    int tid;
{
    /*
     * if this is a sample hit, propagate the continuous state to the
     * discrete state
     */
    
    if (ssIsSampleHitEvent(S, 1, tid)) {
	x[1] = x[0];
    }
}

/*
 * mdlDerivatives - compute the derivatives
 *
 * In this function, you compute the S-function block's derivatives.
 * The derivatives are placed in the dx variable.
 */

static void mdlDerivatives(dx, x, u, S, tid)
    double *dx, *x, *u;
    SimStruct *S;
    int tid;
{
    /*
     * the continous part of this block is simply an integrator,
     * so the derivative is the input
     */
    
    dx[0] = u[0];
}

/*
 * mdlTerminate - called when the simulation is terminated.
 *
 * In this function, you should perform any actions that are necessary
 * at the termination of a simulation.  For example, if memory was allocated
 * in mdlInitializeConditions, this is the place to free it.
 */

static void mdlTerminate(S)
    SimStruct *S;
{
}

#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
