<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki-ext.aps.anl.gov/epics/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=RalphLange</id>
	<title>EPICSWIKI - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-ext.aps.anl.gov/epics/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=RalphLange"/>
	<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Special:Contributions/RalphLange"/>
	<updated>2026-06-04T00:28:05Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.1</generator>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Calculation&amp;diff=3735</id>
		<title>RRM 3-13 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Calculation&amp;diff=3735"/>
		<updated>2014-06-19T15:16:50Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Operands */ RNDM unary -&amp;gt; nullary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-13|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-13 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-13 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (binary function)&lt;br /&gt;
* MAX: Maximum (binary function)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 (condition)? True result : False result&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-13 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-13 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-13 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-13 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=3734</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=3734"/>
		<updated>2014-06-19T15:09:07Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Operands */ RNDM unary -&amp;gt; nullary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 or '?:' operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete up-to-date description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Literals ====&lt;br /&gt;
&lt;br /&gt;
* Standard double precision floating point numbers&lt;br /&gt;
* Inf: Infinity&lt;br /&gt;
* Nan: Not a Number&lt;br /&gt;
&lt;br /&gt;
==== Constants ====&lt;br /&gt;
&lt;br /&gt;
* PI: returns the mathematical constant π&lt;br /&gt;
* D2R: evaluates to π/180 which, when used as a multiplier, converts an angle from degrees to radians&lt;br /&gt;
* R2D: evaluates to 180/π which as a multiplier converts an angle from radians to degrees&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword VAL returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* LN: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Assignment Operator ====&lt;br /&gt;
&lt;br /&gt;
* := : assigns a value (right hand side) to a variable (i.e. field)&lt;br /&gt;
&lt;br /&gt;
==== Parentheses, Comma, and Semicolon ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
The semicolon is used to separate expressions.  Although only one traditional calculation expression is allowed, multiple assignment expressions are allowed.&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
Prior to Base 3.14.9 it was legal to omit the : and the second (else) part of the conditional, like this:&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
From 3.14.9 onwards this expression must be rewritten as&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:VAL&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
==== Assignment ====&lt;br /&gt;
&lt;br /&gt;
 sin(a);&amp;amp;nbsp;a:=a+d2r&lt;br /&gt;
&lt;br /&gt;
* Causes the CALC record to output the successive values of a sine curve in 1 degree intervals&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3731</id>
		<title>How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3731"/>
		<updated>2014-04-02T08:18:32Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Fix RedHat script for Fedora/RHEL ifconfig variations&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== UDP Name Resolution: Broadcast vs. Unicast ==&lt;br /&gt;
