spec

Software for Diffraction

epics

EPICS specific functions

DESCRIPTION

spec can be used in the EPICS (Experimental Physics and Industrial Control System) environment when linked with the EPICS channel access libraries. When so linked, the three functions epics_get(), epics_put() and epics_par() provide generic channel access to EPICS process variables (PVs). In addition, the built-in support for the standard EPICS motor, scaler, MCA and generic-serial records becomes available through spec's hardware-independent functions and commands.

CONFIGURATION

spec must be linked with a supported version of the EPICS channel access libraries. spec supports EPICS 3.13, 3.14, 3.15 and 3.16 releases. EPICS release 7 is supported as of spec release 6.08.03. The EPICS source can be downloaded from the EPICS home page at epics.anl.gov/epics, and the libraries can be built from those sources.

To link spec with the EPICS libraries, the path to the libraries must be specified for the spec Install script. The path is stored as the parameter epics_home in spec's install_data file. The path can specify the location of a base or lib directory or the complete path to the actual libraries. For example, on a 64-bit Linux platform, spec will look for the libraries in the following locations:

$epics_home
$epics_home/lib/linux-x86_x64
$epics_home/base/lib/linux-x86_x64

Although the install_data file can be edited directly, one still needs to run spec's Install script to relink and reinstall spec if the install configuration is changed.

On some recent Linux platforms, the default EPICS configuration forces linking with the readline library which causes problems when linking spec with the default libedit library. One fix is to rebuild the EPICS libraries from source disabling the readline configuration which is not needed for most uses of the libraries. To disable, edit the EPICS configuration file, CONFIG_SITE.Common.linux-x86_64 on a 64-bit Linux platform, and comment out this line:

#COMMANDLINE_LIBRARY = READLINE

Another work around is to change the default spec installation to use -lreadline instead of libedit/libedit.a. On Linux, in order to link spec with libreadline, the readline developer package, either libreadline-dev or readline-devel, depending on the Linux distribution, needs to be installed.

On Linux platforms, the default installation gives the spec executable special privileges in order to access hardware interfaces. The current method uses capabilities(7). Prior to spec release 6.05.01, spec was made a set-user-id root executable. With either method, shared libraries used by spec, such as the EPICS libraries, must be configured system wide. That can be accomplished by creating (or editing if it already exists) a file called, for example:

/etc/ld.so.conf.d/local.conf

The file should contain a line with the complete path name of the EPICS libraries, such as:

/opt/EPICS/base/lib/linux-x86

Run the following command (as root) to update the shared library information on the system:

/sbin/ldconfig

See the Linux man pages for ldconfig, ld.so and capabilities for further information.

Note, the special privileges allow spec to access the I/O resources associated with PC cards and USB devices used in many spec configurations. If no such hardware is present, the special privileges are not required.

FUNCTIONS

In the epics_get() and epics_put() functions below, note the special considerations given when the process variable is a byte array (EPICS type DBF_CHAR). The special treatment is given as these arrays are often used to hold strings since the maximum length of the EPICS DBF_STRING type is only 40 bytes. Many EPICS records use arrays of DBF_CHAR where longer strings are needed. (The special treatment for DBF_CHAR arrays is as of spec release 5.08.06-5.)

Note also that prior to EPICS 3.14, the maximum size of a data transfer was 16,384 bytes. With release 3.14 and later, one can set the EPICS_CA_MAX_ARRAY_BYTES environment variable to larger values to overcome that limit.

The following functions for generic EPICS access are available:

