|
libFAUDES
Sections
Index
|
iop_sdevice.cppGo 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