 /*      
 *          Copyright (C) 2001 RasSimTech Ltd. 
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version. 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details. 
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 */


//   $Revision: 1.0.1 $  $Date: 2001/03/31 00:00:00 $

#define S_FUNCTION_NAME AVDSPlaybackSaveBlock
#define S_FUNCTION_LEVEL 2


#include <afxwin.h>         // MFC core and standard components
#include <iomanip>	//setw

#include "simstruc.h"

#include "AVDSPlaybackSave.h"



#define SAMPLE_TIME 0.0


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////   PARAMETER DEFINITIONS      //////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

enum enParameters {
					paramDataFileNameBase,
					paramVehicleID,
					paramNumberSignals,
					paramTotalParameters};

#define PARAM_DATA_FILE_NAME_BASE(S) ssGetSFcnParam(S,paramDataFileNameBase)
#define PARAM__VEHICLE_ID(S) ssGetSFcnParam(S,paramVehicleID)
#define PARAM_NUMBER_SIGNALS(S) ssGetSFcnParam(S,paramNumberSignals)


////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////   INPUT/OUTPUT DEFINITIONS   //////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

// TOTAL INPUTS DEFINED BY PARAMETER
enum enInputs {	
				inDummyInput,
				inTotalInputs };

#define U(element) (*uPtrs[element])  /* Pointer to Input Port0 */

// NOT USING OUTPUTS
enum enOutputs { 
				outSimulationTime,
				outTotalOutputs };


extern "C"
{
	void mdlStart(SimStruct *S);
	void mdlInitializeSizes(SimStruct *S);
	void mdlInitializeSampleTimes(SimStruct *S);
	void mdlInitializeConditions(SimStruct *S);
	void mdlOutputs(SimStruct *S, int_T tid);
	void mdlUpdate(SimStruct *S, int_T tid);
	void mdlTerminate(SimStruct *S);
	void mdlCheckParameters(SimStruct *S);
}


/*====================*
 * S-function methods *
 *====================*/

#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
	/* Function: mdlCheckParameters =============================================
	 * Abstract:
	 *    Validate our parameters to verify they are okay.
	*/
	static void mdlCheckParameters(SimStruct *S)
	{
      /* Check 1st parameter: Base File Name for the data file */
      {
          if (!mxIsChar(PARAM_DATA_FILE_NAME_BASE(S)) != 1) 
		  {
              ssSetErrorStatus(S,"1st parameter to the AVDSPlaybackSetupBlock must be the "
                               "Base File Name for the data file.");
              return;
          }
      }
      /* Check 2nd parameter: vehicle ID number */
      {
          if (!mxIsDouble(PARAM__VEHICLE_ID(S)) || mxGetNumberOfElements(PARAM__VEHICLE_ID(S)) != 1) 
		  {
              ssSetErrorStatus(S,"2nd parameter to the AVDSPlaybackSaveBlock must be the "
                               "vehicle number, this is used to build the data file name.");
              return;
          }
      }
      /* Check 3rd parameter: number of input signals */
      {
          if (!mxIsDouble(PARAM_NUMBER_SIGNALS(S)) || mxGetNumberOfElements(PARAM_NUMBER_SIGNALS(S)) != 1) 
		  {
              ssSetErrorStatus(S,"2nd parameter to the AVDSPlaybackSaveBlock must be the "
                               "number of input signals to the block.");
              return;
          }
      }
	}
#endif /* MDL_CHECK_PARAMETERS */


 
/* 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)
{
    ssSetNumSFcnParams(S, paramTotalParameters);  /* Number of expected parameters */

	ssSetNumContStates(S, 0);	// number continuous
    ssSetNumDiscStates(S, 0);	// number discrete states

    if (!ssSetNumInputPorts(S, 1)) 
	{
		return;
	}

	int iNumberInputs = (int)*mxGetPr(PARAM_NUMBER_SIGNALS(S));
    ssSetInputPortWidth(S, 0, iNumberInputs);
    ssSetInputPortDirectFeedThrough(S, 0, 1);	//not optional in R12

    if (!ssSetNumOutputPorts(S, 1))
	{
		return;
	}
    ssSetOutputPortWidth(S, 0, outTotalOutputs);


    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 */
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}


#define MDL_INITIALIZE_CONDITIONS
/* Function: mdlInitializeConditions ========================================
 * Abstract:
 *    Initialize both continuous states to zero.
 */
static void mdlInitializeConditions(SimStruct *S)
{
}

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

#define MDL_START  /* Change to #undef to remove function */
#if defined(MDL_START) 
  /* Function: mdlStart =======================================================
   * Abstract:
   *    This function is called once at start of model execution. If you
   *    have states that should be initialized once, this is the place
   *    to do it.
   */
static void mdlStart(SimStruct *S)
{
	CAVDSPlaybackSave* pavdsPlaybackSave = new CAVDSPlaybackSave();
	if(!pavdsPlaybackSave)
	{
		ssSetErrorStatus(S,"AVDSPlaybackSaveBlock: Error instantiating CAVDSPlaybackSave class.");
		return;
	}
	ssSetUserData(S,(void*)pavdsPlaybackSave);


	char caDataFileNameBase[256];
	mxGetString(PARAM_DATA_FILE_NAME_BASE(S),caDataFileNameBase,256);
	int iVehicleNumber = (int)*mxGetPr(PARAM__VEHICLE_ID(S));

	CString cstrDataFileName;
	cstrDataFileName.Format("%s%0.2d.dat",caDataFileNameBase,iVehicleNumber);
	sprintf(pavdsPlaybackSave->m_caFileName,"%s",cstrDataFileName);

	// make sure to delete any data in the file before writing to it
	ofstream ofsTemp(pavdsPlaybackSave->m_caFileName,(ios::out));
	ofsTemp.close();
	pavdsPlaybackSave->m_pofsOutToFile = new ofstream(pavdsPlaybackSave->m_caFileName,(ios::out|ios::app));

	pavdsPlaybackSave->m_iNumberInputs = (int)*mxGetPr(PARAM_NUMBER_SIGNALS(S));


}
#endif /*  MDL_START */


/* Function: mdlTerminate =====================================================
 * Abstract:
 *    No termination needed, but we are required to have this routine.
 */
static void mdlTerminate(SimStruct *S)
{
	CAVDSPlaybackSave* pavdsPlaybackSave = (CAVDSPlaybackSave*)ssGetUserData(S);
	delete pavdsPlaybackSave->m_pofsOutToFile;
	delete 	pavdsPlaybackSave;
}



/* Function: mdlOutputs =======================================================
 * Abstract:
 *      y = Cx + Du 
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
	real_T* prealOutputs = ssGetOutputPortRealSignal(S,0);
	CAVDSPlaybackSave* pavdsPlaybackSave = (CAVDSPlaybackSave*)ssGetUserData(S);
	InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);

	for (int iCount=0;iCount<pavdsPlaybackSave->m_iNumberInputs;iCount++)
	{
		*pavdsPlaybackSave->m_pofsOutToFile <<setprecision(6)<< (double)*uPtrs[iCount] << "\t";
	}
	*pavdsPlaybackSave->m_pofsOutToFile << endl;

	prealOutputs[outSimulationTime] = pavdsPlaybackSave->dGetSimulationTime();
}



#define MDL_UPDATE
/* Function: mdlUpdate ======================================================
 * Abstract:
 *      xdot = Ax + Bu
 */
static void mdlUpdate(SimStruct *S, int_T tid)
{
}



#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


