iop_sdevice.hGo to the documentation of this file.00001 /** @file iop_sdevice.h Virtual device for signal based io */ 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 #ifndef FAUDES_SDEVICE_H 00014 #define FAUDES_SDEVICE_H 00015 00016 #include "corefaudes.h" 00017 #include "iop_vdevice.h" 00018 00019 00020 00021 namespace faudes { 00022 00023 00024 /** 00025 * Configuration of a signal based output mapping. 00026 * 00027 * An output mapping consists of a list of actions that to be performed when the 00028 * event is executed. Each action may set or clear the physical output line 00029 * specified by an abstract bitaddress. 00030 * 00031 */ 00032 00033 class AttributeSignalOutput : public AttributeVoid { 00034 00035 FAUDES_TYPE_DECLARATION(Void,AttributeSignalOutput,AttributeVoid) 00036 00037 public: 00038 00039 /** Default constructor (no actions at all) */ 00040 AttributeSignalOutput(void) : AttributeVoid() {}; 00041 00042 /** Copy - constructor */ 00043 AttributeSignalOutput(const AttributeSignalOutput& rOtherAttr) : AttributeVoid() 00044 { DoAssign(rOtherAttr); }; 00045 00046 /** Test for default value (never) */ 00047 virtual bool IsDefault(void) const {return false;}; 00048 00049 /** Clear */ 00050 virtual void Clear(void) {mActions.clear();}; 00051 00052 /** Enum for action */ 00053 typedef enum { Set, Clr, Inv } Value; 00054 00055 /** Typedef for a single output action */ 00056 class Action { 00057 public: 00058 Action(void) {mBit=0;mValue=Clr;}; 00059 int mBit; //// Bitaddress (numeric) 00060 Value mValue; //// Value to set (enum: set,clr,inv) 00061 }; 00062 00063 /** List of actions to perform */ 00064 std::vector<Action> mActions; 00065 00066 protected: 00067 00068 /** 00069 * Copy method 00070 * 00071 * @param rSrcAttr 00072 * Source to copy from 00073 * @return 00074 * Ref to this attribute 00075 */ 00076 virtual void DoAssign(const AttributeSignalOutput& rSrcAttr); 00077 00078 /** 00079 * Reads the attribute from TokenReader, see AttributeVoid for public wrappers. 00080 * 00081 * If the current token indicates an output mapping, the method reads that 00082 * section. Else it does nothing. Exceptions may only be thrown 00083 * on invalid data within the section. The label argument is ignored, we the hardcoded 00084 * output for output device attributes. The context argument is ignored. 00085 * 00086 * @param rTr 00087 * TokenReader to read from 00088 * @param rLabel 00089 * Section to read 00090 * @param pContext 00091 * Read context to provide contextual information 00092 * 00093 * @exception Exception 00094 * - IO error (id 1) 00095 */ 00096 virtual void DoRead(TokenReader& rTr,const std::string& rLabel="", const Type* pContext=0); 00097 00098 /** 00099 * Writes the attribute to TokenWriter, see AttributeVoid for public wrappers. 00100 * 00101 * Writes the output mapping data. The label argument is ignored, we use 00102 * the hardcoded section "Output". The context argument is ignored. 00103 * 00104 * @param rTw 00105 * TokenWriter to write to 00106 * @param rLabel 00107 * Section to write 00108 * @param pContext 00109 * Read context to provide contextual information 00110 * 00111 * @exception Exception 00112 * - IO error (id 2) 00113 */ 00114 virtual void DoWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const; 00115 00116 }; // end class AttributeSignalOutput 00117 00118 00119 00120 00121 00122 00123 /** 00124 * Configuration of a signal based input mapping. 00125 * 00126 * A input mapping consists of a list of abstract bitaddresses with an 00127 * edge polarity each. When on one of respecive physical input lines an edge 00128 * with matching priority is sensed, the logical event is triggered. 00129 * 00130 */ 00131 00132 class AttributeSignalInput : public AttributeVoid { 00133 00134 FAUDES_TYPE_DECLARATION(Void,AttributeSignalInput,AttributeVoid) 00135 00136 public: 00137 00138 /** Default constructor (no triggers) */ 00139 AttributeSignalInput(void) : AttributeVoid() {}; 00140 00141 /** Copy constructor */ 00142 AttributeSignalInput (const AttributeSignalInput& rOtherAttr) : AttributeVoid() 00143 { DoAssign(rOtherAttr); }; 00144 00145 /** Test for default value (never) */ 00146 virtual bool IsDefault(void) const {return false;}; 00147 00148 /** Clear */ 00149 virtual void Clear(void) {mTriggers.clear();}; 00150 00151 /** Typedef for a single input trigger */ 00152 class Trigger { 00153 public: 00154 Trigger(void) {mBit=0; mPos=false; mNeg=false;}; 00155 int mBit; //// Bitaddress 00156 bool mPos; //// Positive edge triggers event 00157 bool mNeg; //// Negative edge triggers event 00158 }; 00159 00160 /** List of triggers */ 00161 std::vector<Trigger> mTriggers; 00162 00163 protected: 00164 00165 /** 00166 * Copy method 00167 * 00168 * @param rSrcAttr 00169 * Source to copy from 00170 * @return 00171 * Ref to this attribute 00172 */ 00173 virtual void DoAssign(const AttributeSignalInput& rSrcAttr); 00174 00175 /** 00176 * Reads the attribute from TokenReader, see AttributeVoid for public wrappers. 00177 * 00178 * If the current token indicates a input mapping, the method reads that 00179 * section. Else it does nothing. Exceptions may only be thrown 00180 * on invalid data within the section. The label argument is ignored, we use the 00181 * hardcoded section "Input" for input attributes. The context argument is ignored. 00182 * 00183 * @param rTr 00184 * TokenReader to read from 00185 * @param rLabel 00186 * Section to read 00187 * @param pContext 00188 * Read context to provide contextual information 00189 * 00190 * @exception Exception 00191 * - IO error (id 1) 00192 */ 00193 virtual void DoRead(TokenReader& rTr,const std::string& rLabel="", const Type* pContext=0); 00194 00195 00196 /** 00197 * Writes the attribute to TokenWriter, see AttributeVoid for public wrappers. 00198 * 00199 * Writes the input mapping data.The label argument is ignored, we use the 00200 * hardcoded section "Input". The context argument is ignored. 00201 * 00202 * @param rTw 00203 * TokenWriter to write to 00204 * @param rLabel 00205 * Section to write 00206 * @param pContext 00207 * Read context to provide contextual information 00208 * 00209 * @exception Exception 00210 * - IO error (id 2) 00211 */ 00212 00213 virtual void DoWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const; 00214 00215 }; // end class AttributeSignalInput 00216 00217 00218 00219 00220 /** 00221 * Configuration of a signal based input or output 00222 * 00223 * This class is derived from the AttributeDeviceEvent to specialise 00224 * for signal based input and output mapping. 00225 * 00226 */ 00227 00228 class AttributeSignalEvent : public AttributeDeviceEvent { 00229 00230 FAUDES_TYPE_DECLARATION(Void,AttributeSignalEvent,AttributeDeviceEvent) 00231 00232 public: 00233 00234 /** Default constructor (no mapping at all) */ 00235 AttributeSignalEvent(void); 00236 00237 /** Copy constructor */ 00238 AttributeSignalEvent(const AttributeSignalEvent& rOtherAttr); 00239 00240 /** Test for default value (never) */ 00241 virtual bool IsDefault(void) const {return false;}; 00242 00243 /** Clear */ 00244 virtual void Clear(void) { AttributeDeviceEvent::Clear(); }; 00245 00246 /** Get output mapping */ 00247 const AttributeSignalOutput* Outputp(void) const { 00248 return static_cast<AttributeSignalOutput*>(mpOutputAttribute); }; 00249 AttributeSignalOutput* Outputp(void) { 00250 return static_cast<AttributeSignalOutput*>(mpOutputAttribute); }; 00251 00252 /** Get input mapping */ 00253 const AttributeSignalInput* Inputp(void) const { 00254 return static_cast<AttributeSignalInput*>(mpInputAttribute); }; 00255 AttributeSignalInput* Inputp(void) { 00256 return static_cast<AttributeSignalInput*>(mpInputAttribute); }; 00257 00258 protected: 00259 00260 /** DoAssign */ 00261 virtual void DoAssign(const AttributeSignalEvent& rSrc) 00262 { AttributeDeviceEvent::DoAssign(rSrc);}; 00263 00264 /** Prototype, input (construct on first use static) */ 00265 static const AttributeSignalInput* InputPrototypep(void); 00266 00267 /** Prototype, output (construct on first use static) */ 00268 static const AttributeSignalOutput* OutputPrototypep(void); 00269 00270 }; // class AttributeSignalEvent 00271 00272 00273 00274 /** 00275 * An sDevice implements signal based semantics for faudes events. 00276 * 00277 * The class is configured by AttributeSignalEvents, which in turn consist of 00278 * either a AttributeSignalInput or a AttributeSignalOutput. Thus, 00279 * we set and clear output signals for output events, while edges on input 00280 * signals trigger input events. 00281 * 00282 * Sensing edges is done by separate thread that is started by Start(). 00283 * 00284 * This class is still virtual in that it does not provide the code for actually 00285 * reading or writing signals. See cDevice and pDevice for derived device classes 00286 * that implement digital io via comedi or the parallel printer port, respectively. 00287 * 00288 * @ingroup IODevicePlugin 00289 */ 00290 00291 class sDevice : public vDevice { 00292 00293 // provide all access to background task 00294 friend void* SDeviceSynchro(void*); 00295 00296 public: 00297 00298 // have my types 00299 typedef AttributeSignalInput::Trigger Trigger; 00300 typedef AttributeSignalOutput::Action Action; 00301 typedef AttributeSignalOutput::Value Value; 00302 00303 /** 00304 * Default constructor 00305 */ 00306 sDevice(void); 00307 00308 /** 00309 * copy-constructor 00310 */ 00311 sDevice(const sDevice& rOtherDevice); 00312 00313 /** 00314 * Explicit destructor. 00315 */ 00316 virtual ~sDevice(void); 00317 00318 00319 /** 00320 * Clear all configuration. 00321 * This implies Stop(). 00322 */ 00323 virtual void Clear(void); 00324 00325 /** 00326 * 00327 * Build up internal data-structure (e.g. signal-event - mapping) 00328 * 00329 */ 00330 virtual void Compile(void); 00331 00332 /** 00333 * Insert event as input event. 00334 * Note: you can only configure events 00335 * while the device is down. 00336 * 00337 * @param event 00338 * Event by name. 00339 */ 00340 void InsInputEvent(const std::string& event); 00341 00342 00343 /** 00344 * Add a trigger condition. 00345 * Note: you can only add a trigger condition to an 00346 * input event; you can only (re)-configure events 00347 * while the device is down. 00348 * 00349 * @param event 00350 * Event 00351 * @param trigger 00352 * Trigger to append 00353 */ 00354 void AppendTrigger(const std::string& event, const Trigger& trigger); 00355 00356 /** 00357 * Insert event as output event. 00358 * Note: you can only configure event 00359 * while the device is down. 00360 * 00361 * @param event 00362 * Event by name. 00363 */ 00364 void InsOutputEvent(const std::string& event); 00365 00366 /** 00367 * Add an action. 00368 * Note: you can only add a actions to an 00369 * output event; you can only (re)-configure events 00370 * while the device is down. 00371 * 00372 * @param event 00373 * Event 00374 * @param action 00375 * Action to append 00376 */ 00377 void AppendAction(const std::string& event, const Action& action); 00378 00379 /** 00380 * Report max bit address. 00381 * 00382 * @return 00383 * Set of all configured inputs 00384 */ 00385 int MaxBitAddress(void) const { return mMaxBitAddress;}; 00386 00387 00388 /** 00389 * Activate the device. This function enables output execution and input reading. 00390 * It starts the background thread for edge detection and input event buffer. 00391 * 00392 * @exception Exception 00393 * - Not yet configured (id 551) 00394 */ 00395 virtual void Start(void); 00396 00397 /** 00398 * Deactivate the device. This function disables output execution and input reading. 00399 * It stops the backhround thread and resets all output signals to 0. 00400 */ 00401 virtual void Stop(void); 00402 00403 00404 /** 00405 * Clear dynamic data and restart device 00406 */ 00407 virtual void Reset(void); 00408 00409 00410 /** 00411 * Run output command. 00412 * 00413 * @exception Exception 00414 * - unknown output event (id 65) 00415 */ 00416 virtual void WriteOutput(Idx output); 00417 00418 00419 00420 /** 00421 * Set output signal. 00422 * 00423 * 00424 * This function provides user level access to output signals. 00425 * It executes the virtual pre and post hook methods 00426 * and the virtual actual harware access to set the signal level 00427 * via DoWriteSignal(int,bool). 00428 * 00429 * @param bitaddr 00430 * Abstract bit address 00431 * @param value 00432 * True for active/high/1/set; 00433 * false for passive/low/0/clr; 00434 * 00435 */ 00436 void WriteSignal(int bitaddr, bool value); 00437 00438 /** 00439 * Get input signal. 00440 * 00441 * This function provides user level access to input signals. 00442 * It executes the virtual pre and post hook methods 00443 * and the virtual actual harware access to sample an input signal via DoReadSignal(int). 00444 * 00445 * @param bitaddr 00446 * Abstract bit address 00447 * @return 00448 * True for logic level high; 00449 */ 00450 bool ReadSignal(int bitaddr); 00451 00452 00453 /** 00454 * Report cycle time 00455 * 00456 * @return 00457 * Actual cycle time in ussecs 00458 */ 00459 00460 virtual int CycleTime() const; 00461 00462 /** 00463 * Set cycle time 00464 * 00465 * @param cycleTime 00466 * Desired cycle time in usecs 00467 */ 00468 00469 virtual void CycleTime(int cycleTime); 00470 00471 protected: 00472 00473 /** Overall configuration (with actual type) */ 00474 TaNameSet<AttributeSignalEvent>* pConfiguration ; 00475 00476 /** Reverse input map: map signal edges to logical event sets */ 00477 std::map<int, EventSet> mInputPosEdgeIndexMap; 00478 00479 /** Reverse input map: map signal edges to logical event sets */ 00480 std::map<int, EventSet> mInputNegEdgeIndexMap; 00481 00482 /** Reverse output map: map signal addres to events that affect the resp. line */ 00483 std::map<int, EventSet> mOutputLevelIndexMap; 00484 00485 /** Address range */ 00486 int mMaxBitAddress; 00487 00488 /** 00489 * Writes non-event-related configuration to TokenWriter 00490 * 00491 * Device data will be written bottom-to-top along the class-hierarchy, 00492 * see also vDevice::DoWritePreface. 00493 * 00494 * Note: in order to keep the outputfile-layout as simple as possible no label will 00495 * be used to separate this data-section. 00496 * 00497 * @param rTw 00498 * TokenWriter to write 00499 * @param rLabel 00500 * Section to write 00501 * @param pContext 00502 * Context to provide contextual information 00503 * 00504 * */ 00505 void DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext=0) const; 00506 00507 /** 00508 * Reads non-event-related configuration from TokenReader 00509 * 00510 * Device date is read bottom-to-top along the class-hierarchy; 00511 * see also vDevice::DoReadPreface. 00512 * 00513 * 00514 * Note: in order to keep the inputfile-layout as simple as possible no label will 00515 * be used to separate this data-section. 00516 * 00517 * @param rTr 00518 * TokenReader to read from 00519 * @param rLabel 00520 * Section to read 00521 * @param pContext 00522 * Read context to provide contextual information 00523 * 00524 * */ 00525 virtual void DoReadPreface(TokenReader& rTr,const std::string& rLabel="", const Type* pContext=0); 00526 00527 /** 00528 * IO Hook, inputs 00529 * 00530 * The background thread calls this hook before reading input signals. 00531 * You may reimplement this method to e.g. prepare a process image. 00532 * 00533 * @return 00534 * True on success, false on error 00535 * 00536 */ 00537 virtual bool DoReadSignalsPre(void) {return true;}; 00538 00539 /** 00540 * IO Hook, inputs 00541 * 00542 * The background thread calls this hook after reading input signals. 00543 * You may reimplement this method to e.g. release a process image. 00544 * 00545 * 00546 */ 00547 virtual void DoReadSignalsPost(void) {}; 00548 00549 /** 00550 * Sample input signal. 00551 * 00552 * Reimplement this function to implements actual harware access to sample an input signal. 00553 * This function gets 00554 * called from the periodic background thread to sense edges. 00555 * It is guaranteed that the pre-hook was called befor and returned "true". 00556 * The post-hook will be invoked after relevant signals have been sampled. 00557 * 00558 * @param bitaddr 00559 * Abstract bit address 00560 * @return 00561 * True for logic level high; 00562 */ 00563 virtual bool DoReadSignal(int bitaddr)=0; 00564 00565 /** 00566 * IO Hook, outputs 00567 * 00568 * This hook is invoked before writing a signal value. 00569 * You may reimplement this method to e.g. assemble a process image. 00570 * 00571 * @return 00572 * True on success, false on error 00573 * 00574 */ 00575 virtual bool DoWriteSignalsPre(void) {return true;}; 00576 00577 /** 00578 * IO Hook, output 00579 * 00580 * This hook is invoked after writing a signal value. 00581 * You may reimplement this method to e.g. assemble a process image. 00582 * 00583 * 00584 */ 00585 virtual void DoWriteSignalsPost(void) {}; 00586 00587 /** 00588 * Reimplement this function in a derived class for actual harware access 00589 * to set or clear an output signal. Hooks are executed appropriately. 00590 * If the device is configured for synchronous write, the background task 00591 * is used to write signals. Otherwise, signal values are written instantly. 00592 * 00593 * @param bitaddr 00594 * Abstract bit address 00595 * @param value 00596 * True for active/high/1/set; 00597 * false for passive/low/0/clr; 00598 * 00599 */ 00600 virtual void DoWriteSignal(int bitaddr, bool value)=0; 00601 00602 00603 /** 00604 * Loop hook. 00605 * This function is called once during each cycle of the 00606 * backgroud thread 00607 * 00608 */ 00609 virtual void DoLoopCallback(void) {}; 00610 00611 00612 /** Background: mutex for below shared variables*/ 00613 faudes_mutex_t mMutex; 00614 00615 /** True for synchronous output writes */ 00616 bool mSyncWrite; 00617 00618 private: 00619 00620 /** Background: thread handle (global) */ 00621 faudes_thread_t mThreadSynchro; 00622 00623 /** Cycle time of background thread in nsecs (shared) */ 00624 int mCycleTime; 00625 00626 /** Background: cycle counter (shared) */ 00627 int mCycleCount; 00628 00629 /** Background: cycle count (global only) */ 00630 int mRecentCycleCount; 00631 00632 /** Background: type def for edge detection */ 00633 typedef struct { 00634 bool current; //// current value (most recent reading) 00635 bool past; //// past value (reading before) 00636 bool posrel; //// positive edge is relevant for some input event 00637 bool negrel; //// negative edge is relevant for some input event 00638 bool pos; //// positive edge detected 00639 bool neg; //// negative edge detected 00640 bool lost; //// relevant edge has been lost 00641 } Edges; 00642 00643 /** Background: accumulated edges (shared) */ 00644 Edges* mpInputEdges; 00645 00646 /** Background: recently accumulated edges (global only) */ 00647 Edges* mpRecentInputEdges; 00648 00649 /** Background: some input event did occur (shared) */ 00650 bool mInputReady; 00651 00652 /** Background: type def output values */ 00653 typedef struct { 00654 bool current; //// current value (actual line level) 00655 bool next; //// next value (buffered line level, flush on sync write) 00656 bool edge; //// value will change 00657 bool lost; //// edgle will be lost 00658 bool rel; //// relevant to some output event 00659 } Levels; 00660 00661 /** Background: accumulated output values (shared) */ 00662 Levels* mpOutputLevels; 00663 00664 /** Background: terminate-flag for background task */ 00665 bool mCancelRequest; 00666 00667 /** clear all input states */ 00668 void ClrInputSignals(void); 00669 00670 /** clear all output values */ 00671 void ClrOutputSignals(void); 00672 00673 }; 00674 00675 // declare background thread 00676 void* SDeviceSynchro(void*); 00677 00678 } 00679 00680 00681 #endif 00682 libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |