About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

iop_sdevice.h

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

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen