iop_sdevice.cpp
Go to the documentation of this file.
1 /** @file iop_sdevice.cpp Virtual device for interface definition */
2 
3 /*
4  FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2008, Thomas Moor
7  Exclusive copyright is granted to Klaus Schmidt
8 
9 */
10 
11 
12 
13 #include "iop_sdevice.h"
14 #include "sp_densityfnct.h"
15 
16 namespace faudes {
17 
18 
19 /*
20  **********************************************
21  **********************************************
22  **********************************************
23 
24  implementation: AttributeSignalOutput
25 
26  **********************************************
27  **********************************************
28  **********************************************
29  */
30 
31 // faudes type std
32 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeSignalOutput,AttributeVoid)
33 
34 //DoAssign(Src)
35 void AttributeSignalOutput::DoAssign(const AttributeSignalOutput& rSrcAttr) {
36  FD_DHV("AttributeSignalOutput(" << this << "):DoAssign(): assignment from " << &rSrcAttr);
37  mActions=rSrcAttr.mActions;
38 }
39 
40 //DoWrite(rTw);
41 void AttributeSignalOutput::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
42  (void) rLabel; (void) pContext;
43 
44  FD_DHV("AttributeSignalOutput::DoWrite(): #" << mActions.size() );
45  rTw.WriteBegin("Actions");
46  std::vector<Action>::const_iterator ait;
47  for(ait=mActions.begin(); ait!=mActions.end(); ait++) {
48  Token atoken;
49  if(ait->mValue==Set)
50  atoken.SetEmpty("Set");
51  if(ait->mValue==Clr)
52  atoken.SetEmpty("Clr");
53  if(ait->mValue==Inv)
54  atoken.SetEmpty("Inv");
55  atoken.InsAttributeInteger("address",ait->mBit);
56  rTw << atoken;
57  }
58  rTw.WriteEnd("Actions");
59 }
60 
61 
62 //DoRead(rTr)
63 void AttributeSignalOutput::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
64  (void) rLabel; (void) pContext;
65  Token token;
66  FD_DHV("AttributeSignalOutput::DoRead()");
67 
68  // sense and digest pre 2.16 format
69  rTr.Peek(token);
70  if(token.IsBegin())
71  if((token.StringValue()=="Output") || (token.StringValue()=="Actuator")) {
72  rTr.ReadBegin("Actuator");
73  bool err=false;
74  rTr.ReadBegin("Actions");
75  while(!rTr.Eos("Actions")) {
76  Action action;
77  action.mBit=rTr.ReadInteger();
78  std::string value=rTr.ReadOption();
79  if(value== "Set") {
80  action.mValue=Set;
81  } else if(value == "Clr") {
82  action.mValue=Clr;
83  } else if(value == "Inv") {
84  action.mValue=Inv;
85  } else {
86  err=true;
87  break;
88  }
89  mActions.push_back(action);
90  }
91  rTr.ReadEnd("Actions");
92  rTr.ReadEnd("Actuator");
93  if(err) {
94  std::stringstream errstr;
95  errstr << "Invalid output event property" << rTr.FileLine();
96  throw Exception("AttributeSignalOutput::Read", errstr.str(), 52); //52 oder 352
97  }
98  } // end pre 2.16
99 
100 
101  // test for actions section
102  rTr.Peek(token);
103  if(!token.IsBegin()) return;
104  if(token.StringValue()!="Actions") return;
105  // read begin
106  bool err=false;
107  rTr.ReadBegin("Actions");
108  while(!rTr.Eos("Actions")) {
109  // prepare
110  Token atag;
111  Action action;
112  rTr.Peek(atag);
113  // set
114  if(atag.IsBegin())
115  if(atag.StringValue()=="Set") {
116  rTr.ReadBegin("Set");
117  action.mValue=Set;
118  action.mBit=atag.AttributeIntegerValue("address");
119  mActions.push_back(action);
120  rTr.ReadEnd("Set");
121  continue;
122  }
123  // clr
124  if(atag.IsBegin())
125  if(atag.StringValue()=="Clr") {
126  rTr.ReadBegin("Clr");
127  action.mValue=Clr;
128  action.mBit=atag.AttributeIntegerValue("address");
129  mActions.push_back(action);
130  rTr.ReadEnd("Clr");
131  continue;
132  }
133  // inv
134  if(atag.StringValue()=="Inv") {
135  rTr.ReadBegin("Inv");
136  action.mValue=Inv;
137  action.mBit=atag.AttributeIntegerValue("address");
138  mActions.push_back(action);
139  rTr.ReadEnd("Inv");
140  continue;
141  }
142  // error on unknown tokens
143  err=true;
144  break;
145  }
146  // done
147  rTr.ReadEnd("Actions");
148  // report error
149  if(err) {
150  std::stringstream errstr;
151  errstr << "Invalid output event property" << rTr.FileLine();
152  throw Exception("AttributeSignalOutput::Read", errstr.str(), 52); //52 oder 352
153  }
154 
155 }//DoRead
156 
157 
158 /*
159  **********************************************
160  **********************************************
161  **********************************************
162 
163  implementation: AttributeSignalInput
164 
165  **********************************************
166  **********************************************
167  **********************************************
168  */
169 
170 
171 // faudes type std
173 
174 
175 //DoAssign(Src)
176 void AttributeSignalInput::DoAssign(const AttributeSignalInput& rSrcAttr) {
177  FD_DHV("AttributeSignalInput(" << this << "):DoAssign(): assignment from " << &rSrcAttr);
178  mTriggers=rSrcAttr.mTriggers;
179 }
180 
181 
182 //DoWrite(rTw,rLabel,pContext)
183 void AttributeSignalInput::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
184  (void) rLabel; (void) pContext;
185  FD_DHV("AttributeSignalInput()::DoWrite()");
186  rTw.WriteBegin("Triggers");
187  std::vector<Trigger>::const_iterator ait;
188  for(ait=mTriggers.begin(); ait!=mTriggers.end(); ait++) {
189  Token atoken;
190  if(ait->mPos && (!ait->mNeg)) {
191  atoken.SetEmpty("PositiveEdge");
192  }
193  if((!ait->mPos) && ait->mNeg) {
194  atoken.SetEmpty("NegativeEdge");
195  }
196  if((ait->mPos) && ait->mNeg) {
197  atoken.SetEmpty("AnyyEdge");
198  atoken.InsAttributeString("edge","any");
199  }
200  atoken.InsAttributeInteger("address",ait->mBit);
201  rTw << atoken;
202 
203  }
204  rTw.WriteEnd("Triggers");
205 }//DoWrite(rTw,rLabel,pContext)
206 
207 
208 //DoRead(rTr,rLabel,pContext)
209 void AttributeSignalInput::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
210  (void) rLabel; (void) pContext;
211  Token token;
212  FD_DHV("AttributeSignalInput()::DoRead(tr)");
213 
214 
215  // sense and digest pre 2.16 format
216  rTr.Peek(token);
217  if(token.IsBegin())
218  if((token.StringValue()=="Input") || (token.StringValue()=="Sensor")) {
219  rTr.ReadBegin("Sensor");
220  bool err=false;
221  rTr.ReadBegin("Triggers");
222  while(!rTr.Eos("Triggers")) {
223  Trigger trigger;
224  trigger.mBit=rTr.ReadInteger();
225  std::string value=rTr.ReadOption();
226  if (value == "PosEdge") {
227  trigger.mPos=true;
228  trigger.mNeg=false;
229  } else if (value == "NegEdge") {
230  trigger.mPos=false;
231  trigger.mNeg=true;
232  } else if (value == "AnyEdge") {
233  trigger.mPos=true;
234  trigger.mNeg=true;
235  } else {
236  err=true;
237  break;
238  }
239  mTriggers.push_back(trigger);
240  }
241  rTr.ReadEnd("Triggers");
242  rTr.ReadEnd("Sensor");
243  if(err) {
244  std::stringstream errstr;
245  errstr << "invalid input event property" << rTr.FileLine();
246  throw Exception("AttributeSignalInput::Read", errstr.str(), 52);
247  }
248  } // end pre2.16
249 
250  // test for triggers section
251  rTr.Peek(token);
252  if(!token.IsBegin()) return;
253  if(token.StringValue()!="Triggers") return;
254  // read begin
255  bool err=false;
256  rTr.ReadBegin("Triggers");
257  while(!rTr.Eos("Triggers")) {
258  // prepare
259  Token atag;
260  Trigger trigger;
261  rTr.Peek(atag);
262  // positive edge
263  if(atag.IsBegin())
264  if(atag.StringValue()=="PositiveEdge") {
265  rTr.ReadBegin("PositiveEdge");
266  trigger.mPos=true;
267  trigger.mNeg=false;
268  trigger.mBit=atag.AttributeIntegerValue("address");
269  mTriggers.push_back(trigger);
270  rTr.ReadEnd("PositiveEdge");
271  continue;
272  }
273  // negative edge
274  if(atag.IsBegin())
275  if(atag.StringValue()=="NegativeEdge") {
276  rTr.ReadBegin("NegativeEdge");
277  trigger.mPos=false;
278  trigger.mNeg=true;
279  trigger.mBit=atag.AttributeIntegerValue("address");
280  mTriggers.push_back(trigger);
281  rTr.ReadEnd("NegativeEdge");
282  continue;
283  }
284  // any edge
285  if(atag.IsBegin())
286  if(atag.StringValue()=="AnyEdge") {
287  rTr.ReadBegin("AnyEdge");
288  trigger.mPos=true;
289  trigger.mNeg=true;
290  trigger.mBit=atag.AttributeIntegerValue("address");
291  mTriggers.push_back(trigger);
292  rTr.ReadEnd("AnyEdge");
293  continue;
294  }
295  // error on unknown tokens
296  err=true;
297  break;
298  }
299  // done
300  rTr.ReadEnd("Triggers");
301  // report error
302  if(err) {
303  std::stringstream errstr;
304  errstr << "Invalid input event property" << rTr.FileLine();
305  throw Exception("AttributeSignalInput::Read", errstr.str(), 52); //52 oder 352
306  }
307 }
308 
309 
310 
311 /*
312  **********************************************
313  **********************************************
314  **********************************************
315 
316  implementation: AttributeSignalEvent
317 
318  **********************************************
319  **********************************************
320  **********************************************
321  */
322 
323 
324 
325 // std faudes type
327 
328 // Default constructor, set my prototypes
330  FD_DHV("AttributeSignalEvent::AttributeSignalEvent(" << this << ")");
331  pOutputPrototype=OutputPrototypep();
332  pInputPrototype=InputPrototypep();
333 }
334 
335 // Copy constructor
338 {
339  FD_DHV("AttributeSimplenetEvent(" << this << "): form other attr " << &rOtherAttr);
342  DoAssign(rOtherAttr);
343 }
344 
345 
346 
347 // autoregister event confiration (required for XML token format)
349  gRti1RegisterSignalDeviceEventSet("SignalDeviceEventSet");
351  gRti1XElementTagSignalDeviceEventSet("SignalDeviceEventSet", "Event");
352 
353 // pseudo statics
356  return attrp;
357 }
358 
359 // pseudo statics
362  return attrp;
363 }
364 
365 /*
366  **********************************************
367  **********************************************
368  **********************************************
369 
370  implementation: sDevice
371 
372  **********************************************
373  **********************************************
374  **********************************************
375  */
376 
377 
378 ////////////////////////////////////////////////
379 // construction and destruction
380 
381 //sDevice()
383  // constructor
384 
385  FD_DHV("sDevice(" << mName << ")::sDevice()");
386  // have event set with appropriate attributes
389  // have appropriate default label for token io
390  mDefaultLabel ="SignalDevice";
391  // my signal data
392  mMaxBitAddress=-1;
393  mpInputEdges=0;
395  mpOutputLevels=0;
396  // background thread:
397  // install mutex
398  faudes_mutex_init(&mMutex);
399  // configuration defaults
400  mName="SignalDevice";
401  mCycleTime=1000; // 1ms
402  mTimeScale=500; // 500ms is one faudes time unit
403  mSyncWrite=false;
404 }
405 
406 
407 //~sDevice()
409  // destructor
410  FD_DHV("sDevice(" << mName << ")::~sDevice()");
411  // cancel background thread: stop
412  Stop();
413  // free mem
414  faudes_mutex_destroy(&mMutex);
415  // free mem
416  if(mpInputEdges) delete mpInputEdges;
418  if(mpOutputLevels) delete mpOutputLevels;
419 }
420 
421 
422 //DoWritePreface(rTw,rLabel,pContext)
423 void sDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
424 
425  FD_DHV("sDevice("<<mName<<")::DoWritePreface()");
426  //call base
427  vDevice::DoWritePreface(rTw,rLabel,pContext);
428  //write cycle-time of background task
429  Token ttag;
430  ttag.SetEmpty("SampleInterval");
431  ttag.InsAttributeInteger("value",mCycleTime);
432  rTw<<ttag;
433  // write sync option
434  if(mSyncWrite) {
435  Token stag;
436  stag.SetEmpty("SynchronousWrite");
437  stag.InsAttributeString("value","true");
438  rTw<<stag;
439  }
440 }
441 
442 //DoReadPreface(rTr,rLabel,pContext)
443 void sDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
444 
445  FD_DHV("sDevice("<<mName<<")::DoReadPreface()");
446  // call base
447  vDevice::DoReadPreface(rTr,rLabel,pContext);
448 
449  // sense and digest pre 2.16 format
450  Token token;
451  rTr.Peek(token);
452  if(token.IsInteger()) {
453  mMaxBitAddress = rTr.ReadInteger();
454  mCycleTime = rTr.ReadInteger();
455  Token token;
456  rTr.Peek(token);
457  if(token.IsOption())
458  if(token.OptionValue()=="SyncWrite") {
459  rTr.Get(token);
460  mSyncWrite=true;
461  }
462  return;
463  }
464 
465  // loop my members
466  while(true) {
467  Token token;
468  rTr.Peek(token);
469  // cycle time
470  if(token.IsBegin())
471  if(token.StringValue()=="SampleInterval") {
472  rTr.ReadBegin("SampleInterval", token);
473  mCycleTime=token.AttributeIntegerValue("value");
474  rTr.ReadEnd("SampleInterval");
475  continue;
476  }
477  // sync write
478  if(token.IsBegin())
479  if(token.StringValue()=="SynchronousWrite") {
480  rTr.ReadBegin("SynchronousWrite");
481  rTr.ReadEnd("SynchronousWrite");
482  mSyncWrite=true;
483  if(token.ExistsAttributeString("value"))
484  if(token.AttributeStringValue("value")!="true")
485  mSyncWrite=false;
486  continue;
487  }
488  // break on unknown
489  break;
490  }
491 
492  // done
493 }
494 
495 
496 // lock - unlock shortcuts;
497 #define LOCK_E {int rc = faudes_mutex_lock(&mMutex); \
498  if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: lock mutex error\n"); exit(1); }}
499 #define UNLOCK_E {int rc = faudes_mutex_unlock(&mMutex); \
500  if(rc) {FD_ERR("sDevice("<<mName<<")::LOCK_E: unlock mutex error\n"); exit(1); }}
501 
502 
503 #define TLOCK_E {int rc = faudes_mutex_lock(&sdevice->mMutex); \
504  if(rc) {FD_ERR("sDevice::TLOCK_E: lock mutex error\n"); exit(1); }}
505 
506 #define TUNLOCK_E {int rc = faudes_mutex_unlock(&sdevice->mMutex); \
507  if(rc) {FD_ERR("sDevice::TLOCK_E: unlock mutex error\n"); exit(1); }}
508 
509 
510 
511 
512 
513 // Start(void)
514 void sDevice::Start(void) {
515  // bail out if device was allready started
516  if( (mState == Up) || (mState == StartUp) ) return;
517  FD_DHV("sDevice("<<mName<<")::Start()");
518  // call base incl virtual reset, state=up
519  vDevice::Start();
520  // create background for edge detection and sync write
521  if(!Inputs().Empty() || mSyncWrite){
522  mState=StartUp;
523  mCancelRequest = false;
524  // create and run thread
525  int rc = faudes_thread_create(&mThreadSynchro, SDeviceSynchro, this);
526  if(rc) {
527  FD_ERR("sDevice("<<mName<<")::Start(): cannot creat thread\n");
528  exit(1);
529  }
530  }
531 }
532 
533 // Stop()
534 void sDevice::Stop(void) {
535  // stop implies reset
536  Reset();
537  // bail out if device allready got the command to shut down
538  if(mState != Up && mState !=StartUp) return;
539  FD_DH("sDevice("<<mName<<")::Stop()");
540  // dont kill thread if no thread was created
541  if(!Inputs().Empty() || mSyncWrite) {
542  // cancle thread
543  LOCK_E;
544  FD_DHV("sDevice("<<mName<<")::Stop(): Lock passed, waiting to join thread");
545  mCancelRequest=true;
546  UNLOCK_E;
547  int pc = faudes_thread_join(mThreadSynchro,NULL);
548  if(pc) {
549  FD_ERR("sDevice("<<mName<<")::Stop(): cannot join thread??\n");
550  }
551  }
552  // indicate success
553  FD_DHV("sDevice("<<mName<<")::Stop(): done");
554  mState=Down;
555 }
556 
557 
558 //Reset()
560  // delete dynamic data
561  FD_DHV("sDevice("<<mName<<")::Reset()");
562  // call base (resets time)
563  vDevice::Reset();
564  //delete dynamic data
565  FD_DHV("sDevice("<<mName<<")::Reset(): reset signals");
566  ClrInputSignals();
568  // done
569  FD_DHV("sDevice("<<mName<<")::Reset(): done");
570 }
571 
572 // Clear()
573 void sDevice::Clear(void) {
574  //delete static data
575  FD_DHV("sDevice(" << mName << ")::Clear()");
576  // call base; note: clear implies stop
577  vDevice::Clear();
578  // clear compiled data
579  mInputPosEdgeIndexMap.clear();
580  mInputNegEdgeIndexMap.clear();
581  mMaxBitAddress=-1;
582  mSyncWrite=false;
583  mCycleTime=1000; // usec
584 }
585 
586 //Compile(void)
587 void sDevice::Compile(void){
588  //setup up internal data structure
589  FD_DHV("sDevice(" << mName << ")::Compile()");
590  // call base
592  // clear my internal data
593  mInputPosEdgeIndexMap.clear();
594  mInputNegEdgeIndexMap.clear();
595  mOutputLevelIndexMap.clear();
596  mMaxBitAddress=-1;
597  // setup my internal data
598  for(EventSet::Iterator eit=pConfiguration->Begin(); eit!=pConfiguration->End(); eit++) {
599  AttributeSignalEvent attr = pConfiguration->Attribute(*eit);
600  if(attr.IsInput()) {
601  // fill in reverse maps
602  std::vector<AttributeSignalInput::Trigger>::const_iterator ait;
603  const AttributeSignalInput* sattr = attr.Inputp();
604  for(ait=sattr->mTriggers.begin(); ait!=sattr->mTriggers.end(); ait++) {
605  if(ait->mPos) mInputPosEdgeIndexMap[ait->mBit].Insert(*eit);
606  if(ait->mNeg) mInputNegEdgeIndexMap[ait->mBit].Insert(*eit);
607  if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
608  }
609  }
610  // check max address, set inverse map
611  if(attr.IsOutput()) {
612  std::vector<AttributeSignalOutput::Action>::const_iterator ait;
613  const AttributeSignalOutput* aattr = attr.Outputp();
614  for(ait=aattr->mActions.begin(); ait!=aattr->mActions.end(); ait++) {
615  if(ait->mBit > mMaxBitAddress) mMaxBitAddress=ait->mBit;
616  mOutputLevelIndexMap[ait->mBit].Insert(*eit);
617  if(ait->mValue == AttributeSignalOutput::Inv && !mSyncWrite) {
618  throw Exception("sDevice::Compile(): ",
619  "Inv-Action is only supported with SyncWrite", 52);
620  }
621  }
622  }
623  }
624  // prep state data
625  if(mpInputEdges) delete mpInputEdges;
627  if(mpOutputLevels) delete mpOutputLevels;
631  // report
632 #ifdef FAUDES_DEBUG_IODEVICE
633  for(int i=0; i<=mMaxBitAddress; i++) {
634  if(mOutputLevelIndexMap[i].Empty()) continue;
635  FD_DH("sDevice(" << mName << ")::Compile(): output signal at address " << i);
636  }
637 #endif
638 }
639 
640 
641 // programmatic config: insert input event
642 void sDevice::InsInputEvent(const std::string& event) {
643  if(mState!=Down) return;
645  inp.DefaultInput();
646  Idx ev=pConfiguration->Insert(event);
647  pConfiguration->Attribute(ev, inp);
648 }
649 
650 
651 // programmatic config: add trigger
652 void sDevice::AppendTrigger(const std::string& event, const Trigger& trigger) {
653  if(mState!=Down) return;
654  if(!pConfiguration->Exists(event)) return;
655  Idx ev=pConfiguration->Index(event);
656  AttributeSignalEvent* attr = pConfiguration->Attributep(ev);
657  if(!attr->IsInput()) return;
658  AttributeSignalInput* iattr = attr->Inputp();
659  iattr->mTriggers.push_back(trigger);
660 }
661 
662 // programmatic config: insert output event
663 void sDevice::InsOutputEvent(const std::string& event) {
664  if(mState!=Down) return;
666  outp.DefaultOutput();
667  Idx ev=pConfiguration->Insert(event);
668  pConfiguration->Attribute(ev, outp);
669 }
670 
671 
672 // programmatic config: add action
673 void sDevice::AppendAction(const std::string& event, const Action& action) {
674  if(mState!=Down) return;
675  if(!pConfiguration->Exists(event)) return;
676  if(!pConfiguration->Exists(event)) return;
677  Idx ev=pConfiguration->Index(event);
678  AttributeSignalEvent* attr = pConfiguration->Attributep(ev);
679  if(!attr->IsOutput()) return;
680  AttributeSignalOutput* oattr = attr->Outputp();
681  oattr->mActions.push_back(action);
682 }
683 
684 
685 //CycleTime(void)
686 int sDevice::CycleTime(void) const {
687  //Report current cycle time
688  FD_DHV("sDevice(" << mName << ")::CycleTime()");
689  return mCycleTime;
690 }
691 
692 //CycleTime(int)
693 void sDevice::CycleTime(int cycleTime) {
694  //Set cycle time
695  FD_DHV("sDevice(" << mName << ")::CycleTime(int)");
696  if( mState==Up || mState==StartUp){
697  std::stringstream errstr;
698  errstr << "Changing cycle-time not possible while background thread is still running ";
699  throw Exception("sDevice::CycleTime: ", errstr.str(), 100);
700  }
701  mCycleTime = cycleTime;
702 }
703 
704 
705 //ReadSignal(int)
706 bool sDevice::ReadSignal(int bit){
707  FD_DHV("sDevice(" << mName << ")::ReadSignal(int)");
708  // make sure device is able to read signals
709  if(Inputs().Empty()){
710  std::stringstream errstr;
711  errstr << "(" << mName << ") is not able to read signals";
712  throw Exception("sDevice::ReadSignal():", errstr.str(), 552);
713  }
714  //return if device is running
715  if(mState!=Up && mState!=StartUp) {
716  std::stringstream errstr;
717  errstr << "Signal access not possible while background thread is not running ";
718  throw Exception("sDevice::ReadSignal: ", errstr.str(), 552);
719  }
720  // lock global image, prevent background thread from reading/writing
721  LOCK_E;
722  // run with hooks
723  bool res=false;
724  if(DoReadSignalsPre()) {
725  res=DoReadSignal(bit);
727  }
728  // free global image
729  UNLOCK_E;
730  return res;
731 }
732 
733 //WriteSignal(int,int)
734 void sDevice::WriteSignal(int bit, bool value){
735  // write one actor value, adressed by bit number (0 to 63);
736  FD_DHV("sDevice(" << mName << ")::WriteSignal(int)");
737  // make sure device supports outputs
738  if(Outputs().Empty()){
739  std::stringstream errstr;
740  errstr << "(" << mName << ") is not configured for outputs";
741  throw Exception("sDevice::WriteSignal():", errstr.str(), 552);
742  }
743  // bail out if device is running
744  if(mState!=Up && mState!=StartUp) {
745  std::stringstream errstr;
746  errstr << "Signal access not possible while background thread is not running ";
747  throw Exception("sDevice::ReadSignal: ", errstr.str(), 552);
748  }
749  // lock global image, prevent background thread from reading/writing
750  LOCK_E;
751  // case a) asynchronous write
752  if(!mSyncWrite) {
753  if(DoWriteSignalsPre()) {
754  DoWriteSignal(bit,value);
756  }
757  }
758  // case b) synchronous write
759  if(mSyncWrite) {
760  // record next value
761  Levels* level= &mpOutputLevels[bit];
762  level->next=value;
763  if(level->edge) level->lost=true;
764  level->edge=true;
765  }
766  // free global image
767  UNLOCK_E;
768 }
769 
770 
771 //SDeviceSynchro(void*)
772 void* SDeviceSynchro(void* arg){
773 
774  //background-thread main-routine
775 
776  // cast this object
777  sDevice* sdevice = static_cast<sDevice*>(arg);
778 
779  FD_DH("sDevice(" << sdevice->mName << ")::Synchro(" << sdevice << "): with ct " << sdevice->mCycleTime);
780 
781 #ifdef FAUDES_DEBUG_IOTIMING_X
782  /////////////////////////////////////////////////////
783  // cyletime analysis
784  // timeA: time consumed for an entire cycle
785  // timeB: time consumed for edge detection and i/o
786  // timeC: time left for usleep
787  //
788  // provide arrays for samples
789  faudes_systime_t* timeA = new faudes_systime_t[MAX_SAMPLES];
790  faudes_systime_t* timeB = new faudes_systime_t[MAX_SAMPLES];
791  faudes_systime_t* timeC = new faudes_systime_t[MAX_SAMPLES];
792  // provide pointer to current sample
793  int itime=0;
794  // take a sample
795  faudes_gettimeofday(timeA+itime);
796 #endif
797 
798  bool running=true;
799 
800  while(running){
801 
802  // loop timer
803  faudes_systime_t timeL1;
804  faudes_gettimeofday(&timeL1);
805 
806  // lock global variables
807  TLOCK_E;
808 
809  // call hook
810  sdevice->DoLoopCallback();
811 
812  // start up: initialize dynamic state
813  if(sdevice->mState==sDevice::StartUp) {
814  // reset outputs (clear image)
815  bool aready= sdevice->DoWriteSignalsPre();
816  if(aready) {
817  // output image: set to zero
818  FD_DHV("sDevice("<<sdevice->Name()<<")::synchro: reset: clear lines");
819  for(int bit=0; bit<=sdevice->mMaxBitAddress; bit++) {
820  sDevice::Levels* level= &sdevice->mpOutputLevels[bit];
821  level->current=false;
822  level->next=false;
823  level->edge=false;
824  level->lost=false;
825  level->rel = (!sdevice->mOutputLevelIndexMap[bit].Empty());
826  if(level->rel) sdevice->DoWriteSignal(bit,false);
827  }
828  sdevice->DoWriteSignalsPost();
829  }
830  // reset inputs (edge detecteion)
831  bool sready= sdevice->DoReadSignalsPre();
832  if(sready) {
833  // edge detection: use actual signal levels
834  FD_DHV("sDevice("<<sdevice->Name()<<")::synchro: reset: edge detection");
835  for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
836  sDevice::Edges* edge= &sdevice->mpInputEdges[bit];
837  edge->current=sdevice->DoReadSignal(bit);
838  edge->past = edge->current;
839  edge->pos = false;
840  edge->neg = false;
841  edge->posrel = (!sdevice->mInputPosEdgeIndexMap[bit].Empty());
842  edge->negrel = (!sdevice->mInputNegEdgeIndexMap[bit].Empty());
843  edge->lost = false;
844  }
845  sdevice->DoReadSignalsPost();
846  for(int bit = 0;bit<=sdevice->mMaxBitAddress;bit++) {
847  sDevice::Edges* redge= &sdevice->mpRecentInputEdges[bit];
848  redge->pos = false;
849  redge->neg = false;
850  redge->posrel = false;
851  redge->negrel = false;
852  redge->lost = false;
853  }
854  }
855  // new state
856  if(sready && aready)
857  sdevice->mState=sDevice::Up;
858  }
859 
860  // normal operation, inputs
861  if(sdevice->mState==sDevice::Up) {
862  bool ready=sdevice->DoReadSignalsPre();
863  if(!ready)
864  sdevice->mState=sDevice::StartUp;
865  if(ready) {
866  // edge detection, accumulative
867  for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
868  // define pointer to Inputedges
869  sDevice::Edges* edge= &sdevice->mpInputEdges[bit];
870  // pass edge-info about edge in last cycle
871  edge->past = edge->current;
872  // and get corresponding input-value
873  edge->current = sdevice->DoReadSignal(bit);
874  if(edge->posrel)
875  if(edge->current && (!edge->past) ) {
876  FD_DHV("sDevice::synchro: sensed positive edge at bit address " << bit);
877  edge->pos = true;
878  // queue events to buffer
879  faudes_mutex_lock(sdevice->pBufferMutex);
880  EventSet::Iterator eit=sdevice->mInputPosEdgeIndexMap[bit].Begin();
881  EventSet::Iterator eit_end=sdevice->mInputPosEdgeIndexMap[bit].End();
882  for(; eit!=eit_end; eit++) {
883  sdevice->pInputBuffer->push_back(*eit);
884  }
885  faudes_mutex_unlock(sdevice->pBufferMutex);
886  //send signal to function "WaitSenosrs()"
887  FD_DHV("sDevice::synchro: send signal " );
888  faudes_cond_broadcast(sdevice->pWaitCondition);
889  }
890  if(edge->negrel)
891  if( (!edge->current) && edge->past ) {
892  FD_DHV("sDevice::synchro: sensed negative edge at bit address " << bit);
893  edge->neg = true;
894  sdevice->mInputReady = true;
895  // queue events to buffer
896  faudes_mutex_lock(sdevice->pBufferMutex);
897  EventSet::Iterator eit=sdevice->mInputNegEdgeIndexMap[bit].Begin();
898  EventSet::Iterator eit_end=sdevice->mInputNegEdgeIndexMap[bit].End();
899  for(; eit!=eit_end; eit++) {
900  sdevice->pInputBuffer->push_back(*eit);
901  }
902  faudes_mutex_unlock(sdevice->pBufferMutex);
903  //send signal to function "WaitSenosrs"
904  FD_DHV("sDevice::synchro: send signal " );
905  faudes_cond_broadcast(sdevice->pWaitCondition);
906  }
907  } // loop bits
908  sdevice->DoReadSignalsPost();
909  } // end-if device ok
910  } // end-if inputs
911 
912 
913  // normal operation, outputs
914  if(sdevice->mState==sDevice::Up && sdevice->mSyncWrite) {
915  bool ready=sdevice->DoWriteSignalsPre();
916  if(!ready)
917  sdevice->mState=sDevice::StartUp;
918  if(ready) {
919  // write values from image
920  for(int bit = 0; bit<=sdevice->mMaxBitAddress; bit++) {
921  // define pointer to levels
922  sDevice::Levels* level= &sdevice->mpOutputLevels[bit];
923  // not written by libfaudes
924  if(!level->edge) continue;
925  // write and record
926  sdevice->DoWriteSignal(bit,level->next);
927  level->current = level->next;
928  level->edge = false;
929  level->lost = false;
930  }
931  sdevice->DoWriteSignalsPost();
932  }
933  }
934 
935  // check for cancel request
936  if(sdevice->mCancelRequest) {
937  running=false;
938  sdevice->mState=vDevice::ShutDown;
939  }
940  // unlock global variables
941  TUNLOCK_E;
942 
943 #ifdef FAUDES_DEBUG_IOTIMING_X
944  //////////////////////////////////////
945  //cycletime analysis: take a sample
946  if(itime < MAX_SAMPLES) faudes_gettimeofday(timeB+itime);
947 #endif
948 
949  // let time pass
950  faudes_systime_t timeL2;
951  faudes_gettimeofday(&timeL2);
952  long int delta = (timeL2.tv_nsec - timeL1.tv_nsec)/1000;
953  delta+= 1000000 * (timeL2.tv_sec - timeL1.tv_sec);
954  if(delta < sdevice->mCycleTime) faudes_usleep(sdevice->mCycleTime-delta);
955  else {
956  if(delta > sdevice->mCycleTime)
957  if(sdevice->mState==sDevice::Up)
958  FD_DH("sDevice::synchro: missed cycle time by " << delta - sdevice->mCycleTime << " usec");
959  }
960 
961 
962 #ifdef FAUDES_DEBUG_IOTIMING_X
963  //////////////////////////////////////
964  // cycletime analysis
965 
966  // take a sample
967  if(itime < MAX_SAMPLES) faudes_gettimeofday(timeC+itime);
968  // increment pointer
969  itime++;
970  if(itime < MAX_SAMPLES) faudes_gettimeofday(timeA+itime);
971 
972 #endif
973  // count cycles
974  sdevice->mCycleCount++;
975  } // loop while running
976 
977 
978 #ifdef FAUDES_DEBUG_IOTIMING_X
979 
980  /////////////////////////////////////////////
981  // cycletime analysis
982  // set up statsitics
983  FD_DHT("sDevice::synchro: performance analysis");
984 
985  SampledDensityFunction SamplesA;
986  SamplesA.Clear();
987  SamplesA.Dim(100);
988  SamplesA.Name("time stamp AA: overall period");
989 
990  SampledDensityFunction SamplesB;
991  SamplesB.Clear();
992  SamplesB.Dim(100);
993  SamplesB.Name("time stamp AB: process time");
994 
995  SampledDensityFunction SamplesC;
996  SamplesC.Clear();
997  SamplesC.Dim(100);
998  SamplesC.Name("time stamp CB: sleep time");
999 
1000  SampledDensityFunction SamplesWS;
1001  SamplesWS.Clear();
1002  SamplesWS.Dim(100);
1003  SamplesWS.Name("time passed till the next call of WaitInputs");
1004 
1005  // timeval-structures needed for further computations
1006  faudes_systime_t dAA,dBA,dCB,dER;
1007 
1008  // perform analysis
1009  // time for a hole cycle
1010  for(int ind = 0; ind < itime-2; ind++){
1011  // compute time needed
1012  // for a hole cycle
1013  faudes_diffsystime(timeA[ind+1],timeA[ind],&dAA);
1014  // for computing input-state
1015  faudes_diffsystime(timeB[ind],timeA[ind],&dBA);
1016  // by usleep(mCyleTime)
1017  faudes_diffsystime(timeC[ind],timeB[ind],&dCB);
1018  // time passed by until the next call of WaitInputs
1019  faudes_diffsystime(sdevice->mptimeBegin[ind+1],sdevice->mptimeEnd[ind],&dER);
1020  // insert samples to density functions
1021  SamplesA.Sample(dAA.tv_sec*1000000 + dAA.tv_nsec/1000);
1022  SamplesB.Sample(dBA.tv_sec*1000000 + dBA.tv_nsec/1000);
1023  SamplesC.Sample(dCB.tv_sec*1000000 + dCB.tv_nsec/1000);
1024  SamplesWS.Sample(1000000*dER.tv_sec + dER.tv_nsec/1000);
1025  }
1026 
1027  // perform statistic computation
1028  SamplesA.Compile();
1029  SamplesB.Compile();
1030  SamplesC.Compile();
1031  SamplesWS.Compile();
1032 
1033  // token output
1034  // SamplesA.Write();
1035  // SamplesB.Write();
1036  // SamplesC.Write();
1037  // SamplesWS.Write();
1038 
1039  // pretty print output
1040  std::cout << SamplesA.Str() << std::endl;
1041  std::cout << SamplesB.Str() << std::endl;
1042  std::cout << SamplesC.Str() << std::endl;
1043  std::cout << SamplesWS.Str() << std::endl;
1044 #endif
1045 
1046  FD_DH("sDevice(" << sdevice->mName << ")::synchro: terminate background thread");
1047  faudes_thread_exit(NULL);
1048  // never happens, prevent gcc warning
1049  return NULL;
1050 }
1051 
1052 // Write Output(Idx)
1054 
1055  FD_DHV("sDevice("<<mName<<")::WriteOutput(" << output <<")");
1056  //return if device is running
1057  if(mState!=Up && mState!=StartUp) return;
1058  //make sure event is part of devices eventset
1059  if(!mOutputs.Exists(output)) {
1060  std::stringstream errstr;
1061  errstr << "Unknown output event " << output;
1062  throw Exception("sDevice::WriteOutput", errstr.str(), 65);
1063  }
1064  // find properties
1065  const AttributeSignalOutput* aattr = pConfiguration->Attribute(output).Outputp();
1066  if(!aattr) {
1067  std::stringstream errstr;
1068  errstr << "Invalid output attribute " << output;
1069  throw Exception("sDevice::WriteOutput", errstr.str(), 65);
1070  }
1071  //debug-flag
1072  FD_DHV("sDevice("<<mName<<")::WriteOutput: properties found");
1073  // execute command ...
1074  std::vector<AttributeSignalOutput::Action>::const_iterator eit;
1075  // ... case a) asynchronous write (does not supper invert)
1076  if(!mSyncWrite) {
1077  // prepare
1078  if(DoWriteSignalsPre()) {
1079  // loop actions
1080  for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
1081  FD_DHV("sDevice("<<mName<<")::WriteOutput: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
1082  DoWriteSignal(eit->mBit,eit->mValue == AttributeSignalOutput::Set);
1083  }
1085  }
1086  }
1087  // ... case b) synchronous write (does support invert)
1088  if(mSyncWrite) {
1089  // lock global image
1090  LOCK_E;
1091  // loop actions and record
1092  for(eit=aattr->mActions.begin(); eit!=aattr->mActions.end(); eit++){
1093  FD_DHV("sDevice("<<mName<<")::WriteOutput: mBit "<<eit->mBit<< " mValue "<<eit->mValue);
1094  Levels* level= &mpOutputLevels[eit->mBit];
1095  switch(eit->mValue) {
1097  level->next=1; break;
1099  level->next=0; break;
1101  level->next= !level->next; break;
1102  }
1103  if(level->edge) level->lost=true;
1104  level->edge=true;
1105  }
1106  // free global image
1107  UNLOCK_E;
1108  }
1109  // done
1110  FD_DHV("sDevice("<<mName<<")::WriteOutput: done");
1111 }
1112 
1113 //ClrInputSignals()
1115  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): MaxBitAddress: " << mMaxBitAddress);
1116  //return if device is not running or device is not able to read inputs
1117  if( mState!=Up || Inputs().Empty()) return;
1118  // lock global variables
1119  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): lock mutex ");
1120  LOCK_E;
1121  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detection ");
1122  // initialise edge detection: assume low signals
1123  for(int bit = 0;bit<=mMaxBitAddress;bit++) {
1124  Edges* edge= &mpInputEdges[bit];
1125  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detetion ReadSignal bit " << bit);
1126  edge->current=0;
1127  edge->past = 0;
1128  edge->pos = false;
1129  edge->neg = false;
1130  edge->posrel = (!mInputPosEdgeIndexMap[bit].Empty());
1131  edge->negrel = (!mInputNegEdgeIndexMap[bit].Empty());
1132  edge->lost = false;
1133  }
1134  // initialise edge detection: actual signal levels
1135  if(DoReadSignalsPre()) {
1136  for(int bit = 0;bit<=mMaxBitAddress;bit++) {
1137  Edges* edge= &mpInputEdges[bit];
1138  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): edge detetion ReadSignal bit " << bit);
1139  edge->current=DoReadSignal(bit);
1140  edge->past = edge->current;
1141  edge->pos = false;
1142  edge->neg = false;
1143  edge->posrel = (!mInputPosEdgeIndexMap[bit].Empty());
1144  edge->negrel = (!mInputNegEdgeIndexMap[bit].Empty());
1145  edge->lost = false;
1146  }
1148  }
1149  // initialize edge detection: recent edges
1150  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): initialize recent edges ");
1151  for(int bit = 0;bit<=mMaxBitAddress;bit++) {
1152  Edges* redge= &mpRecentInputEdges[bit];
1153  redge->pos = false;
1154  redge->neg = false;
1155  redge->posrel = false;
1156  redge->negrel = false;
1157  redge->lost = false;
1158  }
1159  // reset cyclecount
1160  mCycleCount=0;
1162  mInputReady=false;
1163  // unlock global variables
1164  UNLOCK_E;
1165  FD_DHV("sDevice("<<mName<<")::ClrInputSignals(): done");
1166 }
1167 
1168 //ClrOutputSignals()
1170  //clear all output line levels
1171  FD_DHV("sDevice("<<mName<<")::ClrOutputSignals");
1172  // return if device is not running or not abel to set output signals
1173  if(mState!=Up || Outputs().Empty()) return;
1174  // lock variables, prevent background from writing
1175  LOCK_E;
1176  FD_DHV("sDevice("<<mName<<")::ClrOutputSignals: passed lock");
1177  // clear all (allways asynchronous)
1178  if(DoWriteSignalsPre()) {
1179  for(int bit=0; bit<=mMaxBitAddress; bit++)
1180  if(mpOutputLevels[bit].rel) DoWriteSignal(bit, false);
1182  }
1183  // clear image
1184  for(int bit=0; bit<=mMaxBitAddress; bit++) {
1185  Levels* level= &mpOutputLevels[bit];
1186  level->current=false;
1187  level->next=false;
1188  level->edge=false;
1189  level->lost=false;
1190  }
1191  // done
1192  UNLOCK_E;
1193  FD_DHV("sDevice("<<mName<<")::ClrOutputSignals: done");
1194 }
1195 
1196 }//end namespace faudes
1197 
1198 
#define FD_ERR(message)
Debug: report more errors with file/line info.
void faudes_usleep(long int usec)
void faudes_diffsystime(const faudes_systime_t &end, const faudes_systime_t &begin, faudes_systime_t *res)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Definition: cfl_types.h:946
Attribute for the configuration of a input or output mapping.
Definition: iop_vdevice.h:68
const AttributeVoid * pOutputPrototype
Output Prototype (set to nontrivial attribute in derived classes)
Definition: iop_vdevice.h:148
void DefaultOutput(void)
Set to default output attribute.
Definition: iop_vdevice.h:97
const AttributeVoid * pInputPrototype
Input Prototype (set to nontrivial attribute in derived classes)
Definition: iop_vdevice.h:151
bool IsOutput(void) const
Does this attribute define an output mapping?
Definition: iop_vdevice.h:91
void DefaultInput(void)
Set to default input attribute.
Definition: iop_vdevice.h:103
bool IsInput(void) const
Does this attribute define a input mapping?
Definition: iop_vdevice.h:94
Configuration of a signal based input or output.
Definition: iop_sdevice.h:224
static const AttributeSignalOutput * OutputPrototypep(void)
Prototype, output (construct on first use static)
void DoAssign(const AttributeSignalEvent &rSrc)
DoAssign.
Definition: iop_sdevice.h:257
const AttributeSignalInput * Inputp(void) const
Get input mapping.
Definition: iop_sdevice.h:249
const AttributeSignalOutput * Outputp(void) const
Get output mapping.
Definition: iop_sdevice.h:243
static const AttributeSignalInput * InputPrototypep(void)
Prototype, input (construct on first use static)
AttributeSignalEvent(void)
Default constructor (no mapping at all)
Typedef for a single input trigger.
Definition: iop_sdevice.h:150
Configuration of a signal based input mapping.
Definition: iop_sdevice.h:130
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads the attribute from TokenReader, see AttributeVoid for public wrappers.
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes the attribute to TokenWriter, see AttributeVoid for public wrappers.
std::vector< Trigger > mTriggers
List of triggers.
Definition: iop_sdevice.h:159
Typedef for a single output action.
Definition: iop_sdevice.h:56
Configuration of a signal based output mapping.
Definition: iop_sdevice.h:33
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes the attribute to TokenWriter, see AttributeVoid for public wrappers.
Definition: iop_sdevice.cpp:41
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads the attribute from TokenReader, see AttributeVoid for public wrappers.
Definition: iop_sdevice.cpp:63
std::vector< Action > mActions
List of actions to perform.
Definition: iop_sdevice.h:64
Minimal Attribute.
Auto register faudes-type with specified type name.
Definition: cfl_registry.h:460
const std::string & Name(void) const
std::string Str(void) const
Faudes exception class.
bool Exists(const Idx &rIndex) const
Test existence of index.
void Sample(Time::Type time)
Set of indices with symbolic names and attributes.
Definition: cfl_nameset.h:566
A TokenReader reads sequential tokens from a file or string.
long int ReadInteger(void)
Read integer token.
std::string FileLine(void) const
Return "filename:line".
std::string ReadOption(void)
Read option token.
bool Eos(const std::string &rLabel)
Peek a token and check whether it ends the specified section.
void ReadEnd(const std::string &rLabel)
Close the current section by matching the previous ReadBegin().
void ReadBegin(const std::string &rLabel)
Open a section by specified label.
bool Get(Token &token)
Get next token.
bool Peek(Token &token)
Peek next token.
A TokenWriter writes sequential tokens to a file, a string or stdout.
void WriteEnd(const std::string &rLabel)
Write end label.
void WriteBegin(const std::string &rLabel)
Write begin label.
Tokens model atomic data for stream IO.
Definition: cfl_token.h:54
const std::string & StringValue(void) const
Get string value of a name token.
Definition: cfl_token.cpp:178
Int AttributeIntegerValue(const std::string &name)
Access attribute value.
Definition: cfl_token.cpp:397
bool IsInteger(void) const
Test token Type.
Definition: cfl_token.cpp:219
bool ExistsAttributeString(const std::string &name)
Test attibute existence.
Definition: cfl_token.cpp:356
bool IsBegin(void) const
Test token Type.
Definition: cfl_token.cpp:259
void SetEmpty(const std::string &rName)
Initialize as empty-tag token.
Definition: cfl_token.cpp:106
const std::string & OptionValue(void) const
Get option value of a name token.
Definition: cfl_token.cpp:184
void InsAttributeInteger(const std::string &name, Int value)
Insert named attribute with integer value.
Definition: cfl_token.cpp:319
void InsAttributeString(const std::string &name, const std::string &value)
Insert named attribute with string value.
Definition: cfl_token.cpp:310
bool IsOption(void) const
Test token Type.
Definition: cfl_token.cpp:239
const std::string & AttributeStringValue(const std::string &name)
Access attribute value.
Definition: cfl_token.cpp:386
Base class of all libFAUDES objects that participate in the run-time interface.
Definition: cfl_types.h:239
An sDevice implements signal based semantics for faudes events.
Definition: iop_sdevice.h:287
virtual int CycleTime() const
Report cycle time.
int mCycleCount
Background: cycle counter (shared)
Definition: iop_sdevice.h:623
void ClrOutputSignals(void)
clear all output values
bool mCancelRequest
Background: terminate-flag for background task.
Definition: iop_sdevice.h:661
virtual void DoReadSignalsPost(void)
IO Hook, inputs.
Definition: iop_sdevice.h:543
virtual void WriteOutput(Idx output)
Run output command.
int mCycleTime
Cycle time of background thread in nsecs (shared)
Definition: iop_sdevice.h:620
virtual void Stop(void)
Deactivate the device.
int mMaxBitAddress
Address range.
Definition: iop_sdevice.h:482
virtual void DoWriteSignalsPost(void)
IO Hook, output.
Definition: iop_sdevice.h:581
std::map< int, EventSet > mInputNegEdgeIndexMap
Reverse input map: map signal edges to logical event sets.
Definition: iop_sdevice.h:476
Edges * mpRecentInputEdges
Background: recently accumulated edges (global only)
Definition: iop_sdevice.h:643
virtual void DoReadPreface(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads non-event-related configuration from TokenReader.
virtual bool DoWriteSignalsPre(void)
IO Hook, outputs.
Definition: iop_sdevice.h:571
faudes_thread_t mThreadSynchro
Background: thread handle (global)
Definition: iop_sdevice.h:617
Edges * mpInputEdges
Background: accumulated edges (shared)
Definition: iop_sdevice.h:640
void InsInputEvent(const std::string &event)
Insert event as input event.
virtual void Clear(void)
Clear all configuration.
bool mSyncWrite
True for synchronous output writes.
Definition: iop_sdevice.h:612
void DoWritePreface(TokenWriter &rTw, const std::string &rLabel, const Type *pContext=0) const
Writes non-event-related configuration to TokenWriter.
bool mInputReady
Background: some input event did occur (shared)
Definition: iop_sdevice.h:646
virtual void DoLoopCallback(void)
Loop hook.
Definition: iop_sdevice.h:605
void AppendAction(const std::string &event, const Action &action)
Add an action.
virtual ~sDevice(void)
Explicit destructor.
virtual void Start(void)
Activate the device.
void InsOutputEvent(const std::string &event)
Insert event as output event.
faudes_mutex_t mMutex
Background: mutex for below shared variables.
Definition: iop_sdevice.h:605
virtual bool DoReadSignal(int bitaddr)=0
Sample input signal.
virtual void DoWriteSignal(int bitaddr, bool value)=0
Reimplement this function in a derived class for actual harware access to set or clear an output sign...
sDevice(void)
Default constructor.
virtual bool DoReadSignalsPre(void)
IO Hook, inputs.
Definition: iop_sdevice.h:533
TaNameSet< AttributeSignalEvent > * pConfiguration
Overall configuration (with actual type)
Definition: iop_sdevice.h:470
void AppendTrigger(const std::string &event, const Trigger &trigger)
Add a trigger condition.
int mRecentCycleCount
Background: cycle count (global only)
Definition: iop_sdevice.h:626
friend void * SDeviceSynchro(void *)
std::map< int, EventSet > mInputPosEdgeIndexMap
Reverse input map: map signal edges to logical event sets.
Definition: iop_sdevice.h:473
void ClrInputSignals(void)
clear all input states
void WriteSignal(int bitaddr, bool value)
Set output signal.
virtual void Reset(void)
Clear dynamic data and restart device.
std::map< int, EventSet > mOutputLevelIndexMap
Reverse output map: map signal addres to events that affect the resp.
Definition: iop_sdevice.h:479
bool ReadSignal(int bitaddr)
Get input signal.
virtual void Compile(void)
Build up internal data-structure (e.g.
Levels * mpOutputLevels
Background: accumulated output values (shared)
Definition: iop_sdevice.h:658
Virtual base class to define the interface for event io.
Definition: iop_vdevice.h:261
int mTimeScale
FauDES-time: scaling factor in ms/ftu.
Definition: iop_vdevice.h:788
faudes_mutex_t * pBufferMutex
Actual mutex for input buffer (mutexted)
Definition: iop_vdevice.h:803
virtual void Clear(void)
Clear all configuration.
virtual const EventSet & Inputs(void) const
Get inputs as plain set.
virtual void Compile(void)
Compile inner data-structures.
std::string mDefaultLabel
Default label for token io.
Definition: iop_vdevice.h:721
faudes_cond_t * pWaitCondition
Actual Wait Condition.
Definition: iop_vdevice.h:782
virtual void DoReadPreface(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads non-event-configuration data from TokenReader.
virtual void Start(void)
Activate the device.
EventSet * mpConfiguration
Overall event configuration (uses cast for type)
Definition: iop_vdevice.h:761
EventSet mOutputs
All outputs.
Definition: iop_vdevice.h:767
virtual void Reset(void)
Reset device.
virtual void DoWritePreface(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes non-event-configuration data from TokenWriter.
void Name(const std::string &rName)
Set the device name.
std::string mName
Name.
Definition: iop_vdevice.h:758
std::deque< Idx > * pInputBuffer
Actual Fifo buffer for input readings.
Definition: iop_vdevice.h:797
DeviceState mState
Status: running, starting etc.
Definition: iop_vdevice.h:770
virtual const EventSet & Outputs(void) const
Get outputs as plain set.
#define TUNLOCK_E
#define UNLOCK_E
#define TLOCK_E
#define LOCK_E
Virtual device for signal based io
#define FD_DHV(message)
Definition: iop_vdevice.h:37
#define FD_DHT(message)
Definition: iop_vdevice.h:43
#define FD_DH(message)
Definition: iop_vdevice.h:27
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void * SDeviceSynchro(void *arg)
AutoRegisterXElementTag< TaNameSet< AttributeSignalEvent > > gRti1XElementTagSignalDeviceEventSet("SignalDeviceEventSet", "Event")
AutoRegisterType< TaNameSet< AttributeSignalEvent > > gRti1RegisterSignalDeviceEventSet("SignalDeviceEventSet")
Discrete density function approximation.
Background: type def for edge detection
Definition: iop_sdevice.h:629
Background: type def output values
Definition: iop_sdevice.h:649

libFAUDES 2.32f --- 2024.12.22 --- c++ api documentaion by doxygen