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   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