void init() { // Initialize TrueTime kernel ttInitKernel(1, 0, prioFP); // nbrOfInputs, nbrOfOutputs, fixed priority // Create task data (local memory) data = new PD_Data; data->K = 1.5; data->Td = 0.035; data->N = 100000.0; data->h = 0.010; data->ad = data->Td/(data->N*data->h+data->Td); data->bd = data->N*data->K*data->Td/(data->N*data->h+data->Td); data->yold = 0.0; data->Dold = 0.0; data->u = 0.0; // Controller task double deadline = 0.010; double prio = 2.0; ttCreateTask("pid_task", deadline, prio, ctrl_code, data); ttCreateJob("pid_task"); // Disturbance task (uncomment to add disturbance task) // double offset = 0.0002; // double period = 0.007; // prio = 1.0; // ttCreatePeriodicTask("dummy", offset, period, prio, dummy_code); // Initialize network ttCreateInterruptHandler("msgRcv", prio, msgRcvhandler); ttInitNetwork(3, "msgRcv"); // node #3 in the network ttCreateSemaphore("sem", 0); }
double periodicTaskHandlerCode(int seg, void* data) { UserTask* task = (UserTask*) data; ttCreateJob(task->name); //printf("ttCreateJob %s at %f\n", task->name, rtsys->time); return FINISHED; }
double timercode(int seg, void* data) { ttCreateJob("TimerTask"); return FINISHED; }
// ---- Sampler code function for Implementation 4 ---- double sampler_code(int seg, void* data) { double y; int* d = (int*) data; switch (seg) { case 1: y = ttAnalogIn(*d); ttTryPost("Samples", new double(y)); // put sample in mailbox ttCreateJob("pid_task"); // trigger task job return 0.0002; default: return FINISHED; } }
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("ttCreateJob: Wrong number of input arguments! \nUsage: ttCreateJob(taskname)"); } if (mxIsChar(prhs[0]) != 1 || mxGetM(prhs[0]) != 1) { MEX_ERROR("ttCreateJob: taskname must be a string"); } char taskname[100]; mxGetString(prhs[0], taskname, 100); ttCreateJob(taskname); }
double AODVrcvcode(int seg, void* data) { AODVrcv_Data* d = (AODVrcv_Data*) data; int myID = d->nodeID; MailboxMsg *mailboxmsg; GenericNwkMsg *nwkmsg; DataMsg *datamsg; RREQMsg *rreqmsg; RREPMsg *rrepmsg; RERRMsg *rerrmsg, *rerrmsg2; HelloMsg *hellomsg; int i, dest, seqNbr, hopCnt, cond1, cond2; int intermed, drop, cached_RREQID, propagate, nextHop; double now, etime1, etime2, lifetime; double etime = 0.0001; RouteEntry *dest_entry, *src_entry; DataNode *dn; switch (seg) { case 1: nwkmsg = (GenericNwkMsg*) ttGetMsg(ZIGBEENETW); now = ttCurrentTime(); /////////////////////// // Tmote stuff start // /////////////////////// if(nwkmsg->type == RANGE_RESPONSE) { if (ttCurrentTime() < d->rcv_timeout) { // Get data from rangeResponseMsg and then delete it RangeResponseMsg *rangeResp = (RangeResponseMsg *)nwkmsg->msg; double x, y; unsigned int range; range = rangeResp->range; x = rangeResp->x; y = rangeResp->y; d->responseCounter++; // mexPrintf("Response counter = %d \n",d->responseCounter); // Remove 145 for 2ms delay // Add 80 for compensation for unknown error double dist; // dist = 34400.0 * (double)(range - 145 + 80) / 72280.0; original dist = 34400.0 * (double)(range - 145 + 68) / 72280.0; // dist = 34400.0 * (double)(range - 145) / 72280.0; // mexPrintf("Distance measurment from %d = %f \n",rangeResp->nodeID,dist); // Put values in data d->node_x = x; d->node_y = y; d->node_dist = dist; // DEBUG d->node_nodeID = rangeResp->nodeID; if (fabs(dist) < 300.0) { // Start task that sends data to mega128 ttCreateJob("node_data_to_kalman"); } } } else if (nwkmsg->type == RANGE_REQUEST) { d->snd_block = ttCurrentTime() + 0.310; } ////////////////////// // Tmote stuff ends // ////////////////////// else if (nwkmsg->type == DATA) { // Data message datamsg = (DataMsg*) nwkmsg->msg; delete nwkmsg; if (datamsg->dest == myID) { // Data message arrived at destination if (VERBOSE) { mexPrintf("Time: %f Data message arrived at Node#%d\n", now, myID); } // Update expiry timer for route to source d->routing_table[datamsg->src - 1].exptime = now + ACTIVE_ROUTE_TIMEOUT; // Notify application ttTryPost("AODVRcvBox", datamsg); ttCreateJob("RcvTask"); etime = 0.0001; } else { // Forward data message if (VERBOSE) { mexPrintf("Time: %f Node#%d about to forward data to Node#%d Data: %f\n", now, myID, datamsg->dest, datamsg->data); } // Update expiry timer for route to source d->routing_table[datamsg->src - 1].exptime = now + ACTIVE_ROUTE_TIMEOUT; // Find route to destination and update expiry timer dest_entry = &(d->routing_table[datamsg->dest - 1]); dest_entry->exptime = now + ACTIVE_ROUTE_TIMEOUT; // Forward data message to next hop nwkmsg = new GenericNwkMsg; nwkmsg->type = DATA; nwkmsg->msg = datamsg; ttSendMsg(1, dest_entry->nextHop, nwkmsg, datamsg->size); etime = 0.0001; } updateExpiryTimer(d->routing_table, d->dataTimer, myID); } else { // AODV control message (RREQ, RREP, RERR, or HELLO) if (VERBOSE) { mexPrintf("Time: %f Node#%d processing AODV message type: %d from Node#%d\n", now, myID, nwkmsg->type, nwkmsg->intermed); } switch (nwkmsg->type) { case RREQ: rreqmsg = (RREQMsg*) nwkmsg->msg; intermed = nwkmsg->intermed; if (rreqmsg->src == myID) { // Skip RREQs received by the original source etime = 0.00001; } else { // Have this RREQ already been processed? cached_RREQID = d->cache[rreqmsg->src - 1]; drop = 0; if (rreqmsg->RREQID <= cached_RREQID) { // Found in cache, drop redundant RREQ if (VERBOSE) { mexPrintf("Time: %f Node#%d dropping redundant RREQ from Node#%d\n", now, myID, intermed); } drop = 1; } if (!drop) { // process RREQ if (VERBOSE) { mexPrintf("Time: %f Node#%d caching RREQ with Src: %d RREQID: %d\n", now, myID, rreqmsg->src, rreqmsg->RREQID); } // Enter RREQID in cache d->cache[rreqmsg->src - 1] = rreqmsg->RREQID; // Create or update route entry to source src_entry = &(d->routing_table[rreqmsg->src - 1]); if (!src_entry->valid) { // No entry exists or invalid src_entry->destSeqNbr = rreqmsg->srcSeqNbr; for (i=0; i<NBR_AODV; i++) { src_entry->prec[i] = 0; // empty precursor list } } else { // Update destination sequence number src_entry->destSeqNbr = max(src_entry->destSeqNbr, rreqmsg->srcSeqNbr); } src_entry->dest = rreqmsg->src; src_entry->nextHop = intermed; src_entry->hops = rreqmsg->hopCnt + 1; src_entry->exptime = now + ACTIVE_ROUTE_TIMEOUT; src_entry->valid = 1; updateExpiryTimer(d->routing_table, d->dataTimer, myID); // Check if we have a route to destination dest_entry = &(d->routing_table[rreqmsg->dest - 1]); if (rreqmsg->dest==myID || dest_entry->valid) { // We are the destination or we have a route to it if (VERBOSE) { mexPrintf("Node#%d has a route to destination#%d\n", myID, rreqmsg->dest); } if (rreqmsg->dest!=myID) { // I am not the destination, but have a route to it if (VERBOSE) { mexPrintf("Sending first RREP from node with route\n"); } dest = dest_entry->dest; seqNbr = dest_entry->destSeqNbr; hopCnt = dest_entry->hops; lifetime = dest_entry->exptime - now; dest_entry->prec[intermed] = 1; } else { // I am the destination itself if (VERBOSE) { mexPrintf("Sending first RREP from destination itself\n"); } dest = myID; if (d->seqNbrs[myID - 1] + 1 == rreqmsg->srcSeqNbr) { d->seqNbrs[myID - 1]++; } seqNbr = max(d->seqNbrs[myID - 1], rreqmsg->destSeqNbr); hopCnt = 0; lifetime = ACTIVE_ROUTE_TIMEOUT; } // Create RREP rrepmsg = new RREPMsg; rrepmsg->hopCnt = hopCnt; rrepmsg->dest = dest; rrepmsg->destSeqNbr = seqNbr; rrepmsg->src = rreqmsg->src; rrepmsg->lifetime = lifetime; // Send RREP to previous hop nwkmsg = new GenericNwkMsg; nwkmsg->type = RREP; nwkmsg->intermed = myID; nwkmsg->msg = rrepmsg; ttSendMsg(1, intermed, nwkmsg, 20*8); // 20 bytes etime = 0.0001; } else { // We do not have a route to the destination if (VERBOSE) { mexPrintf("Time: %f Node#%d sending new broadcast\n", now, myID); } // Update RREQ rreqmsg->hopCnt++; rreqmsg->destSeqNbr = max(d->seqNbrs[rreqmsg->dest - 1], rreqmsg->destSeqNbr); // Rebroadcast RREQ nwkmsg = new GenericNwkMsg; nwkmsg->type = RREQ; nwkmsg->intermed = myID; nwkmsg->msg = rreqmsg; ttSendMsg(1, 0, nwkmsg, 24*8); // 24 bytes etime = 0.0001; } } else { etime = 0.00001; // used if RREQ is dropped } } break; case RREP: rrepmsg = (RREPMsg*) nwkmsg->msg; intermed = nwkmsg->intermed; if (VERBOSE) { mexPrintf("Node#%d got an RREP from Node#%d for destination#%d\n", myID, intermed, rrepmsg->dest); } // Initialize or update forward route entry dest_entry = &(d->routing_table[rrepmsg->dest - 1]); if (!dest_entry->valid) { // No valid entry exists, initialize new if (VERBOSE) { mexPrintf("Initializing new forward entry from Node#%d to Node#%d\n", myID, rrepmsg->dest); } dest_entry->dest = rrepmsg->dest; dest_entry->nextHop = intermed; dest_entry->hops = rrepmsg->hopCnt + 1; dest_entry->destSeqNbr = rrepmsg->destSeqNbr; dest_entry->exptime = now + rrepmsg->lifetime; for (i=0; i<NBR_AODV; i++) { dest_entry->prec[i] = 0; // empty precursor list } dest_entry->valid = 1; propagate = 1; etime2 = 0.0001;; } else { // Valid forward entry already exists in table // Should it be updated? cond1 = (rrepmsg->destSeqNbr > dest_entry->destSeqNbr); cond2 = ((rrepmsg->destSeqNbr == dest_entry->destSeqNbr) && (rrepmsg->hopCnt+1 < dest_entry->hops)); if (cond1 || cond2) { // Update existing entry if (VERBOSE) { mexPrintf("Updating existing forward entry from Node#%d to Node#%d\n", myID, rrepmsg->dest); } dest_entry->nextHop = intermed; dest_entry->hops = rrepmsg->hopCnt + 1; dest_entry->destSeqNbr = rrepmsg->destSeqNbr; dest_entry->exptime = now + rrepmsg->lifetime; propagate = 1; etime2 = 0.0001; } else { // Existing entry should be kept // Do not propagate RREP if (VERBOSE) { mexPrintf("No entry updated in Node#%d\n", myID); } propagate = 0; etime2 = 0.0001;; } } etime1 = 0; if (rrepmsg->src == myID) { // Original source, no reverse entry exists if (VERBOSE) { mexPrintf("Node#%d got final RREP for route to Node#%d\n", myID, rrepmsg->dest); } // Inform AODVSend to send buffered data messages mailboxmsg = new MailboxMsg; mailboxmsg->type = ROUTE_EST; mailboxmsg->dest = rrepmsg->dest; mailboxmsg->datamsg = NULL; ttTryPost("AODVSndBox", mailboxmsg); etime1 = 0.0001; } else if (propagate) { // Update reverse entry from info in RREP // and get next hop towards source src_entry = &(d->routing_table[rrepmsg->src - 1]); src_entry->exptime = now + rrepmsg->lifetime; src_entry->prec[intermed-1] = 1; // the node that sent the RREP is a precursor towards the src nextHop = src_entry->nextHop; // Update precursor list for forward entry dest_entry->prec[nextHop-1] = 1; // the node that will rcv next RREP is a precursor towards the dest // Update RREP to continue back propagation rrepmsg->hopCnt++; nwkmsg = new GenericNwkMsg; nwkmsg->type = RREP; nwkmsg->intermed = myID; nwkmsg->msg = rrepmsg; ttSendMsg(1, nextHop, nwkmsg, 20*8); // 20 bytes etime1 = 0.0001;; } updateExpiryTimer(d->routing_table, d->dataTimer, myID); etime = etime1 + etime2; break; case RERR: rerrmsg = (RERRMsg*) nwkmsg->msg; intermed = nwkmsg->intermed; if (VERBOSE) { mexPrintf("Node#%d got an RERR from Node#%d for destination#%d\n", myID, intermed, rerrmsg->dest); } // Propagate RERR? dest_entry = &(d->routing_table[rerrmsg->dest - 1]); if (dest_entry->valid && dest_entry->nextHop == intermed) { // Should send RERR to all nodes in precursor list (neighbors) for (i=0; i<NBR_AODV; i++) { if (dest_entry->prec[i]) { // Node i+1 uses this node as next hop towards dest, send RERR rerrmsg2 = new RERRMsg; rerrmsg2->dest = dest_entry->dest; rerrmsg2->destSeqNbr = dest_entry->destSeqNbr; rerrmsg2->receiver = i+1; d->RERRlist->appendNode(new DataNode(rerrmsg2, "")); } } // Invalidate route if (VERBOSE) { mexPrintf("Node#%d invalidating route to Node#%d through Node#%d\n", myID, rerrmsg->dest, intermed); } dest_entry->valid = 0; } etime = 0.0001;; break; case HELLO: hellomsg = (HelloMsg*) nwkmsg->msg; intermed = nwkmsg->intermed; //delete nwkmsg; if (VERBOSE) { mexPrintf("Time: %f Node#%d got a hello message from Node#%d\n", now, myID, hellomsg->dest); } // Update time stamp for last HELLO msg d->dataHello->nbors[hellomsg->dest - 1] = 1; d->dataHello->lastHello[hellomsg->dest - 1] = now; etime = 0.0001;; } } return etime; case 2: // Send next RERR, if any dn = (DataNode*) d->RERRlist->getFirst(); if (dn != NULL) { // Retrieve next RERR in list rerrmsg = (RERRMsg*) dn->data; dn->remove(); delete dn; // Send RERR to receiver nwkmsg = new GenericNwkMsg; nwkmsg->type = RERR; nwkmsg->intermed = myID; nwkmsg->msg = rerrmsg; if (VERBOSE) { mexPrintf("Node#%d sending RERR to Node#%d\n", myID, rerrmsg->receiver); } ttSendMsg(1, rerrmsg->receiver, nwkmsg, 12*8); // 12 bytes ttSleep(0.001); return 0.0001; } else { return FINISHED; } case 3: ttSetNextSegment(2); return 0.0001; } return FINISHED; // to supress compilation warnings }
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; } }