libFAUDES

Sections

Index

iop_sdevice.cpp

Go to the documentation of this file.
00001 /** @file iop_sdevice.cpp Virtual device for interface definition  */
00002 
00003 /*
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008, Thomas Moor
00007    Exclusive copyright is granted to Klaus Schmidt
00008 
00009 */
00010 
00011 
00012 
00013 #include "iop_sdevice.h"
00014 #include "sys/time.h"
00015 #include "sp_densityfnct.h"
00016 
00017 // fix windows/mingw definition
00018 #ifdef FAUDES_WINEXTRA
00019 #define sleep(sec) Sleep((sec) * 1000)
00020 #define usleep(usec) Sleep((usec) / 1000)
00021 #endif
00022 
00023 namespace faudes {
00024 
00025 
00026 /*
00027  **********************************************
00028  **********************************************
00029  **********************************************
00030 
00031  implementation: AttributeSignalActuator
00032 
00033  **********************************************
00034  **********************************************
00035  **********************************************
00036  */
00037 
00038 // faudes type std
00039 FAUDES_TYPE_IMPLEMENTATION(AttributeSignalActuator,AttributeVoid,)
00040 
00041 //DoAssign(Src)
00042 AttributeSignalActuator& AttributeSignalActuator::DoAssign(const AttributeSignalActuator& rSrcAttr) {
00043   FD_DHV("AttributeSignalActuator(" << this << "):DoAssign(): assignment from " <<  &rSrcAttr);
00044   mActions=rSrcAttr.mActions;
00045   return *this;
00046 }
00047 
00048 //DoWrite(rTw);
00049 void AttributeSignalActuator::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00050   (void) rLabel; (void) pContext;
00051   //dummy for token-io
00052   
00053   FD_DHV("AttributeSignalActuator::DoWrite()");
00054   rTw.WriteBegin("Actuator");
00055   rTw.WriteBegin("Actions");
00056   std::vector<Action>::const_iterator ait;
00057 
00058   for(ait=mActions.begin(); ait!=mActions.end(); ait++) {
00059     rTw << (Idx) ait->mBit;
00060     if(ait->mValue) rTw.WriteOption("Set");
00061     else rTw.WriteOption("Clr");
00062   }
00063   rTw.WriteEnd("Actions");
00064   rTw.WriteEnd("Actuator ");
00065 }
00066 
00067 
00068 //DoRead(rTr)
00069 void AttributeSignalActuator::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00070   (void) rLabel; (void) pContext;
00071   //dummy for token-io
00072 
00073   FD_DHV("AttributeSignalActuator::DoRead()");
00074   // clear
00075   mActions.clear();
00076   // test for actuator section
00077   Token token;
00078   rTr.Peek(token);
00079   if(token.Type()!=Token::Begin) return;
00080   if(token.StringValue()!="Actuator") return;
00081   // read actuator section
00082   rTr.ReadBegin("Actuator");
00083   bool err=false;
00084   rTr.ReadBegin("Actions");
00085   while(!rTr.Eos("Actions")) {
00086     // action
00087     Action action;
00088     // 1: bit address
00089     action.mBit=rTr.ReadInteger();
00090     // 2: value
00091     std::string value=rTr.ReadOption();
00092     if(value== "Set") {
00093       action.mValue=true;
00094     } else if(value == "Clr") {
00095       action.mValue=false;
00096     } else {
00097       err=true;
00098       break;
00099     }
00100     // 3. record
00101     mActions.push_back(action);
00102   }
00103   // done
00104   rTr.ReadEnd("Actions");
00105   rTr.ReadEnd("Actuator");
00106   // report error
00107   if(err) {
00108     std::stringstream errstr;
00109     errstr << "invalid actuator event property" << rTr.FileLine();
00110     throw Exception("AttributeSignalActuator::Read", errstr.str(), 52);  //52 oder 352
00111   }
00112 
00113 }//DoRead
00114 
00115 
00116 /*
00117  **********************************************
00118  **********************************************
00119  **********************************************
00120 
00121  implementation: AttributeSignalSensor
00122 
00123  **********************************************
00124  **********************************************
00125  **********************************************
00126  */
00127 
00128 
00129 // faudes type std
00130 FAUDES_TYPE_IMPLEMENTATION(AttributeSignalSensor,AttributeVoid,)
00131 
00132 
00133 //DoAssign(Src)
00134 AttributeSignalSensor& AttributeSignalSensor::DoAssign(const AttributeSignalSensor& rSrcAttr) {
00135   FD_DHV("AttributeSignalSensor(" << this << "):DoAssign(): assignment from " <<  &rSrcAttr);
00136   mTriggers=rSrcAttr.mTriggers;
00137   return *this;
00138 }
00139 
00140 
00141 //DoWrite(rTw,rLabel,pContext)
00142 void AttributeSignalSensor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00143   (void) rLabel; (void) pContext;
00144   //dummy for token-io
00145 
00146   FD_DHV("AttributeSignalSensor()::DoWrite()");
00147   rTw.WriteBegin("Sensor");
00148   rTw.WriteBegin("Triggers");
00149   std::vector<Trigger>::const_iterator ait;
00150   for(ait=mTriggers.begin(); ait!=mTriggers.end(); ait++) {
00151     rTw << ((Idx) ait->mBit);
00152     if(ait->mPos &&  (!ait->mNeg)) {
00153       rTw.WriteOption("PosEdge");
00154     }
00155     if((!ait->mPos) &&  ait->mNeg) {
00156       rTw.WriteOption("NegEdge");
00157     }
00158     if((ait->mPos) &&  ait->mNeg) {
00159       rTw.WriteOption("AnyEdge");
00160     }
00161   }
00162   rTw.WriteEnd("Triggers");
00163   rTw.WriteEnd("Sensor");
00164 }//DoWrite(rTw,rLabel,pContext)
00165 
00166 
00167 //DoRead(rTr,rLabel,pContext)
00168 void AttributeSignalSensor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00169   (void) rLabel; (void) pContext;
00170   //dummy for token-io
00171 
00172   FD_DHV("AttributeSignalSensor()::DoRead(tr)");
00173   // clear
00174   mTriggers.clear();
00175   // test for sensor section
00176   Token token;
00177   rTr.Peek(token);
00178   if(token.Type()!=Token::Begin) return;
00179   if(token.StringValue()!="Sensor") return;
00180   // read sensor section
00181   rTr.ReadBegin("Sensor");
00182   bool err=false;
00183   rTr.ReadBegin("Triggers");
00184   while(!rTr.Eos("Triggers")) {
00185     // trigger
00186     Trigger trigger;
00187     // 1: bit address
00188     trigger.mBit=rTr.ReadInteger();
00189     // 2: value
00190     std::string value=rTr.ReadOption();
00191     if (value == "PosEdge") {
00192       trigger.mPos=true;
00193       trigger.mNeg=false;
00194     } else if (value == "NegEdge") {
00195       trigger.mPos=false;
00196       trigger.mNeg=true;
00197     } else if (value == "AnyEdge") {
00198       trigger.mPos=true;
00199       trigger.mNeg=true;
00200     } else {
00201       err=true;
00202       break;
00203     }
00204     // 3. record
00205     mTriggers.push_back(trigger);
00206   }
00207   // done
00208   rTr.ReadEnd("Triggers");
00209   rTr.ReadEnd("Sensor");
00210   // report error
00211   if(err) {
00212     std::stringstream errstr;
00213     errstr << "invalid sensor event property" << rTr.FileLine();
00214     throw Exception("AttributeSignalSensor::Read", errstr.str(), 52);
00215   }
00216 }
00217 
00218 
00219 
00220 /*
00221  **********************************************
00222  **********************************************
00223  **********************************************
00224 
00225  implementation: AttributeSignalEvent
00226 
00227  **********************************************
00228  **********************************************
00229  **********************************************
00230  */
00231 
00232 
00233 // statics
00234 AttributeSignalActuator AttributeSignalEvent::sActuatorPrototype;
00235 AttributeSignalSensor AttributeSignalEvent::sSensorPrototype;
00236 
00237 // std faudes type
00238 FAUDES_TYPE_IMPLEMENTATION(AttributeSignalEvent,AttributeDeviceEvent,)
00239 
00240 // Default constructor, set my prototypes
00241 AttributeSignalEvent::AttributeSignalEvent(void) : AttributeDeviceEvent() {
00242   FD_DHV("AttributeSignalEvent::AttributeSignalEvent(" << this << ")");
00243   pActuatorPrototype=&sActuatorPrototype;
00244   pSensorPrototype=&sSensorPrototype;
00245 }
00246 
00247 // Copy constructor 
00248 AttributeSignalEvent::AttributeSignalEvent(const AttributeSignalEvent& rOtherAttr) : 
00249   AttributeDeviceEvent() 
00250 {
00251   FD_DHV("AttributeSimplenetEvent(" << this << "): form other attr " <<  &rOtherAttr);
00252   pActuatorPrototype=&sActuatorPrototype;
00253   pSensorPrototype=&sSensorPrototype;
00254   DoAssign(rOtherAttr);
00255 }
00256 
00257 
00258 /*
00259  **********************************************
00260  **********************************************
00261  **********************************************
00262 
00263  implementation: sDevice
00264 
00265  **********************************************
00266  **********************************************
00267  **********************************************
00268  */
00269 
00270 
00271 ////////////////////////////////////////////////
00272 // construction and destruction
00273 
00274 //sDevice()
00275 sDevice::sDevice(void) : vDevice() {
00276   // constructor
00277 
00278   FD_DHV("sDevice(" << mName << ")::sDevice()");
00279   // have event set with appropriate attributes
00280   mpConfiguration = new TaNameSet<AttributeSignalEvent>;
00281   pConfiguration = dynamic_cast< TaNameSet<AttributeSignalEvent>* >(mpConfiguration);
00282   // have appropriate default label for token io
00283   mDefaultLabel ="SignalDevice";
00284   // my signal data
00285   mMaxBitAddress=0;
00286   mpSensorEdges=0;
00287   mpRecentSensorEdges=0;
00288   // background thread:
00289   // install mutex
00290   pthread_mutex_init(&mMutex, NULL);
00291   // configuration defaults
00292   mName="SignalDevice";
00293   mCycleTime=1000; // 1ms
00294   mTimeScale=500;  // 500ms is one faudes time unit
00295 }
00296 
00297 
00298 //~sDevice()
00299 sDevice::~sDevice(void) {
00300   // destructor
00301 
00302   FD_DHV("sDevice(" << mName << ")::~sDevice()");
00303   //cancel background thread: destroy mutex
00304   pthread_mutex_destroy(&mMutex);
00305   // invalidate data
00306   if(mpSensorEdges) delete mpSensorEdges;
00307   if(mpRecentSensorEdges) delete mpRecentSensorEdges;
00308 }
00309 
00310 
00311 //DoWritePreface(rTw,rLabel,pContext)
00312 void sDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel,  const Type* pContext) const {
00313   
00314   FD_DHV("sDevice("<<mName<<")::DoWritePreface()");
00315   //call base
00316   vDevice::DoWritePreface(rTw,rLabel,pContext);
00317   //write max bitaddress and cycle-time of background task
00318   rTw.WriteInteger(mMaxBitAddress);
00319   rTw.WriteInteger(mCycleTime);
00320 }
00321 
00322 //DoReadPreface(rTr,rLabel,pContext)
00323 void sDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
00324   
00325   FD_DHV("sDevice("<<mName<<")::DoReadPreface()");
00326   //call base
00327   vDevice::DoReadPreface(rTr,rLabel,pContext);
00328   //read max bitaddress and cycle-time of background task
00329   //TODO: sollte man doch eigentlich ausrechnen k�nen
00330   mMaxBitAddress = rTr.ReadInteger();
00331   mCycleTime = rTr.ReadInteger();
00332 }
00333 
00334 
00335 
00336 
00337 
00338 // lock - unlock shortcuts;
00339 #define LOCK_E  {int rc = pthread_mutex_lock(&mMutex); \
00340   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: lock mutex error\n"); exit(1); }}
00341 #define UNLOCK_E  {int rc = pthread_mutex_unlock(&mMutex); \
00342   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: unlock mutex error\n"); exit(1); }}
00343 
00344 
00345 #define TLOCK_E  {int rc = pthread_mutex_lock(&sdevice->mMutex); \
00346   if(rc) {FD_ERR("sDevice::TLOCK_E: lock mutex error\n"); exit(1); }}
00347 
00348 #define TUNLOCK_E  {int rc = pthread_mutex_unlock(&sdevice->mMutex); \
00349   if(rc) {FD_ERR("sDevice::TLOCK_E: unlock mutex error\n"); exit(1); }}
00350 
00351 
00352 
00353 
00354 
00355 // Start(void)
00356 void sDevice::Start(void) {
00357   //set device state and create thread
00358 
00359   //return if device was allready started
00360   if( (mState == Up)||(mState == StartUp) )  return;
00361   FD_DHV("sDevice("<<mName<<")::Start()");
00362   //call base
00363   vDevice::Start();
00364   //dont create thread if device-purpose is not to handle input-signals
00365   if(!Sensors().Empty()){
00366     mCancelRequest = false;
00367     //setup thread attribute
00368     pthread_attr_t attr;
00369     pthread_attr_init(&attr);
00370     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00371     //create thread
00372     int rc  = pthread_create(&mThreadSynchro, &attr, SDeviceSynchro, this);
00373     if (rc) {
00374       FD_ERR("sDevice("<<mName<<")::Start(): cannot creat thread\n");
00375       exit(1);
00376     }
00377     //destroy thread-attribute
00378     pthread_attr_destroy(&attr);
00379   }
00380 }
00381 
00382 // Stop()
00383 void sDevice::Stop(void) {
00384   //set device state and kill thread
00385 
00386   //return if device allready got the command to shut down
00387   if(mState != Up && mState !=StartUp)  return;
00388   FD_DHV("sDevice("<<mName<<")::Stop()");
00389   //dont kill thread if no thread was created
00390   if(!Sensors().Empty()) {
00391     //cancle thread
00392     LOCK_E;
00393     mCancelRequest=true;
00394     UNLOCK_E;
00395     int pc = pthread_join(mThreadSynchro,NULL);
00396     if (pc) {
00397       FD_ERR("sDevice("<<mName<<")::Stop(): cannot join  thread??\n");
00398     }
00399   }
00400   // call base
00401   vDevice::Stop();
00402 }//end Stop()
00403 
00404 
00405 //Reset()
00406 void sDevice::Reset(){
00407   //delete dynamic data
00408 
00409   FD_DHV("sDevice("<<mName<<")::Reset()");
00410   // call base (resets time)
00411   vDevice::Reset();
00412   //delete dynamic data
00413   ClrSensorSignals();
00414   ClrActuatorSignals();
00415 }
00416 
00417 // Clear()
00418 void sDevice::Clear(void) {
00419   //delete static data
00420 
00421   FD_DHV("sDevice(" << mName << ")::Clear()");
00422   // call base; note: clear implies stop
00423   vDevice::Clear();
00424   // clear compiled data
00425   mSensorPosEdgeIndexMap.clear();
00426   mSensorNegEdgeIndexMap.clear();
00427   mMaxBitAddress=0;
00428 }
00429 
00430 //Compile(void)
00431 void sDevice::Compile(void){
00432   //setup up internal data structure
00433 
00434   FD_DHV("sDevice(" << mName << ")::Compile()");
00435   // call base
00436   vDevice::Compile();
00437   // clear my internal data
00438   mSensorPosEdgeIndexMap.clear();
00439   mSensorNegEdgeIndexMap.clear();
00440   mMaxBitAddress=0;
00441   // setup my internal data
00442   for(EventSet::Iterator eit=pConfiguration->Begin(); eit!=pConfiguration->End(); eit++) {
00443     AttributeSignalEvent attr = pConfiguration->Attribute(*eit);
00444     if(attr.IsSensor()) {
00445       // fill in reverse maps
00446       std::vector<AttributeSignalSensor::Trigger>::const_iterator ait;
00447       const AttributeSignalSensor* sattr = attr.Sensorp();
00448       for(ait=sattr->mTriggers.begin(); ait!=sattr->mTriggers.end(); ait++) {
00449         if(ait->mPos) mSensorPosEdgeIndexMap[ait->mBit].Insert(*eit);
00450         if(ait->mNeg) mSensorNegEdgeIndexMap[ait->mBit].Insert(*eit);
00451         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00452       }
00453     }
00454     // check max address
00455     if(attr.IsActuator()) {
00456       std::vector<AttributeSignalActuator::Action>::const_iterator ait;
00457       const AttributeSignalActuator* aattr = attr.Actuatorp();
00458       for(ait=aattr->mActions.begin(); ait!=aattr->mActions.end(); ait++) {
00459         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00460       }
00461     }
00462   }
00463   // prep state data
00464   if(mpSensorEdges) delete mpSensorEdges;
00465   if(mpRecentSensorEdges) delete mpRecentSensorEdges;
00466   mpSensorEdges = new Edges[mMaxBitAddress+1];
00467   mpRecentSensorEdges = new Edges[mMaxBitAddress+1];
00468 }
00469 
00470 //CycleTime(void)
00471 int sDevice::CycleTime(void) const {
00472   //Report current cycle time
00473   
00474   FD_DHV("sDevice(" << mName << ")::CycleTime()");
00475   return mCycleTime;
00476 }
00477 
00478 //CycleTime(int)
00479 void sDevice::CycleTime(int cycleTime) {
00480   //Set cycle time
00481   FD_DHV("sDevice(" << mName << ")::CycleTime(int)");
00482   if( mState==Up || mState==StartUp){
00483     std::stringstream errstr;
00484     errstr << "Changing cycle-time not possible while background thread is still running ";
00485     throw Exception("sDevice::CycleTime: ", errstr.str(), 100);
00486   }
00487   mCycleTime = cycleTime;
00488 }
00489 
00490 
00491 //ReadSignal(int)
00492 bool sDevice::ReadSignal(int bit){
00493   FD_DH("sDevice(" << mName << ")::ReadSignal(int)");
00494 
00495   // make sure device is able to read signals
00496   if(Sensors().Empty()){
00497     std::stringstream errstr;
00498     errstr << "(" << mName << ") is not able to read signals";
00499     throw Exception("sDevice::ReadSignal():", errstr.str(), 552);  //TODO: number!
00500   }
00501 
00502   // run with hooks
00503   bool res=false;
00504   if(DoReadSignalsPre())
00505     res=DoReadSignal(bit);
00506   DoReadSignalsPost();
00507 
00508   return res;
00509 }
00510 
00511 //WriteSignal(int,int)
00512 void sDevice::WriteSignal(int bit, bool value){
00513   // write one actor value, adressed by bit number (0 to 63);
00514 
00515   FD_DHV("sDevice(" << mName << ")::WriteSignal(int)");
00516   // make sure device is able to read signals
00517   if(Actuators().Empty()){
00518     std::stringstream errstr;
00519     errstr << "(" << mName << ") is not able to write signals";
00520     throw Exception("sDevice::WriteSignal():", errstr.str(), 552);  //TODO: number!
00521   }
00522 
00523   // run with hooks
00524   if(DoWriteSignalsPre())
00525     DoWriteSignal(bit,value);
00526   DoWriteSignalsPost();
00527 }
00528 
00529 
00530 //SDeviceSynchro(void*)
00531 void* SDeviceSynchro(void* arg){
00532   //background-thread main-routine
00533 
00534   // cast this object
00535   sDevice* sdevice = static_cast<sDevice*>(arg);
00536 
00537   FD_DHV("sDevice(" << sdevice->mName << ")::Synchro(" << sdevice << "): with ct " << sdevice->mCycleTime);
00538 
00539   /////////////////////////////////////////////////////
00540   //  cyletime-measurement
00541   //  timeA: time consumed for a hole cycle
00542   //  timeB: time consumed by computation
00543   //  timeC: real time consumed by usleep
00544   ////////////////////////////////////////////////////
00545 #ifdef FAUDES_DEBUG_IOTIMING_X
00546   //arrays to store measured time in
00547   timeval* timeA = new timeval[MAX_SAMPLES];
00548   timeval* timeB = new timeval[MAX_SAMPLES];
00549   timeval* timeC = new timeval[MAX_SAMPLES];
00550         // define local itterator
00551   int itime=0;
00552   // take time
00553   gettimeofday(timeA+itime,0);
00554 #endif
00555 
00556   bool running=true;
00557 
00558   while(running){
00559     // lock global variables
00560     TLOCK_E;
00561     if(sdevice->DoReadSignalsPre()) {
00562       // edge detection, accumulative
00563       for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
00564         // define pointer to Sensoredges
00565         sDevice::Edges* edge= &sdevice->mpSensorEdges[bit];
00566         // pass edge-info about edge in last cycle
00567         edge->past = edge->current;
00568         // and get corresponding sensor-value
00569         edge->current = sdevice->ReadSignal(bit);
00570         if(edge->posrel)
00571     if( edge->current && (!edge->past) ) {
00572       /*
00573         if(edge->pos && (!edge->lost)) {
00574         FD_DH("sDevice::synchro: lost positive edge at bit address "  << bit);
00575         edge->lost=true;
00576         }
00577       */
00578       FD_DH("sDevice::synchro: sensed positive edge at bit address "  << bit);
00579       edge->pos = true;
00580       // queue events to buffer
00581       pthread_mutex_lock(sdevice->pBufferMutex);
00582       EventSet::Iterator eit=sdevice->mSensorPosEdgeIndexMap[bit].Begin();
00583       EventSet::Iterator eit_end=sdevice->mSensorPosEdgeIndexMap[bit].End();
00584       for(; eit!=eit_end; eit++) {
00585         sdevice->pSensorBuffer->push_back(*eit);
00586       }
00587       pthread_mutex_unlock(sdevice->pBufferMutex);
00588       //send signal to function "WaitSenosrs()"
00589       FD_DH("sDevice::synchro: send signal " );
00590       pthread_cond_broadcast(sdevice->pWaitCondition);
00591     }
00592         if(edge->negrel)
00593     if( (!edge->current) && edge->past ) {
00594       FD_DH("sDevice::synchro: sensed negative edge at bit address "  << bit);
00595       edge->neg = true;
00596       sdevice->mSensorReady = true;
00597       // queue events to buffer
00598       pthread_mutex_lock(sdevice->pBufferMutex);
00599       EventSet::Iterator eit=sdevice->mSensorNegEdgeIndexMap[bit].Begin();
00600       EventSet::Iterator eit_end=sdevice->mSensorNegEdgeIndexMap[bit].End();
00601       for(; eit!=eit_end; eit++) {
00602         sdevice->pSensorBuffer->push_back(*eit);
00603       }
00604       pthread_mutex_unlock(sdevice->pBufferMutex);
00605       //send signal to function "WaitSenosrs"
00606       FD_DH("sDevice::synchro: send signal " );
00607       pthread_cond_broadcast(sdevice->pWaitCondition);
00608     }
00609       } // loop bits
00610     } // if device ok
00611           sdevice->DoReadSignalsPost();
00612     // check for cancel request
00613     if(sdevice->mCancelRequest) running=false;
00614     // unlock global variables
00615     TUNLOCK_E;
00616 
00617     //////////////////////////////////////
00618     //cycletime measurement
00619     //measure time to perform computation
00620 #ifdef FAUDES_DEBUG_IOTIMING_X
00621     if(itime < MAX_SAMPLES) gettimeofday(timeB+itime,0);
00622 #endif
00623 
00624     // let time pass; todo: use proper timer
00625     usleep(sdevice->mCycleTime);
00626 
00627 #ifdef FAUDES_DEBUG_IOTIMING_X
00628     //////////////////////////////////////
00629     // cycletime measurement
00630 
00631     // measure time consumed by wait
00632     if(itime < MAX_SAMPLES)   gettimeofday(timeC+itime,0);
00633     // measure time needed for a hole cyle
00634     // increase iterator
00635     itime++;
00636     if(itime < MAX_SAMPLES)   gettimeofday(timeA+itime,0);
00637 
00638 #endif
00639     // count cycles
00640     sdevice->mCycleCount++;
00641   } // loop while running
00642 
00643 
00644 #ifdef FAUDES_DEBUG_IOTIMING_X
00645 
00646   /////////////////////////////////////////////
00647   // cycletime measurement
00648   // analysis using SampleDensityFunction
00649         FD_DHT("sDevice::synchro: performance analysis");
00650 
00651   SampledDensityFunction SamplesA;
00652   SamplesA.Clear();
00653         SamplesA.Dim(100);
00654         SamplesA.Name("time stamp AA: overall period");
00655 
00656   SampledDensityFunction SamplesB;
00657         SamplesB.Clear();
00658   SamplesB.Dim(100);
00659         SamplesB.Name("time stamp AB: process time");
00660 
00661   SampledDensityFunction SamplesC;
00662   SamplesC.Clear();
00663         SamplesC.Dim(100);
00664         SamplesC.Name("time stamp CB: waited time");
00665 
00666   SampledDensityFunction SamplesWS;
00667   SamplesWS.Clear();
00668   SamplesWS.Dim(100);
00669   SamplesWS.Name("time passed till the next call of WaitSensors");
00670 
00671   // timeval-structures needed for further computations
00672   timeval dAA,dBA,dCB,dER;
00673 
00674   // perform analysis
00675   // time for a hole cycle
00676   for(int ind = 0; ind < itime-2; ind++){
00677     // compute time needed
00678     // for a hole cycle
00679     dAA = vDevice::DiffTime(timeA[ind+1],timeA[ind]);
00680     // for coputing sensor-state
00681     dBA = vDevice::DiffTime(timeB[ind],timeA[ind]);
00682     // by usleep(mCyleTime)
00683     dCB = vDevice::DiffTime(timeC[ind],timeB[ind]);
00684     // time passed by until the next call of WaitSensors
00685     dER = vDevice::DiffTime(sdevice->mptimeBegin[ind+1],sdevice->mptimeEnd[ind]);
00686     // add computed samples to corresponding
00687     // SampleDensityFunction classes
00688     SamplesA.Sample(dAA.tv_sec*1000000 + dAA.tv_usec);
00689     SamplesB.Sample(dBA.tv_sec*1000000 + dBA.tv_usec);
00690     SamplesC.Sample(dCB.tv_sec*1000000 + dCB.tv_usec);
00691     SamplesWS.Sample(1000000*dER.tv_sec + dER.tv_usec);
00692   }
00693 
00694   // perform statistic computation
00695         SamplesA.Compile();
00696         SamplesB.Compile();
00697   SamplesC.Compile();
00698   SamplesWS.Compile();
00699 
00700   // token output
00701   // SamplesA.Write();
00702   // SamplesB.Write();
00703   // SamplesC.Write();
00704   // SamplesWS.Write();
00705 
00706         // pretty output
00707         std::cout << SamplesA.Str() << std::endl;
00708         std::cout << SamplesB.Str() << std::endl;
00709         std::cout << SamplesC.Str() << std::endl;
00710   std::cout <<  SamplesWS.Str() << std::endl;
00711 #endif
00712   FD_DH("sDevice(" << sdevice->mName << ")::synchro: terminate background thread");
00713   pthread_exit(NULL);
00714   // never happens, prevent gcc warning
00715   return NULL; 
00716 }
00717 
00718 // Write Actuator(Idx)
00719 void sDevice::WriteActuator(Idx actuator) {
00720 
00721   FD_DHV("sDevice("<<mName<<")::WriteActuator");
00722   //return if device is running
00723   if(mState!=Up && mState!=StartUp) return;
00724   //make sure event is part of devices eventset
00725   if(!mActuators.Exists(actuator)) {
00726     std::stringstream errstr;
00727     errstr << "Unknown actuator event " << actuator;
00728     throw Exception("sDevice::WriteActuator", errstr.str(), 65);
00729   }
00730   // find properties
00731   const AttributeSignalActuator* aattr = pConfiguration->Attribute(actuator).Actuatorp();
00732   if(!aattr) {
00733     std::stringstream errstr;
00734     errstr << "Invalid actuator attribute " << actuator;
00735     throw Exception("sDevice::WriteActuator", errstr.str(), 65);
00736   }
00737   //debug-flag
00738   FD_DH("sDevice("<<mName<<")::WriteActuator: properties found");
00739   //execute command
00740   std::vector<AttributeSignalActuator::Action>::const_iterator eit;
00741   // run with hooks
00742   if(DoWriteSignalsPre()) {
00743     for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
00744       FD_DH("sDevice("<<mName<<")::WriteActuator: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
00745       DoWriteSignal(eit->mBit,eit->mValue);
00746     }
00747   }
00748   DoWriteSignalsPost();
00749   FD_DHV("sDevice("<<mName<<")::WriteActuator: done");
00750 }
00751 
00752 //ClrSensorSignals()
00753 void sDevice::ClrSensorSignals(void) {
00754   //helper: clear all sensor state
00755 
00756   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): MaxBitAddress: " << mMaxBitAddress);
00757   //return if device is not running or device is not able to read sensors
00758   if(!(mState!=Up||Sensors().Empty())) {
00759     // lock global variables
00760     FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): lock mutex ");
00761     LOCK_E;
00762     FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): edge detection ");
00763     // initialise edge detection
00764     for(int bit = 0;bit<=mMaxBitAddress;bit++) {
00765       Edges* edge= &mpSensorEdges[bit];
00766       FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): edge detetion ReadSignal bit "  << bit);
00767       edge->current=ReadSignal(bit);
00768       edge->past = edge->current;
00769       edge->pos =    false;
00770       edge->neg =    false;
00771       edge->posrel = (!mSensorPosEdgeIndexMap[bit].Empty());
00772       edge->negrel = (!mSensorNegEdgeIndexMap[bit].Empty());
00773       edge->lost =    false;
00774     }
00775     // initialize recent edges
00776     FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): initialize recent edges ");
00777     for(int bit = 0;bit<=mMaxBitAddress;bit++) {
00778       Edges* redge= &mpRecentSensorEdges[bit];
00779       redge->pos =    false;
00780       redge->neg =    false;
00781       redge->posrel = false;
00782       redge->negrel = false;
00783       redge->lost =   false;
00784     }
00785     // reset cyclecount
00786     mCycleCount=0;
00787     mRecentCycleCount=0;
00788     mSensorReady=false;
00789     // unlock global variables
00790     UNLOCK_E;
00791   }
00792   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): done");
00793 }
00794 
00795 //ClrActuatorSignals()
00796 void sDevice::ClrActuatorSignals(void) {
00797   //clear all actuator lines
00798   FD_DHV("sDevice("<<mName<<")::ClrActuatorSignals");
00799   //return if device is running or not abel to set actuator signals
00800   if(!(mState!=Up||Actuators().Empty())){
00801     //stop all actuators
00802     for(int bit=0; bit<=mMaxBitAddress; bit++)  WriteSignal(bit, false);
00803   }
00804 }
00805 
00806 }//end namespace faudes
00807 
00808 

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6