1126 lines
23 KiB
Plaintext
1126 lines
23 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 Record (calc)
|
|
|
|
The calculation or "Calc" record is used to perform algebraic, relational,
|
|
and logical operations on values retrieved from other records. The result
|
|
of its operations can then be accessed by another record so that it can
|
|
then be used.
|
|
|
|
Since 7.0.10 the number of inputs has been increased from 12 to 21.
|
|
|
|
=head2 Parameter Fields
|
|
|
|
The record-specific fields are described below, grouped by functionality.
|
|
|
|
=recordtype calc
|
|
|
|
=cut
|
|
|
|
recordtype(calc) {
|
|
|
|
=head3 Scan Parameters
|
|
|
|
The Calc record has the standard fields for specifying under what
|
|
circumstances the record will be processed.
|
|
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
|
|
|
|
=fields SCAN, PHAS, EVNT, PRIO, PINI
|
|
|
|
=head3 Read Parameters
|
|
|
|
The read parameters for the Calc record consist of 21 input links INPA -
|
|
INPU. The fields can be database links, channel access links, or constants.
|
|
If they are links, they must specify another record's field or a
|
|
channel access link. If they are constants, they will be initialized with
|
|
the value they are configured with and can be changed via C<dbPuts>. They
|
|
cannot be hardware addresses.
|
|
|
|
See L<Address
|
|
Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#address-specification>
|
|
for information on how to specify database links.
|
|
|
|
=fields INPA - INPU
|
|
|
|
=head3 Expression
|
|
|
|
At the core of the Calc record lies the CALC and RPCL fields.
|
|
The CALC field holds an infix expression to be evaluated whenever the record is
|
|
processed.
|
|
The calculated value is placed in the VAL field and can be accessed from there.
|
|
|
|
The CALC expression gets compiled into a stream of Reverse Polish Notation (RPN)
|
|
opcodes for a stack-based machine, and stored in the RPCL field.
|
|
The RPN opcodes are used to calculate VAL at run-time, and are more efficient
|
|
than evaluating the infix expression.
|
|
The CALC expression can be replaced at run-time, triggering a special record
|
|
routine to compile the new expression into 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 C<;>, any one of which may provide the calculation result.
|
|
All other expressions included in the string 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 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 operators, the assignment operator, parentheses
|
|
and commas, and the question mark colon or C<?:> operator.
|
|
|
|
=fields CALC, RPCL
|
|
|
|
=head3 Literals
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Standard double precision floating point numbers
|
|
|
|
=item *
|
|
C<Inf>: Infinity
|
|
|
|
=item *
|
|
C<NaN>: Not a Number
|
|
|
|
=back
|
|
|
|
=head3 Constants
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<PI>: returns the mathematical constant E<pi>
|
|
|
|
=item *
|
|
C<D2R>: evaluates to E<pi>/180 which, when used as a multiplier, converts an
|
|
angle from degrees to radians
|
|
|
|
=item *
|
|
C<R2D>: evaluates to 180/E<pi> which as a multiplier converts an angle from
|
|
radians to degrees
|
|
|
|
=back
|
|
|
|
=head3 Operands
|
|
|
|
The expression uses 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-U fields. The values to be used in the
|
|
expression are simply referenced by the field letter. For instance, the
|
|
value obtained from INPA link is stored in the field A, and the value
|
|
obtained from INPB is stored in field B. The field names can be included in
|
|
the expression which will operate on their respective values, as in A+B.
|
|
Also, the RNDM nullary function can be included as an operand in the
|
|
expression in order to generate a random number between 0 and 1.
|
|
|
|
=fields A - U
|
|
|
|
The keyword VAL returns the current contents of the VAL field (which can be
|
|
written to by a CA put, so it might I<not> be the result from the last time
|
|
the expression was evaluated).
|
|
|
|
=head3 Arithmetic Operators
|
|
|
|
Except for unary minus these are infix binary operators.
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<+> : Addition
|
|
|
|
=item *
|
|
C<-> : Subtraction
|
|
|
|
=item *
|
|
C<-> : Minus (unary)
|
|
|
|
=item *
|
|
C<*> : Multiplication
|
|
|
|
=item *
|
|
C</> : Division
|
|
|
|
=item *
|
|
C<%> : Modulo
|
|
|
|
=item *
|
|
C<^> : Exponential
|
|
|
|
=item *
|
|
C<**> : Exponential
|
|
|
|
=back
|
|
|
|
=head3 Algebraic Functions
|
|
|
|
When functions take more than one argument, a comma separator must appear
|
|
between them.
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<ABS (arg)> : Absolute value
|
|
|
|
=item *
|
|
C<EXP (arg)> : Exponential function
|
|
|
|
=item *
|
|
C<FMOD (num, den)> : Floating point modulo. Added in 7.0.8
|
|
|
|
=item *
|
|
C<LN (arg)> : Natural log
|
|
|
|
=item *
|
|
C<LOG (arg)> : Log base 10
|
|
|
|
=item *
|
|
C<LOGE (arg)> : Natural log
|
|
|
|
=item *
|
|
C<MIN (any number of args)> : Minimum
|
|
|
|
=item *
|
|
C<MAX (any number of args)> : Maximum
|
|
|
|
=item *
|
|
C<SQR (arg)> : Square root
|
|
|
|
=item *
|
|
C<SQRT (arg)> : Square root
|
|
|
|
=back
|
|
|
|
=head3 Trigonometric Functions
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<SIN (arg)> : Sine
|
|
|
|
=item *
|
|
C<ASIN (arg)> : Arc sine
|
|
|
|
=item *
|
|
C<COS (arg)> : Cosine
|
|
|
|
=item *
|
|
C<ACOS (arg)> : Arc cosine
|
|
|
|
=item *
|
|
C<TAN (arg)> : Tangent
|
|
|
|
=item *
|
|
C<ATAN (arg)> : Arc tangent
|
|
|
|
=item *
|
|
C<ATAN2 (den, num)> : 2-parameter Arc tangent. Arg's are reversed to ANSI C
|
|
|
|
=back
|
|
|
|
=head3 Hyperbolic Trigonometry Functions
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<SINH (arg)> : Hyperbolic sine
|
|
|
|
=item *
|
|
C<COSH (arg)> : Hyperbolic cosine
|
|
|
|
=item *
|
|
C<TANH (arg)> : Hyperbolic tangent
|
|
|
|
=back
|
|
|
|
=head3 Numeric Functions
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<CEIL (arg)> : Ceiling
|
|
|
|
=item *
|
|
C<FLOOR (arg)> : Floor
|
|
|
|
=item *
|
|
C<NINT (arg)> : Round to nearest integer
|
|
|
|
=item *
|
|
C<ISINF (arg)> : returns non-zero if any argument is Inf
|
|
|
|
=item *
|
|
C<ISNAN (any number of args)> : returns non-zero (true) if any argument is NaN
|
|
or Inf
|
|
|
|
=item *
|
|
C<FINITE (any number of args)> : returns non-zero (true) if none of the
|
|
arguments are NaN or Inf
|
|
|
|
=back
|
|
|
|
=head3 Boolean/Logical Operators
|
|
|
|
These operators use their arguments as a true (non-zero) or false (zero) value.
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<&&> : And, infix binary
|
|
|
|
=item *
|
|
C<||> : Or, infix binary
|
|
|
|
=item *
|
|
C<!> : Not, unary prefix
|
|
|
|
=back
|
|
|
|
=head3 Bitwise Operators
|
|
|
|
Mostly infix binary, the arguments are converted to a 32-bit integer, the
|
|
operator is applied, and the result converted back into a double.
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
C<&> : Bitwise and
|
|
|
|
=item *
|
|
C<|> : Bitwise or
|
|
|
|
=item *
|
|
C<~> : Bitwise not or one's complement, unary prefix
|
|
|
|
=item *
|
|
C<<< << >>> : Arithmetic shift left
|
|
|
|
=item *
|
|
C<<< >> >>> : Arithmetic shift right
|
|
|
|
=item *
|
|
C<<<< >>> >>>> : Logical shift right
|
|
|
|
=item *
|
|
C<AND> : Bitwise and
|
|
|
|
=item *
|
|
C<OR> : Bitwise or
|
|
|
|
=item *
|
|
C<XOR> : Bitwise exclusive or
|
|
|
|
=item *
|
|
C<NOT> : Bitwise not or one's complement, unary prefix
|
|
|
|
=back
|
|
|
|
=head3 Relational Operators
|
|
|
|
These are all infix binary 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<<< # >>> : Not equal to
|
|
|
|
=item *
|
|
C<<< == >>> : Equal to
|
|
|
|
=item *
|
|
C<<< = >>> : Equal to (not assignment)
|
|
|
|
=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 C<(> and close parentheses C<)> are supported to override precedence
|
|
rules in a sub-expression.
|
|
Nested parentheses are supported to significant depth.
|
|
|
|
The comma C<,> is required to separate the arguments of a function.
|
|
|
|
The semicolon C<;> is used to value separate expressions.
|
|
Exactly one value expression must be present, but multiple assignment
|
|
expressions may be included before and/or after the value expression.
|
|
|
|
=head3 Conditional Operator
|
|
|
|
The C language's question mark colon C<?:> ternary operator is supported.
|
|
The format is:
|
|
|
|
I<condition> C<?> I<true-expression> C<:> I<false-expression>
|
|
|
|
=head2 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 colon C<:> and the second (else)
|
|
part of the conditional, like this:
|
|
|
|
C<<< (A + B)<(C + D) ? E >>>
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Result is C<E> if C<<< (A + B)<(C + D) >>>
|
|
|
|
=item *
|
|
Result is unchanged if C<<< (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 A C<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 Operator Display Parameters
|
|
|
|
These parameters are used to present meaningful data to the operator. These
|
|
fields are used to display VAL and other parameters of the calculation
|
|
record either textually or graphically.
|
|
|
|
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.
|
|
|
|
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, NAME, DESC
|
|
|
|
=head3 Alarm Parameters
|
|
|
|
The possible alarm conditions for the Calc 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.
|
|
|
|
The AFTC field sets the time constant on a low-pass filter that delays the
|
|
reporting of limit alarms until the signal has been within the alarm range for
|
|
that number of seconds (the default AFTC value of zero retains the previous
|
|
behavior).
|
|
|
|
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/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, AFTC
|
|
|
|
=head3 Monitor Parameters
|
|
|
|
These paramaeters 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-LU fields are used to decide when to trigger monitors for the
|
|
corresponding fields. For instance, if LA does not equal the value 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 - LU
|
|
|
|
=cut
|
|
|
|
include "dbCommon.dbd"
|
|
field(VAL,DBF_DOUBLE) {
|
|
prompt("Result")
|
|
promptgroup("50 - Output")
|
|
asl(ASL0)
|
|
}
|
|
field(CALC,DBF_STRING) {
|
|
prompt("Calculation")
|
|
promptgroup("30 - Action")
|
|
special(SPC_CALC)
|
|
pp(TRUE)
|
|
size(160)
|
|
initial("0")
|
|
}
|
|
field(INPA,DBF_INLINK) {
|
|
prompt("Input A")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPB,DBF_INLINK) {
|
|
prompt("Input B")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPC,DBF_INLINK) {
|
|
prompt("Input C")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPD,DBF_INLINK) {
|
|
prompt("Input D")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPE,DBF_INLINK) {
|
|
prompt("Input E")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPF,DBF_INLINK) {
|
|
prompt("Input F")
|
|
promptgroup("41 - Input A-F")
|
|
interest(1)
|
|
}
|
|
field(INPG,DBF_INLINK) {
|
|
prompt("Input G")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPH,DBF_INLINK) {
|
|
prompt("Input H")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPI,DBF_INLINK) {
|
|
prompt("Input I")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPJ,DBF_INLINK) {
|
|
prompt("Input J")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPK,DBF_INLINK) {
|
|
prompt("Input K")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPL,DBF_INLINK) {
|
|
prompt("Input L")
|
|
promptgroup("42 - Input G-L")
|
|
interest(1)
|
|
}
|
|
field(INPM,DBF_INLINK) {
|
|
prompt("Input M")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPN,DBF_INLINK) {
|
|
prompt("Input N")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPO,DBF_INLINK) {
|
|
prompt("Input O")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPP,DBF_INLINK) {
|
|
prompt("Input P")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPQ,DBF_INLINK) {
|
|
prompt("Input Q")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPR,DBF_INLINK) {
|
|
prompt("Input R")
|
|
special(SPC_MOD)
|
|
promptgroup("43 - Input M-R")
|
|
interest(1)
|
|
}
|
|
field(INPS,DBF_INLINK) {
|
|
prompt("Input S")
|
|
special(SPC_MOD)
|
|
promptgroup("44 - Input S-U")
|
|
interest(1)
|
|
}
|
|
field(INPT,DBF_INLINK) {
|
|
prompt("Input T")
|
|
special(SPC_MOD)
|
|
promptgroup("44 - Input S-U")
|
|
interest(1)
|
|
}
|
|
field(INPU,DBF_INLINK) {
|
|
prompt("Input U")
|
|
special(SPC_MOD)
|
|
promptgroup("44 - Input S-U")
|
|
interest(1)
|
|
}
|
|
field(EGU,DBF_STRING) {
|
|
prompt("Engineering Units")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
size(16)
|
|
prop(YES) # get_units
|
|
}
|
|
field(PREC,DBF_SHORT) {
|
|
prompt("Display Precision")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES) # get_precision
|
|
}
|
|
field(HOPR,DBF_DOUBLE) {
|
|
prompt("High Operating Rng")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES) # get_graphic_dpuble, get_control_double
|
|
}
|
|
field(LOPR,DBF_DOUBLE) {
|
|
prompt("Low Operating Range")
|
|
promptgroup("80 - Display")
|
|
interest(1)
|
|
prop(YES) # get_graphic_dpuble, get_control_double
|
|
}
|
|
field(HIHI,DBF_DOUBLE) {
|
|
prompt("Hihi Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
}
|
|
field(LOLO,DBF_DOUBLE) {
|
|
prompt("Lolo Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
}
|
|
field(HIGH,DBF_DOUBLE) {
|
|
prompt("High Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
}
|
|
field(LOW,DBF_DOUBLE) {
|
|
prompt("Low Alarm Limit")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
}
|
|
field(HHSV,DBF_MENU) {
|
|
prompt("Hihi Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(LLSV,DBF_MENU) {
|
|
prompt("Lolo Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(HSV,DBF_MENU) {
|
|
prompt("High Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(LSV,DBF_MENU) {
|
|
prompt("Low Severity")
|
|
promptgroup("70 - Alarm")
|
|
pp(TRUE)
|
|
interest(1)
|
|
prop(YES) # get_alarm_double
|
|
menu(menuAlarmSevr)
|
|
}
|
|
field(AFTC, DBF_DOUBLE) {
|
|
prompt("Alarm Filter Time Constant")
|
|
promptgroup("70 - Alarm")
|
|
interest(1)
|
|
}
|
|
field(AFVL, DBF_DOUBLE) {
|
|
prompt("Alarm Filter Value")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
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(M,DBF_DOUBLE) {
|
|
prompt("Value of Input M")
|
|
pp(TRUE)
|
|
}
|
|
field(N,DBF_DOUBLE) {
|
|
prompt("Value of Input N")
|
|
pp(TRUE)
|
|
}
|
|
field(O,DBF_DOUBLE) {
|
|
prompt("Value of Input O")
|
|
pp(TRUE)
|
|
}
|
|
field(P,DBF_DOUBLE) {
|
|
prompt("Value of Input P")
|
|
pp(TRUE)
|
|
}
|
|
field(Q,DBF_DOUBLE) {
|
|
prompt("Value of Input Q")
|
|
pp(TRUE)
|
|
}
|
|
field(R,DBF_DOUBLE) {
|
|
prompt("Value of Input R")
|
|
pp(TRUE)
|
|
}
|
|
field(S,DBF_DOUBLE) {
|
|
prompt("Value of Input S")
|
|
pp(TRUE)
|
|
}
|
|
field(T,DBF_DOUBLE) {
|
|
prompt("Value of Input T")
|
|
pp(TRUE)
|
|
}
|
|
field(U,DBF_DOUBLE) {
|
|
prompt("Value of Input U")
|
|
pp(TRUE)
|
|
}
|
|
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(LM,DBF_DOUBLE) {
|
|
prompt("Prev Value of M")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LN,DBF_DOUBLE) {
|
|
prompt("Prev Value of N")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LO,DBF_DOUBLE) {
|
|
prompt("Prev Value of O")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LP,DBF_DOUBLE) {
|
|
prompt("Prev Value of P")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LQ,DBF_DOUBLE) {
|
|
prompt("Prev Value of Q")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LR,DBF_DOUBLE) {
|
|
prompt("Prev Value of R")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LS,DBF_DOUBLE) {
|
|
prompt("Prev Value of S")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LT,DBF_DOUBLE) {
|
|
prompt("Prev Value of T")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
field(LU,DBF_DOUBLE) {
|
|
prompt("Prev Value of U")
|
|
special(SPC_NOMOD)
|
|
interest(3)
|
|
}
|
|
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(160)]")
|
|
}
|
|
|
|
=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 a PV_LINK.
|
|
|
|
A routine postfix is called to convert the infix expression in CALC to
|
|
Reverse Polish Notation. The result is stored in RPCL.
|
|
|
|
=head2 C<process>
|
|
|
|
See next section.
|
|
|
|
=head2 C<special>
|
|
|
|
This is called if CALC 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 will be used.
|
|
|
|
=head2 C<get_control_double>
|
|
|
|
Sets the upper control and the lower control 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_alarm_double>
|
|
|
|
Sets the following values:
|
|
|
|
=over 1
|
|
|
|
upper_alarm_limit = HIHI
|
|
|
|
upper_warning_limit = HIGH
|
|
|
|
lower_warning_limit = LOW
|
|
|
|
lower_alarm_limit = LOLO
|
|
|
|
=back
|
|
|
|
=head3 Record Processing
|
|
|
|
Routine process implements the following algorithm:
|
|
|
|
=over 1
|
|
|
|
=item 1.
|
|
|
|
Fetch all arguments.
|
|
|
|
=item 2.
|
|
|
|
Call routine C<calcPerform>, which calculates VAL from the postfix 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. It 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.
|
|
|
|
Check to see if monitors should be invoked.
|
|
|
|
=over 1
|
|
|
|
=item *
|
|
Alarm monitors are invoked if the alarm status or severity has changed.
|
|
|
|
=item *
|
|
Archive and values change monitors are invoked if ADEL and MDEL conditions
|
|
are met.
|
|
|
|
=item *
|
|
Monitors for A-U are checked whenever other monitors are invoked.
|
|
|
|
=item *
|
|
NSEV and NSTA are reset to 0.
|
|
|
|
=back
|
|
|
|
=item 5.
|
|
|
|
Scan forward link if necessary, set PACT FALSE, and return.
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
}
|