/*C-MEX S-function wrapper stepY_T1i_Ctrl_emC_SfH.c 
 * THIS S-FUNCTION IS GENERATED BY jzTc script ".../simulink_SFn_SfH.jzTc" - DO NOT MODIFY
 *
 */

/**Must specify the S_FUNCTION_NAME as the name of the S-function.
 */
#define S_FUNCTION_NAME                stepY_T1i_Ctrl_emC_SfH
#define S_FUNCTION_LEVEL               2

/*
 * Need to include simstruc.h for the definition of the SimStruct and
 * its associated macro definitions.
 */
#include <applstdef_emC.h>  //This file is proper defined for the simulink Sfunc environment to define the environment for CRJ 
#include <emC/Base/Object_emC.h>
#include <emC/Base/DefPortTypes_emC.h>
#include <emC/Base/String_emC.h>
#include <emC/OSAL/os_mem.h>
#include <emC/Base/CheckStack_emC.h>
#undef bool               //it is newly defined in tmwtypes with typedef.
#include <simstruc.h>     //Standard include from mathworks
#include <matrix.h>       //from Simulink, for mxGetDoubles(...) NOTE mxGetPr used, mxGetDoubles does not work in R2018b
#include <string.h>  //memset, strcmp
#include <stdlib.h>  //malloc

//#include <emC/Jc/ReflectionJc.h>   //Access to reflection for bus check necessary
#include <emC/OSAL/os_sharedmem.h> //Support 64-bit-pointer
/*
 * Specific header file(s) required by the S-function.
 */
#include "emC/Ctrl/T1_Ctrl_emC.h"


/**Properties of this SFunctionBlock:
 * InPorts:
 * * 0 x: int16 (Tstep, mInputStep_Entry_DefPortType_emC) 
 * OutPorts:
 * * 0 y_y: int16 (Tstep, mOutputStep_Entry_DefPortType_emC) 
 * Parameters:
 * * 0 Ts_param: float (Tinit, non-tunable)
 * * 1 Tstep: float (Tinit, Tstep, non tunable) 
 * Given routines and args from header:
 * basedOnObjectJc: 
 * dports: 
 * ctor: ctor_T1i_Ctrl_emC
 * dtor: 
 * init: param_T1i_Ctrl_emC

 * step: stepY_T1i_Ctrl_emC
 * updt: 
 * tlcParam: 
 * 
 * Object-FB
 * @simulink init: param_T1i_Ctrl_emC(...)
 * step times: Port based sample time
 * params: ix-step = 0, ix-upd = 0, ix-step2 = 0, ix-init = 0, ix-ctor = 2, nrof = 2  
 *   nrofParamsNoTunable = 2, nrofParamsTunable = 0, nrofParams = 2, maskTunable =        0
 * input ports: ix-step = 0, ix-upd = 1, ix-step2 = 1, ix-init = 1, nrof = 1  
 * input thiz: = -1
 * output ports: ix-step = 0, ix-init = 1, nrof = 1  
 * output thiz: thizInit = -1, thizStep = -1
 *
 */



/**Code Generation Environment flag (simulation or standalone target):
 * Mode of code generation. 1=for Simulation. 0=target code -1= error.
 * It is static valid for all instances. 
 * Set in mdlInitializeSizes(...){ ... = GetRTWEnvironmentMode(simstruct);...
 */
static int_T isSimulationTarget;   

//see below, on end. Routine to get isSimulationTarget
static int_T GetRTWEnvironmentMode(SimStruct *simstruct);



/**A static errorbuffer for preparing error messages. 
 * It is necessary because 'ssSetErrorStatus(simstruct, errorbuffer);' needs a persistent string, not in Stack!
 */
static char errorbuffer[1024];

/**Static struct for port and block information used on startup.
 * It is used only temporary in the adequate routine, not stored. The storage may be in stack too, but it may be too much for stack.
 * On runtime this information is in heap, see mdlStart. 
 */
static struct { DefPortTypes_emC head; Entry_DefPortType_emC __data__[64]; } __defPortTypes = {0};  //up to 32 inputs, 32 outputs, about 3 kByte in Stack.

/**Static area for the configuration parameter. */


#define EDIT_OK(simstruct, P_IDX) \
 (!((ssGetSimMode(simstruct)==SS_SIMMODE_SIZES_CALL_ONLY) && mxIsEmpty(ssGetSFcnParam(simstruct, P_IDX))))

#define isDWorkNeeded(simstruct)               ((!((ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) && isSimulationTarget==0)) || ssIsRapidAcceleratorActive(simstruct))

/*
 * Utility function prototypes.
 */
//static bool IsRealMatrix(const mxArray *m);
static void CheckDataTypes(SimStruct *simstruct);


#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)

/* Function: mdlCheckParameters ===========================================
 * Abstract:
 *    mdlCheckParameters verifies new parameter settings whenever parameter
 *    change or are re-evaluated during a simulation. When a simulation is
 *    running, changes to S-function parameters can occur at any time during
 *    the simulation loop.
 */
static void mdlCheckParameters(SimStruct *simstruct)
{
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.

  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.      
}

#endif




                                                             


//#define MDL_PROCESS_PARAMETERS
#if defined(MDL_PROCESS_PARAMETERS) && defined(MATLAB_MEX_FILE)

/* Function: mdlProcessParameters =========================================
 * Abstract:
 *    Update run-time parameters.
 */
static void XXXmdlProcessParameters(SimStruct *simstruct)
{
  /* Update Run-Time parameters */
  //ssUpdateAllTunableParamsAsRunTimeParams(simstruct);
}

#endif


//should be comment?


/**Start of the busElementPos for the current bus in busElementPos. For max, 20 _cbus or _ycbus. 
 * TODO check buses again. Global?
 */
static int busElementIndex[20];



/**Position of element in some buses. Any bus position record starts on busElementIndex[ix] 
 * for all input and output _cbus and _ycbus. At least 1000 elements for all buses.
 * TODO check buses again. Global?
 */
static int busElementPosLen[1000];

static int ixBusElementIndex=0, ixBusElementPosLen=0;


//struct to return the info to an indexed port.
typedef struct SmlkPortInfo_t {  DTypeId type; ssComplexity complexity; int arraySize; } SmlkPortInfo;



static DTypeId getSmlkType(char cType) {
  DTypeId smlkType;
  switch(cType) {
    case 'F': 
    case 'f': smlkType = SS_SINGLE; break;
    case 'D': 
    case 'd': smlkType = SS_DOUBLE; break;
    case 'I': 
    case 'i': smlkType = SS_INT32; break;
    case 'U': smlkType = SS_UINT32; break;
    case 'H': smlkType = SS_UINT32; break;
    case 'S': 
    case 's': smlkType = SS_INT16; break;                        
    case 'W': smlkType = SS_UINT16; break;
    case 'B': smlkType = SS_INT8; break;
    case 'V': smlkType = SS_UINT8; break;
    case 'Z': smlkType = SS_BOOLEAN; break;
    case 'b': smlkType = SS_UINT8; break;
    case '?': smlkType = DYNAMICALLY_TYPED; break;
    default : smlkType = DYNAMICALLY_TYPED; break;
  }
  return smlkType;
}




/**Get the type info for a port from given Entry_DefPortType_emC.
 * @param ix should be match to the array portTypes, not tested internally.
 */
