示例#1
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys(); // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments.
  if(nrhs != 2) {
    TT_MEX_ERROR("Error using ==> ttAnalogOut\nWrong number of input arguments.");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("Error using ==> ttAnalogOut\nIllegal output channel.");
    return;
  }

  if (!mxIsDoubleScalar(prhs[1])) {
    TT_MEX_ERROR("Error using ==> ttAnalogOut\nIllegal output value.");
    return;
  }

  int outpChan = (int) *mxGetPr(prhs[0]);
  double value = *mxGetPr(prhs[1]);

  ttAnalogOut(outpChan, value);
}
示例#2
0
static void mdlInitializeSizes(SimStruct *S)
{
  const mxArray *arg;

  ssSetNumSFcnParams(S, 3);  /* Number of expected parameters */
  if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    return; /* Parameter mismatch will be reported by Simulink */
  }
  
  if (!ssSetNumInputPorts(S, 0)) return;
  if (!ssSetNumOutputPorts(S, 7)) return;

  RMsys *rmsys = new RMsys;
  rmsys->trigger = 0.0;

  arg = ssGetSFcnParam(S, 0);
  if (mxIsDoubleScalar(arg)) {
    rmsys->networkNbr  = (int)*mxGetPr(arg);
  }
  arg = ssGetSFcnParam(S, 1);
  if (mxIsDoubleScalar(arg)) {
    rmsys->receiver  = (int)*mxGetPr(arg);
  }
  arg = ssGetSFcnParam(S, 2);
  if (mxIsDoubleScalar(arg)) {
    rmsys->outdim  = (int)*mxGetPr(arg);
  }

  /* Output Ports */

  ssSetOutputPortWidth(S, 0, rmsys->outdim);  // data
  ssSetOutputPortWidth(S, 1, 1);              // receiver
  ssSetOutputPortWidth(S, 2, 1);              // length
  ssSetOutputPortWidth(S, 3, 1);              // prio
  ssSetOutputPortWidth(S, 4, 1);              // time stamp
  ssSetOutputPortWidth(S, 5, 1);              // signal power (wireless only)
  ssSetOutputPortWidth(S, 6, 1);              // message id

  ssSetNumContStates(S, 0);
  ssSetNumDiscStates(S, 0);
  
  ssSetNumSampleTimes(S, 1);
    
  ssSetNumRWork(S, 0);
  ssSetNumIWork(S, 0);
  ssSetNumPWork(S, 0); 
  ssSetNumModes(S, 0);
  ssSetNumNonsampledZCs(S, 0);

  ssSetUserData(S, rmsys);
  
  ssSetOptions(S, SS_OPTION_CALL_TERMINATE_ON_EXIT); 
}
示例#3
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs > 2) {
    TT_MEX_ERROR("ttCreateMailbox: Wrong number of input arguments!\nUsage: ttCreateMailbox(mailboxname [, maxSize])");
    return;
  }

  if (mxIsChar(prhs[0]) != 1) {
    TT_MEX_ERROR("ttCreateMailbox: mailboxname must be a string");
    return;
  }
  char mailboxname[MAXCHARS];
  mxGetString(prhs[0], mailboxname, MAXCHARS);

  if (nrhs == 2) {
    if (!mxIsDoubleScalar(prhs[1])) {
      TT_MEX_ERROR("ttCreateMailbox: maxSize must be an integer scalar");
      return;
    }
    int maxSize = (int) *mxGetPr(prhs[1]);
    ttCreateMailbox(mailboxname, maxSize);
  } else {
    ttCreateMailbox(mailboxname);
  }
 
}
示例#4
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys(); // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 1) {
    TT_MEX_ERROR("Wrong number of input arguments!\nUsage: ttAnalogIn(inpChan)");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("ttAnalogIn: inpChan must be a number");
    return;
  }

  int inpChan = (int) *mxGetPr(prhs[0]);

  double retval = ttAnalogIn(inpChan); 

  plhs[0] = mxCreateDoubleScalar(retval);
}
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 2) {
    MEX_ERROR("ttCreateMonitor: Wrong number of input arguments!\nUsage: ttCreateMonitor(monitorname, display)");
    return;
  }

  if (mxIsChar(prhs[0]) != 1) {
    MEX_ERROR("ttCreateMonitor: monitorname must be a string");
    return;
  }
  if (!mxIsDoubleScalar(prhs[1])) {
    MEX_ERROR("ttCreateMonitor: display must be an integer scalar");
    return;
  }

  char monitorname[100];
  mxGetString(prhs[0], monitorname, 100);
  
  int display = (int) *mxGetPr(prhs[1]);
  if (display == 0) {
    ttCreateMonitor(monitorname, false);
  } else {
    ttCreateMonitor(monitorname, true);
  }
}
示例#6
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 1) {
    TT_MEX_ERROR("ttSetNumberOfCPUs: Wrong number of input arguments!\nUsage: ttSetNumberOfCPUs(number)");
    return;
  }
  
  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("ttSetNumberOfCPUs: segment must be a positive integer");
    return;
  }

  int nbr = (int) *mxGetPr(prhs[0]);

  ttSetNumberOfCPUs(nbr);

}
示例#7
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 1) {
    MEX_ERROR("ttLogStop: Wrong number of input arguments!\nUsage: ttLogStop(logID)");
    return;
  }

  int ID = 0;
  if (mxIsDoubleScalar(prhs[0])) {
    ID = (int)*mxGetPr(prhs[0]);
  }
  if (ID <= 0) {
    MEX_ERROR("ttLogStop: logID must be a positive number");
    return;
  }

  ttLogStop(ID);
}
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs < 2 || nrhs > 3 ) {
    MEX_ERROR("ttCreateSemaphore: Wrong number of input arguments!\nUsage: ttCreateSemaphore(semaphorename, initval [, maxval])");
    return;
  }
  if (mxIsChar(prhs[0]) != 1) {
    MEX_ERROR("ttCreateSemaphore: semaphorename must be a string");
    return;
  }
  if (!mxIsDoubleScalar(prhs[1])) {
    MEX_ERROR("ttCreateSemaphore: initval must be an integer scalar");
    return;
  }

  if (nrhs == 3) {
    if (!mxIsDoubleScalar(prhs[2])) {
      MEX_ERROR("ttCreateSemaphore: maxval must be an integer scalar");
      return;
    }
  }

  char semaphorename[100];
  mxGetString(prhs[0], semaphorename, 100);
  int initval = (int) *mxGetPr(prhs[1]);
  if (nrhs == 2) {
    ttCreateSemaphore(semaphorename, initval);
  } else {
    int maxval = (int) *mxGetPr(prhs[2]);
    ttCreateSemaphore(semaphorename, initval, maxval);
  }
}
示例#9
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 3) {
    TT_MEX_ERROR("ttCallBlockSystem: Wrong number of input arguments!\nUsage: ttCallBlockSystem(nbrOutp, inpVec, blockname)");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("ttCallBlockSystem: nbrOutp must be a number");
    return;
  }
  if (!mxIsDouble(prhs[1])) {
    TT_MEX_ERROR("ttCallBlockSystem: inpVec must contain numbers");
    return;
  }
  if (mxIsChar(prhs[2]) != 1 || mxGetM(prhs[2]) != 1) {
    TT_MEX_ERROR("ttCallBlockSystem: blockname must be a non-empty string");
    return;
  }

  int nbrOutp = (int) *mxGetPr(prhs[0]);
  double* outpVec = new double[nbrOutp];

  int nbrInp = mxGetNumberOfElements(prhs[1]);
  double* inpVec = mxGetPr(prhs[1]);
  
  char blockname[MAXCHARS];
  mxGetString(prhs[2], blockname, MAXCHARS);

  ttCallBlockSystem(nbrOutp, outpVec, nbrInp, inpVec, blockname);

  plhs[0] = mxCreateDoubleMatrix(1, nbrOutp, mxREAL);
  // Copy values (will be zeros if call failed)
  for (int i=0; i<nbrOutp; i++) {
    mxGetPr(plhs[0])[i] = outpVec[i];
  }
  
  delete[] outpVec;

}
示例#10
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  int networkNbr;
  char nwhandler[MAXCHARS];

  rtsys = getrtsys(); // Get pointer to rtsys
  if (rtsys == NULL) return;

  // Check number and type of arguments. 
  if (nrhs < 1 || nrhs > 2) {
    mexErrMsgTxt("ttAttachNetworkHandler: Wrong number of input arguments!\nUsage: ttAttachNetworkHandler(network, nwhandler) or\n       ttAttachNetworkHandler(nwhandler)");
  }

  if (nrhs == 2) {
    
    if (!mxIsDoubleScalar(prhs[0])) {
      mexErrMsgTxt("ttAttachNetworkHandler: network must be an integer");
    }
    if (mxIsChar(prhs[1]) != 1 || mxGetM(prhs[1]) != 1) {
      mexErrMsgTxt("ttAttachNetworkHandler: nwhandler must be a string");
    }
    
    networkNbr = (int) *mxGetPr(prhs[0]);
    
    mxGetString(prhs[1], nwhandler, MAXCHARS);
    
    ttAttachNetworkHandler(networkNbr, nwhandler);
    
  } else {
    
    if (mxIsChar(prhs[0]) != 1 || mxGetM(prhs[0]) != 1) {
      mexErrMsgTxt("ttAttachNetworkHandler: nwhandler must be a string");
    }
  
    mxGetString(prhs[0], nwhandler, MAXCHARS);

    ttAttachNetworkHandler(nwhandler);
  }
}
示例#11
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  double value; 
  
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs == 0 || nrhs > 2) {
    MEX_ERROR("ttSetDeadline: Wrong number of input arguments!\nUsage: ttSetDeadline(value) or ttSetDeadline(value, taskname)");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    MEX_ERROR("ttSetDeadline: value must be a number");
    return;
  }
  
  if (nrhs == 1) {
    value = *mxGetPr(prhs[0]);
    ttSetDeadline(value);
    
  } else {
    if (mxIsChar(prhs[1]) != 1 || mxGetM(prhs[1]) != 1) {
      MEX_ERROR("ttSetDeadline: taskname must be a string");
      return;
    }
    
    value = *mxGetPr(prhs[0]);
    char taskname[100];
    mxGetString(prhs[1], taskname, 100);
    
    ttSetDeadline(value, taskname);
  }

}
示例#12
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
    mxArray* data;
    int network;

    rtsys = getrtsys(); // Get pointer to rtsys

    if (rtsys==NULL) {
        return;
    }

    // Check number and type of arguments.
    if (nrhs > 1) {
        MEX_ERROR("ttGetMsg: Wrong number of input arguments!\nUsage: ttGetMsg or\n       ttGetMsg(network)");
        return;
    }

    if (nrhs == 1) {
        if (!mxIsDoubleScalar(prhs[0])) {
            MEX_ERROR("ttGetMsg: network must be an integer scalar");
            return;
        }
        network = (int) *mxGetPr(prhs[0]);
    } else {
        network = 1;
    }

    double signalPower;
    data = ttGetMsgMATLAB(network, &signalPower);

    if ( data==NULL ) {
        data = mxCreateDoubleMatrix(0,0,mxREAL); // Return empty matrix
    }

    plhs[0] = data;
    if ( nlhs>=2 ) {
        plhs[1] = mxCreateDoubleScalar(signalPower);
    }
}
示例#13
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  double prio; 

  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs == 0 || nrhs > 2) {
    TT_MEX_ERROR("ttSetPriority: Wrong number of input argumenys!\nUsage: ttSetPriority(prio) or ttSetPriority(prio, taskname)");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("ttSetPriority: prio must be a number");
    return;
  }
  
  if (nrhs == 1) {
    prio = *mxGetPr(prhs[0]);
    ttSetPriority(prio);
    
  } else {
    if (mxIsChar(prhs[1]) != 1 || mxGetM(prhs[1]) != 1) {
      TT_MEX_ERROR("ttSetPriority: taskname must be a string");
      return;
    }
    
    prio = *mxGetPr(prhs[0]);
    char taskname[MAXCHARS];
    mxGetString(prhs[1], taskname, MAXCHARS);
    
    ttSetPriority(prio, taskname);
  }
}
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  int network;

  rtsys = getrtsys(); // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number of arguments.
  if (nrhs > 1) {
    TT_MEX_ERROR("ttDiscardUnsentMessages: Wrong number of input arguments!\nUsage: ttDiscardUnsentMessages() or\n       ttDiscardUnsentMessages(network)");
    return;
  }

  int nbr;

  if (nrhs > 0) {
    if (!mxIsDoubleScalar(prhs[0])) {
      TT_MEX_ERROR("ttSendMsg: network must be a number");
      return;
    }
    network = (int)*mxGetPr(prhs[0]);
    nbr = ttDiscardUnsentMessages(network);
  }
  else
    // default network (1)
    nbr = ttDiscardUnsentMessages();


  //  if ( nlhs>=1 ){
    plhs[0] = mxCreateDoubleScalar(nbr);
    //}


}
示例#15
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 

  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs != 1) {
    TT_MEX_ERROR("ttSleepUntil: Wrong number of input arguments!\nUsage: ttSleepUntil(time)");
    return;
  }

  if (!mxIsDoubleScalar(prhs[0])) {
    TT_MEX_ERROR("ttSleepUntil: time must be a number");
    return;
  }

  double time = *mxGetPr(prhs[0]);

  ttSleepUntil(time);
}
示例#16
0
double executeCode(char *codeName, int seg, Task *task) {
  double retval;
  mxArray *lhs[2];
  mxArray *rhs[2];

  *mxGetPr(segArray) = (double) seg;

  rhs[0] = segArray;
  if (task->dataMATLAB) {
    //rhs[1] = mxDuplicateArray(task->dataMATLAB);
    rhs[1] = task->dataMATLAB;
  } else {
    rhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL);
    *mxGetPr(rhs[1]) = 0.0;
  }

  mexSetTrapFlag(1); // return control to the MEX file after an error
  lhs[0] = NULL;     // needed not to crash Matlab after an error
  lhs[1] = NULL;     // needed not to crash Matlab after an error
  if (mexCallMATLAB(2, lhs, 2, rhs, codeName) != 0) {
    rtsys->error = true;
    return 0.0;
  }

  if (mxGetClassID(lhs[0]) == mxUNKNOWN_CLASS) {
    printf("??? executeCode: execution time not assigned\n\n");
    printf("Error in ==> code function '%s', segment %d\n", codeName, seg);
    rtsys->error = true;
    return 0.0;
  }

  if (!mxIsDoubleScalar(lhs[0])) {
    printf("??? executeCode: illegal execution time\n\n");
    printf("Error in ==> code function '%s', segment %d\n", codeName, seg);
    rtsys->error = true;
    return 0.0;
  }

  if (mxGetClassID(lhs[1]) == mxUNKNOWN_CLASS) {
    printf("??? executeCode: data not assigned\n\n");
    printf("Error in ==> code function '%s', segment %d\n", codeName, seg);
    rtsys->error = true;
    return 0.0;
  }

  //if ( task->dataMATLAB ) {
  if ( task->dataMATLAB != lhs[1] ) {
    mxDestroyArray(task->dataMATLAB);
    //task->dataMATLAB = mxDuplicateArray(lhs[1]);
    task->dataMATLAB = lhs[1];
    mexMakeArrayPersistent(task->dataMATLAB);
  }
  
  retval = *mxGetPr(lhs[0]);

  //mxDestroyArray(rhs[1]);
  mxDestroyArray(lhs[0]);
  //mxDestroyArray(lhs[1]);

  return retval;
}
示例#17
0
  static void mdlInitializeSizes(SimStruct *S)
  {
    const mxArray *arg;

    ssSetNumSFcnParams(S, 5);  /* Number of expected parameters */
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
      return; /* Parameter mismatch will be reported by Simulink */
    }
  
    // Parse second argument only, to determine nbrOfNodes

    // 2 - Number of nodes
    int nbrOfNodes = 0;
    arg = ssGetSFcnParam(S, 1);
    if (mxIsDoubleScalar(arg)) {
      nbrOfNodes = (int) *mxGetPr(arg);
    }
    if (nbrOfNodes <= 0) {
      ssSetErrorStatus(S, "TrueTime Ultrasound Network: The number of nodes must be an integer > 0");
      return;
    }

    ssSetNumContStates(S, 0);
    ssSetNumDiscStates(S, 0);
  
    ssSetNumInputPorts(S, 3);
    ssSetInputPortDirectFeedThrough(S, 0, 0);
    ssSetInputPortWidth(S, 0, nbrOfNodes);
    ssSetInputPortWidth(S, 1, nbrOfNodes);
    ssSetInputPortWidth(S, 2, nbrOfNodes);
  
    ssSetNumOutputPorts(S, 2);
    ssSetOutputPortWidth(S, 0, nbrOfNodes);
    ssSetOutputPortWidth(S, 1, nbrOfNodes);

    ssSetNumSampleTimes(S, 1);
  
    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0); 
    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs(S, 1);

    // Make sure cleanup is performed even if errors occur
    ssSetOptions(S, SS_OPTION_CALL_TERMINATE_ON_EXIT);

    int i;

    // Create new network struct

    RTnetwork *nwsys = new RTnetwork;
    ssSetUserData(S, nwsys); // save pointer in UserData

    // Arg 1 - Network Number
    nwsys->networkNbr = 0;
    arg = ssGetSFcnParam(S, 0);
    if (mxIsDoubleScalar(arg)) {
      nwsys->networkNbr = (int) *mxGetPr(arg);
    } 
    if (nwsys->networkNbr <= 0) {
      ssSetErrorStatus(S, "TrueTime Ultrasound Network: The network number must be > 0");
      return;
    }

    // Arg 2 - Number of nodes
    arg = ssGetSFcnParam(S, 1);
    nwsys->nbrOfNodes = (int) *mxGetPr(arg); // we know it's right
    //mexPrintf("nbrOfNodes: %d\n", nwsys->nbrOfNodes);
    
    // Arg 3 - Reach
    nwsys->reach = 0.0;
    arg = ssGetSFcnParam(S, 2);
    if (mxIsDoubleScalar(arg)) {
      nwsys->reach = *mxGetPr(arg);
    }
    if (nwsys->reach < 0.0) {
      ssSetErrorStatus(S, "TrueTime Ultrasound Network: The reach must be >= 0");
      return;
    }
    //mexPrintf("reach: %f\n", nwsys->reach);

    // Arg 4 - Ping length
    nwsys->pinglength = 0.0;
    arg = ssGetSFcnParam(S, 3);
    if (mxIsDoubleScalar(arg)) {
      nwsys->pinglength = *mxGetPr(arg);
    }
    if (nwsys->pinglength < 0.0) {
      ssSetErrorStatus(S, "TrueTime Ultrasound Network: The ping length must be >= 0");
      return;
    }
    //mexPrintf("ping length: %f\n", nwsys->pinglength);

    // Arg 5 - Speed of sound
    nwsys->speedofsound = 0.0;
    arg = ssGetSFcnParam(S, 4);
    if (mxIsDoubleScalar(arg)) {
      nwsys->speedofsound = *mxGetPr(arg);
    }
    if (nwsys->speedofsound <= 0.0) {
      ssSetErrorStatus(S, "TrueTime Ultrasound Network: The speed of sound must be > 0");
      return;
    }
    //mexPrintf("speedofsound: %f\n", nwsys->speedofsound);

    /* Write pointer to Simulink block UserData */
    /*    mexCallMATLAB(1, lhs, 0, NULL, "gcbh");
    sprintf(nwsysp,"%p",nwsys);
    rhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
    *mxGetPr(rhs[0]) = *mxGetPr(lhs[0]);
    rhs[1] = mxCreateString("UserData");
    rhs[2] = mxCreateString(nwsysp);
    mexCallMATLAB(0, NULL, 3, rhs, "set_param"); */

    /* Write pointer to MATLAB global workspace */
    /* FIX: The code above is intended to be removed and replaced by this. */
    /* Write rtsys pointer to global workspace */
    mxArray* var = mxCreateDoubleScalar(0.0);
    mexMakeArrayPersistent(var);
    *((void **)mxGetData(var)) = nwsys;
    char nwsysbuf[MAXCHARS];
    sprintf(nwsysbuf, "_nwsys_%d", nwsys->networkNbr);
    mexPutVariable("global", nwsysbuf, var);
    
    nwsys->inputs = new double[nwsys->nbrOfNodes];
    nwsys->oldinputs = new double[nwsys->nbrOfNodes];
    nwsys->outputs   = new double[nwsys->nbrOfNodes];
    nwsys->sendschedule = new double[nwsys->nbrOfNodes];

    for (i=0; i<nwsys->nbrOfNodes; i++) {
      nwsys->inputs[i] = 0.0;
      nwsys->oldinputs[i] = 0.0;
      nwsys->outputs[i] = 0.0;
      nwsys->sendschedule[i] = i+1;
    }

    nwsys->time = 0.0;
    nwsys->prevHit = 0.0;
  
    nwsys->nwnodes = new NWnode*[nwsys->nbrOfNodes];
    for (i=0; i<nwsys->nbrOfNodes; i++) {
      int j;

      nwsys->nwnodes[i] = new NWnode();
      //nwsys->nwnodes[i]->transmitPower = transmitPowerWatt;

      nwsys->nwnodes[i]->signallevels = new double[nwsys->nbrOfNodes]; //802.11
      for (j=0; j<nwsys->nbrOfNodes; j++) {
	nwsys->nwnodes[i]->signallevels[j] = 0;
      }
      
    }

    nwsys->waituntil = 0.0;
    nwsys->sending = -1;  // Note! -1 means nobody is sending
    nwsys->rrturn = nwsys->nbrOfNodes - 1; // want to start at 0
    nwsys->lasttime = -1.0;

    nwsys->slotcount = nwsys->schedsize - 1; // want to start at 0
    nwsys->currslottime = -nwsys->slottime;  // same here

    // rad, kolum, reella tal
    //nwsys->nbrOfTransmissions = mxCreateDoubleMatrix(nwsys->nbrOfNodes, nwsys->nbrOfNodes, mxREAL);
    //mexMakeArrayPersistent(nwsys->nbrOfTransmissions);
  }
