version 2.2

This commit is contained in:
zimoch
2007-07-31 09:19:37 +00:00
commit 90a6fd4af9
91 changed files with 16846 additions and 0 deletions

BIN
doc/EPICS.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

BIN
doc/PSI.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
doc/SLS.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

128
doc/aai.html Normal file
View File

@ -0,0 +1,128 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: aai Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: aai Records</h1>
<p>
<b>Note:</b> aai record support is disabled per default.
Enable it in <code>src/CONFIG_STREAM</code>.
</p>
<h2>Normal Operation</h2>
<p>
With aai records, the format converter is applied to
each element. Between the elements, a separator is printed
or expected as specified by the <code>Separator</code>
<a href="protocol.html#sysvar">variable</a> in the protocol.
When parsing input, a space as the first character of the
<code>Separator</code> matches any number of any whitespace
characters.
</p>
<p>
During input, a maximum of <code>NELM</code> elements is
read and <code>NORD</code> is updated accordingly.
Parsing of elements stops when the separator does not match,
conversion fails, or the end of the input is reached.
A minimum of one element must be available.
</p>
<p>
During output, the first <code>NORD</code> elements are
written.
</p>
<p>
The format data type must be convertible to or from the type
specified in the <code>FTVL</code> field.
The variable <code><i>x[i]</i></code> stands for one element of
the written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u><code><i>x[i]</i>=double(VAL[i])</code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i]</i>)</code><br>
<code>FTVL</code> must be <code>"FLOAT"</code> or <code>"DOUBLE"</code>
</dd>
<dt>LONG or ENUM format (e.g. <code>%i</code> or <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
<code>FTVL</code> can be
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
Signed values are sign-extended to long, unsigned values are
zero-extended to long before converting them.<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i])</i></code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
The value is truncated to the least significant bytes if
<code>FTVL</code> has a smaller data size than <code>long</code>.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<dl>
<dt>If <code>FTVL=="STRING"</code>:</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=VAL[i]</code><br>
<u>Input:</u> <code>VAL[i]=<i>x[i]</i></code><br>
Note that this is an array of strings, not an array of characters.
</dd>
<dt>If <code>FTVL=="CHAR"</code> or <code>FTVL="UCHAR"</code>:</dt>
<dd>
In this case, the complete aai is treated as a large
single string of size <code>NORD</code>.
No separators are printed or expected.<br>
<u>Output:</u> <code><i>x</i>=range(VAL,0,NORD)</code><br>
The first <code>NORD</code> characters are printed,
which might be less than <code>NELM</code>.<br>
<u>Input:</u> <code>VAL=<i>x</i>, NORD=length(<i>x</i>)</code><br>
A maximum of <code>NELM-1</code> characters can be read.
<code>NORD</code> is updated to the index of the first of the
trailing zeros.
Usually, this is the same as the string length.
</dd>
</dl>
Other values of <code>FTVL</code> are not allowed for this format.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

128
doc/aao.html Normal file
View File

@ -0,0 +1,128 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: aao Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: aao Records</h1>
<p>
<b>Note:</b> aao record support is disabled per default.
Enable it in <code>src/CONFIG_STREAM</code>.
</p>
<h2>Normal Operation</h2>
<p>
With aao records, the format converter is applied to
each element. Between the elements, a separator is printed
or expected as specified by the <code>Separator</code>
<a href="protocol.html#sysvar">variable</a> in the protocol.
When parsing input, a space as the first character of the
<code>Separator</code> matches any number of any whitespace
characters.
</p>
<p>
During output, the first <code>NORD</code> elements are
written.
</p>
<p>
During input, a maximum of <code>NELM</code> elements is
read and <code>NORD</code> is updated accordingly.
Parsing of elements stops when the separator does not match,
conversion fails, or the end of the input is reached.
A minimum of one element must be available.
</p>
<p>
The format data type must be convertible to or from the type
specified in the <code>FTVL</code> field.
The variable <code><i>x[i]</i></code> stands for one element of
the written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u><code><i>x[i]</i>=double(VAL[i])</code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i]</i>)</code><br>
<code>FTVL</code> must be <code>"FLOAT"</code> or <code>"DOUBLE"</code>
</dd>
<dt>LONG or ENUM format (e.g. <code>%i</code> or <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
<code>FTVL</code> can be
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
Signed values are sign-extended to long, unsigned values are
zero-extended to long before converting them.<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i])</i></code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
The value is truncated to the least significant bytes if
<code>FTVL</code> has a smaller data size than <code>long</code>.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<dl>
<dt>If <code>FTVL=="STRING"</code>:</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=VAL[i]</code><br>
<u>Input:</u> <code>VAL[i]=<i>x[i]</i></code><br>
Note that this is an array of strings, not an array of characters.
</dd>
<dt>If <code>FTVL=="CHAR"</code> or <code>FTVL="UCHAR"</code>:</dt>
<dd>
In this case, the complete aao is treated as a large
single string of size <code>NORD</code>.
No separators are printed or expected.<br>
<u>Output:</u> <code><i>x</i>=range(VAL,0,NORD)</code><br>
The first <code>NORD</code> characters are printed,
which might be less than <code>NELM</code>.<br>
<u>Input:</u> <code>VAL=<i>x</i>, NORD=length(<i>x</i>)</code><br>
A maximum of <code>NELM-1</code> characters can be read.
<code>NORD</code> is updated to the index of the first of the
trailing zeros.
Usually, this is the same as the string length.
</dd>
</dl>
Other values of <code>FTVL</code> are not allowed for this format.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

81
doc/ai.html Normal file
View File

@ -0,0 +1,81 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: ai Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: ai Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=(VAL-AOFF)/ASLO</code><br>
<u>Input:</u> <code>VAL=(<i>x</i>*ASLO+AOFF)*(1.0-SMOO)+VAL*SMOO</code><br>
In both cases, if <code>ASLO==0.0</code>, it is treated as <code>1.0</code>.
Default values are <code>ASLO=1.0</code>, <code>AOFF=0.0</code>,
<code>SMOO=0.0</code>.<br>
If input is successful, <code>UDF</code> is cleared.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL</code><br>
<u>Input:</u> <code>RVAL=<i>x</i></code><br>
Note that the record calculates
<code>VAL=(((RVAL+ROFF)*ASLO+AOFF)*ESLO+EOFF)*(1.0-SMOO)+VAL*SMOO</code>
if <code>LINR=="LINEAR"</code>.
<code>ESLO</code> and <code>EOFF</code> might be set in the record
definition. <em>StreamDevice</em> does not set it. For example,
<code>EOFF=-10</code> and <code>ESLO=0.000305180437934</code>
(=20.0/0xFFFF) maps 0x0000 to -10.0, 0x7FFF to 0.0 and 0xFFFF to 10.0.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if present.
In contrast to normal operation, in DOUBLE input <code>SMOO</code> is ignored
(treated as <code>0.0</code>).
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

82
doc/ao.html Normal file
View File

@ -0,0 +1,82 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: ao Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: ao Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=(OVAL-AOFF)/ASLO</code><br>
<u>Input:</u> <code>VAL=<i>x</i>*ASLO+AOFF</code><br>
In both cases, if <code>ASLO==0.0</code>, it is treated as <code>1.0</code>.
Default values are <code>ASLO=1.0</code>, <code>AOFF=0.0</code>.<br>
Note that <code>OVAL</code> is not necessarily equal to <code>VAL</code>
if <code>OROC!=0.0</code>.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL</code><br>
<u>Input:</u> <code>RBV=<i>x</i></code><br>
Note that the record calculates
<code>RVAL=(((OVAL-EOFF)/ESLO)-AOFF)/ASLO</code> if
<code>LINR=="LINEAR"</code>. <code>ESLO</code> and <code>EOFF</code>
might be set in the record definition. <em>StreamDevice</em> does not set it.
For example, <code>EOFF=-10</code> and <code>ESLO=0.000305180437934</code>
(=20.0/0xFFFF) maps -10.0 to 0x0000, 0.0 to 0x7FFF and 10.0 to 0xFFFF.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. In contrast to normal operation, output in DOUBLE format uses
<code>VAL</code> instead of <code>OVAL</code>. Note that the record
initializes <code>VAL</code> from <code>DOL</code> if that is a constant.
LONG input is put to <code>RVAL</code> as well as to <code>RBV</code> and
converted by the record.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

BIN
doc/bg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

77
doc/bi.html Normal file
View File

@ -0,0 +1,77 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: bi Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: bi Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL</code><br>
<u>Input:</u> <code>RVAL=<i>x</i>&amp;MASK</code><br>
<code>MASK</code> can be set be set in the record definition. Stream
Device does not set it. If <code>MASK==0</code>, it is ignored
(i.e. <code>RVAL=<i>x</i></code>). The record sets
<code>VAL=(RVAL!=0)</code>, i.e. <code>1</code> if <code>RVAL!=0</code>
and <code>0</code> if <code>RVAL==0</code>.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=(<i>x</i>!=0)</code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> Depending on <code>VAL</code>, <code>ZNAM</code> or
<code>ONAM</code> is written, i.e. <code><i>x</i>=VAL?ONAM:ZNAM</code>.<br>
<u>Input:</u> If input is equal to <code>ZNAM</code> or <code>ONAM</code>,
<code>VAL</code> is set accordingly. Other input strings are not accepted.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

76
doc/bo.html Normal file
View File

@ -0,0 +1,76 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: bo Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: bo Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL</code><br>
<u>Input:</u> <code>RBV=<i>x</i>&amp;MASK</code><br>
<code>MASK</code> can be set be set in the record definition. Stream
Device does not set it. If <code>MASK==0</code>, it is ignored
(i.e. <code>RBV=<i>x</i></code>).
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=(<i>x</i>!=0)</code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> Depending on <code>VAL</code>, <code>ZNAM</code> or
<code>ONAM</code> is written, i.e. <code><i>x</i>=VAL?ONAM:ZNAM</code>.<br>
<u>Input:</u> If input is equal to <code>ZNAM</code> or <code>ONAM</code>,
<code>VAL</code> is set accordingly. Other input strings are not accepted.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. In contrast to normal operation, LONG input is put to
<code>RVAL</code> as well as to <code>RBV</code> and converted by the record.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

634
doc/businterface.html Normal file
View File

