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
asynPortDriverthat dynamically creates parameters referenced by records.Normally, an
asynPortDriverinstantiates 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::Driverworks differently. No parameters exist when theDriveris constructed; instead, instances ofDeviceVariableare 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 theDeviceAddressandDeviceVariableclasses, and needs to be implemented by the class subclassingDriver.Drivers based on
Autoparam::Driverdo not need to override the read and write methods. Instead, they register read and write handlers for “functions” used by records.Autoparam::Driverwill then call these handlers when records are processed.To facilitate updating
I/O Intrrecords (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 Intrrecords bound to the same parameter. SeeDriverOpts::setAutoInterrupts()andResultBase::processInterrupts.The driver can process
I/O Intrrecords 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 theDeviceAddresssubclass.Implement the
createDeviceVariable()method to instantiate theDeviceVariablesubclass.Define static functions that will act as read and write handlers (see
Autoparam::Handlersfor 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
asynPortDriversuch asasynPortDriver::connect()can be overriden as needed. To facilitate that,Driver::deviceVariableFromUser()is provided to obtainDeviceVariablefrom theasynUserpointer thatasynPortDrivermethods are provided.Public Functions
-
explicit Driver(const char *portName, DriverOpts const ¶ms)
Constructs the
Driverwith 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
functionandarguments.DeviceAddressis meant to be subclassed. As records are initialized,Driverneeds some information on the device variable referred to byfunctionandarguments, thus it calls this method.May return NULL on error.
-
virtual DeviceVariable *createDeviceVariable(DeviceVariable *baseVar) = 0
Convert the given
DeviceVariableinto an instance of a subclass.DeviceVariableis meant to be subclassed. As records are initialized,Drivercreates instances of theDeviceVariablebase class, then passes them to this method to convert them to whichever subclass the implementation decides to return.The
baseVarpointer is intended to be passed to the constructor ofDeviceVariablewhich 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
functionand 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) thefunctioncan 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
functionwithDTYPcorresponding toTis processed;writer – Handler function that is called when an output record referencing
functionwithDTYPcorresponding toTis processed;intrRegistrar – A function that is called when a record referencing
functionswitches 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 Intrrecords 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::Octetderives 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 Intrrecords 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
maskspecifies which bits ofvalueare 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 Intrandasyn:READBACKrecords.The list of
DeviceVariablepointers 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
DeviceVariablegiven anasynUser.This facilitates overriding
asynPortDrivermethods if need be. Be aware, though, that theasynUserstructure 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
Driverand the underlyingasynPortDrivercan 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 theasynManagerandasynCommonSyncIOinterfaces 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
Driverwill register a hook that is run at IOC exit and deletes theDriver, which ensures that the destructor is run. This is convenient because theDrivercan be allocated usingnewfrom 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 Intrbehavior for write handlers.When enabled, successful writes will process
I/O Intrrecords bound to the parameter written to, unless overriden byResultBase::processInterrupts.Note that default write handlers (passed as
NULLtoDriver::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::initHookAfterScanInitDefault:
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 theDriverbase 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 ofDeviceAddresscan be created perDeviceVariable, then destroyed even before the IOC is fully initialized.A
DeviceAddressmust 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().DeviceVariableis 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().DeviceVariableinstances 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
DeviceVariablefrom another; the other one is invalidated.Being the only public constructor, this is the only way the driver subclassing
Autoparam::Drivercan construct aDeviceVariable. The usage pattern is the following:The driver overrides
Autoparam::Driver::parseDeviceAddress(). That method interprets the providedfunctionandarguments, returning an instance ofDeviceAddress.The
Autoparam::Driverbase class creates an instance ofDeviceVariablewhich contains the providedDeviceAddressinstance and some internal data.The driver overrides
Autoparam::Driver::createDeviceVariable(). In that method, it uses the provided instance of theDeviceVariablebase class and the previously createdDeviceAddress(now available asDeviceVariable::address()) to instantiate a subclass ofDeviceVariablethat 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
asynPortDriverif 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 theDeviceVariablesubclass) 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
DeviceAddressthat 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.
Arrayis used to pass around a reference to a contiguous buffer of typeT. For example, read and write handlers called byDriverreceive anArrayas an argument, pointing to the data of a waveform record.An
Arraycontains 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
Arrayreference 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
Arrayto deal with string data.This class is called
Octetinstead ofStringto match the asyn nomenclature. It is anArrayofcharand 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 Intrrecords should be processed.Used in
ResultBaseto determine whether interrupts should be processed. When left alone, it specifies the default behavior. When aboolis assigned to it, it overrides the default.See also
-
struct ResultBase
The result returned from a read or write handler.
ResultBasetells theDrivercalling a read or write handler whether the call was successful and how to proceed. Based on this, theDriverwill 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
statusis set toasynSuccess(the default) upon returning from a handler, interrupts may be processed (seeResultBase::processInterrupts).If
statusis 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::alarmStatusandResultBase::alarmSeverityare also set, the record’s alarm and severity are determined according to the value ofstatusand the type of record. For example, onasynError, an input record will be put intoREAD_ALARMand 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 Intrrecords 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
processInterruptstotrueorfalse.
-
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
Octetread 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 Intrscanning.The registrar function is called both when a variable switches to
I/O Intrand when it switches away; thecancelargument reflects that, beingfalsein the former case andtruein 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 Intrscanning. This function is called withcancel = falsewhen the number ofI/O Intrrecords increases to 1, and withcancel = truewhen 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 (
Octets) 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
valueto 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
valueto 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
epicsUInt32support 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”. UseepicsInt32for 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
valueto 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,
Octetbehaves as an array.Public Types
-
typedef Result<Octet> ReadResult
Result type for
Octetreads (essentiallyArrayResult).
-
typedef WriteResult (*WriteHandler)(DeviceVariable &var, Octet const &value)
Writes
valueto 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
Tto the correspondingasynParamTypevalue.This mapping allows using EPICS types everywhere as template arguments and types of function arguments. It is defined as follows:
epicsInt32→asynParamInt32epicsInt64→asynParamInt64epicsFloat64→asynParamFloat64epicsUint32→asynParamUint32DigitalOctet→asynParamOctetArray<epicsInt8>→asynParamInt8ArrayArray<epicsInt16>→asynParamInt16ArrayArray<epicsInt32>→asynParamInt32ArrayArray<epicsInt64>→asynParamInt64ArrayArray<epicsFloat32>→asynParamFloat32ArrayArray<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