1284 lines
29 KiB
Plaintext
1284 lines
29 KiB
Plaintext
#*************************************************************************
|
|
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
|
# National Laboratory.
|
|
# Copyright (c) 2002 The Regents of the University of California, as
|
|
# Operator of Los Alamos National Laboratory.
|
|
# EPICS BASE is distributed subject to a Software License Agreement found
|
|
# in file LICENSE that is included with this distribution.
|
|
#*************************************************************************
|
|
|
|
=title Calculation Output Record (calcout)
|
|
|
|
The Calculation Output or "Calcout" record is similar to the Calc record
|
|
with the added feature of having outputs (an "output link" and an "output
|
|
event") which are conditionally executed based on the result of the
|
|
calculation. This feature allows conditional branching to be implemented
|
|
within an EPICS database (e.g. process Record_A only if Record_B has a
|
|
value of 0). The Calcout record is also similar to the Wait record (with
|
|
additional features) but uses EPICS standard INLINK and OUTLINK fields
|
|
rather than the DBF_STRING fields used in the Wait record. For new
|
|
databases, it is recommended that the Calcout record be used instead of the
|
|
Wait record.
|
|
|
|
=head2 Parameter Fields
|
|
|
|
The record-specific fields are described below, grouped by functionality.
|
|
|
|
=recordtype calcout
|
|
|
|
=cut
|
|
|
|
menu(calcoutOOPT) {
|
|
choice(calcoutOOPT_Every_Time,"Every Time")
|
|
choice(calcoutOOPT_On_Change,"On Change")
|
|
choice(calcoutOOPT_When_Zero,"When Zero")
|
|
choice(calcoutOOPT_When_Non_zero,"When Non-zero")
|
|
choice(calcoutOOPT_Transition_To_Zero,"Transition To Zero")
|
|
choice(calcoutOOPT_Transition_To_Non_zero,"Transition To Non-zero")
|
|
}
|
|
menu(calcoutDOPT) {
|
|
choice(calcoutDOPT_Use_VAL,"Use CALC")
|
|
choice(calcoutDOPT_Use_OVAL,"Use OCAL")
|
|
}
|
|
menu(calcoutINAV) {
|
|
choice(calcoutINAV_EXT_NC,"Ext PV NC")
|
|
choice(calcoutINAV_EXT,"Ext PV OK")
|
|
choice(calcoutINAV_LOC,"Local PV")
|
|
choice(calcoutINAV_CON,"Constant")
|
|
}
|
|
|
|
recordtype(calcout) {
|
|
|
|
=head3 Scan Parameters
|
|
|
|
The Calcout record has the standard fields for specifying under what
|
|
circumstances the record will be processed.
|
|
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
|
|
|
=head3 Read Parameters
|
|
|
|
The read parameters for the Calcout record consists of 12 input links INPA,
|
|
INPB, ... INPL. The fields can be database links, channel access links, or
|
|
constants. If they are links, they must specify another record's field. If
|
|
they are constants, they will be initialized with the value they are
|
|
configured with and can be changed via C<dbPuts>. These fields cannot be
|
|
hardware addresses. In addition, the Calcout record contains the INAV,
|
|
INBV, ... INLV fields which indicate the status of the link fields, for
|
|
example, whether or not the specified PV was found and a link to it
|
|
established. See L<Operator Display Parameters> for an explanation of these
|
|
fields.
|
|
|
|
=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
|
|
|
|
=head3 Expression
|
|
|
|
Like the Calc record, the Calcout record has a CALC field in which the
|
|
developer can enter an infix expression which the record routine will
|
|
evaluate when it processes the record. The resulting value is placed in the
|
|
VAL field. This value can then be used by the OOPT field (see
|
|
L<Output Parameters>) to determine whether or not to write to the output
|
|
link or post an output event. It can also be the value that is written to
|
|
the output link. The CALC expression is actually converted to opcode and
|
|
stored in Reverse Polish Notation in the RPCL field. It is this expression
|
|
which is actually used to calculate VAL. The Reverse Polish expression is
|
|
evaluated more efficiently during run-time than an infix expression. CALC
|
|
can be changes at run-time, and a special record routine will call a
|
|
function to convert it to Reverse Polish Notation.
|
|
|
|
The infix expressions that can be used are very similar to the C expression
|
|
syntax, but with some additions and subtle differences in operator meaning
|
|
and precedence. The string may contain a series of expressions separated by
|
|
a semi-colon character ';' any one of which may actually provide the
|
|
calculation result; however all of the other expressions included must
|
|
assign their result to a variable. All alphabetic elements described below
|
|
are case independent, so upper and lower case letters may be used and mixed
|
|
in the variable and function names as desired. Spaces may be used anywhere
|
|
within an expression except between the characters that make up a single
|
|
expression element.
|
|
|
|
The range of expressions supported by the calculation record are separated into
|
|
literals, constants, operands, algebraic operators, trigonometric operators,
|
|
relational operators, logical operator, the assignment operator,
|
|
parentheses and commas, and the question mark or '?:' operator.
|
|
|
|
=fields CALC, VAL, RPCL
|
|
|
|
=head3 Literals
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Standard double precision floating point numbers
|
|
|
|
=item *
|
|
Inf: Infinity
|
|
|
|
=item *
|
|
Nan: Not a Number
|
|
|
|
=back
|
|
|
|
=head3 Constants
|
|
|
|
=over
|
|
|
|
=item *
|
|
PI: returns the mathematical constant E<pi>
|
|
|
|
=item *
|
|
D2R: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
|
angle from degrees to radians
|
|
|
|
=item *
|
|
R2D: evaluates to 180/E<pi> which, when used as a multiplier, converts an
|
|
angle from radians to degrees
|
|
|
|
=back
|
|
|
|
=head3 Operands
|
|
|
|
The expression can use the values retrieved from the INPx links as
|
|
operands, though constants can be used as operands too. These values
|
|
retrieved from the input links are stored in the A-L fields. The values to
|
|
be used in the expression are simple references by the field letter. For
|
|
instance, the value obtained from the INPA link is stored in field A, and
|
|
the values obtained from the INPB link is stored in the field B. The names
|
|
can be included in the expression will operate on their respective values,
|
|
as in A+B.
|
|
|
|
=fields A, B, C, D, E, F, G, H, I, J, K, L
|
|
|
|
The keyword VAL returns the current contents of the expression's result
|
|
field, i.e. the VAL field for the CALC expression and the OVAL field for
|
|
the OCAL expression. (These fields can be written to by CA put, so it might
|
|
I<not> be the result from the last time the expression was evaluated).
|
|
|
|
=head3 Algebraic Operations
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
ABS: Absolute value (unary)
|
|
|
|
=item *
|
|
SQR: Square root (unary)
|
|
|
|
=item *
|
|
MIN: Minimum (any number of args)
|
|
|
|
=item *
|
|
MAX: Maximum (any number of args)
|
|
|
|
=item *
|
|
FINITE: returns non-zero if none of the arguments are NaN or Inf (any
|
|
number of args)
|
|
|
|
=item *
|
|
ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
|
|
of args)
|
|
|
|
=item *
|
|
CEIL: Ceiling (unary)
|
|
|
|
=item *
|
|
FLOOR: Floor (unary)
|
|
|
|
=item *
|
|
FMOD: Floating point modulo (binary) Added in 7.0.8
|
|
|
|
=item *
|
|
LOG: Log base 10 (unary)
|
|
|
|
=item *
|
|
LOGE: Natural log (unary)
|
|
|
|
=item *
|
|
LN: Natural log (unary)
|
|
|
|
=item *
|
|
EXP: Exponential function (unary)
|
|
|
|
=item *
|
|
^ : Exponential (binary)
|
|
|
|
=item *
|
|
** : Exponential (binary)
|
|
|
|
=item *
|
|
+ : Addition (binary)
|
|
|
|
=item *
|
|
- : Subtraction (binary)
|
|
|
|
=item *
|
|
* : Multiplication (binary)
|
|
|
|
=item *
|
|
/ : Division (binary)
|
|
|
|
=item *
|
|
% : Modulo (binary)
|
|
|
|
=item *
|
|
NOT: Negate (unary)
|
|
|
|
=back
|
|
|
|
=head3 Trigonometric Operators
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
SIN: Sine
|
|
|
|
=item *
|
|
SINH: Hyperbolic sine
|
|
|
|
=item *
|
|
ASIN: Arc sine
|
|
|
|
=item *
|
|
COS: Cosine
|
|
|
|
=item *
|
|
COSH: Hyperbolic cosine
|
|
|
|
=item *
|
|
ACOS: Arc cosine
|
|
|
|
=item *
|
|
TAN: Tangent
|
|
|
|
=item *
|
|
TANH: Hyperbolic tangent
|
|
|
|
=item *
|
|
ATAN: Arc tangent
|
|
|
|
=back
|
|
|
|
=head3 Relational Operators
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<<< >= >>> : Greater than or equal to
|
|
|
|
=item *
|
|
C<<< > >>> : Greater than
|
|
|
|
=item *
|
|
C<<< <= >>> : Less than or equal to
|
|
|
|
=item *
|
|
C<<< < >>> : Less than
|
|
|
|
=item *
|
|
C<<< # >>> : Not equal to
|
|
|
|
=item *
|
|
C<<< = >>> : Equal to
|
|
|
|
=back
|
|
|
|
=head3 Logical Operators
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
&& : And
|
|
|
|
=item *
|
|
|| : Or
|
|
|
|
=item *
|
|
! : Not
|
|
|
|
=back
|
|
|
|
=head3 Bitwise Operators
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<|> : Bitwise Or
|
|
|
|
=item *
|
|
C<&> : Bitwise And
|
|
|
|
=item *
|
|
OR : Bitwise Or
|
|
|
|
=item *
|
|
AND : Bitwise And
|
|
|
|
=item *
|
|
XOR : Bitwise Exclusive Or
|
|
|
|
=item *
|
|
C<~> : One's Complement
|
|
|
|
=item *
|
|
C<<< << >>> : Arithmetic Left Shift
|
|
|
|
=item *
|
|
C<<< >> >>> : Arithmetic Right Shift
|
|
|
|
=item *
|
|
C<<<< >>> >>>> : Logical Right Shift
|
|
|
|
=back
|
|
|
|
=head3 Assignment Operator
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<:=> : assigns a value (right hand side) to a variable (i.e. field)
|
|
|
|
=back
|
|
|
|
=head3 Parentheses, Comma, and Semicolon
|
|
|
|
The open and close parentheses are supported. Nested parentheses are
|
|
supported.
|
|
|
|
The comma is supported when used to separate the arguments of a binary
|
|
function.
|
|
|
|
The semicolon is used to separate expressions. Although only one
|
|
traditional calculation expression is allowed, multiple assignment
|
|
expressions are allowed.
|
|
|
|
=head3 Conditional Expression
|
|
|
|
The C language's question mark operator is supported. The format is:
|
|
C<condition ? True result : False result>
|
|
|
|
=head3 Expression Examples
|
|
|
|
=head3 Algebraic
|
|
|
|
C<A + B + 10>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Result is C<A + B + 10>
|
|
|
|
=back
|
|
|
|
=head3 Relational
|
|
|
|
C<<< (A + B) < (C + D) >>>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Result is 1 if C<<< (A + B) < (C + D) >>>
|
|
|
|
=item *
|
|
Result is 0 if C<<< (A + B) >= (C + D) >>>
|
|
|
|
=back
|
|
|
|
=head3 Question Mark
|
|
|
|
C<<< (A + B) < (C + D) ? E : F + L + 10 >>>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Result is C<E> if C<<< (A + B) < (C + D) >>>
|
|
|
|
=item *
|
|
Result is C<F + L + 10> if C<<< (A + B) >= (C + D) >>>
|
|
|
|
=back
|
|
|
|
Prior to Base 3.14.9 it was legal to omit the : and the second (else) part
|
|
of the conditional, like this:
|
|
|
|
C<(A + B)<(C + D) ? E>
|
|
|
|
=over 1
|
|
|
|
=item
|
|
Result is E if (A + B)<(C + D)
|
|
|
|
=item
|
|
Result is unchanged if (A + B)>=(C + D)
|
|
|
|
From 3.14.9 onwards, this expression must be written as
|
|
C<(A + B) < (C + D) ? E : VAL>
|
|
|
|
=back
|
|
|
|
=head3 Logical
|
|
|
|
C<A & B>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Causes the following to occur:
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Convert A to integer
|
|
|
|
=item *
|
|
Convert B to integer
|
|
|
|
=item *
|
|
Bitwise And A and B
|
|
|
|
=item *
|
|
Convert result to floating point
|
|
|
|
=back
|
|
|
|
=back
|
|
|
|
=head3 Assignment
|
|
|
|
C<sin(a); a:=a+D2R>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Causes the Calc record to output the successive values of a sine curve in
|
|
1 degree intervals.
|
|
|
|
=back
|
|
|
|
=head3 Output Parameters
|
|
|
|
These parameters specify and control the output capabilities of the Calcout
|
|
record. They determine when to write the output, where to write it, and what
|
|
the output will be. The OUT link specifies the Process Variable to which
|
|
the result will be written.
|
|
|
|
=head4 Menu calcoutOOPT
|
|
|
|
The OOPT field determines the condition that causes the output link to be
|
|
written to. It's a menu field that has six choices:
|
|
|
|
=menu calcoutOOPT
|
|
|
|
=over
|
|
|
|
=item *
|
|
C<Every Time> -- write output every time record is processed.
|
|
|
|
=item *
|
|
C<On Change> -- write output every time VAL changes, i.e., every time the
|
|
result of the expression changes.
|
|
|
|
=item *
|
|
C<When Zero> -- when record is processed, write output if VAL is zero.
|
|
|
|
=item *
|
|
C<When Non-zero> -- when record is processed, write output if VAL is
|
|
non-zero.
|
|
|
|
=item *
|
|
C<Transition To Zero> -- when record is processed, write output only if VAL
|
|
is zero and the last value was non-zero.
|
|
|
|
=item *
|
|
C<Transition To Non-zero> -- when record is processed, write output only if
|
|
VAL is non-zero and last value was zero.
|
|
|
|
=back
|
|
|
|
=head4 Menu calcoutDOPT
|
|
|
|
The DOPT field determines what data is written to the output link when the
|
|
output is executed. The field is a menu field with two options:
|
|
|
|
=menu calcoutDOPT
|
|
|
|
If C<Use CALC> is specified, when the record writes its
|
|
output it will write the result of the expression in the CALC field, that
|
|
is, it will write the value of the VAL field. If C<Use OCAL> is specified,
|
|
the record will instead write the result of the expression in the OCAL
|
|
field, which is contained in the OVAL field. The OCAL field is exactly like
|
|
the CALC field and has the same functionality it can contain the string
|
|
representation of an expression which is evaluated at run-time. Thus, if
|
|
necessary, the record can use the result of the CALC expression to
|
|
determine if data should be written and can use the result of the OCAL
|
|
expression as the data to write.
|
|
|
|
If the OEVT field specifies a non-zero integer and the condition in the
|
|
OOPT field is met, the record will post a corresponding event. If the ODLY
|
|
field is non-zero, the record pauses for the specified number of seconds
|
|
before executing the OUT link or posting the output event. During this
|
|
waiting period the record is "active" and will not be processed again until
|
|
the wait is over. The field DLYA is equal to 1 during the delay period. The
|
|
resolution of the delay entry system dependent.
|
|
|
|
The IVOA field specifies what action to take with the OUT link if the
|
|
Calcout record enters an INVALID alarm status. The options are
|
|
C<Continue normally>, C<Don't drive outputs>, and C<Set output to IVOV>.
|
|
If the IVOA field is C<Set output to IVOV>, the data entered into the
|
|
IVOV field is written to the OUT link if the record alarm severity is
|
|
INVALID.
|
|
|
|
=fields OUT, OOPT, DOPT, OCAL, OVAL, OEVT, ODLY, IVOA, IVOV
|
|
|
|
=head3 Operator Display Parameter
|
|
|
|
These parameters are used to present meaningful data to the operator. Some
|
|
are also meant to represent the status of the record at run-time.
|
|
|
|
The EGU field contains a string of up to 16 characters which is supplied by
|
|
the user and which describes the values being operated upon. The string is
|
|
retrieved whenever the routine C<get_units()> is called. The EGU string is
|
|
solely for an operator's sake and does not have to be used.
|
|
|
|
The HOPR and LOPR fields only refer to the limits of the VAL, HIHI, HIGH,
|
|
LOW, and LOLO fields. PREC controls the precision of the VAL field.
|
|
|
|
=head4 Menu calcoutINAV
|
|
|
|
The INAV-INLV fields indicate the status of the link to the PVs specified
|
|
in the INPA-INPL fields respectively. These fields can have four possible
|
|
values:
|
|
|
|
=menu calcoutINAV
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<Ext PV NC> -- the PV wasn't found on this IOC and a Channel Access link
|
|
hasn't been established.
|
|
|
|
=item *
|
|
C<Ext PV OK> -- the PV wasn't found on this IOC and a Channel Access link
|
|
has been established.
|
|
|
|
=item *
|
|
C<Local PV> -- the PV was found on this IOC.
|
|
|
|
=item *
|
|
C<Constant> -- the corresponding link field is a constant.
|
|
|
|
=back
|
|
|
|
The OUTV field indicates the status of the OUT link. If has the same
|
|
possible values as the INAV-INLV fields.
|
|
|
|
The CLCV and OLCV fields indicate the validity of the expression in the
|
|
CALC and OCAL fields respectively. If the expression in invalid, the field
|
|
is set to one.
|
|
|
|
The DLYA field is set to one during the delay specified in ODLY.
|
|
|
|
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
|
|
Parameters> for more on the record name (NAME) and description (DESC) fields.
|
|
|
|
=fields EGU, PREC, HOPR, LOPR, INAV, INBV, INCV, INDV, INEV, INFV, INGV, INHV, INIV, INJV, INKV, INLV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
|
|
|
|
=head3 Alarm Parameters
|
|
|
|
The possible alarm conditions for the Calcout record are the SCAN, READ,
|
|
Calculation, and limit alarms. The SCAN and READ alarms are called by the
|
|
record support routines. The Calculation alarm is called by the record
|
|
processing routine when the CALC expression is an invalid one, upon which
|
|
an error message is generated.
|
|
|
|
The following alarm parameters, which are configured by the user, define the
|
|
limit alarms for the VAL field and the severity corresponding to those
|
|
conditions.
|
|
|
|
The HYST field defines an alarm deadband for each limit.
|
|
|
|
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#alarm-specification>
|
|
for a complete explanation of record alarms and of the standard fields.
|
|
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
|
to alarms that are common to all record types.
|
|
|
|
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
|
|
|
|
=head3 Monitor Parameters
|
|
|
|
These parameters are used to determine when to send monitors for the value
|
|
fields. These monitors are sent when the value field exceeds the last
|
|
monitored field by the appropriate deadband, the ADEL for archiver monitors
|
|
and the MDEL field for all other types of monitors. If these fields have a
|
|
value of zero, every time the value changes, monitors are triggered; if
|
|
they have a value of -1, every time the record is scanned, monitors are
|
|
triggered. See L<Monitor Specification> for a complete explanation of
|
|
monitors.
|
|
|
|
=fields ADEL, MDEL
|
|
|
|
=head3 Run-time Parameters
|
|
|
|
These fields are not configurable using a configuration tool and none are
|
|
modifiable at run-time. They are used to process the record.
|
|
|
|
The LALM field is used to implement the hysteresis factor for the alarm
|
|
limits.
|
|
|
|
The LA-LL fields are used to decide when to trigger monitors for the
|
|
corresponding fields. For instance, if LA does not equal the value for A,
|
|
monitors for A are triggered. The MLST and ALST fields are used in the same
|
|
manner for the VAL field.
|
|
|
|
=fields LALM, ALST, MLST, LA, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
|
|
|
|
=cut
|
|
|
|
include "dbCommon.dbd"
|
|
%/* Declare Device Support Entry Table */
|
|
%struct calcoutRecord;
|
|
%typedef struct calcoutdset {
|
|
% dset common;
|
|
% long (*write)(struct calcoutRecord *prec);
|
|
%} calcoutdset;
|
|
%#define HAS_calcoutdset
|
|
%
|
|
field(RPVT,DBF_NOACCESS) {
|
|
prompt("Record Private")
|
|
special(SPC_NOMOD)
|
|
interest(4)
|
|
extra("struct rpvtStruct *rpvt")
|
|
}
|
|
field(VAL,DBF_DOUBLE) {
|
|
prompt("Result")
|
|
promptgroup("50 - Output")
|
|
asl(ASL0)
|
|
}
|
|
field(PVAL,DBF_DOUBLE) {
|
|
prompt("Previous Value")
|
|
}
|
|
field(CALC,DBF_STRING) {
|
|
prompt("Calculation")
|
|
promptgroup("30 - Action")
|
|
special(SPC_CALC)
|
|
pp(TRUE)
|
|
size(80)
|
|
initial("0")
|
|
}
|
|
field(CLCV,DBF_LONG) {
|
|
prompt("CALC Valid")
|
|
interest(1)
|
|
}
|
|
field(INPA,DBF_INLINK) {
|
|
prompt("Input A")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPB,DBF_INLINK) {
|
|
prompt("Input B")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPC,DBF_INLINK) {
|
|
prompt("Input C")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPD,DBF_INLINK) {
|
|
prompt("Input D")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPE,DBF_INLINK) {
|
|
prompt("Input E")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPF,DBF_INLINK) {
|
|
prompt("Input F")
|
|
special(SPC_MOD)
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPG,DBF_INLINK) {
|
|
prompt("Input G")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPH,DBF_INLINK) {
|
|
prompt("Input H")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPI,DBF_INLINK) {
|
|
prompt("Input I")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPJ,DBF_INLINK) {
|
|
prompt("Input J")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPK,DBF_INLINK) {
|
|
prompt("Input K")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPL,DBF_INLINK) {
|
|
prompt("Input L")
|
|
special(SPC_MOD)
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(OUT,DBF_OUTLINK) {
|
|
prompt("Output Specification")
|
|
special(SPC_MOD)
|
|
promptgroup("50 - Output")
|
|
interest(1)
|
|
}
|
|
field(INAV,DBF_MENU) {
|
|
prompt("INPA PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INBV,DBF_MENU) {
|
|
prompt("INPB PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INCV,DBF_MENU) {
|
|
prompt("INPC PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INDV,DBF_MENU) {
|
|
prompt("INPD PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INEV,DBF_MENU) {
|
|
prompt("INPE PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INFV,DBF_MENU) {
|
|
prompt("INPF PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INGV,DBF_MENU) {
|
|
prompt("INPG PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INHV,DBF_MENU) {
|
|
prompt("INPH PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INIV,DBF_MENU) {
|
|
prompt("INPI PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INJV,DBF_MENU) {
|
|
prompt("INPJ PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INKV,DBF_MENU) {
|
|
prompt("INPK PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(INLV,DBF_MENU) {
|
|
prompt("INPL PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
initial("1")
|
|
}
|
|
field(OUTV,DBF_MENU) {
|
|
prompt("OUT PV Status")
|
|
special(SPC_NOMOD)
|
|
interest(1)
|
|
menu(calcoutINAV)
|
|
}
|
|
field(OOPT,DBF_MENU) {
|
|
prompt("Output Execute Opt")
|
|
promptgroup("50 - Output")
|
|
interest(1)
|
|
menu(calcoutOOPT)
|
|
}
|
|
field(ODLY,DBF_DOUBLE) {
|
|
prompt("Output Execute Delay")
|
|
promptgroup("50 - Output")
|
|
asl(ASL0)
|
|
interest(1)
|
|
}
|
|
field(DLYA,DBF_USHORT) {
|
|
prompt("Output Delay Active")
|
|
special(SPC_NOMOD)
|
|
asl(ASL0)
|
|
}
|
|
field(DOPT,DBF_MENU) {
|
|
prompt("Output Data Opt")
|
|
promptgroup("30 - Action")
|
|
interest(1)
|
|
menu(calcoutDOPT)
|
|
}
|
|
field(OCAL,DBF_STRING) {
|
|
prompt("Output Calculation")
|
|
promptgroup("30 - Action")
|
|
special(SPC_CALC)
|
|
pp(TRUE)
|
|
size(80)
|
|
initial("0")
|
|
}
|
|
field(OCLV,DBF_LONG) {
|
|
prompt("OCAL Valid")
|
|
interest(1)
|
|
}
|
|
field(OEVT,DBF_STRING) {
|
|
prompt("Event To Issue")
|
|
promptgroup("30 - Action")
|
|
special(SPC_MOD)
|
|
asl(ASL0)
|
|
size(40)
|
|
}
|
|
%#include "dbScan.h"
|
|
field(EPVT, DBF_NOACCESS) {
|
|
prompt("Event private")
|
|
special(SPC_NOMOD)
|
|
interest(4)
|
|
extra("EVENTPVT epvt")
|
|
}
|
|
field(IVOA,DBF_MENU) {
|
|
prompt("INVALID output action")
|
|
promptgroup("50 - Output")
|
|
interest(2)
|
|
menu(menuIvoa)
|
|
}
|
|
field(IVOV,DBF_DOUBLE) {
|
|
prompt("INVALID output value")
|
|
promptgroup("50 - Output")
|
|
interest(2)
|
|
}
|
|
field(EGU,DBF_STRING) {
|
|
prompt("Engineering Units")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
size(16)
|
|
prop(YES)
|
|
}
|
|
field(PREC,DBF_SHORT) {
|
|
prompt("Display Precision")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(HOPR,DBF_DOUBLE) {
|
|
prompt("High Operating Rng")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(LOPR,DBF_DOUBLE) {
|
|
prompt("Low Operating Range")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(HIHI,DBF_DOUBLE) {
|
|
prompt("Hihi Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(LOLO,DBF_DOUBLE) {
|
|
prompt("Lolo Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(HIGH,DBF_DOUBLE) {
|
|
prompt("High Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(LOW,DBF_DOUBLE) {
|
|
prompt("Low Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
}
|
|
field(HHSV,DBF_MENU) {
|
|
prompt("Hihi Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(LLSV,DBF_MENU) {
|
|
prompt("Lolo Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(HSV,DBF_MENU) {
|
|
prompt("High Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(LSV,DBF_MENU) {
|
|
prompt("Low Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES)
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(HYST,DBF_DOUBLE) {
|
|
prompt("Alarm Deadband")
|
|
promptgroup("70 - Alarm")
|
|
interest(1)
|
|
}
|
|
field(ADEL,DBF_DOUBLE) {
|
|
prompt("Archive Deadband")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
}
|
|
field(MDEL,DBF_DOUBLE) {
|
|
prompt("Monitor Deadband")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
}
|
|
field(A,DBF_DOUBLE) {
|
|
prompt("Value of Input A")
|
|
pp(TRUE)
|
|
}
|
|
field(B,DBF_DOUBLE) {
|
|
prompt("Value of Input B")
|
|
pp(TRUE)
|
|
}
|
|
field(C,DBF_DOUBLE) {
|
|
prompt("Value of Input C")
|
|
pp(TRUE)
|
|
}
|
|
field(D,DBF_DOUBLE) {
|
|
prompt("Value of Input D")
|
|
pp(TRUE)
|
|
}
|
|
field(E,DBF_DOUBLE) {
|
|
prompt("Value of Input E")
|
|
pp(TRUE)
|
|
}
|
|
field(F,DBF_DOUBLE) {
|
|
prompt("Value of Input F")
|
|
pp(TRUE)
|
|
}
|
|
field(G,DBF_DOUBLE) {
|
|
prompt("Value of Input G")
|
|
pp(TRUE)
|
|
}
|
|
field(H,DBF_DOUBLE) {
|
|
prompt("Value of Input H")
|
|
pp(TRUE)
|
|
}
|
|
field(I,DBF_DOUBLE) {
|
|
prompt("Value of Input I")
|
|
pp(TRUE)
|
|
}
|
|
field(J,DBF_DOUBLE) {
|
|
prompt("Value of Input J")
|
|
pp(TRUE)
|
|
}
|
|
field(K,DBF_DOUBLE) {
|
|
prompt("Value of Input K")
|
|
pp(TRUE)
|
|
}
|
|
field(L,DBF_DOUBLE) {
|
|
prompt("Value of Input L")
|
|
pp(TRUE)
|
|
}
|
|
field(OVAL,DBF_DOUBLE) {
|
|
prompt("Output Value")
|
|
asl(ASL0)
|
|
}
|
|
field(LA,DBF_DOUBLE) {
|
|
prompt("Prev Value of A")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LB,DBF_DOUBLE) {
|
|
prompt("Prev Value of B")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LC,DBF_DOUBLE) {
|
|
prompt("Prev Value of C")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LD,DBF_DOUBLE) {
|
|
prompt("Prev Value of D")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LE,DBF_DOUBLE) {
|
|
prompt("Prev Value of E")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LF,DBF_DOUBLE) {
|
|
prompt("Prev Value of F")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LG,DBF_DOUBLE) {
|
|
prompt("Prev Value of G")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LH,DBF_DOUBLE) {
|
|
prompt("Prev Value of H")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LI,DBF_DOUBLE) {
|
|
prompt("Prev Value of I")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LJ,DBF_DOUBLE) {
|
|
prompt("Prev Value of J")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LK,DBF_DOUBLE) {
|
|
prompt("Prev Value of K")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LL,DBF_DOUBLE) {
|
|
prompt("Prev Value of L")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(POVL,DBF_DOUBLE) {
|
|
prompt("Prev Value of OVAL")
|
|
asl(ASL0)
|
|
}
|
|
field(LALM,DBF_DOUBLE) {
|
|
prompt("Last Value Alarmed")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(ALST,DBF_DOUBLE) {
|
|
prompt("Last Value Archived")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(MLST,DBF_DOUBLE) {
|
|
prompt("Last Val Monitored")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
%#include "postfix.h"
|
|
field(RPCL,DBF_NOACCESS) {
|
|
prompt("Reverse Polish Calc")
|
|
special(SPC_NOMOD)
|
|
interest(4)
|
|
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
|
|
}
|
|
field(ORPC,DBF_NOACCESS) {
|
|
prompt("Reverse Polish OCalc")
|
|
special(SPC_NOMOD)
|
|
interest(4)
|
|
extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
|
|
}
|
|
|
|
=head2 Record Support
|
|
|
|
=head3 Record Support Routines
|
|
|
|
=head2 C<init_record>
|
|
|
|
For each constant input link, the corresponding value field is initialized
|
|
with the constant value if the input link is CONSTANT or a channel access
|
|
link is created if the input link is PV_LINK.
|
|
|
|
A routine postfix is called to convert the infix expression in CALC and
|
|
OCAL to Reverse Polish Notation. The result is stored in RPCL and ORPC,
|
|
respectively.
|
|
|
|
=head2 C<process>
|
|
|
|
See next section.
|
|
|
|
=head2 C<special>
|
|
|
|
This is called if CALC or OCAL is changed. C<special> calls postfix.
|
|
|
|
=head2 C<get_units>
|
|
|
|
Retrieves EGU.
|
|
|
|
=head2 C<get_precision>
|
|
|
|
Retrieves PREC.
|
|
|
|
=head2 C<get_graphic_double>
|
|
|
|
Sets the upper display and lower display limits for a field. If the field
|
|
is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else
|
|
if the field has upper and lower limits defined they will be used, else the
|
|
upper and lower maximum values for the field type will be used.
|
|
|
|
=head2 C<get_control_double>
|
|
|
|
Sets the upper control and lower control limits for a field. If the VAL,
|
|
HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the
|
|
field has upper and lower limits defined they will be used, else the upper
|
|
and lower maximum values for the field will be used.
|
|
|
|
=head2 C<get_alarm_double>
|
|
|
|
Sets the following values:
|
|
|
|
=over
|
|
|
|
upper_alarm_limit = HIHI
|
|
|
|
upper_warning_limit = HIGH
|
|
|
|
lower warning_limit = LOW
|
|
|
|
lower_alarm_limit = LOLO
|
|
|
|
=back
|
|
|
|
=head3 Record Processing
|
|
|
|
=head2 C<process()>
|
|
|
|
The C<process()> routine implements the following algorithm:
|
|
|
|
=over
|
|
|
|
=item 1.
|
|
Fetch all arguments.
|
|
|
|
=item 2.
|
|
Call routine C<calcPerform()>, which calculates VAL from the prefix version
|
|
of the expression given in CALC. If C<calcPerform()> returns success, UDF
|
|
is set to FALSE.
|
|
|
|
=item 3.
|
|
Check alarms. This routine checks to see if the new VAL causes the alarm
|
|
status and severity to change. If so, NSEV, NSTA and LALM are set. If also
|
|
honors the alarm hysteresis factor (HYST). Thus the value must change by at
|
|
least HYST before the alarm status and severity changes.
|
|
|
|
=item 4.
|
|
Determine if the Output Execution Option (OOPT) is met. If met, either
|
|
execute the output link (and output event) immediately (if ODLY = 0), or
|
|
schedule a callback after the specified interval. See the explanation for
|
|
the C<execOutput()> routine below.
|
|
|
|
=item 5.
|
|
Check to see if monitors should be invoked.
|
|
|
|
=over
|
|
|
|
=item *
|
|
Alarm monitors are invoked if the alarm status or severity has changed.
|
|
|
|
=item *
|
|
Archive and value change monitors are invoked if ADEL and MDEL conditions
|
|
are met.
|
|
|
|
=item *
|
|
Monitors for A-L are checked whenever other monitors are invoked.
|
|
|
|
=item *
|
|
NSEV and NSTA are reset to 0
|
|
|
|
=back
|
|
|
|
=item 6.
|
|
If no output delay was specified, scan forward link if necessary, set PACT
|
|
FALSE, and return.
|
|
|
|
=back
|
|
|
|
=head2 C<execOutput()>
|
|
|
|
=over
|
|
|
|
=item 1.
|
|
If DOPT field specifies the use of OCAL, call the routine C<calcPerform()>
|
|
for the postfix version of the expression in OCAL. Otherwise, use VAL.
|
|
|
|
=item 2.
|
|
If the Alarm Severity is INVALID, follow the option as designated by the
|
|
field IVOA.
|
|
|
|
=item 3.
|
|
The Alarm Severity is not INVALID or IVOA specifies "Continue Normally",
|
|
put the value of OVAL to the OUT link and post the event in OEVT (if
|
|
non-zero).
|
|
|
|
=item 4.
|
|
If an output delay was implemented, process the forward link.
|
|
|
|
=back
|
|
|
|
=cut
|
|
}
|
|
|
|
variable(calcoutODLYprecision, int)
|
|
variable(calcoutODLYlimit, double)
|