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: AttributeSignalOutput
00032 
00033  **********************************************
00034  **********************************************
00035  **********************************************
00036  */
00037 
00038 // faudes type std
00039 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeSignalOutput,AttributeVoid)
00040 
00041 //DoAssign(Src)
00042 void AttributeSignalOutput::DoAssign(const AttributeSignalOutput& rSrcAttr) {
00043   FD_DHV("AttributeSignalOutput(" << this << "):DoAssign(): assignment from " <<  &rSrcAttr);
00044   mActions=rSrcAttr.mActions;
00045 }
00046 
00047 //DoWrite(rTw);
00048 void AttributeSignalOutput::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00049   (void) rLabel; (void) pContext;
00050   
00051   FD_DHV("AttributeSignalOutput::DoWrite(): #" << mActions.size() );
00052   rTw.WriteBegin("Actions");
00053   std::vector<Action>::const_iterator ait;
00054   for(ait=mActions.begin(); ait!=mActions.end(); ait++) {
00055     Token atoken;
00056     if(ait->mValue)
00057       atoken.SetEmpty("Set");
00058     else
00059       atoken.SetEmpty("Clr");
00060     atoken.InsAttributeInteger("address",ait->mBit);
00061     rTw << atoken;
00062   }
00063   rTw.WriteEnd("Actions");
00064 }
00065 
00066 
00067 //DoRead(rTr)
00068 void AttributeSignalOutput::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00069   (void) rLabel; (void) pContext;
00070   Token token;
00071   FD_DHV("AttributeSignalOutput::DoRead()");
00072 
00073   // sense and digest pre 2.16 format
00074   rTr.Peek(token);
00075   if(token.IsBegin()) 
00076   if((token.StringValue()=="Output") || (token.StringValue()=="Actuator")) {
00077     rTr.ReadBegin("Actuator");
00078     bool err=false;
00079     rTr.ReadBegin("Actions");
00080     while(!rTr.Eos("Actions")) {
00081       Action action;
00082       action.mBit=rTr.ReadInteger();
00083       std::string value=rTr.ReadOption();
00084       if(value== "Set") {
00085         action.mValue=true;
00086       } else if(value == "Clr") {
00087         action.mValue=false;
00088       } else {
00089         err=true;
00090         break;
00091       }
00092       mActions.push_back(action);
00093     }
00094     rTr.ReadEnd("Actions");
00095     rTr.ReadEnd("Actuator");
00096     if(err) {
00097       std::stringstream errstr;
00098       errstr << "Invalid output event property" << rTr.FileLine();
00099       throw Exception("AttributeSignalOutput::Read", errstr.str(), 52);  //52 oder 352
00100     }
00101   } // end pre 2.16
00102 
00103 
00104   // test for actions section
00105   rTr.Peek(token);
00106   if(!token.IsBegin()) return;
00107   if(token.StringValue()!="Actions") return;
00108   // read begin
00109   bool err=false;
00110   rTr.ReadBegin("Actions");
00111   while(!rTr.Eos("Actions")) {
00112     // prepare
00113     Token atag;
00114     Action action;
00115     rTr.Peek(atag);
00116     // set
00117     if(atag.IsBegin())
00118     if(atag.StringValue()=="Set") {
00119       rTr.ReadBegin("Set");
00120       action.mValue=1;
00121       action.mBit=atag.AttributeIntegerValue("address");
00122       mActions.push_back(action);
00123       rTr.ReadEnd("Set");
00124       continue;
00125     }
00126     // clr
00127     if(atag.IsBegin())
00128     if(atag.StringValue()=="Clr") {
00129       rTr.ReadBegin("Clr");
00130       action.mValue=0;
00131       action.mBit=atag.AttributeIntegerValue("address");
00132       mActions.push_back(action);
00133       rTr.ReadEnd("Clr");
00134       continue;
00135     }
00136     // error on unknown tokens
00137     err=true;
00138     break;
00139   }
00140   // done
00141   rTr.ReadEnd("Actions");
00142   // report error
00143   if(err) {
00144     std::stringstream errstr;
00145     errstr << "Invalid output event property" << rTr.FileLine();
00146     throw Exception("AttributeSignalOutput::Read", errstr.str(), 52);  //52 oder 352
00147   }
00148 
00149 }//DoRead
00150 
00151 
00152 /*
00153  **********************************************
00154  **********************************************
00155  **********************************************
00156 
00157  implementation: AttributeSignalInput
00158 
00159  **********************************************
00160  **********************************************
00161  **********************************************
00162  */
00163 
00164 
00165 // faudes type std
00166 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeSignalInput,AttributeVoid)
00167 
00168 
00169 //DoAssign(Src)
00170 void AttributeSignalInput::DoAssign(const AttributeSignalInput& rSrcAttr) {
00171   FD_DHV("AttributeSignalInput(" << this << "):DoAssign(): assignment from " <<  &rSrcAttr);
00172   mTriggers=rSrcAttr.mTriggers;
00173 }
00174 
00175 
00176 //DoWrite(rTw,rLabel,pContext)
00177 void AttributeSignalInput::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00178   (void) rLabel; (void) pContext;
00179   FD_DHV("AttributeSignalInput()::DoWrite()");
00180   rTw.WriteBegin("Triggers");
00181   std::vector<Trigger>::const_iterator ait;
00182   for(ait=mTriggers.begin(); ait!=mTriggers.end(); ait++) {
00183     Token atoken;
00184     if(ait->mPos &&  (!ait->mNeg)) {
00185       atoken.SetEmpty("PositiveEdge");
00186     }
00187     if((!ait->mPos) &&  ait->mNeg) {
00188       atoken.SetEmpty("NegativeEdge");
00189     }
00190     if((ait->mPos) &&  ait->mNeg) {
00191       atoken.SetEmpty("AnyyEdge");
00192       atoken.InsAttributeString("edge","any");
00193     }
00194     atoken.InsAttributeInteger("address",ait->mBit);
00195     rTw << atoken;
00196 
00197   }
00198   rTw.WriteEnd("Triggers");
00199 }//DoWrite(rTw,rLabel,pContext)
00200 
00201 
00202 //DoRead(rTr,rLabel,pContext)
00203 void AttributeSignalInput::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00204   (void) rLabel; (void) pContext;
00205   Token token;
00206   FD_DHV("AttributeSignalInput()::DoRead(tr)");
00207 
00208 
00209   // sense and digest pre 2.16 format
00210   rTr.Peek(token);
00211   if(token.IsBegin())
00212   if((token.StringValue()=="Input") || (token.StringValue()=="Sensor")) {
00213     rTr.ReadBegin("Sensor");
00214     bool err=false;
00215     rTr.ReadBegin("Triggers");
00216     while(!rTr.Eos("Triggers")) {
00217       Trigger trigger;
00218       trigger.mBit=rTr.ReadInteger();
00219       std::string value=rTr.ReadOption();
00220       if (value == "PosEdge") {
00221         trigger.mPos=true;
00222         trigger.mNeg=false;
00223       } else if (value == "NegEdge") {
00224         trigger.mPos=false;
00225         trigger.mNeg=true;
00226       } else if (value == "AnyEdge") {
00227         trigger.mPos=true;
00228         trigger.mNeg=true;
00229       } else {
00230         err=true;
00231         break;
00232       }
00233       mTriggers.push_back(trigger);
00234     }
00235     rTr.ReadEnd("Triggers");
00236     rTr.ReadEnd("Sensor");
00237     if(err) {
00238       std::stringstream errstr;
00239       errstr << "invalid input event property" << rTr.FileLine();
00240       throw Exception("AttributeSignalInput::Read", errstr.str(), 52);
00241     }
00242   } // end pre2.16
00243  
00244   // test for triggers section
00245   rTr.Peek(token);
00246   if(!token.IsBegin()) return;
00247   if(token.StringValue()!="Triggers") return;
00248   // read begin
00249   bool err=false;
00250   rTr.ReadBegin("Triggers");
00251   while(!rTr.Eos("Triggers")) {
00252     // prepare
00253     Token atag;
00254     Trigger trigger;
00255     rTr.Peek(atag);
00256     // positive edge
00257     if(atag.IsBegin())
00258     if(atag.StringValue()=="PositiveEdge") {
00259       rTr.ReadBegin("PositiveEdge");
00260       trigger.mPos=true;
00261       trigger.mNeg=false;
00262       trigger.mBit=atag.AttributeIntegerValue("address");
00263       mTriggers.push_back(trigger);
00264       rTr.ReadEnd("PositiveEdge");
00265       continue;
00266     }
00267     // negative edge
00268     if(atag.IsBegin())
00269     if(atag.StringValue()=="NegativeEdge") {
00270       rTr.ReadBegin("NegativeEdge");
00271       trigger.mPos=false;
00272       trigger.mNeg=true;
00273       trigger.mBit=atag.AttributeIntegerValue("address");
00274       mTriggers.push_back(trigger);
00275       rTr.ReadEnd("NegativeEdge");
00276       continue;
00277     }
00278     // any edge
00279     if(atag.IsBegin())
00280     if(atag.StringValue()=="AnyEdge") {
00281       rTr.ReadBegin("AnyEdge");
00282       trigger.mPos=true;
00283       trigger.mNeg=true;
00284       trigger.mBit=atag.AttributeIntegerValue("address");
00285       mTriggers.push_back(trigger);
00286       rTr.ReadEnd("AnyEdge");
00287       continue;
00288     }
00289     // error on unknown tokens
00290     err=true;
00291     break;
00292   }
00293   // done
00294   rTr.ReadEnd("Triggers");
00295   // report error
00296   if(err) {
00297     std::stringstream errstr;
00298     errstr << "Invalid input event property" << rTr.FileLine();
00299     throw Exception("AttributeSignalInput::Read", errstr.str(), 52);  //52 oder 352
00300   }
00301 }
00302 
00303 
00304 
00305 /*
00306  **********************************************
00307  **********************************************
00308  **********************************************
00309 
00310  implementation: AttributeSignalEvent
00311 
00312  **********************************************
00313  **********************************************
00314  **********************************************
00315  */
00316 
00317 
00318 
00319 // std faudes type
00320 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeSignalEvent,AttributeDeviceEvent)
00321 
00322 // Default constructor, set my prototypes
00323 AttributeSignalEvent::AttributeSignalEvent(void) : AttributeDeviceEvent() {
00324   FD_DHV("AttributeSignalEvent::AttributeSignalEvent(" << this << ")");
00325   pOutputPrototype=OutputPrototypep();
00326   pInputPrototype=InputPrototypep();
00327 }
00328 
00329 // Copy constructor 
00330 AttributeSignalEvent::AttributeSignalEvent(const AttributeSignalEvent& rOtherAttr) : 
00331   AttributeDeviceEvent() 
00332 {
00333   FD_DHV("AttributeSimplenetEvent(" << this << "): form other attr " <<  &rOtherAttr);
00334   pOutputPrototype=OutputPrototypep();
00335   pInputPrototype=InputPrototypep();
00336   DoAssign(rOtherAttr);
00337 }
00338 
00339 
00340 
00341 // autoregister event confiration (required for XML token format)
00342 AutoRegisterType< TaNameSet<AttributeSignalEvent> > 
00343   gRti1RegisterSignalDeviceEventSet("SignalDeviceEventSet");
00344 AutoRegisterXElementTag< TaNameSet<AttributeSignalEvent> > 
00345   gRti1XElementTagSignalDeviceEventSet("SignalDeviceEventSet", "Event");
00346 
00347 // pseudo statics
00348 const AttributeSignalOutput* AttributeSignalEvent::OutputPrototypep(void){
00349   AttributeSignalOutput* attrp= new AttributeSignalOutput();
00350   return attrp;
00351 }
00352 
00353 // pseudo statics
00354 const AttributeSignalInput* AttributeSignalEvent::InputPrototypep(void) {
00355   AttributeSignalInput* attrp= new AttributeSignalInput();
00356   return attrp;
00357 }
00358 
00359 /*
00360  **********************************************
00361  **********************************************
00362  **********************************************
00363 
00364  implementation: sDevice
00365 
00366  **********************************************
00367  **********************************************
00368  **********************************************
00369  */
00370 
00371 
00372 ////////////////////////////////////////////////
00373 // construction and destruction
00374 
00375 //sDevice()
00376 sDevice::sDevice(void) : vDevice() {
00377   // constructor
00378 
00379   FD_DHV("sDevice(" << mName << ")::sDevice()");
00380   // have event set with appropriate attributes
00381   mpConfiguration = new TaNameSet<AttributeSignalEvent>;
00382   pConfiguration = dynamic_cast< TaNameSet<AttributeSignalEvent>* >(mpConfiguration);
00383   // have appropriate default label for token io
00384   mDefaultLabel ="SignalDevice";
00385   // my signal data
00386   mMaxBitAddress=0;
00387   mpInputEdges=0;
00388   mpRecentInputEdges=0;
00389   mpOutputLevels=0;
00390   // background thread:
00391   // install mutex
00392   pthread_mutex_init(&mMutex, NULL);
00393   // configuration defaults
00394   mName="SignalDevice";
00395   mCycleTime=1000; // 1ms
00396   mTimeScale=500;  // 500ms is one faudes time unit
00397   mSyncWrite=false;
00398 }
00399 
00400 
00401 //~sDevice()
00402 sDevice::~sDevice(void) {
00403   // destructor
00404 
00405   FD_DHV("sDevice(" << mName << ")::~sDevice()");
00406   //cancel background thread: destroy mutex
00407   pthread_mutex_destroy(&mMutex);
00408   // invalidate data
00409   if(mpInputEdges) delete mpInputEdges;
00410   if(mpRecentInputEdges) delete mpRecentInputEdges;
00411   if(mpOutputLevels) delete mpOutputLevels;
00412 }
00413 
00414 
00415 //DoWritePreface(rTw,rLabel,pContext)
00416 void sDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel,  const Type* pContext) const {
00417   
00418   FD_DHV("sDevice("<<mName<<")::DoWritePreface()");
00419   //call base
00420   vDevice::DoWritePreface(rTw,rLabel,pContext);
00421   //write cycle-time of background task
00422   Token ttag;
00423   ttag.SetEmpty("SampleInterval");
00424   ttag.InsAttributeInteger("value",mCycleTime);
00425   rTw<<ttag;
00426   // write sync option
00427   if(mSyncWrite) rTw.WriteOption("SyncWrite");
00428 }
00429 
00430 //DoReadPreface(rTr,rLabel,pContext)
00431 void sDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
00432   
00433   FD_DHV("sDevice("<<mName<<")::DoReadPreface()");
00434   // call base
00435   vDevice::DoReadPreface(rTr,rLabel,pContext);
00436 
00437   // sense and digest pre 2.16 format
00438   Token token;
00439   rTr.Peek(token);
00440   if(token.IsInteger()) {
00441     mMaxBitAddress = rTr.ReadInteger();
00442     mCycleTime = rTr.ReadInteger();
00443     Token token;
00444     rTr.Peek(token);
00445     if(token.IsOption())
00446     if(token.OptionValue()=="SyncWrite") {
00447       rTr.Get(token);
00448       mSyncWrite=true;
00449     }
00450     return;
00451   }
00452   
00453   // loop my members
00454   while(true) {
00455     Token token;
00456     rTr.Peek(token);
00457     // cycle time
00458     if(token.IsBegin()) 
00459     if(token.StringValue()=="SampleInterval") {
00460       rTr.ReadBegin("SampleInterval", token);
00461       mCycleTime=token.AttributeIntegerValue("value");
00462       rTr.ReadEnd("SampleInterval");
00463       continue;
00464     }
00465     // sync write
00466     if(token.IsBegin()) 
00467     if(token.StringValue()=="SynchronousWrite") {
00468       rTr.ReadBegin("SynchronousWrite");
00469       rTr.ReadEnd("SynchronousWrite");
00470       mSyncWrite=true;
00471       continue;
00472     }
00473     // break on unknown
00474     break;
00475   }
00476 
00477   // done
00478 }
00479  
00480 
00481 // lock - unlock shortcuts;
00482 #define LOCK_E  {int rc = pthread_mutex_lock(&mMutex); \
00483   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: lock mutex error\n"); exit(1); }}
00484 #define UNLOCK_E  {int rc = pthread_mutex_unlock(&mMutex); \
00485   if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: unlock mutex error\n"); exit(1); }}
00486 
00487 
00488 #define TLOCK_E  {int rc = pthread_mutex_lock(&sdevice->mMutex); \
00489   if(rc) {FD_ERR("sDevice::TLOCK_E: lock mutex error\n"); exit(1); }}
00490 
00491 #define TUNLOCK_E  {int rc = pthread_mutex_unlock(&sdevice->mMutex); \
00492   if(rc) {FD_ERR("sDevice::TLOCK_E: unlock mutex error\n"); exit(1); }}
00493 
00494 
00495 
00496 
00497 
00498 // Start(void)
00499 void sDevice::Start(void) {
00500   //set device state and create thread
00501 
00502   //return if device was allready started
00503   if( (mState == Up)||(mState == StartUp) )  return;
00504   FD_DHV("sDevice("<<mName<<")::Start()");
00505   //call base incl virtual reset
00506   vDevice::Start();
00507   mState=StartUp;
00508   //create background for edge detection and sync write
00509   if(!Inputs().Empty()){
00510     mCancelRequest = false;
00511     //setup thread attribute
00512     pthread_attr_t attr;
00513     pthread_attr_init(&attr);
00514     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00515     //create thread
00516     int rc  = pthread_create(&mThreadSynchro, &attr, SDeviceSynchro, this);
00517     if (rc) {
00518       FD_ERR("sDevice("<<mName<<")::Start(): cannot creat thread\n");
00519       exit(1);
00520     }
00521     //destroy thread-attribute
00522     pthread_attr_destroy(&attr);
00523   }
00524 }
00525 
00526 // Stop()
00527 void sDevice::Stop(void) {
00528   //set device state and kill thread
00529 
00530   //return if device allready got the command to shut down
00531   if(mState != Up && mState !=StartUp)  return;
00532   FD_DHV("sDevice("<<mName<<")::Stop()");
00533   //dont kill thread if no thread was created
00534   if(!Inputs().Empty()) {
00535     //cancle thread
00536     LOCK_E;
00537     mCancelRequest=true;
00538     UNLOCK_E;
00539     int pc = pthread_join(mThreadSynchro,NULL);
00540     if (pc) {
00541       FD_ERR("sDevice("<<mName<<")::Stop(): cannot join  thread??\n");
00542     }
00543   }
00544   // call base
00545   vDevice::Stop();
00546 }//end Stop()
00547 
00548 
00549 //Reset()
00550 void sDevice::Reset(){
00551   //delete dynamic data
00552   FD_DHV("sDevice("<<mName<<")::Reset()");
00553   // call base (resets time)
00554   vDevice::Reset();
00555   //delete dynamic data
00556   ClrInputSignals();
00557   ClrOutputSignals();
00558 }
00559 
00560 // Clear()
00561 void sDevice::Clear(void) {
00562   //delete static data
00563 
00564   FD_DHV("sDevice(" << mName << ")::Clear()");
00565   // call base; note: clear implies stop
00566   vDevice::Clear();
00567   // clear compiled data
00568   mInputPosEdgeIndexMap.clear();
00569   mInputNegEdgeIndexMap.clear();
00570   mMaxBitAddress=0;
00571   mSyncWrite=false;
00572   mCycleTime=1000; // nsec
00573 }
00574 
00575 //Compile(void)
00576 void sDevice::Compile(void){
00577   //setup up internal data structure
00578 
00579   FD_DHV("sDevice(" << mName << ")::Compile()");
00580   // call base
00581   vDevice::Compile();
00582   // clear my internal data
00583   mInputPosEdgeIndexMap.clear();
00584   mInputNegEdgeIndexMap.clear();
00585   mMaxBitAddress=0;
00586   // setup my internal data
00587   for(EventSet::Iterator eit=pConfiguration->Begin(); eit!=pConfiguration->End(); eit++) {
00588     AttributeSignalEvent attr = pConfiguration->Attribute(*eit);
00589     if(attr.IsInput()) {
00590       // fill in reverse maps
00591       std::vector<AttributeSignalInput::Trigger>::const_iterator ait;
00592       const AttributeSignalInput* sattr = attr.Inputp();
00593       for(ait=sattr->mTriggers.begin(); ait!=sattr->mTriggers.end(); ait++) {
00594         if(ait->mPos) mInputPosEdgeIndexMap[ait->mBit].Insert(*eit);
00595         if(ait->mNeg) mInputNegEdgeIndexMap[ait->mBit].Insert(*eit);
00596         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00597       }
00598     }
00599     // check max address
00600     if(attr.IsOutput()) {
00601       std::vector<AttributeSignalOutput::Action>::const_iterator ait;
00602       const AttributeSignalOutput* aattr = attr.Outputp();
00603       for(ait=aattr->mActions.begin(); ait!=aattr->mActions.end(); ait++) {
00604         if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
00605       }
00606     }
00607   }
00608   // prep state data
00609   if(mpInputEdges) delete mpInputEdges;
00610   if(mpRecentInputEdges) delete mpRecentInputEdges;
00611   if(mpOutputLevels) delete mpOutputLevels;
00612   mpInputEdges = new Edges[mMaxBitAddress+1];
00613   mpRecentInputEdges = new Edges[mMaxBitAddress+1];
00614   mpOutputLevels = new Levels[mMaxBitAddress+1];
00615 }
00616 
00617 //CycleTime(void)
00618 int sDevice::CycleTime(void) const {
00619   //Report current cycle time
00620   
00621   FD_DHV("sDevice(" << mName << ")::CycleTime()");
00622   return mCycleTime;
00623 }
00624 
00625 //CycleTime(int)
00626 void sDevice::CycleTime(int cycleTime) {
00627   //Set cycle time
00628   FD_DHV("sDevice(" << mName << ")::CycleTime(int)");
00629   if( mState==Up || mState==StartUp){
00630     std::stringstream errstr;
00631     errstr << "Changing cycle-time not possible while background thread is still running ";
00632     throw Exception("sDevice::CycleTime: ", errstr.str(), 100);
00633   }
00634   mCycleTime = cycleTime;
00635 }
00636 
00637 
00638 //ReadSignal(int)
00639 bool sDevice::ReadSignal(int bit){
00640   FD_DHV("sDevice(" << mName << ")::ReadSignal(int)");
00641 
00642   // make sure device is able to read signals
00643   if(Inputs().Empty()){
00644     std::stringstream errstr;
00645     errstr << "(" << mName << ") is not able to read signals";
00646     throw Exception("sDevice::ReadSignal():", errstr.str(), 552);  //TODO: number!
00647   }
00648 
00649   // run with hooks
00650   bool res=false;
00651   if(DoReadSignalsPre())
00652     res=DoReadSignal(bit);
00653   DoReadSignalsPost();
00654 
00655   return res;
00656 }
00657 
00658 //WriteSignal(int,int)
00659 void sDevice::WriteSignal(int bit, bool value){
00660   // write one actor value, adressed by bit number (0 to 63);
00661   FD_DHV("sDevice(" << mName << ")::WriteSignal(int)");
00662   // make sure device supports outputs 
00663   if(Outputs().Empty()){
00664     std::stringstream errstr;
00665     errstr << "(" << mName << ") is not configured for outputs";
00666     throw Exception("sDevice::WriteSignal():", errstr.str(), 552);  
00667   }
00668   // lock global image, prevent background thread from reading/writing
00669   LOCK_E;
00670   // case a) asynchronous write
00671   if(!mSyncWrite) {
00672     if(DoWriteSignalsPre()) {
00673       DoWriteSignal(bit,value);
00674       DoWriteSignalsPost();
00675     }
00676   }
00677   // case b) synchronous write
00678   if(mSyncWrite) {
00679     // record next value
00680     Levels* level= &mpOutputLevels[bit];
00681     level->next=value;
00682     if(level->edge) level->lost=true;
00683     level->edge=true;
00684   }
00685   // free global image
00686   UNLOCK_E;
00687 }
00688 
00689 
00690 //SDeviceSynchro(void*)
00691 void* SDeviceSynchro(void* arg){
00692 
00693   //background-thread main-routine
00694 
00695   // cast this object
00696   sDevice* sdevice = static_cast<sDevice*>(arg);
00697 
00698   FD_DH("sDevice(" << sdevice->mName << ")::Synchro(" << sdevice << "): with ct " << sdevice->mCycleTime);
00699 
00700   /////////////////////////////////////////////////////
00701   //  cyletime-measurement
00702   //  timeA: time consumed for a hole cycle
00703   //  timeB: time consumed by computation
00704   //  timeC: real time consumed by usleep
00705   ////////////////////////////////////////////////////
00706 #ifdef FAUDES_DEBUG_IOTIMING_X
00707   //arrays to store measured time in
00708   timeval* timeA = new timeval[MAX_SAMPLES];
00709   timeval* timeB = new timeval[MAX_SAMPLES];
00710   timeval* timeC = new timeval[MAX_SAMPLES];
00711         // define local itterator
00712   int itime=0;
00713   // take time
00714   gettimeofday(timeA+itime,0);
00715 #endif
00716 
00717   bool running=true;
00718 
00719   while(running){
00720 
00721     // lock global variables
00722     TLOCK_E;
00723 
00724           // start up: initialze dynamic state
00725           if(sdevice->mState==sDevice::StartUp) {
00726 
00727             bool aready= sdevice->DoWriteSignalsPre();
00728         if(aready) {
00729               // output image: set to zero
00730         FD_DH("sDevice("<<sdevice->Name()<<")::synchro: reset: clear lines");
00731               for(int bit=0; bit<=sdevice->mMaxBitAddress; bit++) {
00732     sdevice->DoWriteSignal(bit,false);
00733                 sDevice::Levels* level= &sdevice->mpOutputLevels[bit];
00734                 level->current=false;
00735                 level->next=false;
00736                 level->edge=false;
00737                 level->lost=false;
00738         }
00739               sdevice->DoWriteSignalsPost();
00740             }
00741             bool sready= sdevice->DoReadSignalsPre();
00742         if(sready) {
00743               // edge detection: use actual signal levels
00744         FD_DH("sDevice("<<sdevice->Name()<<")::synchro: reset: edge detection");
00745               for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
00746                 sDevice::Edges* edge= &sdevice->mpInputEdges[bit];
00747                 edge->current=sdevice->DoReadSignal(bit);
00748                 edge->past = edge->current;
00749                 edge->pos =    false;
00750                 edge->neg =    false;
00751                 edge->posrel = (!sdevice->mInputPosEdgeIndexMap[bit].Empty());
00752                 edge->negrel = (!sdevice->mInputNegEdgeIndexMap[bit].Empty());
00753                 edge->lost =    false;
00754               }
00755               sdevice->DoReadSignalsPost();
00756               for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
00757                 sDevice::Edges* redge= &sdevice->mpRecentInputEdges[bit];
00758                 redge->pos =    false;
00759                 redge->neg =    false;
00760                 redge->posrel = false;
00761                 redge->negrel = false;
00762                 redge->lost =   false;
00763               }
00764       }
00765             // new state
00766             if(sready && aready) 
00767               sdevice->mState=sDevice::Up;        
00768     }
00769 
00770           // normal operation, outputs
00771           if(sdevice->mState==sDevice::Up && sdevice->mSyncWrite) {
00772             bool ready=sdevice->DoWriteSignalsPre();
00773             if(!ready) 
00774               sdevice->mState=sDevice::StartUp;   
00775             if(ready) {
00776           // write values from image
00777         for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
00778           // define pointer to levels
00779           sDevice::Levels* level= &sdevice->mpOutputLevels[bit];
00780           // not wrtiien by libfaudes
00781           if(!level->edge) continue;
00782           // write and record
00783                 sdevice->DoWriteSignal(bit,level->next);
00784           level->current = level->next;
00785           level->edge = false;
00786         }
00787               sdevice->DoWriteSignalsPost();
00788       }
00789     }
00790  
00791           // normal operation, inputs
00792           if(sdevice->mState==sDevice::Up) {
00793             bool ready=sdevice->DoReadSignalsPre();
00794             if(!ready) 
00795               sdevice->mState=sDevice::StartUp;   
00796             if(ready) {
00797           // edge detection, accumulative
00798         for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
00799           // define pointer to Inputedges
00800           sDevice::Edges* edge= &sdevice->mpInputEdges[bit];
00801           // pass edge-info about edge in last cycle
00802           edge->past = edge->current;
00803           // and get corresponding input-value
00804           edge->current = sdevice->DoReadSignal(bit);
00805           if(edge->posrel)
00806     if(edge->current && (!edge->past) ) {
00807       /*
00808         if(edge->pos && (!edge->lost)) {
00809         FD_DH("sDevice::synchro: lost positive edge at bit address "  << bit);
00810         edge->lost=true;
00811         }
00812       */
00813       FD_DH("sDevice::synchro: sensed positive edge at bit address "  << bit);
00814       edge->pos = true;
00815       // queue events to buffer
00816       pthread_mutex_lock(sdevice->pBufferMutex);
00817       EventSet::Iterator eit=sdevice->mInputPosEdgeIndexMap[bit].Begin();
00818       EventSet::Iterator eit_end=sdevice->mInputPosEdgeIndexMap[bit].End();
00819       for(; eit!=eit_end; eit++) {
00820         sdevice->pInputBuffer->push_back(*eit);
00821       }
00822       pthread_mutex_unlock(sdevice->pBufferMutex);
00823       //send signal to function "WaitSenosrs()"
00824       FD_DHV("sDevice::synchro: send signal " );
00825       pthread_cond_broadcast(sdevice->pWaitCondition);
00826     }
00827           if(edge->negrel)
00828     if( (!edge->current) && edge->past ) {
00829       FD_DH("sDevice::synchro: sensed negative edge at bit address "  << bit);
00830       edge->neg = true;
00831       sdevice->mInputReady = true;
00832       // queue events to buffer
00833       pthread_mutex_lock(sdevice->pBufferMutex);
00834       EventSet::Iterator eit=sdevice->mInputNegEdgeIndexMap[bit].Begin();
00835       EventSet::Iterator eit_end=sdevice->mInputNegEdgeIndexMap[bit].End();
00836       for(; eit!=eit_end; eit++) {
00837         sdevice->pInputBuffer->push_back(*eit);
00838       }
00839       pthread_mutex_unlock(sdevice->pBufferMutex);
00840       //send signal to function "WaitSenosrs"
00841       FD_DHV("sDevice::synchro: send signal " );
00842       pthread_cond_broadcast(sdevice->pWaitCondition);
00843     }
00844         } // loop bits
00845               sdevice->DoReadSignalsPost();
00846       } // end-if device ok
00847     } // end-if inputs
00848  
00849  
00850     // check for cancel request
00851     if(sdevice->mCancelRequest) running=false;
00852     // unlock global variables
00853     TUNLOCK_E;
00854 
00855     //////////////////////////////////////
00856     //cycletime measurement
00857     //measure time to perform computation
00858 #ifdef FAUDES_DEBUG_IOTIMING_X
00859     if(itime < MAX_SAMPLES) gettimeofday(timeB+itime,0);
00860 #endif
00861 
00862     // let time pass; todo: use proper timer
00863     usleep(sdevice->mCycleTime);
00864 
00865 #ifdef FAUDES_DEBUG_IOTIMING_X
00866     //////////////////////////////////////
00867     // cycletime measurement
00868 
00869     // measure time consumed by wait
00870     if(itime < MAX_SAMPLES)   gettimeofday(timeC+itime,0);
00871     // measure time needed for a hole cyle
00872     // increase iterator
00873     itime++;
00874     if(itime < MAX_SAMPLES)   gettimeofday(timeA+itime,0);
00875 
00876 #endif
00877     // count cycles
00878     sdevice->mCycleCount++;
00879   } // loop while running
00880 
00881 
00882 #ifdef FAUDES_DEBUG_IOTIMING_X
00883 
00884   /////////////////////////////////////////////
00885   // cycletime measurement
00886   // analysis using SampleDensityFunction
00887         FD_DHT("sDevice::synchro: performance analysis");
00888 
00889   SampledDensityFunction SamplesA;
00890   SamplesA.Clear();
00891         SamplesA.Dim(100);
00892         SamplesA.Name("time stamp AA: overall period");
00893 
00894   SampledDensityFunction SamplesB;
00895         SamplesB.Clear();
00896   SamplesB.Dim(100);
00897         SamplesB.Name("time stamp AB: process time");
00898 
00899   SampledDensityFunction SamplesC;
00900   SamplesC.Clear();
00901         SamplesC.Dim(100);
00902         SamplesC.Name("time stamp CB: waited time");
00903 
00904   SampledDensityFunction SamplesWS;
00905   SamplesWS.Clear();
00906   SamplesWS.Dim(100);
00907   SamplesWS.Name("time passed till the next call of WaitInputs");
00908 
00909   // timeval-structures needed for further computations
00910   timeval dAA,dBA,dCB,dER;
00911 
00912   // perform analysis
00913   // time for a hole cycle
00914   for(int ind = 0; ind < itime-2; ind++){
00915     // compute time needed
00916     // for a hole cycle
00917     dAA = vDevice::DiffTime(timeA[ind+1],timeA[ind]);
00918     // for coputing input-state
00919     dBA = vDevice::DiffTime(timeB[ind],timeA[ind]);
00920     // by usleep(mCyleTime)
00921     dCB = vDevice::DiffTime(timeC[ind],timeB[ind]);
00922     // time passed by until the next call of WaitInputs
00923     dER = vDevice::DiffTime(sdevice->mptimeBegin[ind+1],sdevice->mptimeEnd[ind]);
00924     // add computed samples to corresponding
00925     // SampleDensityFunction classes
00926     SamplesA.Sample(dAA.tv_sec*1000000 + dAA.tv_usec);
00927     SamplesB.Sample(dBA.tv_sec*1000000 + dBA.tv_usec);
00928     SamplesC.Sample(dCB.tv_sec*1000000 + dCB.tv_usec);
00929     SamplesWS.Sample(1000000*dER.tv_sec + dER.tv_usec);
00930   }
00931 
00932   // perform statistic computation
00933         SamplesA.Compile();
00934         SamplesB.Compile();
00935   SamplesC.Compile();
00936   SamplesWS.Compile();
00937 
00938   // token output
00939   // SamplesA.Write();
00940   // SamplesB.Write();
00941   // SamplesC.Write();
00942   // SamplesWS.Write();
00943 
00944         // pretty output
00945         std::cout << SamplesA.Str() << std::endl;
00946         std::cout << SamplesB.Str() << std::endl;
00947         std::cout << SamplesC.Str() << std::endl;
00948   std::cout <<  SamplesWS.Str() << std::endl;
00949 #endif
00950   FD_DH("sDevice(" << sdevice->mName << ")::synchro: terminate background thread");
00951   pthread_exit(NULL);
00952   // never happens, prevent gcc warning
00953   return NULL; 
00954 }
00955 
00956 // Write Output(Idx)
00957 void sDevice::WriteOutput(Idx output) {
00958 
00959   FD_DHV("sDevice("<<mName<<")::WriteOutput");
00960   //return if device is running
00961   if(mState!=Up && mState!=StartUp) return;
00962   //make sure event is part of devices eventset
00963   if(!mOutputs.Exists(output)) {
00964     std::stringstream errstr;
00965     errstr << "Unknown output event " << output;
00966     throw Exception("sDevice::WriteOutput", errstr.str(), 65);
00967   }
00968   // find properties
00969   const AttributeSignalOutput* aattr = pConfiguration->Attribute(output).Outputp();
00970   if(!aattr) {
00971     std::stringstream errstr;
00972     errstr << "Invalid output attribute " << output;
00973     throw Exception("sDevice::WriteOutput", errstr.str(), 65);
00974   }
00975   //debug-flag
00976   FD_DHV("sDevice("<<mName<<")::WriteOutput: properties found");
00977   // execute command ...
00978   std::vector<AttributeSignalOutput::Action>::const_iterator eit;
00979   // ... case a) asynchronous write
00980   if(!mSyncWrite) {
00981     if(DoWriteSignalsPre()) {
00982       // loop actions
00983       for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
00984         FD_DHV("sDevice("<<mName<<")::WriteOutput: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
00985         DoWriteSignal(eit->mBit,eit->mValue);
00986       }
00987       DoWriteSignalsPost();
00988     }
00989   }
00990   // ... case b) synchronous write
00991   if(!mSyncWrite) {
00992     // lock global image
00993     LOCK_E;
00994     // loop actions and record
00995     for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
00996       FD_DHV("sDevice("<<mName<<")::WriteOutput: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
00997       Levels* level= &mpOutputLevels[eit->mBit];
00998       level->next=eit->mValue;
00999       if(level->edge) level->lost=true;
01000       level->edge=true;
01001     }
01002     // free global image
01003     UNLOCK_E;
01004   }
01005   // done
01006   FD_DHV("sDevice("<<mName<<")::WriteOutput: done");
01007 }
01008 
01009 //ClrInputSignals()
01010 void sDevice::ClrInputSignals(void) {
01011   FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): MaxBitAddress: " << mMaxBitAddress);
01012   //return if device is not running or device is not able to read inputs
01013   if(!(mState!=Up||Inputs().Empty())) return;
01014   // lock global variables
01015   FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): lock mutex ");
01016   LOCK_E;
01017   FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detection ");
01018   // initialise edge detection: assume low signals
01019   for(int bit = 0;bit<=mMaxBitAddress;bit++) {
01020     Edges* edge= &mpInputEdges[bit];
01021     FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detetion ReadSignal bit "  << bit);
01022     edge->current=0;
01023     edge->past = 0;
01024     edge->pos =    false;
01025     edge->neg =    false;
01026     edge->posrel = (!mInputPosEdgeIndexMap[bit].Empty());
01027     edge->negrel = (!mInputNegEdgeIndexMap[bit].Empty());
01028     edge->lost =    false;
01029   }
01030   // initialise edge detection: actual signal levels
01031   if(DoReadSignalsPre()) {
01032     for(int bit = 0;bit<=mMaxBitAddress;bit++) {
01033       Edges* edge= &mpInputEdges[bit];
01034       FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detetion ReadSignal bit "  << bit);
01035       edge->current=DoReadSignal(bit);
01036       edge->past = edge->current;
01037       edge->pos =    false;
01038       edge->neg =    false;
01039       edge->posrel = (!mInputPosEdgeIndexMap[bit].Empty());
01040       edge->negrel = (!mInputNegEdgeIndexMap[bit].Empty());
01041       edge->lost =    false;
01042     }
01043     DoReadSignalsPost();
01044   }
01045   // initialize edge detection: recent edges
01046   FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): initialize recent edges ");
01047   for(int bit = 0;bit<=mMaxBitAddress;bit++) {
01048     Edges* redge= &mpRecentInputEdges[bit];
01049     redge->pos =    false;
01050     redge->neg =    false;
01051     redge->posrel = false;
01052     redge->negrel = false;
01053     redge->lost =   false;
01054   }
01055   // reset cyclecount
01056   mCycleCount=0;
01057   mRecentCycleCount=0;
01058   mInputReady=false;
01059   // unlock global variables
01060   UNLOCK_E;
01061   FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): done");
01062 }
01063 
01064 //ClrOutputSignals()
01065 void sDevice::ClrOutputSignals(void) {
01066   //clear all output line levels
01067   FD_DHV("sDevice("<<mName<<")::ClrOutputSignals");
01068   // return if device is not running or not abel to set output signals
01069   if(mState!=Up||Outputs().Empty()) return;
01070   // lock variables, prevent background from writing
01071   LOCK_E;
01072   // clear all (allways asynchronous)
01073   if(DoWriteSignalsPre()) {
01074     for(int bit=0; bit<=mMaxBitAddress; bit++)  DoWriteSignal(bit, false);
01075     DoWriteSignalsPost();
01076   }
01077   // clear image
01078   for(int bit=0; bit<=mMaxBitAddress; bit++) {
01079     Levels* level= &mpOutputLevels[bit];
01080     level->current=false;
01081     level->next=false;
01082     level->edge=false;
01083     level->lost=false;
01084   }
01085   // done
01086   UNLOCK_E;
01087   FD_DHV("sDevice("<<mName<<")::ClrOutputSignals: done");
01088 }
01089 
01090 }//end namespace faudes
01091 
01092 

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3