示例#18
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys(); // Get pointer to rtsys 
  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs < 3 || nrhs > 4) {
    MEX_ERROR("ttInitKernel: Wrong number of input arguments! \nUsage: ttInitKernel(nbrInputs, nbrOutputs, prioFcn) or\n       ttInitKernel(nbrInputs, nbrOutputs, prioFcn, contextSwitchOH)");
    return;
  }
  if (!mxIsDoubleScalar(prhs[0])) {
    MEX_ERROR("ttInitKernel: nbrInputs must be an integer");
    return;
  }
  if (!mxIsDoubleScalar(prhs[1])) {
    MEX_ERROR("ttInitKernel: nbrOutputs must be an integer");
    return;
  }
  if (mxIsChar(prhs[2]) != 1 || mxGetM(prhs[2]) != 1) {
    MEX_ERROR("ttInitKernel: prioFcn must be a string");
    return;
  }
  if (nrhs == 4) {
    if (!mxIsDoubleScalar(prhs[3])) {
      MEX_ERROR("ttInitKernel: contextSwitchOH must be a number");
      return;
    }
  }

  int nbrInp = (int) *mxGetPr(prhs[0]);
  int nbrOutp = (int) *mxGetPr(prhs[1]);
  
  if ( nbrInp < 0 ) {
    MEX_ERROR("ttInitKernel: nbrInputs must be positive or zero");
    return;
  }
  if ( nbrOutp < 0 ) {
    MEX_ERROR("ttInitKernel: nbrOutputs must be positive or zero");
    return;
  }

  char buf[20];
  mxGetString(prhs[2], buf, 20);

  int dispatch;
  if (strcmp(buf, "prioFP") == 0) {
    dispatch = FP;
  } else if (strcmp(buf, "prioRM") == 0) {
    dispatch = RM;
  } else if (strcmp(buf, "prioDM") == 0){
    dispatch = DM;
  } else if (strcmp(buf, "prioEDF") == 0) {
    dispatch = EDF;
  } else {
    printf("ttInitKernel: Unknown priority function '%s', using fixed priority scheduling!\n",buf);
    dispatch = FP; // default 
  }
  
  if (nrhs == 3) {
    ttInitKernel(nbrInp, nbrOutp, dispatch);
  } else {
    double contextSwitchOH = *mxGetPr(prhs[3]);
    ttInitKernel(nbrInp, nbrOutp, dispatch, contextSwitchOH);
  }
}
示例#19
0
double runKernel(double externalTime) {
  
  Task *task, *temp, *newrunning;
  UserTask *usertask;
  InterruptHandler *handler;
  DataNode* dn;

  // If no energy, then we can not run
  if (rtsys->energyLevel <= 0) {
    debugPrintf("'%s': Energy is out at time: %f\n", rtsys->blockName, rtsys->time);
    return TT_MAX_TIMESTEP;
  }
  
  double timeElapsed = externalTime - rtsys->prevHit; // time since last invocation
  rtsys->prevHit = externalTime;  // update previous invocation time

  debugPrintf("'%s': runkernel at %.16f\n", rtsys->blockName, rtsys->time);
  
#ifdef KERNEL_MATLAB
  // Write rtsys pointer to global workspace so that MATLAB kernel
  // primitives can access it
  *((long *)mxGetPr(rtsys->rtsysptr)) = (long)rtsys;
#endif
  
  double timestep = 0.0;
  int niter = 0;

  while (timestep < TT_TIME_RESOLUTION) {
    
    if (++niter == TT_MAX_ITER) {
      mexPrintf("??? Fatal kernel error: maximum number of iterations reached!\n");
      rtsys->error = 1;
      return 0.0;
    }

    // For each CPU, count down execution time for the current task

    for (int i=0; i<rtsys->nbrOfCPUs; i++) {

      debugPrintf("running core %d\n", i);
      
      rtsys->currentCPU = i;
      rtsys->running = rtsys->runnings[i];
      task = rtsys->running;

      if (task != NULL) {
      
	if (task->state == RUNNING) {
	  task->state = READY;
	}

	double duration = timeElapsed * rtsys->cpuScaling;
      
	// Decrease remaining execution time for current segment and increase total CPU time
	task->execTime -= duration;
	task->CPUTime += duration;

	// If user task, call runkernel hook (to e.g. update budgets)
	if (task->isUserTask()) {
	  usertask = (UserTask*)task;
	  usertask->runkernel_hook(usertask,duration);
	}
      
	// Check if task has finished current segment or not yet started
	if (task->execTime / rtsys->cpuScaling < TT_TIME_RESOLUTION) {
	
	  // Execute next segment 
	  task->segment = task->nextSegment;
	  task->nextSegment++; // default, can later be changed by ttSetNextSegment
	
#ifndef KERNEL_MATLAB
	  debugPrintf("'%s': executing code segment %d of task '%s'\n", rtsys->blockName, task->segment, task->name);
	  task->execTime = task->codeFcn(task->segment, task->data);
	  if (rtsys->error) {
	    TT_RUNKERNEL_ERROR(errbuf);
	    mexPrintf("In task ==> '%s', code segment %d\n", task->name, task->segment);
	    return 0.0;
	  }
#else
	  if (task->codeFcnMATLAB == NULL) {
	    task->execTime = task->codeFcn(task->segment, task->data);
	  } else {

	    mxArray *lhs[2];
	    mxArray *rhs[2];

	    debugPrintf("'%s': executing code function '%s'\n", rtsys->blockName, task->codeFcnMATLAB);

	    *mxGetPr(rtsys->segArray) = (double)task->segment;
	    rhs[0] = rtsys->segArray;
	    if (task->dataMATLAB) {
	      rhs[1] = task->dataMATLAB;
	    } else {
	      rhs[1] = mxCreateDoubleMatrix(0, 0, mxREAL);
	    }
	  
	    mexSetTrapFlag(1); // return control to the MEX file after an error
	    lhs[0] = NULL;     // needed not to crash Matlab after an error
	    lhs[1] = NULL;     // needed not to crash Matlab after an error
	    if (mexCallMATLAB(2, lhs, 2, rhs, task->codeFcnMATLAB) != 0) {
	      rtsys->error = true;
	      return 0.0;
	    }

	    if (mxGetClassID(lhs[0]) == mxUNKNOWN_CLASS) {
	      snprintf(errbuf, MAXERRBUF, "Execution time not assigned in code function '%s'", task->codeFcnMATLAB);
	      TT_RUNKERNEL_ERROR(errbuf);
	      rtsys->error = true;
	      return 0.0;
	    }
	  
	    if (!mxIsDoubleScalar(lhs[0])) {
	      snprintf(errbuf, MAXERRBUF, "Illegal execution time returned by code function '%s'", task->codeFcnMATLAB);
	      TT_RUNKERNEL_ERROR(errbuf);
	      rtsys->error = true;
	      return 0.0;
	    }
	  
	    if (mxGetClassID(lhs[1]) == mxUNKNOWN_CLASS) {
	      snprintf(errbuf, MAXERRBUF, "Data not assigned in code function '%s'", task->codeFcnMATLAB);
	      TT_RUNKERNEL_ERROR(errbuf);
	      rtsys->error = true;
	      return 0.0;
	    }

	    //if ( task->dataMATLAB ) {
	    if ( task->dataMATLAB != lhs[1] ) {
	      mxDestroyArray(task->dataMATLAB);
	      //task->dataMATLAB = mxDuplicateArray(lhs[1]);
	      task->dataMATLAB = lhs[1];
	      mexMakeArrayPersistent(task->dataMATLAB);
	    }
	  
	    task->execTime = *mxGetPr(lhs[0]);
	  
	    //mxDestroyArray(rhs[1]);
	    mxDestroyArray(lhs[0]);
	    //mxDestroyArray(lhs[1]);
	  
	  }
	
#endif
	  if (task->execTime < 0.0) { 

	    // Negative execution time = task is finished
	    debugPrintf("'%s': task '%s' finished\n", rtsys->blockName, task->name);
	    task->execTime = 0.0;
	    task->segment = 0;
	    task->nextSegment = 1;
	    
	    // Remove task from readyQ and set running to NULL
	    if (task->state == READY) {
	      task->remove();
	      task->state = SLEEPING;
	    } else {
	      snprintf(errbuf, MAXERRBUF, "Finished task '%s' not in ReadyQ.", task->name);
	      TT_RUNKERNEL_ERROR(errbuf);
	      rtsys->error = true;
	      return 0.0;
	    }
	    
	    rtsys->runnings[i] = NULL;
	    rtsys->running = NULL;
	    
	    if (task->isUserTask()) {
	      // Execute finish-hook 
	      usertask = (UserTask*)task;
	      usertask->finish_hook(usertask);
	      rtsys->runningUserTasks[i] = NULL;
	    }
	    
	    task->nbrInvocations--;
	    if (task->nbrInvocations > 0) {
	      // There are queued invocations, release the next one
	      dn = (DataNode*) task->pending->getFirst();
	      TaskInvocation *ti = (TaskInvocation *)dn->data;
	      if (task->isUserTask()) { 
		usertask = (UserTask*)task;
		usertask->arrival = ti->timestamp;
		usertask->release = rtsys->time;
		usertask->release_hook(usertask);  // could affect task prio
	      }
	      debugPrintf("'%s': releasing task '%s'\n", rtsys->blockName, task->name);
	      task->moveToList(rtsys->readyQs[task->affinity]);  // re-insert task into readyQ
	      task->state = READY;
	      if (task->isHandler()) {
		handler = (InterruptHandler*)task;
		strncpy(handler->invoker, ti->invoker, MAXCHARS);
		handler->timestamp = ti->timestamp;
	      }
	      task->pending->deleteNode(dn);
	      delete ti;
	    } 
	  }
	}
      }
    }

    // Check time queue for possible releases and expired timers
    
    task = (Task*) rtsys->timeQ->getFirst();
    while (task != NULL) {
      if ((task->wakeupTime() - rtsys->time) >= TT_TIME_RESOLUTION) {
	break; // timeQ is sorted by time, no use to go further
      }
      
      // Task to be released 
      temp = task;
      task = (Task*) task->getNext();
      
      if (temp->isTimer()) {
	Timer *timer = (Timer*)temp;
	debugPrintf("'%s': timer '%s' expired at %f\n", rtsys->blockName, timer->name, rtsys->time);
	invoke_task(timer->task, timer->name);
	if (timer->isPeriodic) {
	  // if periodic timer put back in timeQ
	  timer->time += timer->period;
	  timer->moveToList(rtsys->timeQ);
	} else {
	  timer->remove(); // remove timer from timeQ
	  if (!timer->isOverrunTimer) {
	    // delete the timer
	    dn = getNode(timer->name, rtsys->timerList);
	    rtsys->timerList->deleteNode(dn);
	    delete timer;
	  }
	}
      } 
      else if (temp->isUserTask()) {
	
	usertask = (UserTask*)temp;
	debugPrintf("'%s': releasing task '%s'\n", rtsys->blockName, usertask->name);
	usertask->moveToList(rtsys->readyQs[usertask->affinity]);
	usertask->state = READY;
	
      }
      else if (temp->isHandler()) {
	mexPrintf("??? Fatal kernel error: interrupt handler in TimeQ!\n");
	rtsys->error = 1;
	return 0.0;
      }
    } // end: checking timeQ for releases
    
    
    // For each core, determine the task with highest priority and make it running task
    
    for (int i=0; i<rtsys->nbrOfCPUs; i++) {
      
      debugPrintf("scheduling core %d\n", i);
      
      rtsys->currentCPU = i;
      
      newrunning = (Task*) rtsys->readyQs[i]->getFirst();
      
      // If old running has been preempted, execute suspend_hook
      if (rtsys->runnings[i] != NULL && rtsys->runnings[i] != newrunning) {
	if (rtsys->runnings[i]->isUserTask()) {
	  usertask = (UserTask*)rtsys->runnings[i];
	  usertask->suspend_hook(usertask); 
	}
      }
      
      // If new running != old running, execute start_hook or resume_hook
      if (newrunning != NULL && newrunning != rtsys->runnings[i]) {
	if (newrunning->isUserTask()) {
	  usertask = (UserTask*)newrunning;
	  if (usertask->segment == 0) {
	    usertask->segment = 1;
	    usertask->start_hook(usertask);
	  } else {
	    usertask->resume_hook(usertask);
	  }
	  rtsys->runningUserTasks[i] = usertask;
	}
      }
      
      rtsys->runnings[i] = (Task*) rtsys->readyQs[i]->getFirst(); // hooks may have released handlers
      if (rtsys->runnings[i] != NULL) {
	rtsys->runnings[i]->state = RUNNING;
      }

    }
    
    // Determine next invocation of kernel
    
    double compTime;
    timestep = TT_MAX_TIMESTEP;
    
    // Next release from timeQ (user task or timer)
    if (rtsys->timeQ->getFirst() != NULL) {
      Task* t = (Task*) rtsys->timeQ->getFirst();
      timestep = t->wakeupTime() - rtsys->time;
    }
    
    // Remaining execution time of running tasks
    
    for (int i=0; i<rtsys->nbrOfCPUs; i++) {
      if (rtsys->runnings[i] != NULL) {
	compTime = rtsys->runnings[i]->execTime / rtsys->cpuScaling;
	timestep = (timestep < compTime) ? timestep : compTime;
      } 
    }
      
    timeElapsed = 0.0;
      
  } // end: loop while timestep < TT_TIME_RESOLUTION
    
  return timestep;
}
示例#20
0
static void mdlInitializeSizes(SimStruct *S)
{

  debugPrintf("'%s': mdlInitializeSizes\n", S->path);

  int i;
#ifdef KERNEL_MATLAB
  char initfun[MAXCHARS];
  static mxArray *lhs[1]; // warning: used multiple times
  static mxArray *rhs[3]; // warning: used multiple times
  mxArray *error_msg_array[1];
  char *error_msg;
  int nargin;
#endif

  ssSetNumSFcnParams(S, 7);  /* Number of expected parameters */
  if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    TT_CALLBACK_ERROR(S, "Wrong number of parameters to S-function!");
    return; /* Parameter mismatch will be reported by Simulink */
  }
  
  rtsys = new RTsys;

  strncpy((char*)rtsys->blockName, ssGetBlockName(S), MAXCHARS);