@ -0,0 +1,634 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Bus API</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>Bus API</h1>
<a name="class"></a>
<h2>Bus Interface Class</h2>
<p>
<em>StreamDevice</em> already comes with an interface to <a target="ex"
href="http://www.aps.anl.gov/epics/modules/soft/asyn/">
<em>asynDriver</em></a>.
You should first try to implement your bus driver compatible to
<em>asynDriver</em>.
Then it can be used by <em>StreamDevice</em> automatically.
Only if that does not work, write your own bus interface.
</p>
<p>
A bus interface is a C++ class that inherits from
<em>StreamBusInterface</em>.
Its purpose is to provide an interface to <em>StreamDevice</em> for a
low-level I/O bus driver.
<em>StreamDevice</em> acts as a client of the interface, calling interface
methods and receiving replies via callbacks.
Since the internal details of <em>StreamDevice</em> are not of
interest to a bus interface, I will reference it simply as
<em>client</em> in this chapter.
The interface class must be registered via a call to
<code><a href="#registration">
RegisterStreamBusInterface</a>()</code>
in the global context of the C++ file (not in a header file).
</p>
<p>
Interface methods called by the client must not block for arbitrary
long times.
That means the interface is allowed to take mutex semaphores to protect
its internal data structures but it must not take event semaphores to
wait for external I/O or similar.
</p>
<p>
It is assumed that the interface creates a separate thread to handle
blocking I/O and to call the callback methods in the context of that
thread when I/O has completed or timed out.
The callback methods don't block but may in turn call interface methods.
Much of the actual work will be done in the context of those callbacks,
i.e. in the interface thread, thus be generous with stack.
</p>
<h3>Example bus interface class declaration</h3>
<pre>
#include &lt;StreamBusInterface.h&gt;
class MyInterface : StreamBusInterface
{
// ... (internally used attributes and methods)
<a href="#create">MyInterface</a>(Client* client);
<a href="#create">~MyInterface</a>();
// StreamBusInterface virtual methods
bool <a href="#lock">lockRequest</a>(unsigned long lockTimeout_ms);
bool <a href="#lock">unlock</a>();
bool <a href="#write">writeRequest</a>(const void* output, size_t size,
unsigned long writeTimeout_ms);
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
unsigned long readTimeout_ms,
long expectedLength, bool async);
bool <a href="#read">supportsAsyncRead</a>();
bool <a href="#event">supportsEvent</a>();
bool <a href="#event">acceptEvent</a>(unsigned long mask,
unsigned long replytimeout_ms);
bool <a href="#connect">connectRequest</a>(unsigned long connecttimeout_ms);
bool <a href="#connect">disconnect</a>();
void <a href="#lock">finish</a>();
public:
// creator method
static StreamBusInterface* <a href="#create">getBusInterface</a>(
Client* client, const char* busname,
int addr, const char* param);
};
<a href="#registration">RegisterStreamBusInterface</a>(MyInterface);
// ... (implementation)
</pre>
<h3>Methods to implement</h3>
<p>
The interface class must implement a public static creator method:
</p>
<div class="indent"><code>
static StreamBusInterface*
<a href="#create">getBusInterface</a>(Client*&nbsp;client,
const&nbsp;char*&nbsp;busname, int&nbsp;addr,
const&nbsp;char*&nbsp;param);
</code></div>
<p>
And it must implement the following pure virtual methods:
</p>
<div class="indent"><code>
bool <a href="#lock">lockRequest</a>(unsigned&nbsp;long&nbsp;lockTimeout_ms);
</code></div>
<div class="indent"><code>
bool <a href="#lock">unlock</a>();
</code></div>
<p>
It may implement additional virtual methods if the bus supports it:
</p>
<div class="indent"><code>
bool <a href="#write">writeRequest</a>(const&nbsp;void*&nbsp;output,
size_t&nbsp;size, unsigned&nbsp;long&nbsp;writeTimeout_ms);
</code></div>
<div class="indent"><code>
bool <a href="#read">readRequest</a>(unsigned&nbsp;long&nbsp;replyTimeout_ms,
unsigned&nbsp;long&nbsp;readTimeout_ms,
long&nbsp;expectedLength, bool&nbsp;async);
</code></div>
<div class="indent"><code>
bool <a href="#read">supportsAsyncRead</a>();
</code></div>
<div class="indent"><code>
bool <a href="#event">supportsEvent</a>();
</code></div>
<div class="indent"><code>
bool <a href="#event">acceptEvent</a>(unsigned&nbsp;long&nbsp;mask,
unsigned&nbsp;long&nbsp;replytimeout_ms);
</code></div>
<div class="indent"><code>
bool <a href="#connect">connectRequest</a>(unsigned&nbsp;long&nbsp;connecttimeout_ms);
</code></div>
<div class="indent"><code>
bool <a href="#connect">disconnect</a>();
</code></div>
<div class="indent"><code>
void <a href="#lock">finish</a>();
</code></div>
<p>
It also may override the following virtual method:
</p>
<div class="indent"><code>
void <a href="#create">release</a>();
</code></div>
<h3>Callback methods provided</h3>
<p>
The base class <em>StreamBusInterface</em> implements a set of protected
callback methods which must be called in response to the above request
methods (most probably from another thread):
</p>
<div class="indent"><code>
void <a href="#lock">lockCallback</a>(StreamIoStatus&nbsp;status);
</code></div>
<div class="indent"><code>
void <a href="#write">writeCallback</a>(StreamIoStatus&nbsp;status);
</code></div>
<div class="indent"><code>
long <a href="#read">readCallback</a>(StreamIoStatus&nbsp;status,
const&nbsp;void*&nbsp;input&nbsp;=&nbsp;NULL,
long&nbsp;size&nbsp;=&nbsp;0);
</code></div>
<div class="indent"><code>
void <a href="#event">eventCallback</a>(StreamIoStatus&nbsp;status);
</code></div>
<div class="indent"><code>
void <a href="#connect">connectCallback</a>(StreamIoStatus&nbsp;status);
</code></div>
<h3>Other provided methods, attibutes, and types</h3>
<div class="indent"><code>
<a href="#create">StreamBusInterface</a>(Client*&nbsp;client);
</code></div>
<div class="indent"><code>
long <a href="#lock">priority</a>();
</code></div>
<div class="indent"><code>
const char* <a href="#create">clientName</a>();
</code></div>
<div class="indent"><code>
const&nbsp;char*&nbsp;<a href="#write">getOutTerminator</a>(size_t&&nbsp;length);
</code></div>
<div class="indent"><code>
const&nbsp;char*&nbsp;<a href="#read">getInTerminator</a>(size_t&&nbsp;length);
</code></div>
<div class="indent"><code>
enum&nbsp;StreamIoStatus {StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoEnd, StreamIoFault};
</code></div>
<a name="theory"></a>
<h2>Theory of Operation</h2>
<a name="registration"></a>
<h3>Registration</h3>
<div class="indent"><code>
RegisterStreamBusInterface(<i>interfaceClass</i>);
</code></div>
<p>
During initialization, the macro <code>RegisterStreamBusInterface()</code>
registers the bus interface.
It must be called exactly once for each bus interface class in global
file context.
</p>
<a name="create"></a>
<h3>Creation and deletion</h3>
<div class="indent"><code>
static StreamBusInterface* getBusInterface(Client*&nbsp;client,
const&nbsp;char*&nbsp;busname, int&nbsp;addr,
const&nbsp;char*&nbsp;param);
</code></div>
<div class="indent"><code>
StreamBusInterface(Client*&nbsp;client);
</code></div>
<div class="indent"><code>
void release();
</code></div>
<div class="indent"><code>
const char* clientName();
</code></div>
<p>
During startup, each client instance searches for its bus interface
by name.
It does so by calling the static <code>getBusInterface()</code> method
of every registered interface class.
This method should check by <code>busname</code> if its interface class
is responsible for that bus.
If yes, it should check if the address <code>addr</code> is valid and
associate a <em>device</em> with <code>busname</code>/<code>addr</code>.
Some busses do not have addresses and allow only one device
(e.g. RS232).
Interfaces to such busses can ignore <code>addr</code>.
The bus interface may then try to connect to the device, but it should
allow it to be disconnected or switched off at that time.
If the bus interface requires additional parameters, parse the
<code>param</code> string.
Your constructor should pass <code>client</code> to the base class
constructor <code>StreamBusInterface(Client* client)</code>.
</p>
<p>
On success, <code>getBusInterface</code> should then return a pointer
to a bus interface instance.
Note that many client instances may want to connect to the same device.
Each needs its own bus interface instance.
The bus interface can get a string containing the name of the
client instance from <code>clientName()</code>.
This name is for use in error and log messages.
</p>
<p>
On failure, or if this interface class is not responsible for that bus,
<code>getBusInterface</code> should return <code>NULL</code>.
The client will then try other bus interface classes.
</p>
<p>
When the client does not need the interface any more, it calls
<code>release()</code>.
The default implementation of <code>release()</code> assumes that
<code>getBusInterface()</code> has allocated a new bus interface
and just calls <code>delete</code>.
You should change <code>release()</code> if that assumption is not
correct.
</p>
<a name="connect"></a>
<h3>Connecting and disconnecting</h3>
<div class="indent"><code>
bool connectRequest(unsigned&nbsp;long&nbsp;connecttimeout_ms);
</code></div>
<div class="indent"><code>
bool disconnect();
</code></div>
<div class="indent"><code>
void connectCallback(IoStatus&nbsp;status);
</code></div>
<p>
Connection should be handled automatically.
If the device is disconnected, each attempt to access the
device should try to (re-)connect.
Normally, the interface should not try to disconnect unless
the device does so.
</p>
<p>
However, sometimes the client wants to connect or
disconnect explicitely.
To connect, the client calls <code>connectRequest()</code>.
This function should return <code>true</code> immediately
or <code>false</code> if the request cannot be accepted.
The interface should call <code>connectCallback(StreamIoSuccess)</code>
once the bus could be connected.
If the bus cannot be connected within <code>connecttimeout_ms</code>
milliseconds, the bus interface should call
<code>connectCallback(StreamIoTimeout)</code>.
</p>
<p>
If a device cannot be connected, for example because there is
something wrong with the I/O hardware,
<code>connectCallback(StreamIoFault)</code> may be called.
</p>
<p>
To disconnect, the client calls <code>disconnect()</code>;
This function should return <code>true</code> immediately or
<code>false</code> if disconnecting is impossible.
There is no callback for <code>disconnect()</code>.
</p>
<a name="lock"></a>
<h3>Bus locking</h3>
<div class="indent"><code>
bool lockRequest(unsigned&nbsp;long&nbsp;lockTimeout_ms);
</code></div>
<div class="indent"><code>
void lockCallback(IoStatus&nbsp;status);
</code></div>
<div class="indent"><code>
bool unlock();
</code></div>
<div class="indent"><code>
long priority();
</code></div>
<div class="indent"><code>
void finish();
</code></div>
<p>
Before doing output, the client calls <code>lockRequest()</code> to get
exclusive access to the device.
This function should return <code>true</code> immediately
or <code>false</code> if the request cannot be accepted.
If the device is already locked, the bus interface should add itself to
a queue, sorted by <code>priority()</code>.
As soon as the device is available, the bus interface should call
<code>lockCallback(StreamIoSuccess)</code>.
If the bus cannot be locked within <code>lockTimeout_ms</code>
milliseconds, the bus interface should call
<code>lockCallback(StreamIoTimeout)</code>.
</p>
<p>
If a device cannot be locked, for example because there is
something wrong with the I/O hardware,
<code>lockCallback(StreamIoFault)</code> may be called.
</p>
<p>
Normally, it is not necessary to lock the complete bus but only one
device (i.e. one address).
Other clients should still be able to talk to other devices on the same bus.
</p>
<p>
The client may perform several read and write operations when it has
locked the device.
When the protocol ends and the device is locked, the client calls
<code>unlock()</code>.
If other bus interfaces are in the lock queue, the next one should
call <code>lockCallback(StreamIoSuccess)</code> now.
</p>
<p>
The client calls <code>finish()</code> when the protocol ends.
This allows the bus interface to clean up.
The bus interface should also cancel any outstanding requests of
this client.
</p>
<a name="write"></a>
<h3>Writing output</h3>
<div class="indent"><code>
bool writeRequest(const&nbsp;void*&nbsp;output,
size_t&nbsp;size, unsigned&nbsp;long&nbsp;writeTimeout_ms);
</code></div>
<div class="indent"><code>
void writeCallback(IoStatus&nbsp;status);
</code></div>
<div class="indent"><code>
const&nbsp;char*&nbsp;getOutTerminator(size_t&&nbsp;length);
</code></div>
<p>
To start output, the client calls <code>writeRequest()</code>.
You can safely assume that the device has already been locked at this
time.
That means, no other client will call <code>writeRequest()</code>
for this device and no other output is currently active for this device
until it has been unlocked.
</p>
<p>
The function should arrange transmission of <code>size</code> bytes of
<code>output</code> but return <code>true</code> immediately
or <code>false</code> if the request cannot be accepted.
It must not block until output has completed.
After all output has been successfully transmitted, but not earlier, the
interface should call <code>writeCallback(StreamIoSuccess)</code>.
</p>
<p>
If output blocks for <code>writeTimeout_ms</code> milliseconds,
the interface should abort the transmision and call
<code>writeCallback(StreamIoTimeout)</code>.
</p>
<p>
If output is impossible, for example because there is
something wrong with the I/O hardware,
<code>writeCallback(StreamIoFault)</code> may be called.
</p>
<p>
The interface must transmit excactly the <code>size</code> bytes
from <code>output</code>.
It must not change anything and it should not assume that
any bytes have a special meaning.
In particular, a null byte does not terminate <code>output</code>.
</p>
<p>
A call to <code>getOutTerminator</code> tells the interface which
terminator has already been added to the output.
If <code>NULL</code> was returned, the client is not aware of a
terminator (no outTerminator was defined in the protocol).
In this case, the interface may add a terminator which it knows from
other sources.
An interface is not required to support <code>NULL</code> results
and may not add any terminator in this case.
</p>
<p>
The buffer referenced by <code>output</code> stays valid until
<code>writeCallback()</code> is called.
</p>
<p>
The client may request more I/O or call <code>unlock()</code> after
<code>writeCallback()</code> has been called.
</p>
<a name="read"></a>
<h3>Reading input</h3>
<div class="indent"><code>
bool readRequest(unsigned&nbsp;long&nbsp;replyTimeout_ms,
unsigned&nbsp;long&nbsp;readTimeout_ms,
long&nbsp;expectedLength, bool&nbsp;async);
</code></div>
<div class="indent"><code>
long readCallback(IoStatus&nbsp;status,
const&nbsp;void*&nbsp;input&nbsp;=&nbsp;NULL,
long&nbsp;size&nbsp;=&nbsp;0);
</code></div>
<div class="indent"><code>
const&nbsp;char*&nbsp;getInTerminator(size_t&&nbsp;length);
</code></div>
<div class="indent"><code>
bool supportsAsyncRead();
</code></div>
<p>
The client calls <code>readRequest()</code> to tell the bus interface
that it expects input.
Depending on the bus, this function might have to set the bus hardware
into receive mode.
If <code>expectedLength&gt;0</code>, the the bus interface should stop
input after this number of bytes have been received.
In opposite to writing, the device may be in a non-locked status when
<code>readRequest()</code> is called.
</p>
<p>
This function must not block until input is available.
Instead, it should arrange for
<code>readCallback(StreamIoSuccess, buffer, size)</code> to be called
when input has been received and return <code>true</code>
immediately or <code>false</code> if the request cannot be accepted.
</p>
<p>
Here, <code>buffer</code> is a pointer to
<code>size</code> input bytes.
The bus interface is responsible for the buffer.
The client copies its contents. It does not modify or free it.
</p>
<p>
It is not necessary to wait until all data has been received.
The bus interface can call <code>n=readCallback()</code> after
any amount of input has been received.
If the client needs more input, <code>readCallback()</code>
returns a non-zero value.
A positive <code>n</code> means, the client needs another
<code>n</code> bytes of input.
A negative <code>n</code> means, the client needs an unspecified
amount of additional input.
</p>
<p>
With some bus interfaces, <code>readRequest()</code> might not have to
do anything because the bus is always receiving.
It might also be that the bus has no local buffer associated to store
input before it is fetched with some <code>read()</code> call.
In this case, a race condition between device and client can occure.
To avoid loss of data, <code>readCallback(StreamIoSuccess, buffer, size)</code>
may be called in this case even before <code>readRequest()</code>.
If the client is expecting input in the next future, it will store it.
Otherwise the input is dropped.
</p>
<p>
The <code>replyTimeout_ms</code> parameter defines how many milliseconds
to wait for the first byte of a reply before the device is considered
offline.
If no input has been received after <code>replyTimeout_ms</code>
milliseconds, the bus interface should call
<code>readCallback(StreamIoNoReply)</code>.
</p>
<p>
The <code>readTimeout_ms</code> parameter is the maximum time to wait
for further input.
If input stops for longer than <code>readTimeout_ms</code> milliseconds
the bus interface should call
<code>readCallback(StreamIoTimeout,buffer,size)</code>.
The client decides if this timeout is an error or a legal termination.
Thus, pass all input received so far.
</p>
<p>
A call to <code>getInTerminator(length)</code> tells the interface which
terminator is expected for input and <code>length</code> is set to the
number of bytes of the terminator. The result is a hint to the bus
interface to recognize the end of an input.
Once the terminator string is found, the bus interface should stop
receiving input and call
<code>readCallback(StreamIoSuccess, buffer, size)</code>.
It is not necessary to remove the terminator string from the received input.
An empty terminator string (<code>length==0</code>) means:
Don't look for terminators.
</p>
<p>
If <code>NULL</code> was returned, the client is not aware of a
terminator (no inTerminator was defined in the protocol).
In this case, the interface may look for a terminator which it knows from
other sources, reduce size by the terminator length and call
<code>readCallback(StreamIoEnd, buffer, size)</code>.
A bus interface is not required to support <code>NULL</code> results and
may treat them as empty terminator (see above).
</p>
<p>
Some busses (e.g. GPIB) support special "end of message" signals.
If such a signal is received, the bus interface should call
<code>readCallback(StreamIoEnd, buffer, size)</code>.
Use it to indicate a special "end of message" signal which is not
visible in the normal byte data stream.
If <code>getInTerminator()</code> has not returned <code>NULL</code>
it it not necessary to remove a terminator which may come in
addition to the "end of message" signal.
</p>
<p>
If input is impossible, for example because there is
something wrong with the I/O hardware,
<code>readCallback(StreamIoFault)</code> may be called.
</p>
<p>
If the <code>async</code> flag is <code>true</code>, the client
wants to read input asyncronously without any timeout.
That means, the bus interface should call <code>readCallback()</code>
even if the input was requested by another client.
</p>
<p>
If a client wishes to receive asynchonous input, it first calls
<code>supportsAsyncRead()</code>.
The default implementation of this method always returns
<code>false</code>.
A bus interface may overwrite this method to return <code>true</code>
and eventually prepare for asynchonous input.
The client is then allowed to call <code>readRequest()</code> with
the <code>async==true</code>.
This means that the client is interested in any input.
It should receive a <code>readCallback()</code> of all input which came
in response to a synchonous (<code>async==false</code>) request from
another client (which of course should receive the input, too).
The interface should also receive asynchonous input when no
synchonous client is active at the moment.
Many asynchonous <code>readRequest()</code> calls from different clients
may be active at the same time.
All of them should receive the same input.
</p>
<p>
For asynchonous requests, <code>replyTimeout_ms</code> has a different
meaning: If the bus interface has to poll the bus for input, it may take
<code>replyTimeout_ms</code> as a hint for the poll period.
If many asynchonous requests are active at the same time, it should poll
with the shortest period of all clients.
An asynchonous request does not time out.
It stays active until the next input arrives.
The client may reissue the asynchronous <code>readRequest()</code>
from within the <code>readCallback()</code> if it wants to continue
receiving asynchonous input.
</p>
<p>
If the client calls <code>finish()</code> at any time, the bus
interface should cancel all outstanding requests, including
asynchonous read requests.
</p>
<a name="event"></a>
<h3>Handling events</h3>
<div class="indent"><code>
bool supportsEvent();
</code></div>
<div class="indent"><code>
bool acceptEvent(unsigned long mask, unsigned long replytimeout_ms);
</code></div>
<div class="indent"><code>
void eventCallback(StreamIoStatus status);
</code></div>
<p>
An event is a sort of input from a device which is not part of
the normal byte stream.
One example is the SRQ line of GPIB.
Not all bus types have events.
To support events, the bus interface must overwrite
<code>supportsEvent()</code> to return <code>true</code>.
The default implementation always returns <code>false</code>.
</p>
<p>
If <code>true</code> is returned, the client is allowed to call
<code>acceptEvent()</code>, where <code>mask</code> defines the
(bus dependent) type of event or events to wait for.
If <code>mask</code> is illegal, <code>acceptEvent()</code> should
return <code>false</code>.
The call to <code>acceptEvent()</code> must not block.
It should arrange to call <code>eventCallback(StreamIoSuccess)</code>
when the event matching <code>mask</code> arrives within
<code>replytimeout_ms</code> milliseconds.
If no such event arrives within this time, the bus interface
should call <code>eventCallback(StreamIoTimeout)</code>.
</p>
<p>
To avoid race conditions, the bus interface should buffer events and
also report a matching event which occured before the actual call
to <code>acceptEvent()</code> but after any previous call of any
other request method like <code>writeRequest()</code>.
</p>
<hr>
<p><small>Dirk Zimoch, 2007</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

83
doc/calcout.html Normal file
View File

@ -0,0 +1,83 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: calcout Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: calcout Records</h1>
<p>
<b>Note:</b> Device support for calcout records is only available for
EPICS base R3.14.5 or higher.
</p>
<h2>Normal Operation</h2>
<p>
Different record fields are used for output and input. The variable
<code><i>x</i></code> stands for the written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=OVAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
Note that the record calculates <code>OVAL</code> from <code>CALC</code>
or <code>OCAL</code> depending on <code>DOPT</code>.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=int(OVAL)</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=int(OVAL)</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<p>
For calcout records, it is probably more useful to access fields
<code>A</code> to <code>L</code> directly (e.g. <code>"%(A)f"</code>).
However, even if <code>OVAL</code> is not used, it is calculated by the
record. Thus, <code>CALC</code> must always contain a valid expression
(e.g. <code>"0"</code>).
</p>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