epics_get(PV_name [, type] [, count])
Returns the result of a channel-access get of the process variable PV_name, as in print epics_get("ioc:m1.VAL"). By default, the native data type of the process variable will be retrieved over channel access. However, a different data type can be specified using the optional second argument. Possible types are "char", "short", "long", "float", "double", "enum" and "string". For DBF_ENUM data types, the string value of the process variable is returned, unless another type is specified. For array types, the entire array is retrieved and returned, unless the optional argument count specifies fewer elements (as of spec release 5.00.04). When requesting "string" for types other than DBF_CHAR, arrays will be returned as a spec string data array consisting of 40-byte rows, with as many rows as elements in the EPICS array. Each row will contain an ASCII representation of the corresponding value, with the rest of the row padded with null bytes. For DBF_CHAR data, the return value will be converted to an ordinary string (as of release 5.10.01-8). Note, any bytes following a null byte in the DBF_CHAR array will be lost. If a "monitor" has been set for the process variable using the "monitor_set" option below, the returned result will be the most recent value as set by the monitor call back. Otherwise (or if there has been no monitor call back), spec will access the process variable value using the standard channel access ca_array_get().
epics_put(PV_name, value [, wait_time])
Does a channel-access put of value, which can be either a string or a number, to the process variable PV_name. If the optional wait_time argument is set, spec will wait for a channel-access "callback" to indicate the value has been sent. spec will wait up to the specified number of seconds for that response. Such a feature might come in handy if the channel-access put is to start an acquisition device and one wants to insure the device is started before continuing. If the process variable is an array of a DBF_CHAR type, any non-array value, whether number or string, will be sent via channel access as a string, filling as many elements of the array as the string is long.
epics_par(PV_name, what)

Returns parameters associated with the process variable PV_name, according to the value of the string what, which may have the following values:

"connect"
Queues the call to make the initial connection for the designated process variable, but doesn't force a network packet to be sent. If many process variables are to be accessed from user level, it will be more efficient in terms of network access to use this "connect" option for each, before the individual epics_get() and epics_put() calls. (Available as of spec release 5.08.01-4.)
"refresh"
Closes then reopens the channel access connection. If a monitor has been set, it will be restored. (Available as of spec release 6.00.02.)
"count"
Returns the element count associated with PV_name.
"host"
Returns the host name for PV_name (EPICS 3.12 and above).
"monitor_set"
Creates a "monitor" for the indicated process variable.
"monitor_check"
If the indicated process variable has a monitor, returns the value 1 if the value of the process variable has changed since last read with epics_get(). Returns -1 if no monitor has been created and for other EPICS errors. Otherwise returns zero.
"monitor_clear"
Removes the monitor for the indicated process variable.
"read_access"
Returns nonzero if PV_name has read access (EPICS 3.12 and above).
"retries"
Returns the value for the number of retry attempts after an EPICS channel-access read timeout. Although a process variable name must be provided, the setting is global to all process variables.
"timeout"
Returns the value spec uses for the ca_pend_io() time-out parameter.
"timestamp"
Returns the EPICS timestamp associated with the indicated process variable. The value is converted to the seconds since the UNIX epoch (00:00:00 Jan 1, 1970 UTC - also the spec epoch - the EPICS epoch is marked exactly twenty years later) and includes the fractional part to nanosecond resolution. The value returned here can be used as an argument to spec's date() function to print the time of day associated with the timestamp value. Note, for array EPICS process variables, the timestamp associated with the first element of the array is returned. (Available as of spec release 5.10.02-11.)
"type"
Returns a string (such as "string", "double", "short", etc.) indicating the data type of PV_name.
"write_access"
Returns nonzero if PV_name has write access (EPICS 3.12 and above).
epics_par(PV_name, what, parameter)

Sets parameters associated with the process variable PV_name, according to the value of the string what, which may have the following values:

"retries"
Sets the value for the number of retry attempts after an EPICS channel-access read timeout. Although a process variable name must be provided, the setting is global to all process variables. The default value is two, and the default is restored each time spec is run. A message is printed when the channel-access reads are retried.
"timeout"
Sets the value spec uses for the ca_pend_io() time-out parameter.
"monitor_set"
Associates the spec variable, parameter with the given EPICS process variable. The value of the spec variable will be updated when EPICS events arrive reflecting changes to the PV. The spec variable must be a global variable. Ordinary variables and spec data arrays can be used in this fashion. Associative arrays and associative array elements are not allowed. For a data array, the type and size will not be changed by this command. Data from the PV will be converted or truncated as needed to fit into the constraints of the spec data.

ERRORS

When linked with the EPICS channel-access libraries, spec creates two built-in global variables, EPICS_ERR and EPICS_ERR_MSG (as of spec release 5.08.01-1). If one of the above functions results in an error generated by the channel-access calls, the value of the error will be assigned to EPICS_ERR and the corresponding message, as provided by the ca_message() function, will be assigned to EPICS_ERR_MSG. In addition, certain errors at the spec level, including errors associated with failure to connect to an EPICS server, will result in a -1 assigned to EPICS_ERR and, in some cases, a message assigned to EPICS_ERR_MSG.