#ifdef KERNEL_MATLAB
  rtsys->segArray = mxCreateScalarDouble(0.0);
  mexMakeArrayPersistent(rtsys->segArray);
#endif

  /* Assign various function pointers */
  rtsys->contextSwitchCode = contextSwitchCode;
  rtsys->timeCmp = timeCmp;
  rtsys->prioCmp = prioCmp;
  rtsys->default_arrival = default_arrival;
  rtsys->default_release = default_release;
  rtsys->default_start = default_start;
  rtsys->default_suspend = default_suspend;
  rtsys->default_resume = default_resume;
  rtsys->default_finish = default_finish;
  rtsys->default_runkernel = default_runkernel;
  rtsys->prioFP = prioFP;
  rtsys->prioEDF = prioEDF;
  rtsys->prioDM = prioDM;

  /* Create basic kernel data structures */
  rtsys->taskList = new List("TaskList", NULL);
  rtsys->handlerList = new List("HandlerList", NULL);
  rtsys->timerList = new List("TimerList", NULL);
  rtsys->monitorList = new List("MonitorList", NULL);
  rtsys->eventList = new List("EventList", NULL);
  rtsys->mailboxList = new List("MailboxList", NULL);
  rtsys->semaphoreList = new List("SemaphoreList", NULL);
  rtsys->logList = new List("LogList", NULL);
  rtsys->cbsList = new List("CBSList", NULL);

  /* Read number of inputs, outputs, and triggers from block mask */
  const mxArray *arg;
  arg = ssGetSFcnParam(S, 2);
  int m = mxGetM(arg);
  int n = mxGetN(arg);
  if (n != 2 || m != 1) {
    TT_CALLBACK_ERROR(S, "Illegal number of analog inputs/outputs!");
    return;
  }
  int ninputs = (int)mxGetPr(arg)[0];
  int noutputs = (int)mxGetPr(arg)[1];
  if (ninputs < 0 || noutputs < 0) {
    TT_CALLBACK_ERROR(S, "Illegal number of analog inputs/outputs!");
    return;
  }
  rtsys->nbrOfInputs = ninputs;
  rtsys->nbrOfOutputs = noutputs;
  if (ninputs > 0) {
    rtsys->inputs = new double[ninputs];
  }
  if (noutputs > 0) {
    rtsys->outputs = new double[noutputs];
  }

  arg = ssGetSFcnParam(S, 3);
  if (!mxIsDoubleScalar(arg)) {
    TT_CALLBACK_ERROR(S, "Illegal number of triggers!");
    return;
  }
  int ntriggers = (int)*mxGetPr(arg);
  if (ntriggers < 0) {
    TT_CALLBACK_ERROR(S, "Illegal number of triggers!");
    return;
  }
  rtsys->nbrOfTriggers = ntriggers;
  rtsys->triggers = new Trigger[ntriggers]; 
  
  arg = ssGetSFcnParam(S, 4);
  if (!mxIsDoubleScalar(arg)) {
    TT_CALLBACK_ERROR(S, "Illegal trigger type!");
    return;
  }
  int trigType = (int)*mxGetPr(arg);
  rtsys->trigType = trigType;
  
  /* Create network interfaces according to the block mask */
  arg = ssGetSFcnParam(S, 5);
  m = mxGetM(arg);  // number of rows = number of network interfaces
  n = mxGetN(arg);  // number of cols should be 1 or 2
  int networkNbr;
  int nodeNbr;
  char nwname[MAXCHARS];
  if ((n == 1 && m != 1) || n > 2) {
    TT_CALLBACK_ERROR(S, "Illegal network or node numbers!");
    return;
  }
  if (m > 0) {
    rtsys->networkInterfaces = new NetworkInterface[m]; 
    rtsys->nbrOfNetworks = m;
    for (i=0; i<m; i++) {
      if (n == 1) {
	networkNbr = 1;
	nodeNbr = (int)mxGetPr(arg)[i];
      } else {
	networkNbr = (int)mxGetPr(arg)[i];
	nodeNbr = (int)mxGetPr(arg)[i+m];
      }
      NetworkInterface *nwi = &(rtsys->networkInterfaces[i]);
      nwi->networkNbr = networkNbr;
      nwi->nodeNbr = nodeNbr-1;
      nwi->portNbr = i;
      sprintf(nwname, "network_%d", networkNbr);
    }
  } 

  /* Read clock offset and drift parameters from the block mask */
  arg = ssGetSFcnParam(S, 6);

  if (!mxIsEmpty(arg)) {
    if (mxGetM(arg) == 1 && mxGetN(arg) == 2) {
      rtsys->clockOffset = mxGetPr(arg)[0];
      rtsys->clockDrift = mxGetPr(arg)[1] + 1.0;
    } else {
      TT_CALLBACK_ERROR(S, "Illegal offset/drift parameters!");
      return;
    }
  }