static void getPortInfo(SmlkPortInfo* info, Entry_DefPortType_emC const* portType)
{ 
  if(portType->dimensions <0) {
    info->arraySize = DYNAMICALLY_SIZED;  //No arraysize determined. It is dynamically
  } else if(portType->dimensions >=1) {
    info->arraySize = portType->sizeArray[0];
    if(info->arraySize == 0) { info->arraySize = DYNAMICALLY_SIZED; }
  } else {
    info->arraySize = 1;  //it means scalar. 
  }
  info->type = getSmlkType(portType->type);
  info->complexity = info->type == DYNAMICALLY_TYPED ? COMPLEX_INHERITED 
                   : (portType->type >='a' ? COMPLEX_YES : COMPLEX_NO);
  
}




//
//The static routine setPortInfo(...) reads port properties from the ports itself
//because before mdlStart(...) nothing can be stored in PWork or DWork pointer or in static variable.
//Note: static variable cannot be used because more as one instance of a SFB type may be actually used
//      and the order of invocation is not sorted to the instances.
//This routine offers the port information for mdlSetDefaultPort...(...).
//


//
//Sub routine to set the known port types and sizes and to invoke the users "@simulink defPortTypes" routine.
//Before call the yet known port types are stored in the Entry_DefPortType_emC[] array
//to give information about that to determine the yet not typed ports.
//The users "@simulink defPortTypes" routine is not called if the cause is 'kRun_EPropagatePortTypes_emC'.
//This is to fill the DefPortTypes_emC struct with the types and sizes of all ports before the ctor-, init- or step-routine
// 
static void setPortInfo ( SimStruct *simstruct, DefPortTypes_emC* _fbInfo_, EDefPortTypes_emC _cause_)  
{ //stack local array, the user routine must not store the reference!    
  //Note: because the ctor is not invoked in this time, and DWork cannot be used in this time, no instance data are possible.
    //
  //gather all port information:
  //
  STACKTRC_ENTRY("setPortInfo");
  //The following values are that without variable nrof ports. 
  //
  _fbInfo_->ixInputStep = 0;
  _fbInfo_->ixInputStep2 = 1;
  _fbInfo_->ixInputUpd = 1;
  _fbInfo_->ixInputInit = 1;
  _fbInfo_->ixInputVarg = 1;
  _fbInfo_->ixOutputStep = 1 + 0;
  _fbInfo_->ixOutputStep2 = 1 + 1;
  _fbInfo_->ixOutputInit = 1 + 1;
  _fbInfo_->ixOutputVarg = 1;
  _fbInfo_->ixOutputThizInit = -1;
  _fbInfo_->ixOutputThizStep = -1;
  _fbInfo_->nrofVargsInit = 0;
  _fbInfo_->nrofVargsStep = 0;
  _fbInfo_->bitsParamTunable = 0;
  strncpy_emC(_fbInfo_->pathBlock, ssGetPath(simstruct), sizeof(_fbInfo_->pathBlock));
  //
  //per default the ports for step, step2, Init are in order. Set bit masks.
  _fbInfo_->mInputStep = (1 <<1) -1;
  int mInputStep2 =       ((1 <<1) -1) & ~((1 <<1) -1);
  _fbInfo_->mInputUpd =   ((1 <<1) -1) & ~((1 <<1) -1);
  _fbInfo_->mInputInit = ((1 <<1) -1) & ~((1 <<1) -1);
  _fbInfo_->mOutputStep = ((1 <<1) -1);
  _fbInfo_->mOutputInit =((1 <<1) -1) & ~((1 <<1) -1);
  if(_cause_ == kSetFromArg_EPropagatePortTypes_emC) {
    _fbInfo_->nrofInputs = 1;      //read without regarding variable nrof ports 
    _fbInfo_->nrofOutputs = 1;
    
    //jzTc:set_DefPortTypes_emC(...) from all routines. 
    set_DefPortTypes_emC(_fbInfo_, 0, 'S', "x", null, "int16", 0, mInputStep_Entry_DefPortType_emC);  // x
    set_DefPortTypes_emC(_fbInfo_, 1, 'S', "y_y", null, "int16", 0, mOutputStep_Entry_DefPortType_emC);  //y_y
  } else { 
    //mdlInitializesSizes is processed already, read from Simulink settings:
    _fbInfo_->nrofInputs = ssGetNumInputPorts(simstruct);    //That values are necessary before run the (...).
    _fbInfo_->nrofOutputs = ssGetNumOutputPorts(simstruct);
  }
  //0
  //
  _fbInfo_->TstepMin = 77777777.7f;
  int ixPort;
  char cType;
  int sizeType;
  Entry_DefPortType_emC* entryPortTypes = _fbInfo_->entries; 
  //fill struct with known port properties, but not in initalizeConditions, there the ports are not defined yet.
  for(ixPort = 0; ixPort < _fbInfo_->nrofInputs; ++ixPort) {
    Entry_DefPortType_emC* entryPortType = &entryPortTypes[ixPort];  //dst to set
    if(_cause_ == kSetFromArg_EPropagatePortTypes_emC) { 
      //ports are not initialized yet.
    } else {
      //get infos from initialized ports:
      DTypeId type = ssGetInputPortDataType(simstruct, ixPort);
      switch(type) {
        case SS_DOUBLE: cType = 'D'; sizeType = 8; break; 
        case SS_SINGLE: cType = 'F'; sizeType = 4; break;
        case SS_INT32:  cType = 'I'; sizeType = 4; break;
        case SS_INT16:  cType = 'S'; sizeType = 2; break;
        case SS_INT8:   cType = 'B'; sizeType = 1; break;
        case SS_UINT32: cType = 'U'; sizeType = 4; break;
        case SS_UINT16: cType = 'W'; sizeType = 2; break;
        case SS_UINT8:  cType = 'V'; sizeType = 1; break;
        case SS_BOOLEAN:cType = 'Z'; sizeType = 1; break;
        default:        cType = 0;   sizeType = 0; break;
      }
      if(ssGetInputPortComplexSignal(simstruct, ixPort) == COMPLEX_YES) { cType += ('a'-'A'); sizeType *=2; } //to lower case; 
      entryPortType->type = cType;  
      entryPortType->sizeType = sizeType;  
      //
      int size = ssGetInputPortWidth(simstruct, ixPort); 
      if(size == DYNAMICALLY_SIZED) {
        entryPortType->dimensions = -1;
        entryPortType->sizeArray[0] = 0;
      } else {
        entryPortType->dimensions = 1;
        entryPortType->sizeArray[0] = size;
      }
      entryPortType->Tstep = (float)ssGetInputPortSampleTime(simstruct, ixPort);      //valid only if port based!
      entryPortType->ixTstepSfn = ssGetInputPortSampleTimeIndex(simstruct, ixPort);   //valid only if port based!
      if(_fbInfo_->TstepMin > entryPortType->Tstep) {
        _fbInfo_->TstepMin = entryPortType->Tstep;
        _fbInfo_->ixInOutTstep = ixPort;
        _fbInfo_->ixStepSfnMin = entryPortType->ixTstepSfn;
      }
    }
  }
  for(ixPort = 0; ixPort < _fbInfo_->nrofOutputs; ++ixPort) {
    Entry_DefPortType_emC* entryPortType = &entryPortTypes[_fbInfo_->nrofInputs + ixPort];  //dst to set
    if(_cause_ == kSetFromArg_EPropagatePortTypes_emC) { 
      //ports are not initialized yet.
    } else {
      //get infos from initialized ports:
      DTypeId type = ssGetOutputPortDataType(simstruct, ixPort);
      switch(type) {
        case SS_DOUBLE: cType = 'D'; sizeType = 8; break; 
        case SS_SINGLE: cType = 'F'; sizeType = 4; break;
        case SS_INT32:  cType = 'I'; sizeType = 4; break;
        case SS_INT16:  cType = 'S'; sizeType = 2; break;
        case SS_INT8:   cType = 'B'; sizeType = 1; break;
        case SS_UINT32: cType = 'U'; sizeType = 4; break;
        case SS_UINT16: cType = 'W'; sizeType = 2; break;
        case SS_UINT8:  cType = 'V'; sizeType = 1; break;
        case SS_BOOLEAN:cType = 'Z'; sizeType = 1; break;
        default:        cType = 0;   sizeType = 0; break;
      }
      if(ssGetOutputPortComplexSignal(simstruct, ixPort) == COMPLEX_YES) { cType += ('a'-'A'); ; sizeType *=2; } //to lower case; 
      entryPortType->type = cType; 
      entryPortType->sizeType = sizeType;  
      //  
      int size = ssGetOutputPortWidth(simstruct, ixPort); 
      if(size == DYNAMICALLY_SIZED) {
        entryPortType->dimensions = 0;
        entryPortType->sizeArray[0] = 0;
      } else {
        entryPortType->dimensions = 1;
        entryPortType->sizeArray[0] = size;
      }
      entryPortType->Tstep = (float)ssGetOutputPortSampleTime(simstruct, ixPort);     //valid only if port based!
      entryPortType->ixTstepSfn = ssGetOutputPortSampleTimeIndex(simstruct, ixPort);  //valid only if port based!
      if(_fbInfo_->TstepMin > entryPortType->Tstep) {
        _fbInfo_->TstepMin = entryPortType->Tstep;
        _fbInfo_->ixInOutTstep = -ixPort;
        _fbInfo_->ixStepSfnMin = entryPortType->ixTstepSfn;
      }
    }
  }
  _fbInfo_->mInputDataInit = _fbInfo_->mInputInit;  //used in mdlRTW() for tlc parameter
  
  STACKTRC_RETURN;
}







