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   mpActuatorLevels=0;
00289   // background thread:
00290   // install mutex
00291   pthread_mutex_init(&mMutex, NULL);
00292   // configuration defaults
00293   mName="SignalDevice";
00294   mCycleTime=1000; // 1ms
00295   mTimeScale=500;  // 500ms is one faudes time unit
00296   mSyncWrite=false;
00297 }
00298 
00299 
00300 //~sDevice()
00301 sDevice::~sDevice(void) {
00302   // destructor
00303 
00304   FD_DHV("sDevice(" << mName << ")::~sDevice()");
00305   //cancel background thread: destroy mutex
00306   pthread_mutex_destroy(&mMutex);
00307   // invalidate data
00308   if(mpSensorEdges) delete mpSensorEdges;
00309   if(mpRecentSensorEdges) delete mpRecentSensorEdges;
00310   if(mpActuatorLevels) delete mpActuatorLevels;
00311 }
00312 
00313 
00314 //DoWritePreface(rTw,rLabel,pContext)
00315 void sDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel,  const Type* pContext) const {
00316   
00317   FD_DHV("sDevice("<<mName<<")::DoWritePreface()");
00318   //call base
00319   vDevice::DoWritePreface(rTw,rLabel,pContext);
00320   //write max bitaddress and cycle-time of background task
00321   rTw.WriteInteger(mMaxBitAddress);
00322   rTw.WriteInteger(mCycleTime);
00323   // write sync option
00324   if(mSyncWrite) rTw.WriteOption("SyncWrite");
00325 }
00326 
00327 //DoReadPreface(rTr,rLabel,pContext)
00328 void sDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
00329   
00330   FD_DHV("sDevice("<<mName<<")::DoReadPreface()");
00331   // call base
00332   vDevice::DoReadPreface(rTr,rLabel,pContext);
00333   // read max bitaddress and cycle-time of background task
00334   mMaxBitAddress = rTr.ReadInteger();
00335   mCycleTime = rTr.ReadInteger();
00336   // figure sync option
00337   mSyncWrite=false;
00338   Token token;
00339   rTr.Peek(token);
00340   if(token.Type()==Token::Option)
00341   if(token.StringValue()=="SyncWrite") {
00342     rTr.Get(token);
00343     mSyncWrite=false;
00344   }
00345 }
00346 
00347 
00348 
00349 
00350 
00351 // lock - unlock shortcuts;
00352 #define LOCK_E  {int rc = pthread_mutex_lock(&mMutex); \
00353   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: lock mutex error\n"); exit(1); }}
00354 #define UNLOCK_E  {int rc = pthread_mutex_unlock(&mMutex); \
00355   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: unlock mutex error\n"); exit(1); }}
00356 
00357 
00358 #define TLOCK_E  {int rc = pthread_mutex_lock(&sdevice->mMutex); \
00359   if(rc) {FD_ERR("sDevice::TLOCK_E: lock mutex error\n"); exit(1); }}
00360 
00361 #define TUNLOCK_E  {int rc = pthread_mutex_unlock(&sdevice->mMutex); \
00362   if(rc) {FD_ERR("sDevice::TLOCK_E: unlock mutex error\n"); exit(1); }}
00363 
00364 
00365 
00366 
00367 
00368 // Start(void)
00369 void sDevice::Start(void) {
00370   //set device state and create thread
00371 
00372   //return if device was allready started
00373   if( (mState == Up)||(mState == StartUp) )  return;
00374   FD_DHV("sDevice("<<mName<<")::Start()");
00375   //call base incl virtual reset
00376   vDevice::Start();
00377   //create thread to handle input-signals
00378   if(!Sensors().Empty()){
00379     mCancelRequest = false;
00380     //setup thread attribute
00381     pthread_attr_t attr;
00382     pthread_attr_init(&attr);
00383     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00384     //create thread
00385     int rc  = pthread_create(&mThreadSynchro, &attr, SDeviceSynchro, this);
00386     if (rc) {
00387       FD_ERR("sDevice("<<mName<<")::Start(): cannot creat thread\n");
00388       exit(1);
00389     }
00390     //destroy thread-attribute
00391     pthread_attr_destroy(&attr);
00392   }
00393 }
00394 
00395 // Stop()
00396 void sDevice::Stop(void) {
00397   //set device state and kill thread
00398 
00399   //return if device allready got the command to shut down
00400   if(mState != Up && mState !=StartUp)  return;
00401   FD_DHV("sDevice("<<mName<<")::Stop()");
00402   //dont kill thread if no thread was created
00403   if(!Sensors().Empty()) {
00404     //cancle thread
00405     LOCK_E;
00406     mCancelRequest=true;
00407     UNLOCK_E;
00408     int pc = pthread_join(mThreadSynchro,NULL);
00409     if (pc) {
00410       FD_ERR("sDevice("<<mName<<")::Stop(): cannot join  thread??\n");
00411     }
00412   }
00413   // call base
00414   vDevice::Stop();
00415 }//end Stop()
00416 
00417 
00418 //Reset()
00419 void sDevice::Reset(){
00420   //delete dynamic data
00421   FD_DHV("sDevice("<<mName<<")::Reset()");
00422   // call base (resets time)
00423   vDevice::Reset();
00424   //delete dynamic data
00425   ClrSensorSignals();
00426   ClrActuatorSignals();
00427 }
00428 
00429 // Clear()
00430 void sDevice::Clear(void) {
00431   //delete static data
00432 
00433   FD_DHV("sDevice(" << mName << ")::Clear()");
00434   // call base; note: clear implies stop
00435   vDevice::Clear();
00436   // clear compiled data
00437   mSensorPosEdgeIndexMap.clear();
00438   mSensorNegEdgeIndexMap.clear();
00439   mMaxBitAddress=0;
00440 }
00441 
00442 //Compile(void)
00443 void sDevice::Compile(void){
00444   //setup up internal data structure
00445 
00446   FD_DHV("sDevice(" << mName << ")::Compile()");
00447   // call base
00448   vDevice::Compile();
00449   // clear my internal data
00450   mSensorPosEdgeIndexMap.clear();
00451   mSensorNegEdgeIndexMap.clear();
00452   mMaxBitAddress=0;
00453   // setup my internal data
00454   for(EventSet::Iterator eit=pConfiguration->Begin(); eit!=pConfiguration->End(); eit++) {
00455     AttributeSignalEvent attr = pConfiguration->Attribute(*eit);
00456     if(attr.IsSensor()) {
00457       // fill in reverse maps
00458       std::vector<AttributeSignalSensor::Trigger>::const_iterator ait;
00459       const AttributeSignalSensor* sattr = attr.Sensorp();
00460       for(ait=sattr->mTriggers.begin(); ait!=sattr->mTriggers.end(); ait++) {
00461         if(ait->mPos) mSensorPosEdgeIndexMap[ait->mBit].Insert(*eit);
00462         if(ait->mNeg) mSensorNegEdgeIndexMap[ait->mBit].Insert(*eit);
00463         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00464       }
00465     }
00466     // check max address
00467     if(attr.IsActuator()) {
00468       std::vector<AttributeSignalActuator::Action>::const_iterator ait;
00469       const AttributeSignalActuator* aattr = attr.Actuatorp();
00470       for(ait=aattr->mActions.begin(); ait!=aattr->mActions.end(); ait++) {
00471         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00472       }
00473     }
00474   }
00475   // prep state data
00476   if(mpSensorEdges) delete mpSensorEdges;
00477   if(mpRecentSensorEdges) delete mpRecentSensorEdges;
00478   if(mpActuatorLevels) delete mpActuatorLevels;
00479   mpSensorEdges = new Edges[mMaxBitAddress+1];
00480   mpRecentSensorEdges = new Edges[mMaxBitAddress+1];
00481   mpActuatorLevels = new Levels[mMaxBitAddress+1];
00482 }
00483 
00484 //CycleTime(void)
00485 int sDevice::CycleTime(void) const {
00486   //Report current cycle time
00487   
00488   FD_DHV("sDevice(" << mName << ")::CycleTime()");
00489   return mCycleTime;
00490 }
00491 
00492 //CycleTime(int)
00493 void sDevice::CycleTime(int cycleTime) {
00494   //Set cycle time
00495   FD_DHV("sDevice(" << mName << ")::CycleTime(int)");
00496   if( mState==Up || mState==StartUp){
00497     std::stringstream errstr;
00498     errstr << "Changing cycle-time not possible while background thread is still running ";
00499     throw Exception("sDevice::CycleTime: ", errstr.str(), 100);
00500   }
00501   mCycleTime = cycleTime;
00502 }
00503 
00504 
00505 //ReadSignal(int)
00506 bool sDevice::ReadSignal(int bit){
00507   FD_DH("sDevice(" << mName << ")::ReadSignal(int)");
00508 
00509   // make sure device is able to read signals
00510   if(Sensors().Empty()){
00511     std::stringstream errstr;
00512     errstr << "(" << mName << ") is not able to read signals";
00513     throw Exception("sDevice::ReadSignal():", errstr.str(), 552);  //TODO: number!
00514   }
00515 
00516   // run with hooks
00517   bool res=false;
00518   if(DoReadSignalsPre())
00519     res=DoReadSignal(bit);
00520   DoReadSignalsPost();
00521 
00522   return res;
00523 }
00524 
00525 //WriteSignal(int,int)
00526 void sDevice::WriteSignal(int bit, bool value){
00527   // write one actor value, adressed by bit number (0 to 63);
00528   FD_DHV("sDevice(" << mName << ")::WriteSignal(int)");
00529   // make sure device supports actuators 
00530   if(Actuators().Empty()){
00531     std::stringstream errstr;
00532     errstr << "(" << mName << ") is not configured for actuators";
00533     throw Exception("sDevice::WriteSignal():", errstr.str(), 552);  
00534   }
00535   // lock global image, prevent background thread from reading/writing
00536   LOCK_E;
00537   // case a) asynchronous write
00538   if(!mSyncWrite) {
00539     if(DoWriteSignalsPre()) {
00540       DoWriteSignal(bit,value);
00541       DoWriteSignalsPost();
00542     }
00543   }
00544   // case b) synchronous write
00545   if(mSyncWrite) {
00546     // record next value
00547     Levels* level= &mpActuatorLevels[bit];
00548     level->next=value;
00549     if(level->edge) level->lost=true;
00550     level->edge=true;
00551   }
00552   // free global image
00553   UNLOCK_E;
00554 }
00555 
00556 
00557 //SDeviceSynchro(void*)
00558 void* SDeviceSynchro(void* arg){
00559   //background-thread main-routine
00560 
00561   // cast this object
00562   sDevice* sdevice = static_cast<sDevice*>(arg);
00563 
00564   FD_DHV("sDevice(" << sdevice->mName << ")::Synchro(" << sdevice << "): with ct " << sdevice->mCycleTime);
00565 
00566   /////////////////////////////////////////////////////
00567   //  cyletime-measurement
00568   //  timeA: time consumed for a hole cycle
00569   //  timeB: time consumed by computation
00570   //  timeC: real time consumed by usleep
00571   ////////////////////////////////////////////////////
00572 #ifdef FAUDES_DEBUG_IOTIMING_X
00573   //arrays to store measured time in
00574   timeval* timeA = new timeval[MAX_SAMPLES];
00575   timeval* timeB = new timeval[MAX_SAMPLES];
00576   timeval* timeC = new timeval[MAX_SAMPLES];
00577         // define local itterator
00578   int itime=0;
00579   // take time
00580   gettimeofday(timeA+itime,0);
00581 #endif
00582 
00583   bool running=true;
00584 
00585   while(running){
00586 
00587     // lock global variables
00588     TLOCK_E;
00589 
00590           // start up: initialze dynamic state
00591           if(sdevice->mState==sDevice::StartUp) {
00592             bool aready= sdevice->DoWriteSignalsPre();
00593         if(aready) {
00594               // actuator image: set to zero
00595               for(int bit=0; bit<=sdevice->mMaxBitAddress; bit++) {
00596           FD_DHV("sDevice("<<sdevice->mName<<")::synchro: reset clear line");
00597     sdevice->DoWriteSignal(bit,false);
00598                 sDevice::Levels* level= &sdevice->mpActuatorLevels[bit];
00599                 level->current=false;
00600                 level->next=false;
00601                 level->edge=false;
00602                 level->lost=false;
00603         }
00604               sdevice->DoWriteSignalsPost();
00605             }
00606             bool sready= sdevice->DoReadSignalsPre();
00607         if(sready) {
00608               // edge detection: use actual signal levels
00609               for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
00610                 sDevice::Edges* edge= &sdevice->mpSensorEdges[bit];
00611           FD_DHV("sDevice("<<mName<<")::synchro: reset edge detection");
00612                 edge->current=sdevice->DoReadSignal(bit);
00613                 edge->past = edge->current;
00614                 edge->pos =    false;
00615                 edge->neg =    false;
00616                 edge->posrel = (!sdevice->mSensorPosEdgeIndexMap[bit].Empty());
00617                 edge->negrel = (!sdevice->mSensorNegEdgeIndexMap[bit].Empty());
00618                 edge->lost =    false;
00619               }
00620               sdevice->DoReadSignalsPost();
00621               for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
00622                 sDevice::Edges* redge= &sdevice->mpRecentSensorEdges[bit];
00623                 redge->pos =    false;
00624                 redge->neg =    false;
00625                 redge->posrel = false;
00626                 redge->negrel = false;
00627                 redge->lost =   false;
00628               }
00629       }
00630             // new state
00631             if(sready && aready) 
00632               sdevice->mState=sDevice::Up;        
00633     }
00634 
00635           // normal operation, actuators
00636           if(sdevice->mState==sDevice::Up && sdevice->mSyncWrite) {
00637             bool ready=sdevice->DoWriteSignalsPre();
00638             if(!ready) 
00639               sdevice->mState=sDevice::StartUp;   
00640             if(ready) {
00641           // write values from image
00642         for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
00643           // define pointer to levels
00644           sDevice::Levels* level= &sdevice->mpActuatorLevels[bit];
00645           // not wrtiien by libfaudes
00646           if(!level->edge) continue;
00647           // write and record
00648                 sdevice->DoWriteSignal(bit,level->next);
00649           level->current = level->next;
00650           level->edge = false;
00651         }
00652               sdevice->DoWriteSignalsPost();
00653       }
00654     }
00655  
00656           // normal operation, sensors
00657           if(sdevice->mState==sDevice::Up) {
00658             bool ready=sdevice->DoReadSignalsPre();
00659             if(!ready) 
00660               sdevice->mState=sDevice::StartUp;   
00661             if(ready) {
00662           // edge detection, accumulative
00663         for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
00664           // define pointer to Sensoredges
00665           sDevice::Edges* edge= &sdevice->mpSensorEdges[bit];
00666           // pass edge-info about edge in last cycle
00667           edge->past = edge->current;
00668           // and get corresponding sensor-value
00669           edge->current = sdevice->DoReadSignal(bit);
00670           if(edge->posrel)
00671     if(edge->current && (!edge->past) ) {
00672       /*
00673         if(edge->pos && (!edge->lost)) {
00674         FD_DH("sDevice::synchro: lost positive edge at bit address "  << bit);
00675         edge->lost=true;
00676         }
00677       */
00678       FD_DH("sDevice::synchro: sensed positive edge at bit address "  << bit);
00679       edge->pos = true;
00680       // queue events to buffer
00681       pthread_mutex_lock(sdevice->pBufferMutex);
00682       EventSet::Iterator eit=sdevice->mSensorPosEdgeIndexMap[bit].Begin();
00683       EventSet::Iterator eit_end=sdevice->mSensorPosEdgeIndexMap[bit].End();
00684       for(; eit!=eit_end; eit++) {
00685         sdevice->pSensorBuffer->push_back(*eit);
00686       }
00687       pthread_mutex_unlock(sdevice->pBufferMutex);
00688       //send signal to function "WaitSenosrs()"
00689       FD_DH("sDevice::synchro: send signal " );
00690       pthread_cond_broadcast(sdevice->pWaitCondition);
00691     }
00692           if(edge->negrel)
00693     if( (!edge->current) && edge->past ) {
00694       FD_DH("sDevice::synchro: sensed negative edge at bit address "  << bit);
00695       edge->neg = true;
00696       sdevice->mSensorReady = true;
00697       // queue events to buffer
00698       pthread_mutex_lock(sdevice->pBufferMutex);
00699       EventSet::Iterator eit=sdevice->mSensorNegEdgeIndexMap[bit].Begin();
00700       EventSet::Iterator eit_end=sdevice->mSensorNegEdgeIndexMap[bit].End();
00701       for(; eit!=eit_end; eit++) {
00702         sdevice->pSensorBuffer->push_back(*eit);
00703       }
00704       pthread_mutex_unlock(sdevice->pBufferMutex);
00705       //send signal to function "WaitSenosrs"
00706       FD_DH("sDevice::synchro: send signal " );
00707       pthread_cond_broadcast(sdevice->pWaitCondition);
00708     }
00709         } // loop bits
00710               sdevice->DoReadSignalsPost();
00711       } // end-if device ok
00712     } // end-if sensors
00713  
00714  
00715     // check for cancel request
00716     if(sdevice->mCancelRequest) running=false;
00717     // unlock global variables
00718     TUNLOCK_E;
00719 
00720     //////////////////////////////////////
00721     //cycletime measurement
00722     //measure time to perform computation
00723 #ifdef FAUDES_DEBUG_IOTIMING_X
00724     if(itime < MAX_SAMPLES) gettimeofday(timeB+itime,0);
00725 #endif
00726 
00727     // let time pass; todo: use proper timer
00728     usleep(sdevice->mCycleTime);
00729 
00730 #ifdef FAUDES_DEBUG_IOTIMING_X
00731     //////////////////////////////////////
00732     // cycletime measurement
00733 
00734     // measure time consumed by wait
00735     if(itime < MAX_SAMPLES)   gettimeofday(timeC+itime,0);
00736     // measure time needed for a hole cyle
00737     // increase iterator
00738     itime++;
00739     if(itime < MAX_SAMPLES)   gettimeofday(timeA+itime,0);
00740 
00741 #endif
00742     // count cycles
00743     sdevice->mCycleCount++;
00744   } // loop while running
00745 
00746 
00747 #ifdef FAUDES_DEBUG_IOTIMING_X
00748 
00749   /////////////////////////////////////////////
00750   // cycletime measurement
00751   // analysis using SampleDensityFunction
00752         FD_DHT("sDevice::synchro: performance analysis");
00753 
00754   SampledDensityFunction SamplesA;
00755   SamplesA.Clear();
00756         SamplesA.Dim(100);
00757         SamplesA.Name("time stamp AA: overall period");
00758 
00759   SampledDensityFunction SamplesB;
00760         SamplesB.Clear();
00761   SamplesB.Dim(100);
00762         SamplesB.Name("time stamp AB: process time");
00763 
00764   SampledDensityFunction SamplesC;
00765   SamplesC.Clear();
00766         SamplesC.Dim(100);
00767         SamplesC.Name("time stamp CB: waited time");
00768 
00769   SampledDensityFunction SamplesWS;
00770   SamplesWS.Clear();
00771   SamplesWS.Dim(100);
00772   SamplesWS.Name("time passed till the next call of WaitSensors");
00773 
00774   // timeval-structures needed for further computations
00775   timeval dAA,dBA,dCB,dER;
00776 
00777   // perform analysis
00778   // time for a hole cycle
00779   for(int ind = 0; ind < itime-2; ind++){
00780     // compute time needed
00781     // for a hole cycle
00782     dAA = vDevice::DiffTime(timeA[ind+1],timeA[ind]);
00783     // for coputing sensor-state
00784     dBA = vDevice::DiffTime(timeB[ind],timeA[ind]);
00785     // by usleep(mCyleTime)
00786     dCB = vDevice::DiffTime(timeC[ind],timeB[ind]);
00787     // time passed by until the next call of WaitSensors
00788     dER = vDevice::DiffTime(sdevice->mptimeBegin[ind+1],sdevice->mptimeEnd[ind]);
00789     // add computed samples to corresponding
00790     // SampleDensityFunction classes
00791     SamplesA.Sample(dAA.tv_sec*1000000 + dAA.tv_usec);
00792     SamplesB.Sample(dBA.tv_sec*1000000 + dBA.tv_usec);
00793     SamplesC.Sample(dCB.tv_sec*1000000 + dCB.tv_usec);
00794     SamplesWS.Sample(1000000*dER.tv_sec + dER.tv_usec);
00795   }
00796 
00797   // perform statistic computation
00798         SamplesA.Compile();
00799         SamplesB.Compile();
00800   SamplesC.Compile();
00801   SamplesWS.Compile();
00802 
00803   // token output
00804   // SamplesA.Write();
00805   // SamplesB.Write();
00806   // SamplesC.Write();
00807   // SamplesWS.Write();
00808 
00809         // pretty output
00810         std::cout << SamplesA.Str() << std::endl;
00811         std::cout << SamplesB.Str() << std::endl;
00812         std::cout << SamplesC.Str() << std::endl;
00813   std::cout <<  SamplesWS.Str() << std::endl;
00814 #endif
00815   FD_DH("sDevice(" << sdevice->mName << ")::synchro: terminate background thread");
00816   pthread_exit(NULL);
00817   // never happens, prevent gcc warning
00818   return NULL; 
00819 }
00820 
00821 // Write Actuator(Idx)
00822 void sDevice::WriteActuator(Idx actuator) {
00823 
00824   FD_DHV("sDevice("<<mName<<")::WriteActuator");
00825   //return if device is running
00826   if(mState!=Up && mState!=StartUp) return;
00827   //make sure event is part of devices eventset
00828   if(!mActuators.Exists(actuator)) {
00829     std::stringstream errstr;
00830     errstr << "Unknown actuator event " << actuator;
00831     throw Exception("sDevice::WriteActuator", errstr.str(), 65);
00832   }
00833   // find properties
00834   const AttributeSignalActuator* aattr = pConfiguration->Attribute(actuator).Actuatorp();
00835   if(!aattr) {
00836     std::stringstream errstr;
00837     errstr << "Invalid actuator attribute " << actuator;
00838     throw Exception("sDevice::WriteActuator", errstr.str(), 65);
00839   }
00840   //debug-flag
00841   FD_DH("sDevice("<<mName<<")::WriteActuator: properties found");
00842   // execute command ...
00843   std::vector<AttributeSignalActuator::Action>::const_iterator eit;
00844   // ... case a) asynchronous write
00845   if(!mSyncWrite) {
00846     if(DoWriteSignalsPre()) {
00847       // loop actions
00848       for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
00849         FD_DH("sDevice("<<mName<<")::WriteActuator: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
00850         DoWriteSignal(eit->mBit,eit->mValue);
00851       }
00852       DoWriteSignalsPost();
00853     }
00854   }
00855   // ... case b) synchronous write
00856   if(!mSyncWrite) {
00857     // lock global image
00858     LOCK_E;
00859     // loop actions and record
00860     for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
00861       FD_DH("sDevice("<<mName<<")::WriteActuator: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
00862       Levels* level= &mpActuatorLevels[eit->mBit];
00863       level->next=eit->mValue;
00864       if(level->edge) level->lost=true;
00865       level->edge=true;
00866     }
00867     // free global image
00868     UNLOCK_E;
00869   }
00870   // done
00871   FD_DHV("sDevice("<<mName<<")::WriteActuator: done");
00872 }
00873 
00874 //ClrSensorSignals()
00875 void sDevice::ClrSensorSignals(void) {
00876   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): MaxBitAddress: " << mMaxBitAddress);
00877   //return if device is not running or device is not able to read sensors
00878   if(!(mState!=Up||Sensors().Empty())) return;
00879   // lock global variables
00880   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): lock mutex ");
00881   LOCK_E;
00882   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): edge detection ");
00883   // initialise edge detection: assume low signals
00884   for(int bit = 0;bit<=mMaxBitAddress;bit++) {
00885     Edges* edge= &mpSensorEdges[bit];
00886     FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): edge detetion ReadSignal bit "  << bit);
00887     edge->current=0;
00888     edge->past = 0;
00889     edge->pos =    false;
00890     edge->neg =    false;
00891     edge->posrel = (!mSensorPosEdgeIndexMap[bit].Empty());
00892     edge->negrel = (!mSensorNegEdgeIndexMap[bit].Empty());
00893     edge->lost =    false;
00894   }
00895   // initialise edge detection: actual signal levels
00896   if(DoReadSignalsPre()) {
00897     for(int bit = 0;bit<=mMaxBitAddress;bit++) {
00898       Edges* edge= &mpSensorEdges[bit];
00899       FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): edge detetion ReadSignal bit "  << bit);
00900       edge->current=DoReadSignal(bit);
00901       edge->past = edge->current;
00902       edge->pos =    false;
00903       edge->neg =    false;
00904       edge->posrel = (!mSensorPosEdgeIndexMap[bit].Empty());
00905       edge->negrel = (!mSensorNegEdgeIndexMap[bit].Empty());
00906       edge->lost =    false;
00907     }
00908     DoReadSignalsPost();
00909   }
00910   // initialize edge detection: recent edges
00911   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): initialize recent edges ");
00912   for(int bit = 0;bit<=mMaxBitAddress;bit++) {
00913     Edges* redge= &mpRecentSensorEdges[bit];
00914     redge->pos =    false;
00915     redge->neg =    false;
00916     redge->posrel = false;
00917     redge->negrel = false;
00918     redge->lost =   false;
00919   }
00920   // reset cyclecount
00921   mCycleCount=0;
00922   mRecentCycleCount=0;
00923   mSensorReady=false;
00924   // unlock global variables
00925   UNLOCK_E;
00926   FD_DHV("sDevice("<<mName<<")::ClrSensorSignals(): done");
00927 }
00928 
00929 //ClrActuatorSignals()
00930 void sDevice::ClrActuatorSignals(void) {
00931   //clear all actuator line levels
00932   FD_DHV("sDevice("<<mName<<")::ClrActuatorSignals");
00933   // return if device is not running or not abel to set actuator signals
00934   if(mState!=Up||Actuators().Empty()) return;
00935   // lock variables, prevent background from writing
00936   LOCK_E;
00937   // clear all (allways asynchronous)
00938   if(DoWriteSignalsPre()) {
00939     for(int bit=0; bit<=mMaxBitAddress; bit++)  DoWriteSignal(bit, false);
00940     DoWriteSignalsPost();
00941   }
00942   // clear image
00943   for(int bit=0; bit<=mMaxBitAddress; bit++) {
00944     Levels* level= &mpActuatorLevels[bit];
00945     level->current=false;
00946     level->next=false;
00947     level->edge=false;
00948     level->lost=false;
00949   }
00950   // done
00951   UNLOCK_E;
00952   FD_DHV("sDevice("<<mName<<")::ClrActuatorSignals: done");
00953 }
00954 
00955 }//end namespace faudes
00956 
00957 

libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3