&lt;br /&gt;
Running multiple IOCs on one host has an annoying side effect: Clients that are using that host's IP address in their EPICS_CA_ADDR_LIST with EPICS_CA_AUTO_ADDR_LIST=NO will only reach one of the IOCs - usually the one that was started last. All clients have to use broadcasts to reach all IOCs.&lt;br /&gt;
&lt;br /&gt;
The same is true for CA Gateway machines that are set up in a way that makes multiple Gateway processes serve channels into the same network.&lt;br /&gt;
&lt;br /&gt;
The reason is that the kernel delivers UDP broadcasts to ''all'' processes that are listening to the IP port, while UDP unicast messages will only be delivered to ''one'' of those processes.&lt;br /&gt;
&lt;br /&gt;
== Fix Using iptables ==&lt;br /&gt;
&lt;br /&gt;
Here's a little helper (for Linux hosts) that I recently was playing around with - based on an idea by Rodrigo Bongers (CNPEM, Brazil).&lt;br /&gt;
&lt;br /&gt;
If you drop the right script in the right place (depending on your Linux distribution, see further down), it will automatically create/delete an iptables rule that replaces the destination address of all incoming CA UDP traffic on each interface with the broadcast address of that interface.&lt;br /&gt;
&lt;br /&gt;
A simple and effective trick: the kernel will see all incoming name resolution requests as broadcasts, and delivers them to all IOCs instead of one.&lt;br /&gt;
&lt;br /&gt;
Note: This will not work for clients on the same host. (Adding that feature makes things a lot more complicated, and I like things to be simple.)&lt;br /&gt;
&lt;br /&gt;
If you need connections between IOCs on one host, I would suggest adding the broadcast address of the loopback interface (usually 127.255.255.255) to each IOC's EPICS_CA_ADDR_LIST setting.&lt;br /&gt;
&lt;br /&gt;
=== On Debian and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
Drop/link the following script into &amp;lt;tt&amp;gt;/etc/network/if-up.d/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/etc/network/if-down.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$METHOD&amp;quot; != &amp;quot;none&amp;quot; ] || exit 0&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet addr&amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet addr:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*Bcast:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$addr&amp;quot; -o -z &amp;quot;$bcast&amp;quot; ] &amp;amp;&amp;amp; return 1&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;start&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;stop&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== On RedHat and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
On systems using NetworkManager, drop the following script into &amp;lt;tt&amp;gt;/etc/NetworkManager/dispatcher.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
IFACE=$1&lt;br /&gt;
MODE=$2&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet &amp;quot;`&lt;br /&gt;
&lt;br /&gt;
# Fedora ifconfig output&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet \([0-9.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*broadcast \([0-9.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$addr&amp;quot; -o -z &amp;quot;$bcast&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    # RHEL ifconfig output&lt;br /&gt;
    addr=`echo $line | sed -e 's/.*inet addr:\([0-9.]*\).*/\1/'`&lt;br /&gt;
    bcast=`echo $line | sed -e 's/.*Bcast:\([0-9.]*\).*/\1/'`&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$addr&amp;quot; -o -z &amp;quot;$bcast&amp;quot; ] &amp;amp;&amp;amp; return 1&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;up&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;down&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Enjoy!&lt;br /&gt;
&lt;br /&gt;
[[User:RalphLange|Ralph]] 03:18, 2 April 2014 (CDT)&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Configure_Channel_Access&amp;diff=3730</id>
		<title>How to Configure Channel Access</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Configure_Channel_Access&amp;diff=3730"/>
		<updated>2014-04-01T09:38:38Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Add pointer to iptables trick.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Configure Channel Access =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Basic Operation, One IOC on same subnet ==&lt;br /&gt;
Assume an IOC has a record &amp;quot;fred&amp;quot;, and  you want to use &amp;quot;caget fred&amp;quot; or a similar CA client to read it.&lt;br /&gt;
&lt;br /&gt;
When starting out with one IOC on the network, things are simple:&lt;br /&gt;
&lt;br /&gt;
CA clients will by default broadcast name search requests to UDP port 5064 on the subnet.&lt;br /&gt;
As long as the IOC is running on on any computer on that subnet, it should receive those search requests. Server and client will then establish a TCP connection, and data is exchanged.&lt;br /&gt;
&lt;br /&gt;
== Multiple IOCs on different computers, but same subnet ==&lt;br /&gt;
If running multiple IOCs, each on their own computer, on the same subnet, the basic broadcast name search will still succeed, no change necessary.&lt;br /&gt;
&lt;br /&gt;
== IOCs on different subnets ==&lt;br /&gt;
The default broadcast name search is limited to the subnet of the computer running the CA client.&lt;br /&gt;
To reach IOCs on one or more additional subnets, the environment variable EPICS_CA_ADDR_LIST needs to be configured.&lt;br /&gt;
It can list either the specific IP addresses of each IOC, or the broadcast address of their subnet.&lt;br /&gt;
Note, however, that routers will often not forward broadcast requests, which suggests using specific IP addresses.&lt;br /&gt;
&lt;br /&gt;
== Multiple IOCs on the same computer ==&lt;br /&gt;
When starting the first IOC on a computer, it will listen to name searches on UDP port  5064.&lt;br /&gt;
When starting a second IOC on the same computer, it will also listen to name searches on UDP port  5064.&lt;br /&gt;
Due to limitations in most network kernels, however, only the IOC started ''last'' will actually receive UDP search requests that are sent to that computer, port 5064. As a workaround, you need to configure the EPICS_CA_ADDR_LIST to use the broadcast address of the respective subnet.&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can automatically set up iptables rules that will circumvent the problem. (See [[How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host]].)&lt;br /&gt;
&lt;br /&gt;
== Multiple IOCs on the same computer but on a different subnet ==&lt;br /&gt;
Combining the last two points results in a problem:&lt;br /&gt;
To reach multiple IOCs on the same computer, EPICS_CA_ADDR_LIST must be set to the broadcast address of that computer's subnet.&lt;br /&gt;
If the IOCs' subnet is different from the CA client's subnet however, the broadcast search packets will not usually be forwarded by the intermediate network routers.&lt;br /&gt;
&lt;br /&gt;
There are several options to solve this:&lt;br /&gt;
&lt;br /&gt;
=== Channel Access Gateway ===&lt;br /&gt;
The PV gateway, running on the subnet that has the desired IOCs, will use the broadcast address of that subnet in its EPICS_CA_ADDR_LIST, so it can reach all IOCs, including multiple IOCs running on the same computer, throughout that subnet.&lt;br /&gt;
A CA client on a different subnet uses only EPICS_CA_ADDR_LIST=ip-of-the-gateway to directly reach the gateway, which is possible via routers.&lt;br /&gt;
&lt;br /&gt;
In addition to establishing the basic connectivity, the gateway also offers IOC load reduction and it can add access security, for example limit write access.&lt;br /&gt;
&lt;br /&gt;
=== CA Nameserver ===&lt;br /&gt;
You can run a CA Name Server in the GUI subnet which knows about the IOCs and responds to search requests; in this case you would ''not'' set the EPICS_CA_ADDR_LIST variables. This is almost equivalent to running a CA Gateway, but is slightly more robust because if the Nameserver process dies it wouldn't kill any existing connections.&lt;br /&gt;
&lt;br /&gt;
=== UDP Broadcast Packet Relay ===&lt;br /&gt;
If you have access to a machine with a network interface on both subnets you can run a program on it called [https://www.joachim-breitner.de/udp-broadcast-relay/ UDP Broadcast Packet Relay] to forward UDP broadcast packets between the subnets. For best performance you should run it twice, once for port 5064 and again for 5065. The first one will forward CA search requests between the subnets, while the second redistributes CA beacons which help channels reconnect faster after an IOC has been turned off for some time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Firewalls ==&lt;br /&gt;
Firewalls may need to be configured to pass UDP and TCP traffic on both ports 5064 and 5065.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The [http://www.aps.anl.gov/epics/base/R3-14/12-docs/CAref.html Channel Access Reference Manual] provides a lot more detail.&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3729</id>
		<title>How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3729"/>
		<updated>2014-04-01T09:34:56Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== UDP Name Resolution: Broadcast vs. Unicast ==&lt;br /&gt;
&lt;br /&gt;
Running multiple IOCs on one host has an annoying side effect: Clients that are using that host's IP address in their EPICS_CA_ADDR_LIST with EPICS_CA_AUTO_ADDR_LIST=NO will only reach one of the IOCs - usually the one that was started last. All clients have to use broadcasts to reach all IOCs.&lt;br /&gt;
&lt;br /&gt;
The same is true for CA Gateway machines that are set up in a way that makes multiple Gateway processes serve channels into the same network.&lt;br /&gt;
&lt;br /&gt;
The reason is that the kernel delivers UDP broadcasts to ''all'' processes that are listening to the IP port, while UDP unicast messages will only be delivered to ''one'' of those processes.&lt;br /&gt;
&lt;br /&gt;
== Fix Using iptables ==&lt;br /&gt;
&lt;br /&gt;
Here's a little helper (for Linux hosts) that I recently was playing around with - based on an idea by Rodrigo Bongers (CNPEM, Brazil).&lt;br /&gt;
&lt;br /&gt;
If you drop the right script in the right place (depending on your Linux distribution, see further down), it will automatically create/delete an iptables rule that replaces the destination address of all incoming CA UDP traffic on each interface with the broadcast address of that interface.&lt;br /&gt;
&lt;br /&gt;
A simple and effective trick: the kernel will see all incoming name resolution requests as broadcasts, and delivers them to all IOCs instead of one.&lt;br /&gt;
&lt;br /&gt;
Note: This will not work for clients on the same host. (Adding that feature makes things a lot more complicated, and I like things to be simple.)&lt;br /&gt;
&lt;br /&gt;
If you need connections between IOCs on one host, I would suggest adding the broadcast address of the loopback interface (usually 127.255.255.255) to each IOC's EPICS_CA_ADDR_LIST setting.&lt;br /&gt;
&lt;br /&gt;
=== On Debian and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
Drop/link the following script into &amp;lt;tt&amp;gt;/etc/network/if-up.d/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/etc/network/if-down.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$METHOD&amp;quot; != &amp;quot;none&amp;quot; ] || exit 0&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet addr&amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet addr:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*Bcast:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;start&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;stop&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== On RedHat and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
On systems using NetworkManager, drop the following script into &amp;lt;tt&amp;gt;/etc/NetworkManager/dispatcher.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
IFACE=$1&lt;br /&gt;
MODE=$2&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet &amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet \([0-9.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*broadcast \([0-9.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;up&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;down&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Enjoy!&lt;br /&gt;
&lt;br /&gt;
[[User:RalphLange|Ralph]] 04:34, 1 April 2014 (CDT)&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3728</id>
		<title>How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3728"/>
		<updated>2014-04-01T09:27:10Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== UDP Name Resolution: Broadcast vs. Unicast ==&lt;br /&gt;
&lt;br /&gt;
Running multiple IOCs on one host has an annoying side effect: Clients that are using that host's IP address in their EPICS_CA_ADDR_LIST with EPICS_CA_AUTO_ADDR_LIST=NO will only reach one of the IOCs - usually the one that was started last. All clients have to use broadcasts to reach all IOCs.&lt;br /&gt;
&lt;br /&gt;
The same is true for CA Gateway machines that are set up in a way that makes multiple Gateway processes serve channels into the same network.&lt;br /&gt;
&lt;br /&gt;
The reason is that the kernel delivers UDP broadcasts to ''all'' processes that are listening to the IP port, while UDP unicast messages will only be delivered to ''one'' of those processes.&lt;br /&gt;
&lt;br /&gt;
== Fix Using iptables ==&lt;br /&gt;
&lt;br /&gt;
Here's a little helper (for Linux hosts) that I recently was playing around with - based on an idea by Rodrigo Bongers (CNPEM, Brazil).&lt;br /&gt;
&lt;br /&gt;
If you drop the right script in the right place (depending on your Linux distribution, see further down), it will automatically create/delete an iptables rule that replaces the destination address of all incoming CA UDP traffic on each interface with the broadcast address of that interface.&lt;br /&gt;
&lt;br /&gt;
A simple and effective trick: the kernel will see all incoming name resolution requests as broadcasts, and delivers them to all IOCs instead of one.&lt;br /&gt;
&lt;br /&gt;
Note: This will not work for clients on the same host. (Adding that feature makes things a lot more complicated, and I like things to be simple.)&lt;br /&gt;
&lt;br /&gt;
If you need connections between IOCs on one host, I would suggest adding the broadcast address of the loopback interface (usually 127.255.255.255) to each IOC's EPICS_CA_ADDR_LIST setting.&lt;br /&gt;
&lt;br /&gt;
=== On Debian and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
Drop/link the following script into &amp;lt;tt&amp;gt;/etc/network/if-up.d/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/etc/network/if-down.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$METHOD&amp;quot; != &amp;quot;none&amp;quot; ] || exit 0&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet addr&amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet addr:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*Bcast:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;start&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;stop&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== On RedHat and Derivatives ===&lt;br /&gt;
&lt;br /&gt;
On systems using NetworkManager, drop the following script into &amp;lt;tt&amp;gt;/etc/NetworkManager/dispatcher.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
IFACE=$1&lt;br /&gt;
MODE=$2&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet &amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet \([0-9.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*broadcast \([0-9.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;up&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;down&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3727</id>
		<title>How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_Make_Channel_Access_Reach_Multiple_Soft_IOCs_on_a_Linux_Host&amp;diff=3727"/>
		<updated>2014-04-01T09:26:12Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Created page with &amp;quot;= How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host =  == UDP Name Resolution: Broadcast vs. Unicast ==  Running multiple IOCs on one host has an annoying side ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host =&lt;br /&gt;
&lt;br /&gt;
== UDP Name Resolution: Broadcast vs. Unicast ==&lt;br /&gt;
&lt;br /&gt;
Running multiple IOCs on one host has an annoying side effect: Clients that are using that host's IP address in their EPICS_CA_ADDR_LIST with EPICS_CA_AUTO_ADDR_LIST=NO will only reach one of the IOCs - usually the one that was started last. All clients have to use broadcasts to reach all IOCs.&lt;br /&gt;
&lt;br /&gt;
The same is true for CA Gateway machines that are set up in a way that makes multiple Gateway processes serve channels into the same network.&lt;br /&gt;
&lt;br /&gt;
The reason is that the kernel delivers UDP broadcasts to ''all'' processes that are listening to the IP port, while UDP unicast messages will only be delivered to ''one'' of those processes.&lt;br /&gt;
&lt;br /&gt;
== Fix Using iptables ==&lt;br /&gt;
&lt;br /&gt;
Here's a little helper (for Linux hosts) that I recently was playing around with - based on an idea by Rodrigo Bongers (CNPEM, Brazil).&lt;br /&gt;
&lt;br /&gt;
If you drop the right script in the right place (depending on your Linux distribution, see further down), it will automatically create/delete an iptables rule that replaces the destination address of all incoming CA UDP traffic on each interface with the broadcast address of that interface.&lt;br /&gt;
&lt;br /&gt;
A simple and effective trick: the kernel will see all incoming name resolution requests as broadcasts, and delivers them to all IOCs instead of one.&lt;br /&gt;
&lt;br /&gt;
Note: This will not work for clients on the same host. (Adding that feature makes things a lot more complicated, and I like things to be simple.)&lt;br /&gt;
&lt;br /&gt;
If you need connections between IOCs on one host, I would suggest adding the broadcast address of the loopback interface (usually 127.255.255.255) to each IOC's EPICS_CA_ADDR_LIST setting.&lt;br /&gt;
&lt;br /&gt;
== Debian and Derivatives ==&lt;br /&gt;
&lt;br /&gt;
Drop/link the following script into &amp;lt;tt&amp;gt;/etc/network/if-up.d/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/etc/network/if-down.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$METHOD&amp;quot; != &amp;quot;none&amp;quot; ] || exit 0&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet addr&amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet addr:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*Bcast:\([0-9\.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;start&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;stop&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== RedHat and Derivatives ==&lt;br /&gt;
&lt;br /&gt;
On systems using NetworkManager, drop the following script into &amp;lt;tt&amp;gt;/etc/NetworkManager/dispatcher.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh -e&lt;br /&gt;
# Called when an interface goes up / down&lt;br /&gt;
&lt;br /&gt;
# Author: Ralph Lange &amp;lt;Ralph.Lange@gmx.de&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Make any incoming Channel Access name resolution queries go to the broadcast address&lt;br /&gt;
# (to hit all IOCs on this host)&lt;br /&gt;
&lt;br /&gt;
# Change this if you run CA on a non-standard port&lt;br /&gt;
PORT=5064&lt;br /&gt;
&lt;br /&gt;
IFACE=$1&lt;br /&gt;
MODE=$2&lt;br /&gt;
&lt;br /&gt;
[ &amp;quot;$IFACE&amp;quot; != &amp;quot;lo&amp;quot; ] || exit 0&lt;br /&gt;
&lt;br /&gt;
line=`ifconfig $IFACE | grep &amp;quot;inet &amp;quot;`&lt;br /&gt;
addr=`echo $line | sed -e 's/.*inet \([0-9.]*\).*/\1/'`&lt;br /&gt;
bcast=`echo $line | sed -e 's/.*broadcast \([0-9.]*\).*/\1/'`&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$MODE&amp;quot; = &amp;quot;up&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
elif [ &amp;quot;$MODE&amp;quot; = &amp;quot;down&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
    iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&amp;lt;/pre&amp;gt;&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=HowTo_Documents&amp;diff=3726</id>
		<title>HowTo Documents</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=HowTo_Documents&amp;diff=3726"/>
		<updated>2014-04-01T08:47:56Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Infrastructure and Other Stuff */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a directory of various How-To documents written by members of the EPICS collaboration.  Contributions to this page are most welcome!&lt;br /&gt;
&lt;br /&gt;
=== EPICS Base on Different Architectures and Operating Systems ===&lt;br /&gt;
&lt;br /&gt;
* [http://www.aps.anl.gov/epics/base/RTEMS/tutorial/ Getting Started with EPICS on RTEMS]&lt;br /&gt;
* [[HowToPC104|Getting Started with R3.14.7 on a PC104 running Linux]]&lt;br /&gt;
* [[How To Port EPICS to a new OS/Architecture]]&lt;br /&gt;
* [[How To Use Posix Thread Priority Scheduling under Linux]]&lt;br /&gt;
* [[How To cross compile EPICS and a IOC to an old x86 Linux system]]&lt;br /&gt;
* [http://prjemian.github.io/epicspi/ Installing EPICS on a Raspberry Pi]&lt;br /&gt;
&lt;br /&gt;
=== Drivers and Device Support ===&lt;br /&gt;
&lt;br /&gt;
* [http://www.aps.anl.gov/epics/modules/soft/asyn/HowToDoSerial_StreamDevice.html How To Do Serial (using Asyn Driver and StreamDevice)] (also covers VXI-11)&lt;br /&gt;
* [http://www.aps.anl.gov/epics/modules/soft/asyn/R4-15/HowToDoSerial/tutorial.pdf How To Do Serial (using Asyn Driver and devGPIB)]&lt;br /&gt;
* [[How to make your EPICS driver operating system independent]]&lt;br /&gt;
* [[How To Write Device Support that uses Asyn Driver]] ''(Incomplete!)''&lt;br /&gt;
* [[How to use GPIB ports with linux-gpib and StreamDevice]]&lt;br /&gt;
* [[How to avoid copying arrays with waveformRecord]]&lt;br /&gt;
&lt;br /&gt;
=== Applications ===&lt;br /&gt;
&lt;br /&gt;
* [[Common Database patterns]]&lt;br /&gt;
* [[How To Install Channel Archiver On Scientific Linux]]&lt;br /&gt;
* [[What PV Save and Restore Tools are available]]&lt;br /&gt;
* [[How to Add a New Breakpoint Table]]&lt;br /&gt;
* [[&amp;quot;Best Practice&amp;quot; Guidelines]]&lt;br /&gt;
* [[How do I get EPICS applications to work with a Mac OS X firewall?]]&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure and Other Stuff ===&lt;br /&gt;
&lt;br /&gt;
* [[How To Set Up a Linux Box as an IOC Boot Server]]&lt;br /&gt;
* [[How To Set Up a Mirror of the EPICS Web Site]]&lt;br /&gt;
* [[How to Set Up a Soft IOC Framework on Linux]]&lt;br /&gt;
* [[How to Configure Channel Access]]&lt;br /&gt;
* [[How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host]]&lt;br /&gt;
* [[How to Set Up Console Access and Logging for VME and Soft IOCs]]&lt;br /&gt;
* [[How to Set Up NAL (Nagios Alarm Handler) to monitor an EPICS network]]&lt;br /&gt;
&lt;br /&gt;
=== Collaboration Stuff ===&lt;br /&gt;
&lt;br /&gt;
* [[How to run an EPICS Collaboration Meeting]]&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=3706</id>
		<title>RRM 3-14 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=3706"/>
		<updated>2012-12-03T12:29:29Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: HOPR, LOPR fields FLOAT -&amp;gt; DOUBLE&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are six possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Median&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of every element of the array obtained from INP over time; that is, the entire array referenced by INP is retrieved, and for each element the new average is calculated and placed in the corresponding element of the value buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the buffer. Thus, VAL[0] holds the average of the first element of INP over N samples, VAL[1] holds the average of the next element of INP over N samples, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If any of the &amp;lt;CODE&amp;gt;N to 1&amp;lt;/CODE&amp;gt;algorithms are chosen, then VAL is a circular buffer of NSAM samples.&lt;br /&gt;
&lt;br /&gt;
The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (Lowest, Highest, or Average), is written to the circular buffer referenced by VAL. If &amp;lt;CODE&amp;gt;Low Value&amp;lt;/CODE&amp;gt; the lowest value of all the samples is written; if &amp;lt;CODE&amp;gt;High Value&amp;lt;/CODE&amp;gt; the highest value is written; and if &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;, the average of all the samples are written.  The &amp;lt;CODE&amp;gt;Median&amp;lt;/CODE&amp;gt; setting behaves like &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; with scalar input data.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Median&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the median value.&lt;br /&gt;
&lt;br /&gt;
The compression record keeps NSAM data samples.&lt;br /&gt;
&lt;br /&gt;
The field N determines the number of elements to compress into each result.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
IHIL and ILIL can be set to provide an initial value filter on the input array. If ILIL &amp;amp;lt; IHIL input elements will be skipped until a value is found that is in the range ILIL to IHIL.&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=3705</id>
		<title>RRM 3-14 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=3705"/>
		<updated>2012-12-03T12:28:47Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: IHIL, ILIL fields FLOAT -&amp;gt; DOUBLE&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are six possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Median&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of every element of the array obtained from INP over time; that is, the entire array referenced by INP is retrieved, and for each element the new average is calculated and placed in the corresponding element of the value buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the buffer. Thus, VAL[0] holds the average of the first element of INP over N samples, VAL[1] holds the average of the next element of INP over N samples, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If any of the &amp;lt;CODE&amp;gt;N to 1&amp;lt;/CODE&amp;gt;algorithms are chosen, then VAL is a circular buffer of NSAM samples.&lt;br /&gt;
&lt;br /&gt;
The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (Lowest, Highest, or Average), is written to the circular buffer referenced by VAL. If &amp;lt;CODE&amp;gt;Low Value&amp;lt;/CODE&amp;gt; the lowest value of all the samples is written; if &amp;lt;CODE&amp;gt;High Value&amp;lt;/CODE&amp;gt; the highest value is written; and if &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;, the average of all the samples are written.  The &amp;lt;CODE&amp;gt;Median&amp;lt;/CODE&amp;gt; setting behaves like &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; with scalar input data.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average value.&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Median&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the median value.&lt;br /&gt;
&lt;br /&gt;
The compression record keeps NSAM data samples.&lt;br /&gt;
&lt;br /&gt;
The field N determines the number of elements to compress into each result.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
IHIL and ILIL can be set to provide an initial value filter on the input array. If ILIL &amp;amp;lt; IHIL input elements will be skipped until a value is found that is in the range ILIL to IHIL.&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Conversion_Code_Clean-Up&amp;diff=2921</id>
		<title>Conversion Code Clean-Up</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Conversion_Code_Clean-Up&amp;diff=2921"/>
		<updated>2010-10-18T16:25:30Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: First version of Conversion Code Clean-Up description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Conversion Code Clean-Up ==&lt;br /&gt;
&lt;br /&gt;
=== Current Situation ===&lt;br /&gt;
&lt;br /&gt;
There are two codes for conversion, a full version in '''db/dbConvert.c''' and a &amp;quot;fast&amp;quot; version in '''db/dbFastLinkConv.c'''.&lt;br /&gt;
&lt;br /&gt;
Both contain the full matrix of conversions as a large set of almost identical C functions.&lt;br /&gt;
&lt;br /&gt;
=== Possible Improvements ===&lt;br /&gt;
&lt;br /&gt;
Using templated functions in C++ would greatly reduce the source code, still allowing for source level optimization by providing explicit instantiations for simple cases (e.g. same type).&lt;br /&gt;
&lt;br /&gt;
The new functions could also be changed to not use dbAddr as parameter (explicitly name the parts needed from dbAddr instead), so they can be used for non-V3-record applications.&lt;br /&gt;
&lt;br /&gt;
The array interface could be improved:&lt;br /&gt;
 * Start/End/Increment parameters would allow extracting sub arrays&lt;br /&gt;
 * Chunked array storage could be supported&lt;br /&gt;
&lt;br /&gt;
=== Approach ===&lt;br /&gt;
&lt;br /&gt;
First step should be adding test code that verifies all conversions, and takes performance numbers. That way the existing code could be tested for both function and performance.&lt;br /&gt;
&lt;br /&gt;
Then, the new conversion routines should be implemented, with simple wrappers that map the existing (array of function pointer) interfaces to use the new code.&lt;br /&gt;
&lt;br /&gt;
The test code should be used to verify and spec the new implementation.&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1890</id>
		<title>Future Development Ideas</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1890"/>
		<updated>2010-10-18T16:24:33Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Conversion Code Clean-Up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are projects that can/should be added to EPICS V3 using an evolutionary process.  The ordering is not necessarily accurate.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tasks which could be done now ==&lt;br /&gt;
&lt;br /&gt;
These items can be worked on immediately as they do not depend on any other work to have been completed, and could even be included in the next 3.14 release if appropriate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
Bugs tagged 'codeathon' are especially appropriate.&lt;br /&gt;
&lt;br /&gt;
=== Documentation (3.14/3.15) ===&lt;br /&gt;
&lt;br /&gt;
Lots we can do here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Record Reference Manual ====&lt;br /&gt;
&lt;br /&gt;
* Extend the DBD to HTML converter so we can move detailed record reference documentation into the record.dbd and/or record.c files.  Should we attempt to embed the RRM text inside the DBD files?&lt;br /&gt;
&lt;br /&gt;
==== Application Developers Guide ====&lt;br /&gt;
&lt;br /&gt;
* Write a &amp;quot;Building and Porting EPICS&amp;quot; chapter&lt;br /&gt;
* Restructure the AppDevGuide to make it more accessible&lt;br /&gt;
** Combine the libCom and libCom/osi chapters&lt;br /&gt;
** Maybe have a separate section for all callable APIs&lt;br /&gt;
** Consider moving API documentation into the appropriate source files and using Doxygen or perldoc to extract it.&lt;br /&gt;
&lt;br /&gt;
==== Other Documents ====&lt;br /&gt;
&lt;br /&gt;
* Look at all the documentation we have and see what's missing&lt;br /&gt;
* Data Access, other new CA-related documentation...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More test programs ===&lt;br /&gt;
&lt;br /&gt;
There are test programs in libCom/test which cover quite a lot of the libCom functionality, but they are by far from complete.  Writing test code is a very good way to learn the capabilities of the code being tested, and is not usually hard to to, so this would be a good &amp;quot;getting started&amp;quot; project.&lt;br /&gt;
&lt;br /&gt;
Check the Diamond code coverage report as part of their Base Autotests for ideas what code to tackle.&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&lt;br /&gt;
&lt;br /&gt;
=== IOC Test Framework in Perl ===&lt;br /&gt;
&lt;br /&gt;
Once we have good test coverage for libCom we should look at IOC-level testing, including tests for individual record types.  This needs code to start a soft IOC with a particular database file, make channel connections over CA and perform the necessary tests, then close down the IOC and clean up.  Tests should be automatable, e.g. by generating TAP output and run under the standard Perl Test::Harness, as used by the 'make runtests' target.&lt;br /&gt;
&lt;br /&gt;
Once the framework exists, write test programs for each core record type and device support.  Look at the Soft-Test suite and implement those tests too, although a complete rewrite might be appropriate for them...&lt;br /&gt;
&lt;br /&gt;
=== Convert makeBpt into Perl (3.15) ===&lt;br /&gt;
&lt;br /&gt;
The makeBpt tool in src/bpt generates non-linear break-point tables from data files.  A fair bit of the C code is concerned with parsing the input file.  There is no particular need for this code to be written in C, speed is not an issue, and eventually I hope to convert all programs needed for building EPICS into Perl code.  Maybe start this project by writing a program to test the output, then convert the C code into Perl.&lt;br /&gt;
&lt;br /&gt;
=== Database diagnostics ===&lt;br /&gt;
&lt;br /&gt;
When an IOC is too busy to service CA, the engineers need a way to find out what records are causing the problem.  Something like a dbSpy command might be helpful, which would keep a count of the records processed by each scan thread and give periodic reports.  Would need to be designed carefully so it doesn't eat RAM or slow down the machine too much.&lt;br /&gt;
&lt;br /&gt;
Other diagnostics could also be added: dbProcess rate, ...&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: db, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== Record aliases in VDCT ===&lt;br /&gt;
&lt;br /&gt;
EPICS Base R3.14.11 supports record aliases, but AFAIK VDCT does not (not sure about the new version of VDCT though).  Both preserving the aliases attached to a record loaded from a .db file, and providing creation and editing capabilities for them through the GUI.  This is a Java programming task which will need prior communication with CosyLab.&lt;br /&gt;
&lt;br /&gt;
=== Move alarm*.h headers ===&lt;br /&gt;
&lt;br /&gt;
A first step towards a more packagable build system would be to move the alarm.h and alarmString.h headers out of src/dbStatic; they are the only thing currently preventing src/catools and src/cap5 from being built immediately after src/ca.&lt;br /&gt;
&lt;br /&gt;
=== RSRV Using EPICS_CAS_INTF_ Variables ===&lt;br /&gt;
&lt;br /&gt;
Change the socket binding in rsrv to use the EPICS_CAS_INTF_ variable(s) so we can limit IOCs to a subset of the interfaces of the host it's running on.&lt;br /&gt;
&lt;br /&gt;
=== Packagable Build System ===&lt;br /&gt;
&lt;br /&gt;
The EPICS Build system currently does not distinguish between programs that are needed by IOC developers (e.g. dbToMenuH) and end-user programs (e.g. caget).  We could divide our build targets into these very easily, which would make packaging EPICS Base much more straight-forward.  I see the following parts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== End-user Binaries ====&lt;br /&gt;
&lt;br /&gt;
* catools&lt;br /&gt;
* Shared libraries&lt;br /&gt;
* SoftIoc (requires compiled-in DBD data though)&lt;br /&gt;
&lt;br /&gt;
These could be installed into /usr/local from an RPM or equivalent packaging system.&lt;br /&gt;
&lt;br /&gt;
==== Developer Tools ====&lt;br /&gt;
&lt;br /&gt;
* flex, antelope binaries etc.&lt;br /&gt;
* static libraries&lt;br /&gt;
* DBD and header files&lt;br /&gt;
* Build system components&lt;br /&gt;
&lt;br /&gt;
These could be packaged into a -devel RPM or equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extended Device Support (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Converting Asyn's device support layers to Extended support exposed the need to clean up the extended interface, i.e. reduce the code duplication which is currently required since the record knows nothing about the device change.&lt;br /&gt;
&lt;br /&gt;
Libs affected: db, rec.&lt;br /&gt;
&lt;br /&gt;
=== New Record Types ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add record types - valve record, improved control records for PID and Lead/Lag (if we had a good process control guy to design the record).&lt;br /&gt;
&lt;br /&gt;
Enhancements to PID should start from the most advanced implementation currently available, which is ''not'' the old PID record type from Base 3.13. There's a PID record in synApps, and there may be others available from other sites too.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: (external app)&lt;br /&gt;
&lt;br /&gt;
=== CA support for Array with Timebase ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add a new dbr_type into the channel access database - new array that includes time base and offset at least. One that also supports up to 3 dimensions (or better n).&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: Many...&lt;br /&gt;
&lt;br /&gt;
=== More flexible Access Security ===&lt;br /&gt;
&lt;br /&gt;
The AS design defines each field's security level in the record description, and limits us to only levels 0 and 1.  Some sites may want finer control over accesses: being able to put individual fields of a specific record into a different level, and having additional static levels (use a bitmask?) would help in a number of situations. It is not clear how much work this would entail though.&lt;br /&gt;
&lt;br /&gt;
Priority: Low&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, as, ...&lt;br /&gt;
&lt;br /&gt;
=== Authentication ===&lt;br /&gt;
&lt;br /&gt;
From Ralph: Two or three institutes need a way to password-protect access to certain databases. The usual encryption libraries are freely available, but I guess this issue needs a lot more thinking. Granularity: by record, by connection = IOC, or centralised? Should the authentication last for the client's lifetime or should a short form (some security token or key) be sent with every CA data package?&lt;br /&gt;
&lt;br /&gt;
=== Secure CA ===&lt;br /&gt;
&lt;br /&gt;
Secure channel access protocol - add SSL wrappers around CA to make it secure.&lt;br /&gt;
&lt;br /&gt;
The CA-over-TCP branch should form the basis of this work.&lt;br /&gt;
&lt;br /&gt;
Priority: R3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: ca, cas, rsrv&lt;br /&gt;
&lt;br /&gt;
=== Online Record Creation ===&lt;br /&gt;
&lt;br /&gt;
It might be possible to add new record instances at runtime, although delete would need a change to the record interface to support.  The tricky thing is to do this in a manner which is completely thread-safe since the pdbbase structure does not have many locks, and adding them could significantly affect operation of the IOC.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, misc&lt;br /&gt;
&lt;br /&gt;
=== Conversion Code Clean-Up ===&lt;br /&gt;
&lt;br /&gt;
The existing conversion routines (i.e. the fast and full versions in db) could be significantly cleaned up by using C++ templated functions. There would probably be minor savings in object code size, but major savings in terms of source code size and clarity.&lt;br /&gt;
&lt;br /&gt;
Here's a [[Conversion Code Clean-Up|more detailed description]] of how this could be done.&lt;br /&gt;
&lt;br /&gt;
Priority: 3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tasks which are already under way ==&lt;br /&gt;
&lt;br /&gt;
These tasks are already being worked on but may have stalled.  They might be hard for someone else to take over at this stage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CA Event Rate Limiting (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify a maximum event rate for each channel subscription it creates.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== CA Event Filtering (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify an event filter with the channel subscription which must be true for events to be posted to the client.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== Compiling DBD Files (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A Perl implementation of the DBD file parser exists and provides working dbdToRecordH and dbdToMenuH scripts. I'm working to revive my plans to convert all DBD file information into C tables that get compiled into the IOC executable or its shared libraries.&lt;br /&gt;
&lt;br /&gt;
With this parser written in Perl, it is much easier to add new facilities to DBD files, such as adding new field types (see Variable Length Strings below).&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbStatic, +dbHost, db.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Things which can't be completed yet ==&lt;br /&gt;
&lt;br /&gt;
These are tasks are waiting on other people or for other tasks to be completed before they can be finished, although there may be infrastructure to support them that can be worked on in parallel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IOCSH Command Registration (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Add DBD file syntax to convert DBD file information into a C header file which declares the command functions (similar to how we do record types in the current code-base).  This header would then be included by the C file that defines those functions, thus the C compiler would do the work of ensuring that the routine implemented actually matches the command that will call it.&lt;br /&gt;
&lt;br /&gt;
The command information in the DBD file will also be useful for future versions of the IRMIS parser for st.cmd scripts, where we need to be able to tie the device support configuration commands into IRMIS' need to map hardware devices to record addresses.&lt;br /&gt;
&lt;br /&gt;
This should be done in the compiled-dbd branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, all libs Registrar code.&lt;br /&gt;
&lt;br /&gt;
=== DBE_PROPERTY event generation (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Extend the DBD syntax to link all fields that contain property values with the fields that the property is supplied with, then have dbPut() post a DBE_PROPERTY monitor on those fields whenever the property value changes.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db&lt;br /&gt;
Waiting for: Perl DBD Processing&lt;br /&gt;
&lt;br /&gt;
=== Link Support (3.15+) ===&lt;br /&gt;
&lt;br /&gt;
See original proposal by ANJ, which needs to be modified to add notify interfaces.&lt;br /&gt;
&lt;br /&gt;
=== Array Field Support (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
Make it easier to add array fields to record types without having to do as much coding in the record support.  See [http://www.aps.anl.gov/epics/core-talk/2007/msg00078.php Ben Franksen email] and the work done by Nick Rees at the 2009 Codeathon.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, rec.&lt;br /&gt;
&lt;br /&gt;
=== Unbundling (3.15/++) ===&lt;br /&gt;
&lt;br /&gt;
Split Base into three or more independent modules.  Each module would have its own version number, and the modules can therefore each have an independent existance, although there would obviously be specific dependencies associated with particular versions.&lt;br /&gt;
&lt;br /&gt;
If we adopt this, we should bundle working subsets of modules together and release the complete bundle as a tarfile.&lt;br /&gt;
&lt;br /&gt;
I see the unbundled modules as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Nothing&lt;br /&gt;
&lt;br /&gt;
These are the common parts used by everything:&lt;br /&gt;
&lt;br /&gt;
* Build system&lt;br /&gt;
* libCom &amp;amp; OSI layer&lt;br /&gt;
** Basic registry routines&lt;br /&gt;
** IOC shell&lt;br /&gt;
* Antelope&lt;br /&gt;
* Flex&lt;br /&gt;
* makeApp tool&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Client ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CA-specific build rules (probably none)&lt;br /&gt;
* CA client library&lt;br /&gt;
* CA Tools&lt;br /&gt;
* CA application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Server ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, IOC, CAC?&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CAS-specific build rules (probably none)&lt;br /&gt;
* GDD&lt;br /&gt;
* The CAS server tool&lt;br /&gt;
* RSRV (the old CA server code)&lt;br /&gt;
* CAS application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== IOC ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, CAC, CAS&lt;br /&gt;
&lt;br /&gt;
The rest is code that runs on the IOC.&lt;br /&gt;
&lt;br /&gt;
* IOC-specific build rules&lt;br /&gt;
* Static and runtime database access&lt;br /&gt;
* Runtime database&lt;br /&gt;
* Standard record types&lt;br /&gt;
* Soft device support&lt;br /&gt;
* The registry (device, driver, record, function)&lt;br /&gt;
* IOC application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Variable Length Strings (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
3.15 already includes the BaseString C++ classes in libCom, a set of C wrapper routines is needed for the base class operations.  This can form the basis of a new variable length string type for use in the database in addition to DBF_STRING.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, ...&lt;br /&gt;
&lt;br /&gt;
=== Device Status String Field ===&lt;br /&gt;
&lt;br /&gt;
DESY want a string field in dbCommon for device support to post signal-specific status information to. Once we have variable-length string types it would be reasonable to add this (if not used/set it would only add one pointer to each record instance).&lt;br /&gt;
&lt;br /&gt;
=== Alternate DB File Formats (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
There are calls to replace the existing DB file format with an XML-based format.  Currently the DB file parser is too highly integrated into the process of record creation to easily add a second format, but it would be feasible to separate these two and hence allow an expat-based or similar parser to be written. This would probably require a close analysis and upgrade to the locking arrangements of the database.  Alternative to XML would be JSON, for which a parser is already being included in the jsonfm branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost?, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== New Record API ===&lt;br /&gt;
&lt;br /&gt;
These requests all need a significant change to the record support API.  They are also fairly closely related, so should be used as input into any new API that gets devised.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Gets (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be great if an input link could initiate processing, and get a value that is known to be the result of that processing, even if &lt;br /&gt;
records to be processed are asynchronous.  Currently, a record that needs completion-qualified data must know how to trigger the processing that generates that data.&lt;br /&gt;
&lt;br /&gt;
From Ben Franksen: Implemented an asyncronous dbGetLinkCallback() routine.  To do this properly though needs an upgrade to the record support API, but maybe could be shoe-horned into the the existing API by adding a dbGetLinkCallback() with a private callback pointer, and we'd require new record types to use this.  What does this do to the device support interface though?  Implications need study.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
==== Blocking Puts (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be nice to have a link attribute that could put, request processing, and wait for completion.  We have this capability now, in dbCaPutCallback(), but it's selectable only at DCT time.&lt;br /&gt;
&lt;br /&gt;
The idea is for a version of the SEQ record where rather than a fixed delay, the second link would wait for the completion callback from the first link.  This should be possible today with a special record type, but Tim suggests it should be possible with any link field of any record type.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple Master problem (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Jeff: Changes to output values in a PLC or similar device initiated outside of the output record. This could be resolved adding a new routine to the RSET that the device support calls back when it has a new raw ouptut value to back-propagate to the VAL field.  Currently done by some devices that set PACT and call the record's process() routine to use its second-half processing only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Records Can't Block (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: I think almost half the code in the sscan record is devoted to &lt;br /&gt;
bookmarking. In the middle of some algorithm, the record needs to wait for external events; the only way back in is process(), and so the record has to &lt;br /&gt;
have a complicated arrangement of switches that get it back into the &lt;br /&gt;
algorithm it was executing, with enough state information to decide what to do &lt;br /&gt;
next. At the same time, the record must check to see if it's now processing &lt;br /&gt;
because of some out-of-band request from the user.  Normal and exceptional processing must, therefore, be mixed together in the switch &lt;br /&gt;
arrangement, and adding new behaviors to the record becomes a very hairy undertaking.&lt;br /&gt;
&lt;br /&gt;
But what the record would really like to do is just wait with its &lt;br /&gt;
context intact for events, and allow special() to release it from the wait &lt;br /&gt;
if the user has requested something that requires this.  I guess this means the record should include author-defined event types in the wait mask, and special() should be able to generate author-defined events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamically Loaded Modules (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
After converting the DBD load process into table registration, it should become easier to allow support modules (containing record types, device support and other drivers) to be discovered and loaded dynamically.  Unloading is a very different matter though, we don't have the shutdown facilities to allow that.&lt;br /&gt;
&lt;br /&gt;
=== Atomic Operations through CA (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
This is related to the Asynch Gets issue above; implement Read-Write (Swap, permits semaphores), Process-Read and Write-Process-Read (Command/Response) as atomic operations available through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1879</id>
		<title>Future Development Ideas</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1879"/>
		<updated>2010-10-18T16:06:41Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Conversion Code Clean-Up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are projects that can/should be added to EPICS V3 using an evolutionary process.  The ordering is not necessarily accurate.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tasks which could be done now ==&lt;br /&gt;
&lt;br /&gt;
These items can be worked on immediately as they do not depend on any other work to have been completed, and could even be included in the next 3.14 release if appropriate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
Bugs tagged 'codeathon' are especially appropriate.&lt;br /&gt;
&lt;br /&gt;
=== Documentation (3.14/3.15) ===&lt;br /&gt;
&lt;br /&gt;
Lots we can do here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Record Reference Manual ====&lt;br /&gt;
&lt;br /&gt;
* Extend the DBD to HTML converter so we can move detailed record reference documentation into the record.dbd and/or record.c files.  Should we attempt to embed the RRM text inside the DBD files?&lt;br /&gt;
&lt;br /&gt;
==== Application Developers Guide ====&lt;br /&gt;
&lt;br /&gt;
* Write a &amp;quot;Building and Porting EPICS&amp;quot; chapter&lt;br /&gt;
* Restructure the AppDevGuide to make it more accessible&lt;br /&gt;
** Combine the libCom and libCom/osi chapters&lt;br /&gt;
** Maybe have a separate section for all callable APIs&lt;br /&gt;
** Consider moving API documentation into the appropriate source files and using Doxygen or perldoc to extract it.&lt;br /&gt;
&lt;br /&gt;
==== Other Documents ====&lt;br /&gt;
&lt;br /&gt;
* Look at all the documentation we have and see what's missing&lt;br /&gt;
* Data Access, other new CA-related documentation...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More test programs ===&lt;br /&gt;
&lt;br /&gt;
There are test programs in libCom/test which cover quite a lot of the libCom functionality, but they are by far from complete.  Writing test code is a very good way to learn the capabilities of the code being tested, and is not usually hard to to, so this would be a good &amp;quot;getting started&amp;quot; project.&lt;br /&gt;
&lt;br /&gt;
Check the Diamond code coverage report as part of their Base Autotests for ideas what code to tackle.&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&lt;br /&gt;
&lt;br /&gt;
=== IOC Test Framework in Perl ===&lt;br /&gt;
&lt;br /&gt;
Once we have good test coverage for libCom we should look at IOC-level testing, including tests for individual record types.  This needs code to start a soft IOC with a particular database file, make channel connections over CA and perform the necessary tests, then close down the IOC and clean up.  Tests should be automatable, e.g. by generating TAP output and run under the standard Perl Test::Harness, as used by the 'make runtests' target.&lt;br /&gt;
&lt;br /&gt;
Once the framework exists, write test programs for each core record type and device support.  Look at the Soft-Test suite and implement those tests too, although a complete rewrite might be appropriate for them...&lt;br /&gt;
&lt;br /&gt;
=== Convert makeBpt into Perl (3.15) ===&lt;br /&gt;
&lt;br /&gt;
The makeBpt tool in src/bpt generates non-linear break-point tables from data files.  A fair bit of the C code is concerned with parsing the input file.  There is no particular need for this code to be written in C, speed is not an issue, and eventually I hope to convert all programs needed for building EPICS into Perl code.  Maybe start this project by writing a program to test the output, then convert the C code into Perl.&lt;br /&gt;
&lt;br /&gt;
=== Database diagnostics ===&lt;br /&gt;
&lt;br /&gt;
When an IOC is too busy to service CA, the engineers need a way to find out what records are causing the problem.  Something like a dbSpy command might be helpful, which would keep a count of the records processed by each scan thread and give periodic reports.  Would need to be designed carefully so it doesn't eat RAM or slow down the machine too much.&lt;br /&gt;
&lt;br /&gt;
Other diagnostics could also be added: dbProcess rate, ...&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: db, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== Record aliases in VDCT ===&lt;br /&gt;
&lt;br /&gt;
EPICS Base R3.14.11 supports record aliases, but AFAIK VDCT does not (not sure about the new version of VDCT though).  Both preserving the aliases attached to a record loaded from a .db file, and providing creation and editing capabilities for them through the GUI.  This is a Java programming task which will need prior communication with CosyLab.&lt;br /&gt;
&lt;br /&gt;
=== Move alarm*.h headers ===&lt;br /&gt;
&lt;br /&gt;
A first step towards a more packagable build system would be to move the alarm.h and alarmString.h headers out of src/dbStatic; they are the only thing currently preventing src/catools and src/cap5 from being built immediately after src/ca.&lt;br /&gt;
&lt;br /&gt;
=== RSRV Using EPICS_CAS_INTF_ Variables ===&lt;br /&gt;
&lt;br /&gt;
Change the socket binding in rsrv to use the EPICS_CAS_INTF_ variable(s) so we can limit IOCs to a subset of the interfaces of the host it's running on.&lt;br /&gt;
&lt;br /&gt;
=== Packagable Build System ===&lt;br /&gt;
&lt;br /&gt;
The EPICS Build system currently does not distinguish between programs that are needed by IOC developers (e.g. dbToMenuH) and end-user programs (e.g. caget).  We could divide our build targets into these very easily, which would make packaging EPICS Base much more straight-forward.  I see the following parts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== End-user Binaries ====&lt;br /&gt;
&lt;br /&gt;
* catools&lt;br /&gt;
* Shared libraries&lt;br /&gt;
* SoftIoc (requires compiled-in DBD data though)&lt;br /&gt;
&lt;br /&gt;
These could be installed into /usr/local from an RPM or equivalent packaging system.&lt;br /&gt;
&lt;br /&gt;
==== Developer Tools ====&lt;br /&gt;
&lt;br /&gt;
* flex, antelope binaries etc.&lt;br /&gt;
* static libraries&lt;br /&gt;
* DBD and header files&lt;br /&gt;
* Build system components&lt;br /&gt;
&lt;br /&gt;
These could be packaged into a -devel RPM or equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extended Device Support (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Converting Asyn's device support layers to Extended support exposed the need to clean up the extended interface, i.e. reduce the code duplication which is currently required since the record knows nothing about the device change.&lt;br /&gt;
&lt;br /&gt;
Libs affected: db, rec.&lt;br /&gt;
&lt;br /&gt;
=== New Record Types ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add record types - valve record, improved control records for PID and Lead/Lag (if we had a good process control guy to design the record).&lt;br /&gt;
&lt;br /&gt;
Enhancements to PID should start from the most advanced implementation currently available, which is ''not'' the old PID record type from Base 3.13. There's a PID record in synApps, and there may be others available from other sites too.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: (external app)&lt;br /&gt;
&lt;br /&gt;
=== CA support for Array with Timebase ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add a new dbr_type into the channel access database - new array that includes time base and offset at least. One that also supports up to 3 dimensions (or better n).&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: Many...&lt;br /&gt;
&lt;br /&gt;
=== More flexible Access Security ===&lt;br /&gt;
&lt;br /&gt;
The AS design defines each field's security level in the record description, and limits us to only levels 0 and 1.  Some sites may want finer control over accesses: being able to put individual fields of a specific record into a different level, and having additional static levels (use a bitmask?) would help in a number of situations. It is not clear how much work this would entail though.&lt;br /&gt;
&lt;br /&gt;
Priority: Low&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, as, ...&lt;br /&gt;
&lt;br /&gt;
=== Authentication ===&lt;br /&gt;
&lt;br /&gt;
From Ralph: Two or three institutes need a way to password-protect access to certain databases. The usual encryption libraries are freely available, but I guess this issue needs a lot more thinking. Granularity: by record, by connection = IOC, or centralised? Should the authentication last for the client's lifetime or should a short form (some security token or key) be sent with every CA data package?&lt;br /&gt;
&lt;br /&gt;
=== Secure CA ===&lt;br /&gt;
&lt;br /&gt;
Secure channel access protocol - add SSL wrappers around CA to make it secure.&lt;br /&gt;
&lt;br /&gt;
The CA-over-TCP branch should form the basis of this work.&lt;br /&gt;
&lt;br /&gt;
Priority: R3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: ca, cas, rsrv&lt;br /&gt;
&lt;br /&gt;
=== Online Record Creation ===&lt;br /&gt;
&lt;br /&gt;
It might be possible to add new record instances at runtime, although delete would need a change to the record interface to support.  The tricky thing is to do this in a manner which is completely thread-safe since the pdbbase structure does not have many locks, and adding them could significantly affect operation of the IOC.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, misc&lt;br /&gt;
&lt;br /&gt;
=== Conversion Code Clean-Up ===&lt;br /&gt;
&lt;br /&gt;
The existing conversion routines (i.e. the fast and full versions in db) could be significantly cleaned up by using C++ templated functions. There would probably be minor savings in object code size, but major savings in terms of source code size and clarity.&lt;br /&gt;
&lt;br /&gt;
Here's a [[Conversion Code Clean-up|more detailed description]] of how this could be done.&lt;br /&gt;
&lt;br /&gt;
Priority: 3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tasks which are already under way ==&lt;br /&gt;
&lt;br /&gt;
These tasks are already being worked on but may have stalled.  They might be hard for someone else to take over at this stage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CA Event Rate Limiting (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify a maximum event rate for each channel subscription it creates.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== CA Event Filtering (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify an event filter with the channel subscription which must be true for events to be posted to the client.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== Compiling DBD Files (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A Perl implementation of the DBD file parser exists and provides working dbdToRecordH and dbdToMenuH scripts. I'm working to revive my plans to convert all DBD file information into C tables that get compiled into the IOC executable or its shared libraries.&lt;br /&gt;
&lt;br /&gt;
With this parser written in Perl, it is much easier to add new facilities to DBD files, such as adding new field types (see Variable Length Strings below).&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbStatic, +dbHost, db.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Things which can't be completed yet ==&lt;br /&gt;
&lt;br /&gt;
These are tasks are waiting on other people or for other tasks to be completed before they can be finished, although there may be infrastructure to support them that can be worked on in parallel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IOCSH Command Registration (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Add DBD file syntax to convert DBD file information into a C header file which declares the command functions (similar to how we do record types in the current code-base).  This header would then be included by the C file that defines those functions, thus the C compiler would do the work of ensuring that the routine implemented actually matches the command that will call it.&lt;br /&gt;
&lt;br /&gt;
The command information in the DBD file will also be useful for future versions of the IRMIS parser for st.cmd scripts, where we need to be able to tie the device support configuration commands into IRMIS' need to map hardware devices to record addresses.&lt;br /&gt;
&lt;br /&gt;
This should be done in the compiled-dbd branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, all libs Registrar code.&lt;br /&gt;
&lt;br /&gt;
=== DBE_PROPERTY event generation (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Extend the DBD syntax to link all fields that contain property values with the fields that the property is supplied with, then have dbPut() post a DBE_PROPERTY monitor on those fields whenever the property value changes.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db&lt;br /&gt;
Waiting for: Perl DBD Processing&lt;br /&gt;
&lt;br /&gt;
=== Link Support (3.15+) ===&lt;br /&gt;
&lt;br /&gt;
See original proposal by ANJ, which needs to be modified to add notify interfaces.&lt;br /&gt;
&lt;br /&gt;
=== Array Field Support (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
Make it easier to add array fields to record types without having to do as much coding in the record support.  See [http://www.aps.anl.gov/epics/core-talk/2007/msg00078.php Ben Franksen email] and the work done by Nick Rees at the 2009 Codeathon.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, rec.&lt;br /&gt;
&lt;br /&gt;
=== Unbundling (3.15/++) ===&lt;br /&gt;
&lt;br /&gt;
Split Base into three or more independent modules.  Each module would have its own version number, and the modules can therefore each have an independent existance, although there would obviously be specific dependencies associated with particular versions.&lt;br /&gt;
&lt;br /&gt;
If we adopt this, we should bundle working subsets of modules together and release the complete bundle as a tarfile.&lt;br /&gt;
&lt;br /&gt;
I see the unbundled modules as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Nothing&lt;br /&gt;
&lt;br /&gt;
These are the common parts used by everything:&lt;br /&gt;
&lt;br /&gt;
* Build system&lt;br /&gt;
* libCom &amp;amp; OSI layer&lt;br /&gt;
** Basic registry routines&lt;br /&gt;
** IOC shell&lt;br /&gt;
* Antelope&lt;br /&gt;
* Flex&lt;br /&gt;
* makeApp tool&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Client ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CA-specific build rules (probably none)&lt;br /&gt;
* CA client library&lt;br /&gt;
* CA Tools&lt;br /&gt;
* CA application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Server ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, IOC, CAC?&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CAS-specific build rules (probably none)&lt;br /&gt;
* GDD&lt;br /&gt;
* The CAS server tool&lt;br /&gt;
* RSRV (the old CA server code)&lt;br /&gt;
* CAS application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== IOC ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, CAC, CAS&lt;br /&gt;
&lt;br /&gt;
The rest is code that runs on the IOC.&lt;br /&gt;
&lt;br /&gt;
* IOC-specific build rules&lt;br /&gt;
* Static and runtime database access&lt;br /&gt;
* Runtime database&lt;br /&gt;
* Standard record types&lt;br /&gt;
* Soft device support&lt;br /&gt;
* The registry (device, driver, record, function)&lt;br /&gt;
* IOC application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Variable Length Strings (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
3.15 already includes the BaseString C++ classes in libCom, a set of C wrapper routines is needed for the base class operations.  This can form the basis of a new variable length string type for use in the database in addition to DBF_STRING.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, ...&lt;br /&gt;
&lt;br /&gt;
=== Device Status String Field ===&lt;br /&gt;
&lt;br /&gt;
DESY want a string field in dbCommon for device support to post signal-specific status information to. Once we have variable-length string types it would be reasonable to add this (if not used/set it would only add one pointer to each record instance).&lt;br /&gt;
&lt;br /&gt;
=== Alternate DB File Formats (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
There are calls to replace the existing DB file format with an XML-based format.  Currently the DB file parser is too highly integrated into the process of record creation to easily add a second format, but it would be feasible to separate these two and hence allow an expat-based or similar parser to be written. This would probably require a close analysis and upgrade to the locking arrangements of the database.  Alternative to XML would be JSON, for which a parser is already being included in the jsonfm branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost?, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== New Record API ===&lt;br /&gt;
&lt;br /&gt;
These requests all need a significant change to the record support API.  They are also fairly closely related, so should be used as input into any new API that gets devised.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Gets (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be great if an input link could initiate processing, and get a value that is known to be the result of that processing, even if &lt;br /&gt;
records to be processed are asynchronous.  Currently, a record that needs completion-qualified data must know how to trigger the processing that generates that data.&lt;br /&gt;
&lt;br /&gt;
From Ben Franksen: Implemented an asyncronous dbGetLinkCallback() routine.  To do this properly though needs an upgrade to the record support API, but maybe could be shoe-horned into the the existing API by adding a dbGetLinkCallback() with a private callback pointer, and we'd require new record types to use this.  What does this do to the device support interface though?  Implications need study.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
==== Blocking Puts (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be nice to have a link attribute that could put, request processing, and wait for completion.  We have this capability now, in dbCaPutCallback(), but it's selectable only at DCT time.&lt;br /&gt;
&lt;br /&gt;
The idea is for a version of the SEQ record where rather than a fixed delay, the second link would wait for the completion callback from the first link.  This should be possible today with a special record type, but Tim suggests it should be possible with any link field of any record type.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple Master problem (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Jeff: Changes to output values in a PLC or similar device initiated outside of the output record. This could be resolved adding a new routine to the RSET that the device support calls back when it has a new raw ouptut value to back-propagate to the VAL field.  Currently done by some devices that set PACT and call the record's process() routine to use its second-half processing only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Records Can't Block (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: I think almost half the code in the sscan record is devoted to &lt;br /&gt;
bookmarking. In the middle of some algorithm, the record needs to wait for external events; the only way back in is process(), and so the record has to &lt;br /&gt;
have a complicated arrangement of switches that get it back into the &lt;br /&gt;
algorithm it was executing, with enough state information to decide what to do &lt;br /&gt;
next. At the same time, the record must check to see if it's now processing &lt;br /&gt;
because of some out-of-band request from the user.  Normal and exceptional processing must, therefore, be mixed together in the switch &lt;br /&gt;
arrangement, and adding new behaviors to the record becomes a very hairy undertaking.&lt;br /&gt;
&lt;br /&gt;
But what the record would really like to do is just wait with its &lt;br /&gt;
context intact for events, and allow special() to release it from the wait &lt;br /&gt;
if the user has requested something that requires this.  I guess this means the record should include author-defined event types in the wait mask, and special() should be able to generate author-defined events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamically Loaded Modules (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
After converting the DBD load process into table registration, it should become easier to allow support modules (containing record types, device support and other drivers) to be discovered and loaded dynamically.  Unloading is a very different matter though, we don't have the shutdown facilities to allow that.&lt;br /&gt;
&lt;br /&gt;
=== Atomic Operations through CA (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
This is related to the Asynch Gets issue above; implement Read-Write (Swap, permits semaphores), Process-Read and Write-Process-Read (Command/Response) as atomic operations available through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1878</id>
		<title>Future Development Ideas</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1878"/>
		<updated>2010-10-18T16:05:35Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Conversion Code Clean-Up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are projects that can/should be added to EPICS V3 using an evolutionary process.  The ordering is not necessarily accurate.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tasks which could be done now ==&lt;br /&gt;
&lt;br /&gt;
These items can be worked on immediately as they do not depend on any other work to have been completed, and could even be included in the next 3.14 release if appropriate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
Bugs tagged 'codeathon' are especially appropriate.&lt;br /&gt;
&lt;br /&gt;
=== Documentation (3.14/3.15) ===&lt;br /&gt;
&lt;br /&gt;
Lots we can do here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Record Reference Manual ====&lt;br /&gt;
&lt;br /&gt;
* Extend the DBD to HTML converter so we can move detailed record reference documentation into the record.dbd and/or record.c files.  Should we attempt to embed the RRM text inside the DBD files?&lt;br /&gt;
&lt;br /&gt;
==== Application Developers Guide ====&lt;br /&gt;
&lt;br /&gt;
* Write a &amp;quot;Building and Porting EPICS&amp;quot; chapter&lt;br /&gt;
* Restructure the AppDevGuide to make it more accessible&lt;br /&gt;
** Combine the libCom and libCom/osi chapters&lt;br /&gt;
** Maybe have a separate section for all callable APIs&lt;br /&gt;
** Consider moving API documentation into the appropriate source files and using Doxygen or perldoc to extract it.&lt;br /&gt;
&lt;br /&gt;
==== Other Documents ====&lt;br /&gt;
&lt;br /&gt;
* Look at all the documentation we have and see what's missing&lt;br /&gt;
* Data Access, other new CA-related documentation...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More test programs ===&lt;br /&gt;
&lt;br /&gt;
There are test programs in libCom/test which cover quite a lot of the libCom functionality, but they are by far from complete.  Writing test code is a very good way to learn the capabilities of the code being tested, and is not usually hard to to, so this would be a good &amp;quot;getting started&amp;quot; project.&lt;br /&gt;
&lt;br /&gt;
Check the Diamond code coverage report as part of their Base Autotests for ideas what code to tackle.&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&lt;br /&gt;
&lt;br /&gt;
=== IOC Test Framework in Perl ===&lt;br /&gt;
&lt;br /&gt;
Once we have good test coverage for libCom we should look at IOC-level testing, including tests for individual record types.  This needs code to start a soft IOC with a particular database file, make channel connections over CA and perform the necessary tests, then close down the IOC and clean up.  Tests should be automatable, e.g. by generating TAP output and run under the standard Perl Test::Harness, as used by the 'make runtests' target.&lt;br /&gt;
&lt;br /&gt;
Once the framework exists, write test programs for each core record type and device support.  Look at the Soft-Test suite and implement those tests too, although a complete rewrite might be appropriate for them...&lt;br /&gt;
&lt;br /&gt;
=== Convert makeBpt into Perl (3.15) ===&lt;br /&gt;
&lt;br /&gt;
The makeBpt tool in src/bpt generates non-linear break-point tables from data files.  A fair bit of the C code is concerned with parsing the input file.  There is no particular need for this code to be written in C, speed is not an issue, and eventually I hope to convert all programs needed for building EPICS into Perl code.  Maybe start this project by writing a program to test the output, then convert the C code into Perl.&lt;br /&gt;
&lt;br /&gt;
=== Database diagnostics ===&lt;br /&gt;
&lt;br /&gt;
When an IOC is too busy to service CA, the engineers need a way to find out what records are causing the problem.  Something like a dbSpy command might be helpful, which would keep a count of the records processed by each scan thread and give periodic reports.  Would need to be designed carefully so it doesn't eat RAM or slow down the machine too much.&lt;br /&gt;
&lt;br /&gt;
Other diagnostics could also be added: dbProcess rate, ...&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: db, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== Record aliases in VDCT ===&lt;br /&gt;
&lt;br /&gt;
EPICS Base R3.14.11 supports record aliases, but AFAIK VDCT does not (not sure about the new version of VDCT though).  Both preserving the aliases attached to a record loaded from a .db file, and providing creation and editing capabilities for them through the GUI.  This is a Java programming task which will need prior communication with CosyLab.&lt;br /&gt;
&lt;br /&gt;
=== Move alarm*.h headers ===&lt;br /&gt;
&lt;br /&gt;
A first step towards a more packagable build system would be to move the alarm.h and alarmString.h headers out of src/dbStatic; they are the only thing currently preventing src/catools and src/cap5 from being built immediately after src/ca.&lt;br /&gt;
&lt;br /&gt;
=== RSRV Using EPICS_CAS_INTF_ Variables ===&lt;br /&gt;
&lt;br /&gt;
Change the socket binding in rsrv to use the EPICS_CAS_INTF_ variable(s) so we can limit IOCs to a subset of the interfaces of the host it's running on.&lt;br /&gt;
&lt;br /&gt;
=== Packagable Build System ===&lt;br /&gt;
&lt;br /&gt;
The EPICS Build system currently does not distinguish between programs that are needed by IOC developers (e.g. dbToMenuH) and end-user programs (e.g. caget).  We could divide our build targets into these very easily, which would make packaging EPICS Base much more straight-forward.  I see the following parts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== End-user Binaries ====&lt;br /&gt;
&lt;br /&gt;
* catools&lt;br /&gt;
* Shared libraries&lt;br /&gt;
* SoftIoc (requires compiled-in DBD data though)&lt;br /&gt;
&lt;br /&gt;
These could be installed into /usr/local from an RPM or equivalent packaging system.&lt;br /&gt;
&lt;br /&gt;
==== Developer Tools ====&lt;br /&gt;
&lt;br /&gt;
* flex, antelope binaries etc.&lt;br /&gt;
* static libraries&lt;br /&gt;
* DBD and header files&lt;br /&gt;
* Build system components&lt;br /&gt;
&lt;br /&gt;
These could be packaged into a -devel RPM or equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extended Device Support (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Converting Asyn's device support layers to Extended support exposed the need to clean up the extended interface, i.e. reduce the code duplication which is currently required since the record knows nothing about the device change.&lt;br /&gt;
&lt;br /&gt;
Libs affected: db, rec.&lt;br /&gt;
&lt;br /&gt;
=== New Record Types ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add record types - valve record, improved control records for PID and Lead/Lag (if we had a good process control guy to design the record).&lt;br /&gt;
&lt;br /&gt;
Enhancements to PID should start from the most advanced implementation currently available, which is ''not'' the old PID record type from Base 3.13. There's a PID record in synApps, and there may be others available from other sites too.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: (external app)&lt;br /&gt;
&lt;br /&gt;
=== CA support for Array with Timebase ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add a new dbr_type into the channel access database - new array that includes time base and offset at least. One that also supports up to 3 dimensions (or better n).&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: Many...&lt;br /&gt;
&lt;br /&gt;
=== More flexible Access Security ===&lt;br /&gt;
&lt;br /&gt;
The AS design defines each field's security level in the record description, and limits us to only levels 0 and 1.  Some sites may want finer control over accesses: being able to put individual fields of a specific record into a different level, and having additional static levels (use a bitmask?) would help in a number of situations. It is not clear how much work this would entail though.&lt;br /&gt;
&lt;br /&gt;
Priority: Low&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, as, ...&lt;br /&gt;
&lt;br /&gt;
=== Authentication ===&lt;br /&gt;
&lt;br /&gt;
From Ralph: Two or three institutes need a way to password-protect access to certain databases. The usual encryption libraries are freely available, but I guess this issue needs a lot more thinking. Granularity: by record, by connection = IOC, or centralised? Should the authentication last for the client's lifetime or should a short form (some security token or key) be sent with every CA data package?&lt;br /&gt;
&lt;br /&gt;
=== Secure CA ===&lt;br /&gt;
&lt;br /&gt;
Secure channel access protocol - add SSL wrappers around CA to make it secure.&lt;br /&gt;
&lt;br /&gt;
The CA-over-TCP branch should form the basis of this work.&lt;br /&gt;
&lt;br /&gt;
Priority: R3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: ca, cas, rsrv&lt;br /&gt;
&lt;br /&gt;
=== Online Record Creation ===&lt;br /&gt;
&lt;br /&gt;
It might be possible to add new record instances at runtime, although delete would need a change to the record interface to support.  The tricky thing is to do this in a manner which is completely thread-safe since the pdbbase structure does not have many locks, and adding them could significantly affect operation of the IOC.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, misc&lt;br /&gt;
&lt;br /&gt;
=== Conversion Code Clean-Up ===&lt;br /&gt;
&lt;br /&gt;
The existing conversion routines (i.e. the fast and full versions in db) could be significantly cleaned up by using C++ templated functions. There would probably be minor savings in object code size, but major savings in terms of source code size and clarity.&lt;br /&gt;
&lt;br /&gt;
Here's a [[conversion code clean-up|more detailed description]] of how this could be done.&lt;br /&gt;
&lt;br /&gt;
Priority: 3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tasks which are already under way ==&lt;br /&gt;
&lt;br /&gt;
These tasks are already being worked on but may have stalled.  They might be hard for someone else to take over at this stage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CA Event Rate Limiting (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify a maximum event rate for each channel subscription it creates.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== CA Event Filtering (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify an event filter with the channel subscription which must be true for events to be posted to the client.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== Compiling DBD Files (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A Perl implementation of the DBD file parser exists and provides working dbdToRecordH and dbdToMenuH scripts. I'm working to revive my plans to convert all DBD file information into C tables that get compiled into the IOC executable or its shared libraries.&lt;br /&gt;
&lt;br /&gt;
With this parser written in Perl, it is much easier to add new facilities to DBD files, such as adding new field types (see Variable Length Strings below).&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbStatic, +dbHost, db.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Things which can't be completed yet ==&lt;br /&gt;
&lt;br /&gt;
These are tasks are waiting on other people or for other tasks to be completed before they can be finished, although there may be infrastructure to support them that can be worked on in parallel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IOCSH Command Registration (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Add DBD file syntax to convert DBD file information into a C header file which declares the command functions (similar to how we do record types in the current code-base).  This header would then be included by the C file that defines those functions, thus the C compiler would do the work of ensuring that the routine implemented actually matches the command that will call it.&lt;br /&gt;
&lt;br /&gt;
The command information in the DBD file will also be useful for future versions of the IRMIS parser for st.cmd scripts, where we need to be able to tie the device support configuration commands into IRMIS' need to map hardware devices to record addresses.&lt;br /&gt;
&lt;br /&gt;
This should be done in the compiled-dbd branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, all libs Registrar code.&lt;br /&gt;
&lt;br /&gt;
=== DBE_PROPERTY event generation (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Extend the DBD syntax to link all fields that contain property values with the fields that the property is supplied with, then have dbPut() post a DBE_PROPERTY monitor on those fields whenever the property value changes.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db&lt;br /&gt;
Waiting for: Perl DBD Processing&lt;br /&gt;
&lt;br /&gt;
=== Link Support (3.15+) ===&lt;br /&gt;
&lt;br /&gt;
See original proposal by ANJ, which needs to be modified to add notify interfaces.&lt;br /&gt;
&lt;br /&gt;
=== Array Field Support (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
Make it easier to add array fields to record types without having to do as much coding in the record support.  See [http://www.aps.anl.gov/epics/core-talk/2007/msg00078.php Ben Franksen email] and the work done by Nick Rees at the 2009 Codeathon.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, rec.&lt;br /&gt;
&lt;br /&gt;
=== Unbundling (3.15/++) ===&lt;br /&gt;
&lt;br /&gt;
Split Base into three or more independent modules.  Each module would have its own version number, and the modules can therefore each have an independent existance, although there would obviously be specific dependencies associated with particular versions.&lt;br /&gt;
&lt;br /&gt;
If we adopt this, we should bundle working subsets of modules together and release the complete bundle as a tarfile.&lt;br /&gt;
&lt;br /&gt;
I see the unbundled modules as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Nothing&lt;br /&gt;
&lt;br /&gt;
These are the common parts used by everything:&lt;br /&gt;
&lt;br /&gt;
* Build system&lt;br /&gt;
* libCom &amp;amp; OSI layer&lt;br /&gt;
** Basic registry routines&lt;br /&gt;
** IOC shell&lt;br /&gt;
* Antelope&lt;br /&gt;
* Flex&lt;br /&gt;
* makeApp tool&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Client ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CA-specific build rules (probably none)&lt;br /&gt;
* CA client library&lt;br /&gt;
* CA Tools&lt;br /&gt;
* CA application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Server ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, IOC, CAC?&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CAS-specific build rules (probably none)&lt;br /&gt;
* GDD&lt;br /&gt;
* The CAS server tool&lt;br /&gt;
* RSRV (the old CA server code)&lt;br /&gt;
* CAS application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== IOC ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, CAC, CAS&lt;br /&gt;
&lt;br /&gt;
The rest is code that runs on the IOC.&lt;br /&gt;
&lt;br /&gt;
* IOC-specific build rules&lt;br /&gt;
* Static and runtime database access&lt;br /&gt;
* Runtime database&lt;br /&gt;
* Standard record types&lt;br /&gt;
* Soft device support&lt;br /&gt;
* The registry (device, driver, record, function)&lt;br /&gt;
* IOC application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Variable Length Strings (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
3.15 already includes the BaseString C++ classes in libCom, a set of C wrapper routines is needed for the base class operations.  This can form the basis of a new variable length string type for use in the database in addition to DBF_STRING.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, ...&lt;br /&gt;
&lt;br /&gt;
=== Device Status String Field ===&lt;br /&gt;
&lt;br /&gt;
DESY want a string field in dbCommon for device support to post signal-specific status information to. Once we have variable-length string types it would be reasonable to add this (if not used/set it would only add one pointer to each record instance).&lt;br /&gt;
&lt;br /&gt;
=== Alternate DB File Formats (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
There are calls to replace the existing DB file format with an XML-based format.  Currently the DB file parser is too highly integrated into the process of record creation to easily add a second format, but it would be feasible to separate these two and hence allow an expat-based or similar parser to be written. This would probably require a close analysis and upgrade to the locking arrangements of the database.  Alternative to XML would be JSON, for which a parser is already being included in the jsonfm branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost?, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== New Record API ===&lt;br /&gt;
&lt;br /&gt;
These requests all need a significant change to the record support API.  They are also fairly closely related, so should be used as input into any new API that gets devised.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Gets (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be great if an input link could initiate processing, and get a value that is known to be the result of that processing, even if &lt;br /&gt;
records to be processed are asynchronous.  Currently, a record that needs completion-qualified data must know how to trigger the processing that generates that data.&lt;br /&gt;
&lt;br /&gt;
From Ben Franksen: Implemented an asyncronous dbGetLinkCallback() routine.  To do this properly though needs an upgrade to the record support API, but maybe could be shoe-horned into the the existing API by adding a dbGetLinkCallback() with a private callback pointer, and we'd require new record types to use this.  What does this do to the device support interface though?  Implications need study.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
==== Blocking Puts (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be nice to have a link attribute that could put, request processing, and wait for completion.  We have this capability now, in dbCaPutCallback(), but it's selectable only at DCT time.&lt;br /&gt;
&lt;br /&gt;
The idea is for a version of the SEQ record where rather than a fixed delay, the second link would wait for the completion callback from the first link.  This should be possible today with a special record type, but Tim suggests it should be possible with any link field of any record type.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple Master problem (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Jeff: Changes to output values in a PLC or similar device initiated outside of the output record. This could be resolved adding a new routine to the RSET that the device support calls back when it has a new raw ouptut value to back-propagate to the VAL field.  Currently done by some devices that set PACT and call the record's process() routine to use its second-half processing only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Records Can't Block (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: I think almost half the code in the sscan record is devoted to &lt;br /&gt;
bookmarking. In the middle of some algorithm, the record needs to wait for external events; the only way back in is process(), and so the record has to &lt;br /&gt;
have a complicated arrangement of switches that get it back into the &lt;br /&gt;
algorithm it was executing, with enough state information to decide what to do &lt;br /&gt;
next. At the same time, the record must check to see if it's now processing &lt;br /&gt;
because of some out-of-band request from the user.  Normal and exceptional processing must, therefore, be mixed together in the switch &lt;br /&gt;
arrangement, and adding new behaviors to the record becomes a very hairy undertaking.&lt;br /&gt;
&lt;br /&gt;
But what the record would really like to do is just wait with its &lt;br /&gt;
context intact for events, and allow special() to release it from the wait &lt;br /&gt;
if the user has requested something that requires this.  I guess this means the record should include author-defined event types in the wait mask, and special() should be able to generate author-defined events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamically Loaded Modules (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
After converting the DBD load process into table registration, it should become easier to allow support modules (containing record types, device support and other drivers) to be discovered and loaded dynamically.  Unloading is a very different matter though, we don't have the shutdown facilities to allow that.&lt;br /&gt;
&lt;br /&gt;
=== Atomic Operations through CA (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
This is related to the Asynch Gets issue above; implement Read-Write (Swap, permits semaphores), Process-Read and Write-Process-Read (Command/Response) as atomic operations available through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1877</id>
		<title>Future Development Ideas</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Future_Development_Ideas&amp;diff=1877"/>
		<updated>2010-10-18T16:01:12Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Tasks which could be done now */ add conversion code clean-up&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are projects that can/should be added to EPICS V3 using an evolutionary process.  The ordering is not necessarily accurate.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tasks which could be done now ==&lt;br /&gt;
&lt;br /&gt;
These items can be worked on immediately as they do not depend on any other work to have been completed, and could even be included in the next 3.14 release if appropriate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
Bugs tagged 'codeathon' are especially appropriate.&lt;br /&gt;
&lt;br /&gt;
=== Documentation (3.14/3.15) ===&lt;br /&gt;
&lt;br /&gt;
Lots we can do here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Record Reference Manual ====&lt;br /&gt;
&lt;br /&gt;
* Extend the DBD to HTML converter so we can move detailed record reference documentation into the record.dbd and/or record.c files.  Should we attempt to embed the RRM text inside the DBD files?&lt;br /&gt;
&lt;br /&gt;
==== Application Developers Guide ====&lt;br /&gt;
&lt;br /&gt;
* Write a &amp;quot;Building and Porting EPICS&amp;quot; chapter&lt;br /&gt;
* Restructure the AppDevGuide to make it more accessible&lt;br /&gt;
** Combine the libCom and libCom/osi chapters&lt;br /&gt;
** Maybe have a separate section for all callable APIs&lt;br /&gt;
** Consider moving API documentation into the appropriate source files and using Doxygen or perldoc to extract it.&lt;br /&gt;
&lt;br /&gt;
==== Other Documents ====&lt;br /&gt;
&lt;br /&gt;
* Look at all the documentation we have and see what's missing&lt;br /&gt;
* Data Access, other new CA-related documentation...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More test programs ===&lt;br /&gt;
&lt;br /&gt;
There are test programs in libCom/test which cover quite a lot of the libCom functionality, but they are by far from complete.  Writing test code is a very good way to learn the capabilities of the code being tested, and is not usually hard to to, so this would be a good &amp;quot;getting started&amp;quot; project.&lt;br /&gt;
&lt;br /&gt;
Check the Diamond code coverage report as part of their Base Autotests for ideas what code to tackle.&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&lt;br /&gt;
&lt;br /&gt;
=== IOC Test Framework in Perl ===&lt;br /&gt;
&lt;br /&gt;
Once we have good test coverage for libCom we should look at IOC-level testing, including tests for individual record types.  This needs code to start a soft IOC with a particular database file, make channel connections over CA and perform the necessary tests, then close down the IOC and clean up.  Tests should be automatable, e.g. by generating TAP output and run under the standard Perl Test::Harness, as used by the 'make runtests' target.&lt;br /&gt;
&lt;br /&gt;
Once the framework exists, write test programs for each core record type and device support.  Look at the Soft-Test suite and implement those tests too, although a complete rewrite might be appropriate for them...&lt;br /&gt;
&lt;br /&gt;
=== Convert makeBpt into Perl (3.15) ===&lt;br /&gt;
&lt;br /&gt;
The makeBpt tool in src/bpt generates non-linear break-point tables from data files.  A fair bit of the C code is concerned with parsing the input file.  There is no particular need for this code to be written in C, speed is not an issue, and eventually I hope to convert all programs needed for building EPICS into Perl code.  Maybe start this project by writing a program to test the output, then convert the C code into Perl.&lt;br /&gt;
&lt;br /&gt;
=== Database diagnostics ===&lt;br /&gt;
&lt;br /&gt;
When an IOC is too busy to service CA, the engineers need a way to find out what records are causing the problem.  Something like a dbSpy command might be helpful, which would keep a count of the records processed by each scan thread and give periodic reports.  Would need to be designed carefully so it doesn't eat RAM or slow down the machine too much.&lt;br /&gt;
&lt;br /&gt;
Other diagnostics could also be added: dbProcess rate, ...&lt;br /&gt;
&lt;br /&gt;
Priority: Medium&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: db, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== Record aliases in VDCT ===&lt;br /&gt;
&lt;br /&gt;
EPICS Base R3.14.11 supports record aliases, but AFAIK VDCT does not (not sure about the new version of VDCT though).  Both preserving the aliases attached to a record loaded from a .db file, and providing creation and editing capabilities for them through the GUI.  This is a Java programming task which will need prior communication with CosyLab.&lt;br /&gt;
&lt;br /&gt;
=== Move alarm*.h headers ===&lt;br /&gt;
&lt;br /&gt;
A first step towards a more packagable build system would be to move the alarm.h and alarmString.h headers out of src/dbStatic; they are the only thing currently preventing src/catools and src/cap5 from being built immediately after src/ca.&lt;br /&gt;
&lt;br /&gt;
=== RSRV Using EPICS_CAS_INTF_ Variables ===&lt;br /&gt;
&lt;br /&gt;
Change the socket binding in rsrv to use the EPICS_CAS_INTF_ variable(s) so we can limit IOCs to a subset of the interfaces of the host it's running on.&lt;br /&gt;
&lt;br /&gt;
=== Packagable Build System ===&lt;br /&gt;
&lt;br /&gt;
The EPICS Build system currently does not distinguish between programs that are needed by IOC developers (e.g. dbToMenuH) and end-user programs (e.g. caget).  We could divide our build targets into these very easily, which would make packaging EPICS Base much more straight-forward.  I see the following parts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== End-user Binaries ====&lt;br /&gt;
&lt;br /&gt;
* catools&lt;br /&gt;
* Shared libraries&lt;br /&gt;
* SoftIoc (requires compiled-in DBD data though)&lt;br /&gt;
&lt;br /&gt;
These could be installed into /usr/local from an RPM or equivalent packaging system.&lt;br /&gt;
&lt;br /&gt;
==== Developer Tools ====&lt;br /&gt;
&lt;br /&gt;
* flex, antelope binaries etc.&lt;br /&gt;
* static libraries&lt;br /&gt;
* DBD and header files&lt;br /&gt;
* Build system components&lt;br /&gt;
&lt;br /&gt;
These could be packaged into a -devel RPM or equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extended Device Support (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Converting Asyn's device support layers to Extended support exposed the need to clean up the extended interface, i.e. reduce the code duplication which is currently required since the record knows nothing about the device change.&lt;br /&gt;
&lt;br /&gt;
Libs affected: db, rec.&lt;br /&gt;
&lt;br /&gt;
=== New Record Types ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add record types - valve record, improved control records for PID and Lead/Lag (if we had a good process control guy to design the record).&lt;br /&gt;
&lt;br /&gt;
Enhancements to PID should start from the most advanced implementation currently available, which is ''not'' the old PID record type from Base 3.13. There's a PID record in synApps, and there may be others available from other sites too.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: (external app)&lt;br /&gt;
&lt;br /&gt;
=== CA support for Array with Timebase ===&lt;br /&gt;
&lt;br /&gt;
From Bob: Add a new dbr_type into the channel access database - new array that includes time base and offset at least. One that also supports up to 3 dimensions (or better n).&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: Many...&lt;br /&gt;
&lt;br /&gt;
=== More flexible Access Security ===&lt;br /&gt;
&lt;br /&gt;
The AS design defines each field's security level in the record description, and limits us to only levels 0 and 1.  Some sites may want finer control over accesses: being able to put individual fields of a specific record into a different level, and having additional static levels (use a bitmask?) would help in a number of situations. It is not clear how much work this would entail though.&lt;br /&gt;
&lt;br /&gt;
Priority: Low&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, as, ...&lt;br /&gt;
&lt;br /&gt;
=== Authentication ===&lt;br /&gt;
&lt;br /&gt;
From Ralph: Two or three institutes need a way to password-protect access to certain databases. The usual encryption libraries are freely available, but I guess this issue needs a lot more thinking. Granularity: by record, by connection = IOC, or centralised? Should the authentication last for the client's lifetime or should a short form (some security token or key) be sent with every CA data package?&lt;br /&gt;
&lt;br /&gt;
=== Secure CA ===&lt;br /&gt;
&lt;br /&gt;
Secure channel access protocol - add SSL wrappers around CA to make it secure.&lt;br /&gt;
&lt;br /&gt;
The CA-over-TCP branch should form the basis of this work.&lt;br /&gt;
&lt;br /&gt;
Priority: R3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: ca, cas, rsrv&lt;br /&gt;
&lt;br /&gt;
=== Online Record Creation ===&lt;br /&gt;
&lt;br /&gt;
It might be possible to add new record instances at runtime, although delete would need a change to the record interface to support.  The tricky thing is to do this in a manner which is completely thread-safe since the pdbbase structure does not have many locks, and adding them could significantly affect operation of the IOC.&lt;br /&gt;
&lt;br /&gt;
Priority: Dalesio&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db, misc&lt;br /&gt;
&lt;br /&gt;
=== Conversion Code Clean-Up ===&lt;br /&gt;
&lt;br /&gt;
The existing conversion routines (i.e. the fast and full versions in db) could be significantly cleaned up by using C++ templated functions. There would probably be minor savings in object code size, but major savings in terms of source code size and clarity.&lt;br /&gt;
&lt;br /&gt;
Priority: 3.15&amp;lt;br&amp;gt;&lt;br /&gt;
Libs affected: dbStatic, db&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tasks which are already under way ==&lt;br /&gt;
&lt;br /&gt;
These tasks are already being worked on but may have stalled.  They might be hard for someone else to take over at this stage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CA Event Rate Limiting (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify a maximum event rate for each channel subscription it creates.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== CA Event Filtering (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A CA client can specify an event filter with the channel subscription which must be true for events to be posted to the client.&lt;br /&gt;
&lt;br /&gt;
Waiting for: JSON field modifiers&lt;br /&gt;
&lt;br /&gt;
=== Compiling DBD Files (3.15) ===&lt;br /&gt;
&lt;br /&gt;
A Perl implementation of the DBD file parser exists and provides working dbdToRecordH and dbdToMenuH scripts. I'm working to revive my plans to convert all DBD file information into C tables that get compiled into the IOC executable or its shared libraries.&lt;br /&gt;
&lt;br /&gt;
With this parser written in Perl, it is much easier to add new facilities to DBD files, such as adding new field types (see Variable Length Strings below).&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbStatic, +dbHost, db.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Things which can't be completed yet ==&lt;br /&gt;
&lt;br /&gt;
These are tasks are waiting on other people or for other tasks to be completed before they can be finished, although there may be infrastructure to support them that can be worked on in parallel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IOCSH Command Registration (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Add DBD file syntax to convert DBD file information into a C header file which declares the command functions (similar to how we do record types in the current code-base).  This header would then be included by the C file that defines those functions, thus the C compiler would do the work of ensuring that the routine implemented actually matches the command that will call it.&lt;br /&gt;
&lt;br /&gt;
The command information in the DBD file will also be useful for future versions of the IRMIS parser for st.cmd scripts, where we need to be able to tie the device support configuration commands into IRMIS' need to map hardware devices to record addresses.&lt;br /&gt;
&lt;br /&gt;
This should be done in the compiled-dbd branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, all libs Registrar code.&lt;br /&gt;
&lt;br /&gt;
=== DBE_PROPERTY event generation (3.15) ===&lt;br /&gt;
&lt;br /&gt;
Extend the DBD syntax to link all fields that contain property values with the fields that the property is supplied with, then have dbPut() post a DBE_PROPERTY monitor on those fields whenever the property value changes.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db&lt;br /&gt;
Waiting for: Perl DBD Processing&lt;br /&gt;
&lt;br /&gt;
=== Link Support (3.15+) ===&lt;br /&gt;
&lt;br /&gt;
See original proposal by ANJ, which needs to be modified to add notify interfaces.&lt;br /&gt;
&lt;br /&gt;
=== Array Field Support (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
Make it easier to add array fields to record types without having to do as much coding in the record support.  See [http://www.aps.anl.gov/epics/core-talk/2007/msg00078.php Ben Franksen email] and the work done by Nick Rees at the 2009 Codeathon.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, rec.&lt;br /&gt;
&lt;br /&gt;
=== Unbundling (3.15/++) ===&lt;br /&gt;
&lt;br /&gt;
Split Base into three or more independent modules.  Each module would have its own version number, and the modules can therefore each have an independent existance, although there would obviously be specific dependencies associated with particular versions.&lt;br /&gt;
&lt;br /&gt;
If we adopt this, we should bundle working subsets of modules together and release the complete bundle as a tarfile.&lt;br /&gt;
&lt;br /&gt;
I see the unbundled modules as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Nothing&lt;br /&gt;
&lt;br /&gt;
These are the common parts used by everything:&lt;br /&gt;
&lt;br /&gt;
* Build system&lt;br /&gt;
* libCom &amp;amp; OSI layer&lt;br /&gt;
** Basic registry routines&lt;br /&gt;
** IOC shell&lt;br /&gt;
* Antelope&lt;br /&gt;
* Flex&lt;br /&gt;
* makeApp tool&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Client ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CA-specific build rules (probably none)&lt;br /&gt;
* CA client library&lt;br /&gt;
* CA Tools&lt;br /&gt;
* CA application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Channel Access Server ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, IOC, CAC?&lt;br /&gt;
&lt;br /&gt;
Jeff Hill's responsibility.&lt;br /&gt;
&lt;br /&gt;
* CAS-specific build rules (probably none)&lt;br /&gt;
* GDD&lt;br /&gt;
* The CAS server tool&lt;br /&gt;
* RSRV (the old CA server code)&lt;br /&gt;
* CAS application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== IOC ====&lt;br /&gt;
&lt;br /&gt;
Depends on: Core, CAC, CAS&lt;br /&gt;
&lt;br /&gt;
The rest is code that runs on the IOC.&lt;br /&gt;
&lt;br /&gt;
* IOC-specific build rules&lt;br /&gt;
* Static and runtime database access&lt;br /&gt;
* Runtime database&lt;br /&gt;
* Standard record types&lt;br /&gt;
* Soft device support&lt;br /&gt;
* The registry (device, driver, record, function)&lt;br /&gt;
* IOC application makeApp templates&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Variable Length Strings (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
3.15 already includes the BaseString C++ classes in libCom, a set of C wrapper routines is needed for the base class operations.  This can form the basis of a new variable length string type for use in the database in addition to DBF_STRING.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost, dbStatic, db, ...&lt;br /&gt;
&lt;br /&gt;
=== Device Status String Field ===&lt;br /&gt;
&lt;br /&gt;
DESY want a string field in dbCommon for device support to post signal-specific status information to. Once we have variable-length string types it would be reasonable to add this (if not used/set it would only add one pointer to each record instance).&lt;br /&gt;
&lt;br /&gt;
=== Alternate DB File Formats (3.15++) ===&lt;br /&gt;
&lt;br /&gt;
There are calls to replace the existing DB file format with an XML-based format.  Currently the DB file parser is too highly integrated into the process of record creation to easily add a second format, but it would be feasible to separate these two and hence allow an expat-based or similar parser to be written. This would probably require a close analysis and upgrade to the locking arrangements of the database.  Alternative to XML would be JSON, for which a parser is already being included in the jsonfm branch.&lt;br /&gt;
&lt;br /&gt;
Libs affected: dbHost?, dbStatic.&lt;br /&gt;
&lt;br /&gt;
=== New Record API ===&lt;br /&gt;
&lt;br /&gt;
These requests all need a significant change to the record support API.  They are also fairly closely related, so should be used as input into any new API that gets devised.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Gets (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be great if an input link could initiate processing, and get a value that is known to be the result of that processing, even if &lt;br /&gt;
records to be processed are asynchronous.  Currently, a record that needs completion-qualified data must know how to trigger the processing that generates that data.&lt;br /&gt;
&lt;br /&gt;
From Ben Franksen: Implemented an asyncronous dbGetLinkCallback() routine.  To do this properly though needs an upgrade to the record support API, but maybe could be shoe-horned into the the existing API by adding a dbGetLinkCallback() with a private callback pointer, and we'd require new record types to use this.  What does this do to the device support interface though?  Implications need study.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
==== Blocking Puts (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: It would be nice to have a link attribute that could put, request processing, and wait for completion.  We have this capability now, in dbCaPutCallback(), but it's selectable only at DCT time.&lt;br /&gt;
&lt;br /&gt;
The idea is for a version of the SEQ record where rather than a fixed delay, the second link would wait for the completion callback from the first link.  This should be possible today with a special record type, but Tim suggests it should be possible with any link field of any record type.&lt;br /&gt;
&lt;br /&gt;
Andrew's Comment: This should be part of the implementation of linkSupport which I proposed in detail many years ago.  The purpose of the &amp;quot;Compiling DBD Files&amp;quot; item above is to make extending the DBD file syntax easier to do in the future, which is a necessary part of that development.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple Master problem (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Jeff: Changes to output values in a PLC or similar device initiated outside of the output record. This could be resolved adding a new routine to the RSET that the device support calls back when it has a new raw ouptut value to back-propagate to the VAL field.  Currently done by some devices that set PACT and call the record's process() routine to use its second-half processing only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Records Can't Block (3.16++) ====&lt;br /&gt;
&lt;br /&gt;
From Tim Mooney: I think almost half the code in the sscan record is devoted to &lt;br /&gt;
bookmarking. In the middle of some algorithm, the record needs to wait for external events; the only way back in is process(), and so the record has to &lt;br /&gt;
have a complicated arrangement of switches that get it back into the &lt;br /&gt;
algorithm it was executing, with enough state information to decide what to do &lt;br /&gt;
next. At the same time, the record must check to see if it's now processing &lt;br /&gt;
because of some out-of-band request from the user.  Normal and exceptional processing must, therefore, be mixed together in the switch &lt;br /&gt;
arrangement, and adding new behaviors to the record becomes a very hairy undertaking.&lt;br /&gt;
&lt;br /&gt;
But what the record would really like to do is just wait with its &lt;br /&gt;
context intact for events, and allow special() to release it from the wait &lt;br /&gt;
if the user has requested something that requires this.  I guess this means the record should include author-defined event types in the wait mask, and special() should be able to generate author-defined events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamically Loaded Modules (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
After converting the DBD load process into table registration, it should become easier to allow support modules (containing record types, device support and other drivers) to be discovered and loaded dynamically.  Unloading is a very different matter though, we don't have the shutdown facilities to allow that.&lt;br /&gt;
&lt;br /&gt;
=== Atomic Operations through CA (3.16++) ===&lt;br /&gt;
&lt;br /&gt;
This is related to the Asynch Gets issue above; implement Read-Write (Swap, permits semaphores), Process-Read and Write-Process-Read (Command/Response) as atomic operations available through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=2792</id>
		<title>RRM 3-13 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=2792"/>
		<updated>2010-09-30T16:33:06Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Algorithms and Related Fields */  Fix description of Average algorithm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-13|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-13 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-13 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of every element of the array obtained from INP over time; that is, the entire array referenced by INP is retrieved, and for each element the new average is calculated and placed in the corresponding element of the value buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the buffer. Thus, VAL[0] holds the average of the first element of INP over N samples, VAL[1] holds the average of the next element of INP over N samples, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-13 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-13 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1893</id>
		<title>RRM 3-14 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1893"/>
		<updated>2010-09-30T16:32:56Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Algorithms and Related Fields */  Fix description of Average algorithm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of every element of the array obtained from INP over time; that is, the entire array referenced by INP is retrieved, and for each element the new average is calculated and placed in the corresponding element of the value buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the buffer. Thus, VAL[0] holds the average of the first element of INP over N samples, VAL[1] holds the average of the next element of INP over N samples, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_check_out_EPICS_Base_with_Bazaar&amp;diff=1860</id>
		<title>How to check out EPICS Base with Bazaar</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=How_to_check_out_EPICS_Base_with_Bazaar&amp;diff=1860"/>
		<updated>2010-05-26T14:18:12Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Added bzr+ssh: spec hint (might work through firewall when lp: doesn't)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bazaar can support several different approaches; the one you should use depends on what you expect to do with the code-base.  It usually allows you to change your mind later though, so don't worry if you pick the wrong model to start with, you can modify your configuration as you need later on (although I'm not going to give instructions on how to do that here, read the documentation).&lt;br /&gt;
&lt;br /&gt;
You must have Bazaar version 2.x installed; older versions do not support the same repository format. I'm using version 2.0.1 at the time of writing this, but any release in the 2.x series should be fine.&lt;br /&gt;
&lt;br /&gt;
Bazaar has extensive built-in help text, just type 'bzr help &amp;lt;command&amp;gt;' for more information on &amp;lt;command&amp;gt; or 'bzr help topics' for a list of other help topics.  The complete documentation for the tool can be found online [http://doc.bazaar.canonical.com/bzr.2.0/en/ here].&lt;br /&gt;
&lt;br /&gt;
If you have problems connecting to launchpad and your network requires you to use an HTTP proxy server, make sure that you have both the http_proxy and https_proxy environment variables set appropriately.&lt;br /&gt;
&lt;br /&gt;
If you are behind a firewall and the 'lp:' shorthand does not work, try the following transport specification:&lt;br /&gt;
   bzr checkout bzr+ssh://&amp;lt;lp-user-name&amp;gt;@bazaar.launchpad.net/~epics-core/epics-base/3.14/&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Check out a working tree (for users, CVS model, remote history) ==&lt;br /&gt;
&lt;br /&gt;
Use this option if you just want to a copy of the latest version of Base from the repository (for example to build and test) but don't expect to modify the code at all, or to look at its history much.  This approach is very similar to using CVS since you only download a copy of the particular revision you're interested in, but it require network connectivity for all activities that access the repository in any way.  An EPICS Base 3.14 working tree uses about 12MB of disk space at the time of writing.&lt;br /&gt;
&lt;br /&gt;
The following command will create a directory tree called base-3.14 containing the latest code that was checked in to the 3.14 branch of Base:&lt;br /&gt;
   bzr checkout --lightweight lp:epics-base/3.14 base-3.14&lt;br /&gt;
&lt;br /&gt;
The lp: path above specifies a branch to check out from the launchpad server.  The branch at lp:epics-base/3.14 is a branch containing all the development work for the R3.14 releases of Base.  There are similar branches for the older series, although we're not expecting anyone to check any of these out; they're provided for historical reasons.  The development on the branch called trunk will eventually become the 3.15 series.&lt;br /&gt;
&lt;br /&gt;
If you want to check out a specific tagged version, in this case we're requesting the R3.14.11 release, use this command instead:&lt;br /&gt;
   bzr checkout --lightweight -r tag:R3.14.11 lp:epics-base/3.14 base-3.14&lt;br /&gt;
&lt;br /&gt;
To update a lightweight working tree at a later date with the latest changes from the branch, use this command inside the tree:&lt;br /&gt;
   bzr update&lt;br /&gt;
&lt;br /&gt;
You can use the command 'bzr tags' from inside the working tree to list all the tags known on this branch.&lt;br /&gt;
&lt;br /&gt;
Unlike CVS, 'bzr update' cannot apply changes that move your tree to a different historical revision; for that you use the command below, in this case to move to the R3.14.10 release tag:&lt;br /&gt;
   bzr revert -r tag:R3.14.10&lt;br /&gt;
&lt;br /&gt;
If you made any local changes to the files in the working tree your changes will be retained through a 'bzr update' or 'bzr revert' operation.  Any local changes that overlap with changes from the repository will create a conflict and have to be resolved by hand, just as happens with CVS.&lt;br /&gt;
&lt;br /&gt;
If you find yourself using Bazaar commands inside the tree more than once or twice, you should probably check out a branch instead, which makes a local copy of the complete history of the branch and removes the need for network activity to access that history.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Check out a branch (for users, local history) ==&lt;br /&gt;
&lt;br /&gt;
This option is similar to the previous one but also gives you a local copy of the complete history of the branch.  This speeds up all activities that need to examine the repository history, but since the local branch is still bound to the central repository at launchpad.net you can't commit any changes to it without write permission for the repository branch.  A 3.14 branch needs about 28MB of disk space at the time of writing.&lt;br /&gt;
&lt;br /&gt;
The following command will create a directory tree called base-3.14 containing the latest code and all of the history that was checked in to the 3.14 branch of Base:&lt;br /&gt;
   bzr checkout lp:epics-base/3.14 base-3.14&lt;br /&gt;
&lt;br /&gt;
The lp: path above specifies a branch to check out from the launchpad server.  The branch at lp:epics-base/3.14 is a branch containing all the development work for the R3.14 releases of Base.  There are similar branches for the older series, although we're not expecting anyone to check any of these out; they're provided for historical reasons.  The development on the branch called trunk will eventually become the 3.15 series.&lt;br /&gt;
&lt;br /&gt;
If you want to check out a particular tagged version, use this command instead:&lt;br /&gt;
   bzr checkout -r tag:R3.14.11 lp:~epics-core/epics-base/3.14 base-3.14&lt;br /&gt;
&lt;br /&gt;
Inside the working tree, Bazaar supports the expected commands 'bzr log' and 'bzr diff' to examine file history.  Use 'bzr help revisionspec' for information on specifying particular revisions to examine.&lt;br /&gt;
&lt;br /&gt;
To update your working tree with the latest changes from the parent branch at some later date, use this command inside the tree:&lt;br /&gt;
   bzr update&lt;br /&gt;
Note that if you're working in a regular branch and not a checkout, the command to use is&lt;br /&gt;
   bzr pull&lt;br /&gt;
and if you have committed changes to your branch that are not in the parent&lt;br /&gt;
   bzr merge&lt;br /&gt;
&lt;br /&gt;
Note that 'bzr pull' or 'bzr update' cannot move your tree to a different historical revision like in CVS, for that you use this command:&lt;br /&gt;
   bzr revert -r tag:R3.14.10&lt;br /&gt;
&lt;br /&gt;
You can use 'bzr tags' when inside the working tree to list all the tags known on this branch.&lt;br /&gt;
&lt;br /&gt;
If you made any local changes to the files in the working tree your changes will be retained through a 'bzr update' or 'bzr revert' operation.  Any local changes that overlap with changes from the repository will create a conflict and have to be resolved by hand, just as happens with CVS.&lt;br /&gt;
&lt;br /&gt;
If you want to keep some permanent local changes, consider unbinding your tree from the central repository branch, which converts it to a regular branch.  This will allow you to check local changes into the local repository while still permitting 'bzr update' to fetch changes as before.  The 'bzr unbind' command does this, and can be undone again with 'bzr bind'.&lt;br /&gt;
&lt;br /&gt;
== Developer Branches ==&lt;br /&gt;
&lt;br /&gt;
Developers have a more complex configuration since they usually want to be able to commit their changes to a local repository and later on merge those changes into the branch in the central repository.  The model described here corresponds to the &amp;quot;decentralized with shared mainline&amp;quot; workflow given in the [http://doc.bazaar.canonical.com/bzr.2.0/en/user-guide/distributed_intro.html Bazaar User Guide].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Initial Checkout ===&lt;br /&gt;
&lt;br /&gt;
First initialize a local repository in a parent directory which will be used as the backing-store to hold the history of all your development work on EPICS Base, then inside this directory checkout a mirror branch of Base from Launchpad:&lt;br /&gt;
   bzr init-repo ~/epics-base&lt;br /&gt;
   cd ~/epics-base&lt;br /&gt;
   bzr checkout lp:epics-base/3.14 mirror-3.14&lt;br /&gt;
&lt;br /&gt;
This mirror branch should never be used directly for developing new code or major bug fixing, but can be used for &amp;quot;obviously correct&amp;quot; changes to things like comments or string literals.  Major work should take place in a different tree usually called a ''feature'' or ''task branch''.  The mirror branch allows you to merge tested sets of changes from your feature branches into the central repository. Performing a commit in the mirror branch will immediately push the change to the official branch on the Launchpad website.&lt;br /&gt;
&lt;br /&gt;
=== Creating a Task Branch ===&lt;br /&gt;
&lt;br /&gt;
Bazaar encourages developers to create a separate branch for each separate feature or bug fix being developed, which would normally be created as a sibling to the mirror branch we checked out above.  While working on the fix you are free to commit changes whenever you like, which are recorded in your local repository:&lt;br /&gt;
   cd ~/epics-base&lt;br /&gt;
   bzr branch mirror-3.14 fix-123&lt;br /&gt;
   cd fix-123&lt;br /&gt;
   # ''Hack...''&lt;br /&gt;
   bzr ci -m 'Hacked the frooz-bodger to stop it wibbling'&lt;br /&gt;
&lt;br /&gt;
If a commit fixes a bug registered on Launchpad, you can have Bazaar record that fact like this:&lt;br /&gt;
   bzr ci --fixes=lp:123&lt;br /&gt;
&lt;br /&gt;
=== Merges: Updating ===&lt;br /&gt;
&lt;br /&gt;
While you're working other developers may be committing changes into the central branch.  To incorporate those changes into your task branches is a two-stage process: First update your mirror branch to fetch those changes from the central repository, then merge and commit them into each of your working trees.  Note that you should either shelve (see below) or check in any local modifications into the task branch before doing the merge step (if you use --force you risk mixing up your changes with someone else's):&lt;br /&gt;
   cd ~/epics-base&lt;br /&gt;
   bzr update mirror-3.14&lt;br /&gt;
   # ''For each task branch:''&lt;br /&gt;
   cd fix-123&lt;br /&gt;
   bzr merge&lt;br /&gt;
   # ''Fix any conflicts and tell bzr like this:''&lt;br /&gt;
   bzr resolve ''file''&lt;br /&gt;
   # ''Finally commit the merge''&lt;br /&gt;
   bzr ci -m 'Merged with 3.14'&lt;br /&gt;
&lt;br /&gt;
If you have not committed any changes to your fix-123 branch yet, you can skip the shelve step and combine the merge and commit phases above into a single command, so that after updating the mirror-3.14 tree as above, you just do this:&lt;br /&gt;
   cd fix-123&lt;br /&gt;
   bzr pull&lt;br /&gt;
   # ''Should report any conflicts''&lt;br /&gt;
&lt;br /&gt;
If you're not sure whether you've made any commits or not, you can ask Bazaar:&lt;br /&gt;
   cd fix-123&lt;br /&gt;
   bzr missing&lt;br /&gt;
   # ''Reports commit differences between trees''&lt;br /&gt;
&lt;br /&gt;
=== Merges: Committing Changes ===&lt;br /&gt;
&lt;br /&gt;
The ability to commit changes to the central repository is restricted to members of the epics-core team at [https://launchpad.net/ Launchpad.net], but Bazaar and Launchpad will still allow you to publish branches containing your own development even if you do not belong to that team; a team-member can subsequently merge and commit the changes from your branch into the official one.&lt;br /&gt;
&lt;br /&gt;
For epics-core members, a feature branch is merged and committed to the central branch as follows:&lt;br /&gt;
   cd ~/epics-base/mirror-3.14&lt;br /&gt;
   bzr update&lt;br /&gt;
   bzr missing ../fix-123&lt;br /&gt;
   # ''Check that you're about to merge the right changes''&lt;br /&gt;
   bzr merge ../fix-123&lt;br /&gt;
   # ''Fix any conflicts and tell Bazaar like this:''&lt;br /&gt;
   bzr resolve ''file''&lt;br /&gt;
   # ''Finally commit the merge''&lt;br /&gt;
   bzr ci -m 'Fixed bug #123'&lt;br /&gt;
&lt;br /&gt;
If you're merging someone else's branch which is published on Launchpad, you can use the lp:~user/epics-base/branch-name URL for their branch directly, it is not necessary to download or checkout a copy of a branch to merge it:&lt;br /&gt;
   cd ~/epics-base/mirror-3.14&lt;br /&gt;
   bzr update&lt;br /&gt;
   bzr missing lp:~mdavidsaver/epics-base/rec-init&lt;br /&gt;
   # ''Check that you're about to merge the right changes''&lt;br /&gt;
   bzr merge lp:~mdavidsaver/epics-base/rec-init&lt;br /&gt;
   bzr ci -m &amp;quot;Merged Michael Davidsaver's 'rec-init' branch.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To apply a bug-fix change to more than one series branch, say to both 3.14 and the main trunk, Bazaar's merge command allows you to cherry-pick commits from a different branch.  If it's just one check-in this is very easy, especially if it's the last commit you made to that source branch.  In that case, you would use these commands to merge those changes to the trunk:&lt;br /&gt;
   cd ~/epics-base/mirror-trunk&lt;br /&gt;
   bzr update&lt;br /&gt;
   bzr merge -c -1 ../fix-123&lt;br /&gt;
   # ''Fix any conflicts and tell bzr like this:''&lt;br /&gt;
   bzr resolve ''file''&lt;br /&gt;
   # ''Finally commit the merge''&lt;br /&gt;
   bzr ci -m 'Fixed bug #123'&lt;br /&gt;
The '-c -1' option to 'bzr merge' means &amp;quot;cherry-pick just the last commit&amp;quot;, '-c -2' would be the penultimate commit and so on.  You can use 'bzr log' in the feature branch to find a specific absolute revision number on that branch and use that instead of the negative numbers.  If there were several commits you can give 'bzr merge' a range using the option '-r 44..47' instead, but note that '-r 44' means &amp;quot;merge all changes up to and including revision 44.&amp;quot;  If you get it wrong, you can always use 'bzr revert' to undo.&lt;br /&gt;
&lt;br /&gt;
After you have merged and committed your changes from a feature branch into the central branch(es) at launchpad, you may delete the branch directory as necessary ('rm -rf fix-123').&lt;br /&gt;
&lt;br /&gt;
=== Shelving Local Changes ===&lt;br /&gt;
&lt;br /&gt;
If you have some local changes that you don't want to commit, say some CONFIG_SITE changes needed to build the code at your site, you can use 'bzr shelve configure/CONFIG_SITE' to temporarily hide them before committing or merging, and 'bzr unshelve' later to bring them back.  The shelve command will show you each of the changes in the named file(s) in turn and ask whether you want to shelve it or not.  Read the 'bzr help shelve' output for more details.&lt;br /&gt;
&lt;br /&gt;
=== Publishing a Branch ===&lt;br /&gt;
&lt;br /&gt;
If you're not a member of epics-core, you can still publish your own branches of the epics-base project on Launchpad where other people can find and use them.  You must have registered for an account at [https://launchpad.net/ Launchpad.net] first and uploaded your ssh public-key.&lt;br /&gt;
   bzr launchpad-login ''userid''&lt;br /&gt;
   cd ~/epics-base/fix-123&lt;br /&gt;
   bzr push lp:~''user-id''/epics-base/fix-123&lt;br /&gt;
&lt;br /&gt;
If you are a member of epics-core, you can create a shared branch that other members can also commit to by using the group name as the user-id in the Bazaar target path:&lt;br /&gt;
   bzr push lp:~epics-core/epics-base/feature-xyz&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=2852</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=2852"/>
		<updated>2010-04-15T20:55:52Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Adde status section with links to Launchpad&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''Initial changes: [[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
: ''Rebase/merge to 3.14 and additional fixes: [[User:RalphLange|Ralph Lange]], April 2010''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
A possible implementation would be a client-side caRepeater which connects through a 5065/TCP connection to a server-side caRepeater. That way neither client nor server code would have to be changed.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement friend SearchDest::searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback::notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(maybe this could be refactored and moved to a separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;br /&gt;
&lt;br /&gt;
== Status ==&lt;br /&gt;
&lt;br /&gt;
The original changes (against 3.15 aka CVS trunk) have been pulled out and merged into a development branch.&lt;br /&gt;
&lt;br /&gt;
Development branch: https://code.launchpad.net/~ralph-lange/epics-base/ca-over-tcp&lt;br /&gt;
&lt;br /&gt;
Blueprint: https://blueprints.launchpad.net/epics-base/+spec/ca-over-tcp&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Core_Developer_Pages&amp;diff=1866</id>
		<title>Core Developer Pages</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Core_Developer_Pages&amp;diff=1866"/>
		<updated>2010-04-15T20:50:22Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Put CA over TCP back to current development&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developing EPICS Base ==&lt;br /&gt;
&lt;br /&gt;
* [[How to check out EPICS Base with Bazaar]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Development Plans ==&lt;br /&gt;
&lt;br /&gt;
* [[Future Development Ideas]]&lt;br /&gt;
&lt;br /&gt;
=== Current Development Work ===&lt;br /&gt;
&lt;br /&gt;
* [[Migrate from CVS to Bazaar]]&lt;br /&gt;
* [[CA over TCP]] - Allow Channel Access to be run through an SSH tunnel&lt;br /&gt;
&lt;br /&gt;
=== Completed Development Work ===&lt;br /&gt;
&lt;br /&gt;
I think these are done now:&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1849</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1849"/>
		<updated>2010-04-15T20:48:31Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Added header note&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''Initial changes: [[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
: ''Rebase/merge to 3.14 and additional fixes: [[User:RalphLange|Ralph Lange]], April 2010''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
A possible implementation would be a client-side caRepeater which connects through a 5065/TCP connection to a server-side caRepeater. That way neither client nor server code would have to be changed.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement friend SearchDest::searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback::notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(maybe this could be refactored and moved to a separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1847</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1847"/>
		<updated>2010-04-15T20:44:47Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Beacons */  Added low-impact idea for beacons over TCP&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
A possible implementation would be a client-side caRepeater which connects through a 5065/TCP connection to a server-side caRepeater. That way neither client nor server code would have to be changed.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement friend SearchDest::searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback::notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(maybe this could be refactored and moved to a separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1846</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1846"/>
		<updated>2010-04-15T20:41:41Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CA Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement friend SearchDest::searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback::notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(maybe this could be refactored and moved to a separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1845</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1845"/>
		<updated>2010-04-15T20:40:45Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(maybe this could be refactored and moved to a separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1844</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1844"/>
		<updated>2010-04-15T20:30:15Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(probably this should be moved to separate name resolver class to avoid code repetition)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods, should be moved to a resolver than both can use)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1843</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1843"/>
		<updated>2010-04-15T19:28:21Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* rsrv */ Added changes to rsrv&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(probably this could be moved to a base class. casCoreClient?)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
* camessage.c changes&lt;br /&gt;
** rename search_reply() to search_reply_udp()&lt;br /&gt;
** add search_reply_tcp() with similar functionality&lt;br /&gt;
** change jump table accordingly&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1842</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1842"/>
		<updated>2010-04-15T19:25:17Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CAS */ Added changes in cas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
* casStrmClient changes&lt;br /&gt;
** add private client addr member (init'd through constructor arg)&lt;br /&gt;
** add casStrmClient::searchAction that does roughly the same as the casDGClient::searchAction ''(probably this could be moved to a base class. casCoreClient?)''&lt;br /&gt;
** add casStrmClient::asyncSearchResponse and casStrmClient::searchResponse ''(again: same as casDGClient methods)''&lt;br /&gt;
* casStreamIO changes&lt;br /&gt;
** add private client address member&lt;br /&gt;
** add public methods to get client host name and address&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1841</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1841"/>
		<updated>2010-04-15T19:10:01Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CA Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor)&lt;br /&gt;
** creates SearchDestTCP and adds it to the search list&lt;br /&gt;
** creates tcpiiu specifying the SeachDestTCP to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1840</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1840"/>
		<updated>2010-04-15T19:08:00Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CA Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1839</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1839"/>
		<updated>2010-04-15T19:03:57Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix: (2010-04-15)'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1838</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1838"/>
		<updated>2010-04-15T19:03:32Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* ''Fixed:'' TCP Nameserver Connections Do Not Reconnect */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix (2010-04-09):'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix:'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1837</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1837"/>
		<updated>2010-04-15T17:53:14Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Issues */ Added &amp;quot;Fixed: TCP Nameserver Connection Down Blocks All Callbacks&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix:'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connection Down Blocks All Callbacks ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client's TCP receive thread tries to reconnect in an endless loop, doing a epicsThreadSleep(cac.connectionTimeout) between attempts.&lt;br /&gt;
While the receive thread is sleeping, no other CA callbacks are executed.&lt;br /&gt;
&lt;br /&gt;
''Fix:'' tcpRecvThread::connect() holds the cac mutex lock. That lock must be released during the epicsThreadSleep().&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=2877</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=2877"/>
		<updated>2010-04-13T18:57:52Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Expression */ Added ';', literals, constants, assignment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 or '?:' operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete up-to-date description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Literals ====&lt;br /&gt;
&lt;br /&gt;
* Standard double precision floating point numbers&lt;br /&gt;
* Inf: Infinity&lt;br /&gt;
* Nan: Not a Number&lt;br /&gt;
&lt;br /&gt;
==== Constants ====&lt;br /&gt;
&lt;br /&gt;
* PI: returns the mathematical constant π&lt;br /&gt;
* D2R: evaluates to π/180 which, when used as a multiplier, converts an angle from degrees to radians&lt;br /&gt;
* R2D: evaluates to 180/π which as a multiplier converts an angle from radians to degrees&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; 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 a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Assignment Operator ====&lt;br /&gt;
&lt;br /&gt;
* := : assigns a value (right hand side) to a variable (i.e. field)&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1881</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1881"/>
		<updated>2010-04-13T18:57:42Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Expression */  Added ';', literals, constants, assignment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 or '?:' operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete up-to-date description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Literals ====&lt;br /&gt;
&lt;br /&gt;
* Standard double precision floating point numbers&lt;br /&gt;
* Inf: Infinity&lt;br /&gt;
* Nan: Not a Number&lt;br /&gt;
&lt;br /&gt;
==== Constants ====&lt;br /&gt;
&lt;br /&gt;
* PI: returns the mathematical constant π&lt;br /&gt;
* D2R: evaluates to π/180 which, when used as a multiplier, converts an angle from degrees to radians&lt;br /&gt;
* R2D: evaluates to 180/π which as a multiplier converts an angle from radians to degrees&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Assignment Operator ====&lt;br /&gt;
&lt;br /&gt;
* := : assigns a value (right hand side) to a variable (i.e. field)&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1833</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1833"/>
		<updated>2010-04-13T18:24:11Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Operands */ Fix: VAL keyword returns OVAL for OCAL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the conditional '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; 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 a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1836</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1836"/>
		<updated>2010-04-09T14:28:48Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: Added issue found - and the fix applied.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== ''Fixed:'' TCP Nameserver Connections Do Not Reconnect ===&lt;br /&gt;
When a TCP nameserver connection goes away (e.g. if the nameserver dies), the client does not reconnect when the connection comes back (e.g. the nameserver is restarted).&lt;br /&gt;
&lt;br /&gt;
''Fix:'' The private member SearchDestTCP::_addr must be an osiSockAddr, not a reference to it. The constructor cac::cac() frees the list of destinations after creating the SearchDestTCP instances. The SearchDestTCP couldn't reconnect, because it had lost the target address.&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=1873</id>
		<title>RRM 3-13 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=1873"/>
		<updated>2010-04-08T15:08:12Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Read Parameters and Algorithm Parameters */ Fix: ALG and N are SPC_RESET, not SPC_NOMOD.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-13|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-13 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-13 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of all the elements of the array obtained from INP; that is, the entire array referenced by INP is retrieved, and the average of the elements is placed in the next element of the circular buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the circular buffer. Thus, VAL[0] holds the average of the first sampling of INP, VAL[1] holds the average of the next sampling of INP, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-13 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-13 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1872</id>
		<title>RRM 3-14 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1872"/>
		<updated>2010-04-08T15:08:06Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Read Parameters and Algorithm Parameters */ Fix: ALG and N are SPC_RESET, not SPC_NOMOD.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of all the elements of the array obtained from INP; that is, the entire array referenced by INP is retrieved, and the average of the elements is placed in the next element of the circular buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the circular buffer. Thus, VAL[0] holds the average of the first sampling of INP, VAL[1] holds the average of the next sampling of INP, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1822</id>
		<title>RRM 3-14 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Compression&amp;diff=1822"/>
		<updated>2010-04-08T15:05:20Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* special */ Fix: ALG and N are SPC_RESET, not SPC_NOMOD.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of all the elements of the array obtained from INP; that is, the entire array referenced by INP is retrieved, and the average of the elements is placed in the next element of the circular buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the circular buffer. Thus, VAL[0] holds the average of the first sampling of INP, VAL[1] holds the average of the next sampling of INP, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-14 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=1823</id>
		<title>RRM 3-13 Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-13_Compression&amp;diff=1823"/>
		<updated>2010-04-08T15:05:17Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* special */ Fix: ALG and N are SPC_RESET, not SPC_NOMOD.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-13|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= compress - Compression =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data compression record is used to collect and compress data from arrays. When the INP field references a data array field, it immediately compresses the entire array into an element of an array using one of several algorithms, overwriting the previous element. If the INP field obtains its value from a scalar-value field, the compression record will collect a new sample each time the record is processed and add it to the compressed data array as a circular buffer.&lt;br /&gt;
&lt;br /&gt;
The INP link can also specify a constant; however, if this is the case, the compression algorithms are ignored, and the record support routines merely return after checking the FLNK field.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The data compression fields fall into the following categories: &lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
=== Scanning Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-13 dbCommon#Scan Fields|Scan Fields]]. In addition,  [[RRM 3-13 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since  the compression record supports no direct interfaces to hardware, its SCAN field cannot specify &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters and Algorithm Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields determine what channel to read and how to compress the data. The user specifies the algorithm to be used in the ALG field. There are five possible algorithms which can be specified as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
* &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These algorithms are explained in one of the sections below.&lt;br /&gt;
&lt;br /&gt;
The RES field can be accessed at run time to cause the algorithm to reset itself.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RES&amp;lt;TD&amp;gt;Reset&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALG&amp;lt;TD&amp;gt;Algorithm&amp;lt;TD&amp;gt;[[RRM 3-13 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NSAM&amp;lt;TD&amp;gt;Number in Sample&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;N&amp;lt;TD&amp;gt;Number&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ILIL&amp;lt;TD&amp;gt;Initial Low Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IHIL&amp;lt;TD&amp;gt;Initial High Interest Value&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Input Specification ====&lt;br /&gt;
&lt;br /&gt;
The input specification should be a database or channel access link. Though INP can be a constant, the data compression algorithms are supported only when INP is a database link. See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on specifying links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algorithms and Related Fields ====&lt;br /&gt;
&lt;br /&gt;
As stated above, the ALG field specifies which algorithm to be performed on the data. The rest of the fields--NSAM, N, ILIL, IHIL, and OFF--are used in the compressions, though N is not used in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm and ILIL, IHIL, and OFF are used neither in the &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm nor in the &amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; algorithm.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;Circular Buffer&amp;lt;/CODE&amp;gt; algorithm keeps a circular buffer of length NSAM. Each time the record is processed, it gets the data referenced by INP and puts it into the circular buffer referenced by VAL. Note that when INP refers to a scalar, VAL is just a time ordered circular buffer of values obtained from INP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;CODE&amp;gt;Average&amp;lt;/CODE&amp;gt; takes an average of all the elements of the array obtained from INP; that is, the entire array referenced by INP is retrieved, and the average of the elements is placed in the next element of the circular buffer. The retrieved array is truncated to be of length NSAM. N successive arrays are averaged and placed in the circular buffer. Thus, VAL[0] holds the average of the first sampling of INP, VAL[1] holds the average of the next sampling of INP, and so on. The following shows the equation:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-1.gif]]&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;, or &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt; are chosen, then VAL is a circular buffer of NSAM samples. The actual algorithm depends on whether INP references a scalar or an array. If INP refers to a scalar, then N successive time ordered samples of INP are taken. After the Nth sample is obtained a new value, determined by the algorithm (LOW, HIGH, or AVE), is written to the circular buffer referenced by VAL. If LOW, the lowest value is written; if HIGH, the highest value of all the samples is written; and if AVE, the average of all the samples are written.&lt;br /&gt;
&lt;br /&gt;
If INP refers to an array, then the following applies:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Low Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the lowest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 High Value&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, keeping the highest value&lt;br /&gt;
; &amp;lt;CODE&amp;gt;N to 1 Average&amp;lt;/CODE&amp;gt;&lt;br /&gt;
: Compress N to 1 samples, taking the average&lt;br /&gt;
&lt;br /&gt;
The compression record keeps (NSAM) data samples.&lt;br /&gt;
&lt;br /&gt;
The N field determines the number of fields to compress into 1.&lt;br /&gt;
&lt;br /&gt;
Thus, if NSAM was 3, and N was also equal to 3, then the algorithms would work as in the following diagram:&lt;br /&gt;
&lt;br /&gt;
[[Image:RRM 3-13 Compression-2.gif]]&lt;br /&gt;
&lt;br /&gt;
OFF number of samples are ignored at the beginning of the array being compressed. IHIL and ILIL are used as initial value filters when compressing arrays; that is, the compression does not begin until a value is found that is either greater than IHIL or less than ILIL&lt;br /&gt;
&lt;br /&gt;
RES resets the algorithm before the maximum number of samples are reached.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. They display the value and other parameters of the record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
The HOPR and LOPR fields only specify the range for VAL, HIHI, HIGH, LOLO and LOW fields.&lt;br /&gt;
&lt;br /&gt;
PREC controls the floating-point precision whenever &amp;lt;CODE&amp;gt;get_precision&amp;lt;/CODE&amp;gt; is called, and the field being referenced is the VAL field (i.e., one of the values contained in the circular buffer).&lt;br /&gt;
&lt;br /&gt;
The EGU field should be given a string that describes the value of VAL, but is used whenever the &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; record support routine is called.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-13 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
The compression record has the alarm parameters common to all record types.  [[RRM 3-13 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used by the run-time code for processing the data compression algorithm. They are not configurable by the user, though some are accessible at run-time. They can represent the current state of the waveform or of the record whose field is referenced by the INP field.&lt;br /&gt;
&lt;br /&gt;
NUSE holds the number of elements currently stored in VAL. &lt;br /&gt;
&lt;br /&gt;
BPTR is a pointer that refers to the buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
The SPTR field pointer to an array that is used for array averages.&lt;br /&gt;
&lt;br /&gt;
WPTR is used by the dbGetlinks routines. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NUSE&amp;lt;TD&amp;gt;Number Used&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;BPTR&amp;lt;TD&amp;gt;Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;SPTR&amp;lt;TD&amp;gt;Summing Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;WPTR&amp;lt;TD&amp;gt;Work Buffer Pointer&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;&amp;amp;nbsp;&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CVB&amp;lt;TD&amp;gt;Compress Value Buffer&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INX&amp;lt;TD&amp;gt;Current Index of Circular Buffer&amp;lt;TD&amp;gt;ULONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
Space for all necessary arrays is allocated. The addresses are stored in the appropriate fields in the record.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This routine is called when RSET, ALG, or N are set. It performs a reset.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== cvt_dbaddr ====&lt;br /&gt;
&lt;br /&gt;
This is called by dbNameToAddr. It makes the dbAddr structure refer to the actual buffer holding the result.&lt;br /&gt;
&lt;br /&gt;
==== get_array_info ====&lt;br /&gt;
&lt;br /&gt;
Obtains values from the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== put_array_info ====&lt;br /&gt;
&lt;br /&gt;
Writes values into the circular buffer referenced by VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper display and lower display limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the upper control and the lower control limits for a field. If the field is VAL, 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.&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# If INP is not a database link, check monitors and the forward link and return.&lt;br /&gt;
# Get the current data referenced by INP.&lt;br /&gt;
# Perform the appropriate algorithm:&lt;br /&gt;
#* Average: Read N successive instances of INP and perform an element by element average. Until N instances have been obtained it just return without checking monitors or the forward link. When N instances have been obtained complete the algorithm, store the result in the VAL array, check monitors and the forward link, and return.&lt;br /&gt;
#* Circular Buffer: Write the values obtained from INP into the VAL array as a circular buffer, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to a scalar: Obtain N successive values from INP and apply the NTO1xxx algorithm to these values. Until N values are obtained monitors and forward links are not checked. When N successive values have been obtained, complete the algorithm, check monitors and the forward link, and return.&lt;br /&gt;
#* N to 1 xxx and INP refers to an array: The ILIL and IHIL are honored if ILIL &amp;amp;lt; IHIL. The input array is divided into subarrays of length N. The specified N to 1 xxx compression algorithm is applied to each sub-array and the result stored in the array referenced by VAL. The monitors and forward link are checked.&lt;br /&gt;
# If success, set UDF to FALSE.&lt;br /&gt;
# Check to see if monitors should be invoked:&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1824</id>
		<title>CA over TCP</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=CA_over_TCP&amp;diff=1824"/>
		<updated>2010-04-08T14:58:51Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* CA Client */  Adapted to first implementation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: ''[[User:JeffHill|Jeff Hill]] and [[User:RalphLange|Ralph Lange]], Codeathon 2008''&lt;br /&gt;
&lt;br /&gt;
: (This refers to the [[User:AndrewJohnson/V3_Evolution#CA_over_TCP| CA over TCP]] topic of Andrew's project list.)&lt;br /&gt;
&lt;br /&gt;
== Goal ==&lt;br /&gt;
&lt;br /&gt;
Provide a way to run CA on TCP circuits. Intended use: Run CA clients remotely that use an ssh tunnel to safely and securely connect to the control system. For security reasons these tunneled connections should connect to a CA Gateway.&lt;br /&gt;
&lt;br /&gt;
== Approach ==&lt;br /&gt;
&lt;br /&gt;
TCP connections can easily be tunneled through ssh. To allow CA connections through a TCP tunnel, the use of UDP (currently for name resolution and server beacons) must be avoided.&lt;br /&gt;
&lt;br /&gt;
=== Beacons ===&lt;br /&gt;
We are just ignoring the beacon topic for the time being. With the current EPICS release, CA clients do not raise the search interval above a certain limit. Even without beacon anomalies being detected, all unresolved channels will connect sooner or later. That should be good enough for a start.&lt;br /&gt;
&lt;br /&gt;
=== Name Resolution ===&lt;br /&gt;
A new environment variable EPICS_CA_NAME_SERVERS will be used to configure TCP name resolution. This variable takes a list of IP addresses. The client will open regular TCP connections (default port 5064) to those servers at init time and issue name resolution requests over TCP in addition to issuing the UDP requests to addresses in EPICS_CA_ADDR_LIST.&lt;br /&gt;
&lt;br /&gt;
The CA server will be changed to forward the name resolution requests coming from TCP directly to the server tool.&lt;br /&gt;
&lt;br /&gt;
Servers that are not capable of handling name requests over TCP (e.g. older rsrv or CAS version) will be ignored, i.e. the client will not see the requested channels through TCP and not connect unless a different (name) server answers the request.&lt;br /&gt;
&lt;br /&gt;
== List of Necessary Changes ==&lt;br /&gt;
&lt;br /&gt;
=== CA Client ===&lt;br /&gt;
* tcpiiu changes&lt;br /&gt;
** add bool _nameService private member data flag&lt;br /&gt;
** pass bool nameService arg to tcpiiu constructor (setting private bool flag)&lt;br /&gt;
** if _nameService, constructor registers member SearchDest with cac&lt;br /&gt;
** if _nameService, destructor unregisters member SearchDest with cac&lt;br /&gt;
** if _nameService flag is set send thread sleeps and then tries to connect again if connect fails&lt;br /&gt;
** if _nameService flag set the receive thread, upon receiving disconnect notification from the socket&lt;br /&gt;
*** command send thread to exit&lt;br /&gt;
*** waits for send thread exit&lt;br /&gt;
*** (clear all buffers)&lt;br /&gt;
*** sleep&lt;br /&gt;
*** restarts the send thread&lt;br /&gt;
*** exits&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestTCP&lt;br /&gt;
** private member of type SearchDestTCP called _searchDest&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** implement SearchDest :: searchRequest () that issues a tcp search request if server is capable, else directly calls the Callback :: notify ()&lt;br /&gt;
&lt;br /&gt;
* udpiiu changes&lt;br /&gt;
** private member class deriving from SearchDest called SearchDestUDP&lt;br /&gt;
*** instances on the search list&lt;br /&gt;
** private member class deriving from SearchDest :: Callback called SearchRespCallback&lt;br /&gt;
*** implement SearchRespCallback  :: notify ()&lt;br /&gt;
** implement code calling Callback :: notify () when resp to search request arrives&lt;br /&gt;
** build udp search dest objects&lt;br /&gt;
*** remove &amp;quot;dest&amp;quot; member data&lt;br /&gt;
*** add private tsDLLList &amp;lt; SearchDest &amp;gt; list called _searchDestList&lt;br /&gt;
*** build address list ELLLIST using iocinf.c code parsing addr list and traversing NICs&lt;br /&gt;
*** for each member of this list create private SearchDest derived objects&lt;br /&gt;
*** install the SearchDest derived objects in _searchDestList&lt;br /&gt;
*** destroy ELLLIST members&lt;br /&gt;
** add public register/unregister SearchDest to udpiiu (called by cac)&lt;br /&gt;
&lt;br /&gt;
* cac changes&lt;br /&gt;
** code parsing EPICS_CA_NAME_SERVERS (in constructor?)&lt;br /&gt;
** creates tcpiiu specifying nameService is true to its constructor&lt;br /&gt;
** add public register/unregister SearchDest to cac (called by tcpiiu const and dest)&lt;br /&gt;
** in destructor guarantee that udpiiu is shutdown prior to deleting nameService tcpiiu&lt;br /&gt;
&lt;br /&gt;
=== CAS ===&lt;br /&gt;
''to be identified''&lt;br /&gt;
&lt;br /&gt;
=== rsrv ===&lt;br /&gt;
None.&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1830</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1830"/>
		<updated>2010-04-02T21:47:01Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Expression */  Added pointer for calc expression to AppDevGuide.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the conditional '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1832</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1832"/>
		<updated>2010-04-02T21:45:26Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Expression */ Added pointer for calc expression to AppDevGuide&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
'''NOTE:''' A complete description of the calculation expression can be found in the '''Application Developer's Guide''', chapter libCom / calc / Infix Expression Syntax (19.2.1 for EPICS 3.14.11).&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1817</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1817"/>
		<updated>2010-03-31T13:46:48Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Bitwise Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1816</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1816"/>
		<updated>2010-03-31T13:46:39Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Relational Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1815</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1815"/>
		<updated>2010-03-31T13:46:29Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Trigonometric Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1814</id>
		<title>RRM 3-14 Calculation</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calculation&amp;diff=1814"/>
		<updated>2010-03-31T13:46:20Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Algebraic Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calc - Calculation =&lt;br /&gt;
&lt;br /&gt;
The calculation or &amp;quot;Calc&amp;quot; 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 be used.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calc record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calc record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calc record consist 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 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. They cannot be hardware addresses.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
At the core of the Calc record lie the CALC and RPCL fields. The CALC field contains the infix expression which the record routine will use when it processes the record. The resulting value is placed in the VAL field and can be accessed from there. The CALC expression is actually converted to opcode and stored as 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 changed at run-time, and a special record routine calls a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the question mark or '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;DBF_STRING&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;DBF_NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression uses the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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 unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Expression Examples ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is unchanged if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to present meaningful data to the operator. These fields are used to display VAL and the other parameters of the calculation record either textually or graphically.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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, everytime the value changes, monitors are triggered; if they have a value of -1, everytime the record is scanned, monitors are triggered. See [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
A routine postfix is called to convert the infix expression in CALC to reverse polish notation. The result is stored in RPCL.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
  upper_alarm_limit = HIHI&lt;br /&gt;
  upper_warning_limit = HIGH&lt;br /&gt;
  lower_warning_limit = LOW&lt;br /&gt;
  lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
Routine process implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform, which calculates VAL from the postfix version of the expression given in CALC. If calcPerform returns success UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# Scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1818</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1818"/>
		<updated>2010-03-31T13:41:36Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Relational Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the conditional '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1812</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1812"/>
		<updated>2010-03-31T13:41:17Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Bitwise Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the conditional '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1811</id>
		<title>RRM 3-14 Calcout</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=RRM_3-14_Calcout&amp;diff=1811"/>
		<updated>2010-03-31T13:40:28Z</updated>

		<summary type="html">&lt;p&gt;RalphLange: /* Logical Operators */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[RRM 3-14|EPICS Record Reference Manual]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Calcout - Calculation Output Record =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Calculation Output or &amp;quot;Calcout&amp;quot; record is similar to the Calc record with the added feature of having outputs (an &amp;quot;output link&amp;quot; and an &amp;quot;output event&amp;quot;) 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.&lt;br /&gt;
&lt;br /&gt;
== Parameter Fields ==&lt;br /&gt;
&lt;br /&gt;
The fields in this record fall into these categories:&lt;br /&gt;
&lt;br /&gt;
* scan parameters&lt;br /&gt;
* read parameters&lt;br /&gt;
* expression parameters&lt;br /&gt;
* output parameters&lt;br /&gt;
* operator display parameters&lt;br /&gt;
* alarm parameters&lt;br /&gt;
* monitor parameters&lt;br /&gt;
* run-time parameters&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scan Parameters ===&lt;br /&gt;
&lt;br /&gt;
The Calcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in [[RRM 3-14 dbCommon#Scan Fields|Scan Fields]]. In addition, [[RRM 3-14 Concepts#Scanning Specification|Scanning Specification]] explains how these fields are used. Since the Calcout record supports no direct interfaces to hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot be &amp;lt;CODE&amp;gt;I/O Intr&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read Parameters ===&lt;br /&gt;
&lt;br /&gt;
The read parameters for the Calcout record consist 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 &amp;lt;CODE&amp;gt;dbPuts&amp;lt;/CODE&amp;gt;. 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 [[#Operator Display Parameters|Operator Display Parameters]] for an explanation of these fields.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 Concepts#Address Specification|Address Specification]] for information on how to specify database links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPA&amp;lt;TD&amp;gt;Input Link A&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPB&amp;lt;TD&amp;gt;Input Link B&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPC&amp;lt;TD&amp;gt;Input Link C&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPD&amp;lt;TD&amp;gt;Input Link D&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPE&amp;lt;TD&amp;gt;Input Link E&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPF&amp;lt;TD&amp;gt;Input Link F&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPG&amp;lt;TD&amp;gt;Input Link G&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPH&amp;lt;TD&amp;gt;Input Link H&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPI&amp;lt;TD&amp;gt;Input Link I&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPJ&amp;lt;TD&amp;gt;Input Link J&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPK&amp;lt;TD&amp;gt;Input Link K&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INPL&amp;lt;TD&amp;gt;Input Link L&amp;lt;TD&amp;gt;INLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Expression ===&lt;br /&gt;
&lt;br /&gt;
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 [[#Output Parameters|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 changed at run-time, and a special record routine will call a function to convert it to Reverse Polish Notation.&lt;br /&gt;
&lt;br /&gt;
The range of expressions supported by the calculation record are separated into operands, algebraic operators, trigonometric operators, relational operators, logical operators, parentheses and commas, and the conditional '?:' operator. The expression can consist of any of these operators, as well as any of the values from the input links which are the operands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CALC&amp;lt;TD&amp;gt;Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;VAL&amp;lt;TD&amp;gt;Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;RPCL&amp;lt;TD&amp;gt;Reverse Polish&amp;lt;TD&amp;gt;NOACCESS&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt; Also, the RNDM unary function can be included as an operand in the expression in order to generate a random number between 0 and 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operands ====&lt;br /&gt;
&lt;br /&gt;
The expression can use the values retrieved from the INP''x'' 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 simply referenced by the field letter. For instance, the value obtained from the 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;A&amp;lt;TD&amp;gt;Input Value A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;B&amp;lt;TD&amp;gt;Input Value B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;C&amp;lt;TD&amp;gt;Input Value C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;D&amp;lt;TD&amp;gt;Input Value D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;E&amp;lt;TD&amp;gt;Input Value E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;F&amp;lt;TD&amp;gt;Input Value F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;G&amp;lt;TD&amp;gt;Input Value G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;H&amp;lt;TD&amp;gt;Input Value H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;I&amp;lt;TD&amp;gt;Input Value I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;J&amp;lt;TD&amp;gt;Input Value J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;K&amp;lt;TD&amp;gt;Input Value K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;L&amp;lt;TD&amp;gt;Input Value L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes/No&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The keyword &amp;lt;tt&amp;gt;VAL&amp;lt;/tt&amp;gt; returns the current contents of the VAL field (which can be written to by a CA put, so it might ''not'' be the result from last time the expression was evaluated).&lt;br /&gt;
&lt;br /&gt;
==== Algebraic Operators ====&lt;br /&gt;
&lt;br /&gt;
* ABS: Absolute value (unary)&lt;br /&gt;
* SQR: Square root (unary)&lt;br /&gt;
* MIN: Minimum (any number of args)&lt;br /&gt;
* MAX: Maximum (any number of args)&lt;br /&gt;
* FINITE: returns non-zero if none of the arguments are NaN or Inf (any number of args)&lt;br /&gt;
* ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number of args)&lt;br /&gt;
* CEIL: Ceiling (unary)&lt;br /&gt;
* FLOOR: Floor (unary)&lt;br /&gt;
* LOG: Log base 10 (unary)&lt;br /&gt;
* LOGE: Natural log (unary)&lt;br /&gt;
* EXP: Exponential function (unary)&lt;br /&gt;
* ^: Exponential (binary)&lt;br /&gt;
* ** : Exponential (binary)&lt;br /&gt;
* + : Addition (binary)&lt;br /&gt;
* - : Subtraction (binary)&lt;br /&gt;
* * : Multiplication (binary)&lt;br /&gt;
* / : Division (binary)&lt;br /&gt;
* % : Modulo (binary)&lt;br /&gt;
* NOT: Negate (unary)&lt;br /&gt;
&lt;br /&gt;
==== Trigonometric Operators ====&lt;br /&gt;
&lt;br /&gt;
* SIN: Sine&lt;br /&gt;
* SINH: Hyperbolic sine&lt;br /&gt;
* ASIN: Arc sine&lt;br /&gt;
* COS: Cosine&lt;br /&gt;
* COSH: Hyperbolic cosine&lt;br /&gt;
* ACOS: Arc cosine&lt;br /&gt;
* TAN: Tangent&lt;br /&gt;
* TANH: Hyperbolic tangent&lt;br /&gt;
* ATAN: Arc tangent&lt;br /&gt;
&lt;br /&gt;
==== Relational Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;gt;= : Greater than or equal to&lt;br /&gt;
* &amp;amp;gt; : Greater than&lt;br /&gt;
* &amp;amp;lt;= : Less than or equal to&lt;br /&gt;
* &amp;amp;lt;: Less than&lt;br /&gt;
* # : Not equal to&lt;br /&gt;
* = : Equal to&lt;br /&gt;
&lt;br /&gt;
==== Logical Operators ====&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;amp;&amp;amp;amp; : And&lt;br /&gt;
* || : Or&lt;br /&gt;
* ! : Not&lt;br /&gt;
&lt;br /&gt;
==== Bitwise Operators ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* | : Bitwise Or&lt;br /&gt;
* &amp;amp;amp; : Bitwise And&lt;br /&gt;
* OR : Bitwise Or&lt;br /&gt;
* AND: Bitwise And&lt;br /&gt;
* XOR: Bitwise Exclusive Or&lt;br /&gt;
* ~ : One's Complement&lt;br /&gt;
* &amp;amp;lt;&amp;amp;lt; : Left shift&lt;br /&gt;
* &amp;amp;gt;&amp;amp;gt; : Right shift&lt;br /&gt;
&lt;br /&gt;
==== Parentheses and Comma ====&lt;br /&gt;
&lt;br /&gt;
The open and close parentheses are supported. Nested parenthesis are supported.&lt;br /&gt;
&lt;br /&gt;
The comma is supported when used to separate the arguments of a binary function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Conditional Expression ====&lt;br /&gt;
&lt;br /&gt;
The C language's question mark operator is supported. The format is:&lt;br /&gt;
&lt;br /&gt;
 condition ? True result : False result&lt;br /&gt;
&lt;br /&gt;
=== Example Expressions ===&lt;br /&gt;
&lt;br /&gt;
==== Algebraic ====&lt;br /&gt;
&lt;br /&gt;
 A + B + 10&lt;br /&gt;
&lt;br /&gt;
* Result is A + B + 10&lt;br /&gt;
&lt;br /&gt;
==== Relational ====&lt;br /&gt;
&lt;br /&gt;
 (A + B) &amp;amp;lt; (C + D)&lt;br /&gt;
&lt;br /&gt;
* Result is 1 if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is 0 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Question Mark ====&lt;br /&gt;
&lt;br /&gt;
 (A+B)&amp;amp;lt;(C+D)?E:F+L+10&lt;br /&gt;
&lt;br /&gt;
* Result is E if (A+B) &amp;amp;lt; (C+D)&lt;br /&gt;
* Result is F+L+10 if (A+B) &amp;amp;gt;= (C+D)&lt;br /&gt;
&lt;br /&gt;
==== Logical ====&lt;br /&gt;
&lt;br /&gt;
 A&amp;amp;amp;B&lt;br /&gt;
&lt;br /&gt;
* Causes the following to occur:&lt;br /&gt;
** Convert A to integer&lt;br /&gt;
** Convert B to integer&lt;br /&gt;
** Bit-wise And A and B&lt;br /&gt;
** Convert result to floating point&lt;br /&gt;
&lt;br /&gt;
=== Output Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. The OOPT field determines the condition that causes the output link to be written to. It's a menu field that has six choices:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Every Time&amp;lt;/CODE&amp;gt; -- write output every time record is processed.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;On Change&amp;lt;/CODE&amp;gt; -- write output every time VAL changes, i.e., every time the result of the expression changes.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;When Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output if VAL is non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is zero and last value was non-zero.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Transition To Non-zero&amp;lt;/CODE&amp;gt; -- when record is processed, write output only if VAL is non-zero and last value was zero.&lt;br /&gt;
&lt;br /&gt;
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: &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; or &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt;. If &amp;lt;CODE&amp;gt;Use CALC&amp;lt;/CODE&amp;gt; is specified, when the record writes its output it will write the result of the expression in the CALC record, that is, it will write the value of the VAL field. If &amp;lt;CODE&amp;gt;Use OCAL&amp;lt;/CODE&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;amp;quot;active&amp;amp;quot; 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 is system dependent.&lt;br /&gt;
&lt;br /&gt;
The IVOA field specifies what action to take with the OUT link if the Calcout record enters an INVALID alarm status. The options are &amp;lt;CODE&amp;gt;Continue normally&amp;lt;/CODE&amp;gt;, &amp;lt;CODE&amp;gt;Don't drive outputs&amp;lt;/CODE&amp;gt;, and &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;. If the IVOA field is &amp;lt;CODE&amp;gt;Set output to IVOV&amp;lt;/CODE&amp;gt;, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUT&amp;lt;TD&amp;gt;Output Specification&amp;lt;TD&amp;gt;OUTLINK&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;N/A&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OOPT&amp;lt;TD&amp;gt;Output Execute Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DOPT&amp;lt;TD&amp;gt;Output Data Option&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|RECCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCAL&amp;lt;TD&amp;gt; Output Calculation&amp;lt;TD&amp;gt;STRING[36]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OVAL&amp;lt;TD&amp;gt;Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OEVT&amp;lt;TD&amp;gt;Event To Issue&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ODLY&amp;lt;TD&amp;gt;Output Execution Delay&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOA&amp;lt;TD&amp;gt;Invalid Output Action&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;IVOV&amp;lt;TD&amp;gt;Invalid Output Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Operator Display Parameters ===&lt;br /&gt;
&lt;br /&gt;
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. An example of an interactive MEDM display screen that displays the status of the Calcout record is located here.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;CODE&amp;gt;get_units&amp;lt;/CODE&amp;gt; is called. The EGU string is solely for an operator's sake and does not have to be used.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The INAV-INLV fields indicate the status of the link to the PVs specified in the INPA-INPL fields, respectively. The field can have three possible values:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV NC&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link hasn't been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Ext PV OK&amp;lt;/CODE&amp;gt; -- the PV wasn't found on this IOC and a Channel Access link has been established.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Local PV&amp;lt;/CODE&amp;gt; -- the PV was found on this IOC.&lt;br /&gt;
* &amp;lt;CODE&amp;gt;Constant&amp;lt;/CODE&amp;gt; -- the corresponding link field is a constant.&lt;br /&gt;
&lt;br /&gt;
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.&lt;br /&gt;
&lt;br /&gt;
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.&lt;br /&gt;
&lt;br /&gt;
The DLYA field is set to one during the delay interval specified in ODLY.&lt;br /&gt;
&lt;br /&gt;
See [[RRM 3-14 dbCommon#Fields Common to All Record Types|Fields Common to All Record Types]] for more on the record name (NAME) and description (DESC) fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;EGU&amp;lt;TD&amp;gt;Engineering Units&amp;lt;TD&amp;gt;STRING [16]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;PREC&amp;lt;TD&amp;gt;Display Precision&amp;lt;TD&amp;gt;SHORT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HOPR&amp;lt;TD&amp;gt;High Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOPR&amp;lt;TD&amp;gt;Low Operating Range&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INAV&amp;lt;TD&amp;gt;Link Status of INPA&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INBV&amp;lt;TD&amp;gt;Link Status of INPB&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INCV&amp;lt;TD&amp;gt;Link Status of INPC&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INDV&amp;lt;TD&amp;gt;Link Status of INPD&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INEV&amp;lt;TD&amp;gt;Link Status of INPE&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INFV&amp;lt;TD&amp;gt;Link Status of INPF&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INGV&amp;lt;TD&amp;gt;Link Status of INPG&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INHV&amp;lt;TD&amp;gt;Link Status of INPH&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INIV&amp;lt;TD&amp;gt;Link Status of INPI&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INJV&amp;lt;TD&amp;gt;Link Status of INPJ&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INKV&amp;lt;TD&amp;gt;Link Status of INPK&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;INLV&amp;lt;TD&amp;gt;Link Status of INPL&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;1&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OUTV&amp;lt;TD&amp;gt;OUT PV Status&amp;lt;TD&amp;gt;RECCHOICE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;CLCV&amp;lt;TD&amp;gt;CALC Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;OCLV&amp;lt;TD&amp;gt;OCAL Valid&amp;lt;TD&amp;gt;LONG&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DLYA&amp;lt;TD&amp;gt;Output Delay Active&amp;lt;TD&amp;gt;USHORT&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;NAME&amp;lt;TD&amp;gt;Record Name&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;DESC&amp;lt;TD&amp;gt;Description&amp;lt;TD&amp;gt;STRING [29]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Null&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alarm Parameters ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
The HYST field defines an alarm deadband for each limit. See [[RRM 3-14 Concepts#Alarm Specification|Alarm Specification]] for a complete explanation of alarms and these fields. [[RRM 3-14 dbCommon#Alarm Fields|Alarm Fields]] lists other fields related to a alarms that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIHI&amp;lt;TD&amp;gt;Hihi Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HIGH&amp;lt;TD&amp;gt;High Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOW&amp;lt;TD&amp;gt;Low Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LOLO&amp;lt;TD&amp;gt;Lolo Alarm Limit&amp;lt;TD&amp;gt;FLOAT&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HHSV&amp;lt;TD&amp;gt;Severity for a Hihi Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HSV&amp;lt;TD&amp;gt;Severity for a High Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LSV&amp;lt;TD&amp;gt;Severity for a Low Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LLSV&amp;lt;TD&amp;gt;Severity for a Lolo Alarm&amp;lt;TD&amp;gt;[[RRM 3-14 Menu Choices|GBLCHOICE]]&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;Yes&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;HYST&amp;lt;TD&amp;gt;Alarm Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Monitor Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters are used to determine when to send monitors for the value fields. The 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 [[RRM 3-14 Concepts#Monitor Specification|Monitor Specification]] for a complete explanation of monitors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ADEL&amp;lt;TD&amp;gt;Archive Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MDEL&amp;lt;TD&amp;gt;Monitor, i.e. value change, Deadband&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time Parameters ===&lt;br /&gt;
&lt;br /&gt;
These fields are not configurable using a configuration too and none are modifiable at run-time. They are used to process the record.&lt;br /&gt;
&lt;br /&gt;
The LALM field is used to implement the hysteresis factor for the alarm limits.&lt;br /&gt;
&lt;br /&gt;
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 MLST fields are used in the same manner for the VAL field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;TABLE BORDER=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;TH&amp;gt;Field&amp;lt;TH&amp;gt;Summary&amp;lt;TH&amp;gt;Type&amp;lt;TH&amp;gt;DCT&amp;lt;TH&amp;gt;Initial&amp;lt;TH&amp;gt;Access&amp;lt;TH&amp;gt;Modify&amp;lt;TH&amp;gt;Rec Proc Monitor&amp;lt;TH&amp;gt;PP&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LALM&amp;lt;TD&amp;gt;Last Alarmed Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;ALST&amp;lt;TD&amp;gt;Archive Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;MLST&amp;lt;TD&amp;gt;Monitor Last Value&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LA&amp;lt;TD&amp;gt;Previous Input Value for A&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LB&amp;lt;TD&amp;gt;Previous Input Value for B&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LC&amp;lt;TD&amp;gt;Previous Input Value for C&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LD&amp;lt;TD&amp;gt;Previous Input Value for D&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LE&amp;lt;TD&amp;gt;Previous Input Value for E&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LF&amp;lt;TD&amp;gt;Previous Input Value for F&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LG&amp;lt;TD&amp;gt;Previous Input Value for G&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LH&amp;lt;TD&amp;gt;Previous Input Value for H&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LI&amp;lt;TD&amp;gt;Previous Input Value for I&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LJ&amp;lt;TD&amp;gt;Previous Input Value for J&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LK&amp;lt;TD&amp;gt;Previous Input Value for K&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TR&amp;gt;&lt;br /&gt;
&amp;lt;TD&amp;gt;LL&amp;lt;TD&amp;gt;Previous Input Value for L&amp;lt;TD&amp;gt;DOUBLE&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;0&amp;lt;TD&amp;gt;Yes&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&amp;lt;TD&amp;gt;No&lt;br /&gt;
&amp;lt;/TABLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Record Support ==&lt;br /&gt;
&lt;br /&gt;
=== Record Support Routines ===&lt;br /&gt;
&lt;br /&gt;
==== init_record ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
See next section.&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&lt;br /&gt;
This is called if CALC or OCAL is changed. special calls postfix.&lt;br /&gt;
&lt;br /&gt;
==== get_value ====&lt;br /&gt;
&lt;br /&gt;
Fills in the values of struct valueDes so that they refer to VAL.&lt;br /&gt;
&lt;br /&gt;
==== get_units ====&lt;br /&gt;
&lt;br /&gt;
Retrieves EGU.&lt;br /&gt;
&lt;br /&gt;
==== get_precision ====&lt;br /&gt;
&lt;br /&gt;
Retrieves PREC.&lt;br /&gt;
&lt;br /&gt;
==== get_graphic_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_control_double ====&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==== get_alarm_double ====&lt;br /&gt;
&lt;br /&gt;
Sets the following values:&lt;br /&gt;
&lt;br /&gt;
 upper_alarm_limit = HIHI&lt;br /&gt;
 upper_warning_limit = HIGH&lt;br /&gt;
 lower_warning_limit = LOW&lt;br /&gt;
 lower_alarm_limit = LOLO&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Record Processing ===&lt;br /&gt;
&lt;br /&gt;
==== process() ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;CODE&amp;gt;process()&amp;lt;/CODE&amp;gt; routine implements the following algorithm:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Fetch all arguments.&lt;br /&gt;
# Call routine calcPerform(), which calculates VAL from the postfix version of the expression given in CALC. If calcPerform() returns success, UDF is set to FALSE.&lt;br /&gt;
# 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.&lt;br /&gt;
# Determine if the Output Execution Option (OOPT) is met. If it is 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 &amp;lt;CODE&amp;gt;execOutput()&amp;lt;/CODE&amp;gt; routine below.&lt;br /&gt;
# Check to see if monitors should be invoked.&lt;br /&gt;
#* Alarm monitors are invoked if the alarm status or severity has changed.&lt;br /&gt;
#* Archive and value change monitors are invoked if ADEL and MDEL conditions are met.&lt;br /&gt;
#* Monitors for A-L are checked whenever other monitors are invoked.&lt;br /&gt;
#* NSEV and NSTA are reset to 0.&lt;br /&gt;
# If no output delay was specified, scan forward link if necessary, set PACT FALSE, and return.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== execOutput() ====&lt;br /&gt;
&lt;br /&gt;
# If DOPT field specifies the use of OCAL, call the routine calcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.&lt;br /&gt;
# If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.&lt;br /&gt;
# If the Alarm Severity is not INVALID or IVOA specifies &amp;amp;quot;Continue Normally&amp;amp;quot;, put the value of OVAL to the OUT link and post the event in OEVT (if non-zero).&lt;br /&gt;
# If an output delay was implemented, process the forward link.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
EPICS Record Reference Manual - 19 MAY 1998&lt;/div&gt;</summary>
		<author><name>RalphLange</name></author>
	</entry>
</feed>