224
doc/epics3_13.html Normal file
View File

@ -0,0 +1,224 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Using EPICS 3.13</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Using EPICS 3.13</h1>
<a name="pre"></a>
<h2>1. Prerequisites</h2>
<p>
<em>StreamDevice</em> version 2.2 and higher can run on EPICS 3.13.
However, this requires some preparation, because EPICS 3.13 is missing
some libraries and header files.
Also <em>asynDriver</em></a> needs to be modified to compile with EPICS 3.13.
Due to the limitations of EPICS 3.13, you can build streamDevice only for
vxWorks systems.
</p>
<p>
Of course, you need an installation of <a target="ex"
href="http://www.aps.anl.gov/epics/base/R3-13.php">EPICS 3.13</a>.
I guess you already have that, otherwhise you would want to
<a href="setup">install <em>StreamDevice</em> on EPICS 3.14</a>.
I have tested <em>StreamDevice</em> with EPICS versions 3.13.7 up to 3.13.10
with vxWorks 5.3.1 and 5.5 on a ppc604 processor.
</p>
<p>
Download my <a
href="http://epics.web.psi.ch/software/streamdevice/compat-1-0.tgz">
compatibility package</a>,
<a target="ex"
href="http://www.aps.anl.gov/epics/modules/soft/asyn/"><em>asynDriver</em></a>
version 4-3 or higher,
and my <a
href="http://epics.web.psi.ch/software/streamdevice/configure.tgz">
configure patches</a>.
</p>
<a name="compat"></a>
<h2>2. Build the Compatibility Package</h2>
<p>
Unpack <kbd>compat-1-0.tgz</kbd> in the <kbd>&lt;top&gt;</kbd> directory of
your application build area.
(Please refer to the <a target="ex"
href="http://www.aps.anl.gov/epics/EpicsDocumentation/AppDevManuals/iocScm-3.13.2/managingATop.html#3">
<em>EPICS IOC Software Configuration Management</em></a> document.)
</p>
<p>
Change to the <kbd>compat</kbd> directory and run <kbd>make</kbd>.
This installs many EPICS 3.14-style header files and a small library
(<kbd>compatLib</kbd>).
</p>
<a name="asyn"></a>
<h2>3. Build the <em>asynDriver</em> Library</h2>
<p>
Unpack the <em>asynDriver</em> package and change to its top directory.
</p>
<p>
Unpack <kbd>configure.tgz</kbd> here.
This will modify files in the <kbd>configure</kbd> directory.
Change to the <kbd>configure</kbd> directory and edit <kbd>CONFIG_APP</kbd>.
Set <code>COMPAT=...</code> to the <kbd>&lt;top&gt;</kbd>
directory where you have installed the compatibility package before.
(This patch might also allow you to compile other 3.14-style drivers for 3.13.
It has absolutely no effect if you use EPICS 3.14.)
</p>
<p>
Edit <kbd>RELEASE</kbd> and comment out <code>IPAC=...</code>
(unless you have the <em>ipac</em> package and somehow made it
compatible to EPICS 3.13).
Set <code>EPICS_BASE</code> to your EPICS 3.13 installation.
</p>
<p>
Run <kbd>make</kbd> in the <kbd>configure</kbd> directory.
</p>
<p>
Change to <kbd>../asyn/devGpib</kbd> and edit
<kbd>devGpib.h</kbd> and <kbd>devSupportGpib.c</kbd>.
Change all occurrences of <code>static&nbsp;gDset</code> to
<code>gDset</code>.
</p>
<p>
Go one directory up (to <kbd>asyn</kbd>) and run <kbd>make</kbd> twice!
(The first run will just create <kbd>Makefile.Vx</kbd>.)
Ignore all compiler warnings.
</p>
<p>
Do not try to build the test applications. It will not work.
</p>
<a name="lib"></a>
<h2>4. Build the <em>StreamDevice</em> Library</h2>
<p>
Go to the <kbd>&lt;top&gt;</kbd> directory of your application build area.
</p>
<p>
Edit <kbd>config/RELEASE</kbd> and add the variable <code>ASYN</code>.
Set it to the location of the <em>asynDriver</em> installation.
Also set the <code>COMPAT</code> variable to the location of the
compatibility package.
Run <kbd>make</kbd> in the <kbd>config</kbd> directory.
<p>
Unpack the <em>StreamDevice</em> package in your <kbd>&lt;top&gt;</kbd>
directory.
Change to the newly created <em>StreamDevice</em> directory
and run <kbd>make</kbd>.
</p>
<a name="app"></a>
<h2>5. Build an Application</h2>
<p>
To use <em>StreamDevice</em>, your application must be built with the
<em>asyn</em>, <em>stream</em>, and <em>compat</em> libraries and must load
<kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd>.
Also, as the <em>stream</em> library contains C++ code, the application
must be munched.
Therefore, include <kbd>$(TOP)/config/RULES.munch</kbd>.
(Put your application in the same <kbd>&lt;top&gt;</kbd> as the
<em>StreamDevice</em> installation.)
</p>
<p>
Include the following lines in your <kbd>Makefile.Vx</kbd>:
</p>
<pre>
LDLIBS += $(COMPAT_BIN)/compatLib
LDLIBS += $(ASYN_BIN)/asynLib
LDLIBS += $(INSTALL_BIN)/streamLib
include $(TOP)/config/RULES.munch
</pre>
<p>
Include the following lines in your <kbd>xxxAppInclude.dbd</kbd> file to use
<em>stream</em> and <em>asyn</em> (you also need a <kbd>base.dbd</kbd>):
</p>
<pre>
include "base.dbd"
include "stream.dbd"
include "asyn.dbd"
</pre>
<p>
You can find an example application in the <kbd>streamApp</kbd>
subdirectory.
</p>
<a name="sta"></a>
<h2>6. The Startup Script</h2>
<p>
<em>StreamDevice</em> is based on <a
href="protocol.html"><em>protocol files</em></a>.
To tell <em>StreamDevice</em> where to search for protocol files,
set the environment variable <code>STREAM_PROTOCOL_PATH</code> to a
list of directories to search.
Directories are separated by <code>:</code>.
The default value is <code>STREAM_PROTOCOL_PATH=.</code>,
i.e. the current directory.
</p>
<p>
Also configure the buses (in <em>asynDriver</em> terms: ports) you want
to use with <em>StreamDevice</em>.
You can give the buses any name you want, like <kbd>COM1</kbd> or
<kbd>socket</kbd>, but I recommend to use names related to the
connected device.
</p>
<h3>Example:</h3>
<p>
A power supply with serial communication (9600 baud, 8N1) is connected to
<kbd>/dev/ttyS1</kbd>.
The name of the power supply is <tt>PS1</tt>.
Protocol files are either in the current working directory or in the
<kbd>../protocols</kbd> directory.
</p>
<p>
Then the startup script must contain lines like this:
</p>
<pre>
ld < iocCore
ld < streamApp.munch
dbLoadDatabase ("streamApp.dbd")
putenv ("STREAM_PROTOCOL_PATH=.:../protocols")
drvAsynSerialPortConfigure ("PS1","/dev/ttyS1")
asynSetOption ("PS1", 0, "baud", "9600")
asynSetOption ("PS1", 0, "bits", "8")
asynSetOption ("PS1", 0, "parity", "none")
asynSetOption ("PS1", 0, "stop", "1")
</pre>
<p>
An alternative approach is to skip step 5 (do not build an application)
and load all components explicitely in the startup script.
The <code>STREAM_PROTOCOL_PATH</code> variable can also be a vxWorks shell
variable.
</p>
<pre>
ld < iocCore
ld < compatLib
ld < asynLib
ld < streamLib.munch
dbLoadDatabase ("asyn.dbd")
dbLoadDatabase ("stream.dbd")
STREAM_PROTOCOL_PATH=".:../protocols"
drvAsynSerialPortConfigure ("PS1","/dev/ttyS1")
asynSetOption ("PS1", 0, "baud", "9600")
asynSetOption ("PS1", 0, "bits", "8")
asynSetOption ("PS1", 0, "parity", "none")
asynSetOption ("PS1", 0, "stop", "1")
</pre>
<h2>7. <a href="setup.html#pro">Continue as with EPICS 3.14.</a></h2>
<hr>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

BIN
doc/ex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

BIN
doc/exr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

20
doc/formatconverter.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Format Converter API</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Format Converter API</h1>
<h2>Sorry, this documentation is still missing.</h2>
<hr>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

410
doc/formats.html Normal file
View File

