git-svn-id: https://subversion.xor.aps.anl.gov/synApps/areaDetector/trunk@7579 dc6c5ff5-0b8b-c028-a01f-ffb33f00fc8b
1217 lines
53 KiB
HTML
Executable File
1217 lines
53 KiB
HTML
Executable File
<HTML>
|
|
<HEAD>
|
|
<TITLE>areaDetector: EPICS Area Detector Support</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
|
|
<CENTER>
|
|
<H1>areaDetector: EPICS Area Detector Support</H1>
|
|
|
|
<H2> R1-2</H2>
|
|
<H2> May 16, 2008</H2>
|
|
<H2> Mark Rivers</H2>
|
|
<H2> University of Chicago</H2>
|
|
</CENTER>
|
|
|
|
<P> </P>
|
|
|
|
<CENTER><H2>Contents</H2></CENTER>
|
|
<UL>
|
|
<LI><A href="#Overview">
|
|
Overview</A>
|
|
<LI><A href="#Architecture">
|
|
Architecture</A>
|
|
<LI>Implementation details
|
|
<UL>
|
|
<LI><A href="#asynPortDriver">
|
|
asynPortDriver</A>
|
|
<LI><A href="#NDArray">
|
|
NDArray</A>
|
|
<LI><A href="#NDArrayPool">
|
|
NDArrayPool</A>
|
|
<LI><A href="#asynNDArrayDriver">
|
|
asynNDArrayDriver</A>
|
|
<LI><A href="#ADDriver">
|
|
ADDriver</A>
|
|
<LI><A href="#ADStdDriverParams">
|
|
ADStdDriverParams</A>
|
|
</UL>
|
|
<LI><A href="pluginDoc.html" target="_blank">
|
|
Plugins</A>
|
|
<UL>
|
|
<LI><A href="pluginDoc.html#NDPluginDriver" target="_blank">
|
|
NDPluginDriver</A>
|
|
<LI><A href="pluginDoc.html#NDPluginStdArrays" target="_blank">
|
|
NDPluginStdArrays</A>
|
|
<LI><A href="pluginDoc.html#NDPluginFile" target="_blank">
|
|
NDPluginFile</A>
|
|
<LI><A href="pluginDoc.html#NDPluginROI" target="_blank">
|
|
NDPluginROI</A>
|
|
</UL>
|
|
<LI>Detector drivers
|
|
<UL>
|
|
<LI><A href="simDetectorDoc.html" target="_blank">
|
|
Simulation detector driver</A>
|
|
<LI><A href="prosilicaDoc.html" target="_blank">
|
|
Prosilica driver</A>
|
|
<LI><A href="pilatusDoc.html" target="_blank">
|
|
Pilatus driver</A>
|
|
<LI><A href="adscDoc.html" target="_blank">
|
|
ADSC driver</A>
|
|
</UL>
|
|
</UL>
|
|
|
|
<P> </P>
|
|
|
|
<CENTER><H2><A name=Overview>
|
|
Overview</A></H2></CENTER>
|
|
<P>
|
|
The areaDetector module provides a general-purpose interface for area (2-D) detectors in EPICS.
|
|
It is intended to be used with a wide variety of detectors and cameras, ranging from high frame rate
|
|
CCD and CMOS cameras, pixel-array detectors such as the Pilatus, and large format detectors like the
|
|
MAR-345 online imaging plate.</P>
|
|
|
|
The goals of this module are:
|
|
<UL>
|
|
<LI> Minimize the amount of code that needs to be written to implement a
|
|
new detector.
|
|
<LI> Provide a standard interface defining the functions and parameters that
|
|
a detector driver must support.
|
|
<LI> Provide a set of base EPICS records that will be present for every detector
|
|
using this module. This allows the use of generic EPICS clients for
|
|
displaying images and controlling cameras and detectors.
|
|
<LI> Allow easy extensibility to take advantage of detector-specific features
|
|
beyond the standard parameters.
|
|
<LI> Have high-performance. Applications can be written to get the detector
|
|
image data through EPICS, but an interface is also available to receive the detector
|
|
data at a lower-level for very high performance.
|
|
<LI> Provide an optional Region-Of-Interest (ROI) driver that performs computations
|
|
on regions within the image data. A basic ROI driver is included in the module,
|
|
and it is easy to add addtional ROI drivers for specific applications.
|
|
<LI> Provide detector drivers for commonly used detectors in synchrotron applications.
|
|
These include Prosilica GigE video cameras, MAR-CCD x-ray detectors, MAR-345 online
|
|
imaging plate detectors, the Pilatus pixel-array detector, and the Roper Scientific CCD
|
|
cameras.
|
|
</UL>
|
|
|
|
|
|
<P> </P>
|
|
|
|
<CENTER><H2><A name=Architecture>
|
|
Architecture</A></H2></CENTER>
|
|
<P>
|
|
The architecture of the areaDetector module is shown below.
|
|
|
|
<CENTER><IMG src="areaDetectorArchitecture.png"></CENTER>
|
|
|
|
From the bottom to the top this architecture consists of the following:</P>
|
|
<UL>
|
|
<LI>Layer 1. This is the layer that allows user written code to
|
|
communicate with the hardware.
|
|
It is usually provided by the detector vendor. It may consist of a library or DLL,
|
|
of a socket protocol to a driver, a Microsoft COM interface, etc.
|
|
<LI>Layer 2. This is the driver that is written for the areaDetector application to
|
|
control a particular detector. It is normally written in C++ and inherits from the
|
|
ADDriver class. It uses the standard asyn interfaces for control and status
|
|
information. Each time it receives a new data array it passes it as an NDArray object
|
|
to all Layer 3 clients that have registered for callbacks. This is the only code that
|
|
needs to be written to implement a new detector. Existing drivers range from
|
|
650 to 1050 lines of code.
|
|
<LI>Layer 3. Code running at this level is called a "plug-in". This code registers with a
|
|
driver for a callback whenever there is a new data array. The existing plugins implement
|
|
file saving (NDPluginFile), region-of-interest (ROI) calculations (NDPluginROI),
|
|
and conversion of detector data to standard EPICS array types for use by
|
|
Channel Access clients (NDPluginStdArrays). Plugins are normally written in C++ and
|
|
inherit from NDPluginDriver. Existing plugins range from 280 to 650 lines
|
|
of code.
|
|
<LI>Layer 4. This is standard asyn device support that comes with the EPICS asyn module.
|
|
<LI>Layer 5. These are standard EPICS records, and EPICS database (template) files that
|
|
define records to communicate with drivers at Layer 2 and plugins at Layer 3.
|
|
<LI>Layer 6. These are EPICS channel access clients, such as MEDM that communicate with
|
|
the records at Layer 5. There is a free IDL client that can display images using
|
|
EPICS waveform and other records communicating with the NDPluginStdArrays plugin
|
|
at Layer 3.
|
|
</UL>
|
|
|
|
The code in Layers 1-3 is essentially independent of EPICS. There are only 2 EPICS dependencies in this
|
|
code.
|
|
<OL>
|
|
<LI><A HREF="http://www.aps.anl.gov/epics/base/R3-14/9-docs/AppDevGuide.pdf">libCom</A>.
|
|
libCom from EPICS base provides operating-system independent functions for
|
|
threads, mutexes, etc.
|
|
<LI><A HREF="http://www.aps.anl.gov/epics/modules/soft/asyn">asyn</A>.
|
|
asyn is a module that provides interthread messaging services, including queueing
|
|
and callbacks.
|
|
</OL>
|
|
In particular it is possible to eliminate layers 4-6 in the architecture shown in Figure 1, providing
|
|
there is a programs such as the high-performance GUI shown in Layer 3. This means that it is not necessary
|
|
to run an EPICS IOC or to use EPICS Channel Access when using the drivers and plugins at Layers 2 and 3.
|
|
<P>
|
|
The plugin architecture is very powerful, because new plugins can be written for application-specific
|
|
purposes. For example, a plugin could be written to analyze images and find the center of the beam,
|
|
and such a plugin would then work with any detector driver.
|
|
Plugins are also powerful because they can be reconfigured at run-time. For example
|
|
the NDPluginStdArrays can switch from getting its array data from a detector driver to an NDPluginROI
|
|
plugin. That way it will switch from displaying the entire detector to whatever sub-region the ROI
|
|
driver has selected. Any Channel Access clients connected to the NDPluginStdArrays driver
|
|
will automatically switch to displaying this subregion.
|
|
Similarly, the NDPluginFile plugin can be switched at run-time from saving the entire image to saving
|
|
a selected ROI, just by changing its input source.
|
|
<P>
|
|
The use of plugins is optional, and it is only plugins that require the driver to make callbacks with
|
|
image data. If there are no plugins being used then EPICS can be used simply
|
|
to control the detector, without accessing the data itself. This is most useful when
|
|
the vendor API has the ability to save the data to a file.
|
|
<P>
|
|
What follows is a detailed description of the software, working from the bottom up.
|
|
Most of the code is object oriented, and written in C++. The parts of the code that depend
|
|
on anything from EPICS except libCom and asyn have been kept in in separate C files, so that
|
|
it should be easy to build applications that do not run as part of an EPICS IOC.
|
|
|
|
<P> </P>
|
|
<CENTER><H2><A name=asynPortDriver>
|
|
asynPortDriver</A></H2></CENTER>
|
|
|
|
The areaDetector module depends heavily on
|
|
<A HREF="http://www.aps.anl.gov/epics/modules/soft/asyn">asyn</A>.
|
|
It is the software that is used for interthread communication,
|
|
using the standard asyn interfaces (e.g. asynInt32, asynOctet, etc.), and callbacks. Detector drivers and plugins
|
|
are asyn port drivers, meaning that they implement one or more of the standard asyn interfaces. They register
|
|
themselves as interrupt sources, so that they do callbacks to registered asyn clients when values change.
|
|
asynPortDriver is a base C++ class that handles all of the details of registering the port driver,
|
|
registering the supported interfaces,
|
|
and registering the required interrupt sources.
|
|
<P>
|
|
Drivers and plugins each need to support a number of parameters that control their operation and provide
|
|
status information. Most of these can be treated as 32-bit integers, 64-bit floats, or strings.
|
|
When the new value of a parameter is sent to a driver, (e.g. detector binning in the X direction)
|
|
from an asyn client (e.g. an EPICS record),
|
|
then the driver will need to take some action. It may change some other parameters in response to this
|
|
new value (e.g. image size in the X direction). The sequence of operations in the driver can be summarized as
|
|
<OL>
|
|
<LI>New parameter value arrives, or new data arrives from detector.
|
|
<LI>Change values of one or more parameters.
|
|
<LI>For each parameter whose value changes set a flag noting that it changed.
|
|
<LI>When operation is complete, call the registered callbacks for each changed parameter.
|
|
</OL>
|
|
asynPortDriver provides methods to simplify the above sequence, which must be
|
|
implemented for each of the many parameters that the driver supports. Each parameter is assigned
|
|
a number, which is the value in the pasynUser-> reason field that asyn clients pass to
|
|
the driver when reading or writing that parameter. asynPortDriver maintains a table
|
|
of parameter values, associating each parameter number with a data type (integer, double, or string),
|
|
caching the current value, and maintaining a flag indicating if a value has changed.
|
|
Drivers use asynPortDriver methods to read the current value
|
|
from the table, and to set new values in the table. There is a method to call all registered callbacks
|
|
for values that have changed since callbacks were last done.
|
|
|
|
<P>The following are the public definitions in the asynPortDriver class:
|
|
<PRE>
|
|
#define asynCommonMask 0x00000001
|
|
#define asynDrvUserMask 0x00000002
|
|
#define asynOptionMask 0x00000004
|
|
#define asynInt32Mask 0x00000008
|
|
#define asyUInt32DigitalMask 0x00000010
|
|
#define asynFloat64Mask 0x00000020
|
|
#define asynOctetMask 0x00000040
|
|
#define asynInt8ArrayMask 0x00000080
|
|
#define asynInt16ArrayMask 0x00000100
|
|
#define asynInt32ArrayMask 0x00000200
|
|
#define asynFloat32ArrayMask 0x00000400
|
|
#define asynFloat64ArrayMask 0x00000800
|
|
#define asynGenericPointerMask 0x00001000
|
|
|
|
class asynPortDriver {
|
|
public:
|
|
asynPortDriver(const char *portName, int maxAddr, int paramTableSize, int interfaceMask, int interruptMask);
|
|
virtual asynStatus getAddress(asynUser *pasynUser, const char *functionName, int *address);
|
|
virtual asynStatus findParam(asynParamString_t *paramTable, int numParams, const char *paramName, int *param);
|
|
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
|
|
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
|
virtual asynStatus getBounds(asynUser *pasynUser, epicsInt32 *low, epicsInt32 *high);
|
|
virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value);
|
|
virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
|
|
virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars,
|
|
size_t *nActual, int *eomReason);
|
|
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars,
|
|
size_t *nActual);
|
|
virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeInt8Array(asynUser *pasynUser, epicsInt8 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksInt8Array(epicsInt8 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readInt16Array(asynUser *pasynUser, epicsInt16 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeInt16Array(asynUser *pasynUser, epicsInt16 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksInt16Array(epicsInt16 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readInt32Array(asynUser *pasynUser, epicsInt32 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeInt32Array(asynUser *pasynUser, epicsInt32 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksInt32Array(epicsInt32 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readFloat32Array(asynUser *pasynUser, epicsFloat32 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeFloat32Array(asynUser *pasynUser, epicsFloat32 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksFloat32Array(epicsFloat32 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksFloat64Array(epicsFloat64 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readGenericPointer(asynUser *pasynUser, void *pointer);
|
|
virtual asynStatus writeGenericPointer(asynUser *pasynUser, void *pointer);
|
|
virtual asynStatus doCallbacksGenericPointer(void *pointer, int reason, int addr);
|
|
virtual asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
|
|
const char **pptypeName, size_t *psize);
|
|
virtual asynStatus drvUserGetType(asynUser *pasynUser,
|
|
const char **pptypeName, size_t *psize);
|
|
virtual asynStatus drvUserDestroy(asynUser *pasynUser);
|
|
virtual void report(FILE *fp, int details);
|
|
virtual asynStatus connect(asynUser *pasynUser);
|
|
virtual asynStatus disconnect(asynUser *pasynUser);
|
|
|
|
virtual asynStatus setIntegerParam(int index, int value);
|
|
virtual asynStatus setIntegerParam(int list, int index, int value);
|
|
virtual asynStatus setDoubleParam(int index, double value);
|
|
virtual asynStatus setDoubleParam(int list, int index, double value);
|
|
virtual asynStatus setStringParam(int index, const char *value);
|
|
virtual asynStatus setStringParam(int list, int index, const char *value);
|
|
virtual asynStatus getIntegerParam(int index, int * value);
|
|
virtual asynStatus getIntegerParam(int list, int index, int * value);
|
|
virtual asynStatus getDoubleParam(int index, double * value);
|
|
virtual asynStatus getDoubleParam(int list, int index, double * value);
|
|
virtual asynStatus getStringParam(int index, int maxChars, char *value);
|
|
virtual asynStatus getStringParam(int list, int index, int maxChars, char *value);
|
|
virtual asynStatus callParamCallbacks();
|
|
virtual asynStatus callParamCallbacks(int list, int addr);
|
|
virtual void reportParams();
|
|
|
|
/* asynUser connected to ourselves for asynTrace */
|
|
asynUser *pasynUser;
|
|
};
|
|
</PRE>
|
|
|
|
A brief explanation of the methods and data in this class is provided here. Users should look at the
|
|
example driver (simDetector) and plugins provided with areaDetector for examples of how this
|
|
class is used.
|
|
|
|
<PRE>
|
|
asynPortDriver(const char *portName, int maxAddr, int paramTableSize, int interfaceMask, int interruptMask);
|
|
</PRE>
|
|
This is the constructor for the class.
|
|
<UL>
|
|
<LI><CODE>portName</CODE> is the name of the asyn port for this driver or plugin.
|
|
<LI><CODE>maxAddr</CODE> is the maximum number of asyn addresses that this driver supports.
|
|
This number returned by the <CODE>pasynManager-> getAddr()</CODE> function. Typically it is 1, but some
|
|
plugins (e.g. NDPluginROI) support values > 1. This controls the number of parameter
|
|
tables that are created.
|
|
<LI><CODE>parmTableSize</CODE> is the maximum number of parameters that this driver or plugin supports.
|
|
This controls the size of the parameter tables.
|
|
<LI><CODE>interfaceMask</CODE> is a mask with each bit defining which asyn interfaces this driver
|
|
or plugin supports.
|
|
The bit mask values are defined in asynPortDriver.h, e.g. <CODE>asynInt32Mask</CODE>.
|
|
<LI><CODE>interruptMask</CODE> is a mask with each bit defining which of the asyn interfaces this driver
|
|
or plugin supports can generate interrupts.
|
|
The bit mask values are defined in asynPortDriver.h, e.g. <CODE>asynInt8ArrayMask</CODE>.
|
|
</UL>
|
|
<BR>
|
|
<PRE>
|
|
virtual asynStatus getAddress(asynUser *pasynUser, const char *functionName, int *address);
|
|
</PRE>
|
|
Returns the value from pasynManager-> getAddr(pasynUser,...).
|
|
Returns an error if the address is not valid, e.g. >= this-> maxAddr.
|
|
|
|
<PRE>
|
|
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
|
|
virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value);
|
|
virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars,
|
|
size_t *nActual, int *eomReason);
|
|
</PRE>
|
|
These methods are called by asyn clients to return the current cached value for the
|
|
parameter indexed by pasynUser-> reason in the parameter table defined by <CODE>getAddress()</CODE>.
|
|
Derived classed typically do not need to implement these methods.
|
|
|
|
<BR>
|
|
<PRE>
|
|
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
|
virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
|
|
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars,
|
|
size_t *nActual);
|
|
</PRE>
|
|
These methods are called by asynClients to set the new value of a parameter. The
|
|
implementation of these methods in asynPortDriver copies the parameter into a cached
|
|
location for use by the asynRead(Int32, Float64, and Octet) methods. Most drivers
|
|
will provide their own implementations of these methods to do driver-dependent operations
|
|
when there is a new value of the parameter.
|
|
|
|
<BR>
|
|
<PRE>
|
|
virtual asynStatus readXXXArray(asynUser *pasynUser, epicsInt8 *value,
|
|
size_t nElements, size_t *nIn);
|
|
virtual asynStatus writeXXXArray(asynUser *pasynUser, epicsInt8 *value,
|
|
size_t nElements);
|
|
virtual asynStatus doCallbacksXXXArray(epicsInt8 *value,
|
|
size_t nElements, int reason, int addr);
|
|
virtual asynStatus readGenericPointer(asynUser *pasynUser, void *handle);
|
|
virtual asynStatus writeGenericPointer(asynUser *pasynUser, void *handle);
|
|
virtual asynStatus doCallbacksGenericPointer(void *handle, int reason, int addr);
|
|
</PRE>
|
|
where XXX=(Int8, Int16, Int32, Float32, or Float64).
|
|
The readXXX and writeXXX methods only have stub methods that return an error in asynPortDriver, so they
|
|
must be implemented in the derived classes if the corresponding interface is
|
|
used. They are not pure virtual functions so that the derived class need not implement
|
|
the interface if it is not used. The doCallbacksXXX methods in asynPortDriver
|
|
call any registered asyn clients on the corresponding interface if the <CODE>reason</CODE>
|
|
and <CODE>addr</CODE> values match. It typically does not need to be implemented in derived classes.
|
|
|
|
<BR>
|
|
<PRE>
|
|
virtual asynStatus findParam(asynParamString_t *paramTable, int numParams, const char *paramName, int *param);
|
|
virtual asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
|
|
const char **pptypeName, size_t *psize);
|
|
virtual asynStatus drvUserGetType(asynUser *pasynUser,
|
|
const char **pptypeName, size_t *psize);
|
|
virtual asynStatus drvUserDestroy(asynUser *pasynUser);
|
|
</PRE>
|
|
drvUserCreate must be implemented in derived classes that use the parameter facilities of asynPortDriver.
|
|
The <CODE>findParam</CODE> method is a convenience function that searches an array of {enum, string} structures
|
|
and returns the enum (parameter number) matching the string. This is typically used in the
|
|
implementation of <CODE>drvUserCreate</CODE> in derived classes. <CODE>drvUserGetType</CODE> and
|
|
<CODE>drvUserDestroy</CODE> typically do not need to be implemented in derived classes.
|
|
|
|
<BR>
|
|
<PRE>
|
|
virtual void report(FILE *fp, int details);
|
|
virtual asynStatus connect(asynUser *pasynUser);
|
|
virtual asynStatus disconnect(asynUser *pasynUser);
|
|
</PRE>
|
|
The <CODE>report</CODE> function prints information on registered interrupt clients if details > 0, and prints
|
|
parameter table information if details > 5. It is typically called by the implementation of
|
|
<CODE>report</CODE> in derived classes before or after
|
|
they print specific information about themselves. <CODE>connect</CODE> and <CODE>disconnect</CODE> call
|
|
<CODE>pasynManager-> exceptionConnect</CODE> and <CODE>pasynManager-> exceptionDisconnect</CODE> respectively.
|
|
Derived classes may or may not need to implement these functions.
|
|
|
|
<BR>
|
|
<PRE>
|
|
virtual asynStatus setIntegerParam(int index, int value);
|
|
virtual asynStatus setIntegerParam(int list, int index, int value);
|
|
virtual asynStatus setDoubleParam(int index, double value);
|
|
virtual asynStatus setDoubleParam(int list, int index, double value);
|
|
virtual asynStatus setStringParam(int index, const char *value);
|
|
virtual asynStatus setStringParam(int list, int index, const char *value);
|
|
virtual asynStatus getIntegerParam(int index, int * value);
|
|
virtual asynStatus getIntegerParam(int list, int index, int * value);
|
|
virtual asynStatus getDoubleParam(int index, double * value);
|
|
virtual asynStatus getDoubleParam(int list, int index, double * value);
|
|
virtual asynStatus getStringParam(int index, int maxChars, char *value);
|
|
virtual asynStatus getStringParam(int list, int index, int maxChars, char *value);
|
|
virtual asynStatus callParamCallbacks();
|
|
virtual asynStatus callParamCallbacks(int list, int addr);
|
|
</PRE>
|
|
The <CODE>setXXXParam</CODE> methods set the value of a parameter in the parameter table
|
|
in the object. If the value is different from the previous value of the parameter
|
|
they also set the flag indicating that the value has changed. The <CODE>getXXXParam</CODE>
|
|
methods return the current value of the parameter. There are two versions of the
|
|
<CODE>setXXXParam</CODE> and <CODE>getXXXParam</CODE> methods, one with a <CODE>list</CODE>
|
|
argument, and one without. The one without uses <CODE>list=0</CODE>, since there
|
|
is often only a single parameter list (i.e. if maxAddr=1). The <CODE>callParamCallbacks</CODE>
|
|
methods call back any registered clients for parameters that have changed since the last
|
|
time <CODE>callParamCallbacks</CODE> was called. The version of <CODE>callParamCallbacks</CODE>
|
|
with no arguments uses the first parameter list and matches asyn address=0. There is a
|
|
second version of <CODE>callParamCallbacks</CODE> that takes an argument specifying the parameter list
|
|
number, and the asyn address to match.
|
|
|
|
<CENTER><H2><A name=NDArray>
|
|
NDArray</A></H2></CENTER>
|
|
|
|
The NDArray (N-Dimensional array) is the class that is used for passing detector data from drivers
|
|
to plugins. The NDArray class is defined as follows:
|
|
|
|
<PRE>
|
|
#define ND_ARRAY_MAX_DIMS 10
|
|
|
|
/* Enumeration of array data types */
|
|
typedef enum
|
|
{
|
|
NDInt8,
|
|
NDUInt8,
|
|
NDInt16,
|
|
NDUInt16,
|
|
NDInt32,
|
|
NDUInt32,
|
|
NDFloat32,
|
|
NDFloat64
|
|
} NDDataType_t;
|
|
|
|
|
|
typedef struct NDDimension {
|
|
int size;
|
|
int offset;
|
|
int binning;
|
|
int reverse;
|
|
} NDDimension_t;
|
|
|
|
typedef struct NDArrayInfo {
|
|
int nElements;
|
|
int bytesPerElement;
|
|
int totalBytes;
|
|
} NDArrayInfo_t;
|
|
|
|
class NDArray {
|
|
public:
|
|
/* Data: NOTE this must come first because ELLNODE must be first, i.e. same address as object */
|
|
/* The first 2 fields are used for the freelist */
|
|
ELLNODE node;
|
|
int referenceCount;
|
|
/* The NDArrayPool object that created this array */
|
|
void *owner;
|
|
|
|
int uniqueId;
|
|
double timeStamp;
|
|
int ndims;
|
|
NDDimension_t dims[ND_ARRAY_MAX_DIMS];
|
|
NDDataType_t dataType;
|
|
int dataSize;
|
|
void *pData;
|
|
|
|
/* Methods */
|
|
NDArray();
|
|
int initDimension (NDDimension_t *pDimension, int size);
|
|
int getInfo (NDArrayInfo_t *pInfo);
|
|
int copy (NDArray *pOut);
|
|
int reserve();
|
|
int release();
|
|
};
|
|
|
|
|
|
</PRE>
|
|
An NDArray is a general purpose class for handling array data. An NDArray object is self-describing,
|
|
meaning it contains enough information to describe the data itself. It is not intended to
|
|
contain meta-data describing how the data was collected, etc.
|
|
<P>
|
|
An NDArray can have up to ND_ARRAY_MAX_DIMS dimensions, currently 10. A fixed maximum
|
|
number of dimensions is used to significantly simplify the code compared to
|
|
unlimited number of dimensions. Each dimension of the array is described
|
|
by an NDDimension_t structure. The fields in NDDimension_t are as follows:
|
|
|
|
<UL>
|
|
<LI><CODE>size</CODE> is the number of elements in this dimension.
|
|
<LI><CODE>offset</CODE> is the starting element in this dimension
|
|
relative to the first element of the detector in unbinned units. If a selected
|
|
region of the detector is being read, then this value may be
|
|
> 0. The offset value is cumulative, so if a plugin such as NDPluginROI
|
|
further selects a subregion, the offset is relative
|
|
to the first element in the detector and not to the first element of
|
|
the region passed to NDPluginROI.
|
|
<LI><CODE>binning</CODE> is the binning (sumation of elements) in this
|
|
dimension. The offset value is cumulative, so if a plugin such as
|
|
NDPluginROI performs binning,
|
|
the binning is expressed relative
|
|
to the pixels in the detector and not to the possibly binned
|
|
pixels passed to NDPluginROI.
|
|
<LI><CODE>reverse</CODE> is 0 if the data are in their normal order
|
|
as read out from the detector in this dimension,
|
|
and 1 if they are in reverse order. This value is cumulative,
|
|
so if a plugin such as
|
|
NDPluginROI reverses the data, the value must reflect the
|
|
orientation relative to the original detector, and not to
|
|
the possibly reversed data passed to NDPluginROI.
|
|
</UL>
|
|
The first 3 data fields in the NDArray class, <CODE>(node, referenceCount, owner)</CODE> are used
|
|
by the NDArrayPool class discussed below.
|
|
The remaining data fields are as follows:
|
|
<UL>
|
|
<LI><CODE>uniqueId</CODE> This should be a number that uniquely identifies this array. Detector
|
|
drivers should assign this number to the NDArray before calling the plugins.
|
|
<LI><CODE>timeStamp</CODE> This should be a timestamp value in seconds recording when the frame
|
|
was collected. The time=0 reference is driver-dependent because of differences in vendor
|
|
libraries. If there is a choice, it is recommended to use timeStamp=0 for Epoch, (00:00:00 UTC,
|
|
January 1, 1970).
|
|
<LI><CODE>ndims</CODE> The number of dimensions in this array.
|
|
<LI><CODE>dims</CODE> Array of NDDimension_t structures. The array is of length ND_MAX_DIMS, but
|
|
only the first <CODE>ndims</CODE> values must contain valid information.
|
|
<LI><CODE>dataType</CODE> The data type of this array, one of the NDDataType_t enum values.
|
|
The data types supported are signed and unsigned 8, 16, and 32-bit integers, and 32 and 64-bit floats.
|
|
<LI><CODE>dataSize</CODE> The size of the memory buffer pointed to by <CODE>pData</CODE> in bytes. This may be
|
|
larger than the amount actually required to hold the data for this array.
|
|
<LI><CODE>pData</CODE> Pointer to the memory for this array. The data is assumed to be stored
|
|
in the order of <CODE>dims[0]</CODE> changing fastest, and <CODE>dims[ndims-1]</CODE> changing slowest.
|
|
</UL>
|
|
The methods of the NDArray class are:
|
|
<UL>
|
|
<LI><CODE>initDimension</CODE> This method simply initializes the dimension structure to size=size,
|
|
binning=1, reverse=0, offset=0.
|
|
<LI><CODE>getInfo</CODE>. This convenience method returns information about an NDArray, including the total number
|
|
of elements, the number of byte per element, and the total number of bytes in the array.
|
|
<LI><CODE>copy</CODE>. This method makes a copy of an NDArray object. If the output array pointer is NULL
|
|
then it is first allocated. If the output array object already exists (pOut!=NULL) then it
|
|
must have sufficient memory allocated to it to hold the data.
|
|
<LI><CODE>reserve</CODE>. This method calls NDArrayPool->reserve() for this object. It increases the reference
|
|
count for this array.
|
|
<LI><CODE>release</CODE>. This method calls NDArrayPool->release() for this object. It decreases the reference
|
|
count for this array.
|
|
</UL>
|
|
|
|
|
|
|
|
<CENTER><H2><A name=NDArrayPool>
|
|
NDArrayPool</A></H2></CENTER>
|
|
|
|
The NDArrayPool class manages a free list (pool) of NDArray objects (described above). Drivers allocate NDArray objects
|
|
from the pool, and pass these objects to plugins. Plugins increase the reference count on the object when they
|
|
place the object on their queue, and decrease the reference count when they are done processing the array. When
|
|
the reference count reaches 0 again the NDArray object is placed back on the free list. This mechanism minimizes the
|
|
copying of array data in plugins.
|
|
The public interface of the NDArrayPool class is defined as follows:
|
|
|
|
<PRE>
|
|
class NDArrayPool {
|
|
public:
|
|
NDArrayPool (int maxBuffers, size_t maxMemory);
|
|
NDArray* alloc (int ndims, int *dims, NDDataType_t dataType, int dataSize, void *pData);
|
|
int reserve (NDArray *pArray);
|
|
int release (NDArray *pArray);
|
|
int convert (NDArray *pIn,
|
|
NDArray **ppOut,
|
|
NDDataType_t dataTypeOut,
|
|
NDDimension_t *outDims);
|
|
int report (int details);
|
|
</PRE>
|
|
|
|
The methods of the NDArrayPool class are:
|
|
<UL>
|
|
<LI><CODE>NDArrayPool</CODE> This is the constructor for the class. The maxBuffers argument is the maximum
|
|
number of NDArray objects that the pool is allowed to contain. The maxMemory argument is the maxiumum
|
|
number of bytes of memory the the pool is allowed to use, summed over all of the NDArray objects.
|
|
<LI><CODE>alloc</CODE> This method allocates a new NDArray object. The first 3 arguments are required. ndims
|
|
is the number of dimensions in the NDArray. dims is an array of dimensions, whose size must be at least ndims.
|
|
dataType is the data type of the NDArray data. dataSize is the number of bytes to allocate for the array data.
|
|
If it is 0 then alloc() will compute the size required from ndims, dims, and dataType. pData is a pointer
|
|
to a data buffer. If it is NULL then alloc will allocate a new array buffer. If pData is not NULL then
|
|
it is assumed to point to a valid buffer. In this case
|
|
dataSize must contain the actual number of bytes in the existing array, and this array must be large enough
|
|
to hold the array data. alloc() searches its free list to find a free NDArray buffer. If is cannot find one
|
|
then it will allocate a new one and add it to the free list. If doing so would exceed maxBuffers then alloc()
|
|
will return an error. Similarly if allocating the memory required for this NDArray would cause the
|
|
cumulative memory allocated for the pool to exceed maxMemory then an error will be returned. alloc() sets
|
|
the reference count for the returned NDArray to 1.
|
|
<LI><CODE>reserve</CODE>. This method increases the reference count for the NDArray object. Plugins must call
|
|
reserve() when an NDArray is placed on a queue for later processing.
|
|
<LI><CODE>release</CODE>. This method decreases the reference count for the NDArray object. Plugins must call
|
|
release() when an NDArray is removed from the queue and processing on it is complete. Drivers must call
|
|
release() after calling all plugins.
|
|
<LI><CODE>convert</CODE> This method creates a new output NDArray from an input NDArray, performing conversion
|
|
operations. The conversion can change the data type if dataTypeOut is different from
|
|
pIn->dataType. It can also change the dimensions. outDims may have different values of size, binning, offset and
|
|
reverse for each of its dimensions from input array dimensions (pIn->dims).
|
|
<LI><CODE>report</CODE> This method reports on the free list size and other properties of the NDArrayPool object.
|
|
</UL>
|
|
|
|
|
|
<CENTER><H2><A name=asynNDArrayDriver>
|
|
asynNDArrayDriver</A></H2></CENTER>
|
|
|
|
asynNDArrayDriver inherits from asynPortDriver. It implements the asynGenericPointer functions, assuming that
|
|
these reference NDArray objects. This is the class from which both plugins and area detector drivers are
|
|
indirectly derived.
|
|
Its public interface is defined as follows:
|
|
|
|
<PRE>
|
|
class asynNDArrayDriver : public asynPortDriver {
|
|
public:
|
|
asynNDArrayDriver(const char *portName, int maxAddr, int paramTableSize, int maxBuffers, size_t maxMemory,
|
|
int interfaceMask, int interruptMask);
|
|
virtual asynStatus readGenericPointer(asynUser *pasynUser, void *genericPointer);
|
|
virtual asynStatus writeGenericPointer(asynUser *pasynUser, void *genericPointer);
|
|
virtual void report(FILE *fp, int details);
|
|
|
|
};
|
|
</PRE>
|
|
The methods of the asynNDArrayDriver class are:
|
|
<UL>
|
|
<LI><CODE>asynNDArrayDriver</CODE> This is the constructor for the class. portName, maxAddr, paramTableSize,
|
|
interfaceMask and interruptMask are simply passed to the asynPortDriver base class constructor.
|
|
asynNDArray creates an NDArrayPool object to allocate NDArray objects.
|
|
maxBuffers and maxMemory are passed to the constructor for the NDArrayPool object.
|
|
<LI><CODE>readGenericPointer</CODE> This method copies an NDArray object from the asynNDArrayDriver to an NDArray
|
|
whose address is passed by the caller in the genericPointer argument.
|
|
The caller must allocate the memory for the array, and pass the size in NDArray->dataSize. The method will
|
|
limit the amount of data copied to the actual array size or the input dataSize, whichever is smaller.
|
|
<LI><CODE>writeGenericPointer</CODE> This method currently does nothing. Derived classes must implement this method
|
|
as required.
|
|
<LI><CODE>report</CODE> This method calls the report function in the asynPortDriver base class. It then
|
|
calls the NDArrayPool->report() method if details > 5.</UL>
|
|
|
|
<CENTER><H2><A name=ADDriver>
|
|
ADDriver</A></H2></CENTER>
|
|
|
|
ADDriver inherits from asynNDArrayDriver. This is the class from which area detector drivers are directly derived.
|
|
Its public interface is defined as follows:
|
|
<PRE>
|
|
class ADDriver : public asynNDArrayDriver {
|
|
public:
|
|
ADDriver(const char *portName, int maxAddr, int paramTableSize, int maxBuffers, size_t maxMemory,
|
|
int interfaceMask, int interruptMask);
|
|
|
|
/* These are the methods that we override from asynPortDriver */
|
|
virtual asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
|
|
const char **pptypeName, size_t *psize);
|
|
|
|
/* These are the methods that are new to this class */
|
|
int createFileName(int maxChars, char *fullFileName);
|
|
</PRE>
|
|
|
|
The methods of the ADDriver class are:
|
|
<UL>
|
|
<LI><CODE>ADDriver</CODE> This is the constructor for the class. All of the arguments are simply passed to the
|
|
constructor for the asynNDArrayDriver base class. After calling the base class constructor this method sets
|
|
reasonable default values for all of the parameters defined in ADStdDriverParams.h.
|
|
<LI><CODE>drvUserCreate</CODE> This method returns one of the enum values for the parameters defined in
|
|
ADStdDriverParams.h if the driverInfo field matches one the strings defined in that file. Derived classes will
|
|
typically provide an implementation of drvUserCreate() that searches for parameters that are unique to that
|
|
detector driver. If a parameter is not matched, then ADDriver->drvUserCreate() will be called to see if it
|
|
is a standard driver parameter (defined in ADStdDriverParams.h).
|
|
<LI><CODE>createFileName</CODE> This is a convenience function that constructs a complete file name in
|
|
the ADFullFileName parameter from the
|
|
ADFilePath, ADFileName, ADFileNumber, and ADFileTemplate parameters.
|
|
</UL>
|
|
|
|
<CENTER><H2><A name=ADStdDriverParams>
|
|
ADStdDriverParams</A></H2></CENTER>
|
|
|
|
The file <CODE>ADStdDriverParams.h</CODE> defines the following:
|
|
|
|
<PRE>
|
|
/* Enumeration of shutter status */
|
|
typedef enum
|
|
{
|
|
ADShutterClosed,
|
|
ADShutterOpen
|
|
} ADShutterStatus_t;
|
|
|
|
/* Enumeration of detector status */
|
|
typedef enum
|
|
{
|
|
ADStatusIdle,
|
|
ADStatusAcquire,
|
|
ADStatusReadout,
|
|
ASStatusCorrect,
|
|
ADStatusSaving,
|
|
ADStatusAborting,
|
|
ADStatusError,
|
|
} ADStatus_t;
|
|
|
|
typedef enum
|
|
{
|
|
ADImageSingle,
|
|
ADImageMultiple,
|
|
ADImageContinuous
|
|
} ADImageMode_t;
|
|
|
|
typedef enum
|
|
{
|
|
ADTriggerInternal,
|
|
ADTriggerExternal
|
|
} ADTriggerMode_t;
|
|
|
|
</PRE>
|
|
It also defines parameters that all area detector drivers should implement if possible. These parameters are defined
|
|
by enum values with an associated asyn interface, and access (read-only or read-write). The EPICS database
|
|
ADBase.template provides access to these standard driver parameters. The following table lists the
|
|
standard driver parameters. The columns are defined as follows:
|
|
<UL>
|
|
<LI><B>Enum name:</B> The name of the enum value for this parameter in ADStdDriverParams.h. There are several EPICS
|
|
records in ADBase.template that do not have corresponding enum fields,
|
|
and these are indicated as Not Applicable (N/A).
|
|
<LI><B>asyn interface:</B> The asyn interface used to pass this parameter to the driver.
|
|
<LI><B>Access:</B> Read-write (r/w) or read-only (r/o).
|
|
<LI><B>drvUser string:</B> The string used to look up the parameter in the driver through the drvUser interface.
|
|
This string is used in the EPICS database file for generic asyn device support to associate a record with
|
|
a particular parameter.
|
|
<LI><B>EPICS record name:</B> The name of the record in ADBase.template. Each record name begins with the two macro
|
|
parameters $(P) and $(R). In the case of read/write parameters there are normally two records, one for writing
|
|
the value, and a second, ending in _RBV, that contains the actual value (Read Back Value) of the parameter.
|
|
<LI><B>EPICS record type:</B> The record type of the record. Waveform records are used to hold long strings,
|
|
with length (NELM) = 256 bytes and EPICS data type (FTVL) = UCHAR.
|
|
</UL>
|
|
Note that for parameters whose values are defined by enum values (e.g ADImageMode, ADTriggerMode, ADFileFormat, ADStatus),
|
|
drivers can use a different set of enum values for
|
|
these parameters. They can override the enum menu in ADBase.template with detector-specific choices by loading a
|
|
detector-specific template file after loading ADBase.template.
|
|
<P>
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Parameter Definitions in ADStdDriverParams.h and EPICS Record Definitions in ADBase.template</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TH>Enum name</TH>
|
|
<TH>asyn interface</TH>
|
|
<TH>Access</TH>
|
|
<TH>Description</TH>
|
|
<TH>drvUser string</TH>
|
|
<TH>EPICS record name</TH>
|
|
<TH>EPICS record type</TH>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Information about the detector</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADManufacturer</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Detector manufacturer name</TD>
|
|
<TD>MANUFACTURER</TD>
|
|
<TD>$(P)$(R)Manufacturer_RBV</TD>
|
|
<TD>stringin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADModel</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Detector model name</TD>
|
|
<TD>MODEL</TD>
|
|
<TD>$(P)$(R)Model_RBV</TD>
|
|
<TD>stringin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADMaxSizeX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Maximum (sensor) size in the X direction</TD>
|
|
<TD>MAX_SIZE_X</TD>
|
|
<TD>$(P)$(R)MaxSizeX_RBV</TD>
|
|
<TD>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADMaxSizeY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Maximum (sensor) size in the Y direction</TD>
|
|
<TD>MAX_SIZE_Y</TD>
|
|
<TD>$(P)$(R)MaxSizeY_RBV</TD>
|
|
<TD>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Detector readout control including gain, binning, region start and size, reversal</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADGain</TD>
|
|
<TD>asynFloat64</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Detector gain</TD>
|
|
<TD>GAIN</TD>
|
|
<TD>$(P)$(R)Gain<BR>$(P)$(R)Gain_RBV</TD>
|
|
<TD>ao<BR>ai</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADBinX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Binning in the X direction</TD>
|
|
<TD>BIN_X</TD>
|
|
<TD>$(P)$(R)BinX<BR>$(P)$(R)BinX_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADBinY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Binning in the Y direction</TD>
|
|
<TD>BIN_Y</TD>
|
|
<TD>$(P)$(R)BinY<BR>$(P)$(R)BinY_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADMinX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>First pixel to read in the X direction. <BR>0 is the first pixel on the detector.</TD>
|
|
<TD>MIN_X</TD>
|
|
<TD>$(P)$(R)MinX<BR>$(P)$(R)MinX_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADMinY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>First pixel to read in the Y direction.<BR>0 is the first pixel on the detector.</TD>
|
|
<TD>MIN_Y</TD>
|
|
<TD>$(P)$(R)MinY<BR>$(P)$(R)MinY_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADSizeX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Size of the region to read in the X direction</TD>
|
|
<TD>SIZE_X</TD>
|
|
<TD>$(P)$(R)SizeX<BR>$(P)$(R)SizeX_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADSizeY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Size of the region to read in the Y direction</TD>
|
|
<TD>SIZE_Y</TD>
|
|
<TD>$(P)$(R)SizeY<BR>$(P)$(R)SizeY_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADReverseX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Reverse image in the X direction<BR>(0=No, 1=Yes)</TD>
|
|
<TD>REVERSE_X</TD>
|
|
<TD>$(P)$(R)ReverseX<BR>$(P)$(R)ReverseX_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADReverseY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Reverse image in the Y direction<BR>(0=No, 1=Yes)</TD>
|
|
<TD>REVERSE_Y</TD>
|
|
<TD>$(P)$(R)ReverseY<BR>$(P)$(R)ReverseY_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Image and trigger modes</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADImageMode</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Image mode (ADImageMode_t).</TD>
|
|
<TD>IMAGE_MODE</TD>
|
|
<TD>$(P)$(R)ImageMode<BR>$(P)$(R)ImageMode_RBV</TD>
|
|
<TD>mbbo<BR>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADTriggerMode</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Trigger mode (ADTriggerMode_t).</TD>
|
|
<TD>TRIGGER_MODE</TD>
|
|
<TD>$(P)$(R)TriggerMode<BR>$(P)$(R)TriggerMode_RBV</TD>
|
|
<TD>mbbo<BR>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Data type</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADDataType</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Data type (NDDataType_t).</TD>
|
|
<TD>DATA_TYPE</TD>
|
|
<TD>$(P)$(R)DataType<BR>$(P)$(R)DataType_RBV</TD>
|
|
<TD>mbbo<BR>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Actual dimensions of image data</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADImageSizeX</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Size of the image data in the X direction</TD>
|
|
<TD>IMAGE_SIZE_X</TD>
|
|
<TD>$(P)$(R)ImageSizeX_RBV</TD>
|
|
<TD>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADImageSizeY</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Size of the image data in the Y direction</TD>
|
|
<TD>IMAGE_SIZE_Y</TD>
|
|
<TD>$(P)$(R)ImageSizeY_RBV</TD>
|
|
<TD>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADImageSize</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Total size of image data in bytes</TD>
|
|
<TD>IMAGE_SIZE</TD>
|
|
<TD>$(P)$(R)ImageSize_RBV</TD>
|
|
<TD>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Acquisition time and period</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADAcquireTime</TD>
|
|
<TD>asynFloat64</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Acquisition time per image</TD>
|
|
<TD>ACQ_TIME</TD>
|
|
<TD>$(P)$(R)AcquireTime<BR>$(P)$(R)AcquireTime_RBV</TD>
|
|
<TD>ao<BR>ai</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADAcquirePeriod</TD>
|
|
<TD>asynFloat64</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Acquisition period between images</TD>
|
|
<TD>ACQ_PERIOD</TD>
|
|
<TD>$(P)$(R)AcquirePeriod<BR>$(P)$(R)AcquirePeriod_RBV</TD>
|
|
<TD>ao<BR>ai</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Number of exposures and number of images</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADNumExposures</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Number of exposures per image to acquire</TD>
|
|
<TD>NEXPOSURES</TD>
|
|
<TD>$(P)$(R)NumExposures<BR>$(P)$(R)NumExposures_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADNumImages</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Number of images to acquire in one acquisition sequence</TD>
|
|
<TD>NIMAGES</TD>
|
|
<TD>$(P)$(R)NumImages<BR>$(P)$(R)NumImages_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Acquisition control</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADAcquire</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Start (1) or stop (0) image acquisition. This record is linked to an EPICS busy record
|
|
that does not process its forward link until acquisition is complete. Clients should write
|
|
1 to the Acquire record to start acquisition, and wait for Acquire to go to 0 to know that
|
|
acquisition is complete.</TD>
|
|
<TD>ACQUIRE</TD>
|
|
<TD>$(P)$(R)Acquire</TD>
|
|
<TD>bo</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>File saving parameters</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFilePath</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/w</TD>
|
|
<TD>File path</TD>
|
|
<TD>FILE_PATH</TD>
|
|
<TD>$(P)$(R)FilePath<BR>$(P)$(R)FilePath_RBV</TD>
|
|
<TD>waveform<BR>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFileName</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/w</TD>
|
|
<TD>File name</TD>
|
|
<TD>FILE_NAME</TD>
|
|
<TD>$(P)$(R)FileName<BR>$(P)$(R)FileName_RBV</TD>
|
|
<TD>waveform<BR>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFileNumber</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>File number</TD>
|
|
<TD>FILE_NUMBER</TD>
|
|
<TD>$(P)$(R)FileNumber<BR>$(P)$(R)FileNumber_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFileTemplate</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Format string for constructing ADFullFileName from ADFilePath, ADFileName, and ADFileNumber</TD>
|
|
<TD>FILE_TEMPLATE</TD>
|
|
<TD>$(P)$(R)FileTemplate<BR>$(P)$(R)FileTemplate_RBV</TD>
|
|
<TD>waveform<BR>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFullFileName</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Full file name</TD>
|
|
<TD>FULL_FILE_NAME</TD>
|
|
<TD>$(P)$(R)FullFileName_RBV</TD>
|
|
<TD>waveform<BR>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADAutoIncrement</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Auto-increment flag (0=No, 1=Yes)</TD>
|
|
<TD>AUTO_INCREMENT</TD>
|
|
<TD>$(P)$(R)AutoIncrement<BR>$(P)$(R)AutoIncrement_RBV</TD>
|
|
<TD>bo<BR>bi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADAutoSave</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Auto-save flag (0=No, 1=Yes)</TD>
|
|
<TD>AUTO_SAVE</TD>
|
|
<TD>$(P)$(R)AutoSave<BR>$(P)$(R)AutoSave_RBV</TD>
|
|
<TD>bo<BR>bi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADFileFormat</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>File format. The format to write/read data in (e.g. TIFF, netCDF, etc.)</TD>
|
|
<TD>FILE_FORMAT</TD>
|
|
<TD>$(P)$(R)FileFormat<BR>$(P)$(R)FileFormat_RBV</TD>
|
|
<TD>mbbo<BR>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADWriteFile</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Manually save the most recent image to a file when value=1</TD>
|
|
<TD>WRITE_FILE</TD>
|
|
<TD>$(P)$(R)WriteFile</TD>
|
|
<TD>longout</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADReadFile</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Manually read a file when value=1</TD>
|
|
<TD>READ_FILE</TD>
|
|
<TD>$(P)$(R)ReadFile</TD>
|
|
<TD>longout</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Status information</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADStatus</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Acquisition status (ADStatus_t)</TD>
|
|
<TD>STATUS</TD>
|
|
<TD>$(P)$(R)DetectorState_RBV</TD>
|
|
<TD>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADStatusMessage</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Status message string</TD>
|
|
<TD>STATUS_MESSAGE</TD>
|
|
<TD>$(P)$(R)StatusMessage_RBV</TD>
|
|
<TD>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADStringToServer</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>String from driver to string-based vendor server</TD>
|
|
<TD>STRING_TO_SERVER</TD>
|
|
<TD>$(P)$(R)StringToServer_RBV</TD>
|
|
<TD>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADStringFromServer</TD>
|
|
<TD>asynOctet</TD>
|
|
<TD>r/o</TD>
|
|
<TD>String from string-based vendor server to driver</TD>
|
|
<TD>STRING_FROM_SERVER</TD>
|
|
<TD>$(P)$(R)StringFromServer_RBV</TD>
|
|
<TD>waveform</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADImageCounter</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Counter that increments by 1 each time an image is acquired</TD>
|
|
<TD>IMAGE_COUNTER</TD>
|
|
<TD>$(P)$(R)ImageCounter<BR>$(P)$(R)ImageCounter_RBV</TD>
|
|
<TD>longout<BR>longin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>N/A</TD>
|
|
<TD>N/A</TD>
|
|
<TD>r/o</TD>
|
|
<TD>Rate (Hz) at which ImageCounter is incrementing. Computed in database.</TD>
|
|
<TD>N/A</TD>
|
|
<TD>$(P)$(R)ImageRate_RBV</TD>
|
|
<TD>calc</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Shutter control. Note: no areaDetector drivers yet implement shutter control,
|
|
and these parameters may change in the near future.</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>ADShutter</TD>
|
|
<TD>asynInt32</TD>
|
|
<TD>r/w</TD>
|
|
<TD>Shutter control (ADShutterStatus_t)</TD>
|
|
<TD>SHUTTER</TD>
|
|
<TD>$(P)$(R)ShutterMode<BR>$(P)$(R)ShutterMode_RBV</TD>
|
|
<TD>mbbo<BR>mbbi</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>Image data</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>NDArrayData</TD>
|
|
<TD>asynGenericPointer</TD>
|
|
<TD>r/w</TD>
|
|
<TD>The image data as an NDArray object</TD>
|
|
<TD>NDARRAY_DATA</TD>
|
|
<TD>N/A. EPICS access to image data is through NDStdArrays plugin.</TD>
|
|
<TD>N/A</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD COLSPAN=7, ALIGN=CENTER><B>asyn port information</B></TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>N/A</TD>
|
|
<TD>N/A</TD>
|
|
<TD>N/A</TD>
|
|
<TD>The name of the asyn port for this driver</TD>
|
|
<TD>N/A</TD>
|
|
<TD>$(P)$(R)PortName_RBV</TD>
|
|
<TD>stringin</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD>N/A</TD>
|
|
<TD>N/A</TD>
|
|
<TD>N/A</TD>
|
|
<TD>asyn record to control debugging (asynTrace)</TD>
|
|
<TD>N/A</TD>
|
|
<TD>$(P)$(R)AsynIO</TD>
|
|
<TD>asyn</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>
|
|
The following is the MEDM screen that provides access to the parameters in ADStdDriverParams through
|
|
records in ADBase.template. This is a
|
|
top-level MEDM screen that will work with any areaDetector driver. Note however that many drivers will not implement all
|
|
of these parameters, so detector-specific MEDM screens should generally be created that only display the EPICS PVs
|
|
for the features implemented for that detector. Note that the section of the screen labeled "Shutter" is not currently
|
|
implemented for any areaDetector driver, and is subject to change in the near future.
|
|
<P>
|
|
<CENTER><IMG src="ADBase.png"></CENTER>
|
|
|
|
</BODY>
|
|
</HTML>
|