179 lines
6.5 KiB
C
179 lines
6.5 KiB
C
#ifndef epicsPV_h
|
|
#define epicsPV_h
|
|
|
|
#include <cadef.h>
|
|
#include <caerr.h>
|
|
#include <alarm.h>
|
|
|
|
/* How epicsPVs work:
|
|
* A PV is a container for a remote named value provided via a so
|
|
* called EPICS "channel". It is "linked" to the channel in PVcreate()
|
|
* or later with PVlink().
|
|
* Because the original value is remote, the PV can only contain
|
|
* a copy of the value.
|
|
* With the caget() call, one or more PVs are updated from the remote value.
|
|
* After that, the updated value can be read as long, double or string.
|
|
* With the caput() call, the remote value is updated from the PV.
|
|
*/
|
|
|
|
#ifndef PV_DEFAULT_GET_TIMEOUT_SEC
|
|
#define PV_DEFAULT_GET_TIMEOUT_SEC 2.0
|
|
#endif
|
|
|
|
#ifndef PV_DEFAULT_PUT_TIMEOUT_SEC
|
|
#define PV_DEFAULT_PUT_TIMEOUT_SEC 10.0
|
|
#endif
|
|
|
|
typedef struct epicsPV_s* epicsPV;
|
|
|
|
typedef void (*PVconnectionCallback) (epicsPV pv, int connectionUp, void* userarg);
|
|
|
|
/* Channel Access datatypes (plus caTypeNative as default value)
|
|
* depending on the datatype of a PV, exporting the value
|
|
* to double, long or const char* may give different results
|
|
*/
|
|
typedef enum {
|
|
caTypeString,
|
|
caTypeShort,
|
|
caTypeFloat,
|
|
caTypeEnum,
|
|
caTypeChar,
|
|
caTypeLong,
|
|
caTypeDouble,
|
|
caTypeNoAccess,
|
|
caTypeNative
|
|
} caDatatype;
|
|
|
|
/* You don't need to access anything in epicsPV_priv.h directly
|
|
*/
|
|
#include "epicsPV_priv.h"
|
|
|
|
/* create PV and optionally link it to an EPICS channel
|
|
* normally, you call createPV with channelName but without
|
|
* preferredDatatype to use the native datatype of the channel
|
|
* you may read back datatype after connection
|
|
* if channelName is NULL you must call PVlink later
|
|
* a callback can be installed to track connection state changes
|
|
* connectionUp is 1 when the PV connected, 0 when it disconnected
|
|
* userarg is an arbitrary pointer that will be provided with the callback
|
|
*/
|
|
#define PVcreate(channelName) PVcreateWithTypeAndCallback(channelName, caTypeNative, NULL, NULL)
|
|
#define PVcreateWithType(channelName, type) PVcreateWithTypeAndCallback(channelName, type, NULL, NULL)
|
|
#define PVcreateWithCallback(channelName, cb, userarg) PVcreateWithTypeAndCallback(name, caTypeNative, cb, userarg)
|
|
epicsPV PVcreateWithTypeAndCallback(const char* channelName, caDatatype preferredDatatype,
|
|
PVconnectionCallback cb, void* userarg);
|
|
|
|
/* destroy PV and free all resources
|
|
*/
|
|
void PVdestroy(epicsPV pv);
|
|
|
|
/* explititely (re-)link PV to a (different) EPICS channel
|
|
* an unlink PV from a channel
|
|
* it is normally done implicitely by PVcreate and PVdestroy
|
|
* note: linking does not yet send a search request to the
|
|
* network until PVwaitForConnect is called (probably implicitely by caget, caput, camonitor)
|
|
*/
|
|
#define linkPV(pv, channelName)linkPVwithType(pv, channelName, caTypeNative)
|
|
int PVlinkWithType(epicsPV pv, const char* channelName, caDatatype preferredDatatype);
|
|
void PVunlink(epicsPV pv);
|
|
|
|
/* wait until one or all PVs are connected
|
|
* timeoutSec = 0.0 just sends connect requests but does not wait
|
|
* timeoutSec < 0.0 means wait forever
|
|
* returns remaining seconds
|
|
* calling this function is optional because it will be called
|
|
* implicitely before the first get or put on an unconnected PV
|
|
* using the get or put timeout
|
|
*/
|
|
double PVwaitForConnect(epicsPV pv, double timeoutSec);
|
|
#define PVwaitForConnectAll(timeoutSec) PVwaitForConnect(NULL, timeoutSec)
|
|
|
|
/* return channel name (what you provided to PVlink or PVcreate)
|
|
*/
|
|
#define PVname(pv) ((pv)->channel?ca_name((pv)->channel):"")
|
|
|
|
/* return error status of PV
|
|
* see $(EPICS_BASE)/include/caerr.h for error codes
|
|
*/
|
|
#define PVerrorStatus(pv) ((pv)->status)
|
|
#define PVerrorStatusString(pv) (ca_message((pv)->status))
|
|
|
|
/* return connection state
|
|
* see $(EPICS_BASE)/include/cadef.h for valid values
|
|
*/
|
|
#define PVconnectionState(pv) ((pv)->channel?ca_state((pv)->channel):cs_never_conn)
|
|
#define PVconnectionStateString(pv) PVconnectionStateStrings[PVconnectionState(pv)]
|
|
|
|
/* The following functions return information which is available
|
|
* as soon as the PV is connected.
|
|
*/
|
|
|
|
/* return currently used data type
|
|
*/
|
|
#define PVdatatype(pv) ((pv)->usedDatatype)
|
|
#define PVdatatypeString(pv) PVdataTypeStrings[PVdatatype(pv)]
|
|
|
|
/* return number of elements for array data
|
|
*/
|
|
#define PVnumberOfElements(pv) ((pv)->channel?ca_element_count((pv)->channel):0)
|
|
|
|
/* return units and precision (.EGU and .PREC fields)
|
|
* if PV does not have units or precision it returns "" and/or 0
|
|
*/
|
|
#define PVunits(pv) ((pv)->units)
|
|
#define PVprecision(pv) ((pv)->precision)
|
|
|
|
/* return access rights (might change at run-time)
|
|
*/
|
|
#define PVhasReadAccess(pv) ((pv)->channel?ca_read_access((pv)->channel):0)
|
|
#define PVhasWriteAccess(pv) ((pv)->channel?ca_write_access((pv)->channel):0)
|
|
|
|
/* get value from remote server
|
|
* do caget with as many PVs as possible in parallel to increase performance
|
|
*/
|
|
#define caget(pvs...) cagetList(PV_DEFAULT_GET_TIMEOUT_SEC, pvs, NULL)
|
|
#define cagetWithTimeout(timeoutSec, pvs...) cagetList(timeoutSec, pvs, NULL)
|
|
|
|
/* The following functions return information which is available
|
|
* after a successful get() or a monitor.
|
|
*/
|
|
|
|
/* return alarm severity and status (.SEVR and .STAT fields)
|
|
* see $(EPICS_BASE)/include/alarm.h for valid values
|
|
* not conencted PV returns epicsSevInvalid/epicsAlarmNone
|
|
*/
|
|
#define PValarmSeverity(pv) ((pv)->STRING?(pv)->STRING->severity:epicsSevInvalid)
|
|
#define PValarmSeverityString(pv) epicsAlarmSeverityStrings[PValarmSeverity(pv)]
|
|
|
|
#define PValarmStatus(pv) ((pv)->STRING?(pv)->STRING->status:epicsAlarmUDF)
|
|
#define PValarmStatusString(pv) epicsAlarmConditionStrings[PValarmStatus(pv)]
|
|
|
|
/* return time of record processing (.TIME field) as (epicsTimeStamp*)
|
|
* see $(EPICS_BASE)/include/epicsTime.h for epicsTimeStamp
|
|
*/
|
|
extern epicsTimeStamp PVinvalidTimestamp;
|
|
#define PVtimestamp(pv) &((pv)->STRING?(pv)->STRING->stamp:PVinvalidTimestamp)
|
|
|
|
/* return value of pv as long double or string
|
|
* for arrays use PVto*Element to access each element
|
|
*/
|
|
long PVtoLongElement(epicsPV pv, unsigned long index);
|
|
#define PVtoLong(pv) PVtoLongElement(pv,0)
|
|
double PVtoDoubleElement(epicsPV pv, unsigned long index);
|
|
#define PVtoDouble(pv) PVtoDoubleElement(pv,0)
|
|
|
|
/* flags for toString() */
|
|
const char* PVtoStringElement(epicsPV pv, int flags, unsigned long index);
|
|
#define PVtoStringWithUnits(pv) PVtoStringElement(pv,PV_WITHUNITS,0)
|
|
#define PVtoString(pv) PVtoStringElement(pv,0,0)
|
|
|
|
#define caputDouble(pv1, value1...) caputDoubleList(0.0, pv1, value1)
|
|
#define caputWaitDouble(timeoutSec, pv1, val1, ...) caputDoubleList(timeoutSec, pv1, value1)
|
|
int caputDoubleList(double timeoutSec, int flags, epicsPV pv1, double val1, ...);
|
|
|
|
#define caputLong(pv1, val1, ...)
|
|
#define caputString(pv1, val1, ...)
|
|
|
|
|
|
#endif
|