#ifdef KERNEL_MATLAB
  mexSetTrapFlag(1); // return control to the MEX file after an error

  /* Write rtsys pointer to global workspace */

  if (mexGetVariablePtr("global", "_rtsys") == 0) {

    // pointer variable does not exist - let's create one
    debugPrintf("Creating global _rtsys variable\n");
    mxArray* var = mxCreateScalarDouble(0.0);
    mexMakeArrayPersistent(var);
    mexPutVariable("global", "_rtsys", var);

  }

  rtsys->rtsysptr = (mxArray*)mexGetVariablePtr("global", "_rtsys");

  *((long *)mxGetPr(rtsys->rtsysptr)) = (long)rtsys;

  /* Evaluating user-defined init function (MATLAB) */
  mxGetString(ssGetSFcnParam(S, 0), initfun, MAXCHARS);
  rhs[0] = mxCreateString(initfun);
  if (mexCallMATLAB(1, lhs, 1, rhs, "nargin") != 0) {
    goto error;
  }
  nargin = (int)*mxGetPr(lhs[0]);
  if (nargin == 0) {
    if (mexCallMATLAB(0, NULL, 0, NULL, initfun) != 0) {
      goto error;
    } else {
      rtsys->init_phase = false;
    }
  } else if (nargin == 1) {
    rhs[0] = (mxArray *)ssGetSFcnParam(S, 1);
    if (mexCallMATLAB(0, NULL, 1, rhs, initfun) != 0) {
      goto error;
    } else {
      rtsys->init_phase = false;
    }
  } else {
    TT_CALLBACK_ERROR(S, "Init function takes wrong number (> 1) of arguments!");
    return;
  }

  if (rtsys->error) {
  error:
    mexCallMATLAB(1 ,error_msg_array, 0, NULL, "lasterr"); 
    error_msg = mxArrayToString(error_msg_array[0]);
    snprintf(errbuf, MAXERRBUF, "Error in init function '%s'\n%s", initfun, error_msg);
    mxFree(error_msg);
    TT_CALLBACK_ERROR(S, errbuf);
    return;
  }
  