MONITORS

To avoid excess network traffic, monitors can be created for selected process variables. With a monitor, epics_get() calls will return a cached value of the process variable, rather than calling out over the network to fetch a value. The EPICS database will update spec when the value of the process variable changes. The "monitor_check" option to epics_par() allows for testing whether the value has changed since the last time the process variable was read with epics_get().

As of spec release 6.10.01, a spec variable can be associated with a monitor using:

epics_par(PV_name, "monitior_set", spec_name)

The value of the spec variable will track changes to the EPICS PV by virtue of EPICS events. Also, as long as the value of the variable is being tracked, it cannot be changed by assignment. Attempts to assign to the variable will result in an error. The tracking is turned off with

epics_par(PV_name, "monitor_clear")

or

unglobal spec_name

Only one spec variable can be associated with a particular PV. If the monitor is already set, but a different variable name is used in the "monitor_set" call, the monitor association will be transferred to the new variable. If the new variable is not valid, the monitor will be cleared. If the monitor has been set without naming a variable, a subsequent call can be used to add the association without clearing the monitor first.

EPICS events are polled using synchronous code in spec that is called during hardware polling. Hardware polling occurs mainly with the wait() built-in function and while waiting for user keyboard input. In order to detect a change within a loop, a wait() call is required, such as:

epics_par(some_PV, "monitor_set", some_status)
while (some_status == 0) {
        sleep(.1)
        wait(0x28)
}

Without the wait() call, the code would not detect a change in some_status because there is no opening for hardware polling. The 0x08 bit means poll remote events. The 0x20 bit means return a status rather than wait for the change. See the wait help file.

The behavior of "monitor_check" in relation to epics_get() when a spec variable is tracking an EPICS PV is unchanged. The epics_get() will return the cached value, which will be the same value associated with the spec variable associated with the monitor.

Note, a reconfig (or config) call reinitializes the hardware connections and clears all monitors. Use the config_mac feature to set up macros to have monitors automatically created when hardware is initialized or reinitialized.

DEFAULT TIMEOUT

The default timeout for the channel access calls is 0.5 seconds. The timeout for individual process variables can be changed using the epics_par() function, as described above. It also possible to change the default timeout for all newly created connections using the spec_par() function with the "epics_timeout" option. (See the spec_par help file.) The parameters set with spec_par() are saved in the user's state file, so will be restored when spec is restarted, except, of course when starting fresh (with the -f flag).

USING EPICS SCALERS

spec supports counter/timers using the standard EPICS scaler record. In addition, spec allows configuration of arbitrary process variables as counters. For process-variable counters, the value of the PV will be fetched as a DBF_DOUBLE and assigned to the corresponding element of the built-in scaler array S[] when the spec getcounts command is executed.

EPICS counter-related controllers are configured on the Devices screen of the configuration editor as follows:

SCALERS     DEVICE ADDR <>MODE NUM                         <>TYPE U#
    YES   ioc1:sc1              12  EPICS Scaler as Counter/Timer  0
    YES   ioc2:sc2              16   EPICS Scaler as Counter only  1
    YES ioc:pv.VAL               1            EPICS PV as Counter  0
    YES      ioc1:              10            EPICS PV as Counter  1
    YES       ioc:              16               EPICS MIZAR 8310

The first entry selects a master timer with counter channels supported by the standard EPICS scaler record. The second entry selects the same record support, but used only as counters. (Prior to spec release 5.09.01-1, only one master timer could be configured.) In each case, the DEVICE field contains the prefix of the process variables associated with the records.

The third and fourth entries configure arbitrary process variables to be used as counters. The first of these supplies the entire PV name in the DEVICE field. The second example is for multiple PV counters that share the prefix given in the DEVICE field. The reminder of the PV name is specified on the Scaler screen as described below.

The last line configures the legacy EPICS Mizar 8310 counter/timer record.

Individual counter channels are configured on the Scaler screen of the configuration editor along the following lines:

Number      Name Mnemonic  <>Device Unit Chan  <>Use As  Scale Factor
     0   Seconds      sec  EPICS_SC    0    0  timebase       1000000
     1   Monitor      mon  EPICS_SC    0    1   monitor             1
     2  Detector      det  EPICS_SC    1    0   counter             1
     3       PV0      pv0  EPICS_PV    0    0   counter             1
     4       PV1      pv1  EPICS_PV    1    0   counter             1
     5       PV2      pv2  EPICS_PV    1    1   counter             1
     6      Det2     det2  EPICS_MZ    0    1   counter             1