/* 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 *simstruct)
{                    
  //If set, this is the found step time from Global Workspace Tinit.
  double Tinit = 0;  //This value is set from a global Workspace variable with name 'Tinit'. It should be existing.
  
  //
  //The Tstep and Tstep_offset will be set from parameter Tstep or Tstep_offset in mdlInitializeSizes(...)
  //If the parameters are given, the input port gets the sample time of the parameter.
  //If the parameters are not given, firstly the ports are initialized with INHERITED_SAMPLE_TIME, 
  //then the sample time from the model is associated. 
  //
  double Tstep = INHERITED_SAMPLE_TIME;
  double Tstep2 = INHERITED_SAMPLE_TIME;

  STACKTRC_ENTRY("mdlInitializeSizes");
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  TRY {
  
  /*
   * Get the value returned by rtwenvironmentmode(modelName)
   */
  if (ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) {
    isSimulationTarget = GetRTWEnvironmentMode(simstruct);
    if (isSimulationTarget==-1) {
      ssSetErrorStatus(simstruct,
                       "Unable to determine a valid code generation environment mode.");
      testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
      STACKTRC_RETURN;
    }
                                                           
    isSimulationTarget |= ssRTWGenIsModelReferenceSimTarget(simstruct);
  }

  
  
  /* Number of expected parameters */
  ssSetNumSFcnParams(simstruct, 2);
  #if defined(MATLAB_MEX_FILE)

  if (ssGetSFcnParamsCount(simstruct) == 2) {
    /*
     * If the number of expected input parameters is not equal
     * to the number of parameters entered in the dialog box return.
     * Simulink will generate an error indicating that there is a
     * parameter mismatch.
     */
    mdlCheckParameters(simstruct);
    if (ssGetErrorStatus(simstruct) != NULL) {
      STACKTRC_RETURN;
    }
  } else {
    /* Return if number of expected != number of actual parameters */
    STACKTRC_RETURN;
  }

  #endif
  ssSetSFcnParamTunable(simstruct, 0, 0);  //init: Ts_param 
  ssSetSFcnParamTunable(simstruct, 1, 0);  //init: Tstep 

#if defined(MATLAB_MEX_FILE)

  if (ssGetNumSFcnParams(simstruct) == ssGetSFcnParamsCount(simstruct)) {
    /*
     * If the number of expected input parameters is not equal
     * to the number of parameters entered in the dialog box return.
     * Simulink will generate an error indicating that there is a
     * parameter mismatch.
     */
    //TODO necessary?
    //mdlCheckParameters(simstruct);
    if (ssGetErrorStatus(simstruct) != NULL) {
      testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
      STACKTRC_RETURN;
    }
  } else {
    /* Return if number of expected != number of actual parameters */
    testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
    STACKTRC_RETURN;
  }

