/*
* SCOMFRMSAMPLE 
*
* This block sets a sample time for a frame based on the sample time given
* in the mask. The block sample time is 
*
*     Ts*(samples per frame) = Ts*(input width)/(number of channels)
*
*  Copyright 1996-2000 The MathWorks, Inc.
*  $Revision: 1.2 $  $Date: 2000/05/19 14:42:08 $
*
*/

#define S_FUNCTION_NAME scomfrmsample
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"
#include "dsptypes.h"

/* --- Define i/o signals */
enum {INPORT=0, NUM_INPORTS};
enum {OUTPORT=0, NUM_OUTPORTS};

/* --- Define mask parameters */
enum {SAMPLE_TIME_A=0, NUM_CHANS_A, NUM_ARGS};
#define SAMPLE_TIME ssGetSFcnParam(S, SAMPLE_TIME_A)
#define NUM_CHANS   ssGetSFcnParam(S, NUM_CHANS_A)


/* Function: mdlCheckParameters ===============================================
 */
#ifdef MATLAB_MEX_FILE
#define MDL_CHECK_PARAMETERS
static void mdlCheckParameters(SimStruct *S) 
{

    if ( OK_TO_CHECK_VAR(S, SAMPLE_TIME) ) { 
        if (((real_T)mxGetPr(SAMPLE_TIME)[0] <= 0.0) || !IS_SCALAR_DOUBLE(SAMPLE_TIME)) {
            SET_ERROR(S, "The sample time must be a real scalar greater than zero.");
        }
    }

    if ( OK_TO_CHECK_VAR(S, NUM_CHANS) ) { 
        if (!IS_FLINT_GE(NUM_CHANS,1) || !IS_SCALAR_DOUBLE(NUM_CHANS)) {
            SET_ERROR(S, "The number of channels must be an integer greater than 0.");
        }
    }


} /* end mdlCheckParameters */
#endif

/* Function: mdlInitializeSizes ===============================================
 */
static void mdlInitializeSizes(SimStruct *S)
    {
	
	ssSetNumSFcnParams(S, NUM_ARGS);

#if defined(MATLAB_MEX_FILE)
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
    mdlCheckParameters(S);
    if (ssGetErrorStatus(S) != NULL) return;
#endif

    ssSetNumSampleTimes(S, 1);

    /* --- Inputs: */
    if (!ssSetNumInputPorts(S, NUM_INPORTS)) return;

    ssSetInputPortWidth(            S, INPORT, DYNAMICALLY_SIZED);
    ssSetInputPortDirectFeedThrough(S, INPORT, 1);
    ssSetInputPortComplexSignal(    S, INPORT, COMPLEX_INHERITED);
	ssSetInputPortReusable(		    S, INPORT, 0);
         
    /* --- Outputs: */
    if (!ssSetNumOutputPorts(S,NUM_OUTPORTS)) return;
            
	ssSetOutputPortWidth(        S, OUTPORT, DYNAMICALLY_SIZED);
    ssSetOutputPortComplexSignal(S, OUTPORT, COMPLEX_INHERITED);
	ssSetOutputPortReusable(     S, OUTPORT, 0);

	if (!ssSetNumDWork(S, DYNAMICALLY_SIZED)) return;

    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);

} /* End of mdlInitializeSizes(SimStruct *S) */


/* Function: mdlInitializeSampleTimes =========================================
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
	const int_T  portWidth = (int_T)ssGetInputPortWidth(S, INPORT);
	const int_T  numChan   = (int_T)mxGetPr(NUM_CHANS)[0];
	const real_T Ts        = (real_T)mxGetPr(SAMPLE_TIME)[0];

	ssSetSampleTime(S, 0, Ts*(real_T)(portWidth/numChan));
    ssSetOffsetTime(S, 0, 0.0);
}


/* Function: mdlOutputs =======================================================
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
	const int_T inPortWidth  = ssGetInputPortWidth(S,  INPORT);
	const int_T outPortWidth = ssGetOutputPortWidth(S, OUTPORT);

	InputPtrsType ptrInportSignal = ssGetInputPortSignalPtrs(S, INPORT);
	const creal_T *inportSignal   = (creal_T *)*ptrInportSignal;
	creal_T *outportSignal        = (creal_T *)ssGetOutputPortSignal(S, OUTPORT);

	int_T sampleIdx=0;

	for(sampleIdx=0;sampleIdx<inPortWidth;sampleIdx++) {
		outportSignal[sampleIdx].re = inportSignal[sampleIdx].re;
		outportSignal[sampleIdx].im = inportSignal[sampleIdx].im;
	}

}


static void mdlTerminate(SimStruct *S)
{
}


#ifdef  MATLAB_MEX_FILE    
# define MDL_SET_INPUT_PORT_WIDTH
  static void mdlSetInputPortWidth(SimStruct *S, int_T port,
                                    int_T inputPortWidth)
{
	const int_T numChan = (int_T)mxGetPr(NUM_CHANS)[0];

	if(inputPortWidth % numChan != 0) {
        SET_ERROR(S, "Input port width must be a multiple of the number of channels.");
	}

	ssSetInputPortWidth(S, port, inputPortWidth);

	if(ssGetOutputPortWidth(S, OUTPORT) == DYNAMICALLY_SIZED) {

		ssSetOutputPortWidth(S, OUTPORT, inputPortWidth);
	} else {
		SET_ERROR(S, "Port width propagation error.");
	}

}


# define MDL_SET_OUTPUT_PORT_WIDTH
  static void mdlSetOutputPortWidth(SimStruct *S, int_T port,
                                     int_T outputPortWidth)
{
	const int_T numChan = (int_T)mxGetPr(NUM_CHANS)[0];

	if(outputPortWidth % numChan != 0) {
        SET_ERROR(S, "Output port width must be a multiple of the number of channels.");
	}

	ssSetOutputPortWidth(S, port, outputPortWidth);

	if(ssGetInputPortWidth(S, INPORT) == DYNAMICALLY_SIZED) {
		ssSetInputPortWidth(S, INPORT, outputPortWidth);
	} else {
		SET_ERROR(S, "Port width propagation error.");
	}
 
}

#define MDL_SET_INPUT_PORT_COMPLEX_SIGNAL
static void mdlSetInputPortComplexSignal(SimStruct *S,
					 int_T port,
					 CSignal_T portComplex)
{
	ssSetInputPortComplexSignal(S, port, portComplex);

	if(ssGetOutputPortComplexSignal(S, OUTPORT) == COMPLEX_INHERITED) {
		ssSetOutputPortComplexSignal(S, OUTPORT, portComplex);
	} else {
		SET_ERROR(S, "Port complexity propagation error.");
	}
}

#define MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL
static void mdlSetOutputPortComplexSignal(SimStruct *S,
					  int_T port,
					  CSignal_T portComplex)
{
	ssSetOutputPortComplexSignal(S, port, portComplex);

	if(ssGetInputPortComplexSignal(S, INPORT) == COMPLEX_INHERITED) {
		ssSetInputPortComplexSignal(S, INPORT, portComplex);
	} else {
		SET_ERROR(S, "Port complexity propagation error.");
	}
}


#endif

#ifdef  MATLAB_MEX_FILE    
#include "simulink.c"      
#else
#include "cg_sfun.h"       
#endif