The device-type EPICS_SC selects counter channels from the standard EPICS scaler record. The unit numbers start at zero and count off the "EPICS Scaler" entries on the Devices screen.

The process variable counters are selected with EPICS_PV. Again, unit numbers start at zero and correspond to the order of the "EPICS PV" entries on the Devices screen. The process variable name is formed from the name given in the DEVICE field on the Devices screen, optionally appended by the string set as miscellaneous parameter 1 (misc_par_1) on the non-standard optional parameter screen, accessed by typing the p command:

Custom Parameters for Counter 3 "PV0" (pv0)            1/1 configured

NAME                      VALUE
misc_par_1                pv1.VAL

The device-type EPICS_MZ selects a channel from the legacy EPICS Mizar record.

The following function is available for EPICS_SC and EPICS_PV channels:

counter_par(mne, "timestamp")
Returns the time when the value associated with counter mne was last updated via a ca_pend_io() callback. The timestamp value can be used to check whether an updated counter value will be available in S[mne] after calling getcounts. This timestamp is internal to spec and is not the EPICS timestamp.

USING EPICS MOTORS (STANDARD MOTOR RECORD)

spec supports motors under EPICS using the standard EPICS motor record. (See epics.anl.gov/bcda/synApps/motor.)

spec provides two flavors of support. With the first (the EPICS_M1 motors), spec takes all the motor parameters, such as step size, velocity, acceleration, etc., from spec's own configuration file. With the second (the EPICS_M2 motors), the parameters are taken from the EPICS data base, and the parameters in the spec configuration file are ignored. Most sites configure the spec motors as EPICS_M2 so that spec will not cause conflicts with other EPICS utilities.

Note, EPICS_M1 motors write all the parameters configured in the spec configuration file to the EPICS data base when spec reads its configuration file, ignoring values currently set in the EPICS data base. However, spec will accept the position of the motor when first connecting to the data base, if the motor position is nonzero. If the motor position is zero and spec's settings file contains a nonzero position, spec will ask which position should be used.

For EPICS_M2 motors, spec will only change motor parameters in the EPICS data base with the motor_par() function. (See the motors help file.)

Each set of motors with the same EPICS prefix should be entered on a separate line on the Devices screen of the configuration editor:

MOTORS     DEVICE   ADDR  <>MODE  NUM                     <>TYPE U#
   YES      ioc1:                  44     EPICS Motor Controller  0
   YES      ioc2:                  12     EPICS Motor Controller  1

The NUM field should be set to the highest channel number expected. On the motor screen of the configuration editor, motors are assigned by choosing EPICS_M1 or EPICS_M2 in the controller field, as in:

Number: <>Controller  0:EPICS_M2 1:EPICS_M2 2:EPICS_M2 3:EPICS_M2
Unit/Channel                 0/1        0/2        0/3        0/4
Name                   Two Theta      Theta        Chi        Phi
Mnemonic                     tth         th        chi        phi

The optional unit/channel numbering is turned on for all EPICS motors by entering a unit/channel for any of the EPICS motors. The feature is disabled by typing ^D when the unit/channel data is highlighted for any of the EPICS motors. When the feature is disabled, channel numbers are assigned consecutively. Unit numbers are assigned according to the order the EPICS motor controllers appear on the Devices screen, starting from zero. Note, though, channel numbers start at one, to match the APS EPICS motor record convention.

The APS EPICS motor naming convention appends m1, m2, etc., to the prefix defined on the motor controller Devices screen.

An alternative naming scheme can be selected by entering a string value for the optional "Generic Parameter 1" on the second optional motor parameter screen. That string value will be appended to the prefix string defined on the motor controller Devices screen.

With the following configuration:

MOTORS     DEVICE   ADDR  <>MODE  NUM                     <>TYPE U#
   YES X04SA-ES2-                  44     EPICS Motor Controller


Number: <>Controller  0:EPICS_M2 1:EPICS_M2 2:EPICS_M2 3:EPICS_M2
Unit/Channel                 0/1        0/2        0/3        0/4
Name                   Two Theta      Theta        Chi        Phi
Mnemonic                     tth         th        chi        phi
     ...