#endif

  
  //Dwork is needed
  if (!ssSetNumDWork(simstruct, 1)) { //3 Dwork Pointer, 0 for Bus indices, 1 for thiz handle, 2 for thiz 
    STACKTRC_RETURN; }

  /*
   * Configure the dwork 0, 2 (thiz)
   */
  ssSetDWorkDataType(simstruct, 0, SS_UINT32);  //for handle thiz
  ssSetDWorkUsageType(simstruct, 0, SS_DWORK_USED_AS_DWORK);
  ssSetDWorkName(simstruct, 0, "thiz_h");
  ssSetDWorkWidth(simstruct, 0, 1);   
  ssSetDWorkComplexSignal(simstruct, 0, COMPLEX_NO);

  
  //This should be set true, because all FBs can be used as multiple instances.
  ssSupportsMultipleExecInstances(simstruct, true);

  //The sample times should be port based. The handle ports are associated to Tstep because execution order. 
  //
  
  //jzTc: get Tstep Parameter value
  { const mxArray* TsteppG = ssGetSFcnParam(simstruct, 1);  //Tstep
    double* TsteppG1 = mxGetPr(TsteppG);  //assume Parameter is double, get the double (real_T)
    if(TsteppG1 !=null) {
      Tstep = *TsteppG1;
    } else { //Note: Simulink: nevertheless mxGetPr does not check whether it is a number or not. :-( It reads a faulty number.
      ssSetErrorStatus(simstruct,"Problem reading Tstep as parameter 1, should be a number");
      testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
      STACKTRC_RETURN;
    }
  }

   ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES);  //Tstep may be given as parameter and assigend to ports.

  
  
  
  
  if(Tinit == 0) { //not initialized up to now
    //Gets the value of the Tinit time from the global workspace variable Tinit.
    mxArray* args[2] = {0};                         
    mxArray* out = null;
    args[0] = mxCreateString("base");
    args[1] = mxCreateString("Tinit");
    mxArray* exc = mexCallMATLABWithTrap(1, &out, 2, args, "evalin"); //eval in workspace base
    if(exc !=null) { //Tinit found:
      mxDestroyArray(exc); 
      mxDestroyArray(args[0]); mxDestroyArray(args[1]); mxDestroyArray(out); 
      ssSetErrorStatus(simstruct,"The workspace should contain a variable 'Tinit' with a real value.");
      STACKTRC_RETURN;
    } else  {
      Tinit = *mxGetPr(out);   //gets the double result 
      mxDestroyArray(args[0]); mxDestroyArray(args[1]); mxDestroyArray(out); 
    }
  }

  //Invoke the @simulink defPortTypes - routine (...) to determine port types from paramater of the FB:
  memset(&__defPortTypes,0, sizeof(__defPortTypes)); //clean, maybe set from other instance or usage before.
  DefPortTypes_emC* _fbInfo_ = &__defPortTypes.head; //jzTc.initPorts() - reference variable 
  Entry_DefPortType_emC* _entryPortTypes = __defPortTypes.head.entries;  
  ctor_DefPortTypes_emC(_fbInfo_, 64);
  setPortInfo(simstruct, _fbInfo_, kSetFromArg_EPropagatePortTypes_emC);  //fill the local array with port info.

  //Set the number of input ports:
  if (!ssSetNumInputPorts(simstruct, _fbInfo_->nrofInputs)) {
    STACKTRC_RETURN; }
  for(int ixPort = 0; ixPort < _fbInfo_->nrofInputs; ++ixPort) {
    Entry_DefPortType_emC const* portInfo = &_fbInfo_->entries[ixPort];
    // Configure the input port
    SmlkPortInfo info = {0};  //check whether (...) has set an information about the port type and size
    getPortInfo(&info, portInfo);  //check whether type is determined. Note: Pointer type arithmetic
    { //jzTc: non bus input initializing:
      ssSetInputPortDataType(simstruct, ixPort, info.type);
      ssSetInputPortWidth(simstruct, ixPort, info.arraySize);
      ssSetInputPortComplexSignal(simstruct, ixPort, info.complexity);
    }
    ssSetInputPortSampleTime(simstruct, ixPort, portInfo->newDefined_Tstep_Tinit & mInputInit_Entry_DefPortType_emC ? Tinit : Tstep);   //together with ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES)
    ssSetInputPortOffsetTime(simstruct, ixPort, 0);
    ssSetInputPortAcceptExprInRTW(simstruct, ixPort, 1);
    ssSetInputPortOverWritable(simstruct, ixPort, 1);
    ssSetInputPortDirectFeedThrough(simstruct, ixPort, portInfo->newDefined_Tstep_Tinit & mInputUpd_Entry_DefPortType_emC ? 0 : 1);  //upd input with 0      
    ssSetInputPortOptimOpts(simstruct, ixPort, SS_NOT_REUSABLE_AND_LOCAL);
    ssSetInputPortRequiredContiguous(simstruct, ixPort, 1);
  }
  
  //Set the number of output ports:
  if (!ssSetNumOutputPorts(simstruct, _fbInfo_->nrofOutputs)) {
    STACKTRC_RETURN; }

  for(int ixPort = 0; ixPort < _fbInfo_->nrofOutputs; ++ixPort) {
    Entry_DefPortType_emC const* portInfo = &_fbInfo_->entries[ixPort + _fbInfo_->nrofInputs ];
    // Configure the output port
    SmlkPortInfo info = {0};  //check whether (...) has set an information about the port type and size
    getPortInfo(&info, portInfo);  //check whether type is determined. Note: Pointer type arithmetic
    { //jzTc: non bus output initializing:
      ssSetOutputPortDataType(simstruct, ixPort, info.type);
      ssSetOutputPortWidth(simstruct, ixPort, info.arraySize);
      ssSetOutputPortComplexSignal(simstruct, ixPort, info.complexity);
    }
    ssSetOutputPortSampleTime(simstruct, ixPort, portInfo->newDefined_Tstep_Tinit & mInit_Entry_DefPortType_emC ? Tinit : Tstep);   //together with ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES)
    ssSetOutputPortOffsetTime(simstruct, ixPort, 0);
    //ssSetOutputPortAcceptExprInRTW(simstruct, ixPort, 1);
    //ssSetOutputPortOverWritable(simstruct, ixPort, 1);
    //ssSetOutputPortOptimOpts(simstruct, ixPort, SS_NOT_REUSABLE_AND_LOCAL);
    //ssSetOutputPortRequiredContiguous(simstruct, ixPort, 1);
  }
  

  /*
   * Register reserved identifiers to avoid name conflict
   */
  if (ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) {
    /*
     * Register reserved identifier for InitializeConditionsFcnSpec
     */
    //it seems to be not necessary, the S-functions works proper.
    //ssRegMdlInfo(simstruct, "ctor_xyz", MDL_INFO_ID_RESERVED, 0, 0, ssGetPath(simstruct));
  }

  /*
   * This S-function can be used in referenced model simulating in normal mode.
   */
  ssSetModelReferenceNormalModeSupport(simstruct, MDL_START_AND_MDL_PROCESS_PARAMS_OK);

  //The sample times should be port based. The handle ports are associated to Tstep because execution order. 
  //
  /*
   * Set the compliance with the SimState feature.
   */
  ssSetSimStateCompliance(simstruct, USE_DEFAULT_SIM_STATE);

  /*
   * All options have the form SS_OPTION_<name> and are documented in                
   * matlabroot/simulink/include/simstruc.h. The options should be
   * bitwise or'd together as in
   *   ssSetOptions(simstruct, (SS_OPTION_name1 | SS_OPTION_name2))
   */
  ssSetOptions( simstruct,
                SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
                SS_OPTION_EXCEPTION_FREE_CODE |
                SS_OPTION_WORKS_WITH_CODE_REUSE |
                SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
                SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
                //| SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED
              );

#if defined(MATLAB_MEX_FILE)                                                                                                 

  if ((ssGetSimMode(simstruct)!=SS_SIMMODE_SIZES_CALL_ONLY) && !ssRTWGenIsCodeGen(simstruct)) {
    /* Verify Data Type consistency with specification */
    CheckDataTypes(simstruct);
  }

#endif

  //TODO necessary ? ssSetSimulinkVersionGeneratedIn(simstruct, "8.7");
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "unexpected Exception: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;
}



//
//Set sample time of ports with INHERITED_SAMPLE_TIME.
//It determines the step sample time.
//This routine is invoked only if PORT_BASED_SAMPLE_TIMES are set. It may be need as information for multiple rate blocks too.
//
#define MDL_SET_INPUT_PORT_SAMPLE_TIME 
//This method is used to determine the sample time of that input ports they were set to INHERITED_SAMPLE_TIME
void mdlSetInputPortSampleTime(SimStruct *simstruct, int_T port, real_T sampleTime, real_T offsetTime)
{ int ix;
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  ssSetInputPortSampleTime(simstruct, port, sampleTime);
  ssSetInputPortOffsetTime(simstruct, port, offsetTime);
}


#define MDL_SET_OUTPUT_PORT_SAMPLE_TIME
//This method is used to determine the sample time of that output ports they were set to INHERITED_SAMPLE_TIME
void mdlSetOutputPortSampleTime(SimStruct *simstruct, int_T port, real_T sampleTime, real_T offsetTime)
{
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  ssSetOutputPortSampleTime(simstruct, port, sampleTime);
  ssSetOutputPortOffsetTime(simstruct, port, offsetTime);
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
}



#if defined(MATLAB_MEX_FILE)