#else
  /* Save pointer to init args */
  mxArray *initArg = (mxArray *)ssGetSFcnParam(S, 1);
  rtsys->initArg = initArg;
  /* Evaluating user-defined init function (C++) */
  init();
  if (rtsys->error) {
    TT_RUNKERNEL_ERROR(errbuf);
    mexPrintf("??? Error in init() function\n%s\n\n", errbuf);
    mexPrintf("In block ==> '%s'\nSimulation aborted!\n", ssGetBlockName(S));
    ssSetErrorStatus(S, "");
    return;
  }

  rtsys->init_phase = false;
#endif
  
  if (!rtsys->initialized) {
    TT_CALLBACK_ERROR(S, "ttInitKernel was not called in init function");
    return;
  }
  if (!ssSetNumInputPorts(S, 4)) return;
  ssSetInputPortDirectFeedThrough(S, 0, 0);
  ssSetInputPortDirectFeedThrough(S, 1, 0);
  ssSetInputPortDirectFeedThrough(S, 2, 0);
  ssSetInputPortDirectFeedThrough(S, 3, 0);
  if (!ssSetNumOutputPorts(S, 4)) return;

  /* Input Ports */

  if (rtsys->nbrOfInputs > 0) 
    ssSetInputPortWidth(S, 0, rtsys->nbrOfInputs);
  else
    ssSetInputPortWidth(S, 0, 1);
  
  if (rtsys->nbrOfTriggers > 0) 
    ssSetInputPortWidth(S, 1, rtsys->nbrOfTriggers);
  else
    ssSetInputPortWidth(S, 1, 1);

  if (rtsys->nbrOfNetworks > 0) {
    ssSetInputPortWidth(S, 2, rtsys->nbrOfNetworks); /* Network receive */
  }
  else
    ssSetInputPortWidth(S, 2, 1);

  ssSetInputPortWidth(S, 3, 1); //battery

  /* Output Ports */

  if (rtsys->nbrOfOutputs > 0) 
    ssSetOutputPortWidth(S, 0, rtsys->nbrOfOutputs);
  else
    ssSetOutputPortWidth(S, 0, 1);

  if (rtsys->nbrOfNetworks > 0) 
    ssSetOutputPortWidth(S, 1, (rtsys->nbrOfNetworks)); /* Network send */
  else
    ssSetOutputPortWidth(S, 1, 1);

  if (rtsys->nbrOfSchedTasks > 0) 
    ssSetOutputPortWidth(S, 2, rtsys->nbrOfSchedTasks * rtsys->nbrOfCPUs);
  else
    ssSetOutputPortWidth(S, 2, 1);

  ssSetOutputPortWidth(S, 3, 1); //Energy consumption

  ssSetNumContStates(S, 0);
  ssSetNumDiscStates(S, 0);
  
  ssSetNumSampleTimes(S, 1);
    
  ssSetNumRWork(S, 0);
  ssSetNumIWork(S, 0);
  ssSetNumPWork(S, 0); 
  ssSetNumModes(S, 0);
  ssSetNumNonsampledZCs(S, 1);

  ssSetUserData(S, rtsys);
  
  ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_CALL_TERMINATE_ON_EXIT); 

}
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  rtsys = getrtsys() ; // Get pointer to rtsys 
  if (rtsys==NULL) {
    return;
  }

  // Check number and type of arguments. 
  if (nrhs < 5 || nrhs > 6) {
    MEX_ERROR("ttCreatePeriodicTask: Wrong number of input arguments! \nUsage: ttCreatePeriodicTask(name, offset, period, priority, codefcn)\n       ttCreatePeriodicTask(name, offset, period, priority, codefcn, data)");
    return;
  }

  if (mxIsChar(prhs[0]) != 1) {
    MEX_ERROR("ttCreatePeriodicTask: name must be a string");
    return;
  }
  if (!mxIsDoubleScalar(prhs[1])) {
    MEX_ERROR("ttCreatePeriodicTask: offset must be a double scalar");
    return;
  }
  if (!mxIsDoubleScalar(prhs[2])) {
    MEX_ERROR("ttCreatePeriodicTask: period must be a double scalar");
    return;
  }
  if (!mxIsDoubleScalar(prhs[3])) {
    MEX_ERROR("ttCreatePeriodicTask: priority must be a double scalar");
    return;
  }
  if (mxIsChar(prhs[4]) != 1 || mxGetM(prhs[4]) != 1) {
    MEX_ERROR("ttCreatePeriodicTask: codeFcn must be a non-empty string");
    return;
  }
  
  char name[100];
  mxGetString(prhs[0], name, 100);

  double offset = *mxGetPr(prhs[1]);
  if (offset < -EPS) {
    offset = 0.0;
    printf("ttCreatePeriodicTask: negative offset changed to zero\n");
  }
  
  double period = *mxGetPr(prhs[2]);

  double priority = *mxGetPr(prhs[3]);

  char codeFcn[100];
  mxGetString(prhs[4], codeFcn, 100);

  // Make sure that the code function exists in Matlab path
  mxArray *lhs[1];
  mxArray *rhs[1];
  rhs[0] = mxDuplicateArray(prhs[4]);
  mexCallMATLAB(1, lhs, 1, rhs, "exist");
  int number = (int) *mxGetPr(lhs[0]);
  if (number == 0) {
    char buf[200];
    sprintf(buf, "ttCreatePeriodicTask: codeFcn '%s' not in path! Task '%s' not created!", codeFcn, name);
    MEX_ERROR(buf);
    return;
  }

  if (ttCreatePeriodicTask(name, offset, period, priority, NULL)) {

    // Add name of code function (m-file) and data variable
    DataNode *n = (DataNode*) rtsys->taskList->getLast();
    UserTask *usertask = (UserTask*) n->data;
    
    usertask->codeFcnMATLAB = new char[strlen(codeFcn)+1];
    strcpy(usertask->codeFcnMATLAB, codeFcn);
    
    mxArray* data;
    if (nrhs == 5) { // no data specified
      data = mxCreateDoubleMatrix(0, 0, mxREAL);
    } else {
      data = mxDuplicateArray((mxArray*)prhs[5]);
    }
    mexMakeArrayPersistent(data);
    usertask->dataMATLAB = data;
  }
}
示例#22
0
void init() {

  // Read the input argument from the block dialogue
  mxArray *initarg = ttGetInitArg();
  if (!mxIsDoubleScalar(initarg)) {
    TT_MEX_ERROR("The init argument must be a number!\n");
    return;
  }
  int implementation = (int)mxGetPr(initarg)[0];

  // Allocate KernelData memory and store pointer in kernel
  KernelData *kd = new KernelData;
  ttSetUserData(kd);

  // Allocate memory for implementation != 2
  TaskData *d = new TaskData;
  kd->d = d;  // Store pointer in KernelData

  // Allocate memory for implementation 2
  double *d2 = new double;
  kd->d2 = d2; // Store pointer in KernelData

  // Allocate memory for implementation 4
  int *hdl_data = new int;
  kd->hdl_data = hdl_data;   // Store pointer in KernelData
  
  // Initialize TrueTime kernel
  ttInitKernel(prioFP);

  // Task attributes
  double starttime = 0.0;
  double period = 0.006;
  double deadline = period;

  // Controller parameters and states
  d->K = 0.96;
  d->Ti = 0.12;
  d->Td = 0.049;
  d->beta = 0.5;
  d->N = 10.0;
  d->h = period;
  d->u = 0.0;
  d->t = 0.0;  // only used for implementation 3
  d->Iold = 0.0;
  d->Dold = 0.0;
  d->yold = 0.0;
  d->rChan = 1;
  d->yChan = 2;
  d->uChan = 1;

  switch (implementation) {
    
  case 1:
    // IMPLEMENTATION 1: using the built-in support for periodic tasks
    
    ttCreatePeriodicTask("pid_task", starttime, period, pid_code1, d);
    
    break;

  case 2:
    // IMPLEMENTATION 2: calling Simulink block within code function
    
    ttCreatePeriodicTask("pid_task", starttime, period, pid_code2, d2);
    break;

  case 3:
    // IMPLEMENTATION 3: sleepUntil and loop back
  
    ttCreateTask("pid_task", deadline, pid_code3, d);
    ttCreateJob("pid_task");
    break;
    
  case 4:
    // IMPLEMENTATION 4: sampling in timer handler, triggers task job
  
    *hdl_data = 2; // y_chan for reading samples
    ttCreateHandler("timer_handler", 1, sampler_code, hdl_data);
    ttCreatePeriodicTimer("timer", starttime, period, "timer_handler");
    ttCreateMailbox("Samples", 10);
    ttCreateTask("pid_task", deadline, pid_code4, d);
    break;

  }
}
示例#23
0
static void mdlInitializeSizes(SimStruct *S)
{
  static int printed = 0;
  if (!printed) {
    printed = 1;
    printf("-------------------------------------------------------\n");
    printf("                 TrueTime, Version 1.5\n");            
    printf("                   Copyright (c) 2007\n");
    printf("     Martin Ohlin, Dan Henriksson and Anton Cervin\n");
    printf("          Department of Automatic Control LTH\n");        
    printf("                Lund University, Sweden\n");
    printf("-------------------------------------------------------\n");  
  }

#ifdef KERNEL_MATLAB
  char initfun[100];
  static mxArray *lhs[1]; // warning: used multiple times
  static mxArray *rhs[3]; // warning: used multiple times
  
  segArray = mxCreateDoubleScalar(0.0);
  destroyed = false;
  mexMakeArrayPersistent(segArray);
#endif
  
  ssSetNumSFcnParams(S, 4);  /* Number of expected parameters */
  if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    return; /* Parameter mismatch will be reported by Simulink */
  }
  
