Difference between revisions of "RRM 3-13 String Calcout"
(First cut) |
m |
||
(10 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= sCalcout Record = | = sCalcout Record = | ||
The String Calculation Output or "sCalcout" record is derived from the Calcout record and extends it by supporting string expressions | <i>This page actually describes the EPICS-3.14-compatible version of the sCalcout record. Text that does not apply to the 3.13-compatible version is rendered in <font color="blue">blue</font>. Documentation specific to the 3.13-compatible version is currently not available in this format, but may be found in the 'std' module of a 3.13-compatible synApps package.</i> | ||
The String Calculation Output or "sCalcout" record is derived from the Calcout record and extends it by supporting string expressions and operands. The record has 12 numeric fields (A...L) and 12 string fields (AA...LL), which are used as input variables for the expression. It calls an extended version of the EPICS calculation engine that accepts string arguments, supports a variety of string functions, and produces both numeric and string results, in the VAL and SVAL fields, respectively. The record's output link writes string or numeric data, depending on the data type of the field to which it is linked. | |||
== Parameter Fields == | == Parameter Fields == | ||
The fields in this record fall into | The fields in this record fall into the following categories: | ||
* | * Scan Parameters | ||
* | * Read Parameters | ||
* | * Expression Parameters | ||
* | * Output Parameters | ||
* | * Operator Display Parameters | ||
* | * Alarm Parameters | ||
* Monitor Parameters | |||
* Run-Time Parameters | |||
=== Scan Parameters === | === Scan Parameters === | ||
Line 21: | Line 25: | ||
=== Read Parameters === | === Read Parameters === | ||
The read parameters for the sCalcout record consist of 24 input links: 12 | The read parameters for the sCalcout record consist of 24 input links: 12 for numeric values (INPA→A, INPB→B, ... INPL→L); and 12 for string values (INAA→AA, INBB→BB, ... INLL→LL). The fields can be database links, channel access links, or constants. If they are links, they must contain a PV name. If they are constants, associated value fields will be initialized with the constants. These fields cannot be hardware addresses. In addition, the sCalcout record contains the fields INAV, INBV, ... INLV, which indicate the status of the links to numeric fields, and the fields IAAV, IBBV, ... ILLV, which indicate the status of the links to string fields. These fields indicate 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. | ||
See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on how to specify database links. | See [[RRM 3-13 Concepts#Address Specification|Address Specification]] for information on how to specify database links. | ||
Line 27: | Line 31: | ||
<TABLE BORDER="1"> | <TABLE BORDER="1"> | ||
<TH>Field<TH>Summary<TH>Type<TH>DCT<TH>Initial<TH>Access<TH>Modify<TH>Rec Proc Monitor<TR> | <TR><TH>Field<TH>Summary<TH>Type<TH>DCT<TH>Initial<TH>Access<TH>Modify<TH>Rec Proc Monitor | ||
<TD>INPA<TD>Input Link A<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes<TR> | <TR><TD>INPA<TD>Input Link A<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
<TD>INPB<TD>Input Link B<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes<TR> | <TR><TD>INPB<TD>Input Link B<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TR> | <TR><TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>... | ||
<TD>INPL<TD>Input Link L<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | <TR><TD>INPL<TD>Input Link L<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
<TD>INAA<TD>Input Link AA<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes<TR> | <TR><TD>INAA<TD>Input Link AA<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
<TD>INBB<TD>Input Link BB<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes<TR> | <TR><TD>INBB<TD>Input Link BB<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TR> | <TR><TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>...<TD>... | ||
<TD>INLL<TD>Input Link LL<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | <TR><TD>INLL<TD>Input Link LL<TD>INLINK<TD>Yes<TD>0<TD>Yes<TD>Yes<TD>Yes | ||
</TABLE> | </TABLE> | ||
=== Expression Parameters === | === Expression Parameters === | ||
<TABLE BORDER> | <TABLE BORDER> | ||
Line 88: | Line 60: | ||
<TR> | <TR> | ||
<TD> | <TD>CALC</TD> | ||
<TD> | <TD>Infix expression</TD> | ||
<TD> | <TD>String[40]</TD> | ||
<TD> | <TD>Yes</TD> | ||
<TD> | <TD>""</TD> | ||
<TD>Yes</TD> | <TD>Yes</TD> | ||
<TD>Yes</TD> | <TD>Yes</TD> | ||
<TD>Yes</TD> | <TD>Yes</TD> | ||
<TD>No</TD> | |||
</TR> | </TR> | ||
<TR> | <TR> | ||
<TD>B</TD> | <TD>CLCV</TD> | ||
<TD>CALC Valid</TD> | |||
<TD>Input Value B</TD> | <TD>Long</TD> | ||
<TD>DOUBLE</TD> | <TD>No</TD> | ||
<TD>No</TD> | <TD>0</TD> | ||
<TD>0</TD> | <TD>Yes</TD> | ||
<TD>Yes</TD> | <TD>No</TD> | ||
<TD>Yes/No*</TD> | <TD>Yes</TD> | ||
<TD>Yes</TD> | <TD>No</TD> | ||
<TD>Yes</TD> | </TR> | ||
</TR> | |||
<TR> | |||
<TR> | <TD>OCAL</TD> | ||
<TD>...</TD> | <TD>Infix expression</TD> | ||
<TD>...</TD> | <TD>String[40]</TD> | ||
<TD>...</TD> | <TD>Yes</TD> | ||
<TD>...</TD> | <TD>""</TD> | ||
<TD>...</TD> | <TD>Yes</TD> | ||
<TD>...</TD> | <TD>Yes</TD> | ||
<TD>...</TD> | <TD>Yes</TD> | ||
<TD>...</TD> | <TD>No</TD> | ||
<TD>...</TD> | </TR> | ||
</TR> | |||
<TR> | |||
<TD>OCLV</TD> | |||
<TR> | <TD>OCAL Valid</TD> | ||
<TD>L</TD> | <TD>Long</TD> | ||
<TD>Input Value L</TD> | <TD>No</TD> | ||
<TD>DOUBLE</TD> | <TD>0</TD> | ||
<TD>No</TD> | <TD>Yes</TD> | ||
<TD>0</TD> | <TD>No</TD> | ||
<TD>Yes</TD> | <TD>Yes</TD> | ||
<TD>Yes/No*</TD> | <TD>No</TD> | ||
<TD>Yes</TD> | </TR> | ||
</TABLE> | |||
Like the Calcout record, the sCalcout record has the fields CALC and OCAL, in which the developer or user can enter an infix expression to be evaluated when the record is processed. The numeric value resulting from evaluation of CALC will be placed in the VAL field, and the resulting string value will be placed in the SVAL field. VAL 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. Either VAL and SVAL can also be written to the output link. (If you elect to write an output value, the record will choose between VAL and SVAL, depending on the data type of the field at the other end of the output link.) | |||
The CALC and OCAL expressions are actually converted to opcodes and stored in postfix notation in the RPCL and ORPC fields. It is these expressions which are actually used to calculate VAL. A postfix expression can be evaluated more efficiently at run-time than an infix expression would be. When CALC or OCAL is changed at run-time, the record-support routine special() will call a function to check it, and convert it to postfix. | |||
In simple cases, OCAL is ignorable. It's use will be described later, in [[#Output Parameters|Output Parameters]]. | |||
sCalcout-record expressions are very similar to standard EPICS Calc expressions, such as those used with the Calcout record. But in place of the standard EPICS calc engine (which does not support string fields or operations), sCalcout-record uses the <i>sCalc</i> engine, a separate piece of software, which normally is [[#Availability|distributed]] with the sCalcout record. The differences between these engines that matter for numeric expressions are the following: | |||
* The constants S2R (arc-seconds-to-radians) and R2S are supported. | |||
* <font color="blue">The functions MIN() and MAX() may have more than two arguments.</font> | |||
* <font color="blue">The binary operators '>&' (larger of the operands) and '<&' (smaller) are supported.</font> | |||
* The binary operator '!=' (not equal) is a permitted alternatives '#'. | |||
* The unary operator '@' selects an input field by number. (E.g., '@0' means 'A'. If 'B' has the value 3, '@b' means 'D'.) | |||
Expressions supported by the sCalcout record can involve operands, algebraic operators and functions, trigonometric functions, relational operators, logical operators, string operators and functions, parentheses and commas, and the conditional '?:' operator. Numeric and string operands are supported, and | |||
any operand can be used with any operator or function. If an operand has the "wrong" type for the function or operator with which it is used, the operand will be converted implicitly to the correct type. | |||
Grouping of operands with parentheses is important not only to specify the order in which operations are to be performed, but also to distinguish operands from operators whose names are spelled out, such as the logical operator 'AND'. For example, the expression 'AANDB', which could have meant 'A AND B', will be (mis)interpreted by the parser as 'AA NDB'. | |||
==== Operands ==== | |||
The expression can use the values retrieved from the input links as operands, though constants can be used as operands too. These values retrieved from the input links are stored in the A-L, and AA-LL fields. The values to be used in the expression are simply referenced by the field name. For example, 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. | |||
<TABLE BORDER> | |||
<TR> | |||
<TH>Field</TH> | |||
<TH>Summary</TH> | |||
<TH>Type</TH> | |||
<TH>DCT</TH> | |||
<TH>Initial</TH> | |||
<TH>Access</TH> | |||
<TH>Modify</TH> | |||
<TH>Rec Proc Monitor</TH> | |||
<TH>PP</TH> | |||
</TR> | |||
<TR> | |||
<TD>A</TD> | |||
<TD>Input Value A</TD> | |||
<TD>DOUBLE</TD> | |||
<TD>No</TD> | |||
<TD>0</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes/No*</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes</TD> | |||
</TR> | |||
<TR> | |||
<TD>B</TD> | |||
<TD>Input Value B</TD> | |||
<TD>DOUBLE</TD> | |||
<TD>No</TD> | |||
<TD>0</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes/No*</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes</TD> | |||
</TR> | |||
<TR> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
<TD>...</TD> | |||
</TR> | |||
<TR> | |||
<TD>L</TD> | |||
<TD>Input Value L</TD> | |||
<TD>DOUBLE</TD> | |||
<TD>No</TD> | |||
<TD>0</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes/No*</TD> | |||
<TD>Yes</TD> | |||
<TD>Yes</TD> | <TD>Yes</TD> | ||
</TR> | </TR> | ||
Line 189: | Line 247: | ||
</TABLE> | </TABLE> | ||
Legend: * If a | Legend: * If a non-blank input link is associated with this field, then it may | ||
not be modified. | not be modified. This is true even if the input link is invalid (in which case, the value will be 0, for a numeric field, or "Huh?", for a string field). | ||
There are a few special operands not associated with input fields, but | There are a few special operands not associated with input fields, but | ||
Line 246: | Line 304: | ||
<tr> | <tr> | ||
<td align=center valign=top>MIN | <td align=center valign=top>MIN | ||
<td valign=top>Minimum (two-or-more-argument function) | <td valign=top>Minimum (two<font color="blue">-or-more</font>-argument function) | ||
<td><code>MIN(A,B | <td><code>MIN(A,B)</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>MAX | <td align=center valign=top>MAX | ||
<td valign=top>Maximum (two-or-more-argument function) | <td valign=top>Maximum (two<font color="blue">-or-more</font>-argument function) | ||
<td><code>MAX(A,B | <td><code>MAX(A,B)</code> | ||
<tr> | <tr> | ||
Line 339: | Line 397: | ||
<td valign=top>Negate (unary) | <td valign=top>Negate (unary) | ||
<td><code>NOT A</code> | <td><code>NOT A</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>>& | <td align=center valign=top><font color="blue">>&</font> | ||
<td valign=top>Max (binary) | <td valign=top><font color="blue">Max (binary)</font> | ||
<td><code>A>?B</code> | <td><font color="blue"><code>A>?B</code></font> | ||
<tr> | <tr> | ||
<td align=center valign=top><& | <td align=center valign=top><font color="blue"><&</font> | ||
<td valign=top>Min (binary) | <td valign=top><font color="blue">Min (binary)</font> | ||
<td><code>A<?B</code> | <td><font color="blue"><code>A<?B</code></font> | ||
</table> | </table> | ||
Line 571: | Line 629: | ||
<tr> | <tr> | ||
<td align=center valign=top>MIN | <td align=center valign=top>MIN | ||
<td valign=top>Minimum lexically (two-or-more-argument function) | <td valign=top>Minimum lexically (two<font color="blue">-or-more</font>-argument function) | ||
<td><code> | <td><code>MIN('a','b') </code>→<code> 'a'</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>MAX | <td align=center valign=top>MAX | ||
<td>Maximum lexically (two-or-more-argument function) | <td>Maximum lexically (two<font color="blue">-or-more</font>-argument function) | ||
<td><code>MAX('a','b | <td><code>MAX('a','b') </code>→<code> 'b'</code> | ||
<tr> | <tr> | ||
Line 583: | Line 641: | ||
<td>Find first number in string; return nearest integer (one-argument | <td>Find first number in string; return nearest integer (one-argument | ||
function) | function) | ||
<td><code>INT('1.9') | <td><code>INT('1.9') </code>→<code> 1</code><br> | ||
< | <code>INT('abc1.9') </code>→<code> 1</code> | ||
<tr> | <tr> | ||
Line 590: | Line 648: | ||
<td>Find first number in string; return nearest integer (one-argument | <td>Find first number in string; return nearest integer (one-argument | ||
function) | function) | ||
<td><code>NINT('1.9') | <td><code>NINT('1.9') </code>→<code> 2</code><br> | ||
< | <code>NINT('abc1.9') </code>→<code> 2</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>+ | <td align=center valign=top>+ | ||
<td>Concatenate (binary) | <td>Concatenate (binary) | ||
<td><code>'a'+'b' | <td><code>'a'+'b' </code>→<code> 'ab'</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>- | <td align=center valign=top>- | ||
<td>Delete first occurrence of substring (binary) | <td>Delete first occurrence of substring (binary) | ||
<td><code>'abca'-'a' | <td><code>'abca'-'a' </code>→<code> 'bca'</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>-| | <td align=center valign=top><font color="blue">-|</font> | ||
<td>Delete first occurrence of substring (binary) | <td><font color="blue">Delete first occurrence of substring (binary)</font> | ||
<td><code>'abca'-'a' | <td><font color="blue"><code>'abca'-'a' </code>→<code> 'bca'</code></font> | ||
<tr> | <tr> | ||
<td align=center valign=top>|- | <td align=center valign=top><font color="blue">|-</font> | ||
<td>Delete last occurrence of substring (binary) | <td><font color="blue">Delete last occurrence of substring (binary)</font> | ||
<td><code>'abca'-'a' | <td><font color="blue"><code>'abca'-'a' </code>→<code> 'abc'</code></font> | ||
<tr> | <tr> | ||
<td align=center valign=top>>= | <td align=center valign=top>>= | ||
<td>Lexically greater than or equal (binary) | <td>Lexically greater than or equal (binary) | ||
<td><code>'a'>='b' | <td><code>'a'>='b' </code>→<code> 0</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>> | <td align=center valign=top>> | ||
<td>Lexically greater than (binary) | <td>Lexically greater than (binary) | ||
<td><code>'a'>'b' | <td><code>'a'>'b' </code>→<code> 0</code> | ||
<tr> | <tr> | ||
<td align=center valign=top><= | <td align=center valign=top><= | ||
<td>Lexically less than or equal (binary) | <td>Lexically less than or equal (binary) | ||
<td><code>'a'<='b' | <td><code>'a'<='b' </code>→<code> 1</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>< | <td align=center valign=top>< | ||
<td>Lexically less than (binary) | <td>Lexically less than (binary) | ||
<td><code>'a'<'b' | <td><code>'a'<'b' </code>→<code> 1</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>!= | <td align=center valign=top>!= | ||
<td>Lexically not equal to (binary) | <td>Lexically not equal to (binary) | ||
<td><code>'a'!='b' | <td><code>'a'!='b' </code>→<code> 1</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>== | <td align=center valign=top>== | ||
<td>Lexically equal to (binary) | <td>Lexically equal to (binary) | ||
<td><code>'a'=='b' | <td><code>'a'=='b' </code>→<code> 0</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>DBL | <td align=center valign=top>DBL | ||
<td>Convert argument to double (one-argument function) | <td>Convert argument to double (one-argument function) | ||
<td><code>DBL('1') | <td><code>DBL('1') </code>→<code> 1.0</code><br> | ||
< | <code>DBL('abc1.23') </code>→<code> 1.23</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>STR | <td align=center valign=top>STR | ||
<td>Convert argument to string (one-argument function) | <td>Convert argument to string (one-argument function) | ||
<td><code>STR(1) | <td><code>STR(1) </code>→<code> '1.00000000'</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>BYTE | <td align=center valign=top>BYTE | ||
<td>Convert first character of string argument to double (one-argument function) | <td>Convert first character of string argument to double (one-argument function) | ||
<td><code>BYTE('abc') | <td><code>BYTE('abc') </code>→<code> 97.0</code> | ||
<tr> | <tr> | ||
Line 666: | Line 724: | ||
<BR>Allowed format indicators: <B>%cdeEfgGiosuxX</B> | <BR>Allowed format indicators: <B>%cdeEfgGiosuxX</B> | ||
<BR>Disallowed indicators:<B> *</B> | <BR>Disallowed indicators:<B> *</B> | ||
<td><code>PRINTF("%.2f",1.23) | <td><code>PRINTF("%.2f",1.23) </code>→<code> '1.23'</code> | ||
<tr> | <tr> | ||
Line 675: | Line 733: | ||
<BR>Allowed format indicators: <B>%*[cdeEfgGhilosuxX</B> | <BR>Allowed format indicators: <B>%*[cdeEfgGhilosuxX</B> | ||
<BR>Disallowed indicators: <B>$npw</B> | <BR>Disallowed indicators: <B>$npw</B> | ||
<td><code>SSCANF('V=1.25', "%*2c%lf") | <td><code>SSCANF('V=1.25', "%*2c%lf") </code>→<code> 1.25</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>TR_ESC | <td align=center valign=top><font color="blue">TR_ESC</font> | ||
<td>Translate escape sequences into the characters they represent | <td><font color="blue">Translate escape sequences into the characters they represent | ||
(one-argument function). (NOTE: '$T' is a synonym for TR_ESC.) | (one-argument function). (NOTE: '$T' is a synonym for TR_ESC.) | ||
<BR>TR_ESC() applies dbTranslateEscape() to its argument. | <BR>TR_ESC() applies dbTranslateEscape() to its argument. | ||
<BR>This function is approximately the opposite of ESC(). | <BR>This function is approximately the opposite of ESC(). | ||
<BR>An escaped null character will terminate the result string | <BR>An escaped null character will terminate the result string</font> | ||
<td><code>TR_ESC("a\x62c") | <td><font color="blue"><code>TR_ESC("a\x62c") </code>→<code> 'abc'</code></font> | ||
<tr> | <tr> | ||
<td align=center valign=top>ESC | <td align=center valign=top><font color="blue">ESC</font> | ||
<td>Translate escape characters into equivalent escape sequences. | <td><font color="blue">Translate escape characters into equivalent escape sequences. | ||
(one-argument function) (NOTE: '$E' is a synonym for ESC) | (one-argument function) (NOTE: '$E' is a synonym for ESC) | ||
<BR>ESC() applies epicsStrSnEscaped() to its argument. | <BR>ESC() applies epicsStrSnEscaped() to its argument. | ||
Line 694: | Line 752: | ||
<BR>The first null character found in the input string terminates it. | <BR>The first null character found in the input string terminates it. | ||
If there is no null chaacter, the string is assumed to be 40 | If there is no null chaacter, the string is assumed to be 40 | ||
characters long. | characters long.</font> | ||
<td><code>ESC("a<return>c") | <td><font color="blue"><code>ESC("a<return>c") </code>→<code> 'a\rc'</code></font> | ||
<tr> | <tr> | ||
<td align=center valign=top>[ | <td align=center valign=top>[ | ||
<td>Substring | <td>Substring | ||
<td><code>'abcdef'[1,3] | <td><code>'abcdef'[1,3] </code>→<code> 'bcd'</code> | ||
<code><BR>'abcdef'['ab','ef'] | <code><BR>'abcdef'['ab','ef'] </code>→<code> 'cd'</code> | ||
<code><BR>'abcdef'[0,-1] | <code><BR>'abcdef'[0,-1] </code>→<code> 'abcdef'</code> | ||
<tr> | <tr> | ||
<td align=center valign=top>{ | <td align=center valign=top>{ | ||
<td>Substring substitution | <td>Substring substitution | ||
<td><code>'abcdef'{'cd','XX'} | <td><code>'abcdef'{'cd','XX'} </code>→<code> 'abXXef'</code> | ||
<tr> | <tr> | ||
Line 775: | Line 833: | ||
===== String Examples ===== | ===== String Examples ===== | ||
A + "abc" | A + "abc"<br> | ||
A + "abc1.2" | A + "abc1.2"<br> | ||
A + AA (where AA = "abc1.2") | A + AA (where AA = "abc1.2") | ||
Result is A. The strings "abc" and "abc1.2" will be converted implicitly to the number 0. | :Result is A. The strings "abc" and "abc1.2" will be converted implicitly to the number 0. | ||
A + DBL("abc1.2") | A + DBL("abc1.2") | ||
Result is A + 1.2. Explicit conversion to a number (by DBL, INT, or NINT) is more aggressive than implicit conversion, and skips leading non-numeric characters. | :Result is A + 1.2. Explicit conversion to a number (by DBL, INT, or NINT) is more aggressive than implicit conversion, and skips leading non-numeric characters. | ||
"abc" + "def" | "abc" + "def" | ||
Result is "abcdef". | :Result is "abcdef". | ||
PRINTF("abc%1.2f", A) (where A = 1.2345) | PRINTF("abc%1.2f", A) (where A = 1.2345) | ||
Result is "abc1.23". | :Result is "abc1.23". | ||
NOTE: unlike the c-language function | :NOTE: unlike the c-language function printf(<format>,<arg1>,<arg2>,...), this function accepts only one argument after the format string. | ||
printf(<format>,<arg1>,<arg2>,...), | |||
this function accepts only one argument after the format string. | |||
SSCANF(AA, "%*3c%lf") (where AA = "abc1.2") | SSCANF(AA, "%*3c%lf") (where AA = "abc1.2") | ||
Result is "1.20000000". (The format fragment "%*3c" directs sscanf to ignore three characters.) | :Result is "1.20000000". (The format fragment "%*3c" directs sscanf to ignore three characters.)<br> | ||
NOTE: unlike the c-language function | :NOTE: unlike the c-language function sscanf(<source>,<format>,<dest1>,<dest2>,...), this function cannot store to a variable, but only to the value stack. | ||
sscanf(<source>,<format>,<dest1>,<dest2>,...), | |||
this function cannot store to a variable, but only to the value stack. | |||
BYTE("ABC") | BYTE("ABC") | ||
Result is 65, the ASCII code for "A" in decimal. | :Result is 65, the ASCII code for "A" in decimal. | ||
"abcdef"[2,4] | "abcdef"[2,4] | ||
Result is "cde". (The first character of the string is numbered "0".) | :Result is "cde". (The first character of the string is numbered "0".) | ||
"abcdef"[-2,-1] | "abcdef"[-2,-1] | ||
Result is "ef". (The last character of the string is numbered "-1".) | :Result is "ef". (The last character of the string is numbered "-1".) | ||
"abcdef"["ab","ef"] | "abcdef"["ab","ef"] | ||
Result is "cd". (If the first argument is a string, it returns the index of the first character after a successful match, or the first character in the string if no match was found. If the second argument is a string, it returns the index of the last character before a successful match, or the last character in the string if no match was found.) | :Result is "cd". (If the first argument is a string, it returns the index of the first character after a successful match, or the first character in the string if no match was found. If the second argument is a string, it returns the index of the last character before a successful match, or the last character in the string if no match was found.) In other words, string arguments <i>delimit</i> the substring they are specifying without participating in it.) | ||
A==2 ? "yes" : "no" | A==2 ? "yes" : "no" | ||
Result is "yes" if A == 2; otherwise, result is "no". | :Result is "yes" if A == 2; otherwise, result is "no". | ||
"abcdef"{"bcd","dcb"} | "abcdef"{"bcd","dcb"} | ||
Result is "adcbef". | :Result is "adcbef". | ||
"abcdef"{"zzz","dcb"} | "abcdef"{"zzz","dcb"} | ||
Result is "abcdef". (If no match, then no replacement.) | :Result is "abcdef". (If no match, then no replacement.) | ||
"abcdef"[1,-2][1,-2] | "abcdef"[1,-2][1,-2] | ||
Result is "cd" | :Result is "cd" | ||
===== Array Examples ===== | ===== Array Examples ===== | ||
@0 | @0 | ||
Result | :Result is the value of the numeric variable A. ("@0" is just another name for A.) | ||
@@0 | @@0 | ||
Result | :Result is the value of the string variable AA. | ||
@(A+B) | @(A+B) | ||
Result | :Result is the value of the numeric variable whose number is given by the sum of A and B. | ||
=== Output Parameters === | === Output Parameters === | ||
These parameters specify and control the output capabilities of the | These parameters specify and control the output capabilities of the | ||
sCalcout record. They determine when to write the output, where to write | sCalcout 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 | 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 | 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 | that causes the output link to be written to. It's a menu field that has | ||
six choices: | six choices: | ||
<table border> | |||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>Every Time</TT><td valign=top>write output every time record is processed. | <TT>Every Time</TT><td valign=top>write output every time record is processed. | ||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>On Change</TT><td valign=top>write output every time VAL changes, i.e., every | <TT>On Change</TT><td valign=top>write output every time VAL changes, i.e., every time the result of the expression changes. | ||
time the result of the expression changes. | |||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>When Zero</TT><td valign=top>when record is processed, write output if VAL is | <TT>When Zero</TT><td valign=top>when record is processed, write output if VAL is zero. | ||
zero. | |||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>When Non-zero</TT><td valign=top>when record is processed, write output if VAL | <TT>When Non-zero</TT><td valign=top>when record is processed, write output if VAL is non-zero. | ||
is non-zero. | |||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>Transition to Zero</TT><td valign=top>when record is processed, write output only | <TT>Transition to Zero</TT><td valign=top>when record is processed, write output only if VAL is zero and last value was non-zero. | ||
if VAL is zero and last value was non-zero. | |||
<tr><td valign=top> | <tr><td valign=top> | ||
<TT>Transition to Non-zero</TT><td valign=top>when record is processed, write output | <TT>Transition to Non-zero</TT><td valign=top>when record is processed, write output only if VAL is non-zero and last value was zero. | ||
only if VAL is non-zero and last value was zero. | |||
<tr><td valign=top> | <tr><td valign=top> | ||
Line 878: | Line 920: | ||
The DOPT field determines what data is written to the output link when | 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: <TT>Use | the output is executed. The field is a menu field with two options: <TT>Use | ||
Line 887: | Line 928: | ||
the record will instead write the result of the expression in the OCAL | the record will instead write the result of the expression in the OCAL | ||
field, which is contained in the OVAL field (string result in the OSV) | field, which is contained in the OVAL field (string result in the OSV) | ||
field. The OCAL field is exactly like the CALC field and has the same functionality: | 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. | ||
it can contain the string representation of an expression which is evaluated | |||
at run-time. Thus, if necessary, the record can use the result of the CALC | |||
expression to determine if data should be written and can use the result | |||
of the OCAL expression as the data to write. | |||
If the OEVT field specifies a non-zero integer and the condition | |||
in the OOPT field is met, the record will post a corresponding event. If | 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 | the ODLY field is non-zero, the record pauses for the specified number | ||
Line 902: | Line 939: | ||
<TT>tickLib</TT>). | <TT>tickLib</TT>). | ||
The IVOA field specifies what action to take with the OUT link | |||
if the sCalcout record enters an INVALID alarm status. The options are | if the sCalcout record enters an INVALID alarm status. The options are | ||
<TT>Continue normally</TT>, <TT>Don't drive outputs</TT>, and <TT>Set output | <TT>Continue normally</TT>, <TT>Don't drive outputs</TT>, and <TT>Set output | ||
Line 1,043: | Line 1,080: | ||
<TR> | <TR> | ||
<TD>WAIT</TD> | <TD><font color="blue">WAIT</font></TD> | ||
<TD>Wait for completion?</TD> | <TD><font color="blue">Wait for completion?</font></TD> | ||
<TD>Menu</TD> | <TD><font color="blue">Menu</font></TD> | ||
<TD>Yes</TD> | <TD><font color="blue">Yes</font></TD> | ||
<TD>"NoWait"</TD> | <TD><font color="blue">"NoWait"</font></TD> | ||
<TD>Yes</TD> | <TD><font color="blue">Yes</font></TD> | ||
<TD>Yes</TD> | <TD><font color="blue">Yes</font></TD> | ||
<TD>Yes</TD> | <TD><font color="blue">Yes</font></TD> | ||
<TD>No</TD> | <TD><font color="blue">No</font></TD> | ||
</TR> | </TR> | ||
</TABLE> | </TABLE> | ||
<font color="blue"> | |||
< | The sCalcout record now uses device support to write to the | ||
<code>OUT</code> link. Soft device supplied with the record is selected with | <code>OUT</code> link. Soft device supplied with the record is selected with | ||
the .dbd specification <pre> field(DTYP,"Soft Channel") </pre> | the .dbd specification <pre> field(DTYP,"Soft Channel") </pre> | ||
Line 1,067: | Line 1,104: | ||
looks something like | looks something like | ||
<code> xxx:record.field <b>CA</b> NMS</code> | |||
Currently, the record does not try to ensure that <code>WAIT</code> and | |||
<code>OUT</code> are compatibly configured. If <code>WAIT</code> == "Wait", | <code>OUT</code> are compatibly configured. If <code>WAIT</code> == "Wait", | ||
but the link looks like | but the link looks like | ||
<code> xxx:record.field <b>PP</b> NMS</code> | |||
for example, then the record will not wait for completion before executing | |||
its forward link. | its forward link. | ||
</font> | |||
=== Operator Display Parameters === | === Operator Display Parameters === | ||
Line 1,085: | Line 1,123: | ||
of the sCalcout record is located here. | of the sCalcout record is located here. | ||
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. | supplied by the user and which describes the values being operated upon. | ||
The string is retrieved whenever the routine <TT>get_units</TT> is called. | The string is retrieved whenever the routine <TT>get_units</TT> is called. | ||
Line 1,091: | Line 1,129: | ||
used. | used. | ||
The HOPR and LOPR fields only refer to the limits of the VAL, | |||
HIHI, HIGH, LOW, and LOLO fields. PREC controls the precision of the VAL | HIHI, HIGH, LOW, and LOLO fields. PREC controls the precision of the VAL | ||
field. | field. | ||
The INAV-INLV and IAAV-ILLV fields indicate the status of the | |||
link to the PVs specified in the INPA-INPL and INAA-INLL fields, respectively. | link to the PVs specified in the INPA-INPL and INAA-INLL fields, respectively. | ||
The fields can have three possible values: | The fields can have three possible values: | ||
<table border> | <table border> | ||
Line 1,126: | Line 1,163: | ||
</table> | </table> | ||
The OUTV field indicates the status of the OUT link. It has the same possible | |||
values as the INAV-INLV fields. | values as the INAV-INLV fields. | ||
The CLCV and OLCV fields indicate the validity of the expression | |||
in the CALC and OCAL fields, respectively. If the expression is invalid, | in the CALC and OCAL fields, respectively. If the expression is invalid, | ||
the field is set to one. | the field is set to one. | ||
The DLYA field is set to one during the delay interval specified | |||
in ODLY. | in ODLY. | ||
<TABLE BORDER> | <TABLE BORDER> | ||
<TR> | <TR> | ||
Line 1,378: | Line 1,411: | ||
which an error message is generated. | which an error message is generated. | ||
The following alarm parameters which are configured by the user | |||
define the limit alarms for the VAL field and the severity corresponding | define the limit alarms for the VAL field and the severity corresponding | ||
to those conditions. | to those conditions. | ||
The HYST field defines an alarm deadband for each limit. See the | |||
EPICS Record Reference Manual for a complete explanation of alarms | EPICS Record Reference Manual for a complete explanation of alarms | ||
and these fields. | and these fields. | ||
<TABLE BORDER> | <TABLE BORDER> | ||
<TR> | <TR> | ||
Line 1,566: | Line 1,598: | ||
are modifiable at run-time. They are used to process the record. | are modifiable at run-time. They are used to process the record. | ||
The LALM field is used to implement the hysteresis factor for | |||
the alarm limits. | the alarm limits. | ||
The LA-LL fields are used to decide when to trigger monitors for | |||
the corresponding fields. For instance, if LA does not equal the value | 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 | for A, monitors for A are triggered. The MLST and MLST fields are used | ||
in the same manner for the VAL field. | in the same manner for the VAL field. | ||
<TABLE BORDER> | <TABLE BORDER> | ||
<TR> | <TR> | ||
Line 1,751: | Line 1,782: | ||
# Fetch values from all valid input links. | # Fetch values from all valid input links. | ||
# Call sCalcPerform(), which evaluates the expression specified in CALC and stores the result in VAL. If sCalcPerform() returns success, UDF is set to FALSE. | # Call sCalcPerform(), which evaluates the expression specified in CALC and stores the result in VAL. If sCalcPerform() returns success, UDF is set to FALSE. | ||
#Check alarms. This routine checks to see if the new VAL causes the alarm | #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. | ||
status and severity to change. If so, NSEV, NSTA and LALM are set. It also | # 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 to do so after the specified interval. See the explanation for the <TT>execOutput()</TT> routine below. | ||
honors the alarm hysteresis factor (HYST). Thus the value must change by | |||
at least HYST before the alarm status and severity changes. | |||
# 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 to do so after the specified interval. See the | |||
explanation for the <TT>execOutput()</TT> routine below. | |||
# Determine what fields should be posted, and with what attributes. | # Determine what fields should be posted, and with what attributes. | ||
## Post all fields the record has changed. | ## Post all fields the record has changed. | ||
## Alarm monitors are invoked if the alarm status or severity has changed. | ## Alarm monitors are invoked if the alarm status or severity has changed. | ||
## Archive and value change monitors are invoked if ADEL and MDEL conditions | ## Archive and value change monitors are invoked if ADEL and MDEL conditions are met. | ||
are met. | |||
## NSEV and NSTA are reset to 0 | ## NSEV and NSTA are reset to 0 | ||
# | # <font color="blue">Call device support to</font> execute output link. | ||
# | # If we're not waiting for the output delay to expire, or for a completion callback, process the forward link, set PACT FALSE, and return. | ||
==== special ==== | ==== special ==== | ||
Line 1,801: | Line 1,825: | ||
Sets the following values: | Sets the following values: | ||
* upper_alarm_limit = HIHI | |||
* upper_warning_limit = HIGH | |||
* lower_warning_limit = LOW | |||
* lower_alarm_limit = LOLO | |||
==== execOutput() ==== | ==== execOutput() ==== | ||
# If DOPT field specifies the use of OCAL, call the routine sCalcPerform | # If DOPT field specifies the use of OCAL, call the routine sCalcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL. | ||
for the postfix version of the expression in OCAL. Otherwise, use VAL. | # If the Alarm Severity is INVALID, follow the option as designated by the field IVOA. | ||
# If the Alarm Severity is not INVALID or IVOA specifies "Continue Normally", <font color="blue">call device support to</font> write the value of OVAL to <font color="blue">device or</font> PV specified by the OUT link, and post the event in OEVT (if non-zero). | |||
# If the Alarm Severity is INVALID, follow the option as designated by | |||
the field IVOA. | |||
# If the Alarm Severity is not INVALID or IVOA specifies "Continue Normally", | |||
call device support to write the value of OVAL to device or PV specified by | |||
the OUT link, and post the event in OEVT (if non-zero) | |||
== Availability == | == Availability == | ||
The sCalcout record is not included with EPICS base. | The sCalcout record is not included with EPICS base. The 3.14-compatible version is available | ||
as part of the [http://www.aps.anl.gov/aod/bcda/synApps/calc/calc.html calc] module, which is part of the [http://www.aps.anl.gov/aod/bcda/synApps synApps] package of EPICS-based synchrotron-beamline software. | as part of the [http://www.aps.anl.gov/aod/bcda/synApps/calc/calc.html calc] module, which is part of the [http://www.aps.anl.gov/aod/bcda/synApps synApps] package of EPICS-based synchrotron-beamline software. The 3.13-compatible version is available as part of the [http://www.aps.anl.gov/aod/bcda/synApps/std/std.html std] module of a 3.13-compatible synApps distribution. | ||
---- | ---- | ||
EPICS Record Reference Manual - 7 JUNE 2006 | EPICS Record Reference Manual - 7 JUNE 2006 |
Latest revision as of 15:11, 9 June 2006
sCalcout Record
This page actually describes the EPICS-3.14-compatible version of the sCalcout record. Text that does not apply to the 3.13-compatible version is rendered in blue. Documentation specific to the 3.13-compatible version is currently not available in this format, but may be found in the 'std' module of a 3.13-compatible synApps package.
The String Calculation Output or "sCalcout" record is derived from the Calcout record and extends it by supporting string expressions and operands. The record has 12 numeric fields (A...L) and 12 string fields (AA...LL), which are used as input variables for the expression. It calls an extended version of the EPICS calculation engine that accepts string arguments, supports a variety of string functions, and produces both numeric and string results, in the VAL and SVAL fields, respectively. The record's output link writes string or numeric data, depending on the data type of the field to which it is linked.
Parameter Fields
The fields in this record fall into the following categories:
- Scan Parameters
- Read Parameters
- Expression Parameters
- Output Parameters
- Operator Display Parameters
- Alarm Parameters
- Monitor Parameters
- Run-Time Parameters
Scan Parameters
The sCalcout record has the standard fields for specifying under what circumstances the record will be processed. These fields are listed in Scan Fields. In addition, Scanning Specification explains how these fields are used. Since the sCalcout record supports no direct interfaces to input hardware that might generate an interrupt, it cannot be scanned on I/O interrupt, so its SCAN field cannot be I/O Intr
.
Read Parameters
The read parameters for the sCalcout record consist of 24 input links: 12 for numeric values (INPA→A, INPB→B, ... INPL→L); and 12 for string values (INAA→AA, INBB→BB, ... INLL→LL). The fields can be database links, channel access links, or constants. If they are links, they must contain a PV name. If they are constants, associated value fields will be initialized with the constants. These fields cannot be hardware addresses. In addition, the sCalcout record contains the fields INAV, INBV, ... INLV, which indicate the status of the links to numeric fields, and the fields IAAV, IBBV, ... ILLV, which indicate the status of the links to string fields. These fields indicate whether or not the specified PV was found and a link to it established. See Operator Display Parameters for an explanation of these fields.
See Address Specification for information on how to specify database links.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor |
---|---|---|---|---|---|---|---|
INPA | Input Link A | INLINK | Yes | 0 | Yes | Yes | Yes |
INPB | Input Link B | INLINK | Yes | 0 | Yes | Yes | Yes |
... | ... | ... | ... | ... | ... | ... | ... |
INPL | Input Link L | INLINK | Yes | 0 | Yes | Yes | Yes |
INAA | Input Link AA | INLINK | Yes | 0 | Yes | Yes | Yes |
INBB | Input Link BB | INLINK | Yes | 0 | Yes | Yes | Yes |
... | ... | ... | ... | ... | ... | ... | ... |
INLL | Input Link LL | INLINK | Yes | 0 | Yes | Yes | Yes |
Expression Parameters
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
CALC | Infix expression | String[40] | Yes | "" | Yes | Yes | Yes | No |
CLCV | CALC Valid | Long | No | 0 | Yes | No | Yes | No |
OCAL | Infix expression | String[40] | Yes | "" | Yes | Yes | Yes | No |
OCLV | OCAL Valid | Long | No | 0 | Yes | No | Yes | No |
Like the Calcout record, the sCalcout record has the fields CALC and OCAL, in which the developer or user can enter an infix expression to be evaluated when the record is processed. The numeric value resulting from evaluation of CALC will be placed in the VAL field, and the resulting string value will be placed in the SVAL field. VAL can then be used by the OOPT field (see Output Parameters) to determine whether or not to write to the output link or post an output event. Either VAL and SVAL can also be written to the output link. (If you elect to write an output value, the record will choose between VAL and SVAL, depending on the data type of the field at the other end of the output link.)
The CALC and OCAL expressions are actually converted to opcodes and stored in postfix notation in the RPCL and ORPC fields. It is these expressions which are actually used to calculate VAL. A postfix expression can be evaluated more efficiently at run-time than an infix expression would be. When CALC or OCAL is changed at run-time, the record-support routine special() will call a function to check it, and convert it to postfix.
In simple cases, OCAL is ignorable. It's use will be described later, in Output Parameters.
sCalcout-record expressions are very similar to standard EPICS Calc expressions, such as those used with the Calcout record. But in place of the standard EPICS calc engine (which does not support string fields or operations), sCalcout-record uses the sCalc engine, a separate piece of software, which normally is distributed with the sCalcout record. The differences between these engines that matter for numeric expressions are the following:
- The constants S2R (arc-seconds-to-radians) and R2S are supported.
- The functions MIN() and MAX() may have more than two arguments.
- The binary operators '>&' (larger of the operands) and '<&' (smaller) are supported.
- The binary operator '!=' (not equal) is a permitted alternatives '#'.
- The unary operator '@' selects an input field by number. (E.g., '@0' means 'A'. If 'B' has the value 3, '@b' means 'D'.)
Expressions supported by the sCalcout record can involve operands, algebraic operators and functions, trigonometric functions, relational operators, logical operators, string operators and functions, parentheses and commas, and the conditional '?:' operator. Numeric and string operands are supported, and any operand can be used with any operator or function. If an operand has the "wrong" type for the function or operator with which it is used, the operand will be converted implicitly to the correct type.
Grouping of operands with parentheses is important not only to specify the order in which operations are to be performed, but also to distinguish operands from operators whose names are spelled out, such as the logical operator 'AND'. For example, the expression 'AANDB', which could have meant 'A AND B', will be (mis)interpreted by the parser as 'AA NDB'.
Operands
The expression can use the values retrieved from the input links as operands, though constants can be used as operands too. These values retrieved from the input links are stored in the A-L, and AA-LL fields. The values to be used in the expression are simply referenced by the field name. For example, 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.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
A | Input Value A | DOUBLE | No | 0 | Yes | Yes/No* | Yes | Yes |
B | Input Value B | DOUBLE | No | 0 | Yes | Yes/No* | Yes | Yes |
... | ... | ... | ... | ... | ... | ... | ... | ... |
L | Input Value L | DOUBLE | No | 0 | Yes | Yes/No* | Yes | Yes |
AA | Input string AA | STRING (40) | No | 0 | Yes | Yes/No* | Yes | Yes |
BB | Input string BB | STRING (40) | No | 0 | Yes | Yes/No* | Yes | Yes |
... | ... | ... | ... | ... | ... | ... | ... | ... |
LL | Input string LL | STRING (40) | No | 0 | Yes | Yes/No* | Yes | Yes |
Legend: * If a non-blank input link is associated with this field, then it may not be modified. This is true even if the input link is invalid (in which case, the value will be 0, for a numeric field, or "Huh?", for a string field).
There are a few special operands not associated with input fields, but
defined by the record (more exactly, defined by the calc engine the record uses
to evaluate expressions). All but RNDM
are constants.
PI | 3.141592654 |
D2R | Degrees to radians (PI/180) |
R2D | Radians to degrees (1/D2R) |
S2R | Arc seconds to radians (D2R/3600) |
R2S | Radians to arc seconds (1/S2R) |
RNDM | Random number between 0 and 1. |
Algebraic Functions/Operators
Op | Description | Example |
---|---|---|
ABS | Absolute value (one-argument function) | ABS(A)
|
SQRT | Square root (one-argument function) (SQR is deprecated) | SQRT(A)
|
MIN | Minimum (two-or-more-argument function) | MIN(A,B)
|
MAX | Maximum (two-or-more-argument function) | MAX(A,B)
|
CEIL | Ceiling (one-argument function) | CEIL(A)
|
FLOOR | Floor (one-argument function) | FLOOR(A)
|
INT | Nearest integer (one-argument function) | INT(A)
|
NINT | Nearest integer (one-argument function) | NINT(A)
|
LOG | Log base 10 (one-argument function) | LOG(A)
|
LN | Natural logarithm (one-argument function) | LN(A)
|
LOGE | Deprecated synonym for 'LN' | LOGE(A)
|
EXP | Exponential function (unary) | EXP(A)
|
^ | Exponential (binary) (Same as '**'.) | A^B
|
** | Exponential (binary) (Same as '^'.) | A**B
|
+ | Addition (binary) | A+B
|
- | Subtraction (binary) | A-B
|
* | Multiplication (binary) | A*B
|
/ | Division (binary) | A/B
|
% | Modulo (binary) | A%B
|
- | Negate (unary) | -A
|
NOT | Negate (unary) | NOT A
|
>& | Max (binary) | A>?B
|
<& | Min (binary) | A<?B
|
Trigonometric Functions
Op | Description | Example |
---|---|---|
SIN | Sine (one-argument function) | SIN(A)
|
SINH | Hyperbolic sine (one-argument function) | SINH(A)
|
ASIN | Arc sine (one-argument function) | ASIN(A)
|
COS | Cosine (one-argument function) | COS(A)
|
COSH | Hyperbolic cosine (one-argument function) | COSH(A)
|
ACOS | Arc cosine (one-argument function) | ACOS(A)
|
TAN | Tangent (one-argument function) | TAN(A)
|
TANH | Hyperbolic tangent (one-argument function) | TANH(A)
|
ATAN | Arc tangent (one-argument function) | ATAN(A)
|
ATAN2 | Alternate form of arctangent (two-argument function) | ATAN2(A,B)
|
Relational Operators
Op | Description | Example |
---|---|---|
>= | Greater than or equal to | A>=B
|
> | Greater than | A>B
|
<= | Less than or equal to | A<=B
|
< | Less than | A<B
|
!= | Not equal to (same as '#') | A!=B
|
# | Not equal to (same as '!=') | A#B
|
== | Equal to (same as '=') | A==B
|
= | Equal to (same as '==') | A=B
|
Logical Operators
Op | Description | Example |
---|---|---|
&& | Logical AND | A&&B
|
|| | Logical OR | A||B
|
! | Logical NOT | !A
|
Bitwise Operators
Op | Description | Example |
---|---|---|
| | Bitwise OR | A|B
|
OR | Bitwise OR | A OR B
|
& | Bitwise AND | A&B
|
AND | Bitwise AND | A AND B
|
XOR | Bitwise Exclusive OR | A XOR B
|
~ | One's Complement | ~A
|
<< | Left shift | A<<B
|
>> | Right shift | A>>B
|
Parentheses and Comma
The open and close parentheses are supported. Nested parenthesis are supported.
The comma is supported when used to separate the arguments of a binary function.
Conditional Expression
The C language's question mark operator is supported. The format is:
<expression> ? <expression-true result> : <expression-false result>
String Functions/Operators
Most two-argument string functions and binary string operators are "overloaded" numeric functions and operators that perform string operations only if both of their arguments/operands are strings.
Op | Description | Example |
---|---|---|
MIN | Minimum lexically (two-or-more-argument function) | MIN('a','b') → 'a'
|
MAX | Maximum lexically (two-or-more-argument function) | MAX('a','b') → 'b'
|
INT | Find first number in string; return nearest integer (one-argument
function) | INT('1.9') → 1
|
NINT | Find first number in string; return nearest integer (one-argument
function) | NINT('1.9') → 2
|
+ | Concatenate (binary) | 'a'+'b' → 'ab'
|
- | Delete first occurrence of substring (binary) | 'abca'-'a' → 'bca'
|
-| | Delete first occurrence of substring (binary) | 'abca'-'a' → 'bca'
|
|- | Delete last occurrence of substring (binary) | 'abca'-'a' → 'abc'
|
>= | Lexically greater than or equal (binary) | 'a'>='b' → 0
|
> | Lexically greater than (binary) | 'a'>'b' → 0
|
<= | Lexically less than or equal (binary) | 'a'<='b' → 1
|
< | Lexically less than (binary) | 'a'<'b' → 1
|
!= | Lexically not equal to (binary) | 'a'!='b' → 1
|
== | Lexically equal to (binary) | 'a'=='b' → 0
|
DBL | Convert argument to double (one-argument function) | DBL('1') → 1.0
|
STR | Convert argument to string (one-argument function) | STR(1) → '1.00000000'
|
BYTE | Convert first character of string argument to double (one-argument function) | BYTE('abc') → 97.0
|
PRINTF | Return string constructed from format string and string or
double argument (two-argument function) (NOTE: '$P' is a synonym for PRINTF)
| PRINTF("%.2f",1.23) → '1.23'
|
SSCANF | Return string or double parsed from string argument according
to format string (two-argument function) (NOTE: '$S' is a synonym for SSCANF)
| SSCANF('V=1.25', "%*2c%lf") → 1.25
|
TR_ESC | Translate escape sequences into the characters they represent
(one-argument function). (NOTE: '$T' is a synonym for TR_ESC.)
| TR_ESC("a\x62c") → 'abc'
|
ESC | Translate escape characters into equivalent escape sequences.
(one-argument function) (NOTE: '$E' is a synonym for ESC)
| ESC("a<return>c") → 'a\rc'
|
[ | Substring | 'abcdef'[1,3] → 'bcd'
|
{ | Substring substitution | 'abcdef'{'cd','XX'} → 'abXXef'
|
" | String indicator | "abc"
|
' | String indicator | 'abc'
|
Operand-Array Operators
Op | Description | Example |
---|---|---|
@ | Numeric array element. Regard the numeric fields A-L as an array whose elements
are numbered 0-11, and return the element whose number follows. (unary) | @A
|
@@ | String array element. Regard the string fields AA-LL as an array of strings whose
elements are numbered 0-11, and return the element whose number follows. (unary) | @@A
|
Examples
Algebraic Examples
A + B + 10 Result is A + B + 10
Relational Examples
(A + B) < (C + D) Result is 1 if (A+B) < (C+D) Result is 0 if (A+B) >= (C+D)
Question Mark Examples
(A+B)<(C+D)?E:F+L+10 Result is E if (A+B) < (C+D) Result is F+L+10 if (A+B) >= (C+D)
(A+B)<(C+D)?E Result is E if (A+B) < (C+D) Result is unchanged if (A+B) >= (C+D)
Logical Examples
A&B Causes the following to occur:
- Convert A to integer
- Convert B to integer
- Perform bit-wise AND of A and B
- Convert result to floating point
String Examples
A + "abc"
A + "abc1.2"
A + AA (where AA = "abc1.2")
- Result is A. The strings "abc" and "abc1.2" will be converted implicitly to the number 0.
A + DBL("abc1.2")
- Result is A + 1.2. Explicit conversion to a number (by DBL, INT, or NINT) is more aggressive than implicit conversion, and skips leading non-numeric characters.
"abc" + "def"
- Result is "abcdef".
PRINTF("abc%1.2f", A) (where A = 1.2345)
- Result is "abc1.23".
- NOTE: unlike the c-language function printf(<format>,<arg1>,<arg2>,...), this function accepts only one argument after the format string.
SSCANF(AA, "%*3c%lf") (where AA = "abc1.2")
- Result is "1.20000000". (The format fragment "%*3c" directs sscanf to ignore three characters.)
- NOTE: unlike the c-language function sscanf(<source>,<format>,<dest1>,<dest2>,...), this function cannot store to a variable, but only to the value stack.
BYTE("ABC")
- Result is 65, the ASCII code for "A" in decimal.
"abcdef"[2,4]
- Result is "cde". (The first character of the string is numbered "0".)
"abcdef"[-2,-1]
- Result is "ef". (The last character of the string is numbered "-1".)
"abcdef"["ab","ef"]
- Result is "cd". (If the first argument is a string, it returns the index of the first character after a successful match, or the first character in the string if no match was found. If the second argument is a string, it returns the index of the last character before a successful match, or the last character in the string if no match was found.) In other words, string arguments delimit the substring they are specifying without participating in it.)
A==2 ? "yes" : "no"
- Result is "yes" if A == 2; otherwise, result is "no".
"abcdef"{"bcd","dcb"}
- Result is "adcbef".
"abcdef"{"zzz","dcb"}
- Result is "abcdef". (If no match, then no replacement.)
"abcdef"[1,-2][1,-2]
- Result is "cd"
Array Examples
@0
- Result is the value of the numeric variable A. ("@0" is just another name for A.)
@@0
- Result is the value of the string variable AA.
@(A+B)
- Result is the value of the numeric variable whose number is given by the sum of A and B.
Output Parameters
These parameters specify and control the output capabilities of the sCalcout 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:
Every Time | write output every time record is processed. |
On Change | write output every time VAL changes, i.e., every time the result of the expression changes. |
When Zero | when record is processed, write output if VAL is zero. |
When Non-zero | when record is processed, write output if VAL is non-zero. |
Transition to Zero | when record is processed, write output only if VAL is zero and last value was non-zero. |
Transition to Non-zero | when record is processed, write output only if VAL is non-zero and last value was zero. |
Never | Don't write output ever. |
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: Use
CALC or Use OCAL. If Use CALC 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 [SVAL]
field to a double [string] destination. If Use OCAL is specified,
the record will instead write the result of the expression in the OCAL
field, which is contained in the OVAL field (string result in the OSV)
field. The OCAL field is exactly like the CALC field and has the same functionality:it can contain the string representation of an expression which is evaluated at run-time. Thus, if necessary, the record can use the result of the CALC expression to determine if data should be written and can use the result of the OCAL expression as the data to write.
If the OEVT field specifies a non-zero integer and the condition in the OOPT field is met, the record will post a corresponding event. If the ODLY field is non-zero, the record pauses for the specified number of seconds before executing the OUT link or posting the output event. During this waiting period the record is "active" and will not be processed again until the wait is over. The field DLYA is equal to 1 during the delay period. The resolution of the delay entry is 1/60 of a second (it uses the VxWorks tickLib).
The IVOA field specifies what action to take with the OUT link if the sCalcout record enters an INVALID alarm status. The options are Continue normally, Don't drive outputs, and Set output to IVOV. If the IVOA field is Set output to IVOV, the data entered into the IVOV field is written to the OUT link if the record alarm severity is INVALID.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
OUT | Output Specification | OUTLINK | Yes | 0 | Yes | Yes | N/A | No |
OOPT | Output Execute Option | Menu | Yes | 0 | Yes | Yes | No | No |
DOPT | Output Data Option | Menu | Yes | 0 | Yes | Yes | No | No |
OCAL | Output Calculation | STRING[36] | Yes | Null | Yes | Yes | No | No |
OVAL | Output Value | DOUBLE | No | 0 | Yes | Yes | Yes | No |
OEVT | Event To Issue | SHORT | Yes | 0 | Yes | Yes | No | No |
ODLY | Output Execution Delay | FLOAT | Yes | 0 | Yes | Yes | No | No |
IVOV | Invalid Output Action | Menu | Yes | 0 | Yes | Yes | No | No |
IVOA | Invalid Output Value | DOUBLE | Yes | 0 | Yes | Yes | No | No |
OSV | Output string value | STRING[40] | NO | 0 | Yes | Yes | Yes | No |
WAIT | Wait for completion? | Menu | Yes | "NoWait" | Yes | Yes | Yes | No |
The sCalcout record now uses device support to write to the
OUT
link. Soft device supplied with the record is selected with
the .dbd specification
field(DTYP,"Soft Channel")
This device support uses the record's WAIT
field to determine
whether to wait for completion of processing initiated by the OUT
link before causing the record to execute its forward link. The mechanism by
which this waiting for completion is performed requires that the
OUT
link have the attribute CA
-- i.e., the link text
looks something like
xxx:record.field CA NMS
Currently, the record does not try to ensure that WAIT
and
OUT
are compatibly configured. If WAIT
== "Wait",
but the link looks like
xxx:record.field PP NMS
for example, then the record will not wait for completion before executing its forward link.
Operator Display Parameters
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 sCalcout record is located here.
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 get_units is called. The EGU string is solely for an operator's sake and does not have to be used.
The HOPR and LOPR fields only refer to the limits of the VAL, HIHI, HIGH, LOW, and LOLO fields. PREC controls the precision of the VAL field.
The INAV-INLV and IAAV-ILLV fields indicate the status of the link to the PVs specified in the INPA-INPL and INAA-INLL fields, respectively. The fields can have three possible values:
Ext PV NC | the PV wasn't found on this IOC and a Channel Access link hasn't
been established. |
Ext PV OK | the PV wasn't found on this IOC and a Channel Access link has
been established. |
Local PV | the PV was found on this IOC. |
Constant | the corresponding link field is a constant. |
The OUTV field indicates the status of the OUT link. It has the same possible values as the INAV-INLV fields.
The CLCV and OLCV fields indicate the validity of the expression in the CALC and OCAL fields, respectively. If the expression is invalid, the field is set to one.
The DLYA field is set to one during the delay interval specified in ODLY.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
EGU | Engineering Units | STRING [16] | Yes | Null | Yes | Yes | No | No |
PREC | Display Precision | SHORT | Yes | 0 | Yes | Yes | No | No |
HOPR | High Operating Range | FLOAT | Yes | 0 | Yes | Yes | No | No |
LOPR | Low Operating Range | FLOAT | Yes | 0 | Yes | Yes | No | No |
INAV | Link Status of INPA | Menu | No | 1 | Yes | No | No | No |
INBV | Link Status of INPB | Menu | No | 1 | Yes | No | No | No |
... | ... | ... | ... | ... | ... | ... | ... | ... |
INLV | Link Status of INPL | Menu | No | 1 | Yes | No | No | No |
OUTV | OUT PV Status | Menu | No | 0 | Yes | No | No | No |
CLCV | CALC Valid | LONG | No | 0 | Yes | Yes | No | No |
OCLV | OCAL Valid | LONG | No | 0 | Yes | Yes | No | No |
DLYA | Output Delay Active | USHORT | No | 0 | Yes | No | No | No |
NAME | Record Name | STRING [29] | Yes | 0 | Yes | No | No | No |
DESC | Description | STRING [29] | Yes | Null | Yes | Yes | No | No |
IAAV | Link Status of INAA | Menu | No | 1 | Yes | No | No | No |
IBBV | Link Status of INBB | Menu | No | 1 | Yes | No | No | No |
... | ... | ... | ... | ... | ... | ... | ... | ... |
ILLV | Link Status of INLL | Menu | No | 1 | Yes | No | No | No |
Alarm Parameters
The possible alarm conditions for the sCalcout record are the SCAN, READ, Calculation, and limit alarms. The SCAN and READ alarms are called by the record support routines. The Calculation alarm is called by the record processing routine when the CALC expression is an invalid one, upon which an error message is generated.
The following alarm parameters which are configured by the user define the limit alarms for the VAL field and the severity corresponding to those conditions.
The HYST field defines an alarm deadband for each limit. See the EPICS Record Reference Manual for a complete explanation of alarms and these fields.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
HIHI | Hihi Alarm Limit | FLOAT | Yes | 0 | Yes | Yes | No | Yes |
HIGH | High Alarm Limit | FLOAT | Yes | 0 | Yes | Yes | No | Yes |
LOW | Low Alarm Limit | FLOAT | Yes | 0 | Yes | Yes | No | Yes |
LOLO | Lolo Alarm Limit | FLOAT | Yes | 0 | Yes | Yes | No | Yes |
HHSV | Severity for a Hihi Alarm | Menu | Yes | 0 | Yes | Yes | No | Yes |
HSV | Severity for a High Alarm | Menu | Yes | 0 | Yes | Yes | No | Yes |
LSV | Severity for a Low Alarm | Menu | Yes | 0 | Yes | Yes | No | Yes |
LLSV | Severity for a Lolo Alarm | Menu | Yes | 0 | Yes | Yes | No | Yes |
HYST | Alarm Deadband | DOUBLE | Yes | 0 | Yes | Yes | No | No |
Monitor Parameters
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.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
ADEL | Archive Deadband | DOUBLE | Yes | 0 | Yes | Yes | No | No |
MDEL | Monitor, i.e. value change, Deadband | DOUBLE | Yes | 0 | Yes | Yes | No | No |
Run-time Parameters
These fields are not configurable using a configuration tool and none are modifiable at run-time. They are used to process the record.
The LALM field is used to implement the hysteresis factor for the alarm limits.
The LA-LL fields are used to decide when to trigger monitors for the corresponding fields. For instance, if LA does not equal the value for A, monitors for A are triggered. The MLST and MLST fields are used in the same manner for the VAL field.
Field | Summary | Type | DCT | Initial | Access | Modify | Rec Proc Monitor | PP |
---|---|---|---|---|---|---|---|---|
LALM | Last Alarmed Value | DOUBLE | No | 0 | Yes | No | No | No |
ALST | Archive Last Value | DOUBLE | No | 0 | Yes | No | No | No |
MLST | Monitor Last Value | DOUBLE | No | 0 | Yes | No | No | No |
LA | Previous Input Value for A | DOUBLE | No | 0 | Yes | No | No | No |
LB | Previous Input Value for B | DOUBLE | No | 0 | Yes | No | No | No |
... | ... | ... | ... | ... | ... | ... | ... | ... |
LL | Previous Input Value for A | DOUBLE | No | 0 | Yes | No | No | No |
LAA | Previous Input Value for AA | STRING[40] | No | 0 | Yes | No | No | No |
LBB | Previous Input Value for BB | STRING[40] | No | 0 | Yes | No | No | No |
... | ... | ... | ... | ... | ... | ... | ... | ... |
LLL | Previous Input Value for LL | STRING[40] | No | 0 | Yes | No | No | No |
Record Support
Record Support Routines
init_record
For each constant input link, the corresponding value field is initialized with the constant value if the input link is CONSTANT or a channel access link is created if the input link is PV_LINK.
A routine sCalcPostfix is called to convert the infix expression in CLCA-CLCV to postfix notation. The results are stored in RPCA-RPCP.
process
The process()
routine implements the following algorithm:
- Fetch values from all valid input links.
- Call sCalcPerform(), which evaluates the expression specified in CALC and stores the result in VAL. If sCalcPerform() returns success, UDF is set to FALSE.
- 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.
- 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 to do so after the specified interval. See the explanation for the execOutput() routine below.
- Determine what fields should be posted, and with what attributes.
- Post all fields the record has changed.
- Alarm monitors are invoked if the alarm status or severity has changed.
- Archive and value change monitors are invoked if ADEL and MDEL conditions are met.
- NSEV and NSTA are reset to 0
- Call device support to execute output link.
- If we're not waiting for the output delay to expire, or for a completion callback, process the forward link, set PACT FALSE, and return.
special
This is called if any of the fields A-L, CALC, OCAL, INPA-INPL, INAA-INLL, or OUT are changed. For expressions fields, special() calls sCalcPostfix. For value fields, special() keeps track of which fields have changed, because expressions will not be evaluated for fields that have been written to. For link fields, special() starts the process of checking link status.
get_units
Retrieves EGU.
get_precision
Retrieves PREC.
get_graphic_double
Sets the upper display and lower display limits for a field. If the field is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the field has upper and lower limits defined they will be used, else the upper and lower maximum values for the field type will be used.
get_control_double
Sets the upper control and the lower control limits for a field. If the field is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else if the field has upper and lower limits defined they will be used, else the upper and lower maximum values for the field type will be used.
get_alarm_double
Sets the following values:
- upper_alarm_limit = HIHI
- upper_warning_limit = HIGH
- lower_warning_limit = LOW
- lower_alarm_limit = LOLO
execOutput()
- If DOPT field specifies the use of OCAL, call the routine sCalcPerform for the postfix version of the expression in OCAL. Otherwise, use VAL.
- If the Alarm Severity is INVALID, follow the option as designated by the field IVOA.
- If the Alarm Severity is not INVALID or IVOA specifies "Continue Normally", call device support to write the value of OVAL to device or PV specified by the OUT link, and post the event in OEVT (if non-zero).
Availability
The sCalcout record is not included with EPICS base. The 3.14-compatible version is available as part of the calc module, which is part of the synApps package of EPICS-based synchrotron-beamline software. The 3.13-compatible version is available as part of the std module of a 3.13-compatible synApps distribution.
EPICS Record Reference Manual - 7 JUNE 2006