Compare commits
634 Commits
stream_2_3
...
master
Author | SHA1 | Date | |
---|---|---|---|
20dde4c1d8 | |||
f61e6404f5 | |||
9080d6ca8e | |||
13e7f2d3dc | |||
e87e093c84 | |||
7debc86514 | |||
668d1d5255 | |||
ae5ca0c45b | |||
b00099973f | |||
5bf5cb9a67 | |||
f6848f0503 | |||
1496089bc8 | |||
a090cd4d8f | |||
2b3e4189c1 | |||
211f689cdf | |||
793675bb12 | |||
922294bf6a | |||
942c4779c9 | |||
8ceee295ae | |||
c30e2a4e31 | |||
fc67fb8721 | |||
c123c5c8f7 | |||
8746dea7cf | |||
2915830b02 | |||
fdfa4d4695 | |||
4d717288da | |||
94721c2b0e | |||
bf0e755913 | |||
51e4a0749d | |||
4cdace3ffe | |||
d19b16d096 | |||
b1e0d63c6b | |||
d1b43b879c | |||
6b0ee5e946 | |||
a0d1b35862 | |||
dfbd308d46 | |||
b615dae9b1 | |||
ac6c96c645 | |||
fe1ac364ab | |||
a06006eade | |||
a4e843cc4c | |||
601d4a3709 | |||
f495dd9853 | |||
6b05e006da | |||
068632326c | |||
a5eb4618b7 | |||
fe7f4a5e1b | |||
0010b8f23f | |||
7e42f6fddf | |||
2b15ae7ac0 | |||
055e141791 | |||
52486ae7a0 | |||
becf7d5585 | |||
132f03fc6c | |||
3978357f17 | |||
a1ec9b99e8 | |||
377d511c67 | |||
849586b7fa | |||
e6b2944c67 | |||
67c205e87b | |||
575c0ffcf8 | |||
e662ebda04 | |||
ea8873becd | |||
cf7e7bd6ee | |||
e36ee60ba7 | |||
e7f36a71af | |||
ce4b14c611 | |||
7c55d7bdfa | |||
6afa4828eb | |||
75bbb1a252 | |||
227bb83f60 | |||
4edff374d0 | |||
9273476135 | |||
8b9359723a | |||
bf55d4c202 | |||
1cace82a70 | |||
85e8632b02 | |||
1994912271 | |||
98fa595753 | |||
f6640b3418 | |||
4747bb5bc7 | |||
bd9ee1c660 | |||
22deae23e5 | |||
7f22d5bdc6 | |||
e4087a9244 | |||
cede631c8d | |||
1c9278812b | |||
2ea014ae46 | |||
9fd345e267 | |||
75aa267875 | |||
7dda6ca773 | |||
1378a9fcbb | |||
4d3672994d | |||
967539c4e1 | |||
f072c217f3 | |||
a60ffd685f | |||
0803c94c79 | |||
b03726903d | |||
afe8cc9a3e | |||
277635c65f | |||
4180bbbdd9 | |||
d683969556 | |||
a62d4d1a40 | |||
aadecf1853 | |||
f172f3d0a0 | |||
08ac900eda | |||
53caf69f3a | |||
3eac2b804d | |||
9b9e7bf722 | |||
7a48a5440e | |||
ef5d0cf3f1 | |||
a5e9ed2d78 | |||
40e937b091 | |||
1bac175c42 | |||
507a8229de | |||
3fd2e8fd31 | |||
f2e9395377 | |||
6669b1c33c | |||
21ce272a65 | |||
2b6a064913 | |||
81a901b386 | |||
cfbc4ac369 | |||
d1b6c8bf1a | |||
491cfa6d4b | |||
a6b11bea0e | |||
a6190c7ddf | |||
4ece622c52 | |||
0e525fc893 | |||
85c9a8b130 | |||
905d8a3b4a | |||
1cc5f3fbd6 | |||
3ad63e04d0 | |||
880a399e4e | |||
592146a648 | |||
e03285b9a9 | |||
fb3d20bfd9 | |||
3363f4f525 | |||
ed300116bd | |||
f912e0b370 | |||
b84655e4de | |||
ece1e01d21 | |||
26877dedbd | |||
7aa1802ec6 | |||
eb9f565aec | |||
04906a5835 | |||
acf7efcff2 | |||
d873d220dc | |||
9ef1653e73 | |||
d1d65344af | |||
a76adc31ab | |||
a2fcbc81c8 | |||
fa51c376c1 | |||
483530f053 | |||
8f34dd2c84 | |||
493dc19d8b | |||
3b64242ffd | |||
280cb7765a | |||
835e68bd76 | |||
92903361d0 | |||
fb937316aa | |||
ae6ebc4106 | |||
0f0dd31a0d | |||
189e61bbe8 | |||
d8f88c340a | |||
2ef5c47f19 | |||
cb4d490fb6 | |||
da281ebf97 | |||
c832efbcb6 | |||
b7b3bc0af0 | |||
4a42c3d43a | |||
624cc0134a | |||
d9d5d5f55d | |||
53ea75dc80 | |||
b1f4c2a7d9 | |||
d87e9cedd2 | |||
32d93d9028 | |||
3d30827798 | |||
b688f14c22 | |||
9e972d3f33 | |||
f5da2ea6b3 | |||
4edd2f2eff | |||
846b884eb5 | |||
3f1918ed2d | |||
1d753366d8 | |||
047f18d113 | |||
26c5b012a7 | |||
4f33600a0f | |||
2077dfb0a6 | |||
1b0e890ddd | |||
eb4e4b08ff | |||
ed00d8eee4 | |||
1bb3614e80 | |||
9bd89318bb | |||
fa122460fd | |||
81ce1dfc62 | |||
53d7129ec3 | |||
bb66a49ec1 | |||
03d6d9672e | |||
9891a75bcd | |||
b011c286aa | |||
fb58a80b0c | |||
9e6f2d593d | |||
2cf0c017e2 | |||
93db87cc07 | |||
dace4e5638 | |||
cd0ab98602 | |||
170298b123 | |||
3d22d2205f | |||
845d8bc1a3 | |||
3f8483eca1 | |||
8e92be073d | |||
57ad547df6 | |||
ca2e6f4a8b | |||
4fc619f9a4 | |||
8e02c65b09 | |||
fe44bf4fde | |||
4b97e4f2df | |||
cad3c25079 | |||
04d0eb6361 | |||
c49fe2e31a | |||
a327714907 | |||
2494f32288 | |||
7de7e48c98 | |||
b18fbeb9ab | |||
bd3e430966 | |||
fe075c3bbd | |||
d22955a1c5 | |||
8679dd543b | |||
b594f94b0c | |||
5c68e117fd | |||
f10514db6b | |||
d5dc15e321 | |||
cfa777d718 | |||
54bc78f7c7 | |||
3b30e9acb9 | |||
77d110de70 | |||
c349c209b0 | |||
19467bd5d5 | |||
d69c74bc8f | |||
e09506c2bb | |||
7b7f319c2f | |||
343eef324b | |||
a798cf2f21 | |||
a9d89cd195 | |||
b98f76ece4 | |||
1f74040f96 | |||
6156260ad4 | |||
774efecd40 | |||
5bb231d8e8 | |||
162fa7b329 | |||
f94e8bc746 | |||
f462a35db3 | |||
1120651daa | |||
3b26bca69a | |||
89d3801a5f | |||
710a442d31 | |||
f7d5cbf5ce | |||
c1144cf277 | |||
9481b95b30 | |||
18a0e54033 | |||
c1b89cb087 | |||
6f4383cd10 | |||
e9db72de72 | |||
827e6eace9 | |||
4d3960c599 | |||
a3d6e9d908 | |||
4e290413d1 | |||
54eb0b215c | |||
6d422c4259 | |||
9d1084cdf8 | |||
cd5811f59d | |||
13cda13ef1 | |||
6ff52fcc94 | |||
ff058547e8 | |||
ded9bd2b4d | |||
8dde86dae7 | |||
0c5227dfc5 | |||
7cdf39d61c | |||
5a23b89087 | |||
7e2d414021 | |||
b91f087736 | |||
136e2ce779 | |||
ed7a537395 | |||
23f3e806e2 | |||
1d6d23b444 | |||
9f6d4ab63f | |||
0dfcc0f511 | |||
90d657c687 | |||
20b3d081e0 | |||
56b6c9a627 | |||
485d2f128f | |||
409c109972 | |||
7156aee723 | |||
f09a304204 | |||
1302db017b | |||
9a5ac6380d | |||
7c8388af2f | |||
0d7cf3074f | |||
3fdca6cf1d | |||
cbc549f355 | |||
099585fa91 | |||
b0c8a14071 | |||
a9e0fb7beb | |||
943787bc0c | |||
0d5ababe55 | |||
2a1f53a07a | |||
7e2305c34d | |||
8000f41de8 | |||
f0a1839548 | |||
76115ae959 | |||
091cfde2a2 | |||
b77ca836b2 | |||
35edb61f9c | |||
a1561af520 | |||
da174b099e | |||
bcbe749d80 | |||
524aad05a0 | |||
ca01ba7c35 | |||
f2ceb71c2b | |||
4feb14ea35 | |||
2830f07324 | |||
abd8daafc3 | |||
489e783872 | |||
10d1fa8b02 | |||
c8bffebfc6 | |||
97f6beb3ae | |||
b80261ba16 | |||
6a114b2c2c | |||
bf29238762 | |||
13d1fb2ca0 | |||
cc1ab5685c | |||
370b3cd8c4 | |||
3a034f843d | |||
2de8e916b2 | |||
6044edfdd9 | |||
836388cd22 | |||
2685a43760 | |||
0eed3ee9c7 | |||
c5e3e89e44 | |||
1f27983505 | |||
146a8c895f | |||
efd5a0cbcd | |||
2968231b60 | |||
ea2238aa53 | |||
d22e1a5f4a | |||
31189ebecf | |||
d42e5a7a9e | |||
e13aa2a96f | |||
ae021ffeab | |||
5a9d89822f | |||
054b0c0e3f | |||
ac07ac3dcf | |||
0195386606 | |||
0026959b1e | |||
450e88d9a9 | |||
a4888634b6 | |||
46a68831c2 | |||
537d573983 | |||
96450e7010 | |||
31e1243eed | |||
0a90eb3d9c | |||
65f46aec36 | |||
37d14caa5b | |||
384474f6fd | |||
17d8592574 | |||
0936ac7840 | |||
704ece6231 | |||
5c6e98127e | |||
8805437c68 | |||
3acf791409 | |||
0ba674a341 | |||
40c33abac7 | |||
bc67317b0b | |||
06e212c66e | |||
7b314ccffd | |||
1d84986ee8 | |||
2ca8a129f7 | |||
126da8c499 | |||
ea110d5047 | |||
b37fad41c6 | |||
74775996db | |||
74426aab66 | |||
690bbb13d4 | |||
871fbed2b0 | |||
85c68d2ae6 | |||
8870611d4d | |||
67af7fc1bf | |||
93bea174e4 | |||
84fc6aabc8 | |||
38c4f5bcb6 | |||
e2af7e3149 | |||
950d75ba43 | |||
e651c99697 | |||
9694628d3f | |||
046582d1a0 | |||
f6f0ea9ae5 | |||
018547cdf3 | |||
d763a64f03 | |||
cefa460a0d | |||
cc5948ad0b | |||
be1943a66d | |||
d9acb47afe | |||
b721d26fb8 | |||
7530c7c67d | |||
824cd4d283 | |||
2e30e7aee6 | |||
3a5a3e22b9 | |||
51bd766ba6 | |||
0ab0d6db07 | |||
a12de614d6 | |||
240abd2788 | |||
e131fcb32f | |||
f88f594e87 | |||
56ef0651f2 | |||
9b9726b800 | |||
b139221f0b | |||
b0ab8a7a8b | |||
ddac589676 | |||
5b380cdaad | |||
cc9adc77fa | |||
2b38f7bcfa | |||
0ceada70b5 | |||
7bf91b403d | |||
bf5c359649 | |||
c41ac44bd1 | |||
e36013d64e | |||
9e48ad3e61 | |||
054e74d04a | |||
5f6319ed3d | |||
2f39622a57 | |||
7801119215 | |||
a6696cae49 | |||
40b52167aa | |||
814e3d53a3 | |||
6bd46e0470 | |||
d5cda13f6f | |||
bfc8e6a9cd | |||
73cba130c3 | |||
c09bc44aa4 | |||
b907e3f469 | |||
8c3bed09e4 | |||
4c99b82bb7 | |||
a6d72761b9 | |||
6c504d30cf | |||
1c814a451b | |||
daafc125c3 | |||
63f680bdc1 | |||
e88a327957 | |||
223c71bc68 | |||
14a04fd200 | |||
dc85511fe9 | |||
d0b8d3f585 | |||
97652917c9 | |||
c171a62f93 | |||
c7c28e7fa2 | |||
79a17788f2 | |||
9f0a2d2fb6 | |||
66f6ce9bd2 | |||
e5dfe7b816 | |||
6efb17be64 | |||
0310b30446 | |||
863cdf3d7f | |||
e51bb2555e | |||
9e0157d679 | |||
3e91eb4fc1 | |||
caf811c23a | |||
de116c9e5a | |||
eef38b0557 | |||
0057899476 | |||
0148e6e27e | |||
c6af859f9d | |||
01f0761ca8 | |||
d7770846aa | |||
0e76ba6464 | |||
fcb44ec845 | |||
cec8195e5e | |||
6c0eb32d75 | |||
9ae5f1d583 | |||
3b60bb9420 | |||
db50c35ad6 | |||
4f05d4e254 | |||
c5a17b217d | |||
fdccb0c5a9 | |||
ccbafef55a | |||
c594134317 | |||
11cfaf44ee | |||
a34678cbcc | |||
26fd99823c | |||
42c305c79b | |||
9585506644 | |||
4317ae0f75 | |||
6e6c79f5ea | |||
8da0014091 | |||
60d292b3ea | |||
5ce9b737cf | |||
7bcb494044 | |||
13758eb08e | |||
b9c26cb6f8 | |||
e3dd0a319a | |||
80b7ceea2d | |||
eabcce156a | |||
615beb7d02 | |||
78e6c9355c | |||
20129ea341 | |||
388f950559 | |||
96c93714a4 | |||
252eb44959 | |||
0442e2ae4f | |||
31dae22428 | |||
1d5c7adb61 | |||
c138442a95 | |||
a672ab1234 | |||
c550cc01be | |||
7db71589d8 | |||
910cf77d97 | |||
807fe825d6 | |||
ff46c9a4a7 | |||
a42fbc9c6c | |||
74d950ab2d | |||
9049baf730 | |||
050a165a82 | |||
1428b85a34 | |||
e4f8a6ed40 | |||
5a5b42cb67 | |||
e62553eca6 | |||
0846c1dd5b | |||
774e88241a | |||
03a04a51b6 | |||
103e74be03 | |||
129cc61759 | |||
70073e1b69 | |||
c94c1a1e70 | |||
07026b03ae | |||
5a6d293a5f | |||
d51d6648e0 | |||
f521da8606 | |||
b64d486925 | |||
7f1f1c1e65 | |||
2dc0918926 | |||
37d412108a | |||
f03af416eb | |||
82066af0e0 | |||
9c18afb178 | |||
04c6cb50d7 | |||
382784526c | |||
a91496884c | |||
7cdec03dcb | |||
3e5e4b8375 | |||
f8b944f325 | |||
c7e7878d9e | |||
5717dd6345 | |||
2fe3b5c68d | |||
db88081fd7 | |||
1230c01646 | |||
8142dd27eb | |||
19279b208a | |||
9619c359c1 | |||
6b948abc2d | |||
2c7391602a | |||
fd0fccda46 | |||
1164413bd2 | |||
7e1e038ecd | |||
2a8b0aed56 | |||
c856dec6dd | |||
53bb235ff1 | |||
29ac760f0e | |||
7836af6423 | |||
1af9c6ea55 | |||
8c619d3350 | |||
0155d5ab69 | |||
8252b629f5 | |||
494661c0e7 | |||
5b652abd25 | |||
a3e68d7f7d | |||
7cc19d2614 | |||
318d0e389b | |||
8dbe3abcdb | |||
649d775cd3 | |||
a941061a29 | |||
100b7d4543 | |||
1eb8a25432 | |||
9b6f8b3386 | |||
cc1bb004f2 | |||
ab6a6b730d | |||
3d928c49a0 | |||
8fe70f2e39 | |||
862686aeef | |||
2fa54cdfb1 | |||
d987a9abb9 | |||
d37c142d36 | |||
35768cbfbb | |||
5494aae1ba | |||
18ba904d6c | |||
2cd969d643 | |||
0c9d4dc4c0 | |||
ef3b2ec9fd | |||
1fb402e838 | |||
eae987e7f1 | |||
93906dd022 | |||
7e717c564d | |||
14b60c210a | |||
8dae0afa30 | |||
95bf2c78c2 | |||
8c10e5395c | |||
69de0b9f31 | |||
22ae510dca | |||
5fdf3912c8 | |||
b50aec424f | |||
4a1033b6dc | |||
68e178d41b | |||
e83ceda41c | |||
b307adb005 | |||
0a2a304a2b | |||
80477709aa | |||
706c59d069 | |||
6541c40818 | |||
04f64c0f67 | |||
af669103c2 | |||
40d9641150 | |||
9cf2770440 | |||
616bc9a410 | |||
53abbb750b | |||
ec3cbbf559 | |||
8a3cbc1c6a | |||
8a4cda6647 | |||
2d513b96d3 | |||
6a0d7b4492 | |||
755df7c3ee | |||
ddb602196a | |||
0a5f486a9b | |||
574052dcb8 | |||
eaba256c51 | |||
7eab96120f | |||
50f69a76f4 |
3
.VERSION
Normal file
@ -0,0 +1,3 @@
|
||||
COMMIT: $Format:%H$
|
||||
REFS: $Format:%D$
|
||||
DATE: $Format:%ci$
|
1
.ci
Submodule
12
.ci-local/defaults.set
Normal file
@ -0,0 +1,12 @@
|
||||
MODULES=calc asyn
|
||||
|
||||
# EPICS Base
|
||||
BASE_DIRNAME=base
|
||||
BASE_REPONAME=epics-base
|
||||
BASE_REPOOWNER=epics-base
|
||||
BASE_VARNAME=EPICS_BASE
|
||||
BASE_RECURSIVE=no
|
||||
|
||||
ASYN_REPOOWNER=epics-modules
|
||||
|
||||
CALC_REPOOWNER=epics-modules
|
7
.cvsignore
Normal file
@ -0,0 +1,7 @@
|
||||
O.*
|
||||
*~
|
||||
bin
|
||||
lib
|
||||
dbd
|
||||
include
|
||||
*.pdf
|
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
GNUmakefile export-ignore
|
||||
.VERSION export-subst
|
164
.github/workflows/ci-scripts-build.yml
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# This is YAML - indentation levels are crucial
|
||||
|
||||
# Workflow name, shared by all branches
|
||||
|
||||
name: StreamDevice
|
||||
|
||||
# Trigger on pushes and PRs to any branch
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/*'
|
||||
- '.gitattributes'
|
||||
- '.gitignore'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/*'
|
||||
- '.gitattributes'
|
||||
- '.gitignore'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
env:
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||
|
||||
jobs:
|
||||
native:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
BASE: ${{ matrix.base }}
|
||||
WINE: ${{ matrix.wine }}
|
||||
RTEMS: ${{ matrix.rtems }}
|
||||
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
||||
TEST: ${{ matrix.test }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
VV: "1"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Native Linux (WError)
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
extra: "CMD_CPPFLAGS=-Werror"
|
||||
pcre: apt
|
||||
|
||||
- name: Cross mingw64 DLL
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
wine: "64"
|
||||
pcre: no
|
||||
|
||||
- name: Cross mingw64 static
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
base: "7.0"
|
||||
wine: "64"
|
||||
pcre: no
|
||||
|
||||
- name: RTEMS 4.10
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
rtems: "4.10"
|
||||
rtems_target: RTEMS-pc386-qemu
|
||||
pcre: no
|
||||
|
||||
- name: Native Linux with clang
|
||||
os: ubuntu-20.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
pcre: apt
|
||||
|
||||
- name: Native Linux with 3.15
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "3.15"
|
||||
pcre: apt
|
||||
|
||||
- name: Native Linux with 3.14
|
||||
os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "3.14"
|
||||
pcre: apt
|
||||
|
||||
- name: OSX
|
||||
os: macos-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
pcre: no
|
||||
|
||||
- name: vs2019 DLL
|
||||
os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: debug
|
||||
base: "7.0"
|
||||
pcre: no
|
||||
extra: "CMD_CFLAGS=-analysis CMD_CXXFLAGS=-analysis"
|
||||
|
||||
- name: vs2019 static
|
||||
os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: static-debug
|
||||
base: "7.0"
|
||||
pcre: no
|
||||
extra: "CMD_CFLAGS=-analysis CMD_CXXFLAGS=-analysis"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
- name: "apt-get install"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||
if: runner.os == 'Linux'
|
||||
|
||||
- name: Reset RELEASE
|
||||
shell: bash
|
||||
# 'make' on Mac doesn't understand "undefine PCRE"
|
||||
# so replace the whole file
|
||||
run: |
|
||||
cat <<EOF > configure/RELEASE
|
||||
-include \$(TOP)/../RELEASE.local
|
||||
-include \$(TOP)/../RELEASE.\$(EPICS_HOST_ARCH).local
|
||||
-include \$(TOP)/configure/RELEASE.local
|
||||
EOF
|
||||
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
|
||||
- name: "apt-get install pcre"
|
||||
if: matrix.pcre == 'apt'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y install libpcre3-dev
|
||||
cat <<EOF >> configure/CONFIG_SITE.local
|
||||
PCRE_INCLUDE=/usr/include
|
||||
PCRE_LIB=/usr/lib
|
||||
EOF
|
||||
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
O.*
|
||||
*~
|
||||
bin
|
||||
lib
|
||||
dbd
|
||||
include
|
||||
*.pdf
|
||||
*.*log
|
||||
StreamVersion.h
|
||||
*.local
|
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule ".ci"]
|
||||
path = .ci
|
||||
url = https://github.com/epics-base/ci-scripts.git
|
303
CHANGELOG.md
Normal file
@ -0,0 +1,303 @@
|
||||
# Changelog
|
||||
|
||||
## Changes in release 2.8.20
|
||||
|
||||
Fix missing initialization of `inTerminator` and `outTerminator`.
|
||||
Thanks to Krisztián Löki.
|
||||
|
||||
New checksums `%<lrc>` and `%<hexlrc>`.
|
||||
Thanks to Marcio Paduan Donadio.
|
||||
|
||||
Make timestamp output in error and debug messages optional with new
|
||||
iocsh variable `streamMsgTimeStamped`. Default is 1.
|
||||
|
||||
Reduce number of duplicate error messages. Dead time for repeated messages
|
||||
is configurable with new iocsh variable `streamErrorDeadTime`.
|
||||
Thanks to Dominic Oram.
|
||||
|
||||
Shifted some noisy debug messages to `streamDebug` level 2.
|
||||
|
||||
In `STREAM_PROTOCOL_PATH`, allow both `:` and `;` separators on all
|
||||
operating systems to make startup scripts OS independent.
|
||||
On Windows however, an initial single letter followed by a `:` is detected
|
||||
as a drive letter. Thus single letter directories must be separated with
|
||||
`;` or followed by `\` or `/` on Windows.
|
||||
|
||||
Allow absolute path protocol files. Those will not use
|
||||
`STREAM_PROTOCOL_PATH`.
|
||||
Changed the default search path from `"."` to `NULL`.
|
||||
|
||||
Only poll for `I/O Intr` records while `interruptAccept` is true,
|
||||
in particular not between `iocPause` and `iocRun`.
|
||||
|
||||
Added this change log and a document about contributing to StreamDevice.
|
||||
|
||||
## Changes in release 2.8.19
|
||||
|
||||
Make colorization of error and debug messages optional with new
|
||||
iocsh variable `streamDebugColored`. Defaults to 1 when output is a tty
|
||||
and 0 otherwise.
|
||||
|
||||
## Changes in release 2.8.18
|
||||
|
||||
Another format string fix for VxWorks in checksum converter.
|
||||
|
||||
## Changes in release 2.8.17
|
||||
|
||||
Fix format strings for VxWorks 6.9 in checksum converter.
|
||||
|
||||
Fix some compiler warnings on Windows.
|
||||
|
||||
Fix some missing header files installations.
|
||||
|
||||
## Changes in release 2.8.16
|
||||
|
||||
Drop support of upper level `configure/` directory for improved
|
||||
compatibility with SynApps.
|
||||
|
||||
Fix problem with extra spaces after protocol name in record links.
|
||||
|
||||
Make version string generation more robust.
|
||||
|
||||
## Changes in release 2.8.15
|
||||
|
||||
Do not overwrite `HOST_OPT` flag.
|
||||
|
||||
Fix version string generation for zip downloads.
|
||||
|
||||
On Windows use `;` and `\` in `STREAM_PROTOCOL_PATH`.
|
||||
(Was not the case before due to typo in macro name.)
|
||||
|
||||
Link streamApp with `seq` and `pv` libraries when `SNCSEQ` is defined in
|
||||
RELEASE file.
|
||||
|
||||
## Changes in release 2.8.14
|
||||
|
||||
Fix version string generation from git tags.
|
||||
|
||||
## Changes in release 2.8.13
|
||||
|
||||
Fix bug with integer datatype handling in redirectons.
|
||||
|
||||
## Changes in release 2.8.12
|
||||
|
||||
Apply GPL-3.0.
|
||||
|
||||
## Changes in release 2.8.11
|
||||
|
||||
Fix buffer overrun.
|
||||
Thanks to Garth Brown and Bruce Hill.
|
||||
|
||||
Fix bug in 64 bit data type handling in array records (`aai`, `aao`,
|
||||
`waveform`).
|
||||
Thanks to Andrew Johnson.
|
||||
|
||||
Fix Windows linker problem.
|
||||
Thanks to Freddie Akeroyd.
|
||||
|
||||
Allow `(,)` inside protocol parameters. Limitation: Parenthesis must be in
|
||||
matching pairs. Commas within inner parenthesis are consideres part of the
|
||||
argument. Example: `protocol(arg1, (arg2, still arg 2), arg3)`.
|
||||
|
||||
New checksums `%<brksCryo>`, `%<xor8ff>`, `%<nsum8>`, `%<nsum16>`,
|
||||
`%<nsum32>`, `%<notsum>`.
|
||||
Thanks to Mark Davis.
|
||||
|
||||
Some error message cleanup.
|
||||
|
||||
## Changes in release 2.8.10
|
||||
|
||||
Fixes for Windows / Visual Studio 2010.
|
||||
Thanks to Freddie Akeroyd.
|
||||
|
||||
Fix infinite loop in `I/O Intr` scanned records.
|
||||
|
||||
Enable error messages by default and always show error messages too when
|
||||
debug messages are enabled.
|
||||
|
||||
Make sure any console output from StreamDevice can be redirected.
|
||||
|
||||
Fix some problems when building for old EPICS R3.13.
|
||||
|
||||
## Changes in release 2.8.9
|
||||
|
||||
Leave `asynTraceMask` alone. Before, streamDevice had set `setTraceMask`
|
||||
to 0 initially.
|
||||
|
||||
Link with `sscan` module if `SSCAN` is defined in RELEASE file because the
|
||||
`calc` module may need it.
|
||||
|
||||
Fix in regsub converter: Avoid infinite loop if an empty string is matched.
|
||||
Add support for toupper/tolower to regsub converter.
|
||||
|
||||
Fix build problem observed on MacOS related to clash between `wait()`
|
||||
system function and the StreamDevice `wait` command.
|
||||
|
||||
Allow `%%` in addition to `\%` to escape `%` in protocols (compatibility
|
||||
with `printf`/`scanf`).
|
||||
|
||||
Have separate dbd file for applications without scalcout support built in.
|
||||
|
||||
Improved compatibility with SynApps. (fix of the attempt in 2.8.6)
|
||||
|
||||
## Changes in release 2.8.8
|
||||
|
||||
Fix problem with `in` command hanging forever if it is the the first
|
||||
command of the protocol and the device is offline.
|
||||
|
||||
## Changes in release 2.8.7
|
||||
|
||||
Enable colored error/debug output on Windows.
|
||||
|
||||
Changed error/debug hex output highlight from fat to inverse.
|
||||
|
||||
Fix build problem on Windows.
|
||||
|
||||
## Changes in release 2.8.6
|
||||
|
||||
Improved compatibility with SynApps.
|
||||
|
||||
Fix redirection to records with names not starting with a letter or
|
||||
underscore.
|
||||
|
||||
### Fixes/improvements for `mbbo` device support:
|
||||
|
||||
Use `.MASK` and `.SHFT` fields even if no `xxVL` field is defined
|
||||
(and thus `.VAL` is used instead of `.RVAL`).
|
||||
|
||||
Bugfix: Set `mbbo` to unknown state `0xffff` if in readback no state
|
||||
matches.
|
||||
|
||||
Bugfix: Use defined state alarms when `mbbo` is updated by `@init` handler.
|
||||
|
||||
## Changes in release 2.8.5
|
||||
|
||||
A `"\?"` at the end of an input format now matches an empty string.
|
||||
Used to do so unintendedly in earlier versions but had been changed.
|
||||
|
||||
## Changes in release 2.8.4
|
||||
|
||||
Bugfix: After `@init` had been triggered with "magic value" 2 in `.PROC`
|
||||
field, reset the field to 0.
|
||||
|
||||
## Changes in release 2.8.3
|
||||
|
||||
Increase limits on filename, protocolname, busname in record links.
|
||||
|
||||
Bugfix: Fix typo calcout device support that prevented compiling it.
|
||||
|
||||
## Changes in release 2.8.2
|
||||
|
||||
Bugfix: Fix string termination reading into char array records (`waveform`,
|
||||
`aai`, `aao`, `lsi`, `lso`).
|
||||
|
||||
## Changes in release 2.8.1
|
||||
|
||||
Allow empty parameter list `()` in record links.
|
||||
|
||||
## Changes between 2.7 and 2.8.0
|
||||
|
||||
### Build system
|
||||
|
||||
Drop support for (buggy) cygnus-2.7.2 gcc (as used in some old cygwin
|
||||
version).
|
||||
|
||||
Add standard EPICS App build system (`configure/`).
|
||||
|
||||
Some re-ordering of directories.
|
||||
When upgrading from 2.7 or earlier to 2.8, better start with a fresh
|
||||
source directory to avoid problems with files that have moved.
|
||||
|
||||
### New Features
|
||||
|
||||
Support for 64 bit integers. This affects some conversions (e.g. in `ai`
|
||||
and `ao` records).
|
||||
|
||||
Device support for new record types `int64in`, `int64out`, `lsi` and `lso`
|
||||
added.
|
||||
|
||||
Support for new `INT64` and `UINT64` types in `aai`, `aao` and `waveform`
|
||||
records.
|
||||
|
||||
Allow spaces in protocol parameter list in record link.
|
||||
One space after the opening `(`, before and after the separating `,` and
|
||||
before the closing `)` ignored. More spaces are part of the parameter.
|
||||
|
||||
String format `%s` can now pad with 0-bytes instead of spaces using the
|
||||
`0` flag.
|
||||
|
||||
New checksums `%<cpi>` and `%<leybold>`.
|
||||
|
||||
Properly distinguish beween signed and unsigned integers, e.g. when
|
||||
converting to double.
|
||||
Allow signed enums to do this: `%#{backwards=-1|stop=0|forwards=1}`.
|
||||
|
||||
#### New connection handling
|
||||
|
||||
Run `@init` handler each time the device (re-)connects
|
||||
(as long as asynDriver detects connection changes), also at each `iocRun`
|
||||
(after being paused with `iocPause`), and after each `streamReload`.
|
||||
|
||||
Also run `@init` of a record when the "magic value" 2 is written to the
|
||||
`.PROC` field or when new `streamReinitRecord` shell function is called.
|
||||
|
||||
Trigger monitors when `@init` updates output records (after the intial run
|
||||
in `iocInit`).
|
||||
|
||||
Use `"COMM"` error code in `.STAT` when device is disconnected.
|
||||
|
||||
If write fails because device has disconnected, try to re-connect and re-do
|
||||
write once.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix parser bug when command reference was followed by `}` without `;`.
|
||||
|
||||
Fix potential buffer overrun during `streamReload`.
|
||||
After `streamReload`, properly delete handlers and variables that do not
|
||||
exist any longer.
|
||||
|
||||
Fix for waveforms of unsigned integers.
|
||||
|
||||
Several Windows related fixes and support building shared libraries on
|
||||
Windows.
|
||||
|
||||
Fix C++11 warnings.
|
||||
|
||||
Check formatting of `exec` command for errors.
|
||||
|
||||
Fix bug in `dbior` output.
|
||||
|
||||
Fix BCD `%D` format and allow negative values.
|
||||
|
||||
Fix signed hex and octal formats.
|
||||
|
||||
Fix in regsub: Do not run regsub again on substituted string.
|
||||
|
||||
### Shell functions
|
||||
|
||||
New functions `streamReportRecord` and `streamSetLogfile`.
|
||||
|
||||
Support output redirection to file of stream shell functions
|
||||
and protocol dump via `dbior`.
|
||||
|
||||
### Error and debug output
|
||||
|
||||
Cleanup some debug and error messages.
|
||||
|
||||
Hex bytes in debug/error output are now highlighted.
|
||||
|
||||
`StreamError` can now be set before `iocInit`.
|
||||
|
||||
Avoid repeating error messages.
|
||||
Thanks to Ben Franksen.
|
||||
|
||||
### Documentation
|
||||
|
||||
HTML files converted to HTML 5.
|
||||
|
||||
Update and improve several chapters.
|
||||
|
||||
## Changes in releases up to 2.7.14
|
||||
|
||||
Not available. See git log.
|
81
Contributing.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Contributing to StreamDevice
|
||||
|
||||
Contributions from the EPICS community (and others) are welcome.
|
||||
To ease the integration process, please follow the following guidelines.
|
||||
|
||||
All contributions should be done as a pull request to the git repository
|
||||
https://github.com/paulscherrerinstitute/StreamDevice. Make sure to provide
|
||||
meaningful commit messages (no essay but more than "changes").
|
||||
|
||||
For small modifications, a patch file is sufficient. Send it to me or better
|
||||
create an issue on https://github.com/paulscherrerinstitute/StreamDevice/issues
|
||||
and attach the patch file.
|
||||
|
||||
Justify your change requests. Write a short summary for your pull request
|
||||
to explain what the change is about and what it improves or which bug it
|
||||
fixes. Use the issue system on github to report bugs.
|
||||
|
||||
I reserve the right to accept or reject contributions or to request
|
||||
modifications before I accept them.
|
||||
|
||||
Of course, you may as well report bugs without providing a solution yourself.
|
||||
|
||||
## Code compatibility
|
||||
|
||||
All code must compile for any EPICS release from at least R3.14.12 up to the
|
||||
latest one. Likewise the code must be compatible with any operating system
|
||||
supported by EPICS, like Linux, Windows, MacOS, RTEMS and VxWorks.
|
||||
In particular VxWorks 5 compatibility rules out many modern C++ features.
|
||||
But there are also other platforms that for example do not support C++11, so
|
||||
don't use it.
|
||||
There should also be no compiler warning on any OS.
|
||||
|
||||
Avoid compiler dependent features like #pragmas, assumptions on byte order,
|
||||
type size (in particular the size of pointers and long int) and other
|
||||
non-portable things like the availability of certain header files. Make sure
|
||||
non-portable code parts are enclosed in proper compiler branches and provide
|
||||
working implementations for all architectures.
|
||||
|
||||
Make sure that the code in AsynDriverInterface stays compatible with old
|
||||
and new versions of asyn driver.
|
||||
|
||||
The core of StreamDevice does not depend on EPICS. This is on purpose, to be
|
||||
able to use it in other control system frameworks. Modifications should not
|
||||
add EPICS dependencies except to StreamEpics and AsynDriverInterface, or the
|
||||
new dependency must be in a separate file which can be left out of the build
|
||||
without jeopardizing the main functionality of StreamDevice.
|
||||
|
||||
The code must not depend on external libraries that may not be available on
|
||||
all systems, except if provided as a separate file which can be left out of
|
||||
the build on platforms that do not support the library.
|
||||
|
||||
## Language
|
||||
|
||||
Write in English. That includes all identifiers (variables, functions, ...),
|
||||
comments, documentation and commit messages. Check your spelling.
|
||||
|
||||
## File formats
|
||||
|
||||
All files are in Unix format (\n line terminators). Do not change them to
|
||||
any other format (e.g. Windows with \r\n terminators). Do not add new files in
|
||||
other formats.
|
||||
|
||||
The files must contain only ASCII characters. Do not use any Unicode multi-byte
|
||||
characters (including byte order marks) or any pre-Unicode code page dependent
|
||||
characters (e.g. umlaut), not even in comments. Do not use form feed, vertical
|
||||
tab, or other control characters except newline.
|
||||
|
||||
Indents are 4 spaces. Do not use tabs (except in Makefiles). Make sure your
|
||||
editor is set up accordingly.
|
||||
|
||||
Files must end in a newline and there must be no spaces at the end of lines.
|
||||
Do not add excessive amount of newlines at the end of files.
|
||||
|
||||
Do not add any editor configurations (e.g. for emacs) to the files. Also do
|
||||
not add any configuration files or directories for development environments,
|
||||
editors, etc.
|
||||
|
||||
-------
|
||||
|
||||
Dirk Zimoch <dirk.zimoch@psi.ch>, June 2021
|
||||
|
57
GNUmakefile
Normal file
@ -0,0 +1,57 @@
|
||||
ifeq ($(wildcard /ioc/tools/driver.makefile),)
|
||||
$(info If you are not using the PSI build environment, GNUmakefile can be removed.)
|
||||
include Makefile
|
||||
else
|
||||
include /ioc/tools/driver.makefile
|
||||
EXCLUDE_VERSIONS = 3.13.2
|
||||
PROJECT=stream
|
||||
BUILDCLASSES += vxWorks Linux WIN32
|
||||
|
||||
DOCUDIR = docs
|
||||
|
||||
PCRE=1
|
||||
ASYN=1
|
||||
-include ../src/CONFIG_STREAM
|
||||
-include src/CONFIG_STREAM
|
||||
|
||||
SOURCES += $(RECORDTYPES:%=src/dev%Stream.c)
|
||||
SOURCES += $(FORMATS:%=src/%Converter.cc)
|
||||
SOURCES += $(BUSSES:%=src/%Interface.cc)
|
||||
SOURCES += $(STREAM_SRCS:%=src/%)
|
||||
|
||||
HEADERS += src/devStream.h
|
||||
HEADERS += src/StreamFormat.h
|
||||
HEADERS += src/StreamFormatConverter.h
|
||||
HEADERS += src/StreamBuffer.h
|
||||
HEADERS += src/StreamError.h
|
||||
HEADERS += src/StreamProtocol.h
|
||||
HEADERS += src/StreamBusInterface.h
|
||||
HEADERS += src/StreamCore.h
|
||||
HEADERS += src/MacroMagic.h
|
||||
HEADERS += $(COMMON_DIR)/StreamVersion.h
|
||||
|
||||
CPPFLAGS += -DSTREAM_INTERNAL -I$(COMMON_DIR)
|
||||
|
||||
# Update version string each time anything changes
|
||||
StreamVersion$(OBJ) StreamVersion$(DEP): $(COMMON_DIR)/StreamVersion.h $(filter-out StreamVersion$(OBJ) stream_exportAddress$(OBJ),$(LIBOBJS) $(LIBRARY_OBJS))
|
||||
|
||||
$(COMMON_DIR)/StreamVersion.h: $(filter-out StreamVersion.h,$(notdir $(SOURCES) $(HEADERS)))
|
||||
@echo Creating $@
|
||||
$(PERL) ../src/makeStreamVersion.pl $@
|
||||
|
||||
StreamCore$(OBJ) StreamCore$(DEP): streamReferences
|
||||
streamReferences:
|
||||
$(PERL) ../src/makeref.pl Interface $(BUSSES) > $@
|
||||
$(PERL) ../src/makeref.pl Converter $(FORMATS) >> $@
|
||||
|
||||
export DBDFILES = streamSup.dbd
|
||||
streamSup.dbd:
|
||||
@echo Creating $@ from $(RECORDTYPES)
|
||||
$(PERL) ../src/makedbd.pl $(RECORDTYPES) > $@
|
||||
ifdef BASE_3_14
|
||||
ifdef ASYN
|
||||
echo "registrar(AsynDriverInterfaceRegistrar)" >> $@
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
674
LICENSE
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
165
LICENSE.LESSER
Normal file
@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
82
Makefile
@ -1,54 +1,38 @@
|
||||
include /ioc/tools/driver.makefile
|
||||
EXCLUDE_VERSIONS = 3.13.2
|
||||
PROJECT=stream2
|
||||
BUILDCLASSES += Linux
|
||||
##########################################################################
|
||||
# This is an EPICS Makefile for StreamDevice.
|
||||
# Normally it should not be necessary to modify this file.
|
||||
# All configuration can be done in CONFIG_STREAM
|
||||
#
|
||||
# (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
#
|
||||
# This file is part of StreamDevice.
|
||||
#
|
||||
# StreamDevice is free software: You can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# StreamDevice is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
#########################################################################/
|
||||
|
||||
DOCUDIR = doc
|
||||
TOP = .
|
||||
DIRS = configure
|
||||
src_DEPEND_DIRS := $(DIRS)
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DBDS = stream.dbd
|
||||
DIRS += src
|
||||
DIRS += streamApp
|
||||
streamApp_DEPEND_DIRS = src
|
||||
|
||||
BUSSES += AsynDriver
|
||||
FORMATS += Enum
|
||||
FORMATS += BCD
|
||||
FORMATS += Raw
|
||||
FORMATS += Binary
|
||||
FORMATS += Checksum
|
||||
FORMATS += Regexp
|
||||
FORMATS += Exponential
|
||||
RECORDTYPES += aai aao
|
||||
RECORDTYPES += ao ai
|
||||
RECORDTYPES += bo bi
|
||||
RECORDTYPES += mbbo mbbi
|
||||
RECORDTYPES += mbboDirect mbbiDirect
|
||||
RECORDTYPES += longout longin
|
||||
RECORDTYPES += stringout stringin
|
||||
RECORDTYPES += waveform
|
||||
RECORDTYPES += calcout
|
||||
include $(CONFIG)/RULES_TOP
|
||||
|
||||
SOURCES += $(RECORDTYPES:%=src/dev%Stream.c)
|
||||
SOURCES += $(FORMATS:%=src/%Converter.cc)
|
||||
SOURCES += $(BUSSES:%=src/%Interface.cc)
|
||||
SOURCES += $(wildcard src/Stream*.cc)
|
||||
SOURCES += src/StreamVersion.c
|
||||
docs/stream.pdf: docs/*.html docs/*.css docs/*.png
|
||||
cd docs; makepdf
|
||||
|
||||
ifeq (${EPICS_BASETYPE},3.13)
|
||||
USR_INCLUDES += -include $(INSTALL_INCLUDE)/compat3_13.h
|
||||
endif
|
||||
|
||||
StreamCore.o: streamReferences
|
||||
|
||||
streamReferences:
|
||||
@for i in $(BUSSES); \
|
||||
do echo "extern void* ref_$${i}Interface;"; \
|
||||
echo "void* p$$i = ref_$${i}Interface;"; \
|
||||
done > $@
|
||||
@for i in $(FORMATS); \
|
||||
do echo "extern void* ref_$${i}Converter;"; \
|
||||
echo "void* p$$i = ref_$${i}Converter;"; \
|
||||
done >> $@
|
||||
|
||||
stream.dbd:
|
||||
@for r in $(RECORDTYPES); \
|
||||
do echo "device($$r,INST_IO,dev$${r}Stream,\"stream\")"; \
|
||||
done > $@
|
||||
@echo "driver(stream)" >> $@
|
||||
pdf: docs/stream.pdf
|
||||
|
35
README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# StreamDevice
|
||||
|
||||
_StreamDevice_ is a generic [EPICS](https://epics.anl.gov/)
|
||||
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.
|
||||
|
||||
For a full documentation see
|
||||
https://paulscherrerinstitute.github.io/StreamDevice.
|
||||
|
||||
## Licensing
|
||||
|
||||
StreamDevice is free software: You can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
StreamDevice is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
12
config/CONFIG_APP
Normal file
@ -0,0 +1,12 @@
|
||||
#CONFIG_APP
|
||||
include $(TOP)/configure/RELEASE
|
||||
-include $(TOP)/configure/RELEASE.$(HOST_ARCH)
|
||||
-include $(EPICS_BASE)/config/CONFIG
|
||||
INSTALL_LOCATION = $(TOP)
|
||||
ifdef INSTALL_LOCATION_APP
|
||||
INSTALL_LOCATION = $(INSTALL_LOCATION_APP)
|
||||
endif
|
||||
|
||||
ifdef T_A
|
||||
-include $(TOP)/config/O.$(T_A)/CONFIG_APP_INCLUDE
|
||||
endif
|
30
config/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
##########################################################################
|
||||
# This is an EPICS Makefile for StreamDevice.
|
||||
# Normally it should not be necessary to modify this file.
|
||||
# All configuration can be done in CONFIG_STREAM
|
||||
#
|
||||
# (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
#
|
||||
# This file is part of StreamDevice.
|
||||
#
|
||||
# StreamDevice is free software: You can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# StreamDevice is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
#########################################################################/
|
||||
|
||||
TOP=..
|
||||
include $(TOP)/config/CONFIG_APP
|
||||
ifneq ($(wildcard $(EPICS_BASE)/config),)
|
||||
include $(EPICS_BASE)/config/RULES_ARCHS
|
||||
else
|
||||
build install clean realclean:
|
||||
endif
|
20
config/Makefile.Host
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# $Id: Makefile.Host,v 1.1.1.1 2000/04/05 07:33:44 janousch Exp $
|
||||
#
|
||||
|
||||
TOP=../..
|
||||
include $(TOP)/config/CONFIG_APP
|
||||
|
||||
TARGETS = CONFIG_APP_INCLUDE
|
||||
|
||||
include $(TOP)/config/RULES.Host
|
||||
|
||||
inc:: $(TARGETS)
|
||||
|
||||
ifeq ($(wildcard $(TOP)/configure/RELEASE.$(HOST_ARCH)),$(TOP)/configure/RELEASE.$(HOST_ARCH))
|
||||
CONFIG_APP_INCLUDE: $(TOP)/configure/RELEASE.$(HOST_ARCH)
|
||||
endif
|
||||
|
||||
CONFIG_APP_INCLUDE: $(TOP)/configure/RELEASE $(TOP)/config/CONFIG_APP
|
||||
$(RM) $@
|
||||
@$(PERL) $(TOP)/config/makeConfigAppInclude.pl $(T_A) $@ $(TOP)
|
15
config/Makefile.Vx
Normal file
@ -0,0 +1,15 @@
|
||||
#
|
||||
# Makefile.Vx,v 1.1.2.3 2001/09/14 19:39:15 anj Exp
|
||||
#
|
||||
|
||||
TOP=../..
|
||||
include $(TOP)/config/CONFIG_APP
|
||||
|
||||
TARGETS = CONFIG_APP_INCLUDE
|
||||
|
||||
include $(EPICS_BASE)/config/RULES.Vx
|
||||
|
||||
inc:: $(TARGETS)
|
||||
|
||||
CONFIG_APP_INCLUDE: $(wildcard $(TOP)/config/RELEASE*) $(TOP)/config/CONFIG_APP
|
||||
$(PERL) $(TOP)/config/convertRelease.pl -h $(HOST_ARCH) $@
|
3
config/RULES.Host
Normal file
@ -0,0 +1,3 @@
|
||||
#RULES.Host
|
||||
|
||||
include $(EPICS_BASE)/config/RULES.Host
|
@ -1,12 +1,14 @@
|
||||
MUNCH = $(PERL) $(INSTALL_LOCATION)/bin/$(HOST_ARCH)/munch.pl
|
||||
|
||||
# The original 3.13.10 munching rule does not really work well
|
||||
|
||||
# This is the munch.pl taken from EPICS base 3.14.8.2
|
||||
MUNCH = $(PERL) ../../config/munch.pl
|
||||
|
||||
build:: $(LIBNAME).munch
|
||||
|
||||
buildInstall:: $(INSTALL_BIN)/$(LIBNAME).munch
|
||||
|
||||
%.munch: %
|
||||
@echo "Munching $<"
|
||||
$(RM) $*_ctct.o $*_ctdt.c
|
||||
$(NM) $< | $(MUNCH) > $*_ctdt.c
|
||||
$(GCC) -traditional $(CFLAGS) -fdollars-in-identifiers -c $(SOURCE_FLAG) $*_ctdt.c
|
2
config/RULES_ARCHS
Normal file
@ -0,0 +1,2 @@
|
||||
#RULES_ARCHS
|
||||
include $(EPICS_BASE)/config/RULES_ARCHS
|
2
config/RULES_DIRS
Normal file
@ -0,0 +1,2 @@
|
||||
#RULES_DIRS
|
||||
include $(EPICS_BASE)/config/RULES_DIRS
|
186
config/convertRelease.pl
Normal file
@ -0,0 +1,186 @@
|
||||
eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
|
||||
if $running_under_some_shell; # convertRelease.pl
|
||||
#
|
||||
# convertRelease.pl,v 1.1.2.1 2001/09/14 19:39:15 anj Exp
|
||||
#
|
||||
# Parse config/RELEASE file(s) and generate a derived output file.
|
||||
#
|
||||
# This tool replaces makeConfigAppInclude.pl and makeIocCdCommands.pl
|
||||
# and adds consistency checks for RELEASE files.
|
||||
#
|
||||
|
||||
use Cwd;
|
||||
use Getopt::Std;
|
||||
|
||||
$cwd = cwd();
|
||||
$cwd =~ s/\/tmp_mnt//; # hack for sun4
|
||||
$cwd =~ s/\\/\//g; # hack for win32
|
||||
|
||||
getopt "aht";
|
||||
|
||||
if ($opt_a) {
|
||||
$arch = $opt_a;
|
||||
} else { # Look for O.<arch> in current path
|
||||
$_ = $cwd;
|
||||
($arch) = /.*\/O.([\w-]+)$/;
|
||||
}
|
||||
|
||||
$hostarch = $arch;
|
||||
$hostarch = $opt_h if ($opt_h);
|
||||
|
||||
if ($opt_t) {
|
||||
$top = $opt_t;
|
||||
} else { # Find $top from current path
|
||||
$top = $cwd;
|
||||
$top =~ s/\/iocBoot.*//;
|
||||
$top =~ s/\/config\/O\..*//;
|
||||
}
|
||||
|
||||
unless (@ARGV == 1) {
|
||||
print "Usage: convertRelease.pl [-a arch] [-h hostarch] [-t top] outfile\n";
|
||||
print " where outfile is be one of:\n";
|
||||
print "\tcheckRelease - checks consistency with support apps\n";
|
||||
print "\tcdCommands - generate cd path strings for IOC use\n";
|
||||
print "\tCONFIG_APP_INCLUDE - additional build variables\n";
|
||||
exit 2;
|
||||
}
|
||||
$outfile = $ARGV[0];
|
||||
|
||||
# TOP refers to this application
|
||||
%macros = (TOP => $top);
|
||||
@apps = (TOP); # Provides the order of apps in RELEASE file
|
||||
|
||||
# Read the RELEASE file(s)
|
||||
$relfile = "$top/configure/RELEASE";
|
||||
die "Can't find configure/RELEASE file" unless (-r $relfile);
|
||||
&readRelease($relfile, \%macros, \@apps);
|
||||
|
||||
if ($hostarch) {
|
||||
$relfile .= ".$hostarch";
|
||||
&readRelease($relfile, \%macros, \@apps) if (-r $relfile);
|
||||
}
|
||||
|
||||
# This is a perl switch statement:
|
||||
for ($outfile) {
|
||||
/CONFIG_APP_INCLUDE/ and do { &configAppInclude; last; };
|
||||
/cdCommands/ and do { &cdCommands; last; };
|
||||
/checkRelease/ and do { &checkRelease; last; };
|
||||
die "Output file type \'$outfile\' not supported";
|
||||
}
|
||||
|
||||
sub readRelease {
|
||||
my ($file, $Rmacros, $Rapps) = @_;
|
||||
# $Rmacros is a reference to a hash, $Rapps a ref to an array
|
||||
my ($pre, $macro, $post, $path);
|
||||
local *IN;
|
||||
open(IN, $file) or die "Can't open $file: $!\n";
|
||||
while (<IN>) {
|
||||
chomp;
|
||||
s/\s*#.*$//; # Remove trailing comments
|
||||
next if /^\s*$/; # Skip blank lines
|
||||
|
||||
# Expand all macros in the line:
|
||||
while (($pre,$macro,$post) = /(.*)\$\((\w+)\)(.*)/, $macro ne "") {
|
||||
$_ = $pre . $Rmacros->{$macro} . $post;
|
||||
}
|
||||
|
||||
# Handle "<macro> = <path>"
|
||||
($macro, $path) = /^\s*(\w+)\s*=\s*(.*)/;
|
||||
if ($macro ne "") {
|
||||
$Rmacros->{$macro} = $path;
|
||||
push @$Rapps, $macro;
|
||||
next;
|
||||
}
|
||||
# Handle "include <path>" syntax
|
||||
($path) = /^\s*include\s+(.*)/;
|
||||
&readRelease($path, $Rmacros, $Rapps) if (-r $path);
|
||||
}
|
||||
close IN;
|
||||
}
|
||||
|
||||
sub configAppInclude {
|
||||
@includes = grep !/^(TOP|TEMPLATE_TOP)$/, @apps;
|
||||
|
||||
unlink($outfile);
|
||||
open(OUT,">$outfile") or die "$! creating $outfile";
|
||||
print OUT "# Do not modify this file, changes made here will\n";
|
||||
print OUT "# be lost when the application is next rebuilt.\n\n";
|
||||
|
||||
if ($arch) {
|
||||
foreach $app (@includes) {
|
||||
$path = $macros{$app};
|
||||
next unless (-d "$path/bin/$arch");
|
||||
print OUT "${app}_BIN = \$($app)/bin/$arch\n";
|
||||
}
|
||||
foreach $app (@includes) {
|
||||
$path = $macros{$app};
|
||||
next unless (-d "$path/lib/$arch");
|
||||
print OUT "${app}_LIB = \$($app)/lib/$arch\n";
|
||||
}
|
||||
}
|
||||
foreach $app (@includes) {
|
||||
$path = $macros{$app};
|
||||
next unless (-d "$path/include");
|
||||
print OUT "EPICS_INCLUDES += -I\$($app)/include\n";
|
||||
}
|
||||
foreach $app (@includes) {
|
||||
$path = $macros{$app};
|
||||
next unless (-d "$path/dbd");
|
||||
print OUT "EPICS_DBDFLAGS += -I \$($app)/dbd\n";
|
||||
}
|
||||
close OUT;
|
||||
}
|
||||
|
||||
sub cdCommands {
|
||||
die "Architecture not set (use -a option)" unless ($arch);
|
||||
@includes = grep !/^TEMPLATE_TOP$/, @apps;
|
||||
|
||||
# if -t <top> was given, substitute it in the startup path
|
||||
$startup = $cwd;
|
||||
$startup =~ s/.*(\/iocBoot\/.*)/$top$1/ if ($opt_t);
|
||||
|
||||
unlink($outfile);
|
||||
open(OUT,">$outfile") or die "$! creating $outfile";
|
||||
print OUT "startup = \"$startup\"\n";
|
||||
print OUT "appbin = \"$top/bin/$arch\"\n"; # compatibility with R3.13.1
|
||||
|
||||
foreach $app (@includes) {
|
||||
$path = $macros{$app};
|
||||
$lcapp = lc($app);
|
||||
print OUT "$lcapp = \"$path\"\n" if (-d $path);
|
||||
print OUT "${lcapp}bin = \"$path/bin/$arch\"\n" if (-d "$path/bin/$arch");
|
||||
}
|
||||
close OUT;
|
||||
}
|
||||
|
||||
sub checkRelease {
|
||||
$status = 0;
|
||||
delete $macros{TOP};
|
||||
delete $macros{TEMPLATE_TOP};
|
||||
|
||||
while (($app, $path) = each %macros) {
|
||||
%check = (TOP => $path);
|
||||
@order = ();
|
||||
$relfile = "$path/config/RELEASE";
|
||||
&readRelease($relfile, \%check, \@order) if (-r $relfile);
|
||||
if ($hostarch) {
|
||||
$relfile .= ".$hostarch";
|
||||
&readRelease($relfile, \%check, \@order) if (-r $relfile);
|
||||
}
|
||||
delete $check{TOP};
|
||||
|
||||
while (($parent, $ppath) = each %check) {
|
||||
if (exists $macros{$parent} && ($macros{$parent} ne $ppath)) {
|
||||
print "\n" unless ($status);
|
||||
print "Definition of $parent conflicts with $app support.\n";
|
||||
print "In this application config/RELEASE defines\n";
|
||||
print "\t$parent = $macros{$parent}\n";
|
||||
print "but $app at $path has\n";
|
||||
print "\t$parent = $ppath\n";
|
||||
$status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
print "\n" if ($status);
|
||||
exit $status;
|
||||
}
|
62
config/makeConfigAppInclude.pl
Normal file
@ -0,0 +1,62 @@
|
||||
# $Id: makeConfigAppInclude.pl,v 1.1.1.1 2000/04/05 07:33:44 janousch Exp $
|
||||
|
||||
eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
|
||||
if $running_under_some_shell; # makeConfigAppInclude.pl
|
||||
|
||||
use Cwd;
|
||||
|
||||
$arch = $ARGV[0];
|
||||
$outfile = $ARGV[1];
|
||||
$top = $ARGV[2];
|
||||
|
||||
unlink("${outfile}");
|
||||
open(OUT,">${outfile}") or die "$! opening ${outfile}";
|
||||
print OUT "#Do not modify this file.\n";
|
||||
print OUT "#This file is created during the build.\n";
|
||||
|
||||
@files =();
|
||||
push(@files,"$top/config/RELEASE");
|
||||
push(@files,"$top/config/RELEASE.${arch}");
|
||||
foreach $file (@files) {
|
||||
if (-r "$file") {
|
||||
open(IN, "$file") or die "Cannot open $file\n";
|
||||
while ($line = <IN>) {
|
||||
next if ( $line =~ /\s*#/ );
|
||||
chomp($line);
|
||||
$_ = $line;
|
||||
#the following looks for
|
||||
# prefix = $(macro)post
|
||||
($prefix,$macro,$post) = /(.*)\s*=\s*\$\((.*)\)(.*)/;
|
||||
if ($macro eq "") { # true if no macro is present
|
||||
# the following looks for
|
||||
# prefix = post
|
||||
($prefix,$post) = /(.*)\s*=\s*(.*)/;
|
||||
} else {
|
||||
$base = $applications{$macro};
|
||||
if ($base eq "") {
|
||||
#print "error: $macro was not previously defined\n";
|
||||
} else {
|
||||
$post = $base . $post;
|
||||
}
|
||||
}
|
||||
$applications{$prefix} = $post;
|
||||
if ( -d "$post") { #check that directory exists
|
||||
print OUT "\n";
|
||||
if ( -d "$post/bin/$arch") { #check that directory exists
|
||||
print OUT "${prefix}_BIN = $post/bin/${arch}\n";
|
||||
}
|
||||
if ( -d "$post/lib/$arch") { #check that directory exists
|
||||
print OUT "${prefix}_LIB = $post/lib/${arch}\n";
|
||||
}
|
||||
if ( -d "$post/include") { #check that directory exists
|
||||
print OUT "EPICS_INCLUDES += -I$post/include\n";
|
||||
}
|
||||
if ( -d "$post/dbd") { #check that directory exists
|
||||
print OUT "EPICS_DBDFLAGS += -I $post/dbd\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
}
|
||||
}
|
||||
close OUT;
|
29
configure/CONFIG
Normal file
@ -0,0 +1,29 @@
|
||||
# CONFIG - Load build configuration data
|
||||
#
|
||||
# Do not make changes to this file!
|
||||
|
||||
# Allow user to override where the build rules come from
|
||||
RULES = $(EPICS_BASE)
|
||||
|
||||
# RELEASE files point to other application tops
|
||||
include $(TOP)/configure/RELEASE
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
CONFIG = $(RULES)/configure
|
||||
include $(CONFIG)/CONFIG
|
||||
|
||||
# Override the Base definition:
|
||||
INSTALL_LOCATION = $(TOP)
|
||||
|
||||
# CONFIG_SITE files contain other build configuration settings
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
40
configure/CONFIG_SITE
Normal file
@ -0,0 +1,40 @@
|
||||
# CONFIG_SITE
|
||||
|
||||
-include $(SUPPORT)/configure/CONFIG_SITE
|
||||
|
||||
# Make any application-specific changes to the EPICS build
|
||||
# configuration variables in this file.
|
||||
#
|
||||
# Host/target specific settings can be specified in files named
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications pointed to by the RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
||||
# continue building even if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
|
||||
# Set this when you only want to compile this application
|
||||
# for a subset of the cross-compiled target architectures
|
||||
# that Base is built for.
|
||||
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32
|
||||
|
||||
# To install files into a location other than $(TOP) define
|
||||
# INSTALL_LOCATION here.
|
||||
#INSTALL_LOCATION=</absolute/path/to/install/top>
|
||||
|
||||
# Set this when the IOC and build host use different paths
|
||||
# to the install location. This may be needed to boot from
|
||||
# a Microsoft FTP server say, or on some NFS configurations.
|
||||
#IOCS_APPL_TOP = </IOC's/absolute/path/to/install/top>
|
||||
|
||||
# These allow developers to override the CONFIG_SITE variable
|
||||
# settings without having to modify the configure/CONFIG_SITE
|
||||
# file itself.
|
||||
-include $(TOP)/../CONFIG_SITE.local
|
||||
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
11
configure/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# Makefile
|
||||
|
||||
TOP=..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
31
configure/RELEASE
Normal file
@ -0,0 +1,31 @@
|
||||
#RELEASE Location of external products
|
||||
# Run "gnumake clean uninstall install" in the application
|
||||
# top directory each time this file is changed.
|
||||
#
|
||||
# NOTE: The build does not check dependencies on files
|
||||
# external to this application. Thus you should run
|
||||
# "gnumake clean uninstall install" in the top directory
|
||||
# each time EPICS_BASE, SNCSEQ, or any other external
|
||||
# module defined in the RELEASE file is rebuilt.
|
||||
|
||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
||||
|
||||
# If you don't want to install into $(TOP) then
|
||||
# define INSTALL_LOCATION_APP here
|
||||
#INSTALL_LOCATION_APP=<fullpathname>
|
||||
|
||||
SUPPORT=$(TOP)/..
|
||||
-include $(TOP)/../configure/SUPPORT.$(EPICS_HOST_ARCH)
|
||||
|
||||
ASYN=$(SUPPORT)/asyn4-36
|
||||
CALC=$(SUPPORT)/calc-3-7
|
||||
PCRE=$(SUPPORT)/pcre-7-2
|
||||
|
||||
# EPICS_BASE usually appears last so other apps can override stuff:
|
||||
EPICS_BASE=/usr/local/epics/base-7.0.3
|
||||
|
||||
# These lines allow developers to override these RELEASE settings
|
||||
# without having to modify this file directly.
|
||||
-include $(TOP)/../RELEASE.local
|
||||
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||
-include $(TOP)/configure/RELEASE.local
|
9
configure/RULES
Normal file
@ -0,0 +1,9 @@
|
||||
#CONFIG
|
||||
ifneq ($(wildcard $(EPICS_BASE)/configure),)
|
||||
include $(EPICS_BASE)/configure/RULES
|
||||
else
|
||||
include $(EPICS_BASE)/config/RULES_ARCHS
|
||||
endif
|
||||
|
||||
# Library should be rebuilt because LIBOBJS may have changed.
|
||||
$(LIBNAME): ../Makefile
|
BIN
doc/EPICS.gif
Before Width: | Height: | Size: 453 B |
BIN
doc/PSI.gif
Before Width: | Height: | Size: 1.6 KiB |
BIN
doc/SLS.gif
Before Width: | Height: | Size: 2.2 KiB |
BIN
doc/bg.gif
Before Width: | Height: | Size: 868 B |
@ -1,20 +0,0 @@
|
||||
<!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>
|
459
doc/formats.html
@ -1,459 +0,0 @@
|
||||
<!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>, <code>%<nsum></code>, <code>%<-sum></code>, <code>%<negsum8></code>, <code>%<nsum8></code>, or <code>%<-sum8></code></dt>
|
||||
<dd>One byte. The negative of the sum of all characters modulo 2<sup>8</sup>.</dd>
|
||||
<dt><code>%<negsum16></code>, <code>%<nsum16></code>, or <code>%<-sum16></code></dt>
|
||||
<dd>Two bytes. The negative of the sum of all characters modulo 2<sup>16</sup>.</dd>
|
||||
<dt><code>%<negsum32></code>, <code>%<nsum32></code>, or <code>%<-sum32></code></dt>
|
||||
<dd>Four bytes. The negative of the sum of all characters modulo 2<sup>32</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>%<xor7></code></dt>
|
||||
<dd>One byte. All characters xor'ed & 0x7F.</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>
|
||||
|
||||
<a name="regex"></a>
|
||||
<h2>12. Regular Expresion STRING Converter (<code>%/<em>regex</em>/</code>)</h2>
|
||||
<p>
|
||||
This input-only format matches <a target="ex"
|
||||
href="http://www.pcre.org/" >Perl compatible regular expressions (PCRE)</a>.
|
||||
It is only available if a PCRE library is installed.
|
||||
</p>
|
||||
<p>
|
||||
If PCRE is not available for your host or cross architecture, download
|
||||
the sourcecode from <a target="ex" href="http://www.pcre.org/">www.pcre.org</a>
|
||||
and try my EPICS compatible <a target="ex"
|
||||
href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile">Makefile</a>
|
||||
to compile it like a normal EPICS application.
|
||||
The Makefile is known to work with EPICS 3.14.8 and PCRE 7.2.
|
||||
In your RELEASE file define the variable <code>PCRE</code> so that
|
||||
it points to the install location of PCRE.
|
||||
</p>
|
||||
<p>
|
||||
If PCRE is already installed on your system, use the variables
|
||||
<code>PCRE_INCLUDE</code> and <code>PCRE_LIB</code> instead to provide
|
||||
the install directories of <code>pcre.h</code> and the library.
|
||||
</p>
|
||||
<p>
|
||||
If you have PCRE installed in different locations for different (cross)
|
||||
architectures, define the variables in RELEASE.Common.<architecture>
|
||||
instead of the global RELEASE file.
|
||||
</p>
|
||||
<p>
|
||||
If the regular expression is not anchored, i.e. does not start with
|
||||
<code>^</code>, leading non-matching input is skipped.
|
||||
A maximum of <em>width</em> bytes is matched, if specified.
|
||||
If <em>prec</em> is given, it specifies the sub-expression whose match
|
||||
is retuned.
|
||||
Otherwise the complete match is returned.
|
||||
In any case, the complete match is consumed from the input buffer.
|
||||
If the expression contains a <code>/</code> is must be escaped.
|
||||
</p>
|
||||
<p>
|
||||
Example: <code>%.1/<title>(.*)<\/title>/</code> returns
|
||||
the title of an HTML page, skipps anything before the
|
||||
<code><title></code> tag and leaves anything after the
|
||||
<code></title></code> tag in the input buffer.
|
||||
</p>
|
||||
<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>
|
@ -1,32 +0,0 @@
|
||||
<!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>
|
@ -1,20 +0,0 @@
|
||||
<!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>
|
219
doc/nav.html
@ -1,219 +0,0 @@
|
||||
<!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>
|
||||
<li><a target="text" href="formats.html#regex">%/<em>regex</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>
|
||||
|
@ -1,20 +0,0 @@
|
||||
<!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
Before Width: | Height: | Size: 1.2 KiB |
@ -1,20 +0,0 @@
|
||||
<!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>
|
317
doc/setup.html
@ -1,317 +0,0 @@
|
||||
<!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>.)
|
||||
Support for the scalcout is optional. <em>StreamDevice</em> works
|
||||
as well without scalcout or SynApps.
|
||||
</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>, if desired) 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:
|
||||
</p>
|
||||
<pre>
|
||||
ASYN=/home/epics/asyn/4-5
|
||||
CALC=/home/epics/synApps/calc/2-7
|
||||
</pre>
|
||||
<p>
|
||||
If you want to enable regular expression matching, you need the <em>PCRE</em> package.
|
||||
For most Linux systems, it is already installed. In that case add the locations
|
||||
of the <em>PCRE</em> header and library to your <kbd>RELEASE</kbd> file:
|
||||
</p>
|
||||
<pre>
|
||||
PCRE_INCLUDE=/usr/include/pcre
|
||||
PCRE_LIB=/usr/lib
|
||||
</pre>
|
||||
<p>
|
||||
If you want to build <em>StreamDevice</em> for platforms without <em>PCRE</em> support,
|
||||
it is the easiest to build <em>PCRE</em> as an EPICS application.
|
||||
Download the <em>PCRE</em> package from <a target=ex href="http://www.pcre.org">www.pcre.org</a>
|
||||
and compile it with my EPICS compatible
|
||||
<a target=ex href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile">Makefile</a>.
|
||||
Then define the location of the application in your RELEASE file.
|
||||
</p>
|
||||
<pre>
|
||||
PCRE=/home/epics/pcre
|
||||
</pre>
|
||||
<p>
|
||||
Regular expressions are optional. If you don't want them, you don't need this.
|
||||
</p>
|
||||
|
||||
<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
Before Width: | Height: | Size: 318 B |
BIN
doc/space.gif
Before Width: | Height: | Size: 807 B |
@ -1,79 +0,0 @@
|
||||
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; }
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
<!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>
|
@ -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";
|
||||
}
|
BIN
docs/PSI.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@ -1,24 +1,24 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: aai Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>aai Records</h1>
|
||||
<p>
|
||||
<b>Note:</b> aai record support is disabled per default.
|
||||
Enable it in <code>src/CONFIG_STREAM</code>.
|
||||
<b>Note:</b> In EPICS versions before 3.14.12, aai records may be disabled.
|
||||
</p>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
With aai records, the format converter is applied to
|
||||
each element. Between the elements, a separator is printed
|
||||
each array 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
|
||||
@ -39,14 +39,19 @@ written.
|
||||
<p>
|
||||
The format data type must be convertible to or from the type
|
||||
specified in the <code>FTVL</code> field.
|
||||
The types <code>"INT64"</code> and <code>"UINT64"</code> are
|
||||
only available in EPICS base version 3.16 or higher.
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
<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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -57,6 +62,7 @@ the written or read value.
|
||||
<dd>
|
||||
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
|
||||
<code>FTVL</code> can be
|
||||
<code>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -64,6 +70,7 @@ the written or read value.
|
||||
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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -104,25 +111,31 @@ the written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,24 +1,24 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: aao Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>aao Records</h1>
|
||||
<p>
|
||||
<b>Note:</b> aao record support is disabled per default.
|
||||
Enable it in <code>src/CONFIG_STREAM</code>.
|
||||
<b>Note:</b> In EPICS versions before 3.14.12, aao records may be disabled.
|
||||
</p>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
With aao records, the format converter is applied to
|
||||
each element. Between the elements, a separator is printed
|
||||
each array 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
|
||||
@ -39,14 +39,19 @@ A minimum of one element must be available.
|
||||
<p>
|
||||
The format data type must be convertible to or from the type
|
||||
specified in the <code>FTVL</code> field.
|
||||
The types <code>"INT64"</code> and <code>"UINT64"</code> are
|
||||
only available in EPICS base version 3.16 or higher.
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
<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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -57,6 +62,7 @@ the written or read value.
|
||||
<dd>
|
||||
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
|
||||
<code>FTVL</code> can be
|
||||
<code>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -64,6 +70,7 @@ the written or read value.
|
||||
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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -104,25 +111,31 @@ the written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: ai Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>ai Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -38,6 +39,14 @@ written or read value.
|
||||
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.
|
||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||
on 64 bit machines.
|
||||
<p>
|
||||
If <code>LINR=="NO CONVERSION"</code> (the default), <code>VAL</code>
|
||||
is directly converted from and to <code>long</code> without going through
|
||||
<code>RVAL</code>. This allows for more bits on 64 bit machines.
|
||||
To get the old behavior, use <code>LINR=="LINEAR"</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||
<dd>
|
||||
@ -56,26 +65,31 @@ written or read value.
|
||||
(treated as <code>0.0</code>).
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lan="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" / />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" / />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" / />
|
||||
<meta name="author" content="Dirk Zimoch" / />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: ao Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>ao Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -30,13 +31,21 @@ written or read value.
|
||||
<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>
|
||||
<u>Input:</u> <code>RBV=RVAL=<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.
|
||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||
on 64 bit machines.
|
||||
<p>
|
||||
If <code>LINR=="NO CONVERSION"</code> (the default), <code>OVAL</code>
|
||||
is directly converted to <code>long</code> without going through
|
||||
<code>RVAL</code>. This allows for more bits on 64 bit machines.
|
||||
To get the old behavior, use <code>LINR=="LINEAR"</code>.
|
||||
</p>
|
||||
</dd>
|
||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||
<dd>
|
||||
@ -54,29 +63,33 @@ written or read value.
|
||||
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>
|
||||
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: bi Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>bi Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -52,26 +53,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: bo Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>bo Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -51,26 +52,31 @@ written or read value.
|
||||
<code>RVAL</code> as well as to <code>RBV</code> and converted by the record.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="bo.html">bo</a>
|
||||
<a href="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,14 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Bus API</h1>
|
||||
|
||||
<a name="class"></a>
|
||||
@ -18,7 +19,7 @@
|
||||
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>.
|
||||
<em>asynOctet</em>.
|
||||
Then it can be used by <em>StreamDevice</em> automatically.
|
||||
Only if that does not work, write your own bus interface.
|
||||
</p>
|
||||
@ -67,17 +68,13 @@ class MyInterface : StreamBusInterface
|
||||
// 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="#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, ssize_t 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>();
|
||||
bool <a href="#event">acceptEvent</a>(unsigned long mask, unsigned long timeout_ms);
|
||||
bool <a href="#connect">connectRequest</a>(unsigned long timeout_ms);
|
||||
bool <a href="#connect">disconnectRequest</a>();
|
||||
void <a href="#lock">finish</a>();
|
||||
|
||||
public:
|
||||
@ -121,7 +118,7 @@ bool <a href="#write">writeRequest</a>(const void* output,
|
||||
<div class="indent"><code>
|
||||
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
|
||||
unsigned long readTimeout_ms,
|
||||
long expectedLength, bool async);
|
||||
ssize_t expectedLength, bool async);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool <a href="#read">supportsAsyncRead</a>();
|
||||
@ -131,13 +128,13 @@ 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);
|
||||
unsigned long timeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool <a href="#connect">connectRequest</a>(unsigned long connecttimeout_ms);
|
||||
bool <a href="#connect">connectRequest</a>(unsigned long timeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool <a href="#connect">disconnect</a>();
|
||||
bool <a href="#connect">disconnectRequest</a>();
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#lock">finish</a>();
|
||||
@ -156,24 +153,24 @@ 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);
|
||||
void <a href="#lock">lockCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#write">writeCallback</a>(StreamIoStatus status);
|
||||
void <a href="#write">writeCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
long <a href="#read">readCallback</a>(StreamIoStatus status,
|
||||
const void* input = NULL,
|
||||
long size = 0);
|
||||
ssize_t <a href="#read">readCallback</a>(StreamIoStatus status,
|
||||
const void* buffer = NULL,
|
||||
size_t size = 0);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#event">eventCallback</a>(StreamIoStatus status);
|
||||
void <a href="#event">eventCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#connect">connectCallback</a>(StreamIoStatus status);
|
||||
void <a href="#connect">connectCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void <a href="#connect">disconnectCallback</a>(StreamIoStatus status);
|
||||
void <a href="#connect">disconnectCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
|
||||
<h3>Other provided methods, attibutes, and types</h3>
|
||||
@ -196,6 +193,9 @@ const char* <a href="#read">getInTerminator</a>(size_t& length);
|
||||
<div class="indent"><code>
|
||||
enum StreamIoStatus {StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoEnd, StreamIoFault};
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* ::toStr(StreamIoStatus);
|
||||
</code></div>
|
||||
|
||||
<a name="theory"></a>
|
||||
<h2>Theory of Operation</h2>
|
||||
@ -275,34 +275,47 @@ correct.
|
||||
<a name="connect"></a>
|
||||
<h3>Connecting and disconnecting</h3>
|
||||
<div class="indent"><code>
|
||||
bool connectRequest(unsigned long connecttimeout_ms);
|
||||
bool connectRequest(unsigned long timeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool disconnect();
|
||||
bool disconnectRequest();
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void connectCallback(IoStatus status);
|
||||
void connectCallback(IoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void disconnectCallback(IoStatus status);
|
||||
void disconnectCallback(IoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<p>
|
||||
Connection should be handled automatically.
|
||||
If the device is disconnected, each attempt to access the
|
||||
device should try to (re-)connect.
|
||||
Whenever possible connection should be handled automatically.
|
||||
The interface should call <code>connectCallback()</code> when
|
||||
the device has connected and <code>disconnectCallback()</code> when
|
||||
the device has disconnected.
|
||||
These callbacks can be called asynchronously at any time.
|
||||
</p>
|
||||
<p>
|
||||
If the device is disconnected, an attempt to access the
|
||||
device should try to reconnect.
|
||||
Normally, the interface should not try to disconnect unless
|
||||
the device does so.
|
||||
the device does so automatically.
|
||||
</p>
|
||||
<p>
|
||||
However, sometimes the client wants to connect or
|
||||
disconnect explicitely.
|
||||
disconnect explicitly.
|
||||
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 or connection
|
||||
This function should set up things to reconnect but should not block
|
||||
waiting.
|
||||
Instead it should immediately return <code>true</code> if
|
||||
it expects that connection can be established soon, or
|
||||
<code>false</code> if the request cannot be accepted or connection
|
||||
handling is not supported.
|
||||
The interface should call <code>connectCallback(StreamIoSuccess)</code>
|
||||
The interface should call <code>connectCallback()</code>
|
||||
once the bus could be connected.
|
||||
If the bus cannot be connected within <code>connecttimeout_ms</code>
|
||||
If the device can connect immediately without waiting, it may also call
|
||||
<code>connectCallback()</code> directly from <code>connectRequest()</code>.
|
||||
</p>
|
||||
<p>
|
||||
If the bus cannot be connected within <code>timeout_ms</code>
|
||||
milliseconds, the bus interface should call
|
||||
<code>connectCallback(StreamIoTimeout)</code>.
|
||||
</p>
|
||||
@ -312,11 +325,11 @@ something wrong with the I/O hardware,
|
||||
<code>connectCallback(StreamIoFault)</code> may be called.
|
||||
</p>
|
||||
<p>
|
||||
To disconnect, the client calls <code>disconnectRequest()</code>;
|
||||
To disconnect explicitly, the client calls <code>disconnectRequest()</code>;
|
||||
This function should return <code>true</code> immediately or
|
||||
<code>false</code> if the request cannot be accepted or connection
|
||||
handling is not supported.
|
||||
The interface should call <code>connectCallback(StreamIoSuccess)</code>
|
||||
The interface should call <code>connectCallback()</code>
|
||||
once the bus is disconnected. There is no timeout for this operation.
|
||||
If disconnecting is impossible, the interface should call
|
||||
<code>connectCallback(StreamIoFault)</code>.
|
||||
@ -325,10 +338,10 @@ If disconnecting is impossible, the interface should call
|
||||
<a name="lock"></a>
|
||||
<h3>Bus locking</h3>
|
||||
<div class="indent"><code>
|
||||
bool lockRequest(unsigned long lockTimeout_ms);
|
||||
bool lockRequest(unsigned long timeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void lockCallback(IoStatus status);
|
||||
void lockCallback(IoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool unlock();
|
||||
@ -347,7 +360,7 @@ 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>.
|
||||
<code>lockCallback()</code>.
|
||||
If the bus cannot be locked within <code>lockTimeout_ms</code>
|
||||
milliseconds, the bus interface should call
|
||||
<code>lockCallback(StreamIoTimeout)</code>.
|
||||
@ -368,7 +381,7 @@ 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.
|
||||
call <code>lockCallback()</code> now.
|
||||
</p>
|
||||
<p>
|
||||
The client calls <code>finish()</code> when the protocol ends.
|
||||
@ -384,7 +397,7 @@ bool writeRequest(const void* output,
|
||||
size_t size, unsigned long writeTimeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void writeCallback(IoStatus status);
|
||||
void writeCallback(IoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* getOutTerminator(size_t& length);
|
||||
@ -403,7 +416,7 @@ The function should arrange transmission of <code>size</code> bytes of
|
||||
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>.
|
||||
interface should call <code>writeCallback()</code>.
|
||||
</p>
|
||||
<p>
|
||||
If output blocks for <code>writeTimeout_ms</code> milliseconds,
|
||||
@ -416,14 +429,15 @@ 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.
|
||||
The interface must send excactly the <code>size</code> bytes
|
||||
from <code>output</code>, not less.
|
||||
It should not change anything unless the bus needs some special
|
||||
formatting (e.g. added header, escaped bytes) 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
|
||||
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).
|
||||
@ -446,12 +460,12 @@ The client may request more I/O or call <code>unlock()</code> after
|
||||
<div class="indent"><code>
|
||||
bool readRequest(unsigned long replyTimeout_ms,
|
||||
unsigned long readTimeout_ms,
|
||||
long expectedLength, bool async);
|
||||
ssize_t expectedLength, bool async);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
long readCallback(IoStatus status,
|
||||
const void* input = NULL,
|
||||
long size = 0);
|
||||
ssize_t readCallback(IoStatus status,
|
||||
const void* buffer = NULL,
|
||||
size_t size = 0);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
const char* getInTerminator(size_t& length);
|
||||
@ -486,11 +500,11 @@ The client copies its contents. It does not modify or free it.
|
||||
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>
|
||||
If the client expects more input, <code>readCallback()</code>
|
||||
returns a non-zero value.
|
||||
A positive <code>n</code> means, the client needs another
|
||||
A positive <code>n</code> means, the client expects another
|
||||
<code>n</code> bytes of input.
|
||||
A negative <code>n</code> means, the client needs an unspecified
|
||||
A negative <code>n</code> means, the client expects an unspecified
|
||||
amount of additional input.
|
||||
</p>
|
||||
<p>
|
||||
@ -558,46 +572,43 @@ 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
|
||||
Sometimes a client wishes to get any input received at any time, even
|
||||
when requested by another client.
|
||||
If a client wishes to receive such asynchronous 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.
|
||||
If a bus interface supports asynchronous input, it should overwrite
|
||||
this method to set up everything needed to receive asynchronous input
|
||||
and then return <code>true</code>.
|
||||
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.
|
||||
This means that the client is now interested in asynchronous 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
|
||||
in response to any synchonous (<code>async==false</code>) request from
|
||||
another client (which should receive the input, too).
|
||||
The interface should also receive asynchronous input when no
|
||||
synchonous client is active at the moment.
|
||||
Many asynchonous <code>readRequest()</code> calls from different clients
|
||||
Many asynchronous <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
|
||||
For asynchronous 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
|
||||
If many asynchronous requests are active at the same time, it should poll
|
||||
with the shortest period of all clients.
|
||||
An asynchonous request does not time out.
|
||||
An asynchronous 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.
|
||||
receiving asynchronous 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.
|
||||
asynchronous read requests.
|
||||
</p>
|
||||
<a name="event"></a>
|
||||
<h3>Handling events</h3>
|
||||
@ -605,10 +616,10 @@ asynchonous read requests.
|
||||
bool supportsEvent();
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool acceptEvent(unsigned long mask, unsigned long replytimeout_ms);
|
||||
bool acceptEvent(unsigned long mask, unsigned long timeout_ms);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
void eventCallback(StreamIoStatus status);
|
||||
void eventCallback(StreamIoStatus status = StreamIoSuccess);
|
||||
</code></div>
|
||||
<p>
|
||||
An event is a sort of input from a device which is not part of
|
||||
@ -626,9 +637,9 @@ If <code>true</code> is returned, the client is allowed to call
|
||||
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>
|
||||
It should arrange to call <code>eventCallback()</code>
|
||||
when the event matching <code>mask</code> arrives within
|
||||
<code>replytimeout_ms</code> milliseconds.
|
||||
<code>timeout_ms</code> milliseconds.
|
||||
If no such event arrives within this time, the bus interface
|
||||
should call <code>eventCallback(StreamIoTimeout)</code>.
|
||||
</p>
|
||||
@ -638,8 +649,9 @@ 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>
|
||||
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: calcout Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>calcout Records</h1>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Device support for calcout records is only available for
|
||||
@ -58,26 +59,31 @@ Different record fields are used for output and input. The variable
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: Using EPICS 3.13</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Using EPICS 3.13</h1>
|
||||
|
||||
<a name="pre"></a>
|
||||
<h2>1. Prerequisites</h2>
|
||||
@ -217,8 +218,31 @@ asynSetOption ("PS1", 0, "stop", "1")
|
||||
|
||||
<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>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
BIN
docs/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
266
docs/formatconverter.html
Normal file
@ -0,0 +1,266 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: Format Converter API</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Format Converter API</h1>
|
||||
|
||||
<a name="class"></a>
|
||||
<h2>Converter Class</h2>
|
||||
<p>
|
||||
A user defined converter class inherits public from
|
||||
<i>StreamFormatConverter</i> 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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
A converter class must be registered with a call to RegisterConverter()
|
||||
in the global file context.
|
||||
</p>
|
||||
<p>
|
||||
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!
|
||||
</p>
|
||||
|
||||
<h3>Example: LONG converter for <code>%Q</code></h3>
|
||||
<pre>
|
||||
#include "StreamFormatConverter.h"
|
||||
|
||||
class MyConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
ssize_t scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
RegisterConverter(MyConverter,"Q");
|
||||
|
||||
// ... (implementation)
|
||||
</pre>
|
||||
|
||||
<a name="theory"></a>
|
||||
<h2>Theory of Operation</h2>
|
||||
|
||||
<a name="registration"></a>
|
||||
<h3>Registration </h3>
|
||||
<div class="indent"><code>
|
||||
RegisterConverter(<i>converterClass</i>, "<i>characters</i>");
|
||||
</code></div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
HINT: Do not branch depending on the conversion character.
|
||||
Provide multiple classes, that's more efficient.
|
||||
</p>
|
||||
|
||||
<a name="parsing"></a>
|
||||
<h3>Parsing</h3>
|
||||
<div class="indent"><code>
|
||||
int parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
const char*& source, bool scanFormat);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
struct StreamFormat {
|
||||
char conv;
|
||||
StreamFormatType type;
|
||||
unsigned short flags;
|
||||
long prec;
|
||||
unsigned long width;
|
||||
unsigned long infolen;
|
||||
const char* info;
|
||||
};
|
||||
</code></div>
|
||||
|
||||
<p>
|
||||
During initialization, <code>parse()</code> is called whenever one of the
|
||||
conversion characters handled by your converter class is found in a protocol.
|
||||
The fields <code>fmt.conv</code>, <code>fmt.flags</code>,
|
||||
<code>fmt.prec</code>, and <code>fmt.width</code> have
|
||||
already been filled in. If a scan format is parsed, <code>scanFormat</code>
|
||||
is <code>true</code>. If a print format is parsed, <code>scanFormat</code>
|
||||
is <code>false</code>.
|
||||
</p>
|
||||
<p>
|
||||
The <code>fmt.flags</code> field is a bitset and can have any of the following
|
||||
flags set:
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>left_flag</code>: the format contained a <code>-</code>.
|
||||
This is normaly used to indicate that the value should be printed
|
||||
left-aligned.
|
||||
</li>
|
||||
<li><code>sign_flag</code>: the format contained a <code>+</code>.
|
||||
This normaly requests to print a sign even for positive numbers.
|
||||
</li>
|
||||
<li><code>space_flag</code>: the format contained a '<code> </code>' (space).
|
||||
This normaly requests to print a space instead of a sign for positive numbers.
|
||||
</li>
|
||||
<li><code>alt_flag</code>: the format contained a <code>#</code>.
|
||||
This indicated the request to use an alternative format. For example in
|
||||
<code>%#x</code> the hex number is preficed with <code>0x</code>.
|
||||
</li>
|
||||
<li><code>zero_flag</code>: the format contained a <code>0</code>.
|
||||
This normaly requests to pad a numerical value with leading zeros
|
||||
instead of leading spaces.
|
||||
<li><code>skip_flag</code>: the format contained a <code>*</code>.
|
||||
The value is parsed and checked but then discarded.
|
||||
</ul>
|
||||
<p>
|
||||
It is not necessary that these flags have exactly the same meaning in your
|
||||
formats, but a similar and intuitive meaning is helpful for the user.
|
||||
</p>
|
||||
<p>
|
||||
There are two additional flags, <code>default_flag</code> indicating a
|
||||
<code>?</code> and <code>compare_flag</code> indicating a <code>=</code>
|
||||
in the format, that are handled internally by <em>StreamDevice</em> and
|
||||
are not of interest to the converter class.
|
||||
</p>
|
||||
<p>
|
||||
The <code>source</code> 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 <code>source</code> pointer so that is points to the first character
|
||||
after your format string.
|
||||
This is done for example in the builtin formats
|
||||
<code>%[charset]</code> or <code>%{enum0|enum1}</code>.
|
||||
However, many formats don't need additional characters.
|
||||
|
||||
</p>
|
||||
<h4>Example</h4>
|
||||
<pre>
|
||||
source source
|
||||
before after
|
||||
parse() parse()
|
||||
| |
|
||||
"%39[0-9a-zA-Z]constant text"
|
||||
|
|
||||
conversion
|
||||
character
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can write any data you may need later in <code>print*()</code> or
|
||||
<code>scan*()</code> to the
|
||||
<a href="streambuffer.html"><i>Streambuffer</i></a> <code>info</code>.
|
||||
This will probably be necessary if you have parsed additional characters
|
||||
from the format string as in the above example<br>
|
||||
</p>
|
||||
<p>
|
||||
Return <code>unsigned_format</code>, <code>signed_format</code>,
|
||||
<code>double_format</code>, <code>string_format</code>, or
|
||||
<code>enum_format</code> 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.
|
||||
</p>
|
||||
<p>
|
||||
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 <code>pseudo_format</code>.
|
||||
</p>
|
||||
<p>
|
||||
Return <code>false</code> if there is any parse error or if print or scan
|
||||
is requested but not supported by this conversion or flags are used that
|
||||
are not supported by this conversion.
|
||||
</p>
|
||||
|
||||
<a name="printing_scanning"></a>
|
||||
<h3>Printing and Scanning</h3>
|
||||
<p>
|
||||
Provide a <code>print[Long|Double|String|Pseudo]()</code> and/or
|
||||
<code>scan[Long|Double|String|Pseudo]()</code> method appropriate
|
||||
for the data type you have returned in the <code>parse()</code> 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 <code>parse()</code>.
|
||||
Both <code>unsigned_format</code> and <code>signed_format</code> will use
|
||||
the <code>Long</code> flavour.
|
||||
</p>
|
||||
</p>
|
||||
The possible interface methods are:
|
||||
</p>
|
||||
<div class="indent"><code>
|
||||
bool printLong(const StreamFormat& fmt,
|
||||
StreamBuffer& output, long value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool printDouble(const StreamFormat& fmt,
|
||||
StreamBuffer& output, double value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool printString(const StreamFormat& fmt,
|
||||
StreamBuffer& output, const char* value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
bool printPseudo(const StreamFormat& fmt,
|
||||
StreamBuffer& output);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
ssize_t scanLong(const StreamFormat& fmt,
|
||||
const char* input, long& value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
ssize_t scanDouble(const StreamFormat& fmt,
|
||||
const char* input, double& value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
ssize_t scanString(const StreamFormat& fmt,
|
||||
const char* input, char* value, size_t& size);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
ssize_t scanPseudo(const StreamFormat& fmt,
|
||||
StreamBuffer& inputLine, size_t& cursor);
|
||||
</code></div>
|
||||
|
||||
<p>
|
||||
Now, <code>fmt.type</code> contains the value returned by <code>parse()</code>.
|
||||
With <code>fmt.info()</code> get access to the string you have written to
|
||||
<code>info</code> in <code>parse()</code> (null terminated).
|
||||
</p>
|
||||
<p>
|
||||
The length of the info string can be found in <code>fmt.infolen</code>.
|
||||
</p>
|
||||
<p>
|
||||
In <code>print*()</code>, append the converted value to <code>output</code>.
|
||||
Do not modify what is already in output (unless you really know what you're
|
||||
doing, e.g. some <code>printPseudo</code> methods).
|
||||
Return <code>true</code> on success, <code>false</code> on failure.
|
||||
</p>
|
||||
<p>
|
||||
In <code>scan*()</code>, read the value from input and return the number of
|
||||
consumed bytes or -1 on failure.
|
||||
If the <code>skip_flag</code> is set, you don't need to write to
|
||||
<code>value</code>, since the value will be discarded anyway.
|
||||
In <code>scanString()</code>, don't write more bytes than
|
||||
<code>maxlen</code> to <code>value</code> and set <code>size</code> to the
|
||||
actual string length, which may be different to the number of bytes consumed
|
||||
(e.g. if leading spaces are skipped).
|
||||
In <code>scanPseudo()</code>, <code>cursor</code> is the index of the first
|
||||
byte in <code>inputLine</code> to consider, which may be larger than
|
||||
<code>0</code>.
|
||||
</p>
|
||||
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
840
docs/formats.html
Normal file
@ -0,0 +1,840 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: Format Converters</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>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 or record 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 class="new">
|
||||
An exception is the sequence <code>%%</code> which stands for a single
|
||||
literal <code>%</code>.
|
||||
This has been added for compatibility with the C functions
|
||||
<em>printf()</em> and <em>scanf()</em>.
|
||||
It behaves the same as the escaped percent <code>\%</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The flags <code>*# +0-</code> work like in the C functions
|
||||
<em>printf()</em> and <em>scanf()</em>.
|
||||
The flags <code>?</code>, <code>=</code> and <code>!</code> are extensions.
|
||||
</p>
|
||||
<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 usually print a
|
||||
space or a <code>+</code> sign before positive numbers, where negative
|
||||
numbers would have a <code>-</code>.
|
||||
Some converters may redefine the meaning of these flags (see below).
|
||||
</p>
|
||||
<p>
|
||||
The <code>0</code> flag usually says that numbers should be left padded
|
||||
with <code>0</code> if <em>width</em> is larger than required.
|
||||
Some converters may redefine the meaning of this flag (see below).
|
||||
<p>
|
||||
The <code>-</code> flag usually specifies that output is left justified
|
||||
if <em>width</em> is larger than required.
|
||||
Some converters may redefine the meaning of this flag (see below).
|
||||
</p>
|
||||
<p>
|
||||
The <code>?</code> flag makes failing input conversions succeed with
|
||||
a default zero value (0, 0.0, or "", depending on the format type).
|
||||
</p>
|
||||
<p>
|
||||
The <code>=</code> 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.
|
||||
</p>
|
||||
<p>
|
||||
The <code>!</code> flag demands that input is exactly <em>width</em>
|
||||
bytes long (normally <em>width</em> defines the maximum number of
|
||||
bytes read in many formats).
|
||||
This feature has been added by Klemen Vodopivec, SNS.
|
||||
</p>
|
||||
|
||||
<h3>Examples:</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>in "%f";</code></td>
|
||||
<td>Read a float value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>out "%(HOPR)7.4f";</code></td>
|
||||
<td>Write the HOPR field as 7 char float with precision 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>out "%#010x";</code></td>
|
||||
<td>Write a 0-padded 10 char hex integer using the alternative format (with leading 0x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%[_a-zA-Z0-9]";</code></td>
|
||||
<td>Read a string of alphanumerical chars or underscores</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%*i";</code></td>
|
||||
<td>Skip over an integer number</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%?d";</code></td>
|
||||
<td>Read a decimal number or if that fails pretend that value was 0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%=.3f";</code></td>
|
||||
<td>Assure that the input is equal to the current value formatted as a float with precision 3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%!5d";</code></td>
|
||||
<td>Expect exactly 5 decimal digits. Fewer digits are considered loss of data and make the format fail.
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>in "%d%%";</code></td>
|
||||
<td>Read a decimal number followed by a % sign</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, ULONG, ENUM, or STRING.
|
||||
In contrast to to the C functions <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>
|
||||
|
||||
<a name="redirection"></a>
|
||||
<h3>I/O Redirection to other records or fields</h3>
|
||||
<p>
|
||||
To use formats with other than the default fields of a record or even with
|
||||
fields of other records on the same IOC, use the syntax
|
||||
<code>%(<var>record</var>.<var>FIEL</var>D)</code>.
|
||||
If only a field name but no record is given, the active record is assumed.
|
||||
If only a record name but no field name is given, the <code>VAL</code>
|
||||
field is assumed.
|
||||
</p>
|
||||
<p>
|
||||
<b>Example 1:</b> <code>out "%(EGU)s";</code> outputs the
|
||||
<code>EGU</code> field of the active record.
|
||||
</p>
|
||||
<p>
|
||||
<b>Example 2:</b> <code>in "%(<var>otherrecord</var>.RVAL)i";</code>
|
||||
stores the received integer value in the <code>RVAL</code> field of the
|
||||
other record and then processes that record.
|
||||
The other record should probably use <code>DTYP="Raw Soft Channel"</code>
|
||||
in order to convert <code>RVAL</code> to <code>VAL</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Example 3:</b> <code>in "%(<var>otherrecord</var>)f";</code>
|
||||
stores the received floating point value in the <code>VAL</code> field
|
||||
of the other record and then processes that record.
|
||||
The other record should probably use <code>DTYP="Soft Channel"</code>.
|
||||
In the unlikely case that the name of the other record is the same as a field
|
||||
of the active record (e.g. if you name a record "DESC"), then use <code>.VAL</code>
|
||||
explicitly to refer to the record rather than the field of the active record.
|
||||
</p>
|
||||
<p>
|
||||
This feature is quite useful in the case that one line of input contains more
|
||||
than one value that need to be stored in multiple records or if one line of
|
||||
output needs to be contructed from values of multiple records.
|
||||
In order to avoid using full record names in the protocol file, it is recommended
|
||||
to pass the name or part of the name (e.g. the device prefix) of the other
|
||||
record as a <a href="protocol.html#argvar">protocol argument</a>.
|
||||
In that case the redirection usually looks like this:
|
||||
<code>in "%(\$1<var>recordpart</var>)f"</code> and the record calls the protocol
|
||||
like this:
|
||||
<code>field(INP, "@<var>protocolfile</var> <var>protocol</var>($(PREFIX)) $(PORT)")</code>
|
||||
using a macro for the prefix part which is then used for <code>\$1</code>.
|
||||
</p>
|
||||
<p>
|
||||
If the other record 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.
|
||||
STRING formats are compatible with arrays of CHAR or UCHAR.
|
||||
</p>
|
||||
<p>
|
||||
Be aware that using this syntax is by far not as efficient as using the
|
||||
default field.
|
||||
At the moment it is not possible to set the other record to an alarm
|
||||
state if anything fails. It will simply not be processed if the fault
|
||||
happens before or while handling it and it will already have been
|
||||
processed if the fault happens later.
|
||||
</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> or
|
||||
<a href="#regsub">regular expression substitution</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>
|
||||
<b>Output:</b> <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.
|
||||
</p>
|
||||
<p>
|
||||
With the <code>#</code> flag, output always contains a period character.
|
||||
</p>
|
||||
<p>
|
||||
<b>Input:</b> All these formats are equivalent. Leading whitespaces are skipped.
|
||||
</p>
|
||||
<p>
|
||||
With the <code>#</code> flag additional whitespace between sign and number
|
||||
is accepted.
|
||||
</p>
|
||||
<p>
|
||||
When a maximum field width is given, leading whitespace only counts to the
|
||||
field witdth when the space flag is used.
|
||||
</p>
|
||||
|
||||
<a name="stdl"></a>
|
||||
<h2>4. Standard LONG and ULONG Converters (<code>%d</code>, <code>%i</code>,
|
||||
<code>%u</code>, <code>%o</code>, <code>%x</code>, <code>%X</code>)</h2>
|
||||
<p>
|
||||
<b>Output</b>: <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.
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
Unlike printf, <code>%x</code> and <code>%X</code> truncate the
|
||||
output to the the given width (number of least significant half bytes).
|
||||
</p>
|
||||
</p>
|
||||
<p>
|
||||
<b>Input:</b> <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>
|
||||
<p>
|
||||
With the <code>-</code> negative octal and hexadecimal values are accepted.
|
||||
</p>
|
||||
<p>
|
||||
With the <code>#</code> flag additional whitespace between sign and number
|
||||
is accepted.
|
||||
</p>
|
||||
<p>
|
||||
When a maximum field width is given, leading whitespace only counts to the
|
||||
field witdth when the space flag is used.
|
||||
</p>
|
||||
|
||||
<a name="stds"></a>
|
||||
<h2>5. Standard STRING Converters (<code>%s</code>, <code>%c</code>)</h2>
|
||||
<p>
|
||||
<b>Output:</b> <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>
|
||||
<b>Input:</b> <code>%s</code> matches a sequence of non-whitespace characters
|
||||
and <code>%c</code> matches 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> except when
|
||||
the space flag is used but not with <code>%c</code>.
|
||||
The empty string matches.
|
||||
</p>
|
||||
<p>
|
||||
With the <code>#</code> flag <code>%s</code> matches a sequence of not-null
|
||||
characters instead of non-whitespace characters.
|
||||
</p>
|
||||
<p>
|
||||
With the <code>0</code> flag <code>%s</code> pads with 0 bytes instead of
|
||||
spaces.
|
||||
</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>.
|
||||
</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>
|
||||
When using the <code>#</code> flag it is allowed to assign integer values
|
||||
to the strings using <code>=</code>.
|
||||
Unassigned strings increment their values by 1 as usual.
|
||||
</p>
|
||||
<p>
|
||||
If one string is the initial substing of another, the substing must come
|
||||
later to ensure correct matching.
|
||||
In particular if one string is the emptry string, it must be the last one
|
||||
because it always matches.
|
||||
Use <code>#</code> and <code>=</code> to renumber if necessary.
|
||||
</p>
|
||||
<p>
|
||||
Use the assignment <code>=?</code> for the last string to make it the
|
||||
default value for output formats.
|
||||
</p>
|
||||
<p>
|
||||
Example: <code>%#{neg=-1|stop|pos|fast=10|rewind=-10}</code>.
|
||||
</p>
|
||||
<p>
|
||||
If one of the strings contains <code>|</code> or <code>}</code>
|
||||
(or <code>=</code> if the <code>#</code> flag is used)
|
||||
a <code>\</code> must be used to escape the character.
|
||||
</p>
|
||||
<p>
|
||||
<b>Output:</b> Depending on the value, one of the strings is printed,
|
||||
or the default if given and no value matches.
|
||||
</p>
|
||||
<p>
|
||||
<b>Input:</b> If any of the strings matches, the value is set accordingly.
|
||||
</p>
|
||||
|
||||
<a name="bin"></a>
|
||||
<h2>8. Binary LONG or ULONG 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.
|
||||
With the <code>#</code> flag, the bit order is changed to <em>little
|
||||
endian</em>, i.e. least significant bit first.
|
||||
</p>
|
||||
<p>
|
||||
Examples: <code>%B.!</code> or <code>%B\x00\xff</code>.
|
||||
<code>%B01</code> is equivalent to <code>%b</code>.
|
||||
</p>
|
||||
<p>
|
||||
In output, if <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.
|
||||
</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 or ULONG Converter (<code>%r</code>)</h2>
|
||||
<p>
|
||||
The raw converter does not really "convert".
|
||||
A signed or unsigned 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.
|
||||
With the <code>0</code> flag, the value is unsigned, otherwise signed.
|
||||
</p>
|
||||
<p>
|
||||
In output, the <em>precision</em> (or sizeof(long) whatever is less) least
|
||||
significant bytes of the value are sign extended or zero extended
|
||||
(depending on the <code>0</code> flag) to <em>width</em> bytes.
|
||||
The default for <em>precision</em> is 1. Thus if you do not specify
|
||||
the <em>precision</em>, only the least significant byte is written!
|
||||
It is common error to write <code>out "%2r";</code> instead of <code>out "%.2r";</code>.
|
||||
</p>
|
||||
<p>
|
||||
In input, <em>width</em> bytes are read and put into the value.
|
||||
If <em>width</em> is larger than the size of a <code>long</code>, only
|
||||
the least significant bytes are used.
|
||||
If <em>width</em> is smaller than the size of a <code>long</code>,
|
||||
the value is sign extended or zero extended, depending on the
|
||||
<code>0</code> flag.
|
||||
</p>
|
||||
<p>
|
||||
Examples: <code>out "%.2r"; in "%02r";</code>
|
||||
</p>
|
||||
|
||||
<a name="rawdouble"></a>
|
||||
<h2>10. Raw DOUBLE Converter (<code>%R</code>)</h2>
|
||||
<p>
|
||||
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 <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 <em>width</em> must be 4 (float) or 8 (double). The default is 4.
|
||||
</p>
|
||||
|
||||
<a name="bcd"></a>
|
||||
<h2>11. Packed BCD (Binary Coded Decimal) LONG or ULONG 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>12. 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.
|
||||
<span class="new">
|
||||
Any pre-processing of input, e.g. by the <a href="#regsub">regsub</a> converter
|
||||
is ignored for the calculation of the checksum.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
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>precision</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 to
|
||||
hexadecimal ASCII (2 chars per checksum byte).
|
||||
</p>
|
||||
<p>
|
||||
The <code>-</code> flag changes the checksum representation to
|
||||
"poor man's hex": 0x30 ... 0x3f (2 chars per checksum byte).
|
||||
</p>
|
||||
<p>
|
||||
The <code>+</code> flag changes the checksum representation to
|
||||
decimal ASCII (formatted with %d).
|
||||
</p>
|
||||
<!--
|
||||
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>, <code>%<nsum></code>, <code>%<-sum></code>, <code>%<negsum8></code>, <code>%<nsum8></code>, or <code>%<-sum8></code></dt>
|
||||
<dd>One byte. The negative of the sum of all characters modulo 2<sup>8</sup>.</dd>
|
||||
<dt><code>%<negsum16></code>, <code>%<nsum16></code>, or <code>%<-sum16></code></dt>
|
||||
<dd>Two bytes. The negative of the sum of all characters modulo 2<sup>16</sup>.</dd>
|
||||
<dt><code>%<negsum32></code>, <code>%<nsum32></code>, or <code>%<-sum32></code></dt>
|
||||
<dd>Four bytes. The negative of the sum of all characters modulo 2<sup>32</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>%<xor7></code></dt>
|
||||
<dd>One byte. All characters xor'ed & 0x7F.</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, reflected).</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, reflected).</dd>
|
||||
<dt><code>%<modbus></code></dt>
|
||||
<dd>Two bytes. The modbus 16 bit crc checksum
|
||||
(poly=0x8005, init=0xffff, xorout=0x0000, reflected)</dd>
|
||||
<dt><code>%<ccitt16></code></dt>
|
||||
<dd>Two bytes. The usual (but <a target="ex"
|
||||
href="http://srecord.sourceforge.net/crc16-ccitt.html">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://srecord.sourceforge.net/crc16-ccitt.html">correct?</a>)
|
||||
implementation of the CCITT standard 16 bit crc checksum with augment.
|
||||
(poly=0x1021, init=0x1D0F, xorout=0x0000).</dd>
|
||||
<dt><code>%<ccitt16x></code> or <code>%<crc16c></code> or <code>%<xmodem></code></dt>
|
||||
<dd>Two bytes. The XMODEM checksum.
|
||||
(poly=0x1021, init=0x0000, 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, reflected).</dd>
|
||||
<dt><code>%<jamcrc></code></dt>
|
||||
<dd>Four bytes. Another reflected 32 bit crc checksum.
|
||||
(poly=0x04C11DB7, init=0xFFFFFFFF, xorout=0x00000000, reflected).</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>
|
||||
<dt><code>%<lrc></code></dt>
|
||||
<dd>One byte. The Longitudinal Redundancy Check according to <a target="ex"
|
||||
href="https://en.wikipedia.org/wiki/Longitudinal_redundancy_check">Wikipedia</a>.</dd>
|
||||
<dt><code>%<hexlrc></code></dt>
|
||||
<dd>One byte. The LRC for the hex digits. (Other characters are ignored.)</dd>
|
||||
<dt><code>%<leybold></code></dt>
|
||||
<dd>One byte. Used by some Leybold products. 255-bytesum%255 (+32 if result would be <32)</dd>
|
||||
<dt><code>%<brksCryo></code></dt>
|
||||
<dd>One byte. Used by Brooks Cryopumps.</dd>
|
||||
<dt><code>%<CPI></code></dt>
|
||||
<dd>One byte. Used by TRIUMF CPI RF amplifier.</dd>
|
||||
<dt><code>%<bitsum></code> or <code>%<bitsum8></code></dt>
|
||||
<dd>One byte. Number of 1 bits in all characters.</dd>
|
||||
<dt><code>%<bitsum16></code></dt>
|
||||
<dd>Two bytes. Number of 1 bits in all characters.</dd>
|
||||
<dt><code>%<bitsum32></code></dt>
|
||||
<dd>Four bytes. Number of 1 bits in all characters.</dd>
|
||||
</dl>
|
||||
|
||||
<a name="regex"></a>
|
||||
<h2>13. Regular Expresion STRING Converter (<code>%/<em>regex</em>/</code>)</h2>
|
||||
<p>
|
||||
This input-only format matches <a target="ex"
|
||||
href="http://www.pcre.org/" >Perl compatible regular expressions (PCRE)</a>.
|
||||
It is only available if a PCRE library is installed.
|
||||
</p>
|
||||
<div class="box">
|
||||
<p>
|
||||
If PCRE is not available for your host or cross architecture, download
|
||||
the sourcecode from <a target="ex" href="https://www.pcre.org/">www.pcre.org</a>
|
||||
and try my EPICS compatible <a target="ex"
|
||||
href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile">Makefile</a>
|
||||
to compile it like a normal EPICS support module.
|
||||
The Makefile is known to work with EPICS 3.14.8 and PCRE 7.2.
|
||||
In your RELEASE file define the variable <code>PCRE</code> so that
|
||||
it points to the install location of PCRE.
|
||||
</p>
|
||||
<p>
|
||||
If PCRE is already installed on (some of) your systems, you may add
|
||||
architectures where PCRE can be found in standard include and library
|
||||
locations to the variable <code>WITH_SYSTEM_PCRE</code>.
|
||||
If either the header file or the library are in a non-standard place,
|
||||
set in your RELEASE file the variables <code>PCRE_INCLUDE_<em>arch</em></code>
|
||||
and/or <code>PCRE_LIB_<em>arch</em></code> for the respective architectures
|
||||
to the correct directories or set
|
||||
<code>PCRE_INCLUDE</code> and/or <code>PCRE_LIB</code>
|
||||
in architecture specific RELEASE.Common.<em>arch</em> files.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
If the regular expression is not anchored, i.e. does not start with
|
||||
<code>^</code>, leading non-matching input is skipped.
|
||||
To match in multiline mode (across newlines) add <code>(?m)</code>
|
||||
at the beginning of the pattern.
|
||||
To match case insensitive, add <code>(?i)</code>.
|
||||
</p>
|
||||
<p>
|
||||
A maximum of <em>width</em> bytes is matched, if specified.
|
||||
If <em>precision</em> is given, it specifies the sub-expression in <code>()</code>
|
||||
whose match is returned.
|
||||
Otherwise the complete match is returned.
|
||||
In any case, the complete match is consumed from the input buffer.
|
||||
If the expression contains a <code>/</code> it must be escaped like <code>\/</code>.
|
||||
</p>
|
||||
<p>
|
||||
Example: <code>%.1/<title>(.*)<\/title>/</code> returns
|
||||
the title of an HTML page, skipps anything before the
|
||||
<code><title></code> tag and leaves anything after the
|
||||
<code></title></code> tag in the input buffer.
|
||||
</p>
|
||||
<a name="regsub"></a>
|
||||
<h2>14. Regular Expresion Substitution Pseudo-Converter (<code>%#/<em>regex</em>/<em>subst</em>/</code>)</h2>
|
||||
<p>
|
||||
This is a variant of the previous converter (note the <code>#</code>)
|
||||
but instead of returning the matching string,
|
||||
it can be used as a pre-processor for input or
|
||||
as a post-processor for output.
|
||||
</p>
|
||||
<p>
|
||||
Matches of the <em>regex</em> are replaced by the string <em>subst</em> with all
|
||||
<code>&</code> in <em>subst</em> replaced with the match itself and all
|
||||
<code>\1</code> through <code>\9</code> replaced with the match of the corresponding
|
||||
sub-expression <span class="new"> if such a sub-expression exists.
|
||||
|
||||
Occurrences of <code>\U<i>n</i></code>, <code>\L<i>n</i></code>, <code>\u<i>n</i></code>,
|
||||
or <code>\l<i>n</i></code> with <code><i>n</i></code> being a number <code>0</code>
|
||||
through <code>9</code> or <code>&</code> are replaced with the corresponding sub-expression
|
||||
converted to all upper case, all lower case, first letter upper case, or first letter lower
|
||||
case, respectively.</span>
|
||||
</p>
|
||||
<p><span class="new">
|
||||
Due to limitations of the parser, <code>\1</code> and <code>\x01</code> are the same
|
||||
which makes it difficult to use literal bytes with values lower than 10 in <em>subst</em>.
|
||||
Therefore <code>\0</code> aways means a literal byte (incompatible change from earlier version!)
|
||||
and <code>\1</code> through <code>\9</code> mean literal bytes if they are larger than
|
||||
the number of sub-expressions.
|
||||
</span>
|
||||
|
||||
To get a literal <code>&</code> or <code>\</code> or <code>/</code> in the substitution write
|
||||
<code>\&</code> or <code>\\</code> or <code>\/</code>.
|
||||
</p>
|
||||
<p>
|
||||
If <em>width</em> is specified, it limits the number of characters processed.
|
||||
If the <code>-</code> flag is used (i.e. <em>width</em> looks like a negative number)
|
||||
only the last <em>width</em> characters are processed, else the first.
|
||||
Without <em>width</em> (or 0) all available characters are processed.
|
||||
</p>
|
||||
<p>
|
||||
If <em>precision</em> is specified, it indicates which matches to replace.
|
||||
With the <code>+</code> flag given, <em>precision</em> is the maximum
|
||||
number of matches to replace.
|
||||
Otherwise <em>precision</em> is the index (counting from 1) of the match to replace.
|
||||
Without <em>precision</em> (or 0), all matches are replaced.
|
||||
</p>
|
||||
<p>
|
||||
When replacing multiple matches, the next match is searched directly after the currently
|
||||
replaced string, so that the <em>subst</em> string itself will never be modified recursively.
|
||||
<span class="new">
|
||||
However if an empty string is matched, searching advances by 1 character in order to
|
||||
avoid matching the same empty string again.</span>
|
||||
</p>
|
||||
<p>
|
||||
In input, this converter pre-processes data received from the device before
|
||||
following converters read it.
|
||||
Converters preceding this one will read unmodified input.
|
||||
Thus place this converter before those whose input should be pre-processed.
|
||||
<span class="new">
|
||||
However, <a href="#chksum">checksum</a> converters will always use the unmodified
|
||||
input as sent by the device because the modified input would not match the checksum.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
In output it post-processes data already formatted by preceding converters
|
||||
before sending it to the device.
|
||||
Converters following this one will send their output unmodified.
|
||||
Thus place this converter after those whose output should be post-processed.
|
||||
</p>
|
||||
<p>
|
||||
Examples:
|
||||
<div class="indent">
|
||||
<code>%#+-10.2/ab/X/</code> replaces the string <code>ab</code> with <code>X</code>
|
||||
maximal 2 times in the last 10 characters.
|
||||
(<code>abcabcabcabc</code> becomes <code>abcXcXcabc</code>)
|
||||
</div>
|
||||
<div class="indent">
|
||||
<code>%#/\\/\//</code> replaces all <code>\</code> with <code>/</code>
|
||||
(<code>\dir\file</code> becomes <code>/dir/file</code>)
|
||||
</div>
|
||||
<div class="indent">
|
||||
<code>%#/..\B/&:/</code> inserts <code>:</code> after every second character
|
||||
which is not at the end of a word.
|
||||
(<code>0b19353134</code> becomes <code>0b:19:35:31:34</code>)
|
||||
</div>
|
||||
<div class="indent">
|
||||
<code>%#/://</code> removes all <code>:</code> characters.
|
||||
(<code>0b:19:35:31:34</code> becomes <code>0b19353134</code>)
|
||||
</div>
|
||||
<div class="indent">
|
||||
<code>%#/([^+-])*([+-])/\2\1/</code> moves a postfix sign to the front.
|
||||
(<code>1.23-</code> becomes <code>-1.23</code>)<br>
|
||||
</div>
|
||||
<div class="indent">
|
||||
<code>%#-2/.*/\U0/</code> converts the previous 2 characters to upper case.
|
||||
</div>
|
||||
<a name="mantexp"></a>
|
||||
<h2>15. MantissaExponent DOUBLE converter (<code>%m</code>)</h2>
|
||||
<p>
|
||||
This exotic and experimental format matches numbers in the format
|
||||
<i>[sign] mantissa sign exponent</i>, e.g <code>+123-4</code> meaning
|
||||
123e-4 or 0.0123. Mantissa and exponent are decimal integers.
|
||||
The sign of the mantissa is optional.
|
||||
Compared to the standard <code>%e</code> format, this format does not
|
||||
contain the characters <code>.</code> and <code>e</code>.
|
||||
</p>
|
||||
<p>
|
||||
Output formatting is ambigous (e.g. <code>123-4</code> versus
|
||||
<code>1230-5</code>). I chose the following convention:
|
||||
Format <em>precision</em> 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 <code>+</code>, <code>-</code>, and space are supported in
|
||||
the usual way (always sign, left justified, space instead of + sign).
|
||||
Flags <code>#</code> and <code>0</code> are unsupported.
|
||||
</p>
|
||||
<a name="timestamp"></a>
|
||||
<h2>16. Timestamp DOUBLE converter (<code>%T(<em>timeformat</em>)</code>)</h2>
|
||||
<p>
|
||||
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 <code>TIME</code> 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
|
||||
<em>strftime()</em> understands. In addition, fractions of a second can
|
||||
be specified and the time zone can be set in the format string.
|
||||
</p>
|
||||
<p>
|
||||
Example: <code>%(TIME)T(%d %b %Y %H:%M:%.3S %z)</code> may print something like
|
||||
<code> 3 Sep 2010 15:45:59 +0200</code>.
|
||||
</p>
|
||||
<p>
|
||||
Fractions of a second can be specified as <code>%.<em>n</em>S</code>
|
||||
(seconds with <em>n</em> fractional digits), as <code>%0<em>n</em>f</code>
|
||||
or <code>%<em>n</em>f</code> (<em>n</em> fractional digits) or as
|
||||
<code>%N</code> (nanoseconds).
|
||||
In input, <em>n</em> is the maximum number of digits parsed, there may be
|
||||
actually less digits in the input.
|
||||
If <em>n</em> is not specified (<code>%.S</code> or <code>%f</code>) it uses
|
||||
a default value of 6.
|
||||
</p>
|
||||
<p>
|
||||
In input, the time zone can be specified in the format like
|
||||
<code>%+<em>hhmm</em></code> or <code>%-<em>hhmm</em></code> for cases
|
||||
where the parsed time stamp does not specify the time zone, where
|
||||
<em>hhmm</em> is a 4 digit number specifying the offset in hours and minutes.
|
||||
</p>
|
||||
<p>
|
||||
In output, the system function <em>strftime()</em> is used to format the time.
|
||||
There may be differences in the implementation between operating systems.
|
||||
</p>
|
||||
<p>
|
||||
In input, <em>StreamDevice</em> uses its own implementation because many
|
||||
systems are missing the <em>strptime()</em> function and additional formats
|
||||
are supported.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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).
|
||||
</p>
|
||||
|
||||
<footer>
|
||||
<a href="processing.html">Next: Record Processing</a>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
146
docs/index.html
Normal file
@ -0,0 +1,146 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>EPICS <em>StreamDevice</em></h1>
|
||||
|
||||
<h2>What is <em>StreamDevice</em>?</h2>
|
||||
<p>
|
||||
<em>StreamDevice</em> is a generic
|
||||
<a href="https://epics.anl.gov/" 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 telnet-like TCP/IP.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> 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
|
||||
<a href="protocol.html"><em>protocol files</em></a> 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
|
||||
"<kbd>RF:FREQ 499.655 MHZ</kbd>" <em>StreamDevice</em> can be used.
|
||||
Formatting and parsing 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 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
|
||||
<a href="processing.html">processed</a>.
|
||||
It does not provide loops or branches.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> comes with an interface to<a target="ex"
|
||||
href="https://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>.
|
||||
Note that <em>StreamDevice</em> is not an alternative or replacement
|
||||
but a supplement for <em>asynDriver</em>.
|
||||
<em>StreamDevice</em> converts record values to and from strings but
|
||||
leaves it to <em>asynDriver</em> (or other bus interfaces) to exchange
|
||||
these strings with the device.
|
||||
Thus any bus type supported by <em>asynDriver</em> (to be exact by
|
||||
<em>asynOctet</em>) can automatically be used with <em>StreamDevice</em>.
|
||||
</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 protocol.
|
||||
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 intended for huge binary blocks of data that contain
|
||||
many process variables distributed over many records.
|
||||
Consider <a href="https://github.com/paulscherrerinstitute/regdev"
|
||||
target="ex"><em>regDev</em></a>
|
||||
for that.
|
||||
</p>
|
||||
<p>
|
||||
It is not a very flexible html, xml, json, etc. parser. Data needs to
|
||||
come in a predictible order to be parsable by <em>StreamDevice</em>.
|
||||
</p>
|
||||
|
||||
<h2>Recommended Readings</h2>
|
||||
<p>
|
||||
IOC Application Developer's Guide:
|
||||
<a href="https://epics.anl.gov/base/R3-14/12-docs/AppDevGuide/"
|
||||
target="ex">R3.14.12</a>,
|
||||
<a href="https://epics.anl.gov/base/R3-15/6-docs/AppDevGuide/AppDevGuide.html"
|
||||
target="ex">R3.15.6</a>,
|
||||
<a href="https://epics.anl.gov/base/R3-16/2-docs/AppDevGuide/AppDevGuide.html"
|
||||
target="ex">R3.16.2</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
||||
target="ex">EPICS Record Reference Manual</a>
|
||||
</p>
|
||||
|
||||
<h2>Color and Style Conventions</h2>
|
||||
<p>
|
||||
In this document, code is witten in <code>green fixed width font</code>.
|
||||
This marks text you typically type in configuration files etc.
|
||||
</p>
|
||||
<pre>
|
||||
Longer code segments are often set in a box.
|
||||
</pre>
|
||||
|
||||
<h2>Changes in Version 2.8</h2>
|
||||
<ul>
|
||||
<li>Support standard EPICS module build system.
|
||||
<li>Compatible with EPICS 7.
|
||||
<ul>
|
||||
<li>Support for new record types: int64in, int64out, lsi, lso.
|
||||
<li>Support for INT64 and UINT64 in aai, aao, waveform.
|
||||
</ul>
|
||||
<li>Run @init more often (e.g. when device re-connects or paused IOC is resumed).
|
||||
<li>Use "COMM" error code in .STAT when device is disconnected.
|
||||
<li>Allow spaces in protocol parameter list.
|
||||
<li>Support output redirect of all shell functions.
|
||||
<li>Fix building shared libraries on Windows.
|
||||
<li>Fix some C++11 warnings.
|
||||
<li>Fix several signed/unsigned problems.
|
||||
<li>Dropped support for cygnus-2.7.2 gcc (used by some old cygwin).
|
||||
<li>Several bug fixes.
|
||||
<li>Several documentation updates.
|
||||
</ul>
|
||||
|
||||
|
||||
<footer>
|
||||
<a href="setup.html">Next: Setup</a>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
78
docs/int64in.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: int64in Records</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>int64in Records</h1>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> The int64in (integer 64 bit input) record is only available from EPICS base R3.16 on.
|
||||
</p>
|
||||
|
||||
<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>
|
||||
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
78
docs/int64out.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: int64out Records</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>int64out Records</h1>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> The int64out (integer 64 bit output) record is only available from EPICS base R3.16 on.
|
||||
</p>
|
||||
|
||||
<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>
|
||||
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: longin Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>longin Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -25,6 +26,8 @@ written or read value.
|
||||
<dd>
|
||||
<u>Output:</u> <code><i>x</i>=VAL</code><br>
|
||||
<u>Input:</u> <code>VAL=<i>x</i></code>
|
||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||
on 64 bit machines.
|
||||
</dd>
|
||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||
<dd>
|
||||
@ -43,26 +46,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: longout Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>longout Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -25,6 +26,8 @@ written or read value.
|
||||
<dd>
|
||||
<u>Output:</u> <code><i>x</i>=VAL</code><br>
|
||||
<u>Input:</u> <code>VAL=<i>x</i></code>
|
||||
Using unsigned formats with values ≥ 0x800000 gives different results
|
||||
on 64 bit machines.
|
||||
</dd>
|
||||
<dt>ENUM format (e.g. <code>%{</code>):</dt>
|
||||
<dd>
|
||||
@ -43,26 +46,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
79
docs/lsi.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: lsi Records</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>lsi Records</h1>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> The lsi (long string in) record is only available from EPICS base R3.15 on.
|
||||
</p>
|
||||
|
||||
<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><br>
|
||||
Also the <code>LEN</code> field is set to the length of the input
|
||||
including possible null bytes.
|
||||
</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>
|
||||
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
79
docs/lso.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: lso Records</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>lso Records</h1>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> The lso (long string out) record is only available from EPICS base R3.15 on.
|
||||
</p>
|
||||
|
||||
<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><br>
|
||||
Also the <code>LEN</code> field is set to the length of the input
|
||||
including possible null bytes.
|
||||
</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>
|
||||
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
59
docs/makepdf
Executable file
@ -0,0 +1,59 @@
|
||||
#/bin/sh
|
||||
wkhtmltopdf --enable-local-file-access -V >/dev/null 2>&1
|
||||
case $? in
|
||||
127)
|
||||
echo "wkhtmltopdf not installed." >&2
|
||||
echo "See https://wkhtmltopdf.org" >&2
|
||||
exit 1
|
||||
;;
|
||||
0)
|
||||
# have (and need) --enable-local-file-access
|
||||
ENABLE_FILE_ACCESS=--enable-local-file-access
|
||||
;;
|
||||
1)
|
||||
# have no (and need no) --enable-local-file-access
|
||||
;;
|
||||
*)
|
||||
# Some error but I don't know what it means. Try anyway.
|
||||
;;
|
||||
esac
|
||||
|
||||
PAGES="
|
||||
index.html
|
||||
setup.html
|
||||
epics3_13.html
|
||||
protocol.html
|
||||
formats.html
|
||||
processing.html
|
||||
recordtypes.html
|
||||
aai.html
|
||||
aao.html
|
||||
ai.html
|
||||
ao.html
|
||||
bi.html
|
||||
bo.html
|
||||
calcout.html
|
||||
int64in.html
|
||||
int64out.html
|
||||
longin.html
|
||||
longout.html
|
||||
lsi.html
|
||||
lso.html
|
||||
mbbiDirect.html
|
||||
mbboDirect.html
|
||||
mbbi.html
|
||||
mbbo.html
|
||||
scalcout.html
|
||||
stringin.html
|
||||
stringout.html
|
||||
waveform.html
|
||||
tipsandtricks.html
|
||||
recordinterface.html
|
||||
businterface.html
|
||||
formatconverter.html
|
||||
osinterface.html
|
||||
"
|
||||
|
||||
rm -f stream.pdf
|
||||
wkhtmltopdf --print-media-type --page-size Letter \
|
||||
$ENABLE_FILE_ACCESS $PAGES stream.pdf
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: mbbi Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>mbbi Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -69,26 +70,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: mbbiDirect Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>mbbiDirect Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -55,26 +56,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: mbbo Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>mbbo Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -22,7 +23,7 @@ written or read value.
|
||||
<dd>
|
||||
Not allowed.
|
||||
</dd>
|
||||
<dt>LONG format (e.g. <code>%i</code>):</dt>
|
||||
<dt>LONG <span class=new>or ENUM</span> format (e.g. <code>%i</code>):</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
|
||||
@ -32,25 +33,20 @@ written or read value.
|
||||
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>
|
||||
<u>Input:</u> <code>RBV=RVAL=<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>.
|
||||
<code><i>x</i>=RVAL</code> and <code>RBV=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 class=new>
|
||||
<u>Output:</u> <code><i>x</i>=(VAL<<SHFT)&MASK</code><br>
|
||||
<u>Input:</u> <code>VAL=(RBV=(<i>x</i>&MASK))>>SHFT</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>
|
||||
@ -65,31 +61,34 @@ written or read value.
|
||||
<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.
|
||||
present.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: mbboDirect Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>mbboDirect Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -22,26 +23,23 @@ written or read value.
|
||||
<dd>
|
||||
Not allowed.
|
||||
</dd>
|
||||
<dt>LONG format (e.g. <code>%i</code>):</dt>
|
||||
<dt>LONG or ENUM 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>
|
||||
<u>Output:</u> <code><i>x</i>=RVAL</code><br>
|
||||
<u>Input:</u> <code>RAL=<i>x</i></code>, <code>VAL=RVAL>>SHFT</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>
|
||||
<u>Input:</u> <code>RBV=RVAL=<i>x</i>&MASK</code>, <code>VAL=RVAL>>SHFT</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.
|
||||
left by <code>SHFT</code> (<code>((2^NOBT)-1)<<SHFT</code>).
|
||||
The record calculates <code>RVAL=VAL<<SHFT</code>.
|
||||
</dd>
|
||||
<dt>STRING format (e.g. <code>%s</code>):</dt>
|
||||
<dd>
|
||||
@ -52,31 +50,34 @@ written or read value.
|
||||
<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>.
|
||||
present.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
229
docs/nav.html
Normal file
@ -0,0 +1,229 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Navbar</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
<style type="text/css">
|
||||
<!--
|
||||
body {margin:0 0 13ex 1em;
|
||||
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
font-weight:bold;
|
||||
font-size:13px;
|
||||
background-color:#e3eaf6;}
|
||||
a {text-decoration:none;}
|
||||
a:link {color:#333333;}
|
||||
a:visited {color:#333333;}
|
||||
a:hover {color:#FF0000;}
|
||||
a:active {color:#FF0000;}
|
||||
|
||||
h1 {font-size:120%;
|
||||
margin-top: 20px;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 10px;
|
||||
color:#267ab8;}
|
||||
|
||||
div {border-bottom:1px solid black;
|
||||
padding-top:1ex;}
|
||||
|
||||
div div, div div div, div:hover div div
|
||||
{
|
||||
padding-top:0;
|
||||
margin-right:.1em;
|
||||
border:none;
|
||||
box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
padding 0;
|
||||
display:block;
|
||||
position:relative;
|
||||
}
|
||||
div div
|
||||
{display:none;
|
||||
margin-left:2em;
|
||||
margin-right:1em;
|
||||
background-color:#e3eaf6;
|
||||
padding:0 .5em .5ex .5em;
|
||||
border-width:0 thick thick 1px;
|
||||
border-color:black;
|
||||
border-style:solid;
|
||||
}
|
||||
:root *> div div
|
||||
{border-width:0 1px 1px 1px;
|
||||
box-shadow: 5px 5px 5px black;
|
||||
-moz-box-shadow: 5px 5px 5px black;
|
||||
-webkit-box-shadow: 5px 5px 5px black;
|
||||
}
|
||||
div:hover div {
|
||||
position:absolute;
|
||||
display:block;}
|
||||
|
||||
div div div {margin-left:0;}
|
||||
|
||||
a {display:block;
|
||||
margin-top:.3ex;}
|
||||
|
||||
div div a {display:list-item;
|
||||
margin-left:1em;
|
||||
list-style-type:disc;
|
||||
}
|
||||
|
||||
div div div a {list-style-type:circle;}
|
||||
|
||||
-->
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>User's Guide</h1>
|
||||
<div>
|
||||
<a target="_parent" href="index.html">Intro</a>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="setup.html">Setup</a>
|
||||
<a href="javascript:show('setup')" id="setupButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="setup.html#pre">Prerequisites</a>
|
||||
<div>
|
||||
<a target="_parent" href="epics3_13.html">Using EPICS 3.13</a>
|
||||
</div>
|
||||
<a target="_parent" href="setup.html#lib">Build Library</a>
|
||||
<a target="_parent" href="setup.html#app">Build Application</a>
|
||||
<a target="_parent" href="setup.html#sta">Startup Script</a>
|
||||
<a target="_parent" href="setup.html#pro">Protocol File</a>
|
||||
<div>
|
||||
<a target="_parent" href="setup.html#reload">Reloading</a>
|
||||
</div>
|
||||
<a target="_parent" href="setup.html#debug">Debugging</a>
|
||||
<a target="_parent" href="setup.html#rec">Records</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="protocol.html">Protocol Files</a>
|
||||
<a href="javascript:show('protocol')" id="protocolButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="protocol.html#gen">General</a>
|
||||
<a target="_parent" href="protocol.html#proto">Protocols</a>
|
||||
<a target="_parent" href="protocol.html#cmd">Commands</a>
|
||||
<a target="_parent" href="protocol.html#str">Strings</a>
|
||||
<a target="_parent" href="protocol.html#var">Variables</a>
|
||||
<div>
|
||||
<a target="_parent" href="protocol.html#sysvar">System variables</a>
|
||||
<a target="_parent" href="protocol.html#argvar">Protocol Arguments</a>
|
||||
<a target="_parent" href="protocol.html#usrvar">User variables</a>
|
||||
</div>
|
||||
<a target="_parent" href="protocol.html#except">Exception Handlers</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="formats.html">Format Converters</a>
|
||||
<a href="javascript:show('formats')" id="formatsButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="formats.html#syntax">Syntax</a>
|
||||
<a target="_parent" href="formats.html#types">Types & Fields</a>
|
||||
<a target="_parent" href="formats.html#stdd" title="Standard DOUBLE converters">%f %e %g</a>
|
||||
<a target="_parent" href="formats.html#stdl" title="Standard LONG converters">%i %d %u %o %x</a>
|
||||
<a target="_parent" href="formats.html#stds" title="Standard STRING converters">%s %c</a>
|
||||
<a target="_parent" href="formats.html#cset" title="Character set STRING converter">%[<em>charset</em>]</a>
|
||||
<a target="_parent" href="formats.html#enum" title="Enumeration LONG converter">%{<em>s0</em>|<em>s1</em>|...}</a>
|
||||
<a target="_parent" href="formats.html#bin" title="Binary LONG converter">%b %B</a>
|
||||
<a target="_parent" href="formats.html#raw" title="Raw LONG converter">%r</a>
|
||||
<a target="_parent" href="formats.html#rawdouble" title="Raw DOUBLE converter">%R</a>
|
||||
<a target="_parent" href="formats.html#bcd" title="Binary coded decimal LONG converter">%D</a>
|
||||
<a target="_parent" href="formats.html#chksum" title="Checksum pseudo converter">%<<em>checksum</em>></a>
|
||||
<a target="_parent" href="formats.html#regex" title="Perl regular expression STRING converter">%/<em>regex</em>/</a>
|
||||
<a target="_parent" href="formats.html#regsub" title="Perl regular expression substitution pseudo converter">%#/<em>regex</em>/<em>subst</em>/</a>
|
||||
<a target="_parent" href="formats.html#mantexp" title="MantissaExponent DOUBLE converter">%m</a>
|
||||
<a target="_parent" href="formats.html#timestamp" title="Timestamp DOUBLE converter">%T</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="processing.html">Record Processing</a>
|
||||
<a href="javascript:show('proc')" id="procButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="processing.html#proc">Normal Processing</a>
|
||||
<a target="_parent" href="processing.html#init">Initialization</a>
|
||||
<a target="_parent" href="processing.html#iointr">I/O Intr</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="recordtypes.html">Record Types</a>
|
||||
<a href="javascript:show('records')" id="recordsButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="aai.html">aai</a>
|
||||
<a target="_parent" href="aao.html">aao</a>
|
||||
<a target="_parent" href="ai.html">ai</a>
|
||||
<a target="_parent" href="ao.html">ao</a>
|
||||
<a target="_parent" href="bi.html">bi</a>
|
||||
<a target="_parent" href="bo.html">bo</a>
|
||||
<a target="_parent" href="calcout.html">calcout</a>
|
||||
<a target="_parent" href="int64in.html">int64in</a>
|
||||
<a target="_parent" href="int64out.html">int64out</a>
|
||||
<a target="_parent" href="longin.html">longin</a>
|
||||
<a target="_parent" href="longout.html">longout</a>
|
||||
<a target="_parent" href="lsi.html">lsi</a>
|
||||
<a target="_parent" href="lso.html">lso</a>
|
||||
<a target="_parent" href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a target="_parent" href="mbboDirect.html">mbboDirect</a>
|
||||
<a target="_parent" href="mbbi.html">mbbi</a>
|
||||
<a target="_parent" href="mbbo.html">mbbo</a>
|
||||
<a target="_parent" href="scalcout.html">scalcout</a>
|
||||
<a target="_parent" href="stringin.html">stringin</a>
|
||||
<a target="_parent" href="stringout.html">stringout</a>
|
||||
<a target="_parent" href="waveform.html">waveform</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="tipsandtricks.html">Tips & Tricks</a>
|
||||
<a href="javascript:show('tipsandtricks')" id="tipsandtricksButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="tipsandtricks.html#argvar">Many almost identical protocols</a>
|
||||
<a target="_parent" href="tipsandtricks.html#iointr">Read unsolicited input</a>
|
||||
<a target="_parent" href="tipsandtricks.html#multiline">Read multi-line messages</a>
|
||||
<a target="_parent" href="tipsandtricks.html#writemany">Write more than one value in one message</a>
|
||||
<a target="_parent" href="tipsandtricks.html#readmany">Read more than one value from one message</a>
|
||||
<a target="_parent" href="tipsandtricks.html#mixed">Read values of mixed data type</a>
|
||||
<a target="_parent" href="tipsandtricks.html#web">Read a web page</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Programmer's Guide</h1>
|
||||
<div>
|
||||
<a target="_parent" href="recordinterface.html">Record API</a>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="businterface.html">Bus API</a>
|
||||
<a href="javascript:show('bus')" id="busButton"></a>
|
||||
<div>
|
||||
<a target="_parent" href="businterface.html#class">Interface Class</a>
|
||||
<a target="_parent" href="businterface.html#theory">Theory of Operation</a>
|
||||
<div>
|
||||
<a target="_parent" href="businterface.html#registration">Registration</a>
|
||||
<a target="_parent" href="businterface.html#create">Creation & deletion</a>
|
||||
<a target="_parent" href="businterface.html#connect">Connecting</a>
|
||||
<a target="_parent" href="businterface.html#lock">Bus locking</a>
|
||||
<a target="_parent" href="businterface.html#write">Writing output</a>
|
||||
<a target="_parent" href="businterface.html#read">Reading input</a>
|
||||
<a target="_parent" href="businterface.html#event">Handling events</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="formatconverter.html">Format Converter API</a>
|
||||
<div>
|
||||
<a target="_parent" href="formatconverter.html#class">Converter Class</a>
|
||||
<a target="_parent" href="formatconverter.html#theory">Theory of Operation</a>
|
||||
<div>
|
||||
<a target="_parent" href="formatconverter.html#registration">Registration</a>
|
||||
<a target="_parent" href="formatconverter.html#parsing">Parsing</a>
|
||||
<a target="_parent" href="formatconverter.html#printing_scanning">Printing and Scanning</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a target="_parent" href="osinterface.html">Operating System API</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
22
docs/osinterface.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: Operating System API</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Operating System API</h1>
|
||||
|
||||
<h2>Sorry, this documentation is still missing.</h2>
|
||||
|
||||
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,21 +1,22 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: Record Processing</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>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"
|
||||
(see <a href="http://www.aps.anl.gov/epics/base/R3-14/12-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>
|
||||
@ -53,22 +54,23 @@ its <code>SEVR</code> field set to <code>INVALID</code> and its
|
||||
<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>).
|
||||
The device could not be locked (<code>LockTimeout</code>) because
|
||||
other records are keeping the device busy or the device did not reply
|
||||
in time (<a href="protocol.html#sysvar"><code>ReplyTimeout</code></a>).
|
||||
</dd>
|
||||
<dt><code>WRITE</code></dt>
|
||||
<dd>
|
||||
Output could not be written to the device (<code>WriteTimeout</code>).
|
||||
Output could not be written to the device in time
|
||||
(<a href="protocol.html#sysvar"><code>WriteTimeout</code></a>).
|
||||
</dd>
|
||||
<dt><code>READ</code></dt>
|
||||
<dd>
|
||||
Input from the device started but stopped unexpectedly
|
||||
(<code>ReadTimeout</code>).
|
||||
(<a href="protocol.html#sysvar"><code>ReadTimeout</code></a>).
|
||||
</dd>
|
||||
<dt><code>COMM</code></dt>
|
||||
<dd>
|
||||
The device driver reported some other communication error (e.g.
|
||||
unplugged cable).
|
||||
The device driver reported that the device is disconnected.
|
||||
</dd>
|
||||
<dt><code>CALC</code></dt>
|
||||
<dd>
|
||||
@ -94,13 +96,14 @@ will be set according to the original error.
|
||||
<a name="init"></a>
|
||||
<h2>2. Initialization</h2>
|
||||
<p>
|
||||
Often, it is required to initialize records from the hardware after
|
||||
Often, it is useful 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.
|
||||
before any scan task starts <span class="new">and may be re-run
|
||||
later under circumstances listed below</span>.
|
||||
</p>
|
||||
<p>
|
||||
In contrast to <a href="#proc">normal processing</a>, the protocol
|
||||
@ -118,7 +121,7 @@ If the handler fails, the record remains uninitialized:
|
||||
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.
|
||||
forward links or any links with the <code>PP</code> flag.
|
||||
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
|
||||
@ -145,6 +148,33 @@ 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>
|
||||
<p>
|
||||
The <code>@init</code> handler is called in the following situations:
|
||||
<ul>
|
||||
<li>At startup by <code>iocInit</code> during record initialization
|
||||
as described above.
|
||||
<li class="new">When the IOC is resumed with <code>iocRun</code> (after
|
||||
beeing paused with <code>iocPause</code>) before the scan tasks
|
||||
restart and before records with <code>PINI=RUN</code> are processed.
|
||||
<li class="new">When the protocol is
|
||||
<a href="setup.html#reload">reloaded</a></span> for example with
|
||||
<code>streamReload ["<var>recordname</var>"]</code>.
|
||||
<li class="new">When <em>StreamDevice</em> detects that the device has
|
||||
reconnected (after being disconnected). This includes the case that
|
||||
the device was disconnected when the IOC started.
|
||||
Be aware that some drivers test the connection only periodically,
|
||||
e.g. the <em>asynIPPort</em> driver tests it every few seconds.
|
||||
Thus there may be a small delay between the device being online
|
||||
and the record re-initializing.
|
||||
<li class="new">When <code>streamReinit
|
||||
"<var>asynPortname</var>"[,<var>addr</var>]</code> is called
|
||||
(if using an <em>asynDriver</em> port).
|
||||
<li class="new">When the "magic value" <code>2</code> is written to the
|
||||
<code>.PROC</code> field of the record.
|
||||
In this case the record is processed and thus its <code>FLNK</code>
|
||||
and links with the <code>PP</code> flag are triggered.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<a name="iointr"></a>
|
||||
<h2>3. I/O Intr</h2>
|
||||
@ -236,9 +266,10 @@ 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>
|
||||
|
||||
<footer>
|
||||
<a href="recordtypes.html">Next: Supported Record Types</a>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: Protocol Files</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Protocol Files</h1>
|
||||
<a name="gen"></a>
|
||||
<h2>1. General Information</h2>
|
||||
<p>
|
||||
@ -241,8 +242,12 @@ that hex value.<br>
|
||||
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> in input matches any byte, in output it does not print
|
||||
anything.<br>
|
||||
<span class="new">
|
||||
<code>\_</code> in input matches any amount of white space (including none),
|
||||
in output it prints a single space.<br>
|
||||
</span>
|
||||
<code>\$</code> followed by the name of a
|
||||
<a href="#var">protocol varible</a> 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).
|
||||
<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.
|
||||
number in the range of <code>-128</code> to <code>255</code>,
|
||||
<code>-0x80</code> to <code>0xff</code> (not case sesitive),
|
||||
or <code>-0200</code> to <code>0377</code>, respectively.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> also recognizes the ASCII symbolic names
|
||||
(not case sensitive) for several byte codes:<br>
|
||||
<code>NUL </code>(= <code>0x00</code>) <em>null</em><br>
|
||||
<code>SOH </code>(= <code>0x01</code>) <em>start of heading</em><br>
|
||||
<code>STX </code>(= <code>0x02</code>) <em>start of text</em><br>
|
||||
<code>ETX </code>(= <code>0x03</code>) <em>end of text</em><br>
|
||||
<code>EOT </code>(= <code>0x04</code>) <em>end of transmission</em><br>
|
||||
<code>ENQ </code>(= <code>0x05</code>) <em>enquiry</em><br>
|
||||
<code>ACK </code>(= <code>0x06</code>) <em>acknowledge</em><br>
|
||||
<code>BEL </code>(= <code>0x07</code>) <em>bell</em><br>
|
||||
<code>BS </code>(= <code>0x08</code>) <em>backspace</em><br>
|
||||
<code>HT</code> or <code>TAB</code> (= <code>0x09</code>) <em>horizontal tabulator</em><br>
|
||||
<code>LF</code> or <code>NL</code> (= <code>0x0A</code> or <code>10</code>) <em>line feed / new line</em><br>
|
||||
<code>VT </code>(= <code>0x0B</code> or <code>11</code>) <em>vertical tabulator</em><br>
|
||||
<code>FF</code> or <code>NP</code> (= <code>0x0C</code> or <code>12</code>) <em>form feed / new page</em><br>
|
||||
<code>CR </code>(= <code>0x0D</code> or <code>13</code>) <em>carriage return</em><br>
|
||||
<code>SO </code>(= <code>0x0E</code> or <code>14</code>) <em>shift out</em><br>
|
||||
<code>SI </code>(= <code>0x0F</code> or <code>15</code>) <em>shift in</em><br>
|
||||
<code>DLE </code>(= <code>0x10</code> or <code>16</code>) <em>data link escape</em><br>
|
||||
<code>DC1 </code>(= <code>0x11</code> or <code>17</code>) <em>device control 1</em><br>
|
||||
<code>DC2 </code>(= <code>0x12</code> or <code>18</code>) <em>device control 2</em><br>
|
||||
<code>DC3 </code>(= <code>0x13</code> or <code>19</code>) <em>device control 3</em><br>
|
||||
<code>DC4 </code>(= <code>0x14</code> or <code>20</code>) <em>device control 4</em><br>
|
||||
<code>NAK </code>(= <code>0x15</code> or <code>21</code>) <em>negative acknowledge</em><br>
|
||||
<code>SYN </code>(= <code>0x16</code> or <code>22</code>) <em>synchronous idle</em><br>
|
||||
<code>ETB </code>(= <code>0x17</code> or <code>23</code>) <em>end of transmission block</em><br>
|
||||
<code>CAN </code>(= <code>0x18</code> or <code>24</code>) <em>cancel</em><br>
|
||||
<code>EM </code>(= <code>0x19</code> or <code>25</code>) <em>end of medium</em><br>
|
||||
<code>SUB </code>(= <code>0x1A</code> or <code>26</code>) <em></em>substitute<br>
|
||||
<code>ESC </code>(= <code>0x1B</code> or <code>27</code>) <em>escape</em><br>
|
||||
<code>FS </code>(= <code>0x1C</code> or <code>28</code>) <em>file separator</em><br>
|
||||
<code>GS </code>(= <code>0x1D</code> or <code>29</code>) <em>group separator</em><br>
|
||||
<code>RS </code>(= <code>0x1E</code> or <code>30</code>) <em>record separator</em><br>
|
||||
<code>US </code>(= <code>0x1F</code> or <code>31</code>) <em>unit separator</em><br>
|
||||
<code>DEL </code>(= <code>0x7F</code> or <code>127</code>) <em>delete</em><br>
|
||||
<code>SKIP</code> or <code>?</code> 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>
|
||||
<h3>Examples:</h3>
|
||||
<p>
|
||||
The following lines represent the same string:<br>
|
||||
<code>"Hello world\r\n"</code><br>
|
||||
@ -360,6 +390,9 @@ what they influence.
|
||||
the moment.
|
||||
How many milliseconds to wait after last poll or last received
|
||||
input before polling again?
|
||||
A good value is about half the time of the expected input period.
|
||||
Longer values cause latency and shorter values may increase CPU
|
||||
consumption.
|
||||
If not set the same value as for <code>ReplyTimeout</code> is
|
||||
used.
|
||||
</dd>
|
||||
@ -408,9 +441,12 @@ what they influence.
|
||||
(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
|
||||
<span class="new">
|
||||
<strike>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.
|
||||
an <code>in</code> command.</strike> To match arbitrary amount of
|
||||
whitespace in input, use <code>"\_"</code>.
|
||||
</span>
|
||||
</dd>
|
||||
<dt><code>ExtraInput = Error;</code></dt>
|
||||
<dd>
|
||||
@ -446,12 +482,63 @@ To make this easier, <em>protocol arguments</em> can be used:
|
||||
move { out "\$1 GOTO %d"; }
|
||||
</pre>
|
||||
<p>
|
||||
Now, the protocol can be references in the <code>OUT</code> link
|
||||
Now the same protocol can be used 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>
|
||||
<p>
|
||||
Up to 9 parameters can be specified in parentheses, separated by comma.
|
||||
In the protocol, they are referenced as <code>$1</code> ...
|
||||
<code>$9</code> outside quotes or <code>\$1</code> ... <code>\$9</code>
|
||||
within quotes. The parameter <code>$0</code> resolves to the protocol name.
|
||||
</p>
|
||||
<div class="new">
|
||||
<p>
|
||||
To make links more readable, one space is allowed before and after each comma
|
||||
and the enclosing parentheses. This space is not part of the parameter string.
|
||||
Any additional space is part of the parameter.
|
||||
</p>
|
||||
<p>
|
||||
If a parameter contains matching pairs of parentheses, these and all commas
|
||||
inside are part of the parameter.
|
||||
This allows to pass parameter strings like <code>(1,2)</code> easily without
|
||||
much escaping.
|
||||
</p>
|
||||
<p>
|
||||
Unmatched parentheses must be escaped with double backslash <code>\\</code>
|
||||
as well as must be commas outside pairs of parentheses.
|
||||
Double backslash is necessary because one backslash is already consumed by
|
||||
the db file parser.
|
||||
To pass a literal backslash in a parameter string use 4 backslashes
|
||||
<code>\\\\</code>.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Note that macros can be used in parameters. That makes it possible to
|
||||
pass part of the record name to the protocol to be used in
|
||||
<a href="formats.html#redirection">redirections</a>.
|
||||
</p>
|
||||
|
||||
<h4>Example:</h3>
|
||||
<pre>
|
||||
record(ai, "$(PREFIX)recX5") {
|
||||
field(DTYP, "stream")
|
||||
field(INP, "@$(PROTOCOLFILE) read(5, X\\,Y $(PREFIX)) $(PORT)")
|
||||
}
|
||||
record(ai, "$(PREFIX)recY5") {}
|
||||
|
||||
read { out 0x8$1 "READ \$2"; in "%f,%(\$3recY\$1)f" }
|
||||
</pre>
|
||||
<p>
|
||||
The protocol resolves to:
|
||||
</p>
|
||||
<pre>
|
||||
read { out 0x85 "READ X,Y"; in "%f,%($(PREFIX)recY5)f" }
|
||||
</pre>
|
||||
<p>
|
||||
Here <code>$(PREFIX)</code> is replaced with its macro value.
|
||||
But be aware that the macro is actually replaced before the link is parsed so
|
||||
that macro values containing comma or parentheses may have unintended effects.
|
||||
</p>
|
||||
|
||||
<a name="usrvar"></a>
|
||||
@ -523,14 +610,13 @@ There is a fixed set of exception handler names starting with
|
||||
<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
|
||||
This handler 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>.
|
||||
See also chapter <a href="processing.html#init">Record Processing</a>.
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Example:</h3>
|
||||
<h4>Example:</h3>
|
||||
<pre>
|
||||
setPosition {
|
||||
out "POS %f";
|
||||
@ -544,9 +630,10 @@ 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>
|
||||
|
||||
<footer>
|
||||
<a href="formats.html">Next: Format Converters</a>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
328
docs/recordinterface.html
Normal file
@ -0,0 +1,328 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: Record API</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Record API</h1>
|
||||
|
||||
<a name="theory"></a>
|
||||
<h2>Theory of Operation</h2>
|
||||
<p>
|
||||
<em>StreamDevice</em> implements the generic part of an EPICS device support.
|
||||
However it cannot know the internals of a specific record type, such as the
|
||||
.VAL or .RVAL fields or the .INP or .OUT links. It can only access a record
|
||||
as dbCommon. Thus it is necessary to write an interface for each record type
|
||||
which takes care of these details.
|
||||
</p>
|
||||
<p>
|
||||
A record interface consists of three functions, <code>readData()</code> and
|
||||
<code>writeData()</code> and <code>initRecord()</code>.
|
||||
</p>
|
||||
The record interface also implements the device support structure for this
|
||||
record type. Most of its functions will be generic <em>StreamDevice</em>
|
||||
functions. The exception is <code>initRecord()</code>.
|
||||
</p>
|
||||
<p>
|
||||
The name of the device support structure must have the form
|
||||
<code>dev<var>recordtype</var>Stream</code> and the name of the record
|
||||
interface source code file must be
|
||||
<code>dev<var>recordtype</var>Stream.c</code> to work seamlessly with the
|
||||
build system implemented in the Makefile of <em>StreamDevice</em>.
|
||||
</p>
|
||||
<p>
|
||||
Finally add <code><var>recordtype</var></code> to the
|
||||
<code>RECORDTYPES</code> variable in the file src/CONFIG_STREAM
|
||||
and rebuild.
|
||||
</p>
|
||||
<a name="headers"></a>
|
||||
<h3>Headers to Include</h2>
|
||||
<p>
|
||||
A record interface typically <code>#include</code>s the header file
|
||||
for the supported record type, <code>"<var>recordtype</var>Record.h"</code>
|
||||
and <code>"devStream.h"</code>.
|
||||
For many record interfaces this is sufficient, but sometimes additional
|
||||
header files may be needed.
|
||||
</p>
|
||||
|
||||
<a name="functions"></a>
|
||||
<h3>Functions to Implement</h2>
|
||||
<p>
|
||||
A record interface has to implement three functions:
|
||||
</p>
|
||||
<div class="indent"><code>
|
||||
static long readData(dbCommon *record, format_t *format);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
static long writeData(dbCommon *record, format_t *format);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
static long initRecord(dbCommon *record);
|
||||
</code></div>
|
||||
|
||||
<h4>writeData</h4>
|
||||
<p>
|
||||
The function <code>writeData()</code> is called whenever a
|
||||
<a href="protocol.html#proto">protocol</a> needs
|
||||
to handle a prining <a href="formats.html">format converter</a>
|
||||
(without <a href="formats.html#redirection">redirection</a>),
|
||||
typically in an <code>out</code> command.
|
||||
It is also possible that <code>writeData()</code> is called for an input
|
||||
record, e.g. when the <a href="formats.html#syntax"><code>=</code> flag</a>
|
||||
is used in an <code>in</code> command.
|
||||
Thus implement this function for input records as well.
|
||||
</p>
|
||||
<p>
|
||||
The functions is called with a <code>dbCommon *record</code> argument,
|
||||
which the function should cast to the specific record type to get
|
||||
access to the record specific fields, in particular .VAL and .RVAL.
|
||||
</p>
|
||||
<p>
|
||||
The second argument, <code>format_t *format</code>, contains information
|
||||
about the format converter. The only field of interest in this argument
|
||||
is <code>format->type</code> which specifies the data type of the format
|
||||
conversion. Its value is one of <code>DBF_ULONG</code>,
|
||||
<code>DBF_ULONG</code>, <code>DBF_ENUM</code>, <code>DBF_DOUBLE</code>,
|
||||
or <code>DBF_STRING</code>.
|
||||
</p>
|
||||
<p>
|
||||
The <code>writeData()</code> function may access different fields depending
|
||||
on <code>format->type</code>, e.g. .VAL for <code>DBF_DOUBLE</code> but
|
||||
.RVAL for <code>DBF_LONG</code>.
|
||||
It also may interpret the fields in a different way, e.g. cast to
|
||||
<code>long</code> for <code>DBF_LONG</code> but to <code>unsigned long</code>
|
||||
for <code>DBF_ULONG</code>.
|
||||
This is typically done with a <code>switch(format->type)</code> statement.
|
||||
</p>
|
||||
<p>
|
||||
The function may refuse to handle <code>format->type</code> values
|
||||
that make no sense for the record type, e.g. <code>DBF_STRING</code> for a
|
||||
record type that cannot handle strings. In that case the function should
|
||||
return <code>ERROR</code>. It is a good idea to return <code>ERROR</code>
|
||||
in the <code>default</code> part of the <code>switch</code> statement.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> provides a function to output a value from the record:
|
||||
</p>
|
||||
<div class="indent"><code>
|
||||
long streamPrintf(dbCommon *record, format_t *format, ...);
|
||||
</code></div>
|
||||
<p>
|
||||
Once the correct record field and type cast has been chosen, the
|
||||
<code>writeData()</code> function calls
|
||||
<code>return streamPrintf(record, format, value)</code> where the type of
|
||||
value should match <code>field->type</code> (<code>long</code>,
|
||||
<code>unsigned long</code>, <code>double</code>, or <code>char*</code>),
|
||||
returning the result of that call.
|
||||
</p>
|
||||
<p>
|
||||
<b>Example:</b>
|
||||
</p>
|
||||
<pre>
|
||||
static long writeData(dbCommon *record, format_t *format)
|
||||
{
|
||||
<var>recordtype</var>Record *rec = (<var>recordtype</var>Record *)record;
|
||||
|
||||
switch (format->type)
|
||||
{
|
||||
case DBF_ULONG:
|
||||
case DBF_ENUM:
|
||||
return streamPrintf(record, format, (unsigned long)rec->rval);
|
||||
case DBF_LONG:
|
||||
return streamPrintf(record, format, (long)rec->rval);
|
||||
case DBF_DOUBLE:
|
||||
return streamPrintf(record, format, rec->val);
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4>readData</h4>
|
||||
<p>
|
||||
The arguments of this function are the same as for <code>writeData()</code>.
|
||||
But this function stores a value into record fields depending on
|
||||
<code>format->type</code>.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> provides two functions to receive a value;
|
||||
</p>
|
||||
<div class="indent"><code>
|
||||
ssize_t streamScanf(dbCommon *record, format_t *format, void* value);
|
||||
</code></div>
|
||||
<div class="indent"><code>
|
||||
ssize_t streamScanfN(dbCommon *record, format_t *format, void* value, size_t maxStringSize);
|
||||
</code></div>
|
||||
<p>
|
||||
The argument <code>value</code> is a pointer to the variable where the value
|
||||
is to be stored. Its type must match <code>field->type</code>
|
||||
(<code>long*</code>, <code>unsigned long*</code>, <code>double*</code>, or
|
||||
<code>char*</code>).
|
||||
</p>
|
||||
<p>
|
||||
The <code>streamScanfN()</code> function is meant for strings and gets the
|
||||
additional argument <code>maxStringSize</code> to specify the size of the
|
||||
string buffer.
|
||||
</p>
|
||||
<p>
|
||||
The <code>streamScanf()</code> function is actually a macro calling
|
||||
<code>streamScanfN()</code> with <code>MAX_STRING_SIZE</code> (=40) for
|
||||
the last argument. For <code>field->type</code> values other than
|
||||
<code>DBF_STRING</code>, this argument is ignored.
|
||||
</p>
|
||||
<p>
|
||||
In case of strings, these functions return the number of characters
|
||||
actually stored (which may be less than <code>maxStringSize</code>).
|
||||
Some record types may want to store this value into a field of the record.
|
||||
</p>
|
||||
<p>
|
||||
The functions return <code>ERROR</code> on failure. In this case the
|
||||
<code>readData()</code> function should return <code>ERROR</code> as well.
|
||||
Otherwise the function should store the value received into the appropriate
|
||||
record field.
|
||||
</p>
|
||||
<p>
|
||||
If <code>record->pact</code> is <code>true</code>, the function
|
||||
should now return <code>OK</code> or <code>DO_NOT_CONVERT</code> (=2),
|
||||
depending on wheter conversion from .RVAL to .VAL should be left to the
|
||||
record or not.
|
||||
</p>
|
||||
<p>
|
||||
If <code>record->pact</code> is <code>false</code>, the record is curretly
|
||||
executing the <code>@init</code> handler.
|
||||
This typically only affects output records.
|
||||
As the record is not processed by EPICS at this time, changes in fields would
|
||||
not trigger monitor updates.
|
||||
</p>
|
||||
<p>
|
||||
Also the record will not convert .RVAL to .VAL in this case, thus the
|
||||
<code>readData()</code> function should now convert .RVAL
|
||||
to .VAL as usually done by the record.
|
||||
</p>
|
||||
<p>
|
||||
In order to make monitors work properly, the <code>readData()</code> function
|
||||
should then first call <code>recGblResetAlarms()</code> and then call
|
||||
<code>db_post_events()</code> as needed. Usually the code
|
||||
from the record support function <code>monitor()</code> needs to be copied.
|
||||
Unfortunately the <code>monitor()</code> function of the record cannot be
|
||||
called directly because it is <code>static</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Example:</b>
|
||||
</p>
|
||||
<pre>
|
||||
static long readData(dbCommon *record, format_t *format)
|
||||
{
|
||||
<var>recordtype</var>Record *rec = (<var>recordtype</var>Record *)record;
|
||||
unsigned long rval;
|
||||
unsigned short monitor_mask;
|
||||
|
||||
switch (format->type)
|
||||
{
|
||||
case DBF_ULONG:
|
||||
case DBF_LONG:
|
||||
case DBF_ENUM:
|
||||
if (streamScanf(record, format, &rval) == ERROR) return ERROR;
|
||||
rec->rval = rval;
|
||||
if (record->pact) return OK;
|
||||
/* emulate convertion to val */
|
||||
rec->val = rval * rec->eslo + rec->eoff;
|
||||
break;
|
||||
case DBF_DOUBLE:
|
||||
if (streamScanf(record, format, &rec->val) == ERROR) return ERROR;
|
||||
break;
|
||||
if (record->pact) return DO_NOT_CONVERT;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
/* In @init handler, no processing, enforce monitor updates. */
|
||||
monitor_mask = recGblResetAlarms(record);
|
||||
if (rec->oraw != rec->rval)
|
||||
{
|
||||
db_post_events(record, &rec->rval, monitor_mask | DBE_VALUE | DBE_LOG);
|
||||
rec->oraw = rec->rval;
|
||||
}
|
||||
if (!(fabs(rec->mlst - rec->val) <= rec->mdel))
|
||||
{
|
||||
monitor_mask |= DBE_VALUE;
|
||||
ao->mlst = rec->val;
|
||||
}
|
||||
if (!(fabs(rec->alst - rec->val) <= rec->adel))
|
||||
{
|
||||
monitor_mask |= DBE_VALUE;
|
||||
ao->alst = rec->val;
|
||||
}
|
||||
if (monitor_mask)
|
||||
db_post_events(record, &rec->val, monitor_mask);
|
||||
return OK;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4>initRecord</h4>
|
||||
<p>
|
||||
The main purpose of this function is to pass the .INP or .OUT link to
|
||||
<em>StreamDevice</em> for parsing and to make the two functions
|
||||
<code>readData</code> and <code>writeData</code> known.
|
||||
Often the only thing the <code>initRecord()</code> function does is to call
|
||||
<code>streamInitRecord()</code> and return its result.
|
||||
</p>
|
||||
<div class="indent"><code>
|
||||
long streamInitRecord(dbCommon *record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData);
|
||||
</code></div>
|
||||
<pre>
|
||||
static long initRecord(dbCommon *record)
|
||||
{
|
||||
<var>recordtype</var>Record *rec = (<var>recordtype</var>Record *)record;
|
||||
|
||||
return streamInitRecord(record, &rec->out, readData, writeData);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Device Support Structure</h3>
|
||||
<p>
|
||||
For most record types the device support structure contains 5 functions,
|
||||
<code>report</code>, <code>init</code>, <code>init_record</code>,
|
||||
<code>get_ioint_info</code>, and <code>read</code> or <code>write</code>.
|
||||
Few other record typess, for examle ai and ao may have additional functions.
|
||||
For most of these functions simply pass one of the provided
|
||||
<em>StreamDevice</em> functions <code>streamReport</code>,
|
||||
<code>streamInit</code>, <code>streamGetIoInitInfo</code>, and
|
||||
<code>streamRead</code> or <code>streamWrite</code>.
|
||||
Only for <code>init_record</code> pass your own
|
||||
<code>initRecord</code> function. Then export the structure.
|
||||
</p>
|
||||
<pre>
|
||||
struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN write;
|
||||
} dev<var>recordtype</var>Stream = {
|
||||
5,
|
||||
streamReport,
|
||||
streamInit,
|
||||
initRecord,
|
||||
streamGetIointInfo,
|
||||
streamWrite
|
||||
};
|
||||
|
||||
epicsExportAddress(dset,dev<var>recordtype</var>Stream);
|
||||
|
||||
</pre>
|
||||
|
||||
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: Record Types</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Record Types</h1>
|
||||
|
||||
<h2>Supported Record Types</h2>
|
||||
<p>
|
||||
@ -17,25 +18,32 @@
|
||||
in EPICS base which can have device support.
|
||||
</p>
|
||||
<p>
|
||||
There is a separate page for each supported record type:<br>
|
||||
There is a separate page for each supported record type:
|
||||
</p>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
@ -47,8 +55,8 @@ 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>
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,20 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: scalcout Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>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"
|
||||
href="https://www.aps.anl.gov/BCDA/synApps"
|
||||
><em>synApps</em></a> package.
|
||||
Device support for scalcout records is only available for <i>calc</i>
|
||||
module release 2-4 or higher.
|
||||
@ -28,7 +29,7 @@ before the final <code>return(0)</code>:
|
||||
</p>
|
||||
<pre class="box">
|
||||
if(pscalcoutDSET->init_record ) {
|
||||
return (*pscalcoutDSET->init_record)(pcalc);
|
||||
return (*pscalcoutDSET->init_record)(pcalc);
|
||||
}
|
||||
</pre>
|
||||
|
||||
@ -76,26 +77,31 @@ Different record fields are used for output and input. The variable
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
526
docs/setup.html
Normal file
@ -0,0 +1,526 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StreamDevice: Setup</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Setup</h1>
|
||||
|
||||
<a name="pre"></a>
|
||||
<h2>1. Prerequisites</h2>
|
||||
<p>
|
||||
<em>StreamDevice</em> works with
|
||||
<a href="https://epics.anl.gov/base/index.php">EPICS base</a>
|
||||
versions from R3.14.6 on, tested up to 7.0.3.
|
||||
It also works (with limitations) with older
|
||||
<a href="https://epics.anl.gov/base/R3-13.php">R3.13</a>
|
||||
versions from R3.13.7 on.
|
||||
How to use <em>StreamDevice</em> with EPICS R3.13 is described on a
|
||||
<a href="epics3_13.html">separate page</a>.
|
||||
<p>
|
||||
Download and build the EPICS version of your choice first before continuing.
|
||||
</p>
|
||||
</p>
|
||||
<h3>Fix required for base R3.14.8.2 and earlier on Windows</h3>
|
||||
<p>
|
||||
Up to release R3.14.8.2, a fix in EPICS base is required to build
|
||||
<em>StreamDevice</em> on Windows (not cygwin).
|
||||
Add the following line to <kbd>src/iocsh/iocsh.h</kbd>
|
||||
and rebuild base.
|
||||
</p>
|
||||
<pre>
|
||||
epicsShareFunc int epicsShareAPI iocshCmd(const char *command);
|
||||
</pre>
|
||||
|
||||
<h3>Downloading <em>StreamDevice</em></h3>
|
||||
The latest version of StreamDevice can be found on github:
|
||||
<a href="https://github.com/paulscherrerinstitute/StreamDevice"
|
||||
>https://github.com/paulscherrerinstitute/StreamDevice</a>.
|
||||
|
||||
Either download a <a
|
||||
href="https://github.com/paulscherrerinstitute/StreamDevice/archive/master.zip
|
||||
">zip file</a> or clone the git repo:
|
||||
<pre>
|
||||
git clone https://github.com/paulscherrerinstitute/StreamDevice.git
|
||||
</pre>
|
||||
|
||||
<h3>Configuration</h3>
|
||||
<p class="new">
|
||||
<em>StreamDevice</em> now comes with a standard
|
||||
<kbd>configure</kbd> directory.
|
||||
<del>But it can still be built in an external <em><top></em>
|
||||
directory as in previous versions.
|
||||
It will automatically detect <em><top></em> locations
|
||||
from the presence of <kbd>../configure</kbd> or <kbd>../config</kbd>
|
||||
directories.</del> Using an upper level <kbd>../configure</kbd> is
|
||||
no longer supported due to compatibility issues with <em>SynApps</em>.
|
||||
</p>
|
||||
<p class="new">
|
||||
Edit the <kbd>configure/RELEASE</kbd> file to specify the install location
|
||||
of EPICS base and of additional software modules or add a
|
||||
<kbd>configure/RELEASE.local</kbd> file to overwrite, for example:
|
||||
<pre>
|
||||
EPICS_BASE=/home/epics/base-3.16.1
|
||||
</pre>
|
||||
|
||||
<h4>Support for <em>asynDriver</em></h4>
|
||||
<p>
|
||||
You most probably want to have <em>asynDriver</em> support included, because
|
||||
that is the standard way for <em>StreamDevice</em> to talk to hardware.
|
||||
First get and install
|
||||
<a href="https://www.aps.anl.gov/epics/modules/soft/asyn/"
|
||||
><em>asynDriver</em></a> version 4-3 or higher before you build
|
||||
<em>StreamDevice</em>.
|
||||
I have tested <em>StreamDevice</em> with <em>asynDriver</em> versions up to 4-30.
|
||||
Make sure that the <em>asyn</em> library can be found by adding the path to the
|
||||
<em><top></em> directory of your <em>asyn</em> installation to the
|
||||
<kbd>configure/RELEASE</kbd> file:
|
||||
<pre>
|
||||
ASYN=/home/epics/asyn4-30
|
||||
</pre>
|
||||
|
||||
<h4 id="scalcout">Support for <em>sCalcout</em> record</h4>
|
||||
<p>
|
||||
The <a
|
||||
href="https://htmlpreview.github.io/?https://raw.githubusercontent.com/epics-modules/calc/R3-6-1/documentation/sCalcoutRecord.html"
|
||||
><em>sCalcout</em></a> record is part of <a
|
||||
href="https://www.aps.anl.gov/BCDA/synApps"
|
||||
><em>synApps</em></a>.
|
||||
If <em>streamDevice</em> should be built with support for this record,
|
||||
you have to install at least the <a
|
||||
href="https://epics.anl.gov/bcda/synApps/calc/calc.html"
|
||||
><em>calc</em> module</a> from <em>SynApps</em> first.
|
||||
Add references to the <kbd>RELEASE</kbd> file as shown here:
|
||||
<pre>
|
||||
CALC=/home/epics/synApps/calc-R3-6-1
|
||||
</pre>
|
||||
<p>
|
||||
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>.)
|
||||
And the <em>calc</em> module had dependencies on other <em>SynApps</em>
|
||||
modules. Release R2-8 or newer is recommended.
|
||||
</p>
|
||||
<p>
|
||||
Support for the <em>sCalcout</em> is optional. <em>StreamDevice</em> works
|
||||
as well without <em>sCalcout</em> or <em>SynApps</em>. If your application does
|
||||
not need this record support, you may load <kbd>stream-base.dbd</kbd> instead of
|
||||
<kbd>stream.dbd</kbd>, making it optional to include <em>calc</em> as an
|
||||
application dependency.
|
||||
</p>
|
||||
|
||||
<h4>Support for regular expression matching</h4>
|
||||
<p>
|
||||
If you want to enable regular expression matching, you need the <em>PCRE</em> package.
|
||||
For most Linux systems, it is already installed.
|
||||
In that case tell <em>StreamDevice</em> the locations of the
|
||||
<em>PCRE</em> header file and library.
|
||||
However, the pre-installed package can only by used for the host architecture.
|
||||
Thus, add them not to <kbd>RELEASE</kbd> but to
|
||||
<kbd>RELEASE.Common.linux-x86</kbd> (if linux-x86 is your EPICS_HOST_ARCH).
|
||||
Be aware that different Linux distributions may locate the files in different
|
||||
directories.
|
||||
</p>
|
||||
<pre>
|
||||
PCRE_INCLUDE=/usr/include/pcre
|
||||
PCRE_LIB=/usr/lib
|
||||
</pre>
|
||||
<p>
|
||||
For 64 bit installations, the path to the library may be different:
|
||||
</p>
|
||||
<pre>
|
||||
PCRE_INCLUDE=/usr/include/pcre
|
||||
PCRE_LIB=/usr/lib64
|
||||
</pre>
|
||||
<p>
|
||||
A pre-compiled Windows version of <em>PCRE</em> is available at
|
||||
<a href="https://sourceforge.net/projects/gnuwin32/files/pcre/7.0/pcre-7.0.exe/download"
|
||||
>sourceforge</a>
|
||||
</p>
|
||||
<p>
|
||||
If you want to have <em>PCRE</em> support on platforms that don't support it natively,
|
||||
e.g. vxWorks, it is probably the easiest to build <em>PCRE</em> as an EPICS module.
|
||||
</p>
|
||||
<p>
|
||||
<h4>Building the <em>PCRE</em> package as an EPICS module</h4>
|
||||
<p>
|
||||
<ol>
|
||||
<li>
|
||||
Download the <em>PCRE</em> package from <a href="https://www.pcre.org">www.pcre.org</a>.
|
||||
</li>
|
||||
<li>
|
||||
Extract the <em>PCRE</em> package in the <kbd><top></kbd> directory of
|
||||
<em>StreamDevice</em> or create a separate <kbd><top></kbd> location using
|
||||
<code>makeBaseApp.pl</code>.
|
||||
</li>
|
||||
<li>
|
||||
Download this <a href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile"
|
||||
>Makefile</a> and this
|
||||
<a href="http://epics.web.psi.ch/software/streamdevice/pcre/fixforvxworks.pl"
|
||||
>fixforvxworks.pl</a> script and save them to the extracted pcre directory.
|
||||
</li>
|
||||
<li>
|
||||
Change into the pcre direcrory and run <code>perl fixforvxworks.pl</code>
|
||||
</li>
|
||||
<li>
|
||||
Run <code>make</code> (or <code>gmake</code>)
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Define the location of the pcre <kbd><top></kbd> in the RELEASE file for <em>StreamDevice</em>.
|
||||
</p>
|
||||
<pre>
|
||||
PCRE=/home/epics/pcre
|
||||
</pre>
|
||||
<p>
|
||||
Regular expressions are optional. If you don't want them, you don't need this.
|
||||
</p>
|
||||
|
||||
<a name="lib"></a>
|
||||
<h2>2. Building <em>StreamDevice</em></h2>
|
||||
<p>
|
||||
Go to the <em>StreamDevice</em> directory
|
||||
and run <code>make</code> (or <code>gmake</code>).
|
||||
This will create and install the <em>stream</em> library and the
|
||||
<em>StreamDevice</em> database definition files and an example IOC application.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use <em>StreamDevice</em>, your own application must be built with the
|
||||
<em>stream</em> and <em>asyn</em> (and optionally <em>pcre</em>) libraries
|
||||
and must load <kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd> (or alternatively
|
||||
<kbd>stream-base.dbd</kbd>; see <a href="#scalcout">Support for sCalcout record</a>).
|
||||
</p>
|
||||
<p>
|
||||
Include the following lines in your application <kbd>Makefile</kbd>:
|
||||
</p>
|
||||
<pre>
|
||||
PROD_LIBS += stream
|
||||
PROD_LIBS += asyn
|
||||
PROD_LIBS += pcre
|
||||
</pre>
|
||||
<p>
|
||||
Include the following lines in your <kbd>xxxAppInclude.dbd</kbd> file to use
|
||||
<em>stream</em> and <em>asyn</em> with serial lines, IP sockets,
|
||||
and vxi11 ("GPIB over ethernet") support.
|
||||
</p>
|
||||
<pre>
|
||||
include "base.dbd"
|
||||
include "stream.dbd"
|
||||
include "asyn.dbd"
|
||||
registrar(drvAsynIPPortRegisterCommands)
|
||||
registrar(drvAsynSerialPortRegisterCommands)
|
||||
registrar(vxi11RegisterCommands)
|
||||
</pre>
|
||||
<p>
|
||||
You can find an example application in the <kbd>streamApp</kbd>
|
||||
subdirectory.
|
||||
</p>
|
||||
|
||||
<a name="sta"></a>
|
||||
<h2>3. 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 device with serial communication (9600 baud, 8N1, no flow control) is
|
||||
connected to <kbd>/dev/ttyS1</kbd>.
|
||||
The name of the device shall be <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 may look 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>All above options are the defaults.
|
||||
Thus their usage in optional in this case.
|
||||
</p>
|
||||
<p>
|
||||
If the device uses hardware flow control, change the last two lines to:
|
||||
</p>
|
||||
<pre>
|
||||
asynSetOption ("PS1", 0, "clocal", "N")
|
||||
asynSetOption ("PS1", 0, "crtscts", "Y")
|
||||
</pre>
|
||||
<p>
|
||||
Newer versions of <em>asyn</em> also support software flow control
|
||||
(CTRL-S,CTRL-Q). If the device uses this, you may want to set:
|
||||
</p>
|
||||
<pre>
|
||||
asynSetOption ("PS1", 0, "ixon", "Y")
|
||||
asynSetOption ("PS1", 0, "ixany", "Y")
|
||||
</pre>
|
||||
|
||||
<p>If the device was instead connected via telnet-style TCP/IP
|
||||
at address 192.168.164.10 on port 23,
|
||||
the startup script 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>4. 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 protocols
|
||||
<code>getCurrent</code> and <code>setCurrent</code>.
|
||||
</p>
|
||||
<pre>
|
||||
Terminator = CR LF;
|
||||
|
||||
getCurent {
|
||||
out "CURRENT?";
|
||||
in "CURRENT %f A";
|
||||
}
|
||||
|
||||
setCurrent {
|
||||
out "CURRENT %.2f";
|
||||
@init {
|
||||
getCurent;
|
||||
}
|
||||
}
|
||||
</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
|
||||
<span class="new">or empty</span>, all records using
|
||||
<em>StreamDevice</em> reload their protocols.
|
||||
<span class="new">In EPICS 3.14 or higher,
|
||||
<code><var>record</var></code> can be a glob pattern.</span>
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
<span class="new">Reloading triggers an <code>@init</code>
|
||||
<a href="protocol.html#except">handler</a>.</span>
|
||||
See the <a href="protocol.html">next chapter</a> for protocol files in depth.
|
||||
</p>
|
||||
|
||||
<a name="debug"></a>
|
||||
<h2>5. Debug and Error Messages</h2>
|
||||
<p>
|
||||
Generation of debug and error messages is controlled with two shell variables,
|
||||
<code>streamDebug</code> and <code>streamError</code>.
|
||||
Setting those variables to 1 (actually to any number but 0) enables the
|
||||
messages. A few noisy and rarely useful debug messages are only enabled when
|
||||
setting <code>streamDebug</code> to 2.
|
||||
Per default debug messages are switched off and error messages are switched on.
|
||||
Errors occuring while loading protocol files are always shown.
|
||||
</p>
|
||||
<p>
|
||||
Warning: Enabling debug messages this way can create a lot of output!
|
||||
Therefore, some limited debugging can be enabled per record, independent of
|
||||
the <code>streamDebug</code> variable using the <code>.TPRO</code> field of
|
||||
the record. Currently, setting <code>.TPRO</code> to 1 or 2 enables some
|
||||
basic information about the processing of a record and its i/o.
|
||||
</p>
|
||||
<p>
|
||||
Debug output can be redirected to a file with the command
|
||||
<code>streamSetLogfile("<var>filename</var>")</code>.
|
||||
If the file already exists, it will be overwritten, not appended to.
|
||||
While debug messages are only written to the defined log file, error messages
|
||||
are still printed to <var>stderr</var> too.
|
||||
Calling <code>streamSetLogfile</code> without a filename directs debug output
|
||||
back to <var>stderr</var> and closes the log file.
|
||||
</p>
|
||||
<p>
|
||||
By default, error messages to the console are printed in red color if
|
||||
<var>stderr</var> is a tty at startup time, using ANSI color codes. Some
|
||||
terminals may not support this properly.
|
||||
The variable <code>streamDebugColored</code> can be set to 0 or 1 to
|
||||
disable or enable colored error messages explicitly.
|
||||
Error messages written to a log file do not use colors.
|
||||
</p>
|
||||
<p>
|
||||
Error and debug messages are prefixed with a time stamp unless the variable
|
||||
<code>streamMsgTimeStamped</code> is set to 0.
|
||||
</p>
|
||||
<p>
|
||||
when a device is unresponsive, StreamDevice may produce many repeated timeout
|
||||
messages. To reduce this, you can set <code>streamErrorDeadTime</code>
|
||||
to an integer number of seconds. In this case, repeated timeout messages
|
||||
will not be printed during the specified dead time after the last printed
|
||||
message. The default dead time is 0, resulting in every message being printed.
|
||||
</p>
|
||||
|
||||
<h3>Example (vxWorks):</h3>
|
||||
<pre>
|
||||
streamError=1
|
||||
streamDebug=1
|
||||
streamDebugColored=1
|
||||
streamErrorDeadTime=30
|
||||
streamMsgTimeStamped=1
|
||||
streamSetLogfile("logfile.txt")
|
||||
</pre>
|
||||
|
||||
<h3>Example (iocsh):</h3>
|
||||
<pre>
|
||||
var streamError 1
|
||||
var streamDebug 1
|
||||
var streamDebugColored 1
|
||||
var streamErrorDeadTime 30
|
||||
var streamMsgTimeStamped 1
|
||||
streamSetLogfile("logfile.txt")
|
||||
</pre>
|
||||
|
||||
<a name="rec"></a>
|
||||
<h2>6. Configuring the Records</h2>
|
||||
<p>
|
||||
To tell a record to use <em>StreamDevice</em>, set its <code>DTYP</code> field to
|
||||
<code>"stream"</code>.
|
||||
</p>
|
||||
<p>
|
||||
The <code>INP</code> or <code>OUT</code> link has the form
|
||||
<code>"@<var>filename protocol</var>[(<var>arg1</var>,<var>arg2</var>,...)] </var>bus</var> [<var>address</var> [<var>parameters</var>]]"</code>.
|
||||
</p>
|
||||
<p>
|
||||
(Elements in <code>[]</code> are optional. Do not type the <code>[]</code>).
|
||||
</p>
|
||||
<p>
|
||||
Here, <code><var>filename</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.
|
||||
(See the <a href="protocol.html">next chapter</a>.)
|
||||
</p>
|
||||
<p>
|
||||
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>.
|
||||
<span class="new">Spaces in the argument list are now allowed.
|
||||
The first space before and after an argument is ignored. Further spaces are
|
||||
considered part of the argument.</span>
|
||||
</p>
|
||||
<p>
|
||||
The communication channel is specified with <code><var>bus</var></code>
|
||||
(aka <em>asynDriver</em> "port") and <code><var>addr</var></code>.
|
||||
If the bus does not have addresses, <code><var>addr</var></code> may be skipped.
|
||||
Optional <code><var>parameters</var></code> are passed to the bus driver.
|
||||
(At the moment, no bus driver supports parameters.)
|
||||
</p>
|
||||
|
||||
<h3>Example:</h3>
|
||||
<p>
|
||||
Create an input record to read and an output record to set the current of <tt>PS1</tt>.
|
||||
Use protocols <em>getCurrent</em> and <em>setCurrent</em> from file <em>ExamplePS.proto</em>.
|
||||
The bus is called <em>PS1</em> like the device.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
record (ai, "PS1:I-get")
|
||||
{
|
||||
field (DESC, "Read current of PS1")
|
||||
<b>field (DTYP, "stream")</b>
|
||||
<b>field (INP, "@ExamplePS.proto getCurrent PS1")</b>
|
||||
field (EGU, "A")
|
||||
field (PREC, "2")
|
||||
field (LOPR, "0")
|
||||
field (HOPR, "60")
|
||||
field (PINI, "YES")
|
||||
field (SCAN, "10 second")
|
||||
}
|
||||
record (ao, "PS1:I-set")
|
||||
{
|
||||
field (DESC, "Set current of PS1")
|
||||
<b>field (DTYP, "stream")</b>
|
||||
<b>field (OUT, "@ExamplePS.proto setCurrent PS1")</b>
|
||||
field (EGU, "A")
|
||||
field (PREC, "2")
|
||||
field (DRVL, "0")
|
||||
field (DRVH, "60")
|
||||
field (LOPR, "0")
|
||||
field (HOPR, "60")
|
||||
}
|
||||
</pre>
|
||||
|
||||
<footer>
|
||||
<a href="protocol.html">Next: Protocol Files</a>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
169
docs/stream.css
Normal file
@ -0,0 +1,169 @@
|
||||
a:link { color: #0000D0; }
|
||||
a:visited { color: #0000D0; }
|
||||
a:hover { color: #FF0000; }
|
||||
|
||||
body {
|
||||
margin-right: 1em;
|
||||
margin-left: 15em;
|
||||
margin-top: 75px;
|
||||
padding-top: 1px;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
a[name] {
|
||||
position: relative;
|
||||
top: -11ex;
|
||||
}
|
||||
|
||||
pre, tt, kbd, code {
|
||||
font-size: 95%;
|
||||
font-family: Mono, "Lucida Console", Courier, monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f4f4f4;
|
||||
padding: 1ex;
|
||||
border: 1px solid #000000;
|
||||
white-space: pre;
|
||||
margin: 2ex;
|
||||
page-break-inside: avoid;
|
||||
font-size: 85%;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
kbd {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
code {
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
dt {
|
||||
margin-top: 0.5ex;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 250%;
|
||||
margin-top: 0;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
font-family: "Times New Roman", Times, serif;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
line-height: 190%;
|
||||
background-color: white;
|
||||
border-width: 0;
|
||||
border-bottom: 3px solid #1b4486;
|
||||
white-space: nowrap;
|
||||
background-image: url(PSI.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 10px 5px;
|
||||
text-shadow: .1em .1em .1em lightgray;
|
||||
box-shadow: 0 .3em .1em -.2em darkgray;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 140%;
|
||||
margin-bottom: 0.5ex;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
margin-bottom: 0.25ex;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 100%;
|
||||
margin-bottom: 0.25ex;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75ex;
|
||||
margin-bottom: 0.75ex;
|
||||
}
|
||||
|
||||
body h1 + p {
|
||||
margin-top: 1.5ex;
|
||||
margin-bottom: 0.75ex;
|
||||
}
|
||||
|
||||
footer {
|
||||
font-size: 75%;
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid darkgray;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
footer a:only-of-type {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
.indent {
|
||||
text-indent: -4ex;
|
||||
margin-left: 4ex;
|
||||
margin-top: 0.5ex;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-left: 1ex;
|
||||
margin-right: 1ex;
|
||||
margin-top: 0.5ex;
|
||||
padding: 0 1ex;
|
||||
border: thin solid black;
|
||||
text-align: left;
|
||||
background-color: #f0f0f0;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
#navleft {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding-top: 70px;
|
||||
width: 14em;
|
||||
height: 100%;
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
border-width: 0 1px 0 0;
|
||||
background-color: #e3eaf6;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.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 { text-decoration: none; }
|
||||
a[target=ex]:after { content:" [" attr(href) "]"; font-size: 75%; }
|
||||
body { margin: 0 4em; }
|
||||
h1 { position: relative; background-position: 0 0; }
|
||||
#navleft { display: none; }
|
||||
footer { display: none; }
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: stringin Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>stringin Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -42,26 +43,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: stringout Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>stringout Records</h1>
|
||||
|
||||
<h2>Normal Operation</h2>
|
||||
<p>
|
||||
@ -42,26 +43,31 @@ written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</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="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</a>
|
||||
</p>
|
||||
<p><small>Dirk Zimoch, 2005</small></p>
|
||||
<script src="stream.js" type="text/javascript"></script>
|
||||
<a href="stringin.html">stringin</a>
|
||||
<a href="stringout.html">stringout</a>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: Tips and Tricks</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>Tips and Tricks</h1>
|
||||
|
||||
<a name="argvar"></a>
|
||||
<h2>I have many almost identical protocols</h2>
|
||||
@ -54,7 +55,7 @@ read {in "new value = %f";}
|
||||
<code>
|
||||
record (ai, "$(RECORD)") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read $(BUS)")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto read $(BUS)")<br>
|
||||
field (SCAN, "I/O Intr")<br>
|
||||
}
|
||||
</code>
|
||||
@ -95,14 +96,14 @@ array_out {separator=", "; out "an array: (%.2f)";}
|
||||
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:
|
||||
</p>
|
||||
<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.
|
||||
<a href="formats.html#redirection">redirection to fields</a>.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
@ -121,24 +122,24 @@ record (calcout, "$(RECORD)") {<br>
|
||||
field (INPC, "$(C_RECORD)")<br>
|
||||
field (CALC, "0")<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (OUT, "@(DEVICETYPE).proto write_ABC $(BUS)")<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.
|
||||
Use <a href="formats.html#redirection">redirection to records</a>.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
acquire {out 'ACQUIRE "%(\$1:directory.VAL)s/%s",%(\$1:time.VAL).3f;';}
|
||||
acquire {out 'ACQUIRE "%(\$1:directory)s/%s",%(\$1:time).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>.
|
||||
You can specify a record name or record.FIELD in parentheses directly
|
||||
after the <code>%</code>.
|
||||
To avoid plain record names in protocol files use
|
||||
<a href="protocol.html#argvar">protocol arguments</a> like <code>\$1</code>.
|
||||
In the link, specify the record name or just the basename of the
|
||||
other records (device name) in parentheses.
|
||||
</p>
|
||||
@ -146,7 +147,7 @@ other records (device name) in parentheses.
|
||||
<code>
|
||||
record (stringout, "$(DEVICE):getimage") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (OUT, "@(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")<br>
|
||||
field (OUT, "@$(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")<br>
|
||||
}
|
||||
</code>
|
||||
</p>
|
||||
@ -190,12 +191,12 @@ read_B {in "A=%*f, B=%f";}
|
||||
<code>
|
||||
record (ai, "$(DEVICE):A") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read_A $(BUS)")<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 (INP, "@$(DEVICETYPE).proto read_B $(BUS)")<br>
|
||||
field (SCAN, "I/O Intr")<br>
|
||||
}
|
||||
</code>
|
||||
@ -215,20 +216,20 @@ 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.
|
||||
Use <a href="formats.html#redirection">redirection to records</a>.
|
||||
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";}
|
||||
read_AB {out "GET A,B"; in "A=%f, B=%(\$1)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 (INP, "@$(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")<br>
|
||||
field (SCAN, "1 second")<br>
|
||||
}<br>
|
||||
record (ai, "$(DEVICE):B") {<br>
|
||||
@ -243,11 +244,11 @@ processes record B.
|
||||
</p>
|
||||
|
||||
<a name="mixed"></a>
|
||||
<h2>I have a device that sends mixed data types: numbers and strings</h2>
|
||||
<h2>I have a device that sends mixed data types: numbers or 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.
|
||||
<a href="formats.html#redirection">redirection to records</a>.
|
||||
To avoid record names in protocol files, use
|
||||
<a href="protocol.html#argvar">protocol arguments</a>.
|
||||
</p>
|
||||
@ -259,14 +260,14 @@ When asked "<code>CURRENT?</code>", the device send something like
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
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";}}
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
record (ai, "$(DEVICE):readcurrent") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")<br>
|
||||
}<br>
|
||||
record (stringin, "$(DEVICE):message") {<br>
|
||||
}
|
||||
@ -280,7 +281,7 @@ With some more records, you can clean the message record if SEVR is not INVALID.
|
||||
<code>
|
||||
record (calcout, "$(DEVICE):clean_1") {<br>
|
||||
field (INPA, "$(DEVICE):readcurrent.SEVR CP")<br>
|
||||
field (CALC, "A!=2")<br>
|
||||
field (CALC, "A#3")<br>
|
||||
field (OOPT, "When Non-zero")<br>
|
||||
field (OUT, "$(DEVICE):clean_2.PROC")<br>
|
||||
}<br>
|
||||
@ -288,10 +289,128 @@ 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>
|
||||
<a name="web"></a>
|
||||
<h2>I need to read a web page</h2>
|
||||
<p>
|
||||
First you have to send a correctly formatted HTML header for a GET request.
|
||||
Note that this header must contain the full URL like
|
||||
"http://server/page" and must be terminated with <u>two</u>
|
||||
CR LF sequences (<code>"\r\n\r\n"</code> or <code>CR LF CR LF</code>).
|
||||
The server should be the same as in the
|
||||
<a href="setup.html#sta"><code>drvAsynIPPortConfigure</code></a>
|
||||
command (if not using a http proxy).
|
||||
|
||||
The web page you get often contains much more information than you need.
|
||||
<a href="formats.html#regex">Regular expressions</a> are great
|
||||
to find what you are looking for.
|
||||
</p>
|
||||
<h3>Example 1</h3>
|
||||
<p>
|
||||
Read the title of a web page.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
get_title {<br>
|
||||
extrainput = ignore;<br>
|
||||
replyTimeout = 1000;<br>
|
||||
out "GET http://\$1\r\n\r\n";<br>
|
||||
in "%+.1/(?im)<title>(.*)<\/title>/";<br>
|
||||
}
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Terminate the request with two carriage return + newlines, either explicit
|
||||
like here <u>or</u> using an
|
||||
<a href="protocol.html#sysvar"><code>outTerminator</code></a>.
|
||||
The URI (without http:// but including the web server host name)
|
||||
is passed as <a href="protocol.html#argvar">argument</a> 1 to <code>\$1</code>
|
||||
in this example.
|
||||
Note that web servers may be slow, so allow some
|
||||
<a href="protocol.html#argvar"><code>replyTimeout</code></a>.
|
||||
</p>
|
||||
<p>
|
||||
If you don't use an <code>inTerminator</code> then the whole page is
|
||||
read as one "line" to the <code>in</code> command and can be parsed easily
|
||||
with a regular expression.
|
||||
We want to see the string between <code><title></code> and
|
||||
<code></title></code>, so we put it into a subexpression in
|
||||
<code>()</code> and request the first subexpression with <code>.1</code>.
|
||||
Note that the <code>/</code> in the closing tag has be be escaped
|
||||
to avoid a misinterpretation as the closing <code>/</code> of the regular
|
||||
expression.
|
||||
</p>
|
||||
<p>
|
||||
The tags may be upper or lower case like <code><TITLE></code> or
|
||||
<code><Title></code>, so we ask for case insensitive matching with
|
||||
<code>(?i)</code>.
|
||||
</p>
|
||||
<p>
|
||||
The string should be terminated with the first closing
|
||||
<code></title></code>, not the last one in the file.
|
||||
(There should not be more than one title but you never know.)
|
||||
Thus we ask not to be greedy with <code>(?m)</code>.
|
||||
<code>(?i)</code> and <code>(?m)</code> can be combined to <code>(?im)</code>.
|
||||
See the PCRE documentation for more regexp syntax.
|
||||
</p>
|
||||
<p>
|
||||
The regular expression matcher ignores and discards any content before the
|
||||
matching section.
|
||||
Content after the match is discarded with <code>extrainput = ignore</code>
|
||||
so that it does not trigger errors reporting "surplus input".
|
||||
</p>
|
||||
<p>
|
||||
Finally, the title may be too long for the record.
|
||||
The <code>+</code> tells the format matcher not to fail in this case
|
||||
but to truncate the string instead.
|
||||
You can read the string with a stringin record or for longer strings with
|
||||
a waveform record with data type CHAR.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
record (stringin, "$(DEVICE):title") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto get_title($(PAGE)) $(BUS)")<br>
|
||||
}<br>
|
||||
record (waveform, "$(DEVICE):longtitle") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto get_title($(PAGE)) $(BUS)")<br>
|
||||
field (FTVL, "CHAR")<br>
|
||||
field (NELM, "100")<br>
|
||||
}<br>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<h3>Example 2</h3>
|
||||
<p>
|
||||
Read a number from a web page. First we have to locate the number.
|
||||
For that we match against any known string right before the number
|
||||
(and <a href="formats.html#syntax">discard the match</a> with <code>*</code>).
|
||||
Then we read the number.
|
||||
</p>
|
||||
<code>
|
||||
get_title {<br>
|
||||
extrainput = ignore;<br>
|
||||
replyTimeout = 1000;<br>
|
||||
out "GET http://\$1\r\n\r\n";<br>
|
||||
in "%*/Interesting value:/%f more text";<br>
|
||||
}
|
||||
</code>
|
||||
<p>
|
||||
When using <code>extrainput = ignore;</code>, it is always a good idea to
|
||||
match a few bytes after the value, too.
|
||||
This catches errors where loading of the page is interrupted in the middle
|
||||
of the number. (You don't want to miss the exponent from something like 1.23E-14).
|
||||
</p>
|
||||
<p>
|
||||
You can read more than one value from a file with successive regular expressions
|
||||
and <a href="formats.html#redirection">redirections</a>.
|
||||
But this only works if the order of the values is predictible.
|
||||
<i>StreamDevice</i> is not an XML parser! It always reads sequentially.
|
||||
</p>
|
||||
|
||||
<footer>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,20 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<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">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="stream.css" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="Dirk Zimoch" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>StreamDevice: waveform Records</h1>
|
||||
<iframe src="nav.html" id="navleft"></iframe>
|
||||
<h1>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
|
||||
each array 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.
|
||||
@ -36,14 +37,19 @@ written.
|
||||
<p>
|
||||
The format data type must be convertible to or from the type
|
||||
specified in the <code>FTVL</code> field.
|
||||
The types <code>"INT64"</code> and <code>"UINT64"</code> are
|
||||
only available in EPICS base version 3.16 or higher.
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
<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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -54,6 +60,7 @@ the written or read value.
|
||||
<dd>
|
||||
<u>Output:</u> <code><i>x[i]</i>=long(VAL[i])</code><br>
|
||||
<code>FTVL</code> can be
|
||||
<code>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -61,6 +68,7 @@ the written or read value.
|
||||
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>"INT64"</code>, <code>"UINT64"</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>
|
||||
@ -101,26 +109,31 @@ the written or read value.
|
||||
present. All format converters work like in normal operation.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<footer>
|
||||
<nav>
|
||||
<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="calcout.html">calcout</a>
|
||||
<a href="int64in.html">int64in</a>
|
||||
<a href="int64out.html">int64out</a>
|
||||
<a href="longin.html">longin</a>
|
||||
<a href="longout.html">longout</a>
|
||||
<a href="lsi.html">lsi</a>
|
||||
<a href="lso.html">lso</a>
|
||||
<a href="mbbiDirect.html">mbbiDirect</a>
|
||||
<a href="mbboDirect.html">mbboDirect</a>
|
||||
<a href="mbbi.html">mbbi</a>
|
||||
<a href="mbbo.html">mbbo</a>
|
||||
<a href="scalcout.html">scalcout</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>
|
||||
<a href="waveform.html">waveform</a>
|
||||
</nav>
|
||||
Dirk Zimoch, 2018
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -1,22 +1,24 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is the BCD format converter of StreamDevice. *
|
||||
* Please refer to the HTML files in ../doc/ for a detailed *
|
||||
* documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
/*************************************************************************
|
||||
* This is the BCD format converter of StreamDevice.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#include "StreamFormatConverter.h"
|
||||
#include "StreamError.h"
|
||||
@ -27,76 +29,67 @@ class BCDConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
ssize_t scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
int BCDConverter::
|
||||
parse(const StreamFormat&, StreamBuffer&, const char*&, bool)
|
||||
parse(const StreamFormat& fmt, StreamBuffer&, const char*&, bool)
|
||||
{
|
||||
return long_format;
|
||||
return (fmt.flags & sign_flag) ? signed_format : unsigned_format;
|
||||
}
|
||||
|
||||
bool BCDConverter::
|
||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
{
|
||||
unsigned char bcd[6]={0,0,0,0,0,0}; // sufficient for 2^32
|
||||
int i;
|
||||
int prec = fmt.prec; // number of nibbles
|
||||
if (prec == -1)
|
||||
{
|
||||
prec = 2 * sizeof (value);
|
||||
}
|
||||
int width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2;
|
||||
unsigned char bcd;
|
||||
long i, d, s;
|
||||
unsigned long prec = fmt.prec < 0 ? 2 * sizeof(value) : fmt.prec; // number of nibbles
|
||||
unsigned long width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2;
|
||||
unsigned long val = value;
|
||||
|
||||
output.append('\0', width);
|
||||
if (fmt.width > width) width = fmt.width;
|
||||
if (fmt.flags & sign_flag && value < 0)
|
||||
{
|
||||
// negative BCD value, I hope "F" as "-" is OK
|
||||
bcd[5] = 0xF0;
|
||||
value = -value;
|
||||
}
|
||||
if (prec > 10) prec = 10;
|
||||
for (i = 0; i < prec; i++)
|
||||
{
|
||||
bcd[i/2] |= (value % 10) << (4 * (i & 1));
|
||||
value /= 10;
|
||||
}
|
||||
val = -value;
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
// least significant byte first (little endian)
|
||||
for (i = 0; i < (prec + 1) / 2; i++)
|
||||
{
|
||||
output.append(bcd[i]);
|
||||
}
|
||||
for (; i < width; i++)
|
||||
{
|
||||
output.append('\0');
|
||||
}
|
||||
output[-1] |= bcd[5];
|
||||
i = -(long)width;
|
||||
d = 1;
|
||||
s = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// most significant byte first (big endian)
|
||||
int firstbyte = output.length();
|
||||
for (i = 0; i < width - (prec + 1) / 2; i++)
|
||||
i = -1;
|
||||
d = -1;
|
||||
s = -(long)width;
|
||||
}
|
||||
while (width && prec)
|
||||
{
|
||||
width--;
|
||||
bcd = val%10;
|
||||
if (--prec)
|
||||
{
|
||||
output.append('\0');
|
||||
--prec;
|
||||
val /= 10;
|
||||
bcd |= (val%10)<<4;
|
||||
val /= 10;
|
||||
}
|
||||
for (i = (prec - 1) / 2; i >= 0; i--)
|
||||
{
|
||||
output.append(bcd[i]);
|
||||
}
|
||||
output[firstbyte] |= bcd[5];
|
||||
output[i] = bcd;
|
||||
i += d;
|
||||
}
|
||||
if (fmt.flags & sign_flag && value < 0) {
|
||||
output[s] |= 0xf0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int BCDConverter::
|
||||
ssize_t BCDConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
int length = 0;
|
||||
int val = 0;
|
||||
ssize_t consumed = 0;
|
||||
long val = 0;
|
||||
unsigned char bcd1, bcd10;
|
||||
int width = fmt.width;
|
||||
long width = fmt.width;
|
||||
if (width == 0) width = 1;
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
@ -104,7 +97,8 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
int shift = 1;
|
||||
while (width--)
|
||||
{
|
||||
bcd1 = bcd10 = (unsigned char) input[length++];
|
||||
bcd1 = input[consumed++];
|
||||
bcd10 = bcd1>>4;
|
||||
bcd1 &= 0x0F;
|
||||
bcd10 >>= 4;
|
||||
if (bcd1 > 9 || shift * bcd1 < bcd1) break;
|
||||
@ -127,10 +121,10 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
while (width--)
|
||||
{
|
||||
long temp;
|
||||
bcd1 = bcd10 = (unsigned char) input[length];
|
||||
bcd1 = input[consumed];
|
||||
bcd10 = bcd1>>4;
|
||||
bcd1 &= 0x0F;
|
||||
bcd10 >>= 4;
|
||||
if (length == 0 && fmt.flags & sign_flag && bcd10)
|
||||
if (consumed == 0 && fmt.flags & sign_flag && bcd10)
|
||||
{
|
||||
sign = -1;
|
||||
bcd10 = 0;
|
||||
@ -139,17 +133,17 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
temp = val * 100 + (bcd1 + 10 * bcd10);
|
||||
if (temp < val)
|
||||
{
|
||||
length = 0;
|
||||
consumed = 0;
|
||||
break;
|
||||
}
|
||||
val = temp;
|
||||
length++;
|
||||
consumed++;
|
||||
}
|
||||
val *= sign;
|
||||
}
|
||||
if (length == 0) return -1;
|
||||
if (consumed == 0) return -1;
|
||||
value = val;
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (BCDConverter, "D");
|
||||
|
@ -1,24 +1,28 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is the binary format converter of StreamDevice. *
|
||||
* Please refer to the HTML files in ../doc/ for a detailed *
|
||||
* documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
/*************************************************************************
|
||||
* This is the binary format converter of StreamDevice.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "StreamFormatConverter.h"
|
||||
#include "StreamError.h"
|
||||
|
||||
@ -28,91 +32,142 @@ class BinaryConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
ssize_t scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
int BinaryConverter::
|
||||
parse(const StreamFormat& format, StreamBuffer& info,
|
||||
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
const char*& source, bool)
|
||||
{
|
||||
if (format.conv == 'B')
|
||||
if (fmt.conv == 'b')
|
||||
{
|
||||
// user defined characters for %B (next 2 in source)
|
||||
// default characters 0 and 1 for %b
|
||||
info.append("01");
|
||||
return unsigned_format;
|
||||
}
|
||||
|
||||
// user defined characters for %B (next 2 in source)
|
||||
if (*source)
|
||||
{
|
||||
if (*source == esc) source++;
|
||||
info.append(*source++);
|
||||
if (*source)
|
||||
{
|
||||
if (*source == esc) source++;
|
||||
info.append(*source++);
|
||||
if (*source)
|
||||
{
|
||||
if (*source == esc) source++;
|
||||
info.append(*source++);
|
||||
return long_format;
|
||||
}
|
||||
return unsigned_format;
|
||||
}
|
||||
error("Missing characters after %%B format conversion\n");
|
||||
return false;
|
||||
}
|
||||
// default characters for %b
|
||||
info.append("01");
|
||||
return long_format;
|
||||
error("Missing characters after %%B format conversion\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BinaryConverter::
|
||||
printLong(const StreamFormat& format, StreamBuffer& output, long value)
|
||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
{
|
||||
int prec = format.prec;
|
||||
int prec = fmt.prec;
|
||||
if (prec == -1)
|
||||
{
|
||||
// find number of significant bits
|
||||
prec = sizeof (value) * 8;
|
||||
while (prec && (value & (1 << (prec - 1))) == 0) prec--;
|
||||
// Find number of significant bits is nothing is specified.
|
||||
unsigned long x = (unsigned long) value;
|
||||
prec = 32;
|
||||
#if (LONG_BIT > 32)
|
||||
if (x > 0xFFFFFFFF) { prec = 64; x >>=32; }
|
||||
#endif
|
||||
if (x <= 0x0000FFFF) { prec -= 16; x <<=16; }
|
||||
if (x <= 0x00FFFFFF) { prec -= 8; x <<=8; }
|
||||
if (x <= 0x0FFFFFFF) { prec -= 4; x <<=4; }
|
||||
if (x <= 0x3FFFFFFF) { prec -= 2; x <<=2; }
|
||||
if (x <= 0x7FFFFFFF) { prec -= 1; }
|
||||
}
|
||||
if (prec == 0) prec++; // print at least one bit
|
||||
int width = prec;
|
||||
if (format.width > width) width = format.width;
|
||||
char zero = format.info[0];
|
||||
char one = format.info[1];
|
||||
if (!(format.flags & left_flag))
|
||||
unsigned long width = prec;
|
||||
if (fmt.width > width) width = fmt.width;
|
||||
char zero = fmt.info[0];
|
||||
char one = fmt.info[1];
|
||||
char fill = (fmt.flags & zero_flag) ? zero : ' ';
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
// pad left
|
||||
char fill = (format.flags & zero_flag) ? zero : ' ';
|
||||
while (width > prec)
|
||||
// little endian (least significant bit first)
|
||||
if (!(fmt.flags & left_flag))
|
||||
{
|
||||
output.append(fill);
|
||||
// pad left
|
||||
while (width > (unsigned int)prec)
|
||||
{
|
||||
output.append(' ');
|
||||
width--;
|
||||
}
|
||||
}
|
||||
while (prec--)
|
||||
{
|
||||
output.append((value & 1) ? one : zero);
|
||||
value >>= 1;
|
||||
width--;
|
||||
}
|
||||
while (width--)
|
||||
{
|
||||
// pad right
|
||||
output.append(fill);
|
||||
}
|
||||
}
|
||||
while (prec--)
|
||||
else
|
||||
{
|
||||
output.append((value & (1 << prec)) ? one : zero);
|
||||
width--;
|
||||
}
|
||||
while (width--)
|
||||
{
|
||||
// pad right
|
||||
output.append(' ');
|
||||
// big endian (most significant bit first)
|
||||
if (!(fmt.flags & left_flag))
|
||||
{
|
||||
// pad left
|
||||
while (width > (unsigned int)prec)
|
||||
{
|
||||
output.append(fill);
|
||||
width--;
|
||||
}
|
||||
}
|
||||
while (prec--)
|
||||
{
|
||||
output.append((value & (1L << prec)) ? one : zero);
|
||||
width--;
|
||||
}
|
||||
while (width--)
|
||||
{
|
||||
// pad right
|
||||
output.append(' ');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int BinaryConverter::
|
||||
scanLong(const StreamFormat& format, const char* input, long& value)
|
||||
ssize_t BinaryConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
long val = 0;
|
||||
int width = format.width;
|
||||
long width = fmt.width;
|
||||
if (width == 0) width = -1;
|
||||
int length = 0;
|
||||
while (isspace(input[++length])); // skip whitespaces
|
||||
char zero = format.info[0];
|
||||
char one = format.info[1];
|
||||
if (input[length] != zero && input[length] != one) return -1;
|
||||
while (width-- && (input[length] == zero || input[length] == one))
|
||||
size_t consumed = 0;
|
||||
char zero = fmt.info[0];
|
||||
char one = fmt.info[1];
|
||||
if (!isspace(zero) && !isspace(one))
|
||||
while (isspace(input[consumed])) consumed++; // skip whitespaces
|
||||
if (input[consumed] != zero && input[consumed] != one) return -1;
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
val <<= 1;
|
||||
if (input[length++] == one) val |= 1;
|
||||
// little endian (least significan bit first)
|
||||
long mask = 1;
|
||||
while (width-- && (input[consumed] == zero || input[consumed] == one))
|
||||
{
|
||||
if (input[consumed++] == one) val |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// big endian (most significan bit first)
|
||||
while (width-- && (input[consumed] == zero || input[consumed] == one))
|
||||
{
|
||||
val <<= 1;
|
||||
if (input[consumed++] == one) val |= 1;
|
||||
}
|
||||
}
|
||||
value = val;
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (BinaryConverter, "bB");
|
||||
|
@ -1,35 +1,71 @@
|
||||
# Want debugging?
|
||||
# HOST_OPT = NO
|
||||
##########################################################################
|
||||
# This is the build configuration file of StreamDevice.
|
||||
#
|
||||
# (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
#
|
||||
# This file is part of StreamDevice.
|
||||
#
|
||||
# StreamDevice is free software: You can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# StreamDevice is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
#########################################################################/
|
||||
|
||||
# You may add more record interfaces
|
||||
# This requires the naming conventions
|
||||
# dev$(RECORD)Stream.c
|
||||
# dev$(RECORDTYPE)Stream.c
|
||||
|
||||
RECORDS += ao ai
|
||||
RECORDS += bo bi
|
||||
RECORDS += mbbo mbbi
|
||||
RECORDS += mbboDirect mbbiDirect
|
||||
RECORDS += longout longin
|
||||
RECORDS += stringout stringin
|
||||
RECORDS += waveform
|
||||
RECORDS += calcout
|
||||
#RECORDS += aai aao
|
||||
RECORDTYPES += ao ai
|
||||
RECORDTYPES += bo bi
|
||||
RECORDTYPES += mbbo mbbi
|
||||
RECORDTYPES += mbboDirect mbbiDirect
|
||||
RECORDTYPES += longout longin
|
||||
RECORDTYPES += stringout stringin
|
||||
RECORDTYPES += waveform
|
||||
RECORDTYPES += aai aao
|
||||
|
||||
ifdef BASE_3_14
|
||||
RECORDTYPES += calcout
|
||||
endif
|
||||
|
||||
ifdef BASE_3_15
|
||||
RECORDTYPES += lsi lso
|
||||
endif
|
||||
|
||||
ifdef BASE_3_16
|
||||
RECORDTYPES += int64in int64out
|
||||
endif
|
||||
|
||||
# Do you have synApps and want support for scalcout?
|
||||
# Then define CALC or SYNAPPS in your RELEASE file
|
||||
# pointing to the 'calc' module of synApps.
|
||||
# Due to strange cross dependencies in synApps
|
||||
# you have to build the 'sscan' and 'genSub'
|
||||
# modules before building 'calc'.
|
||||
# See doc/scalcout.html for a required fix in scalcout.
|
||||
SYNAPPS_RECORDS += scalcout
|
||||
# Older 'calc' versions have a cross reference on
|
||||
# 'sscan' and/or 'genSub', so you may have to build them first.
|
||||
# Up to version 2-6 (synApps 5-1) the 'calc' module needs a fix.
|
||||
# See doc/scalcout.html for details.
|
||||
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||
RECORDTYPES += scalcout
|
||||
endif
|
||||
|
||||
# You may add more bus interfaces
|
||||
# This requires the naming convention
|
||||
# $(BUS)Interface.cc
|
||||
# asynDriver interface is added automatically
|
||||
# if ASYN is defined in your RELEASE file.
|
||||
# BUSSES += Debug
|
||||
|
||||
BUSSES += Debug
|
||||
BUSSES += Dummy
|
||||
ifdef ASYN
|
||||
BUSSES += AsynDriver
|
||||
endif
|
||||
|
||||
# You may add more format converters
|
||||
# This requires the naming convention
|
||||
@ -38,9 +74,11 @@ SYNAPPS_RECORDS += scalcout
|
||||
FORMATS += Enum
|
||||
FORMATS += BCD
|
||||
FORMATS += Raw
|
||||
FORMATS += RawFloat
|
||||
FORMATS += Binary
|
||||
FORMATS += Checksum
|
||||
FORMATS += Exponential
|
||||
FORMATS += MantissaExponent
|
||||
FORMATS += Timestamp
|
||||
|
||||
# Want Perl regular expression matching?
|
||||
# If PCRE is installed at the same location for all
|
||||
@ -58,17 +96,13 @@ ifneq ($(words $(PCRE) $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
FORMATS += Regexp
|
||||
endif
|
||||
|
||||
# Want a loadable module?
|
||||
# Want a loadable module?
|
||||
# For Tornado 2.0.2, a fix is needed in the
|
||||
# registerRecordDeviceDriver.pl script in base:
|
||||
# at the end replace the line "IoccrfReg iocshReg;"
|
||||
# by "static IoccrfReg iocshReg;"
|
||||
# LOADABLE_MODULE = YES
|
||||
|
||||
# Want to add some memory tracing
|
||||
# to find memory leaks?
|
||||
# USE_MEMGUARD = YES
|
||||
|
||||
# Sources of Stream Kernel
|
||||
# Do not modify
|
||||
|
||||
|
@ -1,38 +1,86 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
|
||||
* (C) 2006 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is the checksum pseudo-converter of StreamDevice. *
|
||||
* Please refer to the HTML files in ../doc/ for a detailed *
|
||||
* documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
/*************************************************************************
|
||||
* This is the checksum pseudo-converter of StreamDevice.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 1999,2006,2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <version.h>
|
||||
/* VxWorks has strncasecmp since version 6
|
||||
but availability depends on configuration.
|
||||
We cannot know.
|
||||
*/
|
||||
#define NEED_strncasecmp
|
||||
/* VxWorks does not have inttypes.h and uint32_t differs between versions */
|
||||
#if defined(_WRS_VXWORKS_MAJOR) && (_WRS_VXWORKS_MAJOR > 6 || (_WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR >= 9))
|
||||
#define PRIX32 "X"
|
||||
#define PRIu32 "u"
|
||||
#else
|
||||
#define PRIX32 "lX"
|
||||
#define PRIu32 "lu"
|
||||
#endif
|
||||
#define PRIX8 "X"
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1700
|
||||
/* Visual Studio 2010 does not have inttypes.h */
|
||||
#define PRIX32 "X"
|
||||
#define PRIu32 "u"
|
||||
#define PRIX8 "X"
|
||||
#else
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__rtems__)
|
||||
#include <rtems.h>
|
||||
#if __RTEMS_MAJOR__ < 5
|
||||
/* RTEMS has strncasecmp since version 5 */
|
||||
#define NEED_strncasecmp
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Windows strncasecmp has a different name. */
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
#ifdef NEED_strncasecmp
|
||||
// Have no strncasecmp but avoid compiler errors in case it exists in future versions
|
||||
extern "C" {
|
||||
static int mystrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
int r=0;
|
||||
while (n && (r = toupper(*s1)-toupper(*s2)) == 0) { n--; s1++; s2++; };
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#define strncasecmp mystrncasecmp
|
||||
#endif
|
||||
|
||||
#include "StreamFormatConverter.h"
|
||||
#include "StreamError.h"
|
||||
#if defined(__vxworks) || defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
|
||||
// These systems have no strncasecmp
|
||||
#include <epicsString.h>
|
||||
#define strncasecmp epicsStrnCaseCmp
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned char uchar;
|
||||
typedef uint32_t (*checksumFunc)(const uint8_t* data, size_t len, uint32_t init);
|
||||
|
||||
typedef ulong (*checksumFunc)(const uchar* data, ulong len, ulong init);
|
||||
|
||||
static ulong sum(const uchar* data, ulong len, ulong sum)
|
||||
static uint32_t sum(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
@ -41,7 +89,7 @@ static ulong sum(const uchar* data, ulong len, ulong sum)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static ulong xor8(const uchar* data, ulong len, ulong sum)
|
||||
static uint32_t xor8(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
@ -50,15 +98,42 @@ static ulong xor8(const uchar* data, ulong len, ulong sum)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static ulong xor7(const uchar* data, ulong len, ulong sum)
|
||||
static uint32_t xor7(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
return xor8(data, len, sum) & 0x7F;
|
||||
}
|
||||
|
||||
static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t bitsum(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
// number of set bits in each byte
|
||||
const uint8_t table[256] = {
|
||||
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
|
||||
4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
|
||||
while (len--)
|
||||
{
|
||||
sum += table[*data++];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t crc_0x07(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^8 + x^2 + x^1 + x^0 (0x07)
|
||||
const static uchar table[256] = {
|
||||
const uint8_t table[256] = {
|
||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
||||
@ -96,10 +171,10 @@ static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x31(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^8 + x^5 + x^4 + x^0 (0x31)
|
||||
const static uchar table[256] = {
|
||||
const uint8_t table[256] = {
|
||||
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
|
||||
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
|
||||
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
|
||||
@ -137,93 +212,93 @@ static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x8005(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x8005(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||
const static unsigned short table[256] = {
|
||||
0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
|
||||
0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
|
||||
0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
|
||||
0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
|
||||
0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
|
||||
0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
|
||||
0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
|
||||
0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
|
||||
0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
|
||||
0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
|
||||
0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
|
||||
0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
|
||||
0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
|
||||
0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
|
||||
0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
|
||||
0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
|
||||
0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
|
||||
0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
|
||||
0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
|
||||
0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
|
||||
0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
|
||||
0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
|
||||
0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
|
||||
0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
|
||||
0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
|
||||
0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
|
||||
0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
|
||||
0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
|
||||
0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
|
||||
0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
|
||||
0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
|
||||
0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202 };
|
||||
const uint16_t table[256] = {
|
||||
0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
|
||||
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
|
||||
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
|
||||
0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
|
||||
0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
|
||||
0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
|
||||
0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
|
||||
0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
|
||||
0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
|
||||
0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
|
||||
0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
|
||||
0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
|
||||
0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
|
||||
0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
|
||||
0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
|
||||
0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
|
||||
0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
|
||||
0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
|
||||
0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
|
||||
0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
|
||||
0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
|
||||
0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
|
||||
0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
|
||||
0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
|
||||
0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
|
||||
0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
|
||||
0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
|
||||
0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
|
||||
0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
|
||||
0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
|
||||
0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
|
||||
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 };
|
||||
|
||||
while (len--) crc = table[((crc>>8) ^ *data++) & 0xFF] ^ (crc << 8);
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x8005_r(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x8005_r(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||
// reflected
|
||||
const static unsigned short table[256] = {
|
||||
0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
|
||||
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
|
||||
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
|
||||
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
|
||||
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
|
||||
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
|
||||
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
|
||||
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
|
||||
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
|
||||
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
|
||||
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
|
||||
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
|
||||
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
|
||||
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
|
||||
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
|
||||
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
|
||||
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
|
||||
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
|
||||
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
|
||||
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
|
||||
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
|
||||
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
|
||||
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
|
||||
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
|
||||
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
|
||||
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
|
||||
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
|
||||
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
|
||||
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
|
||||
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
|
||||
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
|
||||
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 };
|
||||
const uint16_t table[256] = {
|
||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };
|
||||
|
||||
while (len--) crc = table[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x1021(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^16 + x^12 + x^5 + x^0 (0x1021)
|
||||
const static unsigned short table[256] = {
|
||||
const uint16_t table[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
@ -261,11 +336,11 @@ static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x04C11DB7(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||
const static ulong table[] = {
|
||||
const uint32_t table[] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
||||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
@ -335,12 +410,12 @@ static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
||||
static uint32_t crc_0x04C11DB7_r(const uint8_t* data, size_t len, uint32_t crc)
|
||||
{
|
||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||
// reflected
|
||||
const static ulong table[] = {
|
||||
const uint32_t table[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
@ -410,13 +485,13 @@ static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong adler32(const uchar* data, ulong len, ulong init)
|
||||
static uint32_t adler32(const uint8_t* data, size_t len, uint32_t init)
|
||||
{
|
||||
ulong a = init & 0xFFFF;
|
||||
ulong b = (init >> 16) & 0xFFFF;
|
||||
uint32_t a = init & 0xFFFF;
|
||||
uint32_t b = (init >> 16) & 0xFFFF;
|
||||
|
||||
while (len) {
|
||||
ulong tlen = len > 5550 ? 5550 : len;
|
||||
size_t tlen = len > 5550 ? 5550 : len;
|
||||
len -= tlen;
|
||||
do {
|
||||
a += *data++;
|
||||
@ -424,17 +499,17 @@ static ulong adler32(const uchar* data, ulong len, ulong init)
|
||||
} while (--tlen);
|
||||
a = (a & 0xFFFF) + (a >> 16) * 15;
|
||||
b = (b & 0xFFFF) + (b >> 16) * 15;
|
||||
}
|
||||
if (a >= 65521) a -= 65521;
|
||||
b = (b & 0xFFFF) + (b >> 16) * 15;
|
||||
if (b >= 65521) b -= 65521;
|
||||
return b << 16 | a;
|
||||
}
|
||||
if (a >= 65521) a -= 65521;
|
||||
b = (b & 0xFFFF) + (b >> 16) * 15;
|
||||
if (b >= 65521) b -= 65521;
|
||||
return b << 16 | a;
|
||||
}
|
||||
|
||||
static ulong hexsum(const uchar* data, ulong len, ulong sum)
|
||||
static uint32_t hexsum(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
// Add all hex digits, ignore all other bytes.
|
||||
ulong d;
|
||||
uint32_t d;
|
||||
while (len--)
|
||||
{
|
||||
d = toupper(*data++);
|
||||
@ -448,13 +523,116 @@ static ulong hexsum(const uchar* data, ulong len, ulong sum)
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Special TRIUMF version for the CPI RF Amplifier
|
||||
static uint32_t CPI(const uint8_t * data, size_t len, uint32_t init)
|
||||
{
|
||||
init -= (uint32_t)len<<5;
|
||||
while (len--)
|
||||
{
|
||||
init += *data++;
|
||||
}
|
||||
init %= 95;
|
||||
init += 32;
|
||||
return init;
|
||||
}
|
||||
|
||||
// Leybold Graphix uses a strange sum (= notsum + fix):
|
||||
// "CRC = 255 - [(Byte sum of all preceding characters) mod 256]
|
||||
// If this value is lower than 32 (control character of the ASCII code),
|
||||
// then 32 must be added."
|
||||
|
||||
static uint32_t leybold(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sum += *data++;
|
||||
}
|
||||
sum = ~sum;
|
||||
sum &= 0xff;
|
||||
if (sum < 32) sum+=32;
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Checksum used by Brooks Cryopumps
|
||||
static uint32_t brksCryo(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
uint32_t xsum;
|
||||
while (len--) {
|
||||
sum += (*data++) & 0x7F;
|
||||
}
|
||||
xsum = (((sum >> 6) ^ sum) & 0x3F) + 0x30;
|
||||
return xsum;
|
||||
}
|
||||
|
||||
// Longitudinal Redundancy Check
|
||||
static uint32_t lrc(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
while (len--) {
|
||||
sum = (sum + (*data++)) & 0xFF;
|
||||
}
|
||||
|
||||
sum = ((sum ^ 0xFF) + 1) & 0xFF;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Longitudinal Redundancy Check using ASCII representation of numbers, 2-by-2
|
||||
static uint32_t hexlrc(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
uint32_t d;
|
||||
uint32_t final_digit = 0;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
d = toupper(*data++);
|
||||
|
||||
// Convert all hex digits, ignore all other bytes
|
||||
if (isxdigit(d))
|
||||
{
|
||||
// Convert digits from ASCII to number
|
||||
if (isdigit(d)) {
|
||||
d -= '0';
|
||||
}
|
||||
else {
|
||||
d -= 'A' - 0x0A;
|
||||
}
|
||||
|
||||
// For the most significant bits, shift 4 bits
|
||||
if (len % 2) {
|
||||
final_digit = d << 4;
|
||||
// Least significant bits are summed to previous converted digit
|
||||
} else {
|
||||
d += final_digit;
|
||||
final_digit = 0;
|
||||
// Apply lrc rule
|
||||
sum = (sum + d) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply lrc rule
|
||||
sum = ((sum ^ 0xFF) + 1) & 0xFF;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Checksum used by Spellman High Voltage Supplies MPS
|
||||
static uint32_t hv_mps(const uint8_t* data, size_t len, uint32_t sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sum += *data++;
|
||||
}
|
||||
return (~sum & 0x7F) | 0x40;
|
||||
}
|
||||
|
||||
struct checksum
|
||||
{
|
||||
const char* name;
|
||||
checksumFunc func;
|
||||
ulong init;
|
||||
ulong xorout;
|
||||
signed char bytes;
|
||||
uint32_t init;
|
||||
uint32_t xorout;
|
||||
uint8_t bytes;
|
||||
};
|
||||
|
||||
static checksum checksumMap[] =
|
||||
@ -465,47 +643,52 @@ static checksum checksumMap[] =
|
||||
{"sum8", sum, 0x00, 0x00, 1}, // 0xDD
|
||||
{"sum16", sum, 0x0000, 0x0000, 2}, // 0x01DD
|
||||
{"sum32", sum, 0x00000000, 0x00000000, 4}, // 0x000001DD
|
||||
{"nsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"negsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"-sum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"nsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"negsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"-sum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"nsum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"negsum16",sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"-sum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"nsum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"negsum32",sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"-sum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"notsum", sum, 0x00, 0xFF, 1}, // 0x22
|
||||
{"~sum", sum, 0x00, 0xFF, 1}, // 0x22
|
||||
{"xor", xor8, 0x00, 0x00, 1}, // 0x31
|
||||
{"xor8", xor8, 0x00, 0x00, 1}, // 0x31
|
||||
{"xor8ff", xor8, 0x00, 0xFF, 1}, // 0xCE
|
||||
{"xor7", xor7, 0x00, 0x00, 1}, // 0x31
|
||||
{"crc8", crc_0x07, 0x00, 0x00, 1}, // 0xF4
|
||||
{"ccitt8", crc_0x31, 0x00, 0x00, 1}, // 0xA1
|
||||
{"crc16", crc_0x8005, 0x0000, 0x0000, 2}, // 0xFEE8
|
||||
{"crc16r", crc_0x8005_r, 0x0000, 0x0000, 2}, // 0xBB3D
|
||||
{"modbus", crc_0x8005_r, 0xFFFF, 0x0000, 2}, // 0x4B37
|
||||
{"ccitt16", crc_0x1021, 0xFFFF, 0x0000, 2}, // 0x29B1
|
||||
{"ccitt16a",crc_0x1021, 0x1D0F, 0x0000, 2}, // 0xE5CC
|
||||
{"ccitt16x",crc_0x1021, 0x0000, 0x0000, 2}, // 0x31C3
|
||||
{"crc16c", crc_0x1021, 0x0000, 0x0000, 2}, // 0x31C3
|
||||
{"xmodem", crc_0x1021, 0x0000, 0x0000, 2}, // 0x31C3
|
||||
{"crc32", crc_0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFC891918
|
||||
{"crc32r", crc_0x04C11DB7_r, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xCBF43926
|
||||
{"jamcrc", crc_0x04C11DB7_r, 0xFFFFFFFF, 0x00000000, 4}, // 0x340BC6D9
|
||||
{"adler32", adler32, 0x00000001, 0x00000000, 4}, // 0x091E01DE
|
||||
{"hexsum8", hexsum, 0x00, 0x00, 1} // 0x2D
|
||||
{"hexsum8", hexsum, 0x00, 0x00, 1}, // 0x2D
|
||||
{"cpi", CPI, 0x00, 0x00, 1}, // 0x7E
|
||||
{"leybold", leybold, 0x00, 0x00, 1}, // 0x22
|
||||
{"brksCryo",brksCryo, 0x00, 0x00, 1}, // 0x4A
|
||||
{"lrc", lrc, 0x00, 0x00, 1}, // 0x23
|
||||
{"hexlrc", hexlrc, 0x00, 0x00, 1}, // 0xA7
|
||||
{"bitsum", bitsum, 0x00, 0x00, 1}, // 0x21
|
||||
{"bitsum8", bitsum, 0x00, 0x00, 1}, // 0x21
|
||||
{"bitsum16",bitsum, 0x0000, 0x0000, 2}, // 0x0021
|
||||
{"bitsum32",bitsum, 0x00000000, 0x00000000, 4}, // 0x00000021
|
||||
{"hv_mps", hv_mps, 0xFF, 0x00, 1} // 0x63
|
||||
};
|
||||
|
||||
static ulong mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||
static uint32_t mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
class ChecksumConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool scanFormat);
|
||||
bool printPseudo(const StreamFormat&, StreamBuffer&);
|
||||
int scanPseudo(const StreamFormat&, StreamBuffer&, long& cursor);
|
||||
ssize_t scanPseudo(const StreamFormat&, StreamBuffer&, size_t& cursor);
|
||||
};
|
||||
|
||||
int ChecksumConverter::
|
||||
parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
||||
parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool scanFormat)
|
||||
{
|
||||
const char* p = strchr(source, '>');
|
||||
if (!p)
|
||||
@ -514,53 +697,112 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t fnum;
|
||||
bool negflag=false;
|
||||
bool notflag=false;
|
||||
if (*source == '-')
|
||||
{
|
||||
source++;
|
||||
negflag = true;
|
||||
}
|
||||
if (strncasecmp(source, "neg", 3) == 0)
|
||||
{
|
||||
source+=3;
|
||||
negflag = true;
|
||||
}
|
||||
if (*source == '~')
|
||||
{
|
||||
source++;
|
||||
notflag = true;
|
||||
}
|
||||
if (strncasecmp(source, "not", 3) == 0)
|
||||
{
|
||||
source+=3;
|
||||
notflag = true;
|
||||
}
|
||||
uint8_t fnum;
|
||||
size_t len = p-source;
|
||||
uint32_t init, xorout;
|
||||
for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++)
|
||||
{
|
||||
if (strncasecmp(source, checksumMap[fnum].name, p-source) == 0)
|
||||
if ((strncasecmp(source, checksumMap[fnum].name, len) == 0) ||
|
||||
(*source == 'n' && len > 1 && strncasecmp(source+1, checksumMap[fnum].name, len-1) == 0 && (negflag = true)))
|
||||
{
|
||||
init = checksumMap[fnum].init;
|
||||
xorout = checksumMap[fnum].xorout;
|
||||
if (negflag)
|
||||
{
|
||||
init = ~init;
|
||||
xorout = ~xorout;
|
||||
}
|
||||
if (notflag)
|
||||
{
|
||||
xorout = ~xorout;
|
||||
}
|
||||
info.append(&init, sizeof(init));
|
||||
info.append(&xorout, sizeof(xorout));
|
||||
info.append(fnum);
|
||||
source = p+1;
|
||||
return pseudo_format;
|
||||
return scanFormat ? needs_original_format : pseudo_format;
|
||||
}
|
||||
}
|
||||
|
||||
error ("Unknown checksum algorithm \"%.*s\"\n",
|
||||
static_cast<int>(p-source), source);
|
||||
error ("Unknown checksum algorithm \"%.*s\"\n", (int)len, source);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChecksumConverter::
|
||||
printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
{
|
||||
ulong sum;
|
||||
int fnum = format.info[0];
|
||||
int start = format.width;
|
||||
int length = output.length()-format.width;
|
||||
if (format.prec > 0) length -= format.prec;
|
||||
uint32_t sum;
|
||||
const char* info = format.info;
|
||||
uint32_t init = extract<uint32_t>(info);
|
||||
uint32_t xorout = extract<uint32_t>(info);
|
||||
uint8_t fnum = extract<uint8_t>(info);
|
||||
|
||||
size_t start = format.width;
|
||||
size_t length = output.length();
|
||||
if (length >= start) length -= start;
|
||||
else length = 0;
|
||||
if (format.prec > 0) {
|
||||
if (length >= (size_t)format.prec) length -= format.prec;
|
||||
else length = 0;
|
||||
}
|
||||
|
||||
debug("ChecksumConverter %s: output to check: \"%s\"\n",
|
||||
checksumMap[fnum].name, output.expand(start,length)());
|
||||
|
||||
sum = checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<uchar*>(output(start)), length,
|
||||
checksumMap[fnum].init) & mask[checksumMap[fnum].bytes];
|
||||
sum = (xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<uint8_t*>(output(start)), length, init))
|
||||
& mask[checksumMap[fnum].bytes];
|
||||
|
||||
debug("ChecksumConverter %s: output checksum is 0x%lX\n",
|
||||
debug("ChecksumConverter %s: output checksum is 0x%" PRIX32 "\n",
|
||||
checksumMap[fnum].name, sum);
|
||||
|
||||
int i;
|
||||
unsigned outchar;
|
||||
|
||||
uint8_t i;
|
||||
uint8_t outchar;
|
||||
|
||||
if (format.flags & sign_flag) // decimal
|
||||
{
|
||||
// get number of decimal digits from number of bytes: ceil(bytes*2.5)
|
||||
i = (checksumMap[fnum].bytes+1)*25/10-2;
|
||||
output.print("%0*" PRIu32, i, sum);
|
||||
debug("ChecksumConverter %s: decimal appending %0*" PRIu32 "\n",
|
||||
checksumMap[fnum].name, i, sum);
|
||||
}
|
||||
else
|
||||
if (format.flags & alt_flag) // lsb first (little endian)
|
||||
{
|
||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||
{
|
||||
outchar = sum & 0xff;
|
||||
debug("ChecksumConverter %s: little endian appending 0x%X\n",
|
||||
debug("ChecksumConverter %s: little endian appending 0x%02" PRIX8 "\n",
|
||||
checksumMap[fnum].name, outchar);
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
output.printf("%02X", outchar);
|
||||
output.print("%02" PRIX8, outchar);
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
output.print("%c%c",
|
||||
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||
else // binary
|
||||
output.append(outchar);
|
||||
sum >>= 8;
|
||||
@ -572,10 +814,14 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||
{
|
||||
outchar = (sum >> 24) & 0xff;
|
||||
debug("ChecksumConverter %s: big endian appending 0x%X\n",
|
||||
debug("ChecksumConverter %s: big endian appending 0x02%" PRIX8 "\n",
|
||||
checksumMap[fnum].name, outchar);
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
output.printf("%02X", outchar);
|
||||
output.print("%02" PRIX8, outchar);
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
output.print("%c%c",
|
||||
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||
else // binary
|
||||
output.append(outchar);
|
||||
sum <<= 8;
|
||||
@ -584,42 +830,97 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
return true;
|
||||
}
|
||||
|
||||
int ChecksumConverter::
|
||||
scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
ssize_t ChecksumConverter::
|
||||
scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
|
||||
{
|
||||
int fnum = format.info[0];
|
||||
ulong sum;
|
||||
int start = format.width;
|
||||
int length = cursor-format.width;
|
||||
if (format.prec > 0) length -= format.prec;
|
||||
|
||||
debug("ChecksumConverter %s: input to check: \"%s\n",
|
||||
uint32_t sum;
|
||||
const char* info = format.info;
|
||||
uint32_t init = extract<uint32_t>(info);
|
||||
uint32_t xorout = extract<uint32_t>(info);
|
||||
size_t start = format.width;
|
||||
uint8_t fnum = extract<uint8_t>(info);
|
||||
size_t length = cursor;
|
||||
if (length >= start) length -= start;
|
||||
else length = 0;
|
||||
if (format.prec > 0) {
|
||||
if (length >= (size_t)format.prec) length -= format.prec;
|
||||
else length = 0;
|
||||
}
|
||||
|
||||
debug("ChecksumConverter %s: input to check: \"%s\"\n",
|
||||
checksumMap[fnum].name, input.expand(start,length)());
|
||||
|
||||
if (input.length() - cursor <
|
||||
(format.flags & zero_flag ? 2 : 1) * checksumMap[fnum].bytes)
|
||||
uint8_t nDigits =
|
||||
// get number of decimal digits from number of bytes: ceil(bytes*2.5)
|
||||
format.flags & sign_flag ? (checksumMap[fnum].bytes + 1) * 25 / 10 - 2 :
|
||||
format.flags & (zero_flag|left_flag) ? 2 * checksumMap[fnum].bytes :
|
||||
checksumMap[fnum].bytes;
|
||||
ssize_t expectedLength = nDigits;
|
||||
|
||||
if ((ssize_t)( input.length() - cursor ) < expectedLength)
|
||||
{
|
||||
error("Input too short for checksum\n");
|
||||
debug("ChecksumConverter %s: Input '%s' too short (%zu-%zu<%zu) for checksum\n",
|
||||
checksumMap[fnum].name, input.expand(cursor)(), input.length(), cursor, expectedLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sum = checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<uchar*>(input(start)), length,
|
||||
checksumMap[fnum].init) & mask[checksumMap[fnum].bytes];
|
||||
sum = (xorout ^ checksumMap[fnum].func(
|
||||
(uint8_t*)input(start), length, init))
|
||||
& mask[checksumMap[fnum].bytes];
|
||||
|
||||
debug("ChecksumConverter %s: input checksum is 0x%0*lX\n",
|
||||
debug("ChecksumConverter %s: input checksum is 0x%0*" PRIX32 "\n",
|
||||
checksumMap[fnum].name, 2*checksumMap[fnum].bytes, sum);
|
||||
|
||||
int i,j;
|
||||
unsigned inchar;
|
||||
|
||||
unsigned int inchar;
|
||||
|
||||
if (format.flags & sign_flag) // decimal
|
||||
{
|
||||
uint32_t sumin = 0;
|
||||
ssize_t i;
|
||||
for (i = 0; i < expectedLength; i++)
|
||||
{
|
||||
inchar = input[cursor+i];
|
||||
if (isdigit(inchar)) sumin = sumin*10+inchar-'0';
|
||||
else break;
|
||||
}
|
||||
if (sumin != sum)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input %0*" PRIu32 " does not match checksum %0*" PRIu32 "\n",
|
||||
checksumMap[fnum].name, (int)i, sumin, (int)expectedLength, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (format.flags & alt_flag) // lsb first (little endian)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||
{
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
{
|
||||
sscanf(input(cursor+2*i), "%2X", &inchar);
|
||||
if (sscanf(input(cursor+2*i), "%2x", &inchar) != 1)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte '%s' is not a hex byte\n",
|
||||
checksumMap[fnum].name, input.expand(cursor+2*i,2)());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
{
|
||||
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i]);
|
||||
return -1;
|
||||
}
|
||||
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||
return -1;
|
||||
}
|
||||
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||
}
|
||||
else // binary
|
||||
{
|
||||
@ -627,35 +928,52 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
}
|
||||
if (inchar != ((sum >> 8*i) & 0xff))
|
||||
{
|
||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " does not match checksum 0x%0*" PRIX32 "\n",
|
||||
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // msb first (big endian)
|
||||
{
|
||||
int8_t i;
|
||||
uint8_t j;
|
||||
for (i = checksumMap[fnum].bytes-1, j = 0; i >= 0; i--, j++)
|
||||
{
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
{
|
||||
sscanf(input(cursor+2*i), "%2x", &inchar);
|
||||
}
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
{
|
||||
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i]);
|
||||
return -1;
|
||||
}
|
||||
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||
return -1;
|
||||
}
|
||||
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||
}
|
||||
else // binary
|
||||
{
|
||||
inchar = input[cursor+i] & 0xff;
|
||||
}
|
||||
if (inchar != ((sum >> 8*j) & 0xff))
|
||||
{
|
||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
debug("ChecksumConverter %s: Input byte 0x%02" PRIX8 " does not match checksum 0x%0*" PRIX32 "\n",
|
||||
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
return 2*checksumMap[fnum].bytes;
|
||||
return checksumMap[fnum].bytes;
|
||||
return expectedLength;
|
||||
}
|
||||
|
||||
RegisterConverter (ChecksumConverter, "<");
|
||||
|
@ -1,26 +1,31 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is the interface to a debug and example bus drivers for *
|
||||
* StreamDevice. Please refer to the HTML files in ../doc/ for *
|
||||
* a detailed documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
/*************************************************************************
|
||||
* This is a debug and example bus interface for StreamDevice.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#include "StreamBusInterface.h"
|
||||
#include "StreamError.h"
|
||||
#include "StreamBuffer.h"
|
||||
|
||||
#define Z PRINTF_SIZE_T_PREFIX
|
||||
|
||||
// This is a non-blocking bus interface for debugging purpose.
|
||||
// Normally, a bus interface will use blocking I/O and thus require
|
||||
// a separate thread.
|
||||
@ -35,7 +40,7 @@ class DebugInterface : StreamBusInterface
|
||||
bool writeRequest(const void* output, size_t size,
|
||||
unsigned long writeTimeout_ms);
|
||||
bool readRequest(unsigned long replyTimeout_ms,
|
||||
unsigned long readTimeout_ms, long expectedLength, bool async);
|
||||
unsigned long readTimeout_ms, ssize_t expectedLength, bool async);
|
||||
|
||||
protected:
|
||||
~DebugInterface();
|
||||
@ -167,9 +172,9 @@ writeRequest(const void* output, size_t size, unsigned long writeTimeout_ms)
|
||||
// Return false if the read request cannot be accepted.
|
||||
bool DebugInterface::
|
||||
readRequest(unsigned long replyTimeout_ms, unsigned long readTimeout_ms,
|
||||
long expectedLength, bool async)
|
||||
ssize_t expectedLength, bool async)
|
||||
{
|
||||
debug("DebugInterface::readRequest(%s, %ld msec reply, %ld msec read, expect %ld bytes, asyn=%s)\n",
|
||||
debug("DebugInterface::readRequest(%s, %ld msec reply, %ld msec read, expect %" Z "d bytes, asyn=%s)\n",
|
||||
clientName(), replyTimeout_ms, readTimeout_ms, expectedLength, async?"yes":"no");
|
||||
|
||||
// Debug interface does not support async mode.
|
||||
|
81
src/DummyInterface.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/*************************************************************************
|
||||
* This is a debug and example bus interface for StreamDevice.
|
||||
* It does not provide any I/O functionality.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#include "StreamBusInterface.h"
|
||||
#include "StreamError.h"
|
||||
#include "StreamBuffer.h"
|
||||
|
||||
class DummyInterface : StreamBusInterface
|
||||
{
|
||||
DummyInterface(Client* client);
|
||||
|
||||
// StreamBusInterface methods
|
||||
bool lockRequest(unsigned long lockTimeout_ms);
|
||||
bool unlock();
|
||||
|
||||
protected:
|
||||
~DummyInterface();
|
||||
|
||||
public:
|
||||
// static creator method
|
||||
static StreamBusInterface* getBusInterface(Client* client,
|
||||
const char* busname, int addr, const char* param);
|
||||
};
|
||||
|
||||
RegisterStreamBusInterface(DummyInterface);
|
||||
|
||||
DummyInterface::
|
||||
DummyInterface(Client* client) : StreamBusInterface(client)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
DummyInterface::
|
||||
~DummyInterface()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
StreamBusInterface* DummyInterface::
|
||||
getBusInterface(Client* client,
|
||||
const char* busname, int addr, const char*)
|
||||
{
|
||||
if (strcmp(busname, "dummy") == 0)
|
||||
{
|
||||
DummyInterface* interface = new DummyInterface(client);
|
||||
return interface;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool DummyInterface::
|
||||
lockRequest(unsigned long lockTimeout_ms)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DummyInterface::
|
||||
unlock()
|
||||
{
|
||||
return false;
|
||||
}
|
@ -1,22 +1,26 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
|
||||
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is the enum format converter of StreamDevice. *
|
||||
* Please refer to the HTML files in ../doc/ for a detailed *
|
||||
* documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
/*************************************************************************
|
||||
* This is the enum format converter of StreamDevice.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "StreamFormatConverter.h"
|
||||
#include "StreamError.h"
|
||||
@ -28,47 +32,88 @@ class EnumConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
ssize_t scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
// info format: <numEnums><index><string>0<index><string>0...
|
||||
|
||||
int EnumConverter::
|
||||
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
const char*& source, bool)
|
||||
const char*& source, bool scanFormat)
|
||||
{
|
||||
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag|alt_flag))
|
||||
if (fmt.flags & (left_flag|sign_flag|space_flag|zero_flag))
|
||||
{
|
||||
error("Use of modifiers '-', '+', ' ', '0', '#'"
|
||||
error("Use of modifiers '-', '+', ' ', '0' "
|
||||
"not allowed with %%{ conversion\n");
|
||||
return false;
|
||||
}
|
||||
int i = info.length(); // put maxValue here later
|
||||
info.append('\0');
|
||||
int maxValue = 0;
|
||||
long numEnums = 0;
|
||||
size_t n = info.length(); // put numEnums here later
|
||||
info.append(&numEnums, sizeof(numEnums));
|
||||
long index = 0;
|
||||
size_t i = 0;
|
||||
i = info.length(); // put index here later
|
||||
info.append(&index, sizeof(index));
|
||||
while (*source)
|
||||
{
|
||||
switch (*source)
|
||||
if (*source == '=' && (fmt.flags & alt_flag))
|
||||
{
|
||||
case '|':
|
||||
info.append('\0');
|
||||
if (++maxValue > 255)
|
||||
char* p;
|
||||
|
||||
if (*++source == '?')
|
||||
{
|
||||
// default choice
|
||||
if (scanFormat)
|
||||
{
|
||||
error("Too many enums (max 256)\n");
|
||||
error("Default value only allowed in output formats\n");
|
||||
return false;
|
||||
}
|
||||
if (*++source != '}')
|
||||
{
|
||||
error("Default value must be last\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case '}':
|
||||
source++;
|
||||
numEnums = -(numEnums+1);
|
||||
info.append('\0');
|
||||
info[i] = maxValue;
|
||||
debug("EnumConverter::parse %d choices: %s\n",
|
||||
maxValue+1, info.expand(i+1)());
|
||||
memcpy(info(n), &numEnums, sizeof(numEnums));
|
||||
debug2("EnumConverter::parse %ld choices with default: %s\n",
|
||||
-numEnums, info.expand()());
|
||||
return enum_format;
|
||||
case esc:
|
||||
info.append(*source++);
|
||||
default:
|
||||
info.append(*source);
|
||||
}
|
||||
|
||||
index = strtol(source, &p, 0);
|
||||
if (p == source || (*p != '|' && *p != '}'))
|
||||
{
|
||||
error("Integer expected after '=' "
|
||||
"in %%{ format conversion\n");
|
||||
return false;
|
||||
}
|
||||
memcpy(info(i), &index, sizeof(index));
|
||||
source = p;
|
||||
}
|
||||
if (*source == '|' || *source == '}')
|
||||
{
|
||||
numEnums++;
|
||||
info.append('\0');
|
||||
|
||||
if (*source++ == '}')
|
||||
{
|
||||
memcpy(info(n), &numEnums, sizeof(numEnums));
|
||||
debug2("EnumConverter::parse %ld choices: %s\n",
|
||||
numEnums, info.expand()());
|
||||
return enum_format;
|
||||
}
|
||||
index++;
|
||||
i = info.length();
|
||||
info.append(&index, sizeof(index));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*source == esc)
|
||||
info.append(*source++);
|
||||
info.append(*source++);
|
||||
}
|
||||
source++;
|
||||
}
|
||||
error("Missing '}' after %%{ format conversion\n");
|
||||
return false;
|
||||
@ -77,23 +122,28 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
bool EnumConverter::
|
||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
{
|
||||
long maxValue = fmt.info[0]; // number of enums
|
||||
const char* s = fmt.info+1; // first enum string
|
||||
if (value < 0 || value > maxValue)
|
||||
const char* s = fmt.info;
|
||||
long numEnums = extract<long>(s);
|
||||
long index = extract<long>(s);
|
||||
bool noDefault = numEnums >= 0;
|
||||
|
||||
if (numEnums < 0) numEnums=-numEnums-1;
|
||||
while (numEnums-- && (value != index))
|
||||
{
|
||||
error("Value %li out of range [0...%li]\n", value, maxValue);
|
||||
return false;
|
||||
}
|
||||
while (value--)
|
||||
{
|
||||
while(*s)
|
||||
while (*s)
|
||||
{
|
||||
if (*s == esc) s++;
|
||||
s++;
|
||||
}
|
||||
s++;
|
||||
index = extract<long>(s);
|
||||
}
|
||||
while(*s)
|
||||
if (numEnums == -1 && noDefault)
|
||||
{
|
||||
error("Value %li not found in enum set\n", value);
|
||||
return false;
|
||||
}
|
||||
while (*s)
|
||||
{
|
||||
if (*s == esc) s++;
|
||||
output.append(*s++);
|
||||
@ -101,37 +151,39 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int EnumConverter::
|
||||
ssize_t EnumConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
debug("EnumConverter::scanLong(%%%c, \"%s\")\n",
|
||||
fmt.conv, input);
|
||||
long maxValue = fmt.info[0]; // number of enums
|
||||
const char* s = fmt.info+1; // first enum string
|
||||
int length;
|
||||
long val;
|
||||
const char* s = fmt.info;
|
||||
long numEnums = extract<long>(s);
|
||||
long index;
|
||||
ssize_t consumed;
|
||||
bool match;
|
||||
for (val = 0; val <= maxValue; val++)
|
||||
|
||||
while (numEnums--)
|
||||
{
|
||||
debug("EnumConverter::scanLong: check #%ld \"%s\"\n", val, s);
|
||||
length = 0;
|
||||
index = extract<long>(s);
|
||||
debug("EnumConverter::scanLong: check #%ld \"%s\"\n", index, s);
|
||||
consumed = 0;
|
||||
match = true;
|
||||
while(*s)
|
||||
while (*s)
|
||||
{
|
||||
if (*s == StreamProtocolParser::skip)
|
||||
{
|
||||
s++;
|
||||
length++;
|
||||
consumed++;
|
||||
continue;
|
||||
}
|
||||
if (*s == esc) s++;
|
||||
if (*s++ != input[length++]) match = false;
|
||||
if (*s++ != input[consumed++]) match = false;
|
||||
}
|
||||
if (match)
|
||||
{
|
||||
debug("EnumConverter::scanLong: value %ld matches\n", val);
|
||||
value = val;
|
||||
return length;
|
||||
debug("EnumConverter::scanLong: value %ld matches\n", index);
|
||||
value = index;
|
||||
return consumed;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
/***************************************************************
|
||||
* StreamDevice Support *
|
||||
* *
|
||||
* (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) *
|
||||
* (C) 2007 Dirk Zimoch (dirk.zimoch@psi.ch) *
|
||||
* *
|
||||
* This is a custom exponential format converter for *
|
||||
* StreamDevice. *
|
||||
* The number is represented as two signed integers, mantissa *
|
||||
* and exponent, like in +00011-01 *
|
||||
* Please refer to the HTML files in ../doc/ for a detailed *
|
||||
* documentation. *
|
||||
* *
|
||||
* If you do any changes in this file, you are not allowed to *
|
||||
* redistribute it any more. If there is a bug or a missing *
|
||||
* feature, send me an email and/or your patch. If I accept *
|
||||
* your changes, they will go to the next release. *
|
||||
* *
|
||||
* DISCLAIMER: If this software breaks something or harms *
|
||||
* someone, it's your problem. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#include "StreamFormatConverter.h"
|
||||
#include "StreamError.h"
|
||||
#include <math.h>
|
||||
|
||||
// Exponential Converter %m: format +00351-02 means +351e-2
|
||||
|
||||
class ExponentialConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual int scanDouble(const StreamFormat&, const char*, double&);
|
||||
};
|
||||
|
||||
int ExponentialConverter::
|
||||
parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
const char*& source, bool scanFormat)
|
||||
{
|
||||
if (!scanFormat)
|
||||
{
|
||||
error("At the moment for %%m format only input is implemented\n");
|
||||
return false;
|
||||
}
|
||||
return double_format;
|
||||
}
|
||||
|
||||
int ExponentialConverter::
|
||||
scanDouble(const StreamFormat& fmt, const char* input, double& value)
|
||||
{
|
||||
int mantissa;
|
||||
int exponent;
|
||||
int length = -1;
|
||||
|
||||
sscanf(input, "%d%d%n", &mantissa, &exponent, &length);
|
||||
if (fmt.flags & skip_flag) return length;
|
||||
if (length == -1) return -1;
|
||||
value = (double)(mantissa) * pow(10, exponent);
|
||||
return length;
|
||||
}
|
||||
|
||||
RegisterConverter (ExponentialConverter, "m");
|
||||
|
101
src/MacroMagic.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*************************************************************************
|
||||
* This header provides macros for enum to string conversions.
|
||||
* Please see ../docs/ for detailed documentation.
|
||||
*
|
||||
* (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
*
|
||||
* This file is part of StreamDevice.
|
||||
*
|
||||
* StreamDevice is free software: You can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* StreamDevice is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _MacroMagic_h
|
||||
#define _MacroMagic_h
|
||||
|
||||
#if defined __GNUC__ && __GNUC__ < 3
|
||||
|
||||
/* Using old GCC variadic macros */
|
||||
|
||||
#define _NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, args...) N
|
||||
|
||||
#define _fe_0(_call, args...)
|
||||
#define _fe_1(_call, x) _call(x)
|
||||
#define _fe_2(_call, x, args...) _call(x) _fe_1(_call, args)
|
||||
#define _fe_3(_call, x, args...) _call(x) _fe_2(_call, args)
|
||||
#define _fe_4(_call, x, args...) _call(x) _fe_3(_call, args)
|
||||
#define _fe_5(_call, x, args...) _call(x) _fe_4(_call, args)
|
||||
#define _fe_6(_call, x, args...) _call(x) _fe_5(_call, args)
|
||||
#define _fe_7(_call, x, args...) _call(x) _fe_6(_call, args)
|
||||
#define _fe_8(_call, x, args...) _call(x) _fe_7(_call, args)
|
||||
#define _fe_9(_call, x, args...) _call(x) _fe_8(_call, args)
|
||||
#define _fe_10(_call, x, args...) _call(x) _fe_9(_call, args)
|
||||
|
||||
#define MACRO_FOR_EACH(x, args...) \
|
||||
_NTH_ARG(_, ##args, \
|
||||
_fe_10, _fe_9, _fe_8, _fe_7, _fe_6, _fe_5, _fe_4, _fe_3, _fe_2, _fe_1, _fe_0) \
|
||||
(x, ##args)
|
||||
|
||||
/* Enum to string magic */
|
||||
|
||||
#define ENUM(type, args...) \
|
||||
enum type { args }; \
|
||||
static inline const char* type##ToStr(int x) {switch(x) {MACRO_FOR_EACH(_CASE_LINE,args)default: return "invalid";}}\
|
||||
_ENUM_CAST(type)
|
||||
|
||||
#else
|
||||
|
||||
/* Using ISO C variadic macros */
|
||||
|
||||
#define _NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, ...) N
|
||||
|
||||
/*
|
||||
* we need to use _EXPAND below to work around a problem in Visual Studio 2010
|
||||
* where __VA_ARGS__ is treated as a single argument
|
||||
* See https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
|
||||
*/
|
||||
#define _EXPAND( x ) x
|
||||
|
||||
#define _fe_0(_call, ...)
|
||||
#define _fe_1(_call, x) _call(x)
|
||||
#define _fe_2(_call, x, ...) _call(x) _EXPAND(_fe_1(_call, __VA_ARGS__))
|
||||
#define _fe_3(_call, x, ...) _call(x) _EXPAND(_fe_2(_call, __VA_ARGS__))
|
||||
#define _fe_4(_call, x, ...) _call(x) _EXPAND(_fe_3(_call, __VA_ARGS__))
|
||||
#define _fe_5(_call, x, ...) _call(x) _EXPAND(_fe_4(_call, __VA_ARGS__))
|
||||
#define _fe_6(_call, x, ...) _call(x) _EXPAND(_fe_5(_call, __VA_ARGS__))
|
||||
#define _fe_7(_call, x, ...) _call(x) _EXPAND(_fe_6(_call, __VA_ARGS__))
|
||||
#define _fe_8(_call, x, ...) _call(x) _EXPAND(_fe_7(_call, __VA_ARGS__))
|
||||
#define _fe_9(_call, x, ...) _call(x) _EXPAND(_fe_8(_call, __VA_ARGS__))
|
||||
#define _fe_10(_call, x, ...) _call(x) _EXPAND(_fe_9(_call, __VA_ARGS__))
|
||||
|
||||
#define MACRO_FOR_EACH(x, ...) \
|
||||
_EXPAND(_NTH_ARG(_, ##__VA_ARGS__, \
|
||||
_fe_10, _fe_9, _fe_8, _fe_7, _fe_6, _fe_5, _fe_4, _fe_3, _fe_2, _fe_1, _fe_0) \
|
||||
(x, ##__VA_ARGS__))
|
||||
|
||||
/* Enum to string magic */
|
||||
|
||||
#define ENUM(type,...) \
|
||||
enum type { __VA_ARGS__ }; \
|
||||
static inline const char* type##ToStr(int x) {switch(x) {_EXPAND(MACRO_FOR_EACH(_CASE_LINE,__VA_ARGS__)) default: return "invalid";}} \
|
||||
_ENUM_CAST(type)
|
||||
#endif
|
||||
|
||||
#define _CASE_LINE(x) case x: return #x;
|
||||
#ifdef __cplusplus
|
||||
#define _ENUM_CAST(type) ; static inline const char* toStr(type x) {return type##ToStr(x);}
|
||||
#else
|
||||
#define _ENUM_CAST(type)
|
||||
#endif
|
||||
|
||||
#endif
|
160
src/Makefile
@ -1,60 +1,52 @@
|
||||
################################################################
|
||||
# StreamDevice Support #
|
||||
# #
|
||||
# (C) 1999 Dirk Zimoch (zimoch@delta.uni-dortmund.de) #
|
||||
# (C) 2007 Dirk Zimoch (dirk.zimoch@psi.ch) #
|
||||
# #
|
||||
# This is the EPICS 3.14 Makefile of StreamDevice. #
|
||||
# Normally it should not be necessary to modify this file. #
|
||||
# All configuration can be done in CONFIG_STREAM #
|
||||
# #
|
||||
# If you do any changes in this file, you are not allowed to #
|
||||
# redistribute it any more. If there is a bug or a missing #
|
||||
# feature, send me an email and/or your patch. If I accept #
|
||||
# your changes, they will go to the next release. #
|
||||
# #
|
||||
# DISCLAIMER: If this software breaks something or harms #
|
||||
# someone, it's your problem. #
|
||||
# #
|
||||
################################################################
|
||||
##########################################################################
|
||||
# This is the EPICS 3.14+ Makefile for StreamDevice.
|
||||
# Normally it should not be necessary to modify this file.
|
||||
# All configuration can be done in CONFIG_STREAM
|
||||
#
|
||||
# (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch)
|
||||
#
|
||||
# This file is part of StreamDevice.
|
||||
#
|
||||
# StreamDevice is free software: You can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# StreamDevice is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with StreamDevice. If not, see https://www.gnu.org/licenses/.
|
||||
#########################################################################/
|
||||
|
||||
TOP=../..
|
||||
|
||||
# Look if we have EPICS R3.13 or R3.14
|
||||
ifeq ($(wildcard $(TOP)/configure),)
|
||||
# EPICS R3.13
|
||||
include $(TOP)/config/CONFIG_APP
|
||||
# The real work is in Makefile.Vx
|
||||
include $(TOP)/config/RULES_ARCHS
|
||||
else
|
||||
|
||||
# EPICS R3.14
|
||||
TOP= ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
-include CONFIG_STREAM
|
||||
-include ../CONFIG_STREAM
|
||||
|
||||
LIBRARY_DEFAULT = stream
|
||||
LIBRARY_IOC = stream
|
||||
|
||||
DBD += $(LIBRARY_DEFAULT).dbd
|
||||
DBD += stream.dbd
|
||||
DBD += stream-base.dbd
|
||||
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||
DBD += stream-scalcout.dbd
|
||||
endif
|
||||
|
||||
ifdef ASYN
|
||||
LIB_LIBS += asyn
|
||||
BUSSES += AsynDriver
|
||||
endif
|
||||
|
||||
ifdef T_A
|
||||
ifndef BUSSES
|
||||
$(error No bus interface defined! Didn't you set ASYN in your RELEASE file?)
|
||||
endif
|
||||
else
|
||||
$(warning Asyn not included! Didn't you set ASYN in your RELEASE file?)
|
||||
endif
|
||||
|
||||
ifeq ($(LOADABLE_MODULE),YES)
|
||||
SRCS += $(LIBRARY_DEFAULT)_registerRecordDeviceDriver.cpp
|
||||
endif
|
||||
SRCS += stream_registerRecordDeviceDriver.cpp
|
||||
endif
|
||||
SRCS += $(BUSSES:%=%Interface.cc)
|
||||
SRCS += $(FORMATS:%=%Converter.cc)
|
||||
SRCS += $(RECORDS:%=dev%Stream.c)
|
||||
SRCS += $(RECORDTYPES:%=dev%Stream.c)
|
||||
SRCS += $(STREAM_SRCS)
|
||||
|
||||
# find system wide or local PCRE header and library
|
||||
@ -65,50 +57,72 @@ ifdef PCRE
|
||||
LIB_LIBS += pcre
|
||||
else
|
||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
LIB_SYS_LIBS += pcre
|
||||
LIB_SYS_LIBS_DEFAULT += pcre
|
||||
LIB_SYS_LIBS_WIN32 += $(PCRE_LIB)\\pcre
|
||||
SHRLIB_DEPLIB_DIRS += $(PCRE_LIB)
|
||||
ifdef ENABLE_STATIC
|
||||
CPPFLAGS += -DPCRE_STATIC
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
LIB_LIBS += Com dbIoc dbStaticIoc registryIoc iocsh
|
||||
|
||||
ifeq ($(USE_MEMGUARD),YES)
|
||||
# memguard looks for memory leaks (gcc only)
|
||||
CPPFLAGS += -include ../memguard.h
|
||||
LIB_SRCS += memguard.cc
|
||||
endif
|
||||
LIB_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
INC += devStream.h
|
||||
INC += StreamFormat.h
|
||||
INC += StreamFormatConverter.h
|
||||
INC += StreamBuffer.h
|
||||
INC += StreamError.h
|
||||
INC += StreamVersion.h
|
||||
INC += StreamProtocol.h
|
||||
INC += StreamBusInterface.h
|
||||
INC += StreamCore.h
|
||||
INC += MacroMagic.h
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
# switch off annoying rset warnings in 3.16+
|
||||
CPPFLAGS += -DUSE_TYPED_RSET
|
||||
|
||||
# Update version string (contains __DATE__ and __TIME__)
|
||||
# each time make runs.
|
||||
StreamVersion$(OBJ): FORCE
|
||||
FORCE:
|
||||
CPPFLAGS += -DSTREAM_INTERNAL
|
||||
|
||||
-include $(TOP)/configure/RULES
|
||||
|
||||
# Update version string whenever something changed.
|
||||
StreamVersion$(OBJ): $(COMMON_DIR)/StreamVersion.h $(filter-out StreamVersion$(OBJ),$(LIBOBJS) $(LIBRARY_OBJS)) ../CONFIG_STREAM
|
||||
$(COMMON_DIR)/StreamVersion.h: ../../.VERSION $(SRCS) $(filter-out StreamVersion.h, $(INC))
|
||||
@echo Creating $@
|
||||
$(PERL) ../makeStreamVersion.pl $@
|
||||
|
||||
# Add references to all registrars to main file to avoid
|
||||
# missing initialization.
|
||||
StreamCore$(OBJ): streamReferences
|
||||
StreamCore$(OBJ) StreamCore$(DEP): streamReferences
|
||||
|
||||
streamReferences: ../CONFIG_STREAM
|
||||
@for i in $(BUSSES); \
|
||||
do echo "extern void* ref_$${i}Interface;"; \
|
||||
echo "void* p$$i = ref_$${i}Interface;"; \
|
||||
done > $@
|
||||
@for i in $(FORMATS); \
|
||||
do echo "extern void* ref_$${i}Converter;"; \
|
||||
echo "void* p$$i = ref_$${i}Converter;"; \
|
||||
done >> $@
|
||||
$(PERL) ../makeref.pl Interface $(BUSSES) > $@
|
||||
$(PERL) ../makeref.pl Converter $(FORMATS) >> $@
|
||||
|
||||
# create stream.dbd from all RECORDS
|
||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
|
||||
@for r in $(RECORDS); \
|
||||
do echo "device($$r,INST_IO,dev$${r}Stream,\"stream\")"; \
|
||||
done > $@
|
||||
@echo "driver(stream)" >> $@
|
||||
@echo "variable(streamDebug, int)" >> $@
|
||||
@echo "variable(showAsyncErrors, int)" >> $@
|
||||
@echo "registrar(streamRegistrar)" >> $@
|
||||
# create stream-base.dbd from all RECORDTYPES except scalcout record
|
||||
$(COMMON_DIR)/stream-base.dbd: ../CONFIG_STREAM
|
||||
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(filter-out scalcout, $(RECORDTYPES)) > $@
|
||||
|
||||
stream-base.dbd$(DEP): ../CONFIG_STREAM
|
||||
echo stream-base.dbd: $< > $@
|
||||
|
||||
STREAM_DBD_FILES = stream-base.dbd
|
||||
|
||||
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||
# create stream-scalcout.dbd for scalcout record
|
||||
$(COMMON_DIR)/stream-scalcout.dbd: ../CONFIG_STREAM
|
||||
$(PERL) ../makedbd.pl --rec-only scalcout > $@
|
||||
|
||||
stream-scalcout.dbd$(DEP): ../CONFIG_STREAM
|
||||
echo stream-scalcout.dbd: $< > $@
|
||||
|
||||
STREAM_DBD_FILES += stream-scalcout.dbd
|
||||
endif
|
||||
|
||||
# create stream.dbd for all record types
|
||||
$(COMMON_DIR)/stream.dbd: ../CONFIG_STREAM
|
||||
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(RECORDTYPES) > $@
|
||||
|
||||
stream.dbd$(DEP): ../CONFIG_STREAM
|
||||
echo stream.dbd: $< > $@
|
||||
|