/*C-MEX S-function wrapper setLim_PIDf_Ctrl_emC_SfOp.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                setLim_PIDf_Ctrl_emC_SfOp
#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/Base/Object_emC.h>   //The ObjectJc is used as base class for all struct
//#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/PIDf_Ctrl_emC.h"


/**Properties of this SFunctionBlock:
 * InPorts:
 * * 0 lim: float (Tstep, mInputStep_Entry_DefPortType_emC)
 * * 1 thiz: PIDf_Ctrl_emC_s (Tstep, mInputStep_Entry_DefPortType_emC) 
 * OutPorts: 
 * Parameters: 
 * Given routines and args from header:
 * basedOnObjectJc: base.obj
 * dports: 
 * ctor: 
 * dtor: 
 * init: 

 * step: setLim_PIDf_Ctrl_emC
 * updt: 
 * tlcParam: 
 * 
 * Operation-FB
 * step times: Block based sample time
 * params: ix-step = 0, ix-upd = 0, ix-step2 = 0, ix-init = 0, ix-ctor = 0, nrof = 0  
 *   nrofParamsNoTunable = 0, nrofParamsTunable = 0, nrofParams = 0, maskTunable =        0
 * input ports: ix-step = 0, ix-upd = 2, ix-step2 = 2, ix-init = 2, nrof = 2  
 * input thiz: = 1
 * output ports: ix-step = 0, ix-init = 0, nrof = 0  
 * 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);



//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 = 2;
  _fbInfo_->ixInputUpd = 2;
  _fbInfo_->ixInputInit = 2;
  _fbInfo_->ixInputVarg = 2;
  _fbInfo_->ixOutputStep = 2 + 0;
  _fbInfo_->ixOutputStep2 = 2 + 0;
  _fbInfo_->ixOutputInit = 2 + 0;
  _fbInfo_->ixOutputVarg = 0;
  _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 <<2) -1;
  int mInputStep2 =       ((1 <<2) -1) & ~((1 <<2) -1);
  _fbInfo_->mInputUpd =   ((1 <<2) -1) & ~((1 <<2) -1);
  _fbInfo_->mInputInit = ((1 <<2) -1) & ~((1 <<2) -1);
  _fbInfo_->mOutputStep = ((1 <<0) -1);
  _fbInfo_->mOutputInit =((1 <<0) -1) & ~((1 <<0) -1);
  if(_cause_ == kSetFromArg_EPropagatePortTypes_emC) {
    _fbInfo_->nrofInputs = 2;      //read without regarding variable nrof ports 
    _fbInfo_->nrofOutputs = 0;
    
    //jzTc:set_DefPortTypes_emC(...) from all routines. 
    set_DefPortTypes_emC(_fbInfo_, 0, 'F', "lim", null, "float", 0, mInputStep_Entry_DefPortType_emC);  // lim
    set_DefPortTypes_emC(_fbInfo_, 1, 'H', "thiz", null, "PIDf_Ctrl_emC_s", 0, mInputStep_Entry_DefPortType_emC);  // PIDf_Ctrl_emC_s* thiz
  } 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);
  }

  
  
  ssSetNumSFcnParams(simstruct, 0);  //no Parameters, no ctor

#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

  
  
  //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. 
  //
  
  ssSetNumSampleTimes(simstruct, 1); //maybe Tstep is given, or inherited. Block based sample time.

  
  
  
  
  //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
                
              );

#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 { 
      ssSetSampleTime(simstruct, 0, INHERITED_SAMPLE_TIME) ;
      ssSetOffsetTime(simstruct, 0, 0) ;

#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_setLim_PIDf_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=setLim_PIDf_Ctrl_emC");
    } else {
      
      
      //
      
    }
  }
  }_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: 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 = 2;
    int ixOutputStep = 0;
    int nrofInputs =   2;
    
    //Operation-FB:  
    //nrof params = 0,  nrof input ports = 2, nrof output ports = 0  

    char const* error = null;
          //thiz is a handle-reference anytime.
          uint32 thiz_Handle = *(uint32*)ssGetInputPortSignal(simstruct, 2-1);  //thiz-input-handle from last input.
          //uint32 thiz_Handle = *(uint32*)ssGetInputPortSignal(simstruct, 0);  //thiz-input-handle from first input.
           PIDf_Ctrl_emC_s* thiz_Ptr;  //
           PIDf_Ctrl_emC_s* thiz;  //

          {
            thiz_Ptr = (PIDf_Ctrl_emC_s*) ptr_Handle2Ptr(thiz_Handle);
            //error = getPtr_Handle2Ptr(thiz_Handle, (void**)(&(thiz_Ptr)));
            //if(error) { 
            //  ssSetErrorStatus(simstruct, "Handle faulty, abort: Sfunc=setLim_PIDf_Ctrl_emC on thiz");
            //  return;
            //}
          }
          if(thiz_Ptr != null && ((intptr_t)thiz_Ptr) != -1) {
            //don't check only if null, null is admissable, it is returned from getPtr_Handle2Ptr(...) if handle == -1
            //A handle input should based on ObjectJc anyway. To prevent errors on faulty handle values, check whether the ObjectJc is correct. 
            bool ok = checkStrict_ObjectJc((ObjectJc*)(thiz_Ptr), /*sizeof(PIDf_Ctrl_emC_s)*/0, null, 0);
            if( !ok) {
              ssSetErrorStatus(simstruct, "The handle is faulty");
              return;
            }
            { 
              if(!instanceof_s_ObjectJc((ObjectJc*)(thiz_Ptr), "PIDf_Ctrl_emC")) {
                ClassJc const* argType = getClass_ObjectJc((ObjectJc*)thiz_Ptr);
                strcpy_emC(errorbuffer, "faulty reference type in Sfunc=setLim_PIDf_Ctrl_emC on thiz. Expected: PIDf_Ctrl_emC, given: ", sizeof(errorbuffer));
                int zBuffer = strnlen_emC(errorbuffer, sizeof(errorbuffer));
                if(zBuffer >= (sizeof(errorbuffer) - sizeof(argType->name))) {  //sizeof(ClassJc::name) should have place
                  zBuffer = (sizeof(errorbuffer) - sizeof(argType->name))-1;    //Note C: sizeof(argType->name) is correct though argType == null
                }
                char const* argTypeName = argType == null? "--no-Reflection--" : argType->name; 
                strncpy_emC(errorbuffer+zBuffer, argTypeName, sizeof(argType->name));  //NOTE: name may not 0-terminated. 
                ssSetErrorStatus(simstruct, errorbuffer);
                return;
            } }
          } //else: thiz_Ptr == null || -1 is not checked.
          //

          thiz = thiz_Ptr;

    //Operation-FB, no ctor, only one step time
    //time_T time_SmlkStep_ = ssGetT(simstruct);  //time2
    if( thiz != null && isInitialized_ObjectJc((ObjectJc*)thiz) ) {  //jzTc: call step-C  //JzTc: only Tstep
        int ixInputPort = 0;
      //Step...( ... , PIDf_Ctrl_emC_s thiz, ...)
      //Step...( ... , float lim, ...)
          //JZtc: The input port supplies the address of the scalar value, read the value.      
          float const* lim_addr = (float const*)ssGetInputPortSignal(simstruct, 0); //ixInputPort);  //JZtc:gets the address of the input data in Simulink data area.
          float lim = *lim_addr;  //JZtc: for single elements.

          ixInputPort +=1; 
      //invoke the Step-routine: jzTc: prepareAndCall()-E
        setLim_PIDf_Ctrl_emC(thiz, lim);

  //jzTc: postprepare outputs ...{lim=lim @0Tstep, thiz=thiz @1Tstep}thiz: lim: 
    }

    
    //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.
    
      //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)
{ 
}

#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