Generic parameter 1      SAM:TTH     SAM:TH    SAM:CHI    SAM:PHI

The process variable prefixes would be X04SA-ES2-SAM:TTH, X04SA-ES2-SAM:TH, etc.

In configurations with EPICS motors that constantly send updates with small fluctuations in position (due to a sensitive encoder, for example), spec may send move commands to the motors during scans, even if the motors were not involved in the scans. The "slop" parameter can be used with such motors to create a position dead band as of spec release 6.03.07. Position events within "slop" counts of the current position won't update the current position in spec. However, at the end of a move or during a sync command, the current position will always be read. The "slop" parameter is set on the second standard optional parameter motor screen of the configuration editor.

The spec support for the standard EPICS motor records uses a subset of the available process variables, namely those listed here:

     
  ACCL Acceleration time (seconds)
  BDST Backlash distance (egu)
  BVEL Backlash velocity (egu/s)
  DHLM Dial high limit
  DIR User direction
  DISP Disable
  DLLM Dial low limit
  DMOV Done moving to value
  ERES Encoder step size (egu)
  FOFF Offset-freeze switch
  HLS At high limit switch
  LLS At low limit switch
  MRES Motor step size (egu)
  OFF User offset (egu)
  RRBV Raw readback value
  RVAL Raw desired value
  SET Set/use switch
  SPMG Stop/pause/move/go
  STOP Stop
  UEIP Use encoder if present
  VAL User desired value
  VBAS Base velocity (egu/s)
  VELO Velocity (egu/s)

All the above process variables need to be present in order for spec to use an EPICS motor. Refer to epics.anl.gov/bcda/synApps/motor for additional details on the meaning of the process variables.

USING EPICS MOTORS (CLS MOTOR RECORD)

The Canadian Light Source (CLS) uses a local motor record not related to the standard EPICS motor record described in the previous section.

The spec CLS EPICS motor record support takes all motor parameter values from the EPICS database. The CLS EPICS motors are configured as controller type EPICS_CL on the motor screen.

Each CLS EPICS motor controller unit is configured on the Devices screen of the configuration editor along the following lines:

MOTORS         DEVICE  ADDR <>MODE  NUM                         <>TYPE
   YES SMTR1604-5-I10               100  EPICS at CLS Motor Controller

The process variable (PV) base name for each motor is formed by appending a hyphen and the motor channel number to the configured DEVICE name above. For example, for motor channel 17, the "status" PV would be SMTR1604-5-I10-17:status. Each group of motors that share the same initial part of the PV can be included in the same unit. Unit numbers start at zero for the first CLS EPICS motor controller. Channel numbers can be assigned as needed in the unit/channel configuration row on the Motor screen of the configuration editor.

The following CLS EPICS motor record process variables are used with the spec support:

     
  hasEncoder Used to see if position is from encoder
  status Used to see if motor is moving
  step:slope Used to scale positions
  egu Set to target position to move motor
  egu:sp Provides current dial position if no encoder
  egu:fbk Provides current dial position if using encoder
  egu:offset Used for offset between user and dial positions
  enc:slope Needed for loadEncoder used by chg_dial()
  loadStep Used to set dial position
  loadEncoder Used to set dial position if using encoder
  stop Sent to halt motors
  vBase:egups Used to set and get base rate
  velo:egups Used to set and get steady-state velocity
  accel Used to set and get acceleration
  cw Catches high limit
  ccw Catches low limit

The spec support does not use or look at the CLS EPICS motor record "step:offset" and "enc:offset" process variables and expects the values of those to be zero.

NOTES

To use spec on Linux with EPICS 3.15 in a configuration that requires spec to be installed set user-id root for access to I/O devices, the default EPICS build configuration must either disable USE_POSIX_THREAD_PRIORITY_SCHEDULING in the configure/CONFIG_SITE file or comment out the call to mlockall() in the file osdThread.c in the EPICS sources. EPICS 3.15 uses the process privilege level to selectively enable real-time process behavior, including locking the process in memory. If spec is installed set user-id root, EPICS 3.15 locks the process image in memory, which causes spec to crash.

spec has been using the Linux "capabilities" feature since release 6.05.01 rather than set user-id root mode to gain access to privileged I/O devices. This change solves the problem without the need for custom configured EPICS libraries.