diff --git a/doc/EPICS.gif b/doc/EPICS.gif deleted file mode 100644 index 1d4a4b7..0000000 Binary files a/doc/EPICS.gif and /dev/null differ diff --git a/doc/SLS.gif b/doc/SLS.gif deleted file mode 100644 index 08a8734..0000000 Binary files a/doc/SLS.gif and /dev/null differ diff --git a/doc/aai.html b/doc/aai.html index f50e3d9..8c1008f 100644 --- a/doc/aai.html +++ b/doc/aai.html @@ -3,12 +3,13 @@
Note: aai record support is disabled per default. @@ -123,6 +124,5 @@ the written or read value. scalcout
Dirk Zimoch, 2006
- diff --git a/doc/aao.html b/doc/aao.html index 24c4ba4..51a7f68 100644 --- a/doc/aao.html +++ b/doc/aao.html @@ -3,12 +3,13 @@Note: aao record support is disabled per default. @@ -123,6 +124,5 @@ the written or read value. scalcout
Dirk Zimoch, 2006
- diff --git a/doc/ai.html b/doc/ai.html index 51be662..52399d5 100644 --- a/doc/ai.html +++ b/doc/ai.html @@ -3,12 +3,13 @@EOFF=-10
and ESLO=0.000305180437934
(=20.0/0xFFFF) maps 0x0000 to -10.0, 0x7FFF to 0.0 and 0xFFFF to 10.0.
+ Using unsigned formats with values ≥ 0x800000 gives different results
+ on 64 bit machines.
%{
):Dirk Zimoch, 2005
- diff --git a/doc/ao.html b/doc/ao.html index 75c88fb..88ebbda 100644 --- a/doc/ao.html +++ b/doc/ao.html @@ -3,12 +3,13 @@EOFF=-10
and ESLO=0.000305180437934
(=20.0/0xFFFF) maps -10.0 to 0x0000, 0.0 to 0x7FFF and 10.0 to 0xFFFF.
+ Using unsigned formats with values ≥ 0x800000 gives different results
+ on 64 bit machines.
%{
):Dirk Zimoch, 2005
- diff --git a/doc/bg.gif b/doc/bg.gif deleted file mode 100644 index e86e76c..0000000 Binary files a/doc/bg.gif and /dev/null differ diff --git a/doc/bi.html b/doc/bi.html index 581afef..a959fa9 100644 --- a/doc/bi.html +++ b/doc/bi.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/bo.html b/doc/bo.html index 638621b..00c4a74 100644 --- a/doc/bo.html +++ b/doc/bo.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/businterface.html b/doc/businterface.html index ff77a01..eef0ac9 100644 --- a/doc/businterface.html +++ b/doc/businterface.html @@ -3,12 +3,13 @@writeRequest()
.
Dirk Zimoch, 2007
- diff --git a/doc/calcout.html b/doc/calcout.html index 5376631..49ace51 100644 --- a/doc/calcout.html +++ b/doc/calcout.html @@ -3,12 +3,13 @@@@ -78,6 +79,5 @@ Different record fields are used for output and input. The variable scalcout
Dirk Zimoch, 2005
- diff --git a/doc/epics3_13.html b/doc/epics3_13.html index 674da8b..acdbd12 100644 --- a/doc/epics3_13.html +++ b/doc/epics3_13.html @@ -3,12 +3,13 @@Dirk Zimoch, 2006
- diff --git a/doc/favicon.ico b/doc/favicon.ico new file mode 100644 index 0000000..67381a6 Binary files /dev/null and b/doc/favicon.ico differ diff --git a/doc/formatconverter.html b/doc/formatconverter.html index 54e9cc1..83619f9 100644 --- a/doc/formatconverter.html +++ b/doc/formatconverter.html @@ -3,18 +3,219 @@+A user defined converter class inherits public from +StreamFormatConverter and handles one or more conversion characters. +It is not necessary that a given conversion character supports both, +printing and scanning. +But if it does, both must be handled by the same converter class. +
++Any conversion corresponds to one data type. The converter class must +implement print and/or scan methods for this data type. It must also +implement a parse method to analyse the format string. +
++A converter class must be registered with a call to RegisterConverter() +in the global file context. +
++The converter must not contain any class variables, because there will be +only one global instance for each conversion character - not one for each +format string! +
+ +%Q
+#include "StreamFormatConverter.h" + +class MyConverter : public StreamFormatConverter +{ + int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); + bool printLong(const StreamFormat&, StreamBuffer&, long); + int scanLong(const StreamFormat&, const char*, long&); +}; + +RegisterConverter(MyConverter,"Q"); + +// ... (implementation) ++ + +
+RegisterConverter(converterClass, "characters");
+
+This macro registers the converter class for all given conversion +characters. In most cases, you will give only one character. +The macro must be called once for each class in the global file context. +
++HINT: Do not branch depending on the conversion character. +Provide multiple classes, that's more efficient. +
+ + +
+int parse (const StreamFormat& fmt, StreamBuffer& info,
+const char*& source, bool scanFormat);
+
+struct StreamFormat {
+char conv;
+StreamFormatType type;
+unsigned char flags;
+short prec;
+unsigned short width;
+unsigned short infolen;
+const char* info;
+};
+
+During initialization, parse()
is called whenever one of the
+conversion characters handled by your converter class is found in a protocol.
+The fields fmt.conv
, fmt.flags
,
+fmt.prec
, and fmt.width
have
+already been filled in. If a scan format is parsed, scanFormat
+is true
. If a print format is parsed, scanFormat
+is false
.
+
+The fmt.flags
field is a bitset and can have any of the following
+flags set:
+
left_flag
: the format contained a -
.
+ This is normaly used to indicate that the value should be printed
+ left-aligned.
+ sign_flag
: the format contained a +
.
+ This normaly requests to print a sign even for positive numbers.
+ space_flag
: the format contained a '
' (space).
+ This normaly requests to print a space instead of a sign for positive numbers.
+ alt_flag
: the format contained a #
.
+ This indicated the request to use an alternative format. For example in
+ %#x
the hex number is preficed with 0x
.
+ zero_flag
: the format contained a 0
.
+ This normaly requests to pad a numerical value with leading zeros
+ instead of leading spaces.
+ skip_flag
: the format contained a *
.
+ The value is parsed and checked but then discarded.
++It is not necessary that these flags have exactly the same meaning in your +formats, but a similar and intuitive meaning helpful for the user. +
+
+There are two additional flags, default_flag
indicating a
+?
and compare_flag
indicating a =
+int the format, that are handled internally by StreamDevice and
+are not of interest to the converter class.
+
+The source
pointer points to the character of the format string
+just after the conversion character. You can parse additional characters if
+they belong to the format string handled by your class.
+Move the source
pointer so that is points to the first character
+after your format string.
+This is done for example in the builtin formats
+%[charset]
or %{enum0|enum1}
.
+However, many formats don't need additional characters.
+
+
+ source source + before after + parse() parse() + | | +"%39[0-9a-zA-Z]constant text" + | + conversion + character ++ +
+You can write any data you may need later in print*()
or
+scan*()
to the
+Streambuffer info
.
+This will probably be necessary if you have parsed additional characters
+from the format string as in the above example
+
+Return long_format
, double_format,
+string_format, or enum_format
depending on the
+datatype associated with the conversion character.
+It is not necessary to return the same value for print and for scan
+formats.
+You can even return different values depending on the format string,
+but I can't imagine why anyone should do that.
+
+If the format is not a real data conversion but does other things with
+the data (append or check a checksum, encode or decode the data,...),
+return pseudo_format
.
+
+Return false
if there is any parse error or if print or scan
+is requested but not supported by this conversion.
+
+Provide a print[Long|Double|String|Pseudo]()
and/or
+scan[Long|Double|String|Pseudo]()
method appropriate
+for the data type you have returned in the parse()
method.
+That method is called whenever the conversion appears in an output or input,
+respectively.
+You only need to implement the flavour of print and/or scan suitable for
+the datatype returned by parse()
.
+
+Now, fmt.type
contains the value returned by parse()
.
+With fmt.info()
get access to the string you have written to
+info
in parse()
(null terminated).
+
+The length of the info string can be found in fmt.infolen
.
+
+In print*()
, append the converted value to output
.
+Do not modify what is already in output (unless you really know what you're
+doing).
+Return true
on success, false
on failure.
+
+In scan*()
, read the value from input and return the number of
+consumed bytes.
+In the string version, don't write more bytes than maxlen
!
+If the skip_flag
is set, you don't need to write to
+value
, since the value will be discarded anyway.
+Return -1
on failure.
+
Dirk Zimoch, 2006
- +Dirk Zimoch, 2007
diff --git a/doc/formats.html b/doc/formats.html index 6e6adb8..40b7055 100644 --- a/doc/formats.html +++ b/doc/formats.html @@ -3,12 +3,13 @@%
character()
*# +0-
()
*# +0-?=
.
) followed
by an integer precision field (input ony for most formats)
+The flags *# +0-
work like in the C functions
+printf() and scanf().
+The flags ?
and =
are extensions.
+
The *
flag skips data in input formats.
Input is consumed and parsed, a mismatch is an error, but the read
@@ -61,6 +67,16 @@ The 0
flag says that numbers should be left padded with
The -
flag specifies that output is left justified if
width is larger than required.
+The ?
flag makes failing input conversions succeed with
+a default zero value (0, 0.0, or "", depending on the format type).
+
+The =
flag allows to compare input with current values.
+It is only allowed in input formats.
+Instead of reading a new value from input, the current value is
+formatted (like for output) and then compared to the input.
+
in "%*i"; |
skipped integer number | +
in "%?d"; |
+ decimal number or nothing (read as 0) | +
in "%=.3f"; |
+ compare input to the current value formatted as a float with precision 3 | +
l
or h
do not
exist in StreamDevice formats.
-
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 %
.
For example out "%(EGU)s";
outputs the EGU
field formatted as a string.
-Use in "%(otherrecord.VAL)f";
to write the floating
-point input value into the VAL
field of
-otherrecord
.
-(You can't skip .VAL
here.)
-This is very useful when one line of input contains many values that should
+Use in "%(otherrecord.RVAL)f";
to write the floating
+point input value into the RVAL
field of
+otherrecord
.
+
+If no field is given for an other record .VAL is assumed.
+When a record name conflicts with a field name use .VAL explicitly.
+
+
+
+This feature is very useful when one line of input contains many values that should
be distributed to many records.
If otherrecord
is passive and the field has the PP
attribute (see
@@ -129,6 +159,8 @@ 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.
+At the moment it is not possible to set otherrecord
to an alarm
+state when anything fails.
%f
, %e
,
%E
, %g
, %G
)
-In output, %f
prints fixed point, %e
prints
+Output: %f
prints fixed point, %e
prints
exponential notation and %g
prints either fixed point or
exponential depending on the magnitude of the value.
%E
and %G
use E
instead of
e
to separate the exponent.
+
With the #
flag, output always contains a period character.
-In input, all these formats are equivalent. -Leading whitespaces are skipped. +Input: All these formats are equivalent. Leading whitespaces are skipped. +
+
+With the #
flag additional whitespace between sign and number
+is accepted.
+
+When a maximum field width is given, leading whitespace only counts to the +field witdth when the space flag is given.
%d
, %i
,
%u
, %o
, %x
, %X
)
-In output, %d
and %i
print signed decimal,
+Output: %d
and %i
print signed decimal,
%u
unsigned decimal, %o
unsigned octal, and
%x
or %X
unsigned hexadecimal.
%X
uses upper case letters.
+
With the #
flag, octal values are prefixed with 0
and hexadecimal values with 0x
or 0X
.
-In input, %d
matches signed decimal, %u
matches
+Input: %d
matches signed decimal, %u
matches
unsigned decimal, %o
unsigned octal.
%x
and %X
both match upper or lower case unsigned
hexadecimal.
@@ -177,23 +220,40 @@ Octal and hexadecimal values can optionally be prefixed.
hexadecimal notation.
Leading whitespaces are skipped.
+With the -
negative octal and hexadecimal values are accepted.
+
+With the #
flag additional whitespace between sign and number
+is accepted.
+
+When a maximum field width is given, leading whitespace only counts to the +field witdth when the space flag is given. +
%s
, %c
)
-In output, %s
prints a string.
+Output: %s
prints a string.
If precision is specified, this is the maximum string length.
%c
is a LONG format in output, printing one character!
-In input, %s
matches a sequence of non-whitespace characters
-and %c
a sequence of not-null characters.
+Input: %s
matches a sequence of non-whitespace characters
+and %c
matches a sequence of not-null characters.
The maximum string length is given by width.
The default width is infinite for %s
and
1 for %c
.
-Leading whitespaces are skipped with %s
but not with
-%c
.
-The empty string matches.
+Leading whitespaces are skipped with %s
+
+except when the space flag is given
+but not with %c
.
+The empty string matches.
+
+With the #
flag %s
matches a sequence of not-null
+characters instead of non-whitespace characters.
z
.
This format maps an unsigned integer value on a set of strings.
The value 0 corresponds to string0 and so on.
The strings are separated by |
.
-If one of the strings contains |
or }
,
-a \
must be used to escape the character.
Example: %{OFF|STANDBY|ON}
mapps the string OFF
to the value 0, STANDBY
to 1 and ON
to 2.
+When using the #
flag it is allowed to assign integer values
+to the strings using =
.
+
+Example: %#{neg=-1|stop=0|pos=1|fast=10}
.
+
+If one of the strings contains |
or }
+(or =
if the #
flag is used)
+a \
must be used to escape the character.
+
In output, depending on the value, one of the strings is printed.
@@ -248,12 +318,11 @@ Examples: %B.!
or %B\x00\xff
.
%B01
is equivalent to %b
.
-If in output width is larger than the number of significant bits,
+In output, if width is larger than the number of significant bits,
then the flag 0
means that the value should be padded with
with the chosen zero character instead of spaces.
If precision 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 #
is used.
In input, leading spaces are skipped.
@@ -275,11 +344,9 @@ endian, i.e. least significant byte first.
With the 0
flag, the value is unsigned, otherwise signed.
-In output, the width least significant bytes of the value
-are written.
-If width is larger than the size of a long
,
-the value is sign extended or zero extended, depending on the
-0
flag.
+In output, the prec (or sizeof(long) whatever is less) least
+significant bytes of the value are sign extended or zero extended
+(depending on the 0
flag) to width bytes.
In input, width bytes are read and put into the value.
@@ -289,9 +356,25 @@ If width is smaller than the size of a long
,
the value is sign extended or zero extended, depending on the
0
flag.
+Example: out "%.2r"
+
%R
)
+The raw converter does not really "convert".
+A float or double value is written or read in the internal
+(maybe IEEE) representation of the computer.
+The normal byte order is big endian, i.e. most significant byte
+first.
+With the #
flag, the byte order is changed to little
+endian, i.e. least significant byte first.
+The width must be 4 (float) or 8 (double). The default is 4.
+
%D
)%D
)
Packed BCD is a format where each byte contains two binary coded
decimal digits (0
... 9
).
@@ -320,7 +403,7 @@ than 9.
%<checksum>
)%<checksum>
)This is not a normal "converter", because no user data is converted. Instead, a checksum is calculated from the input or output. @@ -399,6 +482,9 @@ In input, the next byte or bytes must match the checksum. href="http://www.joegeluso.com/software/articles/ccitt.htm">correct?) implementation of the CCITT standard 16 bit crc checksum with augment. (poly=0x1021, init=0x1D0F, xorout=0x0000).
%<ccitt16x>
or %<crc16c>
or %<xmodem>
%<crc32>
/
is must be escaped.
+If the expression contains a /
it must be escaped.
Example: %.1/<title>(.*)<\/title>/
returns
@@ -458,23 +544,82 @@ the title of an HTML page, skipps anything before the
<title>
tag and leaves anything after the
</title>
tag in the input buffer.
%m
)%m
)
-This experimental input-only format matches numbers in the format
-[sign] mantissa sign exponent, e.g +123-4
meaning
-123e-4 or 0.0123. Mantissa and exponent are integers. The sign of the
-mantissa is optional. Compared to the standard %e
format,
-this format does not contain the characters .
and e
.
+This exotic and experimental format matches numbers in the format
+[sign] mantissa sign exponent, e.g +123-4
meaning
+123e-4 or 0.0123. Mantissa and exponent are decimal integers.
+The sign of the mantissa is optional.
+Compared to the standard %e
format, this format does not
+contain the characters .
and e
.
Output formatting is ambigous (e.g. 123-4
versus
-1230-5
). Until it has been specified how to handle this,
-output is not supported.
+1230-5
). I chose the following convention:
+Format precision defines number of digits in mantissa.
+No leading '0' in mantissa (except for 0.0 of course).
+Number of digits in exponent is at least 2.
+Format flags +
, -
, and space are supported in
+the usual way (always sign, left justified, space instead of + sign).
+Flags #
and 0
are unsupported.
%T(timeformat)
)
+This format reads or writes timestamps and converts them to a double number.
+The value represents the number of seconds since 1970 (the UNIX epoch).
+The precision of a double is large enough for microseconds (but not for
+nanoseconds). This format is probably used best in combination with a
+redirection to the TIME
field. In this case, the value is
+converted to EPICS timestamps (seconds since 1990 and nanoseconds).
+The timestamp format understands the usual converters that the C function
+strftime() understands. In addition, fractions of a second can
+be specified and the time zone can be set in the format string.
+
+Example: %(TIME)T(%d %b %Y %H:%M:%.3S %z)
may print something like
+ 3 Sep 2010 15:45:59 +0200
.
+
+Fractions of a second can be specified as %.nS
+(seconds with n fractional digits), as %0nf
+or %nf
(n fractional digits) or as
+%N
(nanoseconds).
+In input, n is the maximum number of digits parsed, there may be
+actually less digits in the input.
+If n is not specified (%.S
or %f
) it uses
+a default value of 6.
+
+In input, the time zone can be specified in the format like
+%+hhmm
or %-hhmm
for cases
+where the parsed time stamp does not specify the time zone, where
+hhmm is a 4 digit number specifying the offset in hours and minutes.
+
+In output, the system function strftime() is used to format the time. +There may be differences in the implementation between operating systems. +
++In input, StreamDevice used its own implementation because many +systems are missing the strptime() function and additional formats +are supported. +
++Day of the week can be parsed but is ignored because the information is +redundant when used together with day, month and year and more or less +useless otherwise. No check is done for consistency. +
++Because of the complexity of the problem, locales are not supported. +Thus, only the English month names can be used (week day names are +ignored anyway). +
+Dirk Zimoch, 2007
- +Dirk Zimoch, 2011
diff --git a/doc/head.html b/doc/head.html deleted file mode 100644 index 98913e5..0000000 --- a/doc/head.html +++ /dev/null @@ -1,32 +0,0 @@ - - - -![]() ![]() |
- ![]() |
- ![]() |
- - StreamDevice | -![]() ![]() |
- |
+StreamDevice is a generic +EPICS +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 telnet-like TCP/IP. +
++StreamDevice is not limited to a specific device type or +manufacturer nor is it necessary to re-compile anything to support a +new device type. +Instead, it can be configured for any device type with +protocol files in plain ASCII text +which describes the commands a device understands and the replies it sends. +If the device can be controlled with strings like +"RF:FREQ 499.655 MHZ" StreamDevice can be used. +Formatting and parsing of values is done with +format converters similar to those +known from the C functions printf() and scanf(). +To support other formats, it is possible to +write your own converters. +
++Each record with StreamDevice support runs one protocol +from the protocol file to read or write its value. +Protocols 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 +processed. +It does not provide loops or branches. +
++StreamDevice comes with an interface to +asynDriver +but can be extended to +support other bus drivers. +Note that StreamDevice is not an alternative or replacement +but a supplement for asynDriver. +StreamDevice converts record values to and from strings but +leaves it to asynDriver (or other bus interfaces) to exchange +these strings with the device. +Thus any bus type supported by asynDriver (to be exact by +asynOctet) can automatically be used with StreamDevice. +
++StreamDevice supports all +standard records of EPICS base +which can have device support. +It is also possible to +write support for new record types. +
+ ++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 protocol. +Use other tools for that and use StreamDevice only for the +primitive commands. +
++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. +
+ ++IOC Application Developer's Guide (PDF) +
++EPICS Record Reference Manual +
+ +
+In this document, code is witten in green fixed width font
.
+This marks text you typically type in configuration files etc.
+
+Longer code segments are often set in a box. ++
+Important modifications and new features are
+highlighted with a yellow background.
+Obsolete features are highlighted and crossed out.
+
Dirk Zimoch, 2011
+ diff --git a/doc/longin.html b/doc/longin.html index 74dc3a8..94fb373 100644 --- a/doc/longin.html +++ b/doc/longin.html @@ -3,12 +3,13 @@x=VAL
VAL=x
+ Using unsigned formats with values ≥ 0x800000 gives different results
+ on 64 bit machines.
%{
):Dirk Zimoch, 2005
- diff --git a/doc/longout.html b/doc/longout.html index af8820d..d7e1ab2 100644 --- a/doc/longout.html +++ b/doc/longout.html @@ -3,12 +3,13 @@x=VAL
VAL=x
+ Using unsigned formats with values ≥ 0x800000 gives different results
+ on 64 bit machines.
%{
):Dirk Zimoch, 2005
- diff --git a/doc/mbbi.html b/doc/mbbi.html index 3e5caba..a2ad2d3 100644 --- a/doc/mbbi.html +++ b/doc/mbbi.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/mbbiDirect.html b/doc/mbbiDirect.html index e7bb376..53a8ff3 100644 --- a/doc/mbbiDirect.html +++ b/doc/mbbiDirect.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/mbbo.html b/doc/mbbo.html index 5c4d961..ed08e0a 100644 --- a/doc/mbbo.html +++ b/doc/mbbo.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/mbboDirect.html b/doc/mbboDirect.html index e7f6d17..b193d6f 100644 --- a/doc/mbboDirect.html +++ b/doc/mbboDirect.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/nav.html b/doc/nav.html index 14801f9..40d04de 100644 --- a/doc/nav.html +++ b/doc/nav.html @@ -5,216 +5,209 @@-
-- -
+Dirk Zimoch, 2006
- diff --git a/doc/printer.gif b/doc/printer.gif deleted file mode 100644 index c3ef2ea..0000000 Binary files a/doc/printer.gif and /dev/null differ diff --git a/doc/processing.html b/doc/processing.html index 6424375..dd48ca4 100644 --- a/doc/processing.html +++ b/doc/processing.html @@ -3,12 +3,13 @@ROI
", followed by two floating point numbers.
Dirk Zimoch, 2005
- diff --git a/doc/protocol.html b/doc/protocol.html index 56db86e..434e3c1 100644 --- a/doc/protocol.html +++ b/doc/protocol.html @@ -3,12 +3,13 @@\1
to \9
followed by up to two more decimal
digits means a byte with that decimal value.\?
in the argument string of an in
-command matches any input byte\?
in input matches any byte, in output it does not print
+anything.\_
in input matches any amount of white space (including none),
+in output it prints a single space.\$
followed by the name of a
protocol varible is replaced by the contents of that
variable.
@@ -251,29 +256,54 @@ variable.
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).
-StreamDevice also defines some symbolic names for frequently
-used byte codes as aliases for the numeric byte value:EOT
means end of transmission (ASCII code 4).ACK
means acknowledge (ASCII code 6).BEL
means bell (ASCII code 7).BS
means backspace (ASCII code 8).HT
or TAB
mean horizontal tabulator
-(ASCII code 9).LF
or NL
mean line feed /
-new line (ASCII code 10).CR
means carriage return (ASCII code 13).ESC
means escape (ASCII code 27).DEL
means delete (ASCII code 127).SKIP
in the argument string of an in
-command matches any input byte.
+number in the range of -128
to 255
,
+-0x80
to 0xff
(not case sesitive),
+or -0200
to 0377
, respectively.
+
+
+StreamDevice also recordgnizes the ASCII symbolic names
+(not case sensitive) for several byte codes:
+NUL
(= 0x00
) null
+SOH
(= 0x01
) start of heading
+STX
(= 0x02
) start of text
+ETX
(= 0x03
) end of text
+EOT
(= 0x04
) end of transmission
+ENQ
(= 0x05
) enquiry
+ACK
(= 0x06
) acknowledge
+BEL
(= 0x07
) bell
+BS
(= 0x08
) backspace
+HT
or TAB
(= 0x09
) horizontal tabulator
+LF
or NL
(= 0x0A
or 10
) line feed / new line
+VT
(= 0x0B
or 11
) vertical tabulator
+FF
or NP
(= 0x0C
or 12
) form feed / new page
+CR
(= 0x0D
or 13
) carriage return
+SO
(= 0x0E
or 14
) shift out
+SI
(= 0x0F
or 15
) shift in
+DLE
(= 0x10
or 16
) data link escape
+DC1
(= 0x11
or 17
) device control 1
+DC2
(= 0x12
or 18
) device control 2
+DC3
(= 0x13
or 19
) device control 3
+DC4
(= 0x14
or 20
) device control 4
+NAK
(= 0x15
or 21
) negative acknowledge
+SYN
(= 0x16
or 22
) synchronous idle
+ETB
(= 0x17
or 23
) end of transmission block
+CAN
(= 0x18
or 24
) cancel
+EM
(= 0x19
or 25
) end of medium
+SUB
(= 0x1A
or 26
) substitute
+ESC
(= 0x1B
or 27
) escape
+FS
(= 0x1C
or 28
) file separator
+GS
(= 0x1D
or 29
) group separator
+RS
(= 0x1E
or 30
) record separator
+US
(= 0x1F
or 31
) unit separator
+DEL
(= 0x7F
or 127
) delete
+SKIP
or ?
matches any input byte
A single string can be built from several quoted literals and byte values by writing them separated by whitespaces or comma.
-
The following lines represent the same string:
"Hello world\r\n"
@@ -408,9 +438,12 @@ what they influence.
(see formats and
waveform record), what string
to write or to expect between values?
- If the first character of the Separator
is a
+
+ If the first character of the To match arbitrary amount of
+ whitespace in input, use Separator
is a
space, it matches any number of any whitespace characters in
- an in
command.
+ an in
command."\_"
.
+
ExtraInput = Error;
Dirk Zimoch, 2006
- +Dirk Zimoch, 2011
diff --git a/doc/recordinterface.html b/doc/recordinterface.html index 9cbc871..bbc1396 100644 --- a/doc/recordinterface.html +++ b/doc/recordinterface.html @@ -3,18 +3,18 @@Dirk Zimoch, 2006
- diff --git a/doc/recordtypes.html b/doc/recordtypes.html index b1acb28..46b2c69 100644 --- a/doc/recordtypes.html +++ b/doc/recordtypes.html @@ -3,12 +3,13 @@Dirk Zimoch, 2005
- diff --git a/doc/scalcout.html b/doc/scalcout.html index 892ea25..846dc18 100644 --- a/doc/scalcout.html +++ b/doc/scalcout.html @@ -3,12 +3,13 @@@@ -96,6 +97,5 @@ Different record fields are used for output and input. The variable calcout
Dirk Zimoch, 2005
- diff --git a/doc/setup.html b/doc/setup.html index 1d3b00c..565e7c2 100644 --- a/doc/setup.html +++ b/doc/setup.html @@ -3,79 +3,159 @@-StreamDevice requires either +StreamDevice requires either EPICS base R3.14.6 or higher or EPICS base R3.13.7 or higher. How to use StreamDevice on EPICS R3.13 is described on a separate page. -Because StreamDevice comes with an interface to -asynDriver version R4-3 or higher as the -underlying driver layer, -you should have asynDriver installed first. -
--StreamDevice has support for the -scalcout record from the -calc module of synApps. -Up to calc release R2-6 (synApps release R5_1), -the scalcout record needs a fix. -(See separate scalcout page.) -Support for the scalcout is optional. StreamDevice works -as well without scalcout or SynApps.
+Up to release R3.14.8.2, a fix in EPICS base is required to build StreamDevice on Windows (not cygwin). -In src/iocsh/iocsh.h, add the following line +Add the following line to src/iocsh/iocsh.h and rebuild base.
epicsShareFunc int epicsShareAPI iocshCmd(const char *command);+
-Make sure that the asyn library (and the calc module of
-synApps, if desired) can be found, e.g. by
-adding ASYN
-and (if installed) CALC
or SYNAPPS
-to your <top>/configure/RELEASE file:
+StreamDevice does not come with its own <top>
+location and <top>/configure directory.
+It expects to be put into an already existing <top>
+directory structure.
+You can simply create one with makeBaseApp.pl
+(which is part of EPICS base):
+mkdir top
+cd top
+makeBaseApp.pl -t support
+
+When asked for "Application names" just hit Enter. +Then go to the newly created configure subdirectory and +edit the RELEASE file you find there according to the +instructions below. +
+
+After changing any configuration, you should run make
+in this directory.
+
+For details on <top> directories and RELEASE +files please refer to the +IOC Application Developer's Guide chapter 4: +EPICS Build Facility. +
+ ++You most probably want asynDriver support included, because that is the +standard way for StreamDevice to talk to hardware. +First get and install asynDriver version 4-3 or higher before you build StreamDevice. +I have tested StreamDevice with asynDriver versions up to 4-17. +Make sure that the asyn library can be found by adding the path to the +<top> directory of your asyn installation to the +RELEASE file:
-ASYN=/home/epics/asyn/4-5 -CALC=/home/epics/synApps/calc/2-7 +ASYN=/home/epics/asyn4-17 ++ +
+The sCalcout record is part of synApps. +If streamDevice should be built with support for this record, +you have to install the calc module from SynApps first. +Add references to the RELEASE file as shown here: +
+CALC=/home/epics/synApps/calc-2-8
+Up to calc release R2-6 (synApps release R5_1), +the sCalcout record needs a fix. +(See separate scalcout page.) +And the calc modue had dependencies on other SynApps +modules. Release R2-8 or newer is recommended. +
++Support for the scalcout is optional. StreamDevice works +as well without scalcout or SynApps. +
+ +If you want to enable regular expression matching, you need the PCRE package. -For most Linux systems, it is already installed. In that case add the locations -of the PCRE header and library to your RELEASE file: +For most Linux systems, it is already installed. +In that case add the locations you have to make the locations of the +PCRE header file and library known. +However, the pre-installed package can only by used for the host architecture. +Thus, add them not to RELEASE but to RELEASE.Common.linux-x86 +(if linux-x86 is your EPICS_HOST_ARCH). +Note that different Linux distributions may locate the files in different directories.
PCRE_INCLUDE=/usr/include/pcre PCRE_LIB=/usr/lib
-If you want to build StreamDevice for platforms without PCRE support, -it is the easiest to build PCRE as an EPICS application. -Download the PCRE package from www.pcre.org -and compile it with my EPICS compatible -Makefile. -Then define the location of the application in your RELEASE file. +A pre-compiled Windows version of PCRE is available at +sourceforge +
++If you want to have PCRE support on platforms that don't support it natively, +e.g. vxWorks, it is probably the easiest to build PCRE as an EPICS application. +
++
+
makeBaseApp.pl
.
+perl fixforvxworks.pl
+make
(or gmake
)
++Define the location of the pcre <top> in the RELEASE file for StreamDevice.
PCRE=/home/epics/pcre @@ -84,25 +164,17 @@ PCRE=/home/epics/pcre Regular expressions are optional. If you don't want them, you don't need this. --For details on <top> directories and RELEASE files, -please refer to the -IOC Application Developer's Guide chapter 4: -EPICS Build Facility. -
-2. Build the StreamDevice Library
Unpack the StreamDevice package in a <top> directory +>StreamDevice package in the <top> directory of your application build area. (You might probably have done this already.) Go to the newly created StreamDevice directory -and run make (or gmake). -This will create and install the stream library and the +and run
@@ -121,7 +193,8 @@ PROD_LIBS += asynmake
(orgmake
). +This will create and install the stream library and the stream.dbd file.
Include the following lines in your xxxAppInclude.dbd file to use -stream and asyn with serial lines and IP sockets: +stream and asyn with serial lines, IP sockets, +and vxi11 ("GPIB over ethernet") support.
include "base.dbd" @@ -129,6 +202,7 @@ include "stream.dbd" include "asyn.dbd" registrar(drvAsynIPPortRegisterCommands) registrar(drvAsynSerialPortRegisterCommands) +registrar(vxi11RegisterCommands)
You can find an example application in the streamApp @@ -151,7 +225,7 @@ i.e. the current directory.
Also configure the buses (in asynDriver terms: ports) you want to use with StreamDevice. -You can give the buses any name you want, like COM1 or +You can give the buses any name you want, like COM1 or socket, but I recommend to use names related to the connected device.
@@ -189,7 +263,7 @@ drvAsynIPPortConfigure ("PS1", "192.168.164.10:23")-With a VXI11 (GPIB via TCP/IP) connection, e.g. a +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:
@@ -211,7 +285,7 @@ DuringiocInit
, streamDevice 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 -STREAM_PROTOCOL_PATH
. +STREAM_PROTOCOL_PATH
.Example:
@@ -234,7 +308,7 @@ Terminator = CR LF; setCurrent { out "CURRENT %.2f"; - @init { + @init { out "CURRENT?"; in "CURRENT %f A"; } @@ -270,19 +344,24 @@ See the next chapter for protocol files in depth.
To make a record use StreamDevice, set its
+DTYP
field to"stream"
. +The
INP
orOUT
link has the form"@file protocol bus [address [parameters]]"
.Here,
+file
is the name of the protocol file andprotocol
is the name of a protocol defined in this file. +(See the next chapter.) +If the protocol requires arguments, specify them enclosed in parentheses:
protocol(arg1,arg2,...)
.-The communication channel is specified with
@@ -298,8 +377,8 @@ The bus is called PS1 like the device. record (ao, "PS1:I-set") { field (DESC, "Set current of PS1") - field (DTYP, "stream") - field (OUT, "@ExamplePS.proto setCurrent PS1") + field (DTYP, "stream") + field (OUT, "@ExamplePS.proto setCurrent PS1") field (EGU, "A") field (PREC, "2") field (DRVL, "0") @@ -311,7 +390,6 @@ record (ao, "PS1:I-set")bus
and -addr
. +The communication channel is specified withbus
+(aka asynDriver "port") andaddr
. If the bus does not have addresses,addr
is dispensable. Optionalparameters
are passed to the bus driver.
-Dirk Zimoch, 2007
- +Dirk Zimoch, 2011
diff --git a/doc/sls_icon.ico b/doc/sls_icon.ico deleted file mode 100644 index 9a556f5..0000000 Binary files a/doc/sls_icon.ico and /dev/null differ diff --git a/doc/space.gif b/doc/space.gif deleted file mode 100644 index e1e3800..0000000 Binary files a/doc/space.gif and /dev/null differ diff --git a/doc/stream.css b/doc/stream.css index 8f12e74..11a9ab7 100644 --- a/doc/stream.css +++ b/doc/stream.css @@ -1,13 +1,17 @@ -a:link {color: #0000D0; text-decoration:none;} -a:visited {color: #0000D0; text-decoration:none;} -a:hover {color: #FF0000; text-decoration:none;} +a:link {color: #0000D0;} +a:visited {color: #0000D0;} +a:hover {color: #FF0000;} body { - margin-right:20px; - font-family:sans-serif; + margin-right:1em; + margin-left:15em; + margin-top:11ex; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-size:14px; background-color:#ffffff; -} +} + +a[name] { position:relative; top:-11ex;} pre { background-color:#f4f4f4; @@ -17,6 +21,10 @@ pre { margin:2ex; } +kbd { + font-weight:bold; +} + dt { margin-top:0.5ex; } @@ -26,6 +34,22 @@ h1 { margin-top:0; font-style:italic; font-family:serif; + text-align:center; + position:fixed; + top:0; + left:0; + width:100%; + min-height:60px; + height: 4ex; + line-height:190%; + background-color:white; + border-top:6px solid #1b4486; + border-bottom:4px solid #1b4486; + white-space:nowrap; + background-image:url(PSI.gif); + background-repeat:no-repeat; + background-position:10px 2px; + text-shadow: .1em .1em .1em lightgray; } h2 { @@ -34,6 +58,11 @@ h2 { } h3 { + font-size:120%; + margin-bottom:0.25ex; +} + +h4 { font-size:100%; margin-bottom:0.25ex; } @@ -58,22 +87,41 @@ code { text-align:left; } -/* - a[target=ex] { - background-image:url(ex.png); - background-repeat:no-repeat; - background-position:right center; - padding-right: 12px; - } +#navleft { + position:fixed; + left:0; + top:0; + padding-top:9ex; + width:14em; + height:100%; + border-style:solid; + border-color:black; + border-width:0 1px 0 0; + background-color:#e3eaf6; + overflow:hidden; + z-index:0; +} - a[target=ex]:hover { - background-image:url(exr.png); - } -*/ +.new { + background-color: #ffc; +} + +a[target=ex]:after { + content:" " url(ex.png); +} + +a[target=ex]:hover:after { + content: " " 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;} + a[target=ex] {text-decoration:underline;} + a[target=ex]:after {content:" [" attr(href) "]";} code {color: black; } + body {margin-left:10px;} + h1 {position:absolute;} + #navleft {display:none;} } diff --git a/doc/stream.html b/doc/stream.html deleted file mode 100644 index 56b8e53..0000000 --- a/doc/stream.html +++ /dev/null @@ -1,92 +0,0 @@ - - - -StreamDevice - - - - - - -EPICS StreamDevice Documentation
- -What is StreamDevice?
--StreamDevice is a generic -EPICS -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. -StreamDevice comes with an interface to -asynDriver -but can be extended to -support other bus drivers. -
--If the device can be controlled with strings like -"
-RF:FREQ 499.655 MHZ
", StreamDevice can be used. -How the strings exactly look like is defined in protocols. -Formatting and interpretation of values is done with -format converters similar to those -known from the C functions printf() and scanf(). -To support other formats, it is possible to -write your own converters. --Each record with StreamDevice support runs one protocol -to read or write its value. -All protocols are defined in -protocol files in plain ASCII text. -No compiling is necessary to change a protocol or to support new devices. -Protocols 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 -processed. -It does not provide loops or branches. -
--StreamDevice supports all -standard records of EPICS base -which can have device support. -It is also possible to -write support for new record types. -
- -What is StreamDevice not?
--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 protocol. -Use other tools for that and use StreamDevice only for the -primitive commands. -
--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. -
- -Recommended Readings
--IOC Application Developer's Guide (PDF) -
--EPICS Record Reference Manual -
- -
- -Dirk Zimoch, 2006
- - - diff --git a/doc/stream.js b/doc/stream.js deleted file mode 100644 index da8aaf0..0000000 --- a/doc/stream.js +++ /dev/null @@ -1,5 +0,0 @@ -if (parent.head) { - parent.head.document.getElementById('subtitle').innerHTML=document.title; - parent.document.title=document.title; - document.getElementsByTagName('h1')[0].style.display="none"; -} diff --git a/doc/stringin.html b/doc/stringin.html index 42b48a7..be62172 100644 --- a/doc/stringin.html +++ b/doc/stringin.html @@ -3,12 +3,13 @@StreamDevice: stringin Records - + +StreamDevice: stringin Records
Normal Operation
@@ -62,6 +63,5 @@ written or read value. scalcoutDirk Zimoch, 2005
- diff --git a/doc/stringout.html b/doc/stringout.html index a57bc54..c0dbacf 100644 --- a/doc/stringout.html +++ b/doc/stringout.html @@ -3,12 +3,13 @@StreamDevice: stringout Records - + +StreamDevice: stringout Records
Normal Operation
@@ -62,6 +63,5 @@ written or read value. scalcoutDirk Zimoch, 2005
- diff --git a/doc/tipsandtricks.html b/doc/tipsandtricks.html index 092d5f1..d1391c3 100644 --- a/doc/tipsandtricks.html +++ b/doc/tipsandtricks.html @@ -3,12 +3,13 @@StreamDevice: Tips and Tricks - + +StreamDevice: Tips and Tricks
@@ -54,7 +55,7 @@ read {in "new value = %f";}record (ai, "$(RECORD)") {
@@ -95,10 +96,10 @@ array_out {separator=", "; out "an array: (%.2f)";} The format
field (DTYP, "stream")
- field (INP, "@(DEVICETYPE).proto read $(BUS)")
+ field (INP, "@$(DEVICETYPE).proto read $(BUS)")
field (SCAN, "I/O Intr")
}%.2f
is repeated for each element of the array. All elements are separated by", "
.
Output will look like this: +an array: (3.14, 17.30, -12.34)-B) We have up to 12 numeric values
Use a calcout record and @@ -121,7 +122,7 @@ record (calcout, "$(RECORD)") {
@@ -131,14 +132,14 @@ Use record references in the format.
field (INPC, "$(C_RECORD)")
field (CALC, "0")
field (DTYP, "stream")
- field (OUT, "@(DEVICETYPE).proto write_ABC $(BUS)")
+ field (OUT, "@$(DEVICETYPE).proto write_ABC $(BUS)")
}
-acquire {out 'ACQUIRE "%(\$1:directory.VAL)s/%s",%(\$1:time.VAL).3f;';} +acquire {out 'ACQUIRE "%(\$1:directory)s/%s",%(\$1:time).3f;';}
-You must specify the full
@@ -146,7 +147,7 @@ other records (device name) in parentheses.record.FIELD
name, -even forVAL
fields. -To avoid record names in protocol files use -protocol arguments. +You can specify a record name or record.FIELD in parentheses directly +after the%
. +To avoid plain record names in protocol files use +protocol arguments like\$1
. In the link, specify the record name or just the basename of the other records (device name) in parentheses.record (stringout, "$(DEVICE):getimage") {
@@ -190,12 +191,12 @@ read_B {in "A=%*f, B=%f";}
field (DTYP, "stream")
- field (OUT, "@(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")
+ field (OUT, "@$(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")
}record (ai, "$(DEVICE):A") {
@@ -221,14 +222,14 @@ To avoid record names in protocol files, use
field (DTYP, "stream")
- field (INP, "@(DEVICETYPE).proto read_A $(BUS)")
+ field (INP, "@$(DEVICETYPE).proto read_A $(BUS)")
field (SCAN, "1 second")
}
record (ai, "$(DEVICE):B") {
field (DTYP, "stream")
- field (INP, "@(DEVICETYPE).proto read_B $(BUS)")
+ field (INP, "@$(DEVICETYPE).proto read_B $(BUS)")
field (SCAN, "I/O Intr")
}
-read_AB {out "GET A,B"; in "A=%f, B=%(\$1.VAL)f";} +read_AB {out "GET A,B"; in "A=%f, B=%(\$1)f";}
record (ai, "$(DEVICE):A") {
field (DTYP, "stream")
- field (INP, "@(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")
+ field (INP, "@$(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")
field (SCAN, "1 second")
}
record (ai, "$(DEVICE):B") {
@@ -259,14 +260,14 @@ When asked "CURRENT?
", the device send something like
-read_current {out "CURRENT?"; in "CURRENT %f A"; @mismatch {in "%(\1.VAL)39c";}} +read_current {out "CURRENT?"; in "CURRENT %f A"; @mismatch {in "%(\1)39c";}}
record (ai, "$(DEVICE):readcurrent") {
field (DTYP, "stream")
- field (INP, "@(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")
+ field (INP, "@$(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")
}
record (stringin, "$(DEVICE):message") {
} @@ -292,6 +293,5 @@ record (stringout, "$(DEVICE):clean_2") {
Dirk Zimoch, 2007
- diff --git a/doc/waveform.html b/doc/waveform.html index 8614972..455ff90 100644 --- a/doc/waveform.html +++ b/doc/waveform.html @@ -3,12 +3,13 @@StreamDevice: waveform Records - + +StreamDevice: waveform Records
Normal Operation
@@ -121,6 +122,5 @@ the written or read value. scalcoutDirk Zimoch, 2005
-