API Reference
All symbols of autoparamDriver
are in the Autoparam
namespace. A
limited selection of symbols that are most needed when writing a driver based on
Autoparam::Driver
are put into the
Autoparam::Convenience
namespace which is meant to be imported with
a using
directive.
See also
The driver
-
class Driver : public asynPortDriver
An
asynPortDriver
that dynamically creates parameters referenced by records.Normally, an
asynPortDriver
instantiates a predefined set of parameters, each associated with a string that can subsequently be used to reference a parameter from records in the EPICS database.Autoparam::Driver
works differently. No parameters exist when theDriver
is constructed; instead, instances ofDeviceVariable
are created as EPICS database records are initialized. The string a record uses to refer to a parameter is split into a “function” and its “arguments” which, together, define a “parameter”. This is handled by theDeviceAddress
andDeviceVariable
classes, and needs to be implemented by the class subclassingDriver
.Drivers based on
Autoparam::Driver
do not need to override the read and write methods. Instead, they register read and write handlers for “functions” used by records.Autoparam::Driver
will then call these handlers when records are processed.To facilitate updating
I/O Intr
records (and those output records that are marked withasyn:READBACK
), two mechanisms are provided:When a parameter is written to (or read from), the value can optionally be propagated to
I/O Intr
records bound to the same parameter. SeeDriverOpts::setAutoInterrupts()
andResultBase::processInterrupts
.The driver can process
I/O Intr
records at any time (e.g. from a background thread or in response to hardware interrupts) by(scalars) setting the value using
Driver::setParam()
, then callingasynPortDriver::callParamCallbacks()
;(arrays) calling
Driver::doCallbacksArray()
.
To create a new driver based on
Autoparam::Driver
:Define a subclass of
DeviceAddress
.Define a subclass of
DeviceVariable
.Define a subclass of
Driver
.Implement the
parseDeviceAddress()
method to instantiate theDeviceAddress
subclass.Implement the
createDeviceVariable()
method to instantiate theDeviceVariable
subclass.Define static functions that will act as read and write handlers (see
Autoparam::Handlers
for signatures) and register them as handlers in the driver’s constructor (c.f.Driver::registerHandlers()
).
Define one or more iocshell commands to instatiate and configure the driver.
Apart from read and write functions, methods of
asynPortDriver
such asasynPortDriver::connect()
can be overriden as needed. To facilitate that,Driver::deviceVariableFromUser()
is provided to obtainDeviceVariable
from theasynUser
pointer thatasynPortDriver
methods are provided.Public Functions
-
explicit Driver(const char *portName, DriverOpts const ¶ms)
Constructs the
Driver
with the given options.- Parameters:
portName – The user-provided name of the port used to refer to this driver instance.
params – Options controlling the behavior of
Driver
.
Protected Functions
-
virtual DeviceAddress *parseDeviceAddress(std::string const &function, std::string const &arguments) = 0
Parse the given
function
andarguments
.DeviceAddress
is meant to be subclassed. As records are initialized,Driver
needs some information on the device variable referred to byfunction
andarguments
, thus it calls this method.May return NULL on error.
-
virtual DeviceVariable *createDeviceVariable(DeviceVariable *baseVar) = 0
Convert the given
DeviceVariable
into an instance of a subclass.DeviceVariable
is meant to be subclassed. As records are initialized,Driver
creates instances of theDeviceVariable
base class, then passes them to this method to convert them to whichever subclass the implementation decides to return.The
baseVar
pointer is intended to be passed to the constructor ofDeviceVariable
which will take ownership of it.May return NULL on error.
-
template<typename T>
void registerHandlers(std::string const &function, typename Handlers<T>::ReadHandler reader, typename Handlers<T>::WriteHandler writer, InterruptRegistrar intrRegistrar) Register handlers for the combination of
function
and typeT
.Note that the driver is implicitly locked when when handlers are called.
- Template Parameters:
T – A type corresponding to one of asyn interfaces/parameter types. See
Autoparam::AsynType
. It determines which EPICS device support provided by asyn (determined by record’s DTYP field) thefunction
can be used with.- Parameters:
function –
The name of the “function” (in the sense of “device
function”, see
DeviceVariable
).reader – Handler function that is called when an input record referencing
function
withDTYP
corresponding toT
is processed;writer – Handler function that is called when an output record referencing
function
withDTYP
corresponding toT
is processed;intrRegistrar – A function that is called when a record referencing
function
switches to or fromI/O Intr
.
-
template<typename T>
asynStatus doCallbacksArray(DeviceVariable const &var, Array<T> &value, asynStatus status = asynSuccess, int alarmStatus = epicsAlarmNone, int alarmSeverity = epicsSevNone) Propagate the array data to
I/O Intr
records bound tovar
.Unless this function is called from a read or write handler, the driver needs to be locked. See
asynPortDriver::lock()
.Status and alarms of the records are set according to the same principles as on completion of a write handler. See
Autoparam::ResultBase
.Note: strings are not arrays, even though
Autoparam::Octet
derives fromAutoparam::Array
. UsesetParam()
andcallParamCallbacks()
instead ofdoCallbacksArray()
.
-
template<typename T>
asynStatus setParam(DeviceVariable const &var, T value, asynStatus status = asynSuccess, int alarmStatus = epicsAlarmNone, int alarmSeverity = epicsSevNone) Set the value of the parameter represented by
var
.Unless this function is called from a read or write handler, the driver needs to be locked. See
asynPortDriver::lock()
.Status and alarms of the records are set according to the same principles as on completion of a write handler. See
Autoparam::ResultBase
.Unlike
doCallbacksArray()
, noI/O Intr
records are processed. UseasynPortDriver::callParamCallbacks()
after setting the value. This allows more than one parameter to have its value set before doing record processing.
-
asynStatus setParam(DeviceVariable const &var, epicsUInt32 value, epicsUInt32 mask, asynStatus status = asynSuccess, int alarmStatus = epicsAlarmNone, int alarmSeverity = epicsSevNone)
Set the value of the parameter represented by
var
.This is an overload for digital IO, where
mask
specifies which bits ofvalue
are of interest. While the default overload works withepicsUInt32
, it uses the mask value0xFFFFFFFF
.
-
std::vector<DeviceVariable*> getAllVariables() const
Obtain a list of all device variables.
This function is threadsafe, locking the driver is not necessary.
-
std::vector<DeviceVariable*> getInterruptVariables()
Obtain a list of device variables bound by
I/O Intr
andasyn:READBACK
records.The list of
DeviceVariable
pointers returned by this method is useful if you need to implement periodic polling for data and would like to know which data to poll. It is meant to be used together withdoCallbacksArray()
,setParam()
andasynPortDriver::callParamCallbacks()
.This function is threadsafe, locking the driver is not necessary.
-
DeviceVariable *deviceVariableFromUser(asynUser *pasynUser)
Obtain a
DeviceVariable
given anasynUser
.This facilitates overriding
asynPortDriver
methods if need be. Be aware, though, that theasynUser
structure is used in asyn to represent any number of different things and the one you have may not correspond to anyDeviceVariable
. The argument toasynPortDriver::connect()
is an example. Use of this method is subject to “know what you are doing” constraints.
-
class DriverOpts
Options controlling the behavior of
Driver
.Certain behaviors of
Driver
and the underlyingasynPortDriver
can be controlled throughDriverOpts
. The value passed to theDriver
’s constructor can be created and modified in place, like so:Driver(portName, DriverOpts().setBlocking(true) .setAutoInterrupts(false) .setPriority(epicsThreadPriorityLow));
Public Functions
-
inline DriverOpts &setBlocking(bool enable = true)
Declare whether read and write handlers can block.
If any read or write handler can block in any situation, the driver needs to declare this. What “blocking” means is explained in EPICS Application Developer’s Guide in chapter Device Support.
In short, if read and write handlers return “immediately”, the driver does not need to declare itself as blocking. On the other hand, if handlers are “slow” (e.g. because the device is network-connected), the driver must declare itself as blocking. This causes the EPICS device support layer to implement asynchronous processing, calling read and write handlers from a separate thread.
Default: non-blocking
-
inline DriverOpts &setAutoConnect(bool enable = true)
Enable/disable asyn autoconnect functionality.
Please refer to asyn documentation for more information. In short, if you do not override
asynPortDriver::connect()
orasynPortDriver::disconnect()
, enabling autoconnect simply means that the asyn port will always appear connected, which may be all you need.Important: if overriding
asynPortDriver::connect()
, you need to know what you are doing. Be aware that autoconnect tries to connect before your driver is completely initialized. This means that your code will not be called when autoconnect is enabled. If you need to overrideasynPortDriver::connect()
, you may be better off disabling the autoconnect option here and instead use theasynManager
andasynCommonSyncIO
interfaces to connect (and/or enable autoconnect) from your driver’s constructor, which is executed later when virtual functions have already been set up. See alsosetInitHook()
for a way to connect to the device even later, after all the records are initialized.Default: enabled
-
inline DriverOpts &setAutoDestruct(bool enable = true)
Instruct the driver to clean up on IOC exit.
If enabled, the
Driver
will register a hook that is run at IOC exit and deletes theDriver
, which ensures that the destructor is run. This is convenient because theDriver
can be allocated usingnew
from an iocshell command, then let be.Note: the exit hook will disable the asyn port before destroying the driver. The reason is that records can still be processed after the driver is destroyed. Disabling the port prevents the driver being called, though asyn may print warnings.
Default: disabled
-
inline DriverOpts &setAutoInterrupts(bool enable)
Enable/disable default
I/O Intr
behavior for write handlers.When enabled, successful writes will process
I/O Intr
records bound to the parameter written to, unless overriden byResultBase::processInterrupts
.Note that default write handlers (passed as
NULL
toDriver::registerHandlers()
) are not affected by this: the write handler will always process interrupts.Default: enabled
-
inline DriverOpts &setPriority(int prio)
Set the thread priority of read/write handlers in blocking mode.
If
setBlocking()
was enabled, read and write handlers run in a separate thread. This setting controls the priority of this thread.Default:
epicsThreadPriorityMedium
-
inline DriverOpts &setStacksize(int size)
Set the thread stack size of read/write handlers in blocking mode.
If
setBlocking()
was enabled, read and write handlers run in a separate thread. This setting controls the priority of this thread.Default:
epicsThreadStackMedium
-
inline DriverOpts &setInitHook(InitHook hook = NULL)
Set a function to run after IOC initialization is done.
If the driver needs to do something (like open communication to device) after all the records (and consequently,
DeviceVariable
) are constructed, registering a hook function here is the way to go.The hook is run after the IOC is built, but before any record processing occurs. Specifically, it is hooked to
initHookState::initHookAfterScanInit
Default:
NULL
-
inline DriverOpts &setBlocking(bool enable = true)
Device variables and addresses
-
class DeviceAddress
Represents parsed device address information.
The driver needs to subclass this and return it from the overridden
Autoparam::Driver::parseDeviceAddress()
. This class is intended for storing parsed function arguments, e.g. numeric addresses and offsets. It is used by theDriver
base class to identify which records refer to the same device variable.Unlike
DeviceVariable
, this class should not take any device resources, or, if unavoidable (e.g. because it needs to access the device for name resolution), must release resources when destroyed; because several records can refer to the same underlying variable, many instances ofDeviceAddress
can be created perDeviceVariable
, then destroyed even before the IOC is fully initialized.A
DeviceAddress
must be equality-comparable to other addresses. Two addresses shall compare equal when they refer to the same device variable.Public Functions
-
virtual bool operator==(DeviceAddress const &other) const = 0
Compare to another address. Must be overridden.
-
virtual bool operator==(DeviceAddress const &other) const = 0
-
class DeviceVariable
Represents a device variable and is a handle for asyn parameters.
This class is used as a handle referring to a device device variable, e.g. in read and write handlers or
Driver::setParam()
.DeviceVariable
is meant to be subclassed for use by the subclassed driver. This greatly increases its utility as it can hold any information related to a device variable that the subclassed driver might require. Instances are created byDriver::createDeviceVariable()
.DeviceVariable
instances are created only once per device variable, and are shared between records referring to the same device variable. They are destroyed when the driver is destroyed.Public Functions
-
explicit DeviceVariable(DeviceVariable *other)
Construct
DeviceVariable
from another; the other one is invalidated.Being the only public constructor, this is the only way the driver subclassing
Autoparam::Driver
can construct aDeviceVariable
. The usage pattern is the following:The driver overrides
Autoparam::Driver::parseDeviceAddress()
. That method interprets the providedfunction
andarguments
, returning an instance ofDeviceAddress
.The
Autoparam::Driver
base class creates an instance ofDeviceVariable
which contains the providedDeviceAddress
instance and some internal data.The driver overrides
Autoparam::Driver::createDeviceVariable()
. In that method, it uses the provided instance of theDeviceVariable
base class and the previously createdDeviceAddress
(now available asDeviceVariable::address()
) to instantiate a subclass ofDeviceVariable
that contains everything that the driver needs to access the underlying device variable.
-
virtual ~DeviceVariable()
-
inline std::string const &function() const
Returns the “function” given in the record.
-
inline std::string const &asString() const
Returns the “function+arguments” string representation.
The resulting string is used for display only, e.g. in error messages.
-
inline int asynIndex() const
Returns the index of the underlying asyn parameter.
This allows advanced users to call methods of
asynPortDriver
if the need arises.
-
inline asynParamType asynType() const
Returns the type of the underlying asyn parameter.
Apart from complementing
asynIndex()
, it allows the driver (or the constructor of theDeviceVariable
subclass) to act differently based on the type. While the subclassed driver can also determine this information fromfunction()
(it knows which type each function handler is registered for), usingasynType()
is faster and more convenient.
-
inline DeviceAddress const &address() const
Returns the pre-parsed representation of the device address.
This is the same instance of
DeviceAddress
that has been previously created byDriver::parseDeviceAddress()
.
-
explicit DeviceVariable(DeviceVariable *other)
References to array and string data
-
template<typename T>
class Array A non-owning reference to a data buffer.
Array
is used to pass around a reference to a contiguous buffer of typeT
. For example, read and write handlers called byDriver
receive anArray
as an argument, pointing to the data of a waveform record.An
Array
contains a data pointer, the current size of the buffer and the maximum size of the buffer. It also provides convenience function to copy data to and from other buffers.Public Functions
-
inline Array(T *value, size_t maxSize)
Construct an
Array
reference tovalue
, setting its size tomaxSize
.
-
inline size_t size() const
-
inline size_t maxSize() const
-
inline void setSize(size_t size)
-
inline void fillFrom(T const *data, size_t size)
Set the size and copy data from the provided buffer.
-
inline Array(T *value, size_t maxSize)
-
class Octet : public Autoparam::Array<char>
A specialization of
Array
to deal with string data.This class is called
Octet
instead ofString
to match the asyn nomenclature. It is anArray
ofchar
and provides convenience function to ensure null-termination required by C strings.Note: Octets sometimes behave like arrays (i.e. in read and write handlers) and sometimes like scalars (i.e. when handling interrupts; see
Autoparam::Driver::doCallbacksArray()
andAutoparam::Driver::setParam()
).Public Functions
-
inline Octet(char *value, size_t maxSize)
Construct an Octet reference to
value
, setting it’s size tomaxSize
.
-
inline void terminate()
Terminate the string at its current size.
-
inline void fillFrom(char const *data, size_t size)
Set the size, copy data from the provided buffer and null-terminate.
-
inline void fillFrom(std::string const &string)
Set the size, copy data from the provided string and null-terminate.
-
inline size_t writeTo(char *data, size_t maxSize) const
Copy data to the provided buffer, up to
maxSize
, with null-termination.
-
inline Octet(char *value, size_t maxSize)
Returning results from handlers
-
struct ProcessInterrupts
A tri-state determining whether
I/O Intr
records should be processed.Used in
ResultBase
to determine whether interrupts should be processed. When left alone, it specifies the default behavior. When abool
is assigned to it, it overrides the default.See also
-
struct ResultBase
The result returned from a read or write handler.
ResultBase
tells theDriver
calling a read or write handler whether the call was successful and how to proceed. Based on this, theDriver
will set the appropriate alarm status on the EPICS record that caused the call.The default-constructed result represents a successful handling; thus, in the happy case, the handler need not change anything. If something went wrong, the handler as a fair bit of freedom in deciding what will happen to the record that caused processing.
Subclassed by Autoparam::ArrayResult, Autoparam::Result< T >, Autoparam::Result< Octet >, Autoparam::WriteResult
Public Members
-
asynStatus status
The overall status of read/write handling.
If
status
is set toasynSuccess
(the default) upon returning from a handler, interrupts may be processed (seeResultBase::processInterrupts
).If
status
is set to anything else exceptasynSuccess
, interrupts will not be processed.For read handlers, the value read will be passed to the record regardless of
status
.Unless
ResultBase::alarmStatus
andResultBase::alarmSeverity
are also set, the record’s alarm and severity are determined according to the value ofstatus
and the type of record. For example, onasynError
, an input record will be put intoREAD_ALARM
and an output record will be put intoWRITE_ALARM
.
-
epicsAlarmCondition alarmStatus
Overrides the record’s alarm status.
-
epicsAlarmSeverity alarmSeverity
Overrides the record’s severity status.
-
ProcessInterrupts processInterrupts
Determines whether interrupts should be processed on success.
When a read or write handler finishes with
asynSuccess
, it may be appropriate to processI/O Intr
records that are bound to the same parameter. The decision can be done globally viaAutoparam::DriverOpts::setAutoInterrupts
, but can always be overriden by a handler by settingResultBase::processInterrupts
.The default setting follows the default behavior of
asynPortDriver
:do not process interrupts upon returning from a read handler;
process interrupts upon returning from a write handle, propagating the value just written.
To override the defaults, simply set
processInterrupts
totrue
orfalse
.
-
asynStatus status
-
struct WriteResult : public Autoparam::ResultBase
Result returned from a write handler, status only.
-
struct ArrayResult : public Autoparam::ResultBase
Result returned from an array read handler, status only.
-
template<typename T>
struct Result : public Autoparam::ResultBase Result returned from a scalar read handler, status and value.
-
template<>
struct Result<Octet> : public Autoparam::ResultBase Result returned from
Octet
read handler, status only.Octets behave like arrays in this respect.
Signatures of handler functions
-
typedef asynStatus (*Autoparam::InterruptRegistrar)(DeviceVariable &var, bool cancel)
Called when a device variable switches to or from
I/O Intr
scanning.The registrar function is called both when a variable switches to
I/O Intr
and when it switches away; thecancel
argument reflects that, beingfalse
in the former case andtrue
in the latter. The purpose of the registrar function is to set up or tear down a subscription for events (or interrupts) relevant to the givenvar
.To be more precise: a device variable can be referred to by several EPICS records, any number of which can be set to
I/O Intr
scanning. This function is called withcancel = false
when the number ofI/O Intr
records increases to 1, and withcancel = true
when the number decreases to 0.
-
template<typename T, bool array = IsArray<T>::value>
struct Handlers Handler signatures for type
T
.Specializations of this struct describe the signatures of the read handler, write handler, and interrupt registrar for the given type
T
. Functions with these signatures are passed as arguments to Driver::registerHandlers().This struct is defined separately for scalars, arrays, strings (
Octet
s) and digital IO. See the specializations for concrete signatures.
-
template<typename T>
struct Handlers<T, false> Signatures of handlers for scalar types
T
.Public Types
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, T value)
Writes
value
to the device.
-
typedef ReadResult (*ReadHandler)(DeviceVariable &var)
Reads a value from the device, returning it inside
ReadResult
.
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, T value)
-
template<typename T>
struct Handlers<Array<T>, true> Signatures of handlers for array types
Array<T>
.Public Types
-
typedef ArrayResult ReadResult
Result type for array reads.
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, Array<T> const &value)
Writes
value
to the device.
-
typedef ReadResult (*ReadHandler)(DeviceVariable &var, Array<T> &value)
Reads an array from the device, storing data in
value
.Unlike a scalar read handler, the value is not returned as a
ReadResult
, but written directly to the given buffer, up to the amount returned byvalue.maxSize()
.
-
typedef ArrayResult ReadResult
-
template<>
struct Handlers<epicsUInt32, false> Signatures of handlers for
epicsUInt32
.epicsUInt32
(a.k.a.asynParamUInt32Digital
) is used for digital (i.e. bit-level) IO. As such, its handlers are passed an additional parametermask
. This mask tells the handler which bits the caller is interested in. It’s up to the handler to properly mask the value.Note: You shouldn’t use
epicsUInt32
support for “normal” integer IO, even for unsigned integers. It is meant only for digital IO, which is why the names of the asyn interface and device support explicitly say “Digital”. UseepicsInt32
for normal unsigned integers. If you need to handle unsigned integers which are larger than 31 bits, useepicsInt64
.Public Types
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, epicsUInt32 value, epicsUInt32 mask)
Writes
value
to the device, honoring the givenmask
.
-
typedef ReadResult (*ReadHandler)(DeviceVariable &var, epicsUInt32 mask)
Reads a value from the device, honoring
mask
, returning it insideReadResult
.
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, epicsUInt32 value, epicsUInt32 mask)
-
template<>
struct Handlers<Octet, false> Signatures of handlers for
Octet
.For the purpose of read and write handlers,
Octet
behaves as an array.Public Types
-
typedef Result<Octet> ReadResult
Result type for
Octet
reads (essentiallyArrayResult
).
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, Octet const &value)
Writes
value
to the device.
-
typedef ReadResult (*ReadHandler)(DeviceVariable &var, Octet &value)
Reads a string from the device, storing data in
value
.
-
typedef Result<Octet> ReadResult
Miscellania
-
char const *Autoparam::getAsynTypeName(asynParamType type)
Return string representation of the given asyn parameter type.
-
template<typename T>
struct AsynType Maps type
T
to the correspondingasynParamType
value.This mapping allows using EPICS types everywhere as template arguments and types of function arguments. It is defined as follows:
epicsInt32
→asynParamInt32
epicsInt64
→asynParamInt64
epicsFloat64
→asynParamFloat64
epicsUint32
→asynParamUint32Digital
Octet
→asynParamOctet
Array<epicsInt8>
→asynParamInt8Array
Array<epicsInt16>
→asynParamInt16Array
Array<epicsInt32>
→asynParamInt32Array
Array<epicsInt64>
→asynParamInt64Array
Array<epicsFloat32>
→asynParamFloat32Array
Array<epicsFloat64>
→asynParamFloat64Array
Public Static Attributes
-
static const asynParamType value
-
namespace Convenience
Symbols that are often needed when implementing drivers.
This namespace is meant to be used as
This makes the symbols declared herein easily accessible. Apart from the typdefs shown below, this namespace exposes also:using namespace Autoparam::Convenience;
Typedefs
-
typedef Autoparam::WriteResult WriteResult
-
typedef Autoparam::ArrayResult ArrayReadResult