#define MDL_SET_INPUT_PORT_DATA_TYPE
#define MDL_SET_OUTPUT_PORT_DATA_TYPE
void mdlSetInputPortDataType(SimStruct *simstruct, int_T port, DTypeId id)
{ ssSetInputPortDataType(simstruct, port, id);
}

void mdlSetOutputPortDataType(SimStruct *simstruct, int_T port, DTypeId id)
{ ssSetOutputPortDataType(simstruct, port, id);
  //in manually written routines the user may store the definition of this special port, 
  //use it for own algorithm and determine related ports.
  //In the jzTc generation this is done by invocation of the "@simulink defPortTypes" routine
  //in the Sfunction routine "mdlSetDefaultPortDataTypes". There the current situation of port types is gathered and delivered. 
}



#define MDL_SET_DEFAULT_PORT_DATA_TYPES
//set the ports which were note determined by wiring in the model.
//It is possible that the _entryPortTypes_SfuncGLOBAL structure are filled with the associated port.
//Then use it. Else default is int32
void mdlSetDefaultPortDataTypes(SimStruct *simstruct)
{ 
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_ENTRY("mdlSetDefaultPortDataTypes");
  TRY {
  int ix;
  int nrofInputs = ssGetNumInputPorts(simstruct);
  int nrofOutputs = ssGetNumOutputPorts(simstruct);
  
  for(ix = 0; ix < nrofInputs; ++ix) {
    if(ssGetInputPortDataType(simstruct, ix) == DYNAMICALLY_TYPED) {
      int type;
      
      
      type = SS_INT32;
      
      ssSetInputPortDataType(simstruct, ix, type);
    }
  }	
  for(ix = 0; ix < nrofOutputs; ++ix) {
    if(ssGetOutputPortDataType(simstruct, ix) == DYNAMICALLY_TYPED) {
      int type;
      
      type = SS_INT32;
      
      ssSetOutputPortDataType(simstruct, ix, type);
    }
  }	
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "Unexpected Exception: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;
}


#define MDL_SET_INPUT_PORT_DIMENSION_INFO
#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
static void mdlSetInputPortDimensionInfo(SimStruct *simstruct, int_T port, const DimsInfo_T *dimsInfo)
{
	if (!ssSetInputPortDimensionInfo(simstruct, port, dimsInfo)) return;
}

static void mdlSetOutputPortDimensionInfo(SimStruct *simstruct, int_T port, const DimsInfo_T *dimsInfo)
{
	if (!ssSetOutputPortDimensionInfo(simstruct, port, dimsInfo)) return;
}

void mdlSetDefaultPortDimensionInfo(SimStruct *simstruct)
{ int ix;
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_ENTRY("mdlSetDefaultPortDimensionInfo");
  TRY{ 
  int nrofInputs = ssGetNumInputPorts(simstruct);
  int nrofOutputs = ssGetNumOutputPorts(simstruct);
  
  for(ix = 0; ix < nrofInputs; ++ix) {
    if(ssGetInputPortWidth(simstruct, ix) == DYNAMICALLY_SIZED) {
      
      int dim = 1;
      
      ssSetInputPortWidth(simstruct, ix, dim);
    }
  }	
  for(ix = 0; ix < nrofOutputs; ++ix) {
    if(ssGetOutputPortWidth(simstruct, ix) == DYNAMICALLY_SIZED) {
      
      int dim = 1;
      
      ssSetOutputPortWidth(simstruct, ix, dim);
    }
  }	
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "Unexpected Exception: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;
}



#define MDL_SET_INPUT_PORT_COMPLEX_SIGNAL
#define MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL
void mdlSetInputPortComplexSignal(SimStruct *simstruct, int_T port,  CSignal_T csig)
{
  ssSetInputPortComplexSignal(simstruct, port, csig);
}

void mdlSetOutputPortComplexSignal(SimStruct *simstruct, int_T port,  CSignal_T csig)
{
  ssSetOutputPortComplexSignal(simstruct, port, csig);
}

#define MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS
void mdlSetDefaultPortComplexSignals(SimStruct *simstruct)
{ int ix;
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_ENTRY("mdlSetDefaultPortComplexSignals");
  TRY {
  int nrofInputs = ssGetNumInputPorts(simstruct);
  int nrofOutputs = ssGetNumOutputPorts(simstruct);
  
  for(ix = 0; ix < nrofInputs; ++ix) {
    if(ssGetInputPortComplexSignal(simstruct, ix) != COMPLEX_YES) {
      
      int complexity = COMPLEX_NO;
      
      ssSetInputPortComplexSignal(simstruct, ix, complexity);
    }
  }	
  for(ix = 0; ix < nrofOutputs; ++ix) {
    if(ssGetOutputPortComplexSignal(simstruct, ix) != COMPLEX_YES) {
      
      int complexity = COMPLEX_NO;
      
      ssSetOutputPortComplexSignal(simstruct, ix, complexity);
    }
  }	
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "Unexpected Exception: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;
}

#endif //MATLAB_MEX_FILE





#define MDL_INITIALIZE_SAMPLE_TIMES
/* Function: mdlInitializeSampleTimes =====================================
 * Abstract:
 *    This function is used to specify the sample time(s) for your
 *    S-function. You must register the same number of sample times as
 *    specified in ssSetNumSampleTimes.
 */
static void mdlInitializeSampleTimes(SimStruct *simstruct)
{ //double TstepPort, ToffsPort;
  //Tinit sample time from port
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_ENTRY("mdlInitializeSampleTimes");
  TRY { 
  //Port based sample times:
  //Hint: Also if sample times are given the FB is designated as Port based, 
  //but the sample times are associated to the ports. This is necessary for more as one sample time.
  memset(&__defPortTypes,0, sizeof(__defPortTypes)); //clean, maybe set from other instance or usage before.
  ctor_DefPortTypes_emC(&__defPortTypes.head, 64);
  setPortInfo(simstruct, &__defPortTypes.head, kSetType_EPropagatePortTypes_emC);
  
  //sets all yet not determined sample times. Ports can be disconnected. Only one inherited sample time.
  { double Tstep=INHERITED_SAMPLE_TIME, ToffsStep=0;
    int ix;
    //search first port with given Tstep, break on found.
    for(ix = 0; ix < 1; ++ix) {
      if(ssGetInputPortSampleTime(simstruct, ix) != INHERITED_SAMPLE_TIME) {
        Tstep = ssGetInputPortSampleTime(simstruct, ix);
        ToffsStep = ssGetInputPortOffsetTime(simstruct, ix);
        break;
    } } 
    if(Tstep == INHERITED_SAMPLE_TIME){
      for(ix = 0; ix < 1; ++ix) {
      if(ssGetOutputPortSampleTime(simstruct, ix) != INHERITED_SAMPLE_TIME) {
        Tstep = ssGetOutputPortSampleTime(simstruct, ix);
        ToffsStep = ssGetOutputPortOffsetTime(simstruct, ix);
        break;
      } }
    }
    //transfer to all ports of Tstep input which are not determined yet.
    for(ix = 0; ix < 1; ++ix) {
      if(ssGetInputPortSampleTime(simstruct, ix) == INHERITED_SAMPLE_TIME) {
        ssSetInputPortSampleTime(simstruct, ix, Tstep);
        ssSetInputPortOffsetTime(simstruct, ix, ToffsStep);
    } } 
    for(ix = 0; ix < 1; ++ix) {
    if(ssGetOutputPortSampleTime(simstruct, ix) == INHERITED_SAMPLE_TIME) {
      ssSetOutputPortSampleTime(simstruct, ix, Tstep);
      ssSetOutputPortOffsetTime(simstruct, ix, ToffsStep);
    } } 
  }
#if defined(ssSetModelReferenceSampleTimeDefaultInheritance)

  ssSetModelReferenceSampleTimeDefaultInheritance(simstruct);

#endif
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "Unexpected Exception: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;
  
}



#define MDL_SET_WORK_WIDTHS
#if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE)

/* Function: mdlSetWorkWidths =============================================
 * Abstract:
 *      The optional method, mdlSetWorkWidths is called after input port
 *      width, output port width, and sample times of the S-function have
 *      been determined to set any state and work vector sizes which are
 *      a function of the input, output, and/or sample times.
 *
 *      Run-time parameters are registered in this method using methods
 *      ssSetNumRunTimeParams, ssSetRunTimeParamInfo, and related methods.
 */
static void mdlSetWorkWidths(SimStruct *simstruct)
{
  

  ssSupportsMultipleExecInstances(simstruct, true);
}

#endif


#include <emC/Base/Handle_ptr64_emC.h>
#include <emC/Base/Handle_ptr64_TimeMeas_emC.h>



#define MDL_START
#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 *simstruct)
{
  int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_ENTRY("mdlStart_stepY_T1i_Ctrl_emC")
  TRY {
  
  if (isDWorkNeeded(simstruct)) {
    //
    //===============Get the address of the structure to convert handle values to pointer===============================
    //Note: If more as one instance of this FB will be created, the mdlStart is invoked for any instance.
    //      But there is only one static shMemHandle2Ptr. The first mdlStart creates it. Don't call twice!
    //       
    //
    char const* error = initTimeMeas_Handle2Ptr(1000);
    if(error !=null) {
      ssSetErrorStatus(simstruct, error); // Sfunc=stepY_T1i_Ctrl_emC");
    } else {
      
      
      //
      
  { //Allocates the memory for the bus data for the C-function.
    //The bus data are allocated for this instance especially. 
    //jzcmd: setBusInfo_mdlStart()-A
    char const* error;
    uint32 handle;
    int size1 = (int)sizeof(T1i_Ctrl_emC_s);
    void* ptr = calloc(size1+1024, 1);
    if (ptr==NULL) {
      ssSetErrorStatus(simstruct,"Unexpected error during the memory allocation for T1i_Ctrl_emC_s");
      STACKTRC_RETURN;
    }
    TRY {
      handle = registerPtr_Handle2Ptr(ptr, "ctor_T1i_Ctrl_emC");
    }_TRY;    
    CATCH(Exception, exc) {
    
      ssSetErrorStatus(simstruct,"handle registration faulty");
      STACKTRC_RETURN;
    }END_TRY;
    uint32* addr_handle = (uint32*) ssGetDWork(simstruct, 0);  //there is only one DWork, for thiz or thiz_y
    if(addr_handle !=null) {
      *addr_handle = handle;
    } else {
      ssSetErrorStatus(simstruct,"DWork(1) not existent:  ctor_T1i_Ctrl_emC");
    }
    //Structure is not based on ObjectJc, no CTOR_ObjectJc(...) generated.
    //
  }

    //jzTc-ctor-arg thiz:
    //T1i_Ctrl_emC_s** addr_thiz = (T1i_Ctrl_emC_s**)ssGetDWork(simstruct,1);  //jzTc: genCtor thiz
    //T1i_Ctrl_emC_s* thiz = *addr_thiz;
    T1i_Ctrl_emC_s* thiz = PTR_Handle2Ptr(*(uint32*)ssGetDWork(simstruct,0), T1i_Ctrl_emC_s);
    
    if(error ==null) {
      TRY {
        //jzTc: Call of the constructor:
        ctor_T1i_Ctrl_emC( thiz);
      }_TRY;
      CATCH(Exception, exc){
        int pos = strcpy_emC(errorbuffer, "unexpected ctor-Exception: ", sizeof(errorbuffer));          
        writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
        ssSetErrorStatus(simstruct, errorbuffer); 
      }
      END_TRY;
    }

    }
  }
  }_TRY;
  CATCH(Exception, exc){
    int pos = strcpy_emC(errorbuffer, "Unexpected Exception mdlStart: ", sizeof(errorbuffer));          
    writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
    ssSetErrorStatus(simstruct, errorbuffer); 
  }
  END_TRY;
  testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
  STACKTRC_RETURN;

}

#endif






/* Function: mdlUpdate ===================================================*/
#define MDL_UPDATE 
#if defined(MDL_UPDATE) && defined(MATLAB_MEX_FILE) 
static void mdlUpdate(SimStruct *simstruct, int_T tid)
{ if (isDWorkNeeded(simstruct)) {
  int st_index;  //steptime_index

  int ixInputStep =  0;
  int ixInputStep2 = 1;
  int ixInputInit =  1;
  //int ixPortOutputStep = 0 - 1;
  int ixPortOutputInit = 1 - 1;
  int ixInOutTstep = 0;
  int nrofInputs =   1;
  //
  //call param_T1i_Ctrl_emC(...) with port based sample time      
  if(ixInputInit < nrofInputs) { st_index = ssGetInputPortSampleTimeIndex(simstruct, ixInputInit); }
  else { st_index = ssGetOutputPortSampleTimeIndex(simstruct, ixPortOutputInit); }
  if( ssIsSampleHit(simstruct, st_index, tid)) { //use the Sfn-specific fastest port-based sample time. 
      //Tinit in update:    
      char const* error = null;
      uint32 hthiz = *(uint32*)ssGetDWork(simstruct, 0 );  //get handle stored in DWork in mdlStart(...)
      T1i_Ctrl_emC_s* thiz = PTR_Handle2Ptr(hthiz, T1i_Ctrl_emC_s);
       { 
        int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
        STACKTRC_ENTRY("mdlOutputs_init_param_T1i_Ctrl_emC");
        TRY {

        int ixInputPort = 1;
        //jzTc: get Parameter value
        const mxArray* Ts_param_addr = ssGetSFcnParam(simstruct, 0);  //reference in Simulink-data to the parameter
        double* Ts_param_v = (double*) mxGetData(Ts_param_addr);  //Parameter in simulink is always double, get the double (real_T)
        float Ts_param = 0;  //define the variable for parameter with neccesary type.
        if(Ts_param_v !=null) { //check, mxGetData returns null if there are no data. Usual it should be correct.
          Ts_param = (float) *Ts_param_v;  //convert Parameter to the necessary type
        }

        //jzTc: get Parameter value
        const mxArray* Tstep_addr = ssGetSFcnParam(simstruct, 1);  //reference in Simulink-data to the parameter
        double* Tstep_v = (double*) mxGetData(Tstep_addr);  //Parameter in simulink is always double, get the double (real_T)
        float Tstep = 0;  //define the variable for parameter with neccesary type.
        if(Tstep_v !=null) { //check, mxGetData returns null if there are no data. Usual it should be correct.
          Tstep = (float) *Tstep_v;  //convert Parameter to the necessary type
        }
    
        //invoke the routine with the prepared variable with same name as formal arguments.
        bool _bInit_ = param_T1i_Ctrl_emC(thiz, Ts_param, Tstep);
if(!_bInit_) { //check whether initialization was successfull
  //if not, set a global flag to false to repeat initialization (in generated code). 
  //Here: count the ctInit workspace variable. To check manually whether initialization is repeated.
  double ctInit = 0;
  mxArray* args[3] = {0};                         
  mxArray* array = null;
  args[0] = mxCreateString("base");
  args[1] = mxCreateString("smlk_ctInit");
  mxArray* error = mexCallMATLABWithTrap(1, &array, 2, args, "evalin"); //eval in workspace base
  if(error !=null) { //smlk_ctInit not found:
    mxDestroyArray(error);
  } else {
    ctInit = *mxGetPr(array);   //gets the value of the smlk_ctInit value (as copy)
  }
  ctInit +=1;  //counts non successfully init calls. If the counter is const, all init was done.
  //faulty: mxSetPr(array, ctInit);            //should rewrite, the ctInit ptr is only a local memory position.
  args[2] = mxCreateDoubleScalar(ctInit); 
  error = mexCallMATLABWithTrap(0, null, 3, args, "assignin"); //this rewrites. On error: systemException
  mxDestroyArray(args[0]); mxDestroyArray(args[1]); mxDestroyArray(args[2]); mxDestroyArray(array); 
  if(error !=null) { //smlk_ctInit not found:
    mxDestroyArray(error);
    ssSetErrorStatus(simstruct, "cannot write smlk_ctInit variable in the workspace"); 
  }
}

  //jzTc: postprepare outputs ...{Ts_param=Ts_param @0Tinit, Tstep=Tstep @1Tinit, x=x @0Tstep, y_y=y_y @0Tstep}thiz: Ts_param: Tstep:                                                             
        }_TRY;
        CATCH(Exception, exc){
          int pos = strcpy_emC(errorbuffer, "Unexpected Exception: ", sizeof(errorbuffer));          
          writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
          ssSetErrorStatus(simstruct, errorbuffer); 
        }
        END_TRY;
        STACKTRC_LEAVE;

        testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.  
      } //if initialized
    } //ssIsSampleHit Tinit

  } //isDWorkNeeded
}
#endif








/* Function: mdlOutputs ===================================================
 * Abstract:
 *    In this function, you compute the outputs of your S-function
 *    block. Generally outputs are placed in the output vector(s),
 *    ssGetOutputPortSignal.
 */
#define MDL_OUTPUT 
static void mdlOutputs(SimStruct *simstruct, int_T tid)
{ if (isDWorkNeeded(simstruct)) {
    //int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
    STACKTRC_ENTRY("mdlOutputs");
    

    int ixInputStep =  0;
    int ixInputStep2 = 1;
    int ixOutputStep = 0;
    int nrofInputs =   1;
    
    //Object-FB:  
    //params: ix-init = 0, ix-step = 0, nrof = 2  
    //input ports: ix-init = 0, ix-step2 = 1, ix-step = 0, ix-upd = 1, ix-step2 = 1, nrof = 1  
    //output ports: thizInit = -1, thizStep = -1, ix-step = 0, ix-step2 = 1, nrof = 1, ix-init = 1  

    char const* error = null;

    //Object-FB, thiz from DWork[1], handle from DWork[0]:    
    //T1i_Ctrl_emC_s* thiz = *(T1i_Ctrl_emC_s **)ssGetDWork(simstruct, 1 );
    uint32 hthiz = *(uint32*)ssGetDWork(simstruct, 0 );  //get handle stored in DWork in mdlStart(...)
    T1i_Ctrl_emC_s* thiz = PTR_Handle2Ptr(hthiz, T1i_Ctrl_emC_s);
    //jzTc:readOutput jzTc-2 for y_y: SS_INT16
    int16 * y_y = (int16 *)ssGetOutputPortSignal(simstruct, 0);  //gets the address of the output data in Simulink data area.

    //Port based sample time nrofInputs = 1, ixInputStep = 0, ixOutputStep = 0  
    int sti;
    time_T time_SmlkStep_ = ssGetT(simstruct);

    if (ssIsSampleHit(simstruct, ssGetInputPortSampleTimeIndex(simstruct, 0), tid)) { //use the Sfn-specific fastest port-based sample time. 
      //Note: The Tinit is not used in the Sfn because the initialization should be done in the first steps, not in about 100 ms.
      //      The Tinit step time is only used for generated target code. That step routine is used for initializing the system.
      //      All other step times provide their data also in the fastest one. 
      //

      {  //jzTc: call step-B

        int ixInputPort = 0;
      //Step...( ... , T1i_Ctrl_emC_s thiz, ...)
      //Step...( ... , int16 x, ...)
          //JZtc: The input port supplies the address of the scalar value, read the value.      
          int16 const* x_addr = (int16 const*)ssGetInputPortSignal(simstruct, 0); //ixInputPort);  //JZtc:gets the address of the input data in Simulink data area.
          int16 x = *x_addr;  //JZtc: for single elements.

          ixInputPort +=1; 
      //Step...( ... , int16 y_y, ...)
      //invoke the Step-routine: jzTc: prepareAndCall()-E
        stepY_T1i_Ctrl_emC(thiz, x, y_y);

  //jzTc: postprepare outputs ...{Ts_param=Ts_param @0Tinit, Tstep=Tstep @1Tinit, x=x @0Tstep, y_y=y_y @0Tstep}thiz: x: y_y: 
      //Pointer type output but not defined as pointer to pointer.
      //Do nothing. ignore output values. It is not able to handle.
    //                                                                                         
   } } //

    {  //check init time. NOTE: It is possible that the same call of outputs is for Tinit and Tstep.    
      sti = 0; //TODO not used, get sample time from input or output: ssGetOutputPortSampleTimeIndex(simstruct,0);  //check the output 0, it is for init
      if (ssIsSampleHit(simstruct, sti, tid)) {
        //Init routine in the only 1 sample time:
        sti +=1;
        //No, in step time: param_T1i_Ctrl_emC(thiz, Ts_param, Tstep);
    } }

    
    //testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
    STACKTRC_RETURN;
  }
}










    
/* Function: mdlTerminate =================================================
 * Abstract:
 *    In this function, you should perform any actions that are necessary
 *    at the termination of a simulation.
 */
static void mdlTerminate(SimStruct *simstruct)
{
  if (isDWorkNeeded(simstruct)) {
    STACKTRC_ENTRY("mdlTerminate");
    TRY{ 
      int checkStack = buildCheckStack_emC(&simstruct, 0x10000);  //addr of an argument is the highest one.
    
      //Free the memory for the T1i_Ctrl_emC_s data //jzcmd: freeMem_mdlTerminate()-A
      //T1i_Ctrl_emC_s** addr_thiz = (T1i_Ctrl_emC_s**)ssGetDWork(simstruct,1); 
      T1i_Ctrl_emC_s* thiz = PTRclr_Handle2Ptr(*(uint32*)ssGetDWork(simstruct,0), T1i_Ctrl_emC_s); //*addr_thiz;
      if(thiz != NULL) {
        CALLINE; free(thiz);
      }
      //close the sharedmem handle:
      //Note: If more as one instance of this FB was created, the mdlTerminate is invoked for any instance.
      //      But there is only one static shMemHandle2Ptr. The first mdlTerminate removes it.
      //       
      CALLINE; close_Hande2Ptr();

      testCheckStack_emC(&simstruct, checkStack, 0x10000);  //addr of an argument is the highest one.
    }_TRY;
    CATCH(Exception, exc){
      int pos = strcpy_emC(errorbuffer, "Unexpected Exception mdlTerminate: ", sizeof(errorbuffer));          
      writeException(errorbuffer +pos, sizeof(errorbuffer)-pos, exc, __FILE__, __LINE__, _thCxt);
      ssSetErrorStatus(simstruct, errorbuffer); 
    }
    END_TRY;
    STACKTRC_RETURN;
  }
}







#define MDL_RTW
#if defined(MATLAB_MEX_FILE) && defined(MDL_RTW)

/* Function: mdlRTW =======================================================
 * Abstract:
 *    This function is called when Simulink Coder is generating
 *    the model.rtw file.
 */
static void mdlRTW(SimStruct *simstruct)
{ 
  //Initialize the DefPortTypes_emC from the given operations. 
  memset(&__defPortTypes,0, sizeof(__defPortTypes)); //clean, maybe set from other instance or usage before.
  DefPortTypes_emC* portInfo_tlcParam = &__defPortTypes.head; //jzTc.ssWriteRTWParamSettings-a() - reference variable 
  ctor_DefPortTypes_emC(portInfo_tlcParam, 64);
  setPortInfo(simstruct, portInfo_tlcParam, kRun_EPropagatePortTypes_emC);  //fill the local array with port info.

  int zBuffer_tlcParam = 1200;     
  char buffer_tlcParam[1200] = {0}; //enough space for all String parameter.
  char* pBuffer = buffer_tlcParam; 
  //checked: float Ts_param

  //checked: float Tstep

  //register all non tunable parameters. They are gotten in tlc via access to 'SFcnParamSettings.NAME'
  if (!ssWriteRTWParamSettings(simstruct, 2 +3   //jzTc: 3 param for mInput...
    , SSWRITE_VALUE_NUM, "Ts_param", mxGetPr(ssGetSFcnParam(simstruct, 0))[0]  
    , SSWRITE_VALUE_NUM, "Tstep", mxGetPr(ssGetSFcnParam(simstruct, 1))[0]  
  , SSWRITE_VALUE_DTYPE_NUM, "mInputInit" , &portInfo_tlcParam->mInputDataInit, DTINFO(SS_UINT32, false)
  , SSWRITE_VALUE_DTYPE_NUM, "mInputUpd" , &portInfo_tlcParam->mInputUpd, DTINFO(SS_UINT32, false)
  , SSWRITE_VALUE_DTYPE_NUM, "mInputStep" , &portInfo_tlcParam->mInputStep, DTINFO(SS_UINT32, false)
  ) ) { return;  } //an error occured

}

#endif


/* Function: CheckDataTypeChecksum ======================================
 * Abstract:
 *    CheckDataTypeChecksum invokes a MATLAB helper for checking the consistency
 *    between the data type definition used when this S-Function was generated
 *    and the data type used when calling the S-Function.
 */
static int_T CheckDataTypeChecksum(SimStruct *simstruct, const char* dtypeName, uint32_T*
  chkRef)
{
  mxArray *plhs[1] = { NULL };

  mxArray *prhs[3] = {0};
  mxArray *err = NULL;
  const char *bpath = ssGetPath(simstruct);
  int_T status = -1;
  prhs[0] = mxCreateString(bpath);
  prhs[1] = mxCreateString(dtypeName);
  prhs[2] = mxCreateDoubleMatrix(1, 4, mxREAL);
  mxGetPr(prhs[2])[0] = chkRef[0];
  mxGetPr(prhs[2])[1] = chkRef[1];
  mxGetPr(prhs[2])[2] = chkRef[2];
  mxGetPr(prhs[2])[3] = chkRef[3];
  err = mexCallMATLABWithTrap(1, plhs, 3, prhs,
    "legacycode.LCT.getOrCompareDataTypeChecksum");
  mxDestroyArray(prhs[0]);
  mxDestroyArray(prhs[1]);
  mxDestroyArray(prhs[2]);
  if (err==NULL && plhs[0]!=NULL) {
    status = mxIsEmpty(plhs[0]) ? -1 : (int_T) (mxGetScalar(plhs[0]) != 0);
    mxDestroyArray(plhs[0]);
  }

  return status;
}













/* Function: CheckDataTypes =============================================
 * Abstract:
 *    CheckDataTypes verifies data type consistency between the data type
 *    definition used when this S-Function was generated and the data type
 *    used when calling the S-Function.
 */
static void CheckDataTypes(SimStruct *simstruct)
{
 
  //TODO check with known bus element names and their types.
  //from where is the check sum?
  /* Verify Bus/StructType 'Param_Orthi_FB', specification * /
  {
    uint32_T chk[] = { 4189326214, 1854717099, 3653914067, 1841847726 };

    int_T status;
    status = CheckDataTypeChecksum(simstruct, "Param_Orthi_FB", &chk[0]);
    if (status==-1) {
      ssSetErrorStatus(simstruct,
                       "Unexpected error when checking the validity of the Simulink Bus/StructType 'Param_Orthi_FB'");
    } else if (status==0) {
      ssSetErrorStatus(simstruct,
                       "The Simulink Bus/StructType 'Param_Orthi_FB' definition has changed since the S-Function was generated");
    }
  }
  TODO */
}











/* Function: GetRTWEnvironmentMode ========================================
 * Abstract:
 *   Must be called when ssRTWGenIsCodeGen(S)==true. This function
 *   returns the code generation mode:
 *       -1 if an error occurred
 *        0 for standalone code generation target
 *        1 for simulation target (Accelerator, RTW-SFcn,...)
 */
static int_T GetRTWEnvironmentMode(SimStruct *S)
{
    int_T status;
    mxArray * err = null;
    mxArray *plhs[1] = {0};
    mxArray *prhs[1];

    /* Get the name of the Simulink block diagram */
    prhs[0] = mxCreateString(ssGetModelName(ssGetRootSS(S)));
    plhs[0] = NULL;

    /* Call "isSimulationTarget = rtwenvironmentmode(modelName)" in MATLAB */
    err = mexCallMATLABWithTrap(1, plhs, 1, prhs, "rtwenvironmentmode");

    mxDestroyArray(prhs[0]);

    /* Set the error status if an error occurred */
    if (err) {
        if (plhs[0]) {
            mxDestroyArray(plhs[0]);
            plhs[0] = NULL;
        } /* if: } */
        ssSetErrorStatus(S, "Unknown error during call to 'rtwenvironmentmode'.");
        return -1;
    } /* if */

    /* Get the value returned by rtwenvironmentmode(modelName) */
    if (plhs[0]) {
        status = (int_T) (mxGetScalar(plhs[0]) != 0);
        mxDestroyArray(plhs[0]);
        plhs[0] = NULL;
    } /* if */

    return status;
}



void errorSystem_emC_  (  int errorCode, const char* description, int value1, int value2, char const* file, int line) {
  //TODO
  
}



/*
 * Required S-function trailer
 */
#ifdef MATLAB_MEX_FILE
# include "simulink.c"
#else
# include "cg_sfun.h"
#endif

