/*  File    : sfun_zc.c
 *  Abstract:
 *
 *      Example of an S-function which has nonsampled zero crossings to
 *      implement abs(u). This S-function is designed to be used with
 *      a variable step solver.
 *
 *  Copyright 1990-2000 The MathWorks, Inc.
 *  $Revision: 1.10 $
 */


#define S_FUNCTION_NAME  sfun_zc
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"



/* Function: mdlInitializeSizes ===============================================
 * Abstract:
 *   Setup sizes of the various vectors.
 */
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0);
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
        return; /* Parameter mismatch will be reported by Simulink */
    }

    ssSetNumContStates(    S, 0);
    ssSetNumDiscStates(    S, 0);

    if (!ssSetNumInputPorts(S, 1)) return;
    ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
    ssSetInputPortDirectFeedThrough(S, 0, 1);

    if (!ssSetNumOutputPorts(S,1)) return;
    ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);

    ssSetNumSampleTimes(S, 1);
    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);
    ssSetNumModes(S, DYNAMICALLY_SIZED);
    ssSetNumNonsampledZCs(S, DYNAMICALLY_SIZED);

    /* Take care when specifying exception free code - see sfuntmpl_doc.c */
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);

}



/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *    Specifiy that we inherit our sample time from the driving block.
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0);
}



/* Function: mdlOutputs =======================================================
 * Abstract:
 *    y = abs(u)
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
    int_T             i;
    InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
    real_T            *y    = ssGetOutputPortRealSignal(S,0);
    int_T             width = ssGetOutputPortWidth(S,0);
    int_T             *mode = ssGetModeVector(S);

    UNUSED_ARG(tid); /* not used in single tasking mode */

    if (ssIsMajorTimeStep(S)) {
        for (i = 0; i < width; i++) {
            mode[i] = (*uPtrs[i] >= 0.0);
        }
    }

    for (i = 0; i < width; i++) {
        y[i] = mode[i]? (*uPtrs[i]): -(*uPtrs[i]);
    }
}



#if defined(MATLAB_MEX_FILE) || defined(NRT)
/* Function: mdlZeroCrossings =================================================
 * Abstract:
 *    Zero crossing signal to track is the input signal.
 */
#define MDL_ZERO_CROSSINGS
  static void mdlZeroCrossings(SimStruct *S)
  {
      int_T             i;
      real_T            *zcSignals = ssGetNonsampledZCs(S);
      InputRealPtrsType uPtrs      = ssGetInputPortRealSignalPtrs(S,0);
      int_T             nZCSignals = ssGetNumNonsampledZCs(S);

      for (i = 0; i < nZCSignals; i++) {
          zcSignals[i] = *uPtrs[i];
      }
  }
#endif


/* 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
