/*
 * SZEROFIL   S-function which increases the sampling rate of a signal
 *            by inserting zeros into the signal.
 * DSP Blockset S-Function for zero filling input.
 *	This SIMULINK S-function inserts zeros between input elements of the
 *	scalar input, creating a "zero-filled" signal at a faster rate.
 *      This is for backward compatibility ONLY.
 *
 *  Scott French 10-4-94
 *  Revised: D. Orofino, 24-Feb-97
 *  Copyright 1995-2000 The MathWorks, Inc.
 *  $Revision: 1.13 $  $Date: 2000/05/05 20:16:19 $
 */

#define S_FUNCTION_NAME szerofil

#include <string.h>  /* memcpy */

#include "dsp_sim.h" 

#define NUM_ARGS        2
#define SAMPLETIME_ARG  ssGetArg(S,0)
#define CONVFACTOR_ARG  ssGetArg(S,1)

/*
 * IWork indices:
 */
#define NUM_IWORK      2
#define CONVFACTOR_IDX 0
#define COUNT_IDX      1


#ifdef MATLAB_MEX_FILE
#define MDL_CHECK_PARAMETERS
static void mdlCheckParameters(SimStruct *S) {
    const char *msg = NULL;
    real_T convfactor_dbl;
    int    convfactor_int;

    if ((mxGetM(SAMPLETIME_ARG) != 1) ||
        ((mxGetN(SAMPLETIME_ARG) != 1) && (mxGetN(SAMPLETIME_ARG) != 2))
        ) {
        msg = "The sample time must be either a scalar or 2-element row vector";
        goto ERROR_EXIT;
    }

    if (mxGetM(CONVFACTOR_ARG) * mxGetN(CONVFACTOR_ARG) != 1) {
        msg = "Sample rate conversion factor must be a scalar.";
        goto ERROR_EXIT;
    }
    convfactor_int = convfactor_dbl = mxGetPr(CONVFACTOR_ARG)[0];
    if ((convfactor_dbl != convfactor_int) ||
        (convfactor_dbl <= (real_T)0.0)) {
        msg = "Sample rate conversion factor must be an integer > 0";
        goto ERROR_EXIT;
    }

ERROR_EXIT:
    if (msg != NULL) {
        ssSetErrorStatus(S,msg);
    }
}
#endif


static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, NUM_ARGS);

#if defined(MATLAB_MEX_FILE)
    if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
        mdlCheckParameters(S);
        if (ssGetErrorStatus(S) != NULL) {
            return;
        }
    } else {
        return; /* Simulink will report a parameter mismatch error */
    }
#endif

    ssSetNumContStates(    S, 0);
    ssSetNumDiscStates(    S, 0);
    ssSetNumInputs(        S, DYNAMICALLY_SIZED);
    ssSetNumOutputs(       S, DYNAMICALLY_SIZED);
    ssSetDirectFeedThrough(S, 1);
    ssSetNumSampleTimes(   S, 1);
    ssSetNumRWork(         S, 0);
    ssSetNumIWork(         S, NUM_IWORK);
    ssSetNumPWork(         S, 0);
    ssSetNumModes(         S, 0);
    ssSetNumNonsampledZCs( S, 0);
    ssSetOptions(          S, SS_OPTION_EXCEPTION_FREE_CODE);
}


static void mdlInitializeSampleTimes(SimStruct *S)
{
    int    convfactor      = (int)(mxGetPr(CONVFACTOR_ARG)[0]);
    real_T sample_time_in  = mxGetPr(SAMPLETIME_ARG)[0];
    real_T offset_time_in  = (mxGetN(SAMPLETIME_ARG) == 2)
                           ? mxGetPr(SAMPLETIME_ARG)[1] : 0.0;

    ssSetSampleTimeEvent(S, 0, sample_time_in/convfactor);
    ssSetOffsetTimeEvent(S, 0, (real_T)0.0);
}


static void mdlInitializeConditions(real_T *x0, SimStruct *S)
{
    int convfactor = (int)(mxGetPr(CONVFACTOR_ARG)[0]);

    ssSetIWorkValue(S, CONVFACTOR_IDX, convfactor);
    ssSetIWorkValue(S, COUNT_IDX,      0);
}


static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, 
                       SimStruct *S, int_T tid)
{
    int *count    = ssGetIWork(S) + COUNT_IDX;
    int width     = ssGetNumInputs(S);

    if (*count == 0) {
        /* Copy the input: */
        memcpy((char *)y, (char *)u, width*sizeof(real_T));

    } else {
        /* Upsample: output zeros (at the fast rate): */
        while(width-- != 0) {
            *y++ = (real_T)0.0;
        }
    }

    ++(*count);  /* Increment count  */
    *count %= ssGetIWorkValue(S, CONVFACTOR_IDX); /* wrap count */
}

static void mdlUpdate(real_T *x, const real_T *u, SimStruct *S, int_T tid)
{
}

static void mdlDerivatives(real_T *dx, const real_T *x, const real_T *u, 
                           SimStruct *S, int_T tid)
{
}

static void mdlTerminate(SimStruct *S)
{
}

#include "dsp_trailer.c"
 
/* [EOF]: szerofil.c */
