version 2.2
BIN
doc/EPICS.gif
Normal file
After Width: | Height: | Size: 453 B |
BIN
doc/PSI.gif
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
doc/SLS.gif
Normal file
After Width: | Height: | Size: 2.2 KiB |
128
doc/aai.html
Normal 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
@ -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
@ -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
@ -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
After Width: | Height: | Size: 868 B |
77
doc/bi.html
Normal 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>&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
@ -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>&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
@ -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 <StreamBusInterface.h>
|
||||
|
||||
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* client,
|
||||
const char* busname, int addr,
|
||||
const char* 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 long 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 void* output,
|
||||
size_t size, unsigned long writeTimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
|
||||
unsigned long readTimeout_ms,
|
||||
long expectedLength, bool 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 long mask,
|
||||
unsigned long replytimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool <a href="#connect">connectRequest</a>(unsigned long 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 status);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#write">writeCallback</a>(StreamIoStatus status);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
long <a href="#read">readCallback</a>(StreamIoStatus status,
|
||||
const void* input = NULL,
|
||||
long size = 0);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#event">eventCallback</a>(StreamIoStatus status);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#connect">connectCallback</a>(StreamIoStatus status);
|
||||
</code></div>
|
||||
|
||||
<h3>Other provided methods, attibutes, and types</h3>
|
||||
|
||||
<div class="indent"><code>
|
||||
<a href="#create">StreamBusInterface</a>(Client* 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 char* <a href="#write">getOutTerminator</a>(size_t& length);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* <a href="#read">getInTerminator</a>(size_t& length);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
enum 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* client,
|
||||
const char* busname, int addr,
|
||||
const char* param);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
StreamBusInterface(Client* 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 long connecttimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool disconnect();
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void connectCallback(IoStatus 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 long lockTimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void lockCallback(IoStatus 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 void* output,
|
||||
size_t size, unsigned long writeTimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void writeCallback(IoStatus status);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* getOutTerminator(size_t& 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 long replyTimeout_ms,
|
||||
unsigned long readTimeout_ms,
|
||||
long expectedLength, bool async);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
long readCallback(IoStatus status,
|
||||
const void* input = NULL,
|
||||
long size = 0);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* getInTerminator(size_t& 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>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
@ -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
@ -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><top></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><top></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 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><top></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><top></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><top></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
After Width: | Height: | Size: 187 B |
BIN
doc/exr.png
Normal file
After Width: | Height: | Size: 187 B |
20
doc/formatconverter.html
Normal 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
@ -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 "%(EGU)s";</code> outputs the <code>EGU</code>
|
||||
field formatted as a string.
|
||||
Use <code>in "%(<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>%<<em>checksum</em>></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%<xor>"</code> the checksum is calculated
|
||||
from <code>abcdefg</code>,
|
||||
but in <code>"abcdefg%2.1<xor>"</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 "123456789%<sum>"</code> writes <code>dd</code>
|
||||
but <code>out "123456789%<Sum>"</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>%<SUM></code> or <code>%<SUM8></code></dt>
|
||||
<dd>One byte. The sum of all characters modulo 2<sup>8</sup>.</dd>
|
||||
<dt><code>%<SUM16></code></dt>
|
||||
<dd>Two bytes. The sum of all characters modulo 2<sup>16</sup>.</dd>
|
||||
<dt><code>%<SUM32></code></dt>
|
||||
<dd>Four bytes. The sum of all characters modulo 2<sup>32</sup>.</dd>
|
||||
<dt><code>%<NEGSUM></code> or <code>%<NSUM></code> or <code>%<-SUM></code></dt>
|
||||
<dd>One byte. The negative of the sum of all characters modulo 2<sup>8</sup>.</dd>
|
||||
<dt><code>%<NOTSUM></code> or <code>%<~SUM></code></dt>
|
||||
<dd>One byte. The bitwise inverse of the sum of all characters modulo 2<sup>8</sup>.</dd>
|
||||
<dt><code>%<XOR></code></dt>
|
||||
<dd>One byte. All characters xor'ed.</dd>
|
||||
<dt><code>%<CRC8></code></dt>
|
||||
<dd>One byte. An often used 8 bit CRC checksum
|
||||
(poly=0x07, init=0x00, xorout=0x00).</dd>
|
||||
<dt><code>%<CCITT8></code></dt>
|
||||
<dd>One byte. The CCITT standard 8 bit CRC checksum
|
||||
(poly=0x31, init=0x00, xorout=0x00).</dd>
|
||||
<dt><code>%<CRC16></code></dt>
|
||||
<dd>Two bytes. An often used 16 bit CRC checksum
|
||||
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
|
||||
<dt><code>%<CRC16R></code></dt>
|
||||
<dd>Two bytes. An often used reflected 16 bit CRC checksum
|
||||
(poly=0x8005, init=0x0000, xorout=0x0000).</dd>
|
||||
<dt><code>%<CCITT16></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>%<CCITT16A></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>%<CRC32></code></dt>
|
||||
<dd>Four bytes. The standard 32 bit CRC checksum.
|
||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
|
||||
<dt><code>%<CRC32R></code></dt>
|
||||
<dd>Four bytes. The standard reflected 32 bit CRC checksum.
|
||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0xFFFFFFFF).</dd>
|
||||
<dt><code>%<JAMCRC></code></dt>
|
||||
<dd>Four bytes. Another reflected 32 bit CRC checksum.
|
||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0x00000000).</dd>
|
||||
<dt><code>%<ADLER32></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>%<HEXSUM8></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
@ -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
@ -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
@ -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
@ -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
@ -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&MASK</code><br>
|
||||
<u>Input:</u> <code>RVAL=<i>x</i>&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
@ -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&MASK</code><br>
|
||||
<u>Input:</u> <code>RVAL=<i>x</i>&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
@ -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&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>&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
@ -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&MASK</code><br>
|
||||
<u>Input:</u> <code>RBV=<i>x</i>&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
@ -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="[«]";
|
||||
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="[»]";
|
||||
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 & 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">%<<em>checksum</em>></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 & 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 & 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
@ -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
After Width: | Height: | Size: 1.2 KiB |
244
doc/processing.html
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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><top>/configure/RELEASE</kbd> file:
|
||||
<pre>
|
||||
ASYN=/home/epics/asyn/4-5
|
||||
CALC=/home/epics/synApps/calc/2-7
|
||||
</pre>
|
||||
<p>
|
||||
For details on <kbd><top></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><top></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
|
||||
<carriage return> <line feed> (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 protocol bus</var> [<var>address</var> [<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
After Width: | Height: | Size: 318 B |
BIN
doc/space.gif
Normal file
After Width: | Height: | Size: 807 B |
79
doc/stream.css
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read $(BUS)")<br>
|
||||
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>
|
||||
field (INPA, "$(A_RECORD)")<br>
|
||||
field (INPB, "$(B_RECORD)")<br>
|
||||
field (INPC, "$(C_RECORD)")<br>
|
||||
field (CALC, "0")<br>
|
||||
field (DTYP, "stream")<br>
|
||||
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>
|
||||
field (DTYP, "stream")<br>
|
||||
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>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read_A $(BUS)")<br>
|
||||
field (SCAN, "1 second")<br>
|
||||
}<br>
|
||||
record (ai, "$(DEVICE):B") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read_B $(BUS)")<br>
|
||||
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>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")<br>
|
||||
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 3.24 A</code>" or a message like
|
||||
"<code>device switched 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>
|
||||
field (DTYP, "stream")<br>
|
||||
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>
|
||||
field (INPA, "$(DEVICE):readcurrent.SEVR CP")<br>
|
||||
field (CALC, "A!=2")<br>
|
||||
field (OOPT, "When Non-zero")<br>
|
||||
field (OUT, "$(DEVICE):clean_2.PROC")<br>
|
||||
}<br>
|
||||
record (stringout, "$(DEVICE):clean_2") {<br>
|
||||
field (VAL, "OK")<br>
|
||||
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
@ -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>
|