@ -0,0 +1,410 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Format Converters</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Format Converters</h1>
<a name="syntax"></a>
<h2>1. Format Syntax</h2>
<p>
<em>StreamDevice</em> format converters work very similar to the format
converters of the C functions <em>printf()</em> and <em>scanf()</em>.
But <em>StreamDevice</em> provides more different converters and you can
also write your own converters.
Formats are specified in <a href="protocol.html#str">quoted strings</a>
as arguments of <code>out</code> or <code>in</code>
<a href="protocol.html#cmd">commands</a>.
</p>
<p>
A format converter consists of
</p>
<ul>
<li>The <code>%</code> character</li>
<li>Optionally a field name in <code>()</code></li>
<li>Optionally flags out of the characters <code>*# +0-</code></li>
<li>Optionally an integer <em>width</em> field</li>
<li>Optionally a period character (<code>.</code>) followed
by an integer <em>precision</em> field (input ony for most formats)</li>
<li>A conversion character</li>
<li>Additional information required by some converters</li>
</ul>
<p>
The <code>*</code> flag skips data in input formats.
Input is consumed and parsed, a mismatch is an error, but the read
data is dropped.
This is useful if input contains more than one value.
Example: <code>in "%*f%f";</code> reads the second floating point
number.
</p>
<p>
The <code>#</code> flag may alter the format, depending on the
converter (see below).
</p>
<p>
The '<code> </code>' (space) and <code>+</code> flags print a space
or a <code>+</code> sign before positive numbers, where negative
numbers would have a <code>-</code>.
</p>
<p>
The <code>0</code> flag says that numbers should be left padded with
<code>0</code> if <em>width</em> is larger than required.
</p>
<p>
The <code>-</code> flag specifies that output is left justified if
<em>width</em> is larger than required.
</p>
<h3>Examples:</h3>
<table>
<tr>
<td><code>in "%f";</code></td>
<td>float</td>
</tr>
<tr>
<td><code>out "%(HOPR)7.4f";</code></td>
<td>the HOPR field as 7 char float with precision 4</td>
</tr>
<tr>
<td><code>out "%#010x";</code></td>
<td>0-padded 10 char alternate hex (with leading 0x)</td>
</tr>
<tr>
<td><code>in "%[_a-zA-Z0-9]";</code></td>
<td>string of chars out of a charset</td>
</tr>
<tr>
<td><code>in "%*i";</code></td>
<td>skipped integer number</td>
</tr>
</table>
<a name="types"></a>
<h2>2. Data Types and Record Fields</h2>
<h3>Default fields</h3>
<p>
Every conversion character corresponds to one of the data types DOUBLE,
LONG, ENUM, or STRING.
In opposite to to <em>printf()</em> and <em>scanf()</em>, it is not
required to specify a variable for the conversion.
The variable is typically the <code>VAL</code> or <code>RVAL</code> field
of the record, selected automatically depending on the data type.
Not all data types make sense for all record types.
Refer to the description of <a href="recordtypes.html">supported record
types</a> for details.
</p>
<p>
<em>StreamDevice</em> makes no difference between <code>float</code>
and <code>double</code> nor between <code>short</code>, <code>int</code>
and <code>long</code> values.
Thus, data type modifiers like <code>l</code> or <code>h</code> do not
exist in <em>StreamDevice</em> formats.
</p>
<h3>Accessing record fields directly</h3>
<p>
To use other fields of the record or even fields of other records on the
same IOC for the conversion, write the field name in parentheses directly
after the <code>%</code>.
For example <code>out&nbsp;"%(EGU)s";</code> outputs the <code>EGU</code>
field formatted as a string.
Use <code>in&nbsp;"%(<i>otherrecord</i>.VAL)f";</code> to write the floating
point input value into the <code>VAL</code> field of
<code><i>otherrecord</i></code>.
(You can't skip <code>.VAL</code> here.)
This is very useful when one line of input contains many values that should
be distributed to many records.
If <code><i>otherrecord</i></code> is passive and the field has the PP
attribute (see
<a href="http://www.aps.anl.gov/asd/controls/epics/EpicsDocumentation/AppDevManuals/RecordRef/Recordref-1.html"
target="ex">Record Reference Manual</a>), the record will be processed.
It is your responsibility that the data type of the record field is
compatible to the the data type of the converter.
Note that using this syntax is by far not as efficient as using the
default field.
</p>
<h3>Pseudo-converters</h3>
<p>
Some formats are not actually converters.
They format data which is not stored in a record field, such as a
<a href="#chksum">checksum</a>.
No data type corresponds to those <em>pseudo-converters</em> and the
<code>%(<em>FIELD</em>)</code> syntax cannot be used.
</p>
<a name="stdd"></a>
<h2>3. Standard DOUBLE Converters (<code>%f</code>, <code>%e</code>,
<code>%E</code>, <code>%g</code>, <code>%G</code>)</h2>
<p>
In output, <code>%f</code> prints fixed point, <code>%e</code> prints
exponential notation and <code>%g</code> prints either fixed point or
exponential depending on the magnitude of the value.
<code>%E</code> and <code>%G</code> use <code>E</code> instead of
<code>e</code> to separate the exponent.
With the <code>#</code> flag, output always contains a period character.
</p>
<p>
In input, all these formats are equivalent.
Leading whitespaces are skipped.
</p>
<a name="stdl"></a>
<h2>4. Standard LONG Converters (<code>%d</code>, <code>%i</code>,
<code>%u</code>, <code>%o</code>, <code>%x</code>, <code>%X</code>)</h2>
<p>
In output, <code>%d</code> and <code>%i</code> print signed decimal,
<code>%u</code> unsigned decimal, <code>%o</code> unsigned octal, and
<code>%x</code> or <code>%X</code> unsigned hexadecimal.
<code>%X</code> uses upper case letters.
With the <code>#</code> flag, octal values are prefixed with <code>0</code>
and hexadecimal values with <code>0x</code> or <code>0X</code>.
</p>
<p>
In input, <code>%d</code> matches signed decimal, <code>%u</code> matches
unsigned decimal, <code>%o</code> unsigned octal.
<code>%x</code> and <code>%X</code> both match upper or lower case unsigned
hexadecimal.
Octal and hexadecimal values can optionally be prefixed.
<code>%i</code> matches any integer in decimal, or prefixed octal or
hexadecimal notation.
Leading whitespaces are skipped.
</p>
<a name="stds"></a>
<h2>5. Standard STRING Converters (<code>%s</code>, <code>%c</code>)</h2>
<p>
In output, <code>%s</code> prints a string.
If <em>precision</em> is specified, this is the maximum string length.
<code>%c</code> is a LONG format in output, printing one character!
</p>
<p>
In input, <code>%s</code> matches a sequence of non-whitespace characters
and <code>%c</code> a sequence of not-null characters.
The maximum string length is given by <em>width</em>.
The default <em>width</em> is infinite for <code>%s</code> and
1 for <code>%c</code>.
Leading whitespaces are skipped with <code>%s</code> but not with
<code>%c</code>.
The empty string matches.
</p>
<a name="cset"></a>
<h2>6. Standard Charset STRING Converter (<code>%[<em>charset</em>]</code>)</h2>
<p>
This is an input-only format.
It matches a sequence of characters from <em>charset</em>.
If <em>charset</em> starts with <code>^</code>, the format matches
all characters <u>not</u> in <em>charset</em>.
Leading whitespaces are not skipped.
</p>
<p>
Example: <code>%[_a-z]</code> matches a string consisting
entirely of <code>_</code> (underscore) or letters from <code>a</code>
to <code>z</code>.
</p>
<a name="enum"></a>
<h2>7. ENUM Converter (<code>%{<em>string0</em>|<em>string1</em>|...}</code>)</h2>
<p>
This format maps an unsigned integer value on a set of strings.
The value 0 corresponds to <em>string0</em> and so on.
The strings are separated by <code>|</code>.
If one of the strings contains <code>|</code> or <code>}</code>,
a <code>\</code> must be used to escape the character.
</p>
<p>
Example: <code>%{OFF|STANDBY|ON}</code> mapps the string <code>OFF</code>
to the value 0, <code>STANDBY</code> to 1 and <code>ON</code> to 2.
</p>
<p>
In output, depending on the value, one of the strings is printed.
</p>
<p>
In input, if any of the strings matches the value is set accordingly.
</p>
<a name="bin"></a>
<h2>8. Binary LONG Converter (<code>%b</code>, <code>%B<em>zo</em></code>)</h2>
<p>
This format prints or scans an unsigned integer represented as a binary
string (one character per bit).
The <code>%b</code> format uses the characters <code>0</code> and
<code>1</code>.
With the <code>%B</code> format, you can choose two other characters
to represent zero and one.
</p>
<p>
Examples: <code>%B.!</code> or <code>%B\x00\xff</code>.
<code>%B01</code> is equivalent to <code>%b</code>.
</p>
<p>
If in output <em>width</em> is larger than the number of significant bits,
then the flag <code>0</code> means that the value should be padded with
with the chosen zero character instead of spaces.
If <em>precision</em> is set, it means the number of significant bits.
Otherwise, the highest 1 bit defines the number of significant bits.
There is no alternate format when <code>#</code> is used.
</p>
<p>
In input, leading spaces are skipped.
A maximum of <em>width</em> characters is read.
Conversion stops with the first character that is not the zero or the
one character.
</p>
<a name="raw"></a>
<h2>9. Raw LONG Converter (<code>%r</code>)</h2>
<p>
The raw converter does not really "convert".
A signed integer value is written or read in the internal
(usually two's complement) representation of the computer.
The normal byte order is <em>big endian</em>, i.e. most significant byte
first.
With the <code>#</code> flag, the byte order is changed to <em>little
endian</em>, i.e. least significant byte first.
</p>
<p>
In output, the <em>width</em> least significant bytes of the value
are written.
If <em>width</em> is larger than the size of a <code>long</code>,
the value is sign extended.
</p>
<p>
In input, <em>width</em> bytes are read and put into the value.
If <em>width</em> is longer than the size of a <code>long</code>, only
the least significant bytes are used.
</p>
<a name="bcd"></a>
<h2>10. Packed BCD (Binary Coded Decimal) LONG Converter (<code>%D</code>)</h2>
<p>
Packed BCD is a format where each byte contains two binary coded
decimal digits (<code>0</code> ... <code>9</code>).
Thus a BCD byte is in the range from <code>0x00</code> to <code>0x99</code>.
The normal byte order is <em>big endian</em>, i.e. most significant byte
first.
With the <code>#</code> flag, the byte order is changed to <em>little
endian</em>, i.e. least significant byte first.
The <code>+</code> flag defines that the value is signed, using the
upper half of the most significant byte for the sign.
Otherwise the value is unsigned.
</p>
<p>
In output, <em>precision</em> decimal digits are printed in at least
<em>width</em> output bytes.
Signed negative values have <code>0xF</code> in their most significant half
byte followed by the absolute value.
</p>
<p>
In input, <em>width</em> bytes are read.
If the value is signed, a one in the most significant bit is interpreted as
a negative sign.
Input stops with the first byte (after the sign) that does not represent a
BCD value, i.e. where either the upper or the lower half byte is larger
than 9.
</p>
<a name="chksum"></a>
<h2>11. Checksum Pseudo-Converter (<code>%&lt;<em>checksum</em>&gt;</code>)</h2>
<p>
This is not a normal "converter", because no user data is converted.
Instead, a checksum is calculated from the input or output.
The <em>width</em> field is the byte number from which to start
calculating the checksum.
Default is 0, i.e. the first byte of the input or output of the current
command.
The last byte is <em>prec</em> bytes before the checksum (default 0).
For example in <code>"abcdefg%&lt;xor&gt;"</code> the checksum is calculated
from <code>abcdefg</code>,
but in <code>"abcdefg%2.1&lt;xor&gt;"</code> only from <code>cdef</code>.
</p>
<p>
Normally, multi-byte checksums are in <em>big endian</em> byteorder,
i.e. most significant byte first.
With the <code>#</code> flag, the byte order is changed to <em>little
endian</em>, i.e. least significant byte first.
</p>
<p>
The <code>0</code> flag changes the checksum representation from
binary to hexadecimal ASCII (2 bytes per checksum byte).
<!--
In output, the case of the ASCII checksum matches the case of first
letter of the function name.
E.g. <code>out&nbsp;"123456789%&lt;sum&gt;"</code> writes <code>dd</code>
but <code>out&nbsp;"123456789%&lt;Sum&gt;"</code> writes <code>DD</code>.
In input, case is ignored.
-->
</p>
<p>
In output, the checksum is appended.
</p>
<p>
In input, the next byte or bytes must match the checksum.
</p>
<h3>Implemented checksum functions</h3>
<dl>
<dt><code>%&lt;SUM&gt;</code> or <code>%&lt;SUM8&gt;</code></dt>
<dd>One byte. The sum of all characters modulo 2<sup>8</sup>.</dd>
<dt><code>%&lt;SUM16&gt;</code></dt>
<dd>Two bytes. The sum of all characters modulo 2<sup>16</sup>.</dd>
<dt><code>%&lt;SUM32&gt;</code></dt>
<dd>Four bytes. The sum of all characters modulo 2<sup>32</sup>.</dd>
<dt><code>%&lt;NEGSUM&gt;</code> or <code>%&lt;NSUM&gt;</code> or <code>%&lt;-SUM&gt;</code></dt>
<dd>One byte. The negative of the sum of all characters modulo 2<sup>8</sup>.</dd>
<dt><code>%&lt;NOTSUM&gt;</code> or <code>%&lt;~SUM&gt;</code></dt>
<dd>One byte. The bitwise inverse of the sum of all characters modulo 2<sup>8</sup>.</dd>
<dt><code>%&lt;XOR&gt;</code></dt>
<dd>One byte. All characters xor'ed.</dd>
<dt><code>%&lt;CRC8&gt;</code></dt>
<dd>One byte. An often used 8 bit CRC checksum
(poly=0x07, init=0x00, xorout=0x00).</dd>
<dt><code>%&lt;CCITT8&gt;</code></dt>
<dd>One byte. The CCITT standard 8 bit CRC checksum
(poly=0x31, init=0x00, xorout=0x00).</dd>
<dt><code>%&lt;CRC16&gt;</code></dt>
<dd>Two bytes. An often used 16 bit CRC checksum
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
<dt><code>%&lt;CRC16R&gt;</code></dt>
<dd>Two bytes. An often used reflected 16 bit CRC checksum
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
<dt><code>%&lt;CCITT16&gt;</code></dt>
<dd>Two bytes. The usual (but <a target="ex"
href="http://www.joegeluso.com/software/articles/ccitt.htm">wrong?</a>)
implementation of the CCITT standard 16 bit CRC checksum
(poly=0x1021, init=0xFFFF, xorout=0x0000).</dd>
<dt><code>%&lt;CCITT16A&gt;</code></dt>
<dd>Two bytes. The unusual (but <a target="ex"
href="http://www.joegeluso.com/software/articles/ccitt.htm">correct?</a>)
implementation of the CCITT standard 16 bit CRC checksum with augment.
(poly=0x1021, init=0x1D0F, xorout=0x0000).</dd>
<dt><code>%&lt;CRC32&gt;</code></dt>
<dd>Four bytes. The standard 32 bit CRC checksum.
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
<dt><code>%&lt;CRC32R&gt;</code></dt>
<dd>Four bytes. The standard reflected 32 bit CRC checksum.
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
<dt><code>%&lt;JAMCRC&gt;</code></dt>
<dd>Four bytes. Another reflected 32 bit CRC checksum.
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0x00000000).</dd>
<dt><code>%&lt;ADLER32&gt;</code></dt>
<dd>Four bytes. The Adler32 checksum according to <a target="ex"
href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950</a>.</dd>
<dt><code>%&lt;HEXSUM8&gt;</code></dt>
<dd>One byte. The sum of all hex digits. (Other characters are ignored.)</dd>
</dl>
<hr>
<p align="right"><a href="processing.html">Next: Record Processing</a></p>
<p><small>Dirk Zimoch, 2007</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

32
doc/head.html Normal file
View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Headbar</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
<style type="text/css">
<!--
body {margin:0px 0px 0px 0px;}
big {font-size: 30px; font-family:serif;}
-->
</style>
</head>
<body bgcolor="white">
<table cellspacing=0 cellpadding=0 border=0 width="100%">
<tr><td bgcolor="#267ab8" colspan=6 valign="bottom" height=9 width="100%"></td></tr>
<tr><td bgcolor="#000000" colspan=6 valign="bottom" height=1 width="100%"></td></tr>
<tr>
<td><img src="space.gif" width=180 height=1 alt=""><center><a href="http://www.psi.ch" target="ex"><img src="PSI.gif" width=150 height=55 alt="PSI" border=0></a></center></td>
<td><img src="space.gif" width=1 height=65 alt=""></td>
<td><a href="http://www.aps.anl.gov/epics" target="ex"><img
src="EPICS.gif" border=0 width=50 height=50 alt="EPICS"></a></td>
<td width="100%" align="center" nowrap>
<big><b><em id="subtitle">StreamDevice</em></b></big></td>
<td><img src="space.gif" width=166 height=1 alt=""><center><a href="http://sls.web.psi.ch/view.php/about/index.html" target="ex"><img src="SLS.gif" width=146 height=55 alt="SLS" border=0></a></center></td>
</tr>
<tr><td bgcolor="#267ab8" colspan=6 valign="bottom" height=4 width="100%"></td></tr>
<tr><td bgcolor="#000000" colspan=6 valign="bottom" height=1 width="100%"></td></tr>
</table>
</body>
</html>

20
doc/index.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>StreamDevice Documentation</title>
<link rel="shortcut icon" href="sls_icon.ico">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<frameset rows="80,*" framespacing=0 frameborder=0 border=0>
<frame src="head.html" name="head" scrolling="no" noresize>
<frameset cols="180,*" >
<frame src="nav.html" name="nav" noresize>
<frame src="stream.html" name="text">
</frameset>
<noframes>
<a href="stream.html">Click here for no-frames version.</a>
</noframes>
</frameset>
</html>

68
doc/longin.html Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: longin Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: longin Records</h1>
<h2>Normal Operation</h2>
<p>
The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

68
doc/longout.html Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: longout Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: longout Records</h1>
<h2>Normal Operation</h2>
<p>
The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

