/* * PulserPVs.hh * * Class to interface the PVs defined in the SNL code with the * C++ code used to implement the state sequence. The PVs are * expected to be defined in the SNL code in terms of short, * unsigned and double arrays, and them the structure with pointers * to this arrays is passed to this class. A member of pvStruct is * assigned to this structure, and then is used access the PVs defined * in SNL. This allows not do any CA operations and use facilities * of SNL to deal with CA. Since the same array is going to be accessed * from multiple instances of state sequences with different SSID, * mutexes are implemented to avoid conflicts between different threads * that these state sequences are running. * * Created on: Aug 19, 2015 * Author: Hovanes Egiyan */ #ifndef __PULSERPVS_HH__ #define __PULSERPVS_HH__ #include "seqCom.h" #include #include #include #include #include #include #include #include #include #include #include "MtxLock.hh" #include "PulserMap.h" class PulserPVs { public: // An auxiliary class to interface with the structure with pointers to the PV arrays. // It inherits from pvStructure so that the data layout is the same as the one used in // the SNL code using pvStructure C-structure. class pvStruct : public pvStructure { public: pvStruct() {return;} pvStruct( unsigned offs, unsigned n, unsigned sf, unsigned uf, unsigned df, short* s, unsigned* u, double* d ) { offset=offs; nElm=n; shortFlag=sf; unsignedFlag=uf; doubleFlag=df; shortPtr=s; unsignedPtr=u, doublePtr=d;} pvStruct( const pvStruct& pv ) { offset=pv.offset; nElm=pv.nElm; shortFlag=pv.shortFlag; unsignedFlag=pv.unsignedFlag; doubleFlag=pv.doubleFlag; shortPtr=pv.shortPtr; unsignedPtr=pv.unsignedPtr; doublePtr=pv.doublePtr;} pvStruct& operator=( const pvStruct& pv ) { offset=pv.offset; nElm=pv.nElm; shortFlag=pv.shortFlag; unsignedFlag=pv.unsignedFlag; doubleFlag=pv.doubleFlag; shortPtr=pv.shortPtr;unsignedPtr=pv.unsignedPtr;doublePtr=pv.doublePtr; return *this; } inline unsigned getNElm() {return nElm;} inline unsigned getOffset() {return offset;} inline unsigned getShortFlag() {return shortFlag;} inline unsigned getUnsignedFlag() {return unsignedFlag;} inline unsigned getDoubleFlag() {return doubleFlag;} inline short* getShortPtr() {return shortPtr;} inline unsigned* getUnsignedPtr() {return unsignedPtr;} inline double* getDoublePtr() {return doublePtr;} inline unsigned setOffset(unsigned offs ) { return (offset=offs);} inline unsigned setNElm( unsigned n ) { return (nElm=n);} inline unsigned setShortFlag(unsigned f) {return (shortFlag=f);} inline unsigned setUnsignedFlag(unsigned f) {return (unsignedFlag=f);} inline unsigned setDoubleFlag(unsigned f) {return (doubleFlag=f);} inline short* setShortPtr( short* ptr ) {return (shortPtr=ptr);} inline unsigned* setUnsignedPtr( unsigned* ptr ) {return (unsignedPtr=ptr);} inline double* setDoublePtr( double* ptr) {return (doublePtr=ptr);} }; protected: SS_ID ppSSid; // SNL state sequence Id pvStruct ppArrays; // Arrays with info about SNL PVs unsigned ppCurrentIndex; // Current indexes for PVs std::map ppCurrentTypeIndex; // Current index for arrays of type given by the string key std::map ppTypeIndex; // Index in the array for a given string key std::map ppIndex; // Index for a PV with a given string key std::map ppName; // PV name for a PV with a given string key std::map ppType; // PV var type for a PV with a given string key std::map ppInputFlag; // Flag showing if this is an input PV pthread_mutex_t ppMutex; // Mutex for an object pthread_mutexattr_t ppMtxAttr; // Mutex attributes for an object static unsigned ppMaxConnectChecks; // Max tries assign/connect checks static unsigned ppMaxReadbackChecks; // Max tries for readback during readback checks static unsigned ppSleepTime; // Sleep time during readback checks static double ppReadbackTolerance; // Tolerance for readback during readback checks //! Initialize the mutex for the object void initMutex(); //! Destroy the mutex for the object void closeMutex(); public: // Default constructor PulserPVs() : ppSSid(), ppArrays(), ppCurrentIndex(0), ppCurrentTypeIndex(), ppTypeIndex(), ppIndex(), ppName(), ppType(), ppInputFlag() {initMutex();ppCurrentTypeIndex["short"]=ppCurrentTypeIndex["unsigned"]=ppCurrentTypeIndex["double"]=0;} // Main constructor PulserPVs( SS_ID ssID, pvStruct& pvs ) : ppSSid(ssID), ppArrays(pvs), ppCurrentIndex(0), ppCurrentTypeIndex(), ppTypeIndex(), ppIndex(), ppName(), ppType(), ppInputFlag() {initMutex();ppCurrentTypeIndex["short"]=ppCurrentTypeIndex["unsigned"]=ppCurrentTypeIndex["double"]=0;} // Copy constructor PulserPVs( const PulserPVs& pv ) : ppSSid(pv.ppSSid),ppArrays(pv.ppArrays), ppCurrentIndex(pv.ppCurrentIndex), ppCurrentTypeIndex(pv.ppCurrentTypeIndex), ppTypeIndex(pv.ppTypeIndex), ppIndex(pv.ppIndex), ppName(pv.ppName), ppType(pv.ppType), ppInputFlag(pv.ppInputFlag) {initMutex();} // Assignment operator PulserPVs& operator=( const PulserPVs& pv ) { ppSSid = pv.ppSSid; ppArrays = pv.ppArrays; ppCurrentIndex=pv.ppCurrentIndex; ppCurrentTypeIndex=pv.ppCurrentTypeIndex; ppTypeIndex=pv.ppTypeIndex; ppIndex=pv.ppIndex; ppName=pv.ppName; ppType=pv.ppType; ppInputFlag=pv.ppInputFlag; return *this; } virtual ~PulserPVs() {closeMutex();} virtual inline SS_ID getSSID() {return ppSSid;} virtual inline pvStruct& getArrays() { return ppArrays; } virtual inline unsigned getCurrentIndex() { return ppCurrentIndex; } // Get the number of trials for readback checks inline static unsigned getMaxReadbackChecks() {return ppMaxReadbackChecks; } // Set the sleep time between readback checks inline static unsigned getSleepTime() {return ppSleepTime; } // Set the readback check tolerance inline static double getReadbackTolerance() {return ppReadbackTolerance;} virtual inline SS_ID setSSID(SS_ID id) {return (ppSSid=id);} // Check if the PV with label pvLabel is and input PV // virtual bool pvIsInput( std::string pvLabel ); // Check if the input PVs have changed virtual bool inputsChanged(); // Set the number of trials for readback checks inline static unsigned setMaxReadbackChecks(unsigned n) {return (ppMaxReadbackChecks=n); } // Set the sleep time between readback checks inline static unsigned setSleepTime(unsigned n) {return (ppSleepTime=n); } // Set the readback check tolerance inline static double setReadbackTolerance(double tolr) {return (ppReadbackTolerance=tolr);} // Return the PV array pointer for type T (T can be short, unsigned and double) template T* getPtr4Type(T fakePar); // Get the values of the PVs with a give label "label" defined for different parameter types. // The type is picked based on fakePar type. template T getPV( const std::string label, enum compType syncType, T fakePar ); // Set the values of the PVs template T setValue( std::string pvKey, const T value, enum compType syncType = SYNC ); // Method that waits until the setpoint for short and readback are the same within tolerance template bool gotReadback( const T setValue, const std::string readChannel, double tolerance = ppReadbackTolerance ); // Add a PV of type pvType with label (key) pvKey that will be assigned to PV called pvName virtual void addPV( const std::string pvType, const std::string pvKey, const std::string pvName ); // Connect all the PVs defined so far virtual void assignPVs(); }; #endif /* __PULSERPVS_HH__ */