#ifdef KERNEL_MATLAB  
  mxGetString(ssGetSFcnParam(S, 0), initfun, 100);
#endif

  rtsys = new RTsys;

  /* Assign function pointers */
  rtsys->contextSwitchCode = contextSwitchCode;
  rtsys->periodicTaskHandlerCode = periodicTaskHandlerCode;

  rtsys->timeSort = timeSort;
  rtsys->prioSort = prioSort;

  rtsys->default_arrival = default_arrival;
  rtsys->default_release = default_release;
  rtsys->default_start = default_start;
  rtsys->default_suspend = default_suspend;
  rtsys->default_resume = default_resume;
  rtsys->default_finish = default_finish;

  rtsys->prioFP = prioFP;
  rtsys->prioRM = prioRM;
  rtsys->prioEDF = prioEDF;
  rtsys->prioDM = prioDM;

#ifdef KERNEL_MATLAB
  mexSetTrapFlag(1); // return control to the MEX file after an error

  /* Write rtsys pointer to global workspace */
  char rtsysbuf[100];
  sprintf(rtsysbuf, "%p", rtsys);
  mxArray* var = mxCreateDoubleScalar(0.0);
  mexMakeArrayPersistent(var);
  *((long *)mxGetPr(var)) = (long)rtsys;
  mexPutVariable("global", "_rtsys", var);
  rtsys->rtsysptr = (mxArray*)mexGetVariablePtr("global", "_rtsys");

  /* Evaluating user-defined init function (MATLAB) */
  rhs[0] = mxCreateString(initfun);
  if (mexCallMATLAB(1, lhs, 1, rhs, "nargin") != 0) {
    printf("Call to init function failed!\n");
    ssSetErrorStatus(S, "Call to init function failed!");
    return;
  } else {
    if (*mxGetPr(lhs[0]) == 0) {
      if (mexCallMATLAB(0, NULL, 0, NULL, initfun) != 0) {
	printf("Call to init function failed!\n");
	ssSetErrorStatus(S, "Call to init function failed!");
	return;
      } else {
	rtsys->init_phase = false;
      }
    } else if (*mxGetPr(lhs[0]) == 1) {
      rhs[0] = (mxArray *)ssGetSFcnParam(S, 1);
      if (mexCallMATLAB(0, NULL, 1, rhs, initfun) != 0) {
	printf("Call to init function failed!\n");
	ssSetErrorStatus(S, "Call to init function failed!");
	return;
      } else {
	rtsys->init_phase = false;
      }
    } else {
      printf("Init function takes wrong number (> 1) of arguments!\n");
      ssSetErrorStatus(S, "Init function takes wrong number (> 1) of arguments!");
      return;
    }
  }

#else
  /* Save pointer to init args */
  rtsys->initarg = (mxArray *)ssGetSFcnParam(S, 1);
  /* Evaluating user-defined init function (C++) */
  init();
  rtsys->init_phase = false;
#endif

  
  if (!rtsys->initialized) {
    printf("ttInitKernel was not called in init function!\n");
    ssSetErrorStatus(S, "ttInitKernel was not called in init function!");
    return;
  }

  // Clock drift parameters
  const mxArray *arg;
  arg = ssGetSFcnParam(S, 2);
  if (mxIsDoubleScalar(arg)) {
    rtsys->clockDrift = *mxGetPr(arg) + 1;
  }
  arg = ssGetSFcnParam(S, 3);
  if (mxIsDoubleScalar(arg)) {
    rtsys->clockOffset = *mxGetPr(arg);
  }
  //printf("drift: %f, offset:%f\n", rtsys->clockDrift, rtsys->clockOffset);



  if (!ssSetNumInputPorts(S, 4)) return;
  ssSetInputPortDirectFeedThrough(S, 0, 0);
  ssSetInputPortDirectFeedThrough(S, 1, 0);
  ssSetInputPortDirectFeedThrough(S, 2, 0);
  ssSetInputPortDirectFeedThrough(S, 3, 0);
  if (!ssSetNumOutputPorts(S, 5)) return;

  /* Input Ports */

  if (rtsys->nbrOfInputs > 0) 
    ssSetInputPortWidth(S, 0, rtsys->nbrOfInputs);
  else
    ssSetInputPortWidth(S, 0, 1);
  
  if (rtsys->nbrOfTriggers > 0) 
    ssSetInputPortWidth(S, 1, rtsys->nbrOfTriggers);
  else
    ssSetInputPortWidth(S, 1, 1);

  if (rtsys->nbrOfNetworks > 0) 
    ssSetInputPortWidth(S, 2, rtsys->nbrOfNetworks); /* Network receive */
  else
    ssSetInputPortWidth(S, 2, 1);

  ssSetInputPortWidth(S, 3, 1); //battery

  /* Output Ports */

  if (rtsys->nbrOfOutputs > 0) 
    ssSetOutputPortWidth(S, 0, rtsys->nbrOfOutputs);
  else
    ssSetOutputPortWidth(S, 0, 1);

  if (rtsys->nbrOfNetworks > 0) 
    ssSetOutputPortWidth(S, 1, (rtsys->nbrOfNetworks)); /* Network send */
  else
    ssSetOutputPortWidth(S, 1, 1);

  if (rtsys->nbrOfSchedTasks+rtsys->nbrOfSchedHandlers > 0) 
    ssSetOutputPortWidth(S, 2, rtsys->nbrOfSchedTasks+rtsys->nbrOfSchedHandlers);
  else
    ssSetOutputPortWidth(S, 2, 1);

  if (rtsys->nbrOfSchedMonitors > 0) 
    ssSetOutputPortWidth(S, 3, rtsys->nbrOfSchedMonitors*rtsys->nbrOfTasks);
  else
    ssSetOutputPortWidth(S, 3, 1);

  ssSetOutputPortWidth(S, 4, 1); //Energy consumption

  ssSetNumContStates(S, 0);
  ssSetNumDiscStates(S, 0);
  
  ssSetNumSampleTimes(S, 1);
    
  ssSetNumRWork(S, 0);
  ssSetNumIWork(S, 0);
  ssSetNumPWork(S, 0); 
  ssSetNumModes(S, 0);
  ssSetNumNonsampledZCs(S, 1);

  ssSetUserData(S, rtsys);
  
  ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_CALL_TERMINATE_ON_EXIT); 
}
示例#24
0
static void mdlInitializeSizes(SimStruct *S)
{
  const mxArray *arg;

  ssSetNumSFcnParams(S, 4);  /* Number of expected parameters */
  if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
    return; /* Parameter mismatch will be reported by Simulink */
  }

  if (!ssSetNumInputPorts(S, 5)) return;
  if (!ssSetNumOutputPorts(S, 1)) return;

  SMsys *smsys = new SMsys;
  smsys->trigger = 0.0;

  arg = ssGetSFcnParam(S, 0);
  if (mxIsDoubleScalar(arg)) {
    smsys->networkNbr  = (int)*mxGetPr(arg);
  }
  arg = ssGetSFcnParam(S, 1);
  if (mxIsDoubleScalar(arg)) {
    smsys->sender  = (int)*mxGetPr(arg);
  }
  arg = ssGetSFcnParam(S, 2);
  if (mxIsDoubleScalar(arg)) {
    smsys->indim  = (int)*mxGetPr(arg);
  }
  arg = ssGetSFcnParam(S,3);
  if(mxIsDoubleScalar(arg)) {
    smsys->dynamicSegment = (int)*mxGetPr(arg)-1; // set smsys->dynamicSegment = 0 (static) or 1 (dynamic)
  }
  

  /* Input ports */

  ssSetInputPortDirectFeedThrough(S, 0, 1); 
  ssSetInputPortDirectFeedThrough(S, 1, 1);
  ssSetInputPortDirectFeedThrough(S, 2, 1);
  ssSetInputPortDirectFeedThrough(S, 3, 1);
  ssSetInputPortDirectFeedThrough(S, 4, 1);

  ssSetInputPortWidth(S, 0, 1);             // receiver
  ssSetInputPortWidth(S, 1, smsys->indim);  // data
  ssSetInputPortWidth(S, 2, 1);             // length
  ssSetInputPortWidth(S, 3, 1);             // prio
  ssSetInputPortWidth(S, 4, 1);             // msgID

  /* Output Ports */

  ssSetOutputPortWidth(S, 0, 1);            // snd trigger

  ssSetNumContStates(S, 0);
  ssSetNumDiscStates(S, 0);
  
  ssSetNumSampleTimes(S, 1);
    
  ssSetNumRWork(S, 0);
  ssSetNumIWork(S, 0);
  ssSetNumPWork(S, 0); 
  ssSetNumModes(S, 0);
  ssSetNumNonsampledZCs(S, 0);

  ssSetUserData(S, smsys);
  
  ssSetOptions(S, SS_OPTION_CALL_TERMINATE_ON_EXIT); 
}