94
doc/mbbi.html Normal file
View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: mbbi Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: mbbi Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<dl>
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
(is not <code>0</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL&amp;MASK</code><br>
<u>Input:</u> <code>RVAL=<i>x</i>&amp;MASK</code><br>
Note that the record shifts <code>RVAL</code> right by
<code>SHFT</code> bits, compares the result with all of
<code>ZRVL</code> ... <code>FFVL</code>, and sets <code>VAL</code>
to the index of the first match.
<code>MASK</code> is initialized to <code>NOBT</code> 1-bits shifted
left by <code>SHFT</code>. If <code>MASK==0</code> (because
<code>NOBT</code> was not set) it is ignored, i.e.
<code><i>x</i>=RVAL</code> and <code>RVAL=<i>x</i></code>.
</dd>
<dt>If none of <code>ZRVL</code> ... <code>FFVL</code> is set
(all are <code>0</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
</dl>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> Depending on <code>VAL</code>, one of <code>ZRST</code>
or <code>FFST</code> is written. <code>VAL</code> must be in the range
0 ... 15.<br>
<u>Input:</u> If input is equal one of <code>ZRST</code> ...
<code>FFST</code>, <code>VAL</code> is set accordingly.
Other input strings are not accepted.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

80
doc/mbbiDirect.html Normal file
View File

@ -0,0 +1,80 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: mbbiDirect Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: mbbiDirect Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<dl>
<dt>If <code>MASK==0</code> (because <code>NOBT</code> is not set):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>If <code>MASK!=0</code>:</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL&amp;MASK</code><br>
<u>Input:</u> <code>RVAL=<i>x</i>&amp;MASK</code><br>
</dd>
</dl>
<code>MASK</code> is initialized to <code>NOBT</code> 1-bits shifted
left by <code>SHFT</code>.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">calcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

95
doc/mbbo.html Normal file
View File

@ -0,0 +1,95 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: mbbo Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: mbbo Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<dl>
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
(is not <code>0</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL&amp;MASK</code><br>
Note that the record calculates <code>RVAL</code> by choosing one of
<code>ZRVL</code> ... <code>FFVL</code> depending on <code>VAL</code>
and by shifting it left by <code>SHFT</code> bits.<br>
<u>Input:</u> <code>RBV=<i>x</i>&amp;MASK</code><br>
<code>MASK</code> is initialized to <code>NOBT</code> 1-bits shifted
left by <code>SHFT</code>. If <code>MASK==0</code> (because
<code>NOBT</code> was not set) it is ignored, i.e.
<code><i>x</i>=RVAL</code> and <code>RBV=<i>x</i></code>.
</dd>
<dt>If none of <code>ZRVL</code> ... <code>FFVL</code> is set
(all are <code>0</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
</dl>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> Depending on <code>VAL</code>, one of <code>ZRST</code>
... <code>FFST</code> is written. <code>VAL</code> must be in the
range 0 ... 15.<br>
<u>Input:</u> If input is equal one of <code>ZRST</code> ...
<code>FFST</code>, <code>VAL</code> is set accordingly.
Other input strings are not accepted.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. In contrast to normal operation, LONG input is put to
<code>RVAL</code> as well as to <code>RBV</code> and converted by the
record.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

82
doc/mbboDirect.html Normal file
View File

@ -0,0 +1,82 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: mbboDirect Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: mbboDirect Records</h1>
<h2>Normal Operation</h2>
<p>
Depending on the format type, different record fields are used
for output and input. The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<dl>
<dt>If <code>MASK==0</code> (because <code>NOBT</code> is not set):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>If <code>MASK!=0</code>:</dt>
<dd>
<u>Output:</u> <code><i>x</i>=RVAL&amp;MASK</code><br>
<u>Input:</u> <code>RBV=<i>x</i>&amp;MASK</code><br>
</dd>
</dl>
<code>MASK</code> is initialized to <code>NOBT</code> 1-bits shifted
left by <code>SHFT</code>.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
Not allowed.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. In contrast to normal operation, input is put to
<code>RVAL</code> as well as to <code>RBV</code> and converted by the
record if <code>MASK!=0</code>.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

218
doc/nav.html Normal file
View File

@ -0,0 +1,218 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Navbar</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
<script type="text/javascript">
<!--
active="";
function show(name) {
var m = document.getElementById(name);
var b = document.getElementById(name+"Button");
if (active != "") { hide(active); }
m.style.display = "block";
b.innerHTML="[&laquo;]";
b.href="javascript:hide(\'"+name+"\')"
active=name;
}
function hide(name) {
var m = document.getElementById(name);
var b = document.getElementById(name+"Button");
m.style.display = "none";
b.innerHTML="[&raquo;]";
b.href="javascript:show(\'"+name+"\')"
active="";
}
function printview() {
w = window.open(parent.text.location, "_parent", "dependent=yes,width=800,menubar=yes,toolbar=yes,location=yes");
}
-->
</script>
<style type="text/css">
<!--
body {margin:0px 0px 0px 0px;
font-family:sans-serif;
font-weight:bold;
font-size:13px;}
a {text-decoration:none;}
a:link {color:#333333;}
a:visited {color:#333333;}
a:hover {color:#FF0000;}
a:active {color:#FF0000;}
.top {margin-bottom: 0px;
margin-top: 10px;
border-bottom: solid 1px black;}
.top ul {margin-left: 5px;
margin-top: 2px;
margin-bottom: 2px;
font-size:95%;
line-height:120%;
padding-left:1em;}
.subsub {margin-left: 15px;
line-height:120%;
font-size:80%;}
h1 {font-size:120%;
margin-top: 20px;
margin-right: 20px;
margin-bottom: 10px;
color:#267ab8;}
-->
</style>
</head>
<body background="bg.gif">
<p align="center">
</p>
<div style="margin-left: 20px;">
<h1>User's Guide</h1>
<div class="top">
<a target="text" href="stream.html">Intro</a>
</div>
<div class="top">
<a target="text" href="setup.html">Setup</a>
<a href="javascript:show('setup')" id="setupButton"></a>
<ul id="setup">
<li><a target="text" href="setup.html#pre">Prerequisites</a>
<ul>
<li><a target="text" href="epics3_13.html">Using EPICS 3.13</a></li>
</ul></li>
<li><a target="text" href="setup.html#lib">Build Library</a></li>
<li><a target="text" href="setup.html#app">Build Application</a></li>
<li><a target="text" href="setup.html#sta">Startup Script</a></li>
<li><a target="text" href="setup.html#pro">Protocol File</a>
<ul>
<li><a target="text" href="setup.html#reload">Reloading</a></li>
</ul></li>
<li><a target="text" href="setup.html#rec">Records</a></li>
</ul>
</div>
<div class="top">
<a target="text" href="protocol.html">Protocol Files</a>
<a href="javascript:show('protocol')" id="protocolButton"></a>
<ul id="protocol">
<li><a target="text" href="protocol.html#gen">General</a></li>
<li><a target="text" href="protocol.html#proto">Protocols</a></li>
<li><a target="text" href="protocol.html#cmd">Commands</a></li>
<li><a target="text" href="protocol.html#str">Strings</a></li>
<li><a target="text" href="protocol.html#var">Variables</a>
<ul>
<li><a target="text" href="protocol.html#sysvar">System variables</a></li>
<li><a target="text" href="protocol.html#argvar">Protocol Arguments</a></li>
<li><a target="text" href="protocol.html#usrvar">User variables</a></li>
</ul></li>
<li><a target="text" href="protocol.html#except">Exception Handlers</a></li>
</ul>
</div>
<div class="top">
<a target="text" href="formats.html">Format Converters</a>
<a href="javascript:show('formats')" id="formatsButton"></a>
<ul id="formats">
<li><a target="text" href="formats.html#syntax">Syntax</a></li>
<li><a target="text" href="formats.html#types">Types &amp; Fields</a></li>
<li><a target="text" href="formats.html#stdd">%f %e %g</a></li>
<li><a target="text" href="formats.html#stdl">%i %d %u %o %x</a></li>
<li><a target="text" href="formats.html#stds">%s %c</a></li>
<li><a target="text" href="formats.html#cset">%[<em>charset</em>]</a></li>
<li><a target="text" href="formats.html#enum">%{<em>s0</em>|<em>s1</em>|...}</a></li>
<li><a target="text" href="formats.html#bin">%b %B</a></li>
<li><a target="text" href="formats.html#raw">%r</a></li>
<li><a target="text" href="formats.html#bcd">%D</a></li>
<li><a target="text" href="formats.html#chksum">%&lt;<em>checksum</em>&gt;</a></li>
</ul>
</div>
<div class="top">
<a target="text" href="processing.html">Record Processing</a>
<a href="javascript:show('proc')" id="procButton"></a>
<ul id="proc">
<li><a target="text" href="processing.html#proc">Normal Processing</a></li>
<li><a target="text" href="processing.html#init">Initialization</a></li>
<li><a target="text" href="processing.html#iointr">I/O Intr</a></li>
</ul>
</div>
<div class="top">
<a target="text" href="recordtypes.html">Record Types</a>
<a href="javascript:show('records')" id="recordsButton"></a>
<ul id="records" class="sub">
<li><a target="text" href="aai.html">aai</a></li>
<li><a target="text" href="aao.html">aao</a></li>
<li><a target="text" href="ai.html">ai</a></li>
<li><a target="text" href="ao.html">ao</a></li>
<li><a target="text" href="bi.html">bi</a></li>
<li><a target="text" href="bo.html">bo</a></li>
<li><a target="text" href="mbbi.html">mbbi</a></li>
<li><a target="text" href="mbbo.html">mbbo</a></li>
<li><a target="text" href="mbbiDirect.html">mbbiDirect</a></li>
<li><a target="text" href="mbboDirect.html">mbboDirect</a></li>
<li><a target="text" href="stringin.html">stringin</a></li>
<li><a target="text" href="stringout.html">stringout</a></li>
<li><a target="text" href="longin.html">longin</a></li>
<li><a target="text" href="longout.html">longout</a></li>
<li><a target="text" href="waveform.html">waveform</a></li>
<li><a target="text" href="calcout.html">calcout</a></li>
<li><a target="text" href="scalcout.html">scalcout</a></li>
</ul>
</div>
<div class="top">
<a target="text" href="tipsandtricks.html">Tips &amp; Tricks</a>
<a href="javascript:show('tipsandtricks')" id="tipsandtricksButton"></a>
<ul id="tipsandtricks">
<li><a target="text" href="tipsandtricks.html#argvar">Many almost identical protocols</a></li>
<li><a target="text" href="tipsandtricks.html#iointr">Read unsolicited input</a></li>
<li><a target="text" href="tipsandtricks.html#multiline">Read multi-line messages</a></li>
<li><a target="text" href="tipsandtricks.html#writemany">Write more than one value in one message</a></li>
<li><a target="text" href="tipsandtricks.html#readmany">Read more than one value from one message</a></li>
<li><a target="text" href="tipsandtricks.html#mixed">Read values of mixed data type</a></li>
</ul>
</div>
<h1>Programmer's Guide</h1>
<div class="top">
<a target="text" href="recordinterface.html">Record API</a>
</div>
<div class="top">
<a target="text" href="businterface.html">Bus API</a>
<a href="javascript:show('bus')" id="busButton"></a>
<ul id="bus">
<li><a target="text" href="businterface.html#class">Interface Class</a></li>
<li><a target="text" href="businterface.html#theory">Theory of Operation</a>
<ul>
<li><a target="text" href="businterface.html#registration">Registration</a></li>
<li><a target="text" href="businterface.html#create">Creation &amp; deletion</a></li>
<li><a target="text" href="businterface.html#connect">Connecting</a></li>
<li><a target="text" href="businterface.html#lock">Bus locking</a></li>
<li><a target="text" href="businterface.html#write">Writing output</a></li>
<li><a target="text" href="businterface.html#read">Reading input</a></li>
<li><a target="text" href="businterface.html#event">Handling events</a></li>
</ul></li>
</ul>
</div>
<div class="top">
<a target="text" href="formatconverter.html">Format Converter API</a>
</div>
<div class="top">
<a target="text" href="osinterface.html">Operating System API</a>
</div>
</div>
<p align="center" style="margin-top:20px;">
<script type="text/javascript">
<!--
document.writeln('<a href="javascript:printview()">' +
'<img src="printer.gif" alt="Printer friendly" border=0><br>' +
'<small>Printer friendly<\/small><\/a>');
hide('setup');
hide('protocol');
hide('formats');
hide('proc');
hide('records');
hide('bus');
hide('tipsandtricks');
chapter=decodeURIComponent(parent.location.search.substr(1));
if (chapter) parent.text.location.href=chapter;
//-->
</script>
</p>
</body>
</html>

20
doc/osinterface.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Operating System API</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Operating System API</h1>
<h2>Sorry, this documentation is still missing.</h2>
<hr>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

BIN
doc/printer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

244
doc/processing.html Normal file
View File

@ -0,0 +1,244 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Record Processing</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Record Processing</h1>
<a name="proc"></a>
<h2>1. Normal Processing</h2>
<p>
<em>StreamDevice</em> is an asynchronous device support
(see <a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/AppDevGuide.pdf"
target="ex">IOC Application Developer's Guide</a> chapter 12:
Device Support).
Whenever the record is processed, the <a href="protocol.html">protocol</a>
is scheduled to start and the record is left active (<code>PACT=1</code>).
The protocol itself runs in another thread.
That means that any waiting in the protocol does not delay any other
part of the IOC.
</p>
<p>
After the protocol has finished, the record is processed again, leaving
<code>PACT=0</code> this time, triggering monitors and processing
the forward link <code>FLNK</code>.
Note that input links with PP flag pointing to a <em>StreamDevice</em>
record will read the <u>old</u> value first and start the protocol
afterward.
This is a problem all asynchronous EPICS device supports have.
</p>
<p>
The first <code>out</code> command in the protocol locks the device
for exclusive access.
That means that no other record can communicate with that device.
This ensures that replies given by the device reach the record
which has sent the request.
On a bus with many devices on different addresses, this
normally locks only one device.
The device is unlocked when the protocol terminates.
Another record trying to lock the same device has to wait and
might get a <code>LockTimeout</code>.
<p>
</p>
<p>If any error happens, the protocol is aborted. The record will have
its <code>SEVR</code> field set to <code>INVALID</code> and its
<code>STAT</code> field to something describing the error:
</p>
<dl>
<dt><code>TIMEOUT</code></dt>
<dd>
The device could not be locked (<code>LockTimeout</code>) or the
device did not reply (<code>ReplyTimeout</code>).
</dd>
<dt><code>WRITE</code></dt>
<dd>
Output could not be written to the device (<code>WriteTimeout</code>).
</dd>
<dt><code>READ</code></dt>
<dd>
Input from the device started but stopped unexpectedly
(<code>ReadTimeout</code>).
</dd>
<dt><code>COMM</code></dt>
<dd>
The device driver reported some other communication error (e.g.
unplugged cable).
</dd>
<dt><code>CALC</code></dt>
<dd>
Input did not match the argument string of the <code>in</code> command
or it contained values the record did not accept.
</dd>
<dt><code>UDF</code></dt>
<dd>
Some fatal error happened or the record has not been initialized
correctly (e.g. because the protocol is erroneous).
</dd>
</dl>
<p>
If the protocol is aborted, an
<a href="protocol.html#except">exception handler</a> might be executed
if defined.
Even if the exception handler can complete with no further error, the
protocol will not resume and <code>SEVR</code> and <code>STAT</code>
will be set according to the original error.
</p>
<a name="init"></a>
<h2>2. Initialization</h2>
<p>
Often, it is required to initialize records from the hardware after
booting the IOC, especially output records.
For this purpose, initialization is formally handled as an
<a href="protocol.html#except">exception</a>.
The <code>@init</code> handler is called as part of the
<code>initRecord()</code> function during <code>iocInit</code>
before any scan task starts.
</p>
<p>
In contrast to <a href="#proc">normal processing</a>, the protocol
is handled synchronously.
That means that <code>initRecord()</code> does not return before the
<code>@init</code> handler has finished.
Thus, the records initialize one after the other.
The scan tasks are not started and <code>iocInit</code> does not
return before all <code>@init</code> handlers have finished.
If the handler fails, the record remains uninitialized:
<code>UDF=1</code>, <code>SEVR=INVALID</code>,
<code>STAT=UDF</code>.
</p>
<p>
The <code>@init</code> handler has nothing to do with the
<code>PINI</code> field.
The handler does <u>not</u> process the record nor does it trigger
forward links or other PP links.
It runs <u>before</u> <code>PINI</code> is handled.
If the record has <code>PINI=YES</code>, the <code>PINI</code>
processing is a <a href="#proc">normal processing</a> after the
<code>@init</code> handlers of all records have completed.
</p>
<p>
Depending on the record type, format converters might work
slightly different from normal processing.
Refer to the description of
<a href="recordtypes.html">supported record types</a> for details.
</p>
<p>
If the <code>@init</code>handler has read a value and has completed
without error, the record starts in a defined state.
That means <code>UDF=0</code>, <code>SEVR=NO_ALARM</code>,
<code>STAT=NO_ALARM</code> and the <code>VAL</code> field contains
the value read from the device.
</p>
<p>
If no <code>@init</code> handler is installed, <code>VAL</code> and
<code>RVAL</code> fields remain untouched.
That means they contain the value defined in the record definition,
read from a constant <code>INP</code> or <code>DOL</code> field,
or restored from a bump-less reboot system
(e.g. <em>autosave</em> from the <em>synApps</em> package).
</p>
<a name="iointr"></a>
<h2>3. I/O Intr</h2>
<p>
<em>StreamDevice</em> supports I/O event scanning.
This is a mode where record processing is triggered by the device
whenever the device sends input.
</p>
<p>
In terms of protocol execution this means:
When the <code>SCAN</code> field is set to <code>I/O Intr</code>
(during <code>iocInit</code> or later),
the protocol starts without processing the record.
With the first <code>in</code> command, the protocol is suspended.
If the device has been locked (i.e there was an <code>out</code>
command earlier in the protocol), it is unlocked now.
That means that other records can communicate to the device while
this record is waiting for input.
This <code>in</code> command ignores <code>replyTimeout</code>,
it waits forever.
</p>
<p>
The protocol now receives any input from the device.
It also gets a copy of all input directed to other records.
Non-matching input does not generate a mismatch
<a href="protocol.html#except">exception</a>.
It just restarts the <code>in</code> command until matching input
is received.
</p>
<p>
After receiving matching input, the protocol continues normally.
All other <code>in</code> commands are handled normally.
When the protocol has completed, the record is processed.
It then triggers monitors, forward links, etc.
After the record has been processed, the protocol restarts.
</p>
<p>
This mode is useful in two cases:
First for devices that send data automatically without being asked.
Second to distribute multiple values in one message to different
records.
In this case, one record would send a request to the device and pick
only one value out of the reply.
The other values are read by records in <code>I/O Intr</code> mode.
</p>
<h3>Example:</h3>
<p>
Device <em>dev1</em> has a "region of interest" (ROI) defined by
a start value and an end value. When asked "<code>ROI?</code>",
it replies something like "<code>ROI 17.3 58.7</code>",
i.e. a string containing both values.
</p>
<p>
We need two ai records to store the two values. Whenever record
<code>ROI:start</code> is processed, it requests ROI from the device.
Record <code>ROI:end</code> updates automatically.
</p>
<pre>
record (ai "ROI:start") {
field (DTYP, "stream")
field (INP, "@myDev.proto getROIstart dev1")
}
record (ai "ROI:end") {
field (DTYP, "stream")
field (INP, "@myDev.proto getROIend dev1")
field (SCAN, "I/O Intr")
}
</pre>
<p>
Only one of the two protocols sends a request, but both read
their part of the same reply message.
</p>
<pre>
getROIstart {
out "ROI?";
in "ROI %f %*f";
}
getROIend {
in "ROI %*f %f";
}
</pre>
<p>
Note that the other value is also parsed by each protocol, but skipped
because of the <code>%*</code> <a href="formats.html">format</a>.
Even though the <code>getROIend</code> protocol may receive input
from other requests, it silently ignores every message that does not start
with "<code>ROI</code>", followed by two floating point numbers.
</p>
<hr>
<p align="right"><a href="recordtypes.html">Next: Supported Record Types</a></p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

552
doc/protocol.html Normal file
View File

@ -0,0 +1,552 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Protocol Files</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Protocol Files</h1>
<a name="gen"></a>
<h2>1. General Information</h2>
<p>
A protocol file describes the communication with one device type.
It contains <a href="#proto"><em>protocols</em></a> for each function
of the device type and <a href="#var"><em>variables</em></a> which affect
how the <a href="#cmd"><em>commands</em></a> in a protocol work.
It does not contain information about the individual device or the used
communication bus.
</p>
<p>
Each device type should have its own protocol file.
I suggest to choose a file name that contains the name of the device type.
Don't use spaces in the file name and keep it short.
The file will be referenced by its name in the <code>INP</code>
or <code>OUT</code> link of the records which use it.
The protocol file must be stored in one of the directories listed
in the environment variable <code>STREAM_PROTOCOL_PATH</code>
(see chapter <a href="setup.html#sta">Setup</a>).
</p>
<p>
The protocol file is a plain text file.
Everything not enclosed in quotes
(single <code>'</code> or double <code>"</code>) is not case sensitive.
This includes the names of <a href="#cmd">commands</a>,
<a href="#proto">protocols</a> and <a href="#var">variables</a>.
There may be any amount of whitespaces (space, tab, newline, ...) or
comments between names, <a href="#str">quoted strings</a> and special
characters, such as <code>={};</code>.
A comment is everything starting from an unquoted <code>#</code>
until the end of the line.
</p>
<h3>Example Protocol File:</h3>
<pre>
# This is an example protocol file
Terminator = CR LF;
# Frequency is a float
# use ai and ao records
getFrequency {
out "FREQ?"; in "%f";
}
setFrequency {
out "FREQ %f";
@init { getFrequency; }
}
# Switch is an enum, either OFF or ON
# use bi and bo records
getSwitch {
out "SW?"; in "SW %{OFF|ON}";
}
setSwitch {
out "SW %{OFF|ON}";
@init { getSwitch; }
}
# Connect a stringout record to this to get
# a generic command interface.
# After processing finishes, the record contains the reply.
debug {
ExtraInput = Ignore;
out "%s"; in "%39c"
}
</pre>
<a name="proto"></a>
<h2>2. Protocols</h2>
<p>
For each function of the device type, define one protocol.
A protocol consists of a name followed by a body in braces <code>{}</code>.
The name must be unique within the protocol file.
It is used to reference the protocol in the
<code>INP</code> or <code>OUT</code> link of the record,
thus keep it short.
It should describe the function of the protocol.
It must not contain spaces or any of the characters
<code>,;={}()$'"\#</code>.
</p>
<p>
The protocol body contains a sequence of <a href="#cmd">commands</a> and
optionally <a href="#var">variable assignments</a> separated by
<code>;</code>.
</p>
<h3>Referencing other protocols</h3>
<p>
To save some typing, a previously defined protocol can be called inside
another protocol like a <a href="#cmd">command</a> without parameters.
The protocol name is replaced by the commands in the referenced protocol.
However, this does not include any
<a href="#var">variable assignments</a> or
<a href="#except">exception handlers</a> from the referenced protocol.
See the <code>@init</code> handlers in the above example.
</p>
<h3>Limitations</h3>
<p>
The <em>StreamDevice</em> protocol is not a programming language.
It has neither loops nor conditionals
(in this version of <em>StreamDevice</em>).
However, if an error occurs, e.g. a timeout or a mismatch in input
parsing, an <a href="#excep">exception handler</a> can be called to
clean up.
</p>
<a name="cmd"></a>
<h2>3. Commands</h2>
<p>
Seven different commands can be used in a protocol:
<code>out</code>, <code>in</code>, <code>wait</code>, <code>event</code>,
<code>exec</code>, <code>disconnect</code>, and <code>connect</code>.
Most protocols will consist only of a single <code>out</code> command to
write some value,
or an <code>out</code> command followed by an <code>in</code> command to
read a value.
But there can be any number of commands in a protocol.
</p>
<dl>
<dt><code>out <i>string</i>;</code></dt>
<dd>
Write output to the device.
The argument <a href="#str">string</a> may contain
<a href="formats.html">format converters</a> which are replaced by the
formatted value of the record before sending.
</dd>
<dt><code>in <i>string</i>;</code></dt>
<dd>
Read and parse input from the device.
The argument <a href="#str">string</a> may contain
<a href="formats.html">format converters</a> which specify how to
interpret data to be put into the record.
Input must match the argument string.
Any input from the device should be consumed with an
<code>in</code> command.
If a device, for example, acknowledges a setting, use an
<code>in</code> command to check the acknowledge, even though
it contains no user data.
</dd>
<dt><code>wait <i>milliseconds</i>;</code></dt>
<dd>
Just wait for some milliseconds.
Depending on the resolution of the timer system, the actual delay
can be slightly longer than specified.
</dd>
<dt><code>event(<i>eventcode</i>) <i>milliseconds</i>;</code></dt>
<dd>
Wait for event <code><i>eventcode</i></code> with some timeout.
What an event actually means depends on the used
<a href="businterface.html#event">bus</a>.
Some buses do not support events at all, some provide many different
events.
If the bus supports only one event, <code>(<i>eventcode</i>)</code>
is dispensable.
</dd>
<dt><code>exec <i>string</i>;</code></dt>
<dd>
The argument <a href="#str">string</a> is passed to the IOC shell
as a command to execute.
</dd>
<dt><code>disconnect;</code></dt>
<dd>
Disconnect from the hardware.
This is probably not supported by all busses.
Any <code>in</code> or <code>out</code> command will automatically
reconnect.
Only records reading in
<a href="processing.html#iointr">"I/O Intr"</a> mode
will not cause a reconnect.
</dd>
<dt><code>connect <i>milliseconds</i>;</code></dt>
<dd>
Explicitely connect to the hardware with <code><i>milliseconds</i></code>
timeout.
Since connection is handled automatically, this command is normally not
needed.
It may be useful after a <code>disconnect</code>.
</dd>
</dl>
<a name="str"></a>
<h2>4. Strings</h2>
<p>
In a <em>StreamDevice</em> protocol file, strings can be written
as quoted literals (single quotes or double quotes), as
a sequence of bytes values, or as a combination of both.
</p>
<p>
Examples for quoted literals are:<br>
<code>"That's a string."</code><br>
<code>'Say "Hello"'</code>
</p>
<p>
There is no difference between double quoted and single quoted
literals, it just makes it easier to use quotes of the other type
in a string.
To break long strings into multiple lines of the protocol file,
close the quotes before the line break and reopen them in the next line.
Don't use a line break inside quotes.
</p>
<p>
As arguments of <code>out</code> or <code>in</code>
<a href="#cmd">commands</a>, string literals can contain
<a href="formats.html">format converters</a>.
A format converter starts with <code>%</code> and works similar
to formats in the C functions <em>printf()</em> and <em>scanf()</em>.
</p>
<p>
<em>StreamDevice</em> uses the backslash character <code>\</code> to
define some escape sequences in quoted string literals:<br>
<code>\"</code>, <code>\'</code>, <code>\%</code>, and <code>\\</code>
mean literal <code>"</code>, <code>'</code>, <code>%</code>, and
<code>\</code>.<br>
<code>\a</code> means <em>alarm bell</em> (ASCII code 7).<br>
<code>\b</code> means <em>backspace</em> (ASCII code 8).<br>
<code>\t</code> means <em>tab</em> (ASCII code 9).<br>
<code>\n</code> means <em>new line</em> (ASCII code 10).<br>
<code>\r</code> means <em>carriage return</em> (ASCII code 13).<br>
<code>\e</code> means <em>escape</em> (ASCII code 27).<br>
<code>\x</code> followed by up to two hexadecimal digits means a byte with
that hex value.<br>
<code>\0</code> followed by up to three octal digits means a byte with
that octal value.<br>
<code>\1</code> to <code>\9</code> followed by up to two more decimal
digits means a byte with that decimal value.<br>
<code>\?</code> in the argument string of an <code>in</code>
<a href="#cmd">command</a> matches any input byte<br>
<code>\$</code> followed by the name of a
<a href="#var">protocol varible</a> is replaced by the contents of that
variable.
</p>
<p>
For non-printable characters, it is often easier to write sequences of
byte values instead of escaped quoted string literals.
A byte is written as an unquoted decimal, hexadecimal, or octal
number in the range of -128 to 255 (-0x80 to 0xff, -0200 to 0377).
<em>StreamDevice</em> also defines some symbolic names for frequently
used byte codes as aliases for the numeric byte value:<br>
<code>EOT</code> means <em>end of transmission</em> (ASCII code 4).<br>
<code>ACK</code> means <em>acknowledge</em> (ASCII code 6).<br>
<code>BEL</code> means <em>bell</em> (ASCII code 7).<br>
<code>BS</code> means <em>backspace</em> (ASCII code 8).<br>
<code>HT</code> or <code>TAB</code> mean <em>horizontal tabulator</em>
(ASCII code 9).<br>
<code>LF</code> or <code>NL</code> mean <em>line feed</em> /
<em>new line</em> (ASCII code 10).<br>
<code>CR</code> means <em>carriage return</em> (ASCII code 13).<br>
<code>ESC</code> means <em>escape</em> (ASCII code 27).<br>
<code>DEL</code> means <em>delete</em> (ASCII code 127).<br>
<code>SKIP</code> in the argument string of an <code>in</code>
<a href="#cmd">command</a> matches any input byte.
</p>
<p>
A single string can be built from several quoted literals and byte values
by writing them separated by whitespaces or comma.
</p>
<h3>Example:</h3>
<p>
The following lines represent the same string:<br>
<code>"Hello world\r\n"</code><br>
<code>'Hello',0x20,"world",CR,LF</code><br>
<code>72 101 108 108 111 32 119 111 114 108 100 13 10</code>
</p>
<a name="var"></a>
<h2>5. Protocol Variables</h2>
<p>
<em>StreamDevice</em> uses three types of variables in a protocol file.
<a href="#sysvar"><em>System variables</em></a> influence the behavior
of <code>in</code> and <code>out</code> <a href="#cmd">commands</a>.
<a href="#argvar"><em>Protocol arguments</em></a> work like function
arguments and can be specified in the <code>INP</code> or
<code>OUT</code> link of the record.
<a href="#usrvar"><em>User variables</em></a> can be defined and used
in the protocol as abbreviations for often used values.
</p>
<p>
System and user variables can be set in the global context of the
protocol file or locally inside protocols.
When set globally, a variable keeps its value until overwritten.
When set locally, a variable is valid inside the protocol only.
To set a variable use the syntax:<br>
<code><i>variable</i> = <i>value</i>;</code>
</p>
<p>
Set variables can be referenced outside of
<a href="#str">quoted strings</a> by
<code>$<i>variable</i></code> or <code>${<i>variable</i>}</code>
and inside quoted strings by
<code>\$<i>variable</i></code> or <code>\${<i>variable</i>}</code>.
The reference will be replaced by the value of the variable at
this point.
</p>
<a name="sysvar"></a>
<h3>System variables</h3>
<p>
This is a list of system variables, their default settings and
what they influence.
</p>
<dl>
<dt><code>LockTimeout = 5000;</code></dt>
<dd>
Integer. Affects first <code>out</code> command in a protocol.<br>
If other records currently use the device, how many milliseconds
to wait for exclusive access to the device before giving up?
</dd>
<dt><code>WriteTimeout = 100;</code></dt>
<dd>
Integer. Affects <code>out</code> commands.<br>
If we have access to the device but output cannot be written
immediately, how many milliseconds to wait before giving up?
</dd>
<dt><code>ReplyTimeout = 1000;</code></dt>
<dd>
Integer. Affects <code>in</code> commands.<br>
Different devices need different times to calculate
a reply and start sending it.
How many milliseconds to wait for the first byte of the input
from the device?
Since several other records may be waiting to access the device
during this time, <code>LockTimeout</code> should be larger than
<code>ReplyTimeout</code>.
</dd>
<dt><code>ReadTimeout = 100;</code></dt>
<dd>
Integer. Affects <code>in</code> commands.<br>
The device may send input in pieces (e.g. bytes).
When it stops sending, how many milliseconds to wait for more
input bytes before giving up?
If <code>InTerminator = ""</code>, a read timeout is not an error
but a valid input termination.
</dd>
<dt><code>PollPeriod = $ReplyTimeout;</code></dt>
<dd>
Integer. Affects first <code>in</code> command in
<code>I/O Intr</code> mode (see chapter
<a href="processing.html#iointr">Record Processing</a>).<br>
In that mode, some buses require periodic polling to get asynchronous
input if no other record executes an <code>in</code> command at
the moment.
How many milliseconds to wait after last poll or last received
input before polling again?
If not set the same value as for <code>ReplyTimeout</code> is
used.
</dd>
<dt><code>Terminator</code></dt>
<dd>
String. Affects <code>out</code> and <code>in</code> commands.<br>
Most devices send and expect terminators after each message,
e.g. <code>CR LF</code>.
The value of the <code>Terminator</code> variable is automatically
appended to any output.
It is also used to find the end of input.
It is removed before the input is passed to the <code>in</code>
command.
If no <code>Terminator</code> or <code>InTerminator</code> is defined,
the underlying driver may use its own terminator settings.
For example, <i>asynDriver</i> defines its own terminator settings.
</dd>
<dt><code>OutTerminator = $Terminator;</code></dt>
<dd>
String. Affects <code>out</code> commands.<br>
If a device has different terminators for input and output,
use this for the output terminator.
</dd>
<dt><code>InTerminator = $Terminator;</code></dt>
<dd>
String. Affects <code>in</code> commands.<br>
If a device has different terminators for input and output,
use this for the input terminator.
If no <code>Terminator</code> or <code>InTerminator</code> is defined,
the underlying driver may use its own terminator settings.
If <code>InTerminator = ""</code>, a read timeout is not an error
but a valid input termination.
</dd>
<dt><code>MaxInput = 0;</code></dt>
<dd>
Integer. Affects <code>in</code> commands.<br>
Some devices don't send terminators but always send a fixed message
size. How many bytes to read before terminating input even without
input terminator or read timeout?
The value <code>0</code> means "infinite".
</dd>
<dt><code>Separator = "";</code></dt>
<dd>
String. Affects <code>out</code> and <code>in</code> commands.<br>
When formatting or parsing array values in a format converter
(see <a href="formats.html">formats</a> and
<a href="waveform.html">waveform record</a>), what string
to write or to expect between values?
If the first character of the <code>Separator</code> is a
space, it matches any number of any whitespace characters in
an <code>in</code> command.
</dd>
<dt><code>ExtraInput = Error;</code></dt>
<dd>
<code>Error</code> or <code>Ignore</code>.
Affects <code>in</code> commands.<br>
Normally, when input parsing has completed, any bytes left in the
input are treated as parse error.
If extra input bytes should be ignored, set
<code>ExtraInput = Ignore;</code>
</dd>
</dl>
<a name="argvar"></a>
<h3>Protocol arguments</h3>
<p>
Sometimes, protocols differ only very little.
In that case it can be convenient to write only one protocol
and use <em>protocol arguments</em> for the difference.
For example a motor controller for the 3 axes X, Y, Z requires
three protocols to set a position.
</p>
<pre>
moveX { out "X GOTO %d"; }
moveY { out "Y GOTO %d"; }
moveZ { out "Z GOTO %d"; }
</pre>
<p>
It also needs three versions of any other protocol.
That means basically writing everything three times.
To make this easier, <em>protocol arguments</em> can be used:
</p>
<pre>
move { out "\$1 GOTO %d"; }
</pre>
<p>
Now, the protocol can be references in the <code>OUT</code> link
of three different records as <code>move(X)</code>,
<code>move(Y)</code> and <code>move(Z)</code>.
Up to 9 parameters, referenced as <code>$1</code> ... <code>$9</code>
can be specified in parentheses, separated by comma.
The variable <code>$0</code> is replaced by the name of the protocol.
</p>
<a name="usrvar"></a>
<h3>User variables</h3>
<p>
User defined variables are just a means to save some typing.
Once set, a user variable can be referenced later in the protocol.
</p>
<pre>
f = "FREQ"; # sets f to "FREQ" (including the quotes)
f1 = $f " %f"; # sets f1 to "FREQ %f"
getFrequency {
out $f "?"; # same as: out "FREQ?";
in $f1; # same as: in "FREQ %f";
}
setFrequency {
out $f1; # same as: out "FREQ %f";
}
</pre>
<a name="except"></a>
<h2>6. Exception Handlers</h2>
<p>
When an error happens, an exception handler may be called.
Exception handlers are a kind of sub-protocols in a protocol.
They consist of the same set of commands and are intended to
reset the device or to finish the protocol cleanly in case of
communication problems.
Like variables, exception handlers can be defined globally or
locally.
Globally defined handlers are used for all following protocols
unless overwritten by a local handler.
There is a fixed set of exception handler names starting with
<code>@</code>.
</p>
<dl>
<dt><code>@mismatch</code></dt>
<dd>
Called when input does not match in an <code>in</code> command.<br>
It means that the device has sent something else than what the
protocol expected.
If the handler starts with an <code>in</code> command, then this
command reparses the old input from the unsuccessful <code>in</code>.
Error messages from the unsuccessful <code>in</code> are suppressed.
Nevertheless, the record will end up in <code>INVALID/CALC</code>
state (see chapter <a href="processing.html#proc">Record Processing</a>).
</dd>
<dt><code>@writetimeout</code></dt>
<dd>
Called when a write timeout occurred in an <code>out</code> command.<br>
It means that output cannot be written to the device.
Note that <code>out</code> commands in the handler are
also likely to fail in this case.
</dd>
<dt><code>@replytimeout</code></dt>
<dd>
Called when a reply timeout occurred in an <code>in</code> command.<br>
It means that the device does not send any data.
Note that <code>in</code> commands in the handler are
also likely to fail in this case.
</dd>
<dt><code>@readtimeout</code></dt>
<dd>
Called when a read timeout occurred in an <code>in</code> command.<br>
It means that the device stopped sending data unexpectedly after
sending at least one byte.
</dd>
<dt><code>@init</code></dt>
<dd>
Not really an exception but formally specified in the same syntax.
This handler is called from <code>iocInit</code> during record
initialization.
It can be used to initialize an output record with a value read from
the device.
Also see chapter <a href="processing.html#init">Record Processing</a>.
</dd>
</dl>
<h3>Example:</h3>
<pre>
setPosition {
out "POS %f";
@init { out "POS?"; in "POS %f"; }
}
</pre>
<p>
After executing the exception handler, the protocol terminates.
If any exception occurs within an exception handler, no other handler
is called but the protocol terminates immediately.
An exception handler uses all <a href="#sysvar">system variable</a>
settings from the protocol in which the exception occurred.
</p>
<hr>
<p align="right"><a href="formats.html">Next: Format Converters</a></p>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

20
doc/recordinterface.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Record API</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Record API</h1>
<h2>Sorry, this documentation is still missing.</h2>
<hr>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

54
doc/recordtypes.html Normal file
View File

@ -0,0 +1,54 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Record Types</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Record Types</h1>
<h2>Supported Record Types</h2>
<p>
<em>StreamDevice</em> comes with support for all standard record types
in EPICS base which can have device support.
</p>
<p>
There is a separate page for each supported record type:<br>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p>
Each page describes which record fields are used in input and output
for different <a href="formats.html#types">format data types</a>
during <a href="processing.html#proc">normal record processing</a>
and <a href="processing.html#init">initialization</a>.
</p>
<p>
It is also possible to
<a href="recordinterface.html">write support for other recordtypes</a>.
</p>
<hr>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

101
doc/scalcout.html Normal file
View File

@ -0,0 +1,101 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: scalcout Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: scalcout Records</h1>
<p>
<b>Note:</b> The scalcout record is part of the <i>calc</i> module of
the <a target="ex"
href="http://www.aps.anl.gov/aod/bcda/synApps/index.php"
><em>synApps</em></a> package.
Device support for scalcout records is only available for <i>calc</i>
module release 2-4 or higher.
You also need the synApps modules <i>genSub</i> and <i>sscan</i> to
build <i>calc</i>.
</p>
<p>
Up to release 2-6 (synApps release 5.1), the scalcout record needs a fix.
In sCalcout.c at the end of <code>init_record</code> add
before the final <code>return(0)</code>:
</p>
<pre class="box">
if(pscalcoutDSET->init_record ) {
return (*pscalcoutDSET->init_record)(pcalc);
}
</pre>
<h2>Normal Operation</h2>
<p>
Different record fields are used for output and input. The variable
<code><i>x</i></code> stands for the written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=OVAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
Note that the record calculates <code>OVAL</code> from <code>CALC</code>
or <code>OCAL</code> depending on <code>DOPT</code>.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=int(OVAL)</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=int(OVAL)</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=OSV</code><br>
<u>Input:</u> <code>SVAL=<i>x</i></code><br>
</dd>
</dl>
<p>
For scalcout records, it is probably more useful to access fields
<code>A</code> to <code>L</code> and <code>AA</code> to <code>LL</code>
directly (e.g. <code>"%(A)f"</code> or <code>"%(BB)s"</code>).
However, even if <code>OVAL</code> is not used, it is calculated by the
record. Thus, <code>CALC</code> must always contain a valid expression
(e.g. <code>"0"</code>).
</p>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

290
doc/setup.html Normal file
View File

@ -0,0 +1,290 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Setup</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Setup</h1>
<a name="pre"></a>
<h2>1. Prerequisites</h2>
<p>
<em>StreamDevice</em> requires either
<a href="http://www.aps.anl.gov/epics/base/R3-14/index.php"
target="ex">EPICS base R3.14.6 or higher</a> or
<a href="http://www.aps.anl.gov/epics/base/R3-13.php"
target="ex">EPICS base R3.13.7 or higher</a>.
How to use <em>StreamDevice</em> on EPICS R3.13 is described on a
<a href="epics3_13.html">separate page</a>.
Because <em>StreamDevice</em> comes with an interface to
<a href="http://www.aps.anl.gov/epics/modules/soft/asyn/"
target="ex"><em>asynDriver</em> version R4-3 or higher</a> as the
underlying driver layer,
you should have <em>asynDriver</em> installed first.
</p>
<p>
<em>StreamDevice</em> has support for the
<a href="scalcout.html"><em>scalcout</em></a> record from the
<em>calc</em> module of <a target="ex"
href="http://www.aps.anl.gov/aod/bcda/synApps/index.php"
><em>synApps</em></a>.
Up to <em>calc</em> release R2-6 (<em>synApps</em> release R5_1),
the <em>scalcout</em> record needs a fix.
(See separate <a href="scalcout.html"><em>scalcout</em> page</a>.)
</p>
<p>
Up to release R3.14.8.2, a fix in EPICS base is required to build
<em>StreamDevice</em> on Windows (not cygwin).
In <kbd>src/iocsh/iocsh.h</kbd>, add the following line
and rebuild base.
</p>
<pre>
epicsShareFunc int epicsShareAPI iocshCmd(const char *command);
</pre>
<p>
Make sure that the <em>asyn</em> library and the <em>calc</em> module of
<em>synApps</em> can be found, e.g. by
adding <code>ASYN</code>
and (if installed) <code>CALC</code> or <code>SYNAPPS</code>
to your <kbd>&lt;top&gt;/configure/RELEASE</kbd> file:
<pre>
ASYN=/home/epics/asyn/4-5
CALC=/home/epics/synApps/calc/2-7
</pre>
<p>
For details on <kbd>&lt;top&gt;</kbd> directories and RELEASE files,
please refer to the
<a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/AppDevGuide.pdf"
target="ex"><em>IOC Application Developer's Guide</em></a> chapter 4:
EPICS Build Facility.
</p>
<a name="lib"></a>
<h2>2. Build the <em>StreamDevice</em> Library</h2>
<p>
Unpack the
<a href="http://epics.web.psi.ch/software/streamdevice/StreamDevice-2.tgz"
><em>StreamDevice</em> package</a> in a <kbd>&lt;top&gt;</kbd> directory
of your application build area.
(You might probably have done this already.)
Go to the newly created <em>StreamDevice</em> directory
and run <kbd>make</kbd> (or <kbd>gmake</kbd>).
This will create and install the <em>stream</em> library and the
<kbd>stream.dbd</kbd> file.
</p>
<a name="app"></a>
<h2>3. Build an Application</h2>
<p>
To use <em>StreamDevice</em>, your application must be built with the
<em>asyn</em> and <em>stream</em> libraries and must load
<kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd>.
</p>
<p>
Include the following lines in your application Makefile:
</p>
<pre>
PROD_LIBS += stream
PROD_LIBS += asyn
</pre>
<p>
Include the following lines in your xxxAppInclude.dbd file to use
<em>stream</em> and <em>asyn</em> with serial lines and IP sockets:
</p>
<pre>
include "base.dbd"
include "stream.dbd"
include "asyn.dbd"
registrar(drvAsynIPPortRegisterCommands)
registrar(drvAsynSerialPortRegisterCommands)
</pre>
<p>
You can find an example application in the <kbd>streamApp</kbd>
subdirectory.
</p>
<a name="sta"></a>
<h2>4. The Startup Script</h2>
<p>
<em>StreamDevice</em> is based on <a
href="protocol.html"><em>protocol files</em></a>.
To tell <em>StreamDevice</em> where to search for protocol files,
set the environment variable <code>STREAM_PROTOCOL_PATH</code> to a
list of directories to search.
On Unix and vxWorks systems, directories are separated by <code>:</code>,
on Windows systems by <code>;</code>.
The default value is <code>STREAM_PROTOCOL_PATH=.</code>,
i.e. the current directory.
</p>
<p>
Also configure the buses (in <em>asynDriver</em> terms: ports) you want
to use with <em>StreamDevice</em>.
You can give the buses any name you want, like <kbd>COM1</kbd> or
<kbd>socket</kbd>, but I recommend to use names related to the
connected device.
</p>
<h3>Example:</h3>
<p>
A power supply with serial communication (9600 baud, 8N1) is connected to
<kbd>/dev/ttyS1</kbd>.
The name of the power supply is <tt>PS1</tt>.
Protocol files are either in the current working directory or in the
<kbd>../protocols</kbd> directory.
</p>
<p>
Then the startup script must contain lines like this:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")
drvAsynSerialPortConfigure ("PS1","/dev/ttyS1")
asynSetOption ("PS1", 0, "baud", "9600")
asynSetOption ("PS1", 0, "bits", "8")
asynSetOption ("PS1", 0, "parity", "none")
asynSetOption ("PS1", 0, "stop", "1")
asynSetOption ("PS1", 0, "clocal", "Y")
asynSetOption ("PS1", 0, "crtscts", "N")
</pre>
<p>If the power supply was connected via telnet-style TCP/IP
at address 192.168.164.10 on port 23,
the startupscript would contain:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")
drvAsynIPPortConfigure ("PS1", "192.168.164.10:23")
</pre>
<p>
With a VXI11 (GPIB via TCP/IP) connection, e.g. a
HP E2050A on IP address 192.168.164.10, it would look like this:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")
vxi11Configure ("PS1","192.168.164.10",1,1000,"hpib")
</pre>
<a name="pro"></a>
<h2>5. The Protocol File</h2>
<p>
For each different type of hardware, create a protocol file
which defines protocols for all needed functions of the device.
The file name is arbitrary, but I recommend that it contains
the device type.
It must not contain spaces and should be short.
During <code>iocInit</code>, <em>streamDevice</em> loads and parses
the required protocol files.
If the files contain errors, they are printed on the IOC shell.
Put the protocol file in one of the directories listed in
<code>STREAM_PROTOCOL_PATH</code>.
</p>
<h3>Example:</h3>
<p>
<tt>PS1</tt> is an <em>ExamplePS</em> power supply.
It communicates via ASCII strings which are terminated by
&lt;carriage&nbsp;return&gt; &lt;line&nbsp;feed&gt; (ASCII codes 13, 10).
The output current can be set by sending a string like
<code>"CURRENT 5.13"</code>.
When asked with the string <code>"CURRENT?"</code>, the device returns
the last set value in a string like <code>"CURRENT 5.13 A"</code>.
</p>
<p>
Normally, an analog output record should write its value to the device.
But during startup, the record should be initialized from the the device.
The protocol file <kbd>ExamplePS.proto</kbd> defines the protocol
<code>setCurrent</code>.
</p>
<pre>
Terminator = CR LF;
setCurrent {
out "CURRENT %.2f";
@init {
out "CURRENT?";
in "CURRENT %f A";
}
}
</pre>
<a name="reload"></a>
<h3>Reloading the Protocol File</h3>
<p>
During development, the protocol files might change frequently.
To prevent restarting the IOC all the time, it is possible to reload
the protocol file of one or all records with the shell function
<code>streamReload("<var>record</var>")</code>.
If <code>"<var>record</var>"</code> is not given, all records using
<em>StreamDevice</em> reload their protocols.
Furthermore, the <code>streamReloadSub</code> function can be used
with a subroutine record to reload all protocols.
</p>
<p>
Reloading the protocol file aborts currently running protocols.
This might set <code>SEVR=INVALID</code> and <code>STAT=UDF</code>.
If a record can't reload its protocol file (e.g. because of a syntax
error), it stays <code>INVALID</code>/<code>UDF</code> until a valid
protocol is loaded.
</p>
<p>
See the <a href="protocol.html">next chapter</a> for protocol files in depth.
</p>
<a name="rec"></a>
<h2>6. Configure the Records</h2>
<p>
To make a record use <em>StreamDevice</em>, set its <code>DTYP</code> field to
<code>"stream"</code>.
The <code>INP</code> or <code>OUT</code> link has the form
<code>"@<var>file&nbsp;protocol&nbsp;bus</var>&nbsp;[<var>address</var>&nbsp;[<var>parameters</var>]]"</code>.
</p>
<p>
Here, <code><var>file</var></code> is the name of the protocol file and
<code><var>protocol</var></code> is the name of a protocol defined in this file.
If the protocol requires <a href="protocol.html#argvar">arguments</a>,
specify them enclosed in parentheses:
<code><var>protocol</var>(<var>arg1,arg2,...</var>)</code>.
</p>
<p>
The communication channel is specified with <code><var>bus</var></code> and
<code><var>addr</var></code>.
If the bus does not have addresses, <code><var>addr</var></code> is dispensable.
Optional <code><var>parameters</var></code> are passed to the bus driver.
</p>
<h3>Example:</h3>
<p>
Create an output record to set the current of <tt>PS1</tt>.
Use protocol <em>setCurrent</em> from file <em>ExamplePS.proto</em>.
The bus is called <em>PS1</em> like the device.
</p>
<pre>
record (ao, "PS1:I-set")
{
field (DESC, "Set current of PS1")
field (DTYP, "stream")
field (OUT, "@ExamplePS.proto setCurrent PS1")
field (EGU, "A")
field (PREC, "2")
field (DRVL, "0")
field (DRVH, "60")
field (LOPR, "0")
field (HOPR, "60")
}
</pre>
<hr>
<p align="right"><a href="protocol.html">Next: Protocol Files</a></p>
<p><small>Dirk Zimoch, 2007</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

BIN
doc/sls_icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
doc/space.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

79
doc/stream.css Normal file
View File

@ -0,0 +1,79 @@
a:link {color: #0000D0; text-decoration:none;}
a:visited {color: #0000D0; text-decoration:none;}
a:hover {color: #FF0000; text-decoration:none;}
body {
margin-right:20px;
font-family:sans-serif;
font-size:14px;
background-color:#ffffff;
}
pre {
background-color:#f4f4f4;
padding:1ex;
border:1px solid #000000;
white-space:pre;
margin:2ex;
}
dt {
margin-top:0.5ex;
}
h1 {
font-size:225%;
margin-top:0;
font-style:italic;
font-family:serif;
}
h2 {
font-size:150%;
margin-bottom:0.5ex;
}
h3 {
font-size:100%;
margin-bottom:0.25ex;
}
p {
margin-top:0.75ex;
margin-bottom:0.75ex;
}
small {
font-size:75%;
}
code {
color: #008000;
}
.indent {
text-indent:-4ex;
margin-left:4ex;
margin-top:0.5ex;
text-align:left;
}
/*
a[target=ex] {
background-image:url(ex.png);
background-repeat:no-repeat;
background-position:right center;
padding-right: 12px;
}
a[target=ex]:hover {
background-image:url(exr.png);
}
*/
@media print {
a:link {color: black; text-decoration:none;}
a:visited {color: black; text-decoration:none;}
a:hover {color: black; text-decoration:none;}
code {color: black; }
}

92
doc/stream.html Normal file
View File

@ -0,0 +1,92 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>EPICS <em>StreamDevice</em> Documentation</h1>
<h2>What is <em>StreamDevice</em>?</h2>
<p>
<em>StreamDevice</em> is a generic
<a href="http://www.aps.anl.gov/epics" target="ex">EPICS</a>
device support for devices with a "byte stream" based
communication interface.
That means devices that can be controlled by sending and
receiving strings (in the broadest sense, including non-printable
characters and even null-bytes).
Examples for this type of communication interface are
serial line (RS-232, RS-485, ...),
IEEE-488 (also known as GPIB or HP-IB), and TCP/IP.
<em>StreamDevice</em> comes with an interface to<a target="ex"
href="http://www.aps.anl.gov/epics/modules/soft/asyn/">
<em>asynDriver</em></a>
but can be extended to
<a href="businterface.html">support other bus drivers</a>.
</p>
<p>
If the device can be controlled with strings like
"<code>RF:FREQ 499.655 MHZ</code>", <em>StreamDevice</em> can be used.
How the strings exactly look like is defined in <em>protocols</em>.
Formatting and interpretation of values is done with
<a href="formats.html"><em>format converters</em></a> similar to those
known from the C functions <em>printf()</em> and <em>scanf()</em>.
To support other formats, it is possible to
<a href="formatconverter.html">write your own converters</a>.
</p>
<p>
Each record with <em>StreamDevice</em> support runs one <em>protocol</em>
to read or write its value.
All <em>protocols</em> are defined in
<a href="protocol.html"><em>protocol files</em></a> in plain ASCII text.
No compiling is necessary to change a protocol or to support new devices.
<em>Protocols</em> can be as simple as just one output string or can
consist of many strings sent to and read from the device.
However, a protocol is linear.
That means it runs from start to end each time the record is
<a href="processing.html">processed</a>.
It does not provide loops or branches.
</p>
<p>
<em>StreamDevice</em> supports all
<a href="recordtypes.html">standard records</a> of EPICS base
which can have device support.
It is also possible to
<a href="recordinterface.html">write support for new record types</a>.
</p>
<h2>What is <em>StreamDevice</em> not?</h2>
<p>
It is not a programming language for a high-level application.
It is, for example, not possible to write a complete scanning program
in a <em>protocol</em>.
Use other tools for that and use <em>StreamDevice</em> only for the
primitive commands.
</p>
<p>
It is not a block oriented device support.
It is not possible to send or receive huge blocks of data that contain
many process variables distributed over many records.
</p>
<h2>Recommended Readings</h2>
<p>
<a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/AppDevGuide.pdf"
target="ex">IOC Application Developer's Guide (PDF)</a>
</p>
<p>
<a href="http://www.aps.anl.gov/asd/controls/epics/EpicsDocumentation/AppDevManuals/RecordRef/Recordref-1.html"
target="ex">EPICS Record Reference Manual</a>
</p>
<hr>
<p align="right"><a href="setup.html">Next: Setup</a></p>
<p><small>Dirk Zimoch, 2006</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

5
doc/stream.js Normal file
View File

@ -0,0 +1,5 @@
if (parent.head) {
parent.head.document.getElementById('subtitle').innerHTML=document.title;
parent.document.title=document.title;
document.getElementsByTagName('h1')[0].style.display="none";
}

67
doc/stringin.html Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: stringin Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: stringin Records</h1>
<h2>Normal Operation</h2>
<p>
The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringout.html">stringout</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

67
doc/stringout.html Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: stringout Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: stringout Records</h1>
<h2>Normal Operation</h2>
<p>
The variable <code><i>x</i></code> stands for the
written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
Not allowed.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code>
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="waveform.html">waveform</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

297
doc/tipsandtricks.html Normal file
View File

@ -0,0 +1,297 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: Tips and Tricks</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: Tips and Tricks</h1>
<a name="argvar"></a>
<h2>I have many almost identical protocols</h2>
<p>
You can give <a href="protocol.html#argvar">arguments</a> to a protocol.
In the <code>INP</code> or <code>OUT</code> link, write:
</p>
<p>
<code>
field (OUT, "@protocolfile protocol(arg1,arg2,arg3) bus")
</code>
</p>
<p>
In the protocol, reference arguments as <code>$1 $2 $3</code> or inside strings
as <code>"\$1 \$2 \$3"</code>.
</p>
<p>
<code>
moveaxis {out "move\$1 %.6f";}<br>
field (OUT, "@motor.proto moveaxis(X) motor1")
</code>
</p>
<p>
<code>
readpressure {out 0x02 0x00 $1; in 0x82 0x00 $1 "%2r";}<br>
field (INP, "@vacuumgauge.proto readpressure(0x84) gauge3")
</code>
</p>
<a name="iointr"></a>
<h2>I have a device that sends unsolicited data</h2>
<p>
Use <a href="processing.html#iointr"><code>I/O Intr</code> processing</a>.
The record receives any input and processes only when the input matches.
</p>
<p>
<code>
read {in "new value = %f";}
</code>
</p>
<p>
<code>
record (ai, "$(RECORD)") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (INP, "@(DEVICETYPE).proto read $(BUS)")<br>
&nbsp;&nbsp;field (SCAN, "I/O Intr")<br>
}
</code>
</p>
<a name="multiline"></a>
<h2>I have a device that sends multi-line messages</h2>
<pre>
Here is the value:
3.1415
</pre>
<p>
Use as many <code>in</code> commands as you get input lines.
</p>
<p>
<code>
read_value {in "Here is the value:"; in "%f";}
</code>
</p>
<a name="writemany"></a>
<h2>I need to write more than one value in one message</h2>
<p>
There is more than one solution to this problem.
Different approaches have different requirements.
</p>
<h3>A) All values have the same type and are separated by the same string</h3>
<p>
Use array records (e.g. <a href="waveform.html">waveform</a>,
<a href="aao.html">aao</a>).
</p>
<p>
<code>
array_out {separator=", "; out "an array: (%.2f)";}
</code>
</p>
<p>
The format <code>%.2f</code> is repeated for each element of the array.
All elements are separated by <code>", "</code>.<br>
Output will look like this:
<pre>
an array: (3.14, 17.30, -12.34)
</pre>
</p>
<h3>B) We have up to 12 numeric values</h3>
<p>
Use a <a href="calcout.html">calcout</a> record and
<a href="formats.html#types">field references</a> in the format.
</p>
<p>
<code>
write_ABC {out "A=%(A).2f B=%(B).6f C=%(C).0f";}
</code>
</p>
<p>
You must specify a valid expression in the <code>CALC</code> field
even if you don't use it.
</p>
<p>
<code>
record (calcout, "$(RECORD)") {<br>
&nbsp;&nbsp;field (INPA, "$(A_RECORD)")<br>
&nbsp;&nbsp;field (INPB, "$(B_RECORD)")<br>
&nbsp;&nbsp;field (INPC, "$(C_RECORD)")<br>
&nbsp;&nbsp;field (CALC, "0")<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (OUT, "@(DEVICETYPE).proto write_ABC $(BUS)")<br>
}
</code>
</p>
<h3>C) Values are in other records on the same IOC</h3>
<p>
Use <a href="formats.html#types">record references</a> in the format.
</p>
<p>
<code>
acquire {out 'ACQUIRE "%(\$1:directory.VAL)s/%s",%(\$1:time.VAL).3f;';}
</code>
</p>
<p>
You must specify the full <code>record.FIELD</code> name,
even for <code>VAL</code> fields.
To avoid record names in protocol files use
<a href="protocol.html#argvar">protocol arguments</a>.
In the link, specify the record name or just the basename of the
other records (device name) in parentheses.
</p>
<p>
<code>
record (stringout, "$(DEVICE):getimage") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (OUT, "@(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")<br>
}
</code>
</p>
<a name="readmany"></a>
<h2>I need to read more than one value from one message</h2>
<p>
Again, there is more than one solution to this problem.
</p>
<h3>A) All values have the same type and are separated by the same string</h3>
<p>
Use array records (e.g. <a href="waveform.html">waveform</a>,
<a href="aai.html">aai</a>).<br>
</p>
<p>
<code>
array_in {separator=","; in "array = (%f)";}
</code>
</p>
<p>
The format <code>%f</code> is repeated for each element of the array.
A <code>","</code> is expected beween element.<br>
Input may look like this:
</p>
<pre>
array = (3.14, 17.30, -12.34)
</pre>
<h3>B) The message and the values in it can be filtered easily</h3>
<p>
Use <a href="processing.html#iointr"><code>I/O Intr</code> processing</a>
and <a href="formats.html#syntax">value skipping</a> (<code>%*</code>)<br>
</p>
<p>
<code>
read_A {out "GET A,B"; in "A=%f, B=%*f";}<br>
read_B {in "A=%*f, B=%f";}
</code>
</p>
<p>
<code>
record (ai, "$(DEVICE):A") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (INP, "@(DEVICETYPE).proto read_A $(BUS)")<br>
&nbsp;&nbsp;field (SCAN, "1 second")<br>
}<br>
record (ai, "$(DEVICE):B") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (INP, "@(DEVICETYPE).proto read_B $(BUS)")<br>
&nbsp;&nbsp;field (SCAN, "I/O Intr")<br>
}
</code>
</p>
<p>
Record A actively requests values every second.
The reply contains values A and B.
Record A filters only value A from the input and ignores value B
by using the <code>*</code> flag.
Nevertheless, a complete syntax check is performed: B must be a
valid floating point number.
Record B is <code>I/O Intr</code> and gets (a copy of) any input, including
input that was directed to record A.
If it finds a matching string it ignores value A, reads value B and
then processes.
Any non-matching input is ignored by record B.
</p>
<h3>C) Values should be stored in other records on the same IOC</h3>
<p>
Use <a href="formats.html#types">record references</a> in the format.
To avoid record names in protocol files, use
<a href="protocol.html#argvar">protocol arguments</a>.
</p>
<p>
<code>
read_AB {out "GET A,B"; in "A=%f, B=%(\$1.VAL)f";}
</code>
</p>
<p>
<code>
record (ai, "$(DEVICE):A") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (INP, "@(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")<br>
&nbsp;&nbsp;field (SCAN, "1 second")<br>
}<br>
record (ai, "$(DEVICE):B") {<br>
}
</code>
</p>
<p>
Whenever record A reads input, it stores the first value in its own VAL field
as usual and the second in the VAL field of record B.
Because the VAL field of record B has the PP attribute, this automatically
processes record B.
</p>
<a name="mixed"></a>
<h2>I have a device that sends mixed data types: numbers and strings</h2>
<p>
Use a <code>@mismatch</code>
<a href="protocol.html#except">exception handler</a> and
<a href="formats.html#types">record references</a> in the format.
To avoid record names in protocol files, use
<a href="protocol.html#argvar">protocol arguments</a>.
</p>
<h3>Example</h3>
<p>
When asked "<code>CURRENT?</code>", the device send something like
"<code>CURRENT&nbsp;3.24&nbsp;A</code>" or a message like
"<code>device&nbsp;switched&nbsp;off</code>".
</p>
<p>
<code>
read_current {out "CURRENT?"; in "CURRENT %f A"; @mismatch {in "%(\1.VAL)39c";}}
</code>
</p>
<p>
<code>
record (ai, "$(DEVICE):readcurrent") {<br>
&nbsp;&nbsp;field (DTYP, "stream")<br>
&nbsp;&nbsp;field (INP, "@(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")<br>
}<br>
record (stringin, "$(DEVICE):message") {<br>
}
</code>
</p>
<p>
After <a href="processing.html#proc">processing</a> the readcurrent record, you can see from
SEVR/STAT if the read was successful or not.
With some more records, you can clean the message record if SEVR is not INVALID.
</p>
<code>
record (calcout, "$(DEVICE):clean_1") {<br>
&nbsp;&nbsp;field (INPA, "$(DEVICE):readcurrent.SEVR CP")<br>
&nbsp;&nbsp;field (CALC, "A!=2")<br>
&nbsp;&nbsp;field (OOPT, "When Non-zero")<br>
&nbsp;&nbsp;field (OUT, "$(DEVICE):clean_2.PROC")<br>
}<br>
record (stringout, "$(DEVICE):clean_2") {<br>
&nbsp;&nbsp;field (VAL, "OK")<br>
&nbsp;&nbsp;field (OUT, "$(DEVICE):message PP")<br>
}<br>
</code>
<hr>
<p><small>Dirk Zimoch, 2007</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>

126
doc/waveform.html Normal file
View File

@ -0,0 +1,126 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>StreamDevice: waveform Records</title>
<link rel="shortcut icon" href="sls_icon.ico">
<link rel="stylesheet" type="text/css" href="stream.css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="author" content="Dirk Zimoch">
</head>
<body>
<h1>StreamDevice: waveform Records</h1>
<h2>Normal Operation</h2>
<p>
With waveform records, the format converter is applied to
each element. Between the elements, a separator is printed
or expected as specified by the <code>Separator</code>
<a href="protocol.html#sysvar">variable</a> in the
protocol.
When parsing input, a space as the first character of the
<code>Separator</code> matches any number of any whitespace
characters.
</p>
<p>
During input, a maximum of <code>NELM</code> elements is
read and <code>NORD</code> is updated accordingly.
Parsing of elements stops when the separator does not match,
conversion fails, or the end of the input is reached.
A minimum of one element must be available.
</p>
<p>
During output, the first <code>NORD</code> elements are
written.
</p>
<p>
The format data type must be convertible to or from the type
specified in the <code>FTVL</code> field.
The variable <code><i>x[i]</i></code> stands for one element of
the written or read value.
</p>
<dl>
<dt>DOUBLE format (e.g. <code>%f</code>):</dt>
<dd>
<u>Output:</u><code><i>x[i]</i>=double(VAL[i])</code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i]</i>)</code><br>
<code>FTVL</code> must be <code>"FLOAT"</code> or <code>"DOUBLE"</code>
</dd>
<dt>LONG or ENUM format (e.g. <code>%i</code> or <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
<code>FTVL</code> can be
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
Signed values are sign-extended to long, unsigned values are
zero-extended to long before converting them.<br>
<u>Input:</u> <code>VAL[i]=FTVL(<i>x[i])</i></code><br>
<code>FTVL</code> can be <code>"DOUBLE"</code>, <code>"FLOAT"</code>,
<code>"LONG"</code>, <code>"ULONG"</code>, <code>"SHORT"</code>,
<code>"USHORT"</code>, <code>"CHAR"</code>, <code>"UCHAR"</code>,
or <code>"ENUM"</code> (which is treated as <code>"USHORT"</code>).<br>
The value is truncated to the least significant bytes if
<code>FTVL</code> has a smaller data size than <code>long</code>.
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<dl>
<dt>If <code>FTVL=="STRING"</code>:</dt>
<dd>
<u>Output:</u> <code><i>x[i]</i>=VAL[i]</code><br>
<u>Input:</u> <code>VAL[i]=<i>x[i]</i></code><br>
Note that this is an array of strings, not an array of characters.
</dd>
<dt>If <code>FTVL=="CHAR"</code> or <code>FTVL="UCHAR"</code>:</dt>
<dd>
In this case, the complete waveform is treated as a large
single string of size <code>NORD</code>.
No separators are printed or expected.<br>
<u>Output:</u> <code><i>x</i>=range(VAL,0,NORD)</code><br>
The first <code>NORD</code> characters are printed,
which might be less than <code>NELM</code>.<br>
<u>Input:</u> <code>VAL=<i>x</i>, NORD=length(<i>x</i>)</code><br>
A maximum of <code>NELM-1</code> characters can be read.
<code>NORD</code> is updated to the index of the first of the
trailing zeros.
Usually, this is the same as the string length.
</dd>
</dl>
Other values of <code>FTVL</code> are not allowed for this format.
</dd>
</dl>
<h2>Initialization</h2>
<p>
During <a href="processing.html#init">initialization</a>, the <code>@init</code> handler is executed, if
present. All format converters work like in normal operation.
</p>
<hr>
<p>
<a href="aai.html">aai</a>
<a href="aao.html">aao</a>
<a href="ai.html">ai</a>
<a href="ao.html">ao</a>
<a href="bi.html">bi</a>
<a href="bo.html">bo</a>
<a href="mbbi.html">mbbi</a>
<a href="mbbo.html">mbbo</a>
<a href="mbbiDirect.html">mbbiDirect</a>
<a href="mbboDirect.html">mbboDirect</a>
<a href="longin.html">longin</a>
<a href="longout.html">longout</a>
<a href="stringin.html">stringin</a>
<a href="stringout.html">stringout</a>
<a href="calcout.html">calcout</a>
<a href="scalcout.html">scalcout</a>
</p>
<p><small>Dirk Zimoch, 2005</small></p>
<script src="stream.js" type="text/javascript"></script>
</body>
</html>