├── .VERSION ├── .ci-local └── defaults.set ├── .cvsignore ├── .gitattributes ├── .github └── workflows │ └── ci-scripts-build.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Contributing.md ├── LICENSE ├── LICENSE.LESSER ├── Makefile ├── README.md ├── config ├── CONFIG_APP ├── Makefile ├── Makefile.Host ├── Makefile.Vx ├── RULES.Host ├── RULES.munch ├── RULES_ARCHS ├── RULES_DIRS ├── convertRelease.pl ├── makeConfigAppInclude.pl └── munch.pl ├── configure ├── CONFIG ├── CONFIG_SITE ├── Makefile ├── RELEASE └── RULES ├── docs ├── PSI.png ├── aai.html ├── aao.html ├── ai.html ├── ao.html ├── bi.html ├── bo.html ├── businterface.html ├── calcout.html ├── epics3_13.html ├── ex.png ├── exr.png ├── favicon.ico ├── formatconverter.html ├── formats.html ├── index.html ├── int64in.html ├── int64out.html ├── longin.html ├── longout.html ├── lsi.html ├── lso.html ├── makepdf ├── mbbi.html ├── mbbiDirect.html ├── mbbo.html ├── mbboDirect.html ├── nav.html ├── osinterface.html ├── processing.html ├── protocol.html ├── recordinterface.html ├── recordtypes.html ├── scalcout.html ├── setup.html ├── stream.css ├── stringin.html ├── stringout.html ├── tipsandtricks.html └── waveform.html ├── src ├── AsynDriverInterface.cc ├── BCDConverter.cc ├── BinaryConverter.cc ├── CONFIG_STREAM ├── ChecksumConverter.cc ├── DebugInterface.cc ├── DummyInterface.cc ├── EnumConverter.cc ├── MacroMagic.h ├── Makefile ├── Makefile.Host ├── Makefile.Vx ├── MantissaExponentConverter.cc ├── RawConverter.cc ├── RawFloatConverter.cc ├── RegexpConverter.cc ├── StreamBuffer.cc ├── StreamBuffer.h ├── StreamBusInterface.cc ├── StreamBusInterface.h ├── StreamCore.cc ├── StreamCore.h ├── StreamEpics.cc ├── StreamError.cc ├── StreamError.h ├── StreamFormat.h ├── StreamFormatConverter.cc ├── StreamFormatConverter.h ├── StreamProtocol.cc ├── StreamProtocol.h ├── StreamVersion.c ├── TimestampConverter.cc ├── devStream.h ├── devaaiStream.c ├── devaaoStream.c ├── devaiStream.c ├── devaoStream.c ├── devbiStream.c ├── devboStream.c ├── devcalcoutStream.c ├── devint64inStream.c ├── devint64outStream.c ├── devlonginStream.c ├── devlongoutStream.c ├── devlsiStream.c ├── devlsoStream.c ├── devmbbiDirectStream.c ├── devmbbiStream.c ├── devmbboDirectStream.c ├── devmbboStream.c ├── devscalcoutStream.c ├── devstringinStream.c ├── devstringoutStream.c ├── devwaveformStream.c ├── makeStreamVersion.pl ├── makedbd.pl └── makeref.pl └── streamApp ├── .cvsignore ├── .gitignore ├── Makefile ├── Makefile.Host ├── Makefile.Vx ├── base-3-13.dbd ├── base-3-13LIBOBJS ├── checksums.cmd ├── checksums.db ├── checksums.proto ├── example-3-13.cmd ├── example.cmd ├── example.db ├── example.proto ├── regexp.README ├── regexp.cmd ├── regexp.db ├── regexp.proto ├── simple.cmd ├── simple.db ├── simple.proto ├── streamAppMain.cc ├── terminal.tcl ├── test.adl ├── test.cmd ├── test.db ├── test.proto ├── test.readme └── tests ├── printdouble ├── streamtestlib.tcl ├── test64Bit ├── testBo ├── testCharset ├── testChecksum ├── testCompare ├── testDefaultInput ├── testDouble ├── testEnum ├── testFormatm ├── testFormats ├── testHalfInputTerminator ├── testInteger ├── testIoIntrPollTimeout ├── testLongInputTerminator ├── testLongUnsolicitedInput ├── testMultiLineFormatString ├── testOutTerminators ├── testPINI ├── testParallelAccess ├── testParenthesesInParameters ├── testPercent ├── testPerformance ├── testQuotes ├── testRaw ├── testRawFloat ├── testSeverityAndStatus ├── testSkeleton ├── testSpyOnLongInput ├── testStrangesum ├── testStreamBuffer ├── testString ├── testTimestamp ├── testWaage ├── testWaveform └── testall /.VERSION: -------------------------------------------------------------------------------- 1 | COMMIT: 20dde4c1d8adec5ebb7c0fc54a06fd7511cfe07e 2 | REFS: HEAD -> master 3 | DATE: 2025-05-27 17:09:16 +0200 4 | -------------------------------------------------------------------------------- /.ci-local/defaults.set: -------------------------------------------------------------------------------- 1 | MODULES=calc asyn 2 | 3 | # EPICS Base 4 | BASE_DIRNAME=base 5 | BASE_REPONAME=epics-base 6 | BASE_REPOOWNER=epics-base 7 | BASE_VARNAME=EPICS_BASE 8 | BASE_RECURSIVE=no 9 | 10 | ASYN_REPOOWNER=epics-modules 11 | 12 | CALC_REPOOWNER=epics-modules 13 | -------------------------------------------------------------------------------- /.cvsignore: -------------------------------------------------------------------------------- 1 | O.* 2 | *~ 3 | bin 4 | lib 5 | dbd 6 | include 7 | *.pdf 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | GNUmakefile export-ignore 2 | .VERSION export-subst 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | O.* 2 | *~ 3 | bin 4 | lib 5 | dbd 6 | include 7 | *.pdf 8 | *.*log 9 | StreamVersion.h 10 | *.local 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".ci"] 2 | path = .ci 3 | url = https://github.com/epics-base/ci-scripts.git 4 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to StreamDevice 2 | 3 | Contributions from the EPICS community (and others) are welcome. 4 | To ease the integration process, please follow the following guidelines. 5 | 6 | All contributions should be done as a pull request to the git repository 7 | https://github.com/paulscherrerinstitute/StreamDevice. Make sure to provide 8 | meaningful commit messages (no essay but more than "changes"). 9 | 10 | For small modifications, a patch file is sufficient. Send it to me or better 11 | create an issue on https://github.com/paulscherrerinstitute/StreamDevice/issues 12 | and attach the patch file. 13 | 14 | Justify your change requests. Write a short summary for your pull request 15 | to explain what the change is about and what it improves or which bug it 16 | fixes. Use the issue system on github to report bugs. 17 | 18 | I reserve the right to accept or reject contributions or to request 19 | modifications before I accept them. 20 | 21 | Of course, you may as well report bugs without providing a solution yourself. 22 | 23 | ## Code compatibility 24 | 25 | All code must compile for any EPICS release from at least R3.14.12 up to the 26 | latest one. Likewise the code must be compatible with any operating system 27 | supported by EPICS, like Linux, Windows, MacOS, RTEMS and VxWorks. 28 | In particular VxWorks 5 compatibility rules out many modern C++ features. 29 | But there are also other platforms that for example do not support C++11, so 30 | don't use it. 31 | There should also be no compiler warning on any OS. 32 | 33 | Avoid compiler dependent features like #pragmas, assumptions on byte order, 34 | type size (in particular the size of pointers and long int) and other 35 | non-portable things like the availability of certain header files. Make sure 36 | non-portable code parts are enclosed in proper compiler branches and provide 37 | working implementations for all architectures. 38 | 39 | Make sure that the code in AsynDriverInterface stays compatible with old 40 | and new versions of asyn driver. 41 | 42 | The core of StreamDevice does not depend on EPICS. This is on purpose, to be 43 | able to use it in other control system frameworks. Modifications should not 44 | add EPICS dependencies except to StreamEpics and AsynDriverInterface, or the 45 | new dependency must be in a separate file which can be left out of the build 46 | without jeopardizing the main functionality of StreamDevice. 47 | 48 | The code must not depend on external libraries that may not be available on 49 | all systems, except if provided as a separate file which can be left out of 50 | the build on platforms that do not support the library. 51 | 52 | ## Language 53 | 54 | Write in English. That includes all identifiers (variables, functions, ...), 55 | comments, documentation and commit messages. Check your spelling. 56 | 57 | ## File formats 58 | 59 | All files are in Unix format (\n line terminators). Do not change them to 60 | any other format (e.g. Windows with \r\n terminators). Do not add new files in 61 | other formats. 62 | 63 | The files must contain only ASCII characters. Do not use any Unicode multi-byte 64 | characters (including byte order marks) or any pre-Unicode code page dependent 65 | characters (e.g. umlaut), not even in comments. Do not use form feed, vertical 66 | tab, or other control characters except newline. 67 | 68 | Indents are 4 spaces. Do not use tabs (except in Makefiles). Make sure your 69 | editor is set up accordingly. 70 | 71 | Files must end in a newline and there must be no spaces at the end of lines. 72 | Do not add excessive amount of newlines at the end of files. 73 | 74 | Do not add any editor configurations (e.g. for emacs) to the files. Also do 75 | not add any configuration files or directories for development environments, 76 | editors, etc. 77 | 78 | ------- 79 | 80 | Dirk Zimoch , June 2021 81 | 82 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an EPICS Makefile for StreamDevice. 3 | # Normally it should not be necessary to modify this file. 4 | # All configuration can be done in CONFIG_STREAM 5 | # 6 | # (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | # 8 | # This file is part of StreamDevice. 9 | # 10 | # StreamDevice is free software: You can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # StreamDevice is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | #########################################################################/ 23 | 24 | TOP = . 25 | DIRS = configure 26 | src_DEPEND_DIRS := $(DIRS) 27 | include $(TOP)/configure/CONFIG 28 | 29 | DIRS += src 30 | DIRS += streamApp 31 | streamApp_DEPEND_DIRS = src 32 | 33 | include $(CONFIG)/RULES_TOP 34 | 35 | docs/stream.pdf: docs/*.html docs/*.css docs/*.png 36 | cd docs; makepdf 37 | 38 | pdf: docs/stream.pdf 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StreamDevice 2 | 3 | _StreamDevice_ is a generic [EPICS](https://epics.anl.gov/) 4 | device support for devices with a "byte stream" based 5 | communication interface. 6 | That means devices that can be controlled by sending and receiving 7 | strings (in the broadest sense, including non-printable characters 8 | and even null-bytes). 9 | Examples for this type of communication interface are 10 | serial line (RS-232, RS-485, ...), 11 | IEEE-488 (also known as GPIB or HP-IB), and telnet-like TCP/IP. 12 | 13 | _StreamDevice_ is not limited to a specific device type or manufacturer 14 | nor is it necessary to re-compile anything to support a new device type. 15 | Instead, it can be configured for any device type with _protocol files_ 16 | in plain ASCII text which describes the commands a device understands 17 | and the replies it sends. 18 | 19 | For a full documentation see 20 | https://paulscherrerinstitute.github.io/StreamDevice. 21 | 22 | ## Licensing 23 | 24 | StreamDevice is free software: You can redistribute it and/or modify 25 | it under the terms of the GNU Lesser General Public License as published 26 | by the Free Software Foundation, either version 3 of the License, or 27 | (at your option) any later version. 28 | 29 | StreamDevice is distributed in the hope that it will be useful, 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | GNU Lesser General Public License for more details. 33 | 34 | You should have received a copy of the GNU Lesser General Public License 35 | along with StreamDevice. If not, see https://www.gnu.org/licenses/. 36 | -------------------------------------------------------------------------------- /config/CONFIG_APP: -------------------------------------------------------------------------------- 1 | #CONFIG_APP 2 | include $(TOP)/configure/RELEASE 3 | -include $(TOP)/configure/RELEASE.$(HOST_ARCH) 4 | -include $(EPICS_BASE)/config/CONFIG 5 | INSTALL_LOCATION = $(TOP) 6 | ifdef INSTALL_LOCATION_APP 7 | INSTALL_LOCATION = $(INSTALL_LOCATION_APP) 8 | endif 9 | 10 | ifdef T_A 11 | -include $(TOP)/config/O.$(T_A)/CONFIG_APP_INCLUDE 12 | endif 13 | -------------------------------------------------------------------------------- /config/Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an EPICS Makefile for StreamDevice. 3 | # Normally it should not be necessary to modify this file. 4 | # All configuration can be done in CONFIG_STREAM 5 | # 6 | # (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | # 8 | # This file is part of StreamDevice. 9 | # 10 | # StreamDevice is free software: You can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # StreamDevice is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | #########################################################################/ 23 | 24 | TOP=.. 25 | include $(TOP)/config/CONFIG_APP 26 | ifneq ($(wildcard $(EPICS_BASE)/config),) 27 | include $(EPICS_BASE)/config/RULES_ARCHS 28 | else 29 | build install clean realclean: 30 | endif 31 | -------------------------------------------------------------------------------- /config/Makefile.Host: -------------------------------------------------------------------------------- 1 | # 2 | # $Id: Makefile.Host,v 1.1.1.1 2000/04/05 07:33:44 janousch Exp $ 3 | # 4 | 5 | TOP=../.. 6 | include $(TOP)/config/CONFIG_APP 7 | 8 | TARGETS = CONFIG_APP_INCLUDE 9 | 10 | include $(TOP)/config/RULES.Host 11 | 12 | inc:: $(TARGETS) 13 | 14 | ifeq ($(wildcard $(TOP)/configure/RELEASE.$(HOST_ARCH)),$(TOP)/configure/RELEASE.$(HOST_ARCH)) 15 | CONFIG_APP_INCLUDE: $(TOP)/configure/RELEASE.$(HOST_ARCH) 16 | endif 17 | 18 | CONFIG_APP_INCLUDE: $(TOP)/configure/RELEASE $(TOP)/config/CONFIG_APP 19 | $(RM) $@ 20 | @$(PERL) $(TOP)/config/makeConfigAppInclude.pl $(T_A) $@ $(TOP) 21 | -------------------------------------------------------------------------------- /config/Makefile.Vx: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile.Vx,v 1.1.2.3 2001/09/14 19:39:15 anj Exp 3 | # 4 | 5 | TOP=../.. 6 | include $(TOP)/config/CONFIG_APP 7 | 8 | TARGETS = CONFIG_APP_INCLUDE 9 | 10 | include $(EPICS_BASE)/config/RULES.Vx 11 | 12 | inc:: $(TARGETS) 13 | 14 | CONFIG_APP_INCLUDE: $(wildcard $(TOP)/config/RELEASE*) $(TOP)/config/CONFIG_APP 15 | $(PERL) $(TOP)/config/convertRelease.pl -h $(HOST_ARCH) $@ 16 | -------------------------------------------------------------------------------- /config/RULES.Host: -------------------------------------------------------------------------------- 1 | #RULES.Host 2 | 3 | include $(EPICS_BASE)/config/RULES.Host 4 | -------------------------------------------------------------------------------- /config/RULES.munch: -------------------------------------------------------------------------------- 1 | # The original 3.13.10 munching rule does not really work well 2 | 3 | # This is the munch.pl taken from EPICS base 3.14.8.2 4 | MUNCH = $(PERL) ../../config/munch.pl 5 | 6 | build:: $(LIBNAME).munch 7 | 8 | buildInstall:: $(INSTALL_BIN)/$(LIBNAME).munch 9 | 10 | %.munch: % 11 | @echo "Munching $<" 12 | $(RM) $*_ctct.o $*_ctdt.c 13 | $(NM) $< | $(MUNCH) > $*_ctdt.c 14 | $(GCC) -traditional $(CFLAGS) -fdollars-in-identifiers -c $(SOURCE_FLAG) $*_ctdt.c 15 | $(LINK.c) $@ $< $*_ctdt.o 16 | 17 | -------------------------------------------------------------------------------- /config/RULES_ARCHS: -------------------------------------------------------------------------------- 1 | #RULES_ARCHS 2 | include $(EPICS_BASE)/config/RULES_ARCHS 3 | -------------------------------------------------------------------------------- /config/RULES_DIRS: -------------------------------------------------------------------------------- 1 | #RULES_DIRS 2 | include $(EPICS_BASE)/config/RULES_DIRS 3 | -------------------------------------------------------------------------------- /config/makeConfigAppInclude.pl: -------------------------------------------------------------------------------- 1 | # $Id: makeConfigAppInclude.pl,v 1.1.1.1 2000/04/05 07:33:44 janousch Exp $ 2 | 3 | eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- 4 | if $running_under_some_shell; # makeConfigAppInclude.pl 5 | 6 | use Cwd; 7 | 8 | $arch = $ARGV[0]; 9 | $outfile = $ARGV[1]; 10 | $top = $ARGV[2]; 11 | 12 | unlink("${outfile}"); 13 | open(OUT,">${outfile}") or die "$! opening ${outfile}"; 14 | print OUT "#Do not modify this file.\n"; 15 | print OUT "#This file is created during the build.\n"; 16 | 17 | @files =(); 18 | push(@files,"$top/config/RELEASE"); 19 | push(@files,"$top/config/RELEASE.${arch}"); 20 | foreach $file (@files) { 21 | if (-r "$file") { 22 | open(IN, "$file") or die "Cannot open $file\n"; 23 | while ($line = ) { 24 | next if ( $line =~ /\s*#/ ); 25 | chomp($line); 26 | $_ = $line; 27 | #the following looks for 28 | # prefix = $(macro)post 29 | ($prefix,$macro,$post) = /(.*)\s*=\s*\$\((.*)\)(.*)/; 30 | if ($macro eq "") { # true if no macro is present 31 | # the following looks for 32 | # prefix = post 33 | ($prefix,$post) = /(.*)\s*=\s*(.*)/; 34 | } else { 35 | $base = $applications{$macro}; 36 | if ($base eq "") { 37 | #print "error: $macro was not previously defined\n"; 38 | } else { 39 | $post = $base . $post; 40 | } 41 | } 42 | $applications{$prefix} = $post; 43 | if ( -d "$post") { #check that directory exists 44 | print OUT "\n"; 45 | if ( -d "$post/bin/$arch") { #check that directory exists 46 | print OUT "${prefix}_BIN = $post/bin/${arch}\n"; 47 | } 48 | if ( -d "$post/lib/$arch") { #check that directory exists 49 | print OUT "${prefix}_LIB = $post/lib/${arch}\n"; 50 | } 51 | if ( -d "$post/include") { #check that directory exists 52 | print OUT "EPICS_INCLUDES += -I$post/include\n"; 53 | } 54 | if ( -d "$post/dbd") { #check that directory exists 55 | print OUT "EPICS_DBDFLAGS += -I $post/dbd\n"; 56 | } 57 | } 58 | } 59 | close IN; 60 | } 61 | } 62 | close OUT; 63 | -------------------------------------------------------------------------------- /config/munch.pl: -------------------------------------------------------------------------------- 1 | eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- 2 | if $running_under_some_shell; # makeConfigAppInclude.pl 3 | #************************************************************************* 4 | # Copyright (c) 2002 The University of Chicago, as Operator of Argonne 5 | # National Laboratory. 6 | # Copyright (c) 2002 The Regents of the University of California, as 7 | # Operator of Los Alamos National Laboratory. 8 | # EPICS BASE Versions 3.13.7 9 | # and higher are distributed subject to a Software License Agreement found 10 | # in file LICENSE that is included with this distribution. 11 | #************************************************************************* 12 | 13 | # Creates a ctdt.c file of c++ static constructors and destructors. 14 | # munch.pl,v 1.10 2002/12/16 20:25:53 jba Exp 15 | 16 | @ctorlist = (); 17 | @dtorlist = (); 18 | 19 | while ($line = ) 20 | { 21 | chomp; 22 | next if ($line =~ /__?GLOBAL_.F.+/); 23 | next if ($line =~ /__?GLOBAL_.I._GLOBAL_.D.+/); 24 | if ($line =~ /__?GLOBAL_.D.+/) { 25 | ($adr,$type,$name) = split ' ',$line,3; 26 | $name =~ s/^__/_/; 27 | @dtorlist = (@dtorlist,$name); 28 | }; 29 | if ($line =~ /__?GLOBAL_.I.+/) { 30 | ($adr,$type,$name) = split ' ',$line,3; 31 | $name =~ s/^__/_/; 32 | @ctorlist = (@ctorlist,$name); 33 | }; 34 | } 35 | 36 | foreach $ctor (@ctorlist) 37 | { 38 | if ( $ctor =~ /\./ ) { 39 | printf "void %s() __asm__ (\"_%s\");\n",convertName($ctor),$ctor; 40 | } else { 41 | printf "void %s();\n",$ctor; 42 | } 43 | } 44 | 45 | print "extern void (*_ctors[])();\n"; 46 | print "void (*_ctors[])() = {\n"; 47 | foreach $ctor (@ctorlist) 48 | { 49 | if ( $ctor =~ /\./ ) { 50 | printf " %s,\n",convertName($ctor); 51 | } else { 52 | printf " %s,\n",$ctor; 53 | } 54 | } 55 | print " 0};\n"; 56 | 57 | 58 | foreach $dtor (@dtorlist) 59 | { 60 | if ( $dtor =~ /\./ ) { 61 | printf "void %s() __asm__ (\"_%s\");\n",convertName($dtor),$dtor; 62 | } else { 63 | printf "void %s();\n",$dtor; 64 | } 65 | } 66 | 67 | print "extern void (*_ctors[])();\n"; 68 | print "void (*_dtors[])() = {\n"; 69 | foreach $dtor (@dtorlist) 70 | { 71 | if ( $dtor =~ /\./ ) { 72 | printf " %s,\n",convertName($dtor); 73 | } else { 74 | printf " %s,\n",$dtor; 75 | } 76 | } 77 | print " 0};\n"; 78 | 79 | sub convertName { 80 | my ($name) = @_; 81 | $name =~ s/\./\$/g; 82 | return $name; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /configure/CONFIG: -------------------------------------------------------------------------------- 1 | # CONFIG - Load build configuration data 2 | # 3 | # Do not make changes to this file! 4 | 5 | # Allow user to override where the build rules come from 6 | RULES = $(EPICS_BASE) 7 | 8 | # RELEASE files point to other application tops 9 | include $(TOP)/configure/RELEASE 10 | -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH) 11 | -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common 12 | ifdef T_A 13 | -include $(TOP)/configure/RELEASE.Common.$(T_A) 14 | -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) 15 | endif 16 | 17 | CONFIG = $(RULES)/configure 18 | include $(CONFIG)/CONFIG 19 | 20 | # Override the Base definition: 21 | INSTALL_LOCATION = $(TOP) 22 | 23 | # CONFIG_SITE files contain other build configuration settings 24 | include $(TOP)/configure/CONFIG_SITE 25 | -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common 26 | ifdef T_A 27 | -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) 28 | -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) 29 | endif 30 | -------------------------------------------------------------------------------- /configure/CONFIG_SITE: -------------------------------------------------------------------------------- 1 | # CONFIG_SITE 2 | 3 | -include $(SUPPORT)/configure/CONFIG_SITE 4 | 5 | # Make any application-specific changes to the EPICS build 6 | # configuration variables in this file. 7 | # 8 | # Host/target specific settings can be specified in files named 9 | # CONFIG_SITE.$(EPICS_HOST_ARCH).Common 10 | # CONFIG_SITE.Common.$(T_A) 11 | # CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) 12 | 13 | # CHECK_RELEASE controls the consistency checking of the support 14 | # applications pointed to by the RELEASE* files. 15 | # Normally CHECK_RELEASE should be set to YES. 16 | # Set CHECK_RELEASE to NO to disable checking completely. 17 | # Set CHECK_RELEASE to WARN to perform consistency checking but 18 | # continue building even if conflicts are found. 19 | CHECK_RELEASE = YES 20 | 21 | # Set this when you only want to compile this application 22 | # for a subset of the cross-compiled target architectures 23 | # that Base is built for. 24 | #CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 25 | 26 | # To install files into a location other than $(TOP) define 27 | # INSTALL_LOCATION here. 28 | #INSTALL_LOCATION= 29 | 30 | # Set this when the IOC and build host use different paths 31 | # to the install location. This may be needed to boot from 32 | # a Microsoft FTP server say, or on some NFS configurations. 33 | #IOCS_APPL_TOP = 34 | 35 | # These allow developers to override the CONFIG_SITE variable 36 | # settings without having to modify the configure/CONFIG_SITE 37 | # file itself. 38 | -include $(TOP)/../CONFIG_SITE.local 39 | -include $(TOP)/../configure/CONFIG_SITE.local 40 | -include $(TOP)/configure/CONFIG_SITE.local 41 | -------------------------------------------------------------------------------- /configure/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | 3 | TOP=.. 4 | 5 | include $(TOP)/configure/CONFIG 6 | 7 | TARGETS = $(CONFIG_TARGETS) 8 | CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) 9 | 10 | include $(TOP)/configure/RULES 11 | 12 | -------------------------------------------------------------------------------- /configure/RELEASE: -------------------------------------------------------------------------------- 1 | #RELEASE Location of external products 2 | # Run "gnumake clean uninstall install" in the application 3 | # top directory each time this file is changed. 4 | # 5 | # NOTE: The build does not check dependencies on files 6 | # external to this application. Thus you should run 7 | # "gnumake clean uninstall install" in the top directory 8 | # each time EPICS_BASE, SNCSEQ, or any other external 9 | # module defined in the RELEASE file is rebuilt. 10 | 11 | TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top 12 | 13 | # If you don't want to install into $(TOP) then 14 | # define INSTALL_LOCATION_APP here 15 | #INSTALL_LOCATION_APP= 16 | 17 | SUPPORT=$(TOP)/.. 18 | -include $(TOP)/../configure/SUPPORT.$(EPICS_HOST_ARCH) 19 | 20 | ASYN=$(SUPPORT)/asyn4-36 21 | CALC=$(SUPPORT)/calc-3-7 22 | PCRE=$(SUPPORT)/pcre-7-2 23 | 24 | # EPICS_BASE usually appears last so other apps can override stuff: 25 | EPICS_BASE=/usr/local/epics/base-7.0.3 26 | 27 | # These lines allow developers to override these RELEASE settings 28 | # without having to modify this file directly. 29 | -include $(TOP)/../RELEASE.local 30 | -include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local 31 | -include $(TOP)/configure/RELEASE.local 32 | -------------------------------------------------------------------------------- /configure/RULES: -------------------------------------------------------------------------------- 1 | #CONFIG 2 | ifneq ($(wildcard $(EPICS_BASE)/configure),) 3 | include $(EPICS_BASE)/configure/RULES 4 | else 5 | include $(EPICS_BASE)/config/RULES_ARCHS 6 | endif 7 | 8 | # Library should be rebuilt because LIBOBJS may have changed. 9 | $(LIBNAME): ../Makefile 10 | -------------------------------------------------------------------------------- /docs/PSI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulscherrerinstitute/StreamDevice/20dde4c1d8adec5ebb7c0fc54a06fd7511cfe07e/docs/PSI.png -------------------------------------------------------------------------------- /docs/ai.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: ai Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

ai Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Output: x=(VAL-AOFF)/ASLO
25 | Input: VAL=(x*ASLO+AOFF)*(1.0-SMOO)+VAL*SMOO
26 | In both cases, if ASLO==0.0, it is treated as 1.0. 27 | Default values are ASLO=1.0, AOFF=0.0, 28 | SMOO=0.0.
29 | If input is successful, UDF is cleared. 30 |
31 |
LONG format (e.g. %i):
32 |
33 | Output: x=RVAL
34 | Input: RVAL=x
35 | Note that the record calculates 36 | VAL=(((RVAL+ROFF)*ASLO+AOFF)*ESLO+EOFF)*(1.0-SMOO)+VAL*SMOO 37 | if LINR=="LINEAR". 38 | ESLO and EOFF might be set in the record 39 | definition. StreamDevice does not set it. For example, 40 | EOFF=-10 and ESLO=0.000305180437934 41 | (=20.0/0xFFFF) maps 0x0000 to -10.0, 0x7FFF to 0.0 and 0xFFFF to 10.0. 42 | Using unsigned formats with values ≥ 0x800000 gives different results 43 | on 64 bit machines. 44 |

45 | If LINR=="NO CONVERSION" (the default), VAL 46 | is directly converted from and to long without going through 47 | RVAL. This allows for more bits on 64 bit machines. 48 | To get the old behavior, use LINR=="LINEAR". 49 |

50 |
51 |
ENUM format (e.g. %{):
52 |
53 | Not allowed. 54 |
55 |
STRING format (e.g. %s):
56 |
57 | Not allowed. 58 |
59 |
60 | 61 |

Initialization

62 |

63 | During initialization, the @init handler is executed, if present. 64 | In contrast to normal operation, in DOUBLE input SMOO is ignored 65 | (treated as 0.0). 66 |

67 | 68 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/ao.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: ao Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

ao Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Output: x=(OVAL-AOFF)/ASLO
25 | Input: VAL=x*ASLO+AOFF
26 | In both cases, if ASLO==0.0, it is treated as 1.0. 27 | Default values are ASLO=1.0, AOFF=0.0.
28 | Note that OVAL is not necessarily equal to VAL 29 | if OROC!=0.0. 30 |
31 |
LONG format (e.g. %i):
32 |
33 | Output: x=RVAL
34 | Input: RBV=RVAL=x
35 | Note that the record calculates 36 | RVAL=(((OVAL-EOFF)/ESLO)-AOFF)/ASLO if 37 | LINR=="LINEAR". ESLO and EOFF 38 | might be set in the record definition. StreamDevice does not set it. 39 | For example, EOFF=-10 and ESLO=0.000305180437934 40 | (=20.0/0xFFFF) maps -10.0 to 0x0000, 0.0 to 0x7FFF and 10.0 to 0xFFFF. 41 | Using unsigned formats with values ≥ 0x800000 gives different results 42 | on 64 bit machines. 43 |

44 | If LINR=="NO CONVERSION" (the default), OVAL 45 | is directly converted to long without going through 46 | RVAL. This allows for more bits on 64 bit machines. 47 | To get the old behavior, use LINR=="LINEAR". 48 |

49 |
50 |
ENUM format (e.g. %{):
51 |
52 | Not allowed. 53 |
54 |
STRING format (e.g. %s):
55 |
56 | Not allowed. 57 |
58 |
59 | 60 |

Initialization

61 |

62 | During initialization, the @init handler is executed, if 63 | present. In contrast to normal operation, output in DOUBLE format uses 64 | VAL instead of OVAL. Note that the record 65 | initializes VAL from DOL if that is a constant. 66 |

67 | 68 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/bi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: bi Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

bi Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG format (e.g. %i):
27 |
28 | Output: x=RVAL
29 | Input: RVAL=x&MASK
30 | MASK can be set be set in the record definition. Stream 31 | Device does not set it. If MASK==0, it is ignored 32 | (i.e. RVAL=x). The record sets 33 | VAL=(RVAL!=0), i.e. 1 if RVAL!=0 34 | and 0 if RVAL==0. 35 |
36 |
ENUM format (e.g. %{):
37 |
38 | Output: x=VAL
39 | Input: VAL=(x!=0)
40 |
41 |
STRING format (e.g. %s):
42 |
43 | Output: Depending on VAL, ZNAM or 44 | ONAM is written, i.e. x=VAL?ONAM:ZNAM.
45 | Input: If input is equal to ZNAM or ONAM, 46 | VAL is set accordingly. Other input strings are not accepted. 47 |
48 |
49 | 50 |

Initialization

51 |

52 | During initialization, the @init handler is executed, if 53 | present. All format converters work like in normal operation. 54 |

55 | 56 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/bo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: bo Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

bo Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG format (e.g. %i):
27 |
28 | Output: x=RVAL
29 | Input: RBV=x&MASK
30 | MASK can be set be set in the record definition. Stream 31 | Device does not set it. If MASK==0, it is ignored 32 | (i.e. RBV=x). 33 |
34 |
ENUM format (e.g. %{):
35 |
36 | Output: x=VAL
37 | Input: VAL=(x!=0)
38 |
39 |
STRING format (e.g. %s):
40 |
41 | Output: Depending on VAL, ZNAM or 42 | ONAM is written, i.e. x=VAL?ONAM:ZNAM.
43 | Input: If input is equal to ZNAM or ONAM, 44 | VAL is set accordingly. Other input strings are not accepted. 45 |
46 |
47 | 48 |

Initialization

49 |

50 | During initialization, the @init handler is executed, if 51 | present. In contrast to normal operation, LONG input is put to 52 | RVAL as well as to RBV and converted by the record. 53 |

54 | 55 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /docs/calcout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: calcout Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

calcout Records

14 | 15 |

16 | Note: Device support for calcout records is only available for 17 | EPICS base R3.14.5 or higher. 18 |

19 | 20 |

Normal Operation

21 |

22 | Different record fields are used for output and input. The variable 23 | x stands for the written or read value. 24 |

25 |
26 |
DOUBLE format (e.g. %f):
27 |
28 | Output: x=OVAL
29 | Input: VAL=x
30 | Note that the record calculates OVAL from CALC 31 | or OCAL depending on DOPT. 32 |
33 |
LONG format (e.g. %i):
34 |
35 | Output: x=int(OVAL)
36 | Input: VAL=x
37 |
38 |
ENUM format (e.g. %{):
39 |
40 | Output: x=int(OVAL)
41 | Input: VAL=x
42 |
43 |
STRING format (e.g. %s):
44 |
45 | Not allowed. 46 |
47 |
48 |

49 | For calcout records, it is probably more useful to access fields 50 | A to L directly (e.g. "%(A)f"). 51 | However, even if OVAL is not used, it is calculated by the 52 | record. Thus, CALC must always contain a valid expression 53 | (e.g. "0"). 54 |

55 | 56 |

Initialization

57 |

58 | During initialization, the @init handler is executed, if 59 | present. All format converters work like in normal operation. 60 |

61 | 62 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /docs/ex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulscherrerinstitute/StreamDevice/20dde4c1d8adec5ebb7c0fc54a06fd7511cfe07e/docs/ex.png -------------------------------------------------------------------------------- /docs/exr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulscherrerinstitute/StreamDevice/20dde4c1d8adec5ebb7c0fc54a06fd7511cfe07e/docs/exr.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulscherrerinstitute/StreamDevice/20dde4c1d8adec5ebb7c0fc54a06fd7511cfe07e/docs/favicon.ico -------------------------------------------------------------------------------- /docs/int64in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: int64in Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

int64in Records

14 | 15 |

16 | Note: The int64in (integer 64 bit input) record is only available from EPICS base R3.16 on. 17 |

18 | 19 |

Normal Operation

20 |

21 | The variable x stands for the 22 | written or read value. 23 |

24 |
25 |
DOUBLE format (e.g. %f):
26 |
27 | Not allowed. 28 |
29 |
LONG format (e.g. %i):
30 |
31 | Output: x=VAL
32 | Input: VAL=x 33 |
34 |
ENUM format (e.g. %{):
35 |
36 | Output: x=VAL
37 | Input: VAL=x 38 |
39 |
STRING format (e.g. %s):
40 |
41 | Not allowed. 42 |
43 |
44 | 45 |

Initialization

46 |

47 | During initialization, the @init handler is executed, if 48 | present. All format converters work like in normal operation. 49 |

50 | 51 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/int64out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: int64out Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

int64out Records

14 | 15 |

16 | Note: The int64out (integer 64 bit output) record is only available from EPICS base R3.16 on. 17 |

18 | 19 |

Normal Operation

20 |

21 | The variable x stands for the 22 | written or read value. 23 |

24 |
25 |
DOUBLE format (e.g. %f):
26 |
27 | Not allowed. 28 |
29 |
LONG format (e.g. %i):
30 |
31 | Output: x=VAL
32 | Input: VAL=x 33 |
34 |
ENUM format (e.g. %{):
35 |
36 | Output: x=VAL
37 | Input: VAL=x 38 |
39 |
STRING format (e.g. %s):
40 |
41 | Not allowed. 42 |
43 |
44 | 45 |

Initialization

46 |

47 | During initialization, the @init handler is executed, if 48 | present. All format converters work like in normal operation. 49 |

50 | 51 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/longin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: longin Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

longin Records

14 | 15 |

Normal Operation

16 |

17 | The variable x stands for the 18 | written or read value. 19 |

20 |
21 |
DOUBLE format (e.g. %f):
22 |
23 | Not allowed. 24 |
25 |
LONG format (e.g. %i):
26 |
27 | Output: x=VAL
28 | Input: VAL=x 29 | Using unsigned formats with values ≥ 0x800000 gives different results 30 | on 64 bit machines. 31 |
32 |
ENUM format (e.g. %{):
33 |
34 | Output: x=VAL
35 | Input: VAL=x 36 |
37 |
STRING format (e.g. %s):
38 |
39 | Not allowed. 40 |
41 |
42 | 43 |

Initialization

44 |

45 | During initialization, the @init handler is executed, if 46 | present. All format converters work like in normal operation. 47 |

48 | 49 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /docs/longout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: longout Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

longout Records

14 | 15 |

Normal Operation

16 |

17 | The variable x stands for the 18 | written or read value. 19 |

20 |
21 |
DOUBLE format (e.g. %f):
22 |
23 | Not allowed. 24 |
25 |
LONG format (e.g. %i):
26 |
27 | Output: x=VAL
28 | Input: VAL=x 29 | Using unsigned formats with values ≥ 0x800000 gives different results 30 | on 64 bit machines. 31 |
32 |
ENUM format (e.g. %{):
33 |
34 | Output: x=VAL
35 | Input: VAL=x 36 |
37 |
STRING format (e.g. %s):
38 |
39 | Not allowed. 40 |
41 |
42 | 43 |

Initialization

44 |

45 | During initialization, the @init handler is executed, if 46 | present. All format converters work like in normal operation. 47 |

48 | 49 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /docs/lsi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: lsi Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

lsi Records

14 | 15 |

16 | Note: The lsi (long string in) record is only available from EPICS base R3.15 on. 17 |

18 | 19 |

Normal Operation

20 |

21 | The variable x stands for the 22 | written or read value. 23 |

24 |
25 |
DOUBLE format (e.g. %f):
26 |
27 | Not allowed. 28 |
29 |
LONG format (e.g. %i):
30 |
31 | Not allowed. 32 |
33 |
ENUM format (e.g. %{):
34 |
35 | Not allowed. 36 |
37 |
STRING format (e.g. %s):
38 |
39 | Output: x=VAL
40 | Input: VAL=x
41 | Also the LEN field is set to the length of the input 42 | including possible null bytes. 43 |
44 |
45 | 46 |

Initialization

47 |

48 | During initialization, the @init handler is executed, if 49 | present. All format converters work like in normal operation. 50 |

51 | 52 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/lso.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: lso Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

lso Records

14 | 15 |

16 | Note: The lso (long string out) record is only available from EPICS base R3.15 on. 17 |

18 | 19 |

Normal Operation

20 |

21 | The variable x stands for the 22 | written or read value. 23 |

24 |
25 |
DOUBLE format (e.g. %f):
26 |
27 | Not allowed. 28 |
29 |
LONG format (e.g. %i):
30 |
31 | Not allowed. 32 |
33 |
ENUM format (e.g. %{):
34 |
35 | Not allowed. 36 |
37 |
STRING format (e.g. %s):
38 |
39 | Output: x=VAL
40 | Input: VAL=x
41 | Also the LEN field is set to the length of the input 42 | including possible null bytes. 43 |
44 |
45 | 46 |

Initialization

47 |

48 | During initialization, the @init handler is executed, if 49 | present. All format converters work like in normal operation. 50 |

51 | 52 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/makepdf: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | wkhtmltopdf --enable-local-file-access -V >/dev/null 2>&1 3 | case $? in 4 | 127) 5 | echo "wkhtmltopdf not installed." >&2 6 | echo "See https://wkhtmltopdf.org" >&2 7 | exit 1 8 | ;; 9 | 0) 10 | # have (and need) --enable-local-file-access 11 | ENABLE_FILE_ACCESS=--enable-local-file-access 12 | ;; 13 | 1) 14 | # have no (and need no) --enable-local-file-access 15 | ;; 16 | *) 17 | # Some error but I don't know what it means. Try anyway. 18 | ;; 19 | esac 20 | 21 | PAGES=" 22 | index.html 23 | setup.html 24 | epics3_13.html 25 | protocol.html 26 | formats.html 27 | processing.html 28 | recordtypes.html 29 | aai.html 30 | aao.html 31 | ai.html 32 | ao.html 33 | bi.html 34 | bo.html 35 | calcout.html 36 | int64in.html 37 | int64out.html 38 | longin.html 39 | longout.html 40 | lsi.html 41 | lso.html 42 | mbbiDirect.html 43 | mbboDirect.html 44 | mbbi.html 45 | mbbo.html 46 | scalcout.html 47 | stringin.html 48 | stringout.html 49 | waveform.html 50 | tipsandtricks.html 51 | recordinterface.html 52 | businterface.html 53 | formatconverter.html 54 | osinterface.html 55 | " 56 | 57 | rm -f stream.pdf 58 | wkhtmltopdf --print-media-type --page-size Letter \ 59 | $ENABLE_FILE_ACCESS $PAGES stream.pdf 60 | -------------------------------------------------------------------------------- /docs/mbbi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: mbbi Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

mbbi Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG format (e.g. %i):
27 |
28 |
29 |
If any of ZRVL ... FFVL is set 30 | (is not 0):
31 |
32 | Output: x=RVAL&MASK
33 | Input: RVAL=x&MASK
34 | Note that the record shifts RVAL right by 35 | SHFT bits, compares the result with all of 36 | ZRVL ... FFVL, and sets VAL 37 | to the index of the first match. 38 | MASK is initialized to NOBT 1-bits shifted 39 | left by SHFT. If MASK==0 (because 40 | NOBT was not set) it is ignored, i.e. 41 | x=RVAL and RVAL=x. 42 |
43 |
If none of ZRVL ... FFVL is set 44 | (all are 0):
45 |
46 | Output: x=VAL
47 | Input: VAL=x
48 |
49 |
50 |
51 |
ENUM format (e.g. %{):
52 |
53 | Output: x=VAL
54 | Input: VAL=x
55 |
56 |
STRING format (e.g. %s):
57 |
58 | Output: Depending on VAL, one of ZRST 59 | or FFST is written. VAL must be in the range 60 | 0 ... 15.
61 | Input: If input is equal one of ZRST ... 62 | FFST, VAL is set accordingly. 63 | Other input strings are not accepted. 64 |
65 |
66 | 67 |

Initialization

68 |

69 | During initialization, the @init handler is executed, if 70 | present. All format converters work like in normal operation. 71 |

72 | 73 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/mbbiDirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: mbbiDirect Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

mbbiDirect Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG format (e.g. %i):
27 |
28 |
29 |
If MASK==0 (because NOBT is not set):
30 |
31 | Output: x=VAL
32 | Input: VAL=x
33 |
34 |
If MASK!=0:
35 |
36 | Output: x=RVAL&MASK
37 | Input: RVAL=x&MASK
38 |
39 |
40 | MASK is initialized to NOBT 1-bits shifted 41 | left by SHFT. 42 |
43 |
ENUM format (e.g. %{):
44 |
45 | Not allowed. 46 |
47 |
STRING format (e.g. %s):
48 |
49 | Not allowed. 50 |
51 |
52 | 53 |

Initialization

54 |

55 | During initialization, the @init handler is executed, if 56 | present. All format converters work like in normal operation. 57 |

58 | 59 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/mbbo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: mbbo Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

mbbo Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG or ENUM format (e.g. %i):
27 |
28 |
29 |
If any of ZRVL ... FFVL is set 30 | (is not 0):
31 |
32 | Output: x=RVAL&MASK
33 | Note that the record calculates RVAL by choosing one of 34 | ZRVL ... FFVL depending on VAL 35 | and by shifting it left by SHFT bits.
36 | Input: RBV=RVAL=x&MASK
37 | MASK is initialized to NOBT 1-bits shifted 38 | left by SHFT. If MASK==0 (because 39 | NOBT was not set) it is ignored, i.e. 40 | x=RVAL and RBV=RVAL=x. 41 |
42 |
If none of ZRVL ... FFVL is set 43 | (all are 0):
44 |
45 | Output: x=(VAL<<SHFT)&MASK
46 | Input: VAL=(RBV=(x&MASK))>>SHFT
47 |
48 |
49 |
50 |
STRING format (e.g. %s):
51 |
52 | Output: Depending on VAL, one of ZRST 53 | ... FFST is written. VAL must be in the 54 | range 0 ... 15.
55 | Input: If input is equal one of ZRST ... 56 | FFST, VAL is set accordingly. 57 | Other input strings are not accepted. 58 |
59 |
60 | 61 |

Initialization

62 |

63 | During initialization, the @init handler is executed, if 64 | present. 65 |

66 | 67 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /docs/mbboDirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: mbboDirect Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

mbboDirect Records

14 | 15 |

Normal Operation

16 |

17 | Depending on the format type, different record fields are used 18 | for output and input. The variable x stands for the 19 | written or read value. 20 |

21 |
22 |
DOUBLE format (e.g. %f):
23 |
24 | Not allowed. 25 |
26 |
LONG or ENUM format (e.g. %i):
27 |
28 |
29 |
If MASK==0 (because NOBT is not set):
30 |
31 | Output: x=RVAL
32 | Input: RAL=x, VAL=RVAL>>SHFT
33 |
34 |
If MASK!=0:
35 |
36 | Output: x=RVAL&MASK
37 | Input: RBV=RVAL=x&MASK, VAL=RVAL>>SHFT
38 |
39 |
40 | MASK is initialized to NOBT 1-bits shifted 41 | left by SHFT (((2^NOBT)-1)<<SHFT). 42 | The record calculates RVAL=VAL<<SHFT. 43 |
44 |
STRING format (e.g. %s):
45 |
46 | Not allowed. 47 |
48 |
49 | 50 |

Initialization

51 |

52 | During initialization, the @init handler is executed, if 53 | present. 54 |

55 | 56 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/osinterface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: Operating System API 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Operating System API

14 | 15 |

Sorry, this documentation is still missing.

16 | 17 | 18 |
19 | Dirk Zimoch, 2018 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/recordtypes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: Record Types 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Record Types

14 | 15 |

Supported Record Types

16 |

17 | StreamDevice comes with support for all standard record types 18 | in EPICS base which can have device support. 19 |

20 |

21 | There is a separate page for each supported record type: 22 |

23 |

24 | aai 25 | aao 26 | ai 27 | ao 28 | bi 29 | bo 30 | calcout 31 | int64in 32 | int64out 33 | longin 34 | longout 35 | lsi 36 | lso 37 | mbbiDirect 38 | mbboDirect 39 | mbbi 40 | mbbo 41 | scalcout 42 | stringin 43 | stringout 44 | waveform 45 |

46 | 47 |

48 | Each page describes which record fields are used in input and output 49 | for different format data types 50 | during normal record processing 51 | and initialization. 52 |

53 |

54 | It is also possible to 55 | write support for other recordtypes. 56 |

57 | 58 |
59 | Dirk Zimoch, 2018 60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/scalcout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: scalcout Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

scalcout Records

14 | 15 |

16 | Note: The scalcout record is part of the calc module of 17 | the synApps package. 20 | Device support for scalcout records is only available for calc 21 | module release 2-4 or higher. 22 | You also need the synApps modules genSub and sscan to 23 | build calc. 24 |

25 |

26 | Up to release 2-6 (synApps release 5.1), the scalcout record needs a fix. 27 | In sCalcout.c at the end of init_record add 28 | before the final return(0): 29 |

30 |
 31 |         if(pscalcoutDSET->init_record ) {
 32 |             return (*pscalcoutDSET->init_record)(pcalc);
 33 |         }
 34 | 
35 | 36 |

Normal Operation

37 |

38 | Different record fields are used for output and input. The variable 39 | x stands for the written or read value. 40 |

41 |
42 |
DOUBLE format (e.g. %f):
43 |
44 | Output: x=OVAL
45 | Input: VAL=x
46 | Note that the record calculates OVAL from CALC 47 | or OCAL depending on DOPT. 48 |
49 |
LONG format (e.g. %i):
50 |
51 | Output: x=int(OVAL)
52 | Input: VAL=x
53 |
54 |
ENUM format (e.g. %{):
55 |
56 | Output: x=int(OVAL)
57 | Input: VAL=x
58 |
59 |
STRING format (e.g. %s):
60 |
61 | Output: x=OSV
62 | Input: SVAL=x
63 |
64 |
65 |

66 | For scalcout records, it is probably more useful to access fields 67 | A to L and AA to LL 68 | directly (e.g. "%(A)f" or "%(BB)s"). 69 | However, even if OVAL is not used, it is calculated by the 70 | record. Thus, CALC must always contain a valid expression 71 | (e.g. "0"). 72 |

73 | 74 |

Initialization

75 |

76 | During initialization, the @init handler is executed, if 77 | present. All format converters work like in normal operation. 78 |

79 | 80 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/stream.css: -------------------------------------------------------------------------------- 1 | a:link { color: #0000D0; } 2 | a:visited { color: #0000D0; } 3 | a:hover { color: #FF0000; } 4 | 5 | body { 6 | margin-right: 1em; 7 | margin-left: 15em; 8 | margin-top: 75px; 9 | padding-top: 1px; 10 | font-family: Helvetica, Arial, sans-serif; 11 | font-size: 100%; 12 | background-color: #ffffff; 13 | } 14 | 15 | a[name] { 16 | position: relative; 17 | top: -11ex; 18 | } 19 | 20 | pre, tt, kbd, code { 21 | font-size: 95%; 22 | font-family: Mono, "Lucida Console", Courier, monospace; 23 | } 24 | 25 | pre { 26 | background-color: #f4f4f4; 27 | padding: 1ex; 28 | border: 1px solid #000000; 29 | white-space: pre; 30 | margin: 2ex; 31 | page-break-inside: avoid; 32 | font-size: 85%; 33 | white-space: pre-wrap; 34 | } 35 | 36 | kbd { 37 | font-weight: bold; 38 | } 39 | 40 | code { 41 | color: #008000; 42 | } 43 | 44 | dt { 45 | margin-top: 0.5ex; 46 | } 47 | 48 | h1 { 49 | font-size: 250%; 50 | margin-top: 0; 51 | font-style: italic; 52 | font-weight: bold; 53 | font-family: "Times New Roman", Times, serif; 54 | text-align: center; 55 | position: fixed; 56 | top: 0; 57 | left: 0; 58 | width: 100%; 59 | line-height: 190%; 60 | background-color: white; 61 | border-width: 0; 62 | border-bottom: 3px solid #1b4486; 63 | white-space: nowrap; 64 | background-image: url(PSI.png); 65 | background-repeat: no-repeat; 66 | background-position: 10px 5px; 67 | text-shadow: .1em .1em .1em lightgray; 68 | box-shadow: 0 .3em .1em -.2em darkgray; 69 | } 70 | 71 | h2 { 72 | font-size: 140%; 73 | margin-bottom: 0.5ex; 74 | } 75 | 76 | h3 { 77 | font-size: 120%; 78 | margin-bottom: 0.25ex; 79 | } 80 | 81 | h4 { 82 | font-size: 100%; 83 | margin-bottom: 0.25ex; 84 | } 85 | 86 | h1, h2, h3, h4 { 87 | page-break-after: avoid; 88 | } 89 | 90 | p { 91 | margin-top: 0.75ex; 92 | margin-bottom: 0.75ex; 93 | } 94 | 95 | body h1 + p { 96 | margin-top: 1.5ex; 97 | margin-bottom: 0.75ex; 98 | } 99 | 100 | footer { 101 | font-size: 75%; 102 | margin-top: 1em; 103 | border-top: 1px solid darkgray; 104 | padding-top: 1em; 105 | } 106 | 107 | footer a:only-of-type { 108 | display: block; 109 | position: absolute; 110 | right: 1em; 111 | } 112 | 113 | small { 114 | font-size: 75%; 115 | } 116 | 117 | .indent { 118 | text-indent: -4ex; 119 | margin-left: 4ex; 120 | margin-top: 0.5ex; 121 | text-align: left; 122 | } 123 | 124 | .box { 125 | margin-left: 1ex; 126 | margin-right: 1ex; 127 | margin-top: 0.5ex; 128 | padding: 0 1ex; 129 | border: thin solid black; 130 | text-align: left; 131 | background-color: #f0f0f0; 132 | page-break-inside: avoid; 133 | } 134 | 135 | #navleft { 136 | position: fixed; 137 | left: 0; 138 | top: 0; 139 | padding-top: 70px; 140 | width: 14em; 141 | height: 100%; 142 | border-style: solid; 143 | border-color: black; 144 | border-width: 0 1px 0 0; 145 | background-color: #e3eaf6; 146 | overflow: hidden; 147 | z-index: 0; 148 | } 149 | 150 | .new { 151 | background-color: #ffc; 152 | } 153 | 154 | a[target=ex]:after { 155 | content: " " url(ex.png); 156 | } 157 | 158 | a[target=ex]:hover:after { 159 | content: " " url(exr.png); 160 | } 161 | 162 | @media print { 163 | a:link { text-decoration: none; } 164 | a[target=ex]:after { content:" [" attr(href) "]"; font-size: 75%; } 165 | body { margin: 0 4em; } 166 | h1 { position: relative; background-position: 0 0; } 167 | #navleft { display: none; } 168 | footer { display: none; } 169 | } 170 | -------------------------------------------------------------------------------- /docs/stringin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: stringin Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

stringin Records

14 | 15 |

Normal Operation

16 |

17 | The variable x stands for the 18 | written or read value. 19 |

20 |
21 |
DOUBLE format (e.g. %f):
22 |
23 | Not allowed. 24 |
25 |
LONG format (e.g. %i):
26 |
27 | Not allowed. 28 |
29 |
ENUM format (e.g. %{):
30 |
31 | Not allowed. 32 |
33 |
STRING format (e.g. %s):
34 |
35 | Output: x=VAL
36 | Input: VAL=x 37 |
38 |
39 | 40 |

Initialization

41 |

42 | During initialization, the @init handler is executed, if 43 | present. All format converters work like in normal operation. 44 |

45 | 46 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/stringout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | StreamDevice: stringout Records 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

stringout Records

14 | 15 |

Normal Operation

16 |

17 | The variable x stands for the 18 | written or read value. 19 |

20 |
21 |
DOUBLE format (e.g. %f):
22 |
23 | Not allowed. 24 |
25 |
LONG format (e.g. %i):
26 |
27 | Not allowed. 28 |
29 |
ENUM format (e.g. %{):
30 |
31 | Not allowed. 32 |
33 |
STRING format (e.g. %s):
34 |
35 | Output: x=VAL
36 | Input: VAL=x 37 |
38 |
39 | 40 |

Initialization

41 |

42 | During initialization, the @init handler is executed, if 43 | present. All format converters work like in normal operation. 44 |

45 | 46 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/DummyInterface.cc: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is a debug and example bus interface for StreamDevice. 3 | * It does not provide any I/O functionality. 4 | * Please see ../docs/ for detailed documentation. 5 | * 6 | * (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | * 8 | * This file is part of StreamDevice. 9 | * 10 | * StreamDevice is free software: You can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * StreamDevice is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | *************************************************************************/ 23 | 24 | #include "StreamBusInterface.h" 25 | #include "StreamError.h" 26 | #include "StreamBuffer.h" 27 | 28 | class DummyInterface : StreamBusInterface 29 | { 30 | DummyInterface(Client* client); 31 | 32 | // StreamBusInterface methods 33 | bool lockRequest(unsigned long lockTimeout_ms); 34 | bool unlock(); 35 | 36 | protected: 37 | ~DummyInterface(); 38 | 39 | public: 40 | // static creator method 41 | static StreamBusInterface* getBusInterface(Client* client, 42 | const char* busname, int addr, const char* param); 43 | }; 44 | 45 | RegisterStreamBusInterface(DummyInterface); 46 | 47 | DummyInterface:: 48 | DummyInterface(Client* client) : StreamBusInterface(client) 49 | { 50 | // Nothing to do 51 | } 52 | 53 | DummyInterface:: 54 | ~DummyInterface() 55 | { 56 | // Nothing to do 57 | } 58 | 59 | StreamBusInterface* DummyInterface:: 60 | getBusInterface(Client* client, 61 | const char* busname, int addr, const char*) 62 | { 63 | if (strcmp(busname, "dummy") == 0) 64 | { 65 | DummyInterface* interface = new DummyInterface(client); 66 | return interface; 67 | } 68 | return NULL; 69 | } 70 | 71 | bool DummyInterface:: 72 | lockRequest(unsigned long lockTimeout_ms) 73 | { 74 | return false; 75 | } 76 | 77 | bool DummyInterface:: 78 | unlock() 79 | { 80 | return false; 81 | } 82 | -------------------------------------------------------------------------------- /src/Makefile.Host: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an EPICS 3.13 Makefile for StreamDevice. 3 | # Normally it should not be necessary to modify this file. 4 | # All configuration can be done in CONFIG_STREAM 5 | # 6 | # (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | # 8 | # This file is part of StreamDevice. 9 | # 10 | # StreamDevice is free software: You can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # StreamDevice is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | #########################################################################/ 23 | 24 | TOP = ../.. 25 | ifneq ($(wildcard ../../../config),) 26 | TOP = ../../.. 27 | endif 28 | 29 | include $(TOP)/config/CONFIG_APP 30 | include ../CONFIG_STREAM 31 | 32 | include $(EPICS_BASE)/config/RULES.Host 33 | -------------------------------------------------------------------------------- /src/Makefile.Vx: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an EPICS 3.13 Makefile for StreamDevice. 3 | # Normally it should not be necessary to modify this file. 4 | # All configuration can be done in CONFIG_STREAM 5 | # 6 | # (C) 2007,2018 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | # 8 | # This file is part of StreamDevice. 9 | # 10 | # StreamDevice is free software: You can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # StreamDevice is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | #########################################################################/ 23 | 24 | TOP = ../.. 25 | ifneq ($(wildcard ../../../config),) 26 | TOP = ../../.. 27 | endif 28 | 29 | include $(TOP)/config/CONFIG_APP 30 | include ../CONFIG_STREAM 31 | 32 | CXXCMPLR=NORMAL 33 | G++_NORMAL = $(G++) 34 | 35 | LIBNAME = streamLib 36 | 37 | SRCS.cc += $(BUSSES:%=../%Interface.cc) 38 | SRCS.cc += $(FORMATS:%=../%Converter.cc) 39 | SRCS.cc += $(filter %.cc,$(STREAM_SRCS:%=%../%)) 40 | SRCS.c += $(RECORDTYPES:%=../dev%Stream.c) 41 | SRCS.c += $(filter %.c,$(STREAM_SRCS:%=%../%)) 42 | 43 | LIBOBJS = $(patsubst ../%,%.o,$(basename $(SRCS.cc) $(SRCS.c))) 44 | 45 | DBDNAME = stream.dbd 46 | 47 | INC += devStream.h 48 | INC += StreamFormat.h 49 | INC += StreamFormatConverter.h 50 | INC += StreamBuffer.h 51 | INC += StreamError.h 52 | INC += StreamVersion.h 53 | 54 | include $(EPICS_BASE)/config/RULES.Vx 55 | include ../../config/RULES.munch 56 | 57 | DEPENDS: depends 58 | -include DEPENDS 59 | 60 | CPPFLAGS += -DSTREAM_INTERNAL 61 | 62 | # Update version string whenever something changes 63 | $(LIBNAME): StreamVersion.o 64 | 65 | StreamVersion.o: StreamVersion.h $(filter-out StreamVersion.o,$(LIBOBJS)) ../CONFIG_STREAM 66 | StreamVersion.h: $(SRCS.cc) $(SRCS.c) $(add-prefix ../,$(filter-out StreamVersion.h, $(INC))) 67 | @echo Creating $@ from git tag 68 | $(PERL) ../makeStreamVersion.pl > $@ 69 | 70 | StreamCore.o: streamReferences 71 | 72 | streamReferences: 73 | touch $@ 74 | 75 | # create stream.dbd from all RECORDTYPES 76 | stream.dbd: ../CONFIG_STREAM 77 | $(PERL) ../makedbd.pl -3.13 $(RECORDTYPES) > $@ 78 | 79 | -------------------------------------------------------------------------------- /src/StreamError.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is error and debug message handling of StreamDevice. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #ifndef StreamError_h 24 | #define StreamError_h 25 | 26 | #include 27 | #include 28 | 29 | #ifndef __GNUC__ 30 | #define __attribute__(x) 31 | #endif 32 | 33 | extern int streamDebug; 34 | extern int streamError; 35 | extern int streamDebugColored; 36 | extern int streamMsgTimeStamped; 37 | extern void (*StreamPrintTimestampFunction)(char* buffer, size_t size); 38 | extern const char* (*StreamGetThreadNameFunction)(void); 39 | 40 | void StreamError(int line, const char* file, const char* fmt, ...) 41 | __attribute__((__format__(__printf__,3,4))); 42 | 43 | void StreamVError(int line, const char* file, const char* fmt, va_list args) 44 | __attribute__((__format__(__printf__,3,0))); 45 | 46 | void StreamError(const char* fmt, ...) 47 | __attribute__((__format__(__printf__,1,2))); 48 | 49 | inline void StreamVError(const char* fmt, va_list args) 50 | { 51 | StreamVError(0, NULL, fmt, args); 52 | } 53 | 54 | class StreamDebugClass 55 | { 56 | const char* file; 57 | int line; 58 | public: 59 | StreamDebugClass(const char* file = NULL, int line = 0) : 60 | file(file), line(line) {} 61 | int print(const char* fmt, ...) 62 | __attribute__((__format__(__printf__,2,3))); 63 | }; 64 | 65 | #define error StreamError 66 | #define debug (!streamDebug)?0:StreamDebugClass(__FILE__,__LINE__).print 67 | #define debug2 (streamDebug<2)?0:StreamDebugClass(__FILE__,__LINE__).print 68 | 69 | /* 70 | * ANSI escape sequences for terminal output 71 | */ 72 | enum AnsiMode { ANSI_REVERSE_VIDEO, ANSI_NOT_REVERSE_VIDEO, ANSI_BG_WHITE, 73 | ANSI_RESET, ANSI_RED_BOLD }; 74 | extern const char* ansiEscape(AnsiMode mode); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/StreamFormat.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This header defines the format stucture used to interface 3 | * format converters and EPICS records to StreamDevice 4 | * Please see ../docs/ for detailed documentation. 5 | * 6 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 7 | * 8 | * This file is part of StreamDevice. 9 | * 10 | * StreamDevice is free software: You can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * StreamDevice is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 22 | *************************************************************************/ 23 | 24 | #ifndef StreamFormat_h 25 | #define StreamFormat_h 26 | 27 | typedef enum { 28 | left_flag = 0x01, 29 | sign_flag = 0x02, 30 | space_flag = 0x04, 31 | alt_flag = 0x08, 32 | zero_flag = 0x10, 33 | skip_flag = 0x20, 34 | default_flag = 0x40, 35 | compare_flag = 0x80, 36 | fix_width_flag = 0x100 37 | } StreamFormatFlag; 38 | 39 | typedef enum { 40 | unsigned_format = 1, 41 | signed_format, 42 | enum_format, 43 | double_format, 44 | string_format, 45 | pseudo_format, 46 | needs_original_format 47 | } StreamFormatType; 48 | 49 | extern const char* StreamFormatTypeStr[]; 50 | 51 | typedef struct StreamFormat 52 | { 53 | char conv; 54 | StreamFormatType type; 55 | unsigned short flags; 56 | long prec; 57 | unsigned long width; 58 | unsigned long infolen; 59 | const char* info; 60 | } StreamFormat; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/StreamVersion.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This file provides a version string for StreamDevice. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "StreamVersion.h" 24 | 25 | #define STR2(x) #x 26 | #define STR(x) STR2(x) 27 | const char StreamVersion [] = 28 | "StreamDevice" 29 | #ifdef STREAM_MAJOR 30 | " " STR(STREAM_MAJOR) 31 | "." STR(STREAM_MINOR) 32 | "." STR(STREAM_PATCHLEVEL) 33 | STREAM_DEV 34 | #endif 35 | #ifdef STREAM_COMMIT_DATE 36 | " " STREAM_COMMIT_DATE 37 | #endif 38 | #ifdef STREAM_COMMIT_HASH 39 | "\n commit: " STREAM_COMMIT_HASH 40 | #endif 41 | ; 42 | -------------------------------------------------------------------------------- /src/devStream.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the header for StreamDevice interfaces to EPICS. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #ifndef devStream_h 24 | #define devStream_h 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #ifndef STREAM_INTERNAL 32 | #include "StreamVersion.h" 33 | #endif 34 | 35 | #ifndef OK 36 | #define OK 0 37 | #endif 38 | 39 | #ifndef ERROR 40 | #define ERROR -1 41 | #endif 42 | 43 | #define DO_NOT_CONVERT 2 44 | #define INIT_RUN (!interruptAccept) 45 | 46 | #ifdef epicsExportSharedSymbols 47 | # define devStream_epicsExportSharedSymbols 48 | # undef epicsExportSharedSymbols 49 | # include "shareLib.h" 50 | #endif 51 | 52 | #include "epicsVersion.h" 53 | #ifdef BASE_VERSION 54 | #define EPICS_3_13 55 | /* EPICS 3.13 include files are not C++ ready. */ 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | #endif 60 | 61 | #include "dbCommon.h" 62 | #include "dbScan.h" 63 | #include "devSup.h" 64 | #include "dbAccess.h" 65 | #include "errlog.h" 66 | #include "alarm.h" 67 | #include "recGbl.h" 68 | #include "dbEvent.h" 69 | #include "epicsMath.h" 70 | 71 | #ifdef EPICS_3_13 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | #else 76 | #include "epicsStdioRedirect.h" 77 | #endif 78 | 79 | #ifdef devStream_epicsExportSharedSymbols 80 | # undef devStream_epicsExportSharedSymbols 81 | # define epicsExportSharedSymbols 82 | # include "shareLib.h" 83 | #endif 84 | 85 | #ifdef _WIN32 86 | typedef ptrdiff_t ssize_t; 87 | #endif 88 | 89 | typedef const struct format_s { 90 | unsigned char type; 91 | const struct StreamFormat* priv; 92 | } format_t; 93 | 94 | extern FILE* StreamDebugFile; 95 | 96 | typedef long (*streamIoFunction) (dbCommon*, format_t*); 97 | 98 | #ifdef __cplusplus 99 | extern "C" { 100 | #endif 101 | 102 | extern const char StreamVersion []; 103 | 104 | long streamInit(int after); 105 | long streamInitRecord(dbCommon *record, 106 | const struct link *ioLink, 107 | streamIoFunction readData, streamIoFunction writeData); 108 | long streamReport(int interest); 109 | long streamReadWrite(dbCommon *record); 110 | long streamGetIointInfo(int cmd, 111 | dbCommon *record, IOSCANPVT *ppvt); 112 | long streamPrintf(dbCommon *record, format_t *format, ...); 113 | ssize_t streamScanfN(dbCommon *record, format_t *format, 114 | void*, size_t maxStringSize); 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | /* backward compatibility stuff */ 121 | #define streamScanf(record, format, value) \ 122 | streamScanfN(record, format, value, MAX_STRING_SIZE) 123 | #define streamRead streamReadWrite 124 | #define streamWrite streamReadWrite 125 | #define streamReport NULL 126 | 127 | #ifdef EPICS_3_13 128 | #define epicsExportAddress(a,b) extern int dummy 129 | #else 130 | #include "epicsExport.h" 131 | #endif 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/devbiStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS bi records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "biRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | biRecord *bi = (biRecord *)record; 29 | unsigned long val; 30 | 31 | switch (format->type) 32 | { 33 | case DBF_ULONG: 34 | case DBF_LONG: 35 | { 36 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 37 | if (bi->mask) val &= bi->mask; 38 | bi->rval = val; 39 | return OK; 40 | } 41 | case DBF_ENUM: 42 | { 43 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 44 | bi->val = (val != 0); 45 | return DO_NOT_CONVERT; 46 | } 47 | case DBF_STRING: 48 | { 49 | char buffer[sizeof(bi->znam)]; 50 | if (streamScanfN(record, format, buffer, sizeof(buffer)) == ERROR) 51 | return ERROR; 52 | if (strcmp (bi->znam, buffer) == 0) 53 | { 54 | bi->val = 0; 55 | return DO_NOT_CONVERT; 56 | } 57 | if (strcmp (bi->onam, buffer) == 0) 58 | { 59 | bi->val = 1; 60 | return DO_NOT_CONVERT; 61 | } 62 | } 63 | } 64 | return ERROR; 65 | } 66 | 67 | static long writeData(dbCommon *record, format_t *format) 68 | { 69 | biRecord *bi = (biRecord *)record; 70 | 71 | switch (format->type) 72 | { 73 | case DBF_ULONG: 74 | case DBF_LONG: 75 | { 76 | return streamPrintf(record, format, bi->rval); 77 | } 78 | case DBF_ENUM: 79 | { 80 | return streamPrintf(record, format, (long)bi->val); 81 | } 82 | case DBF_STRING: 83 | { 84 | return streamPrintf(record, format, 85 | bi->val ? bi->onam : bi->znam); 86 | } 87 | } 88 | return ERROR; 89 | } 90 | 91 | static long initRecord(dbCommon *record) 92 | { 93 | biRecord *bi = (biRecord *)record; 94 | 95 | return streamInitRecord(record, &bi->inp, readData, writeData) == ERROR ? 96 | ERROR : OK; 97 | } 98 | 99 | struct { 100 | long number; 101 | DEVSUPFUN report; 102 | DEVSUPFUN init; 103 | DEVSUPFUN init_record; 104 | DEVSUPFUN get_ioint_info; 105 | DEVSUPFUN read; 106 | } devbiStream = { 107 | 5, 108 | streamReport, 109 | streamInit, 110 | initRecord, 111 | streamGetIointInfo, 112 | streamRead 113 | }; 114 | 115 | epicsExportAddress(dset,devbiStream); 116 | -------------------------------------------------------------------------------- /src/devcalcoutStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS calcout records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "calcoutRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | calcoutRecord *co = (calcoutRecord *)record; 29 | unsigned short monitor_mask; 30 | 31 | switch (format->type) 32 | { 33 | case DBF_DOUBLE: 34 | { 35 | if (streamScanf(record, format, &co->val) == ERROR) return ERROR; 36 | break; 37 | } 38 | case DBF_ULONG: 39 | case DBF_LONG: 40 | case DBF_ENUM: 41 | { 42 | long lval; 43 | 44 | if (streamScanf(record, format, &lval) == ERROR) return ERROR; 45 | if (format->type == DBF_LONG) 46 | co->val = lval; 47 | else 48 | co->val = (unsigned long)lval; 49 | break; 50 | } 51 | default: 52 | return ERROR; 53 | } 54 | if (record->pact) return OK; 55 | /* In @init handler, no processing, enforce monitor updates. */ 56 | monitor_mask = recGblResetAlarms(record); 57 | 58 | if (!(fabs(co->mlst - co->val) <= co->mdel)) { 59 | monitor_mask |= DBE_VALUE; 60 | co->mlst = co->val; 61 | } 62 | if (!(fabs(co->mlst - co->val) <= co->adel)) { 63 | monitor_mask |= DBE_LOG; 64 | co->alst = co->val; 65 | } 66 | if (monitor_mask) { 67 | db_post_events(record, &co->val, monitor_mask); 68 | } 69 | 70 | return OK; 71 | } 72 | 73 | static long writeData(dbCommon *record, format_t *format) 74 | { 75 | calcoutRecord *co = (calcoutRecord *)record; 76 | 77 | switch (format->type) 78 | { 79 | case DBF_DOUBLE: 80 | { 81 | return streamPrintf(record, format, co->oval); 82 | } 83 | case DBF_ULONG: 84 | { 85 | return streamPrintf(record, format, (unsigned long)co->oval); 86 | } 87 | case DBF_LONG: 88 | case DBF_ENUM: 89 | { 90 | return streamPrintf(record, format, (long)co->oval); 91 | } 92 | } 93 | return ERROR; 94 | } 95 | 96 | static long initRecord(dbCommon *record) 97 | { 98 | calcoutRecord *co = (calcoutRecord *)record; 99 | 100 | return streamInitRecord(record, &co->out, readData, writeData) == ERROR ? 101 | ERROR : OK; 102 | } 103 | 104 | struct { 105 | long number; 106 | DEVSUPFUN report; 107 | DEVSUPFUN init; 108 | DEVSUPFUN init_record; 109 | DEVSUPFUN get_ioint_info; 110 | DEVSUPFUN write; 111 | DEVSUPFUN special_linconv; 112 | } devcalcoutStream = { 113 | 6, 114 | streamReport, 115 | streamInit, 116 | initRecord, 117 | streamGetIointInfo, 118 | streamWrite, 119 | NULL 120 | }; 121 | 122 | epicsExportAddress(dset,devcalcoutStream); 123 | -------------------------------------------------------------------------------- /src/devint64inStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS int64in records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "int64inRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | int64inRecord *i64i = (int64inRecord *)record; 29 | 30 | switch (format->type) 31 | { 32 | case DBF_ULONG: 33 | case DBF_LONG: 34 | case DBF_ENUM: 35 | { 36 | long val; 37 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 38 | if (format->type == DBF_LONG) 39 | i64i->val = val; 40 | else 41 | i64i->val = (unsigned long)val; 42 | return OK; 43 | } 44 | } 45 | return ERROR; 46 | } 47 | 48 | static long writeData(dbCommon *record, format_t *format) 49 | { 50 | int64inRecord *i64i = (int64inRecord *)record; 51 | 52 | switch (format->type) 53 | { 54 | case DBF_ULONG: 55 | case DBF_ENUM: 56 | case DBF_LONG: 57 | return streamPrintf(record, format, (long)i64i->val); 58 | } 59 | return ERROR; 60 | } 61 | 62 | static long initRecord(dbCommon *record) 63 | { 64 | int64inRecord *i64i = (int64inRecord *)record; 65 | 66 | return streamInitRecord(record, &i64i->inp, readData, writeData) == ERROR ? 67 | ERROR : OK; 68 | } 69 | 70 | struct { 71 | long number; 72 | DEVSUPFUN report; 73 | DEVSUPFUN init; 74 | DEVSUPFUN init_record; 75 | DEVSUPFUN get_ioint_info; 76 | DEVSUPFUN read; 77 | } devint64inStream = { 78 | 5, 79 | streamReport, 80 | streamInit, 81 | initRecord, 82 | streamGetIointInfo, 83 | streamRead 84 | }; 85 | 86 | epicsExportAddress(dset,devint64inStream); 87 | -------------------------------------------------------------------------------- /src/devint64outStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS int64out records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "int64outRecord.h" 24 | #include "devStream.h" 25 | 26 | /* DELTA calculates the absolute difference between its arguments */ 27 | #define DELTA(last, val) ((last) > (val) ? (last) - (val) : (val) - (last)) 28 | 29 | static long readData(dbCommon *record, format_t *format) 30 | { 31 | int64outRecord *i64o = (int64outRecord *)record; 32 | unsigned short monitor_mask; 33 | 34 | switch (format->type) 35 | { 36 | case DBF_ULONG: 37 | case DBF_LONG: 38 | case DBF_ENUM: 39 | { 40 | long val; 41 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 42 | if (format->type == DBF_LONG) 43 | i64o->val = val; 44 | else 45 | i64o->val = (unsigned long)val; 46 | break; 47 | } 48 | default: 49 | return ERROR; 50 | } 51 | if (record->pact) return OK; 52 | /* In @init handler, no processing, enforce monitor updates. */ 53 | monitor_mask = recGblResetAlarms(record); 54 | if (DELTA(i64o->mlst, i64o->val) > i64o->mdel) 55 | { 56 | monitor_mask |= DBE_VALUE; 57 | i64o->mlst = i64o->val; 58 | } 59 | if (DELTA(i64o->alst, i64o->val) > i64o->adel) 60 | { 61 | monitor_mask |= DBE_LOG; 62 | i64o->alst = i64o->val; 63 | } 64 | if (monitor_mask) 65 | db_post_events(record, &i64o->val, monitor_mask); 66 | return OK; 67 | } 68 | 69 | static long writeData(dbCommon *record, format_t *format) 70 | { 71 | int64outRecord *i64o = (int64outRecord *)record; 72 | 73 | switch (format->type) 74 | { 75 | case DBF_ULONG: 76 | case DBF_ENUM: 77 | case DBF_LONG: 78 | return streamPrintf(record, format, (long)i64o->val); 79 | } 80 | return ERROR; 81 | } 82 | 83 | static long initRecord(dbCommon *record) 84 | { 85 | int64outRecord *i64o = (int64outRecord *)record; 86 | 87 | return streamInitRecord(record, &i64o->out, readData, writeData) == ERROR ? 88 | ERROR : OK; 89 | } 90 | 91 | struct { 92 | long number; 93 | DEVSUPFUN report; 94 | DEVSUPFUN init; 95 | DEVSUPFUN init_record; 96 | DEVSUPFUN get_ioint_info; 97 | DEVSUPFUN write; 98 | } devint64outStream = { 99 | 5, 100 | streamReport, 101 | streamInit, 102 | initRecord, 103 | streamGetIointInfo, 104 | streamWrite 105 | }; 106 | 107 | epicsExportAddress(dset,devint64outStream); 108 | -------------------------------------------------------------------------------- /src/devlonginStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS longin records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "longinRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | longinRecord *li = (longinRecord *)record; 29 | 30 | switch (format->type) 31 | { 32 | case DBF_ULONG: 33 | case DBF_LONG: 34 | case DBF_ENUM: 35 | { 36 | long val; 37 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 38 | li->val = val; 39 | return OK; 40 | } 41 | } 42 | return ERROR; 43 | } 44 | 45 | static long writeData(dbCommon *record, format_t *format) 46 | { 47 | longinRecord *li = (longinRecord *)record; 48 | 49 | switch (format->type) 50 | { 51 | case DBF_ULONG: 52 | return streamPrintf(record, format, (unsigned long)li->val); 53 | case DBF_LONG: 54 | case DBF_ENUM: 55 | return streamPrintf(record, format, (long)li->val); 56 | } 57 | return ERROR; 58 | } 59 | 60 | static long initRecord(dbCommon *record) 61 | { 62 | longinRecord *li = (longinRecord *)record; 63 | 64 | return streamInitRecord(record, &li->inp, readData, writeData) == ERROR ? 65 | ERROR : OK; 66 | } 67 | 68 | struct { 69 | long number; 70 | DEVSUPFUN report; 71 | DEVSUPFUN init; 72 | DEVSUPFUN init_record; 73 | DEVSUPFUN get_ioint_info; 74 | DEVSUPFUN read; 75 | } devlonginStream = { 76 | 5, 77 | streamReport, 78 | streamInit, 79 | initRecord, 80 | streamGetIointInfo, 81 | streamRead 82 | }; 83 | 84 | epicsExportAddress(dset,devlonginStream); 85 | -------------------------------------------------------------------------------- /src/devlongoutStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS longout records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "longoutRecord.h" 24 | #include "devStream.h" 25 | 26 | /* DELTA calculates the absolute difference between its arguments */ 27 | #define DELTA(last, val) ((last) > (val) ? (last) - (val) : (val) - (last)) 28 | 29 | static long readData(dbCommon *record, format_t *format) 30 | { 31 | longoutRecord *lo = (longoutRecord *)record; 32 | unsigned short monitor_mask; 33 | 34 | switch (format->type) 35 | { 36 | case DBF_ULONG: 37 | case DBF_LONG: 38 | case DBF_ENUM: 39 | { 40 | long val; 41 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 42 | lo->val = val; 43 | break; 44 | } 45 | default: 46 | return ERROR; 47 | } 48 | if (record->pact) return OK; 49 | /* In @init handler, no processing, enforce monitor updates. */ 50 | monitor_mask = recGblResetAlarms(record); 51 | if (DELTA(lo->mlst, lo->val) > lo->mdel) 52 | { 53 | monitor_mask |= DBE_VALUE; 54 | lo->mlst = lo->val; 55 | } 56 | if (DELTA(lo->alst, lo->val) > lo->adel) 57 | { 58 | monitor_mask |= DBE_LOG; 59 | lo->alst = lo->val; 60 | } 61 | if (monitor_mask) 62 | db_post_events(record, &lo->val, monitor_mask); 63 | return OK; 64 | } 65 | 66 | static long writeData(dbCommon *record, format_t *format) 67 | { 68 | longoutRecord *lo = (longoutRecord *)record; 69 | 70 | switch (format->type) 71 | { 72 | case DBF_ULONG: 73 | return streamPrintf(record, format, lo->val); 74 | case DBF_LONG: 75 | case DBF_ENUM: 76 | return streamPrintf(record, format, (long)lo->val); 77 | } 78 | return ERROR; 79 | } 80 | 81 | static long initRecord(dbCommon *record) 82 | { 83 | longoutRecord *lo = (longoutRecord *)record; 84 | 85 | return streamInitRecord(record, &lo->out, readData, writeData) == ERROR ? 86 | ERROR : OK; 87 | } 88 | 89 | struct { 90 | long number; 91 | DEVSUPFUN report; 92 | DEVSUPFUN init; 93 | DEVSUPFUN init_record; 94 | DEVSUPFUN get_ioint_info; 95 | DEVSUPFUN write; 96 | } devlongoutStream = { 97 | 5, 98 | streamReport, 99 | streamInit, 100 | initRecord, 101 | streamGetIointInfo, 102 | streamWrite 103 | }; 104 | 105 | epicsExportAddress(dset,devlongoutStream); 106 | -------------------------------------------------------------------------------- /src/devlsiStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS lsi records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "lsiRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | lsiRecord *lsi = (lsiRecord *)record; 29 | ssize_t length; 30 | 31 | if (format->type != DBF_STRING) return ERROR; 32 | if ((length = streamScanfN(record, format, lsi->val, (long)lsi->sizv)) == ERROR) 33 | { 34 | return ERROR; 35 | } 36 | if (length < (ssize_t)lsi->sizv) 37 | { 38 | lsi->val[length] = 0; 39 | } 40 | lsi->len = (epicsUInt32)length; 41 | return OK; 42 | } 43 | 44 | static long writeData(dbCommon *record, format_t *format) 45 | { 46 | lsiRecord *lsi = (lsiRecord *)record; 47 | 48 | if (format->type != DBF_STRING) return ERROR; 49 | return streamPrintf(record, format, lsi->val); 50 | } 51 | 52 | static long initRecord(dbCommon *record) 53 | { 54 | lsiRecord *lsi = (lsiRecord *)record; 55 | 56 | return streamInitRecord(record, &lsi->inp, readData, writeData) == ERROR ? 57 | ERROR : OK; 58 | } 59 | 60 | struct { 61 | long number; 62 | DEVSUPFUN report; 63 | DEVSUPFUN init; 64 | DEVSUPFUN init_record; 65 | DEVSUPFUN get_ioint_info; 66 | DEVSUPFUN read; 67 | } devlsiStream = { 68 | 5, 69 | streamReport, 70 | streamInit, 71 | initRecord, 72 | streamGetIointInfo, 73 | streamRead 74 | }; 75 | 76 | epicsExportAddress(dset,devlsiStream); 77 | -------------------------------------------------------------------------------- /src/devlsoStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS lso records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2018 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "lsoRecord.h" 24 | #include "menuPost.h" 25 | #include "devStream.h" 26 | 27 | static long readData(dbCommon *record, format_t *format) 28 | { 29 | lsoRecord *lso = (lsoRecord *)record; 30 | ssize_t length; 31 | unsigned short monitor_mask; 32 | 33 | if (format->type != DBF_STRING) return ERROR; 34 | if ((length = streamScanfN(record, format, lso->val, lso->sizv)) == ERROR) 35 | { 36 | return ERROR; 37 | } 38 | if (length < (ssize_t)lso->sizv) 39 | { 40 | lso->val[length] = 0; 41 | } 42 | lso->len = (epicsUInt32)length; 43 | if (record->pact) return OK; 44 | /* In @init handler, no processing, enforce monitor updates. */ 45 | monitor_mask = recGblResetAlarms(record); 46 | if (lso->len != lso->olen || 47 | memcmp(lso->oval, lso->val, lso->len)) { 48 | monitor_mask |= DBE_VALUE | DBE_LOG; 49 | memcpy(lso->oval, lso->val, lso->len); 50 | } 51 | if (lso->len != lso->olen) { 52 | lso->olen = lso->len; 53 | db_post_events(record, &lso->len, DBE_VALUE | DBE_LOG); 54 | } 55 | if (lso->mpst == menuPost_Always) 56 | monitor_mask |= DBE_VALUE; 57 | if (lso->apst == menuPost_Always) 58 | monitor_mask |= DBE_LOG; 59 | if (monitor_mask) 60 | db_post_events(record, lso->val, monitor_mask); 61 | return OK; 62 | } 63 | 64 | static long writeData(dbCommon *record, format_t *format) 65 | { 66 | lsoRecord *lso = (lsoRecord *)record; 67 | 68 | if (format->type != DBF_STRING) return ERROR; 69 | return streamPrintf(record, format, lso->val); 70 | } 71 | 72 | static long initRecord(dbCommon *record) 73 | { 74 | lsoRecord *lso = (lsoRecord *)record; 75 | 76 | return streamInitRecord(record, &lso->out, readData, writeData) == ERROR ? 77 | ERROR : OK; 78 | } 79 | 80 | struct { 81 | long number; 82 | DEVSUPFUN report; 83 | DEVSUPFUN init; 84 | DEVSUPFUN init_record; 85 | DEVSUPFUN get_ioint_info; 86 | DEVSUPFUN write; 87 | } devlsoStream = { 88 | 5, 89 | streamReport, 90 | streamInit, 91 | initRecord, 92 | streamGetIointInfo, 93 | streamWrite 94 | }; 95 | 96 | epicsExportAddress(dset,devlsoStream); 97 | -------------------------------------------------------------------------------- /src/devmbbiDirectStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS mbbiDirect records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "mbbiDirectRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | mbbiDirectRecord *mbbiD = (mbbiDirectRecord *)record; 29 | unsigned long val; 30 | 31 | if (format->type == DBF_ULONG || format->type == DBF_LONG) 32 | { 33 | if (streamScanf(record, format, &val) == ERROR) return ERROR; 34 | if (mbbiD->mask) 35 | { 36 | val &= mbbiD->mask; 37 | mbbiD->rval = val; 38 | return OK; 39 | } 40 | else 41 | { 42 | /* No MASK, (NOBT = 0): use VAL field */ 43 | mbbiD->val = val; /* no cast because we cannot be sure about type of VAL */ 44 | return DO_NOT_CONVERT; 45 | } 46 | } 47 | return ERROR; 48 | } 49 | 50 | static long writeData(dbCommon *record, format_t *format) 51 | { 52 | mbbiDirectRecord *mbbiD = (mbbiDirectRecord *)record; 53 | unsigned long val; 54 | 55 | if (format->type == DBF_ULONG || format->type == DBF_LONG) 56 | { 57 | if (mbbiD->mask) val = mbbiD->rval & mbbiD->mask; 58 | else val = mbbiD->val; 59 | return streamPrintf(record, format, val); 60 | } 61 | return ERROR; 62 | } 63 | 64 | static long initRecord(dbCommon *record) 65 | { 66 | mbbiDirectRecord *mbbiD = (mbbiDirectRecord *)record; 67 | 68 | mbbiD->mask <<= mbbiD->shft; 69 | return streamInitRecord(record, &mbbiD->inp, readData, writeData) == ERROR ? 70 | ERROR : OK; 71 | } 72 | 73 | struct { 74 | long number; 75 | DEVSUPFUN report; 76 | DEVSUPFUN init; 77 | DEVSUPFUN init_record; 78 | DEVSUPFUN get_ioint_info; 79 | DEVSUPFUN read; 80 | } devmbbiDirectStream = { 81 | 5, 82 | streamReport, 83 | streamInit, 84 | initRecord, 85 | streamGetIointInfo, 86 | streamRead 87 | }; 88 | 89 | epicsExportAddress(dset,devmbbiDirectStream); 90 | -------------------------------------------------------------------------------- /src/devscalcoutStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS scalcout records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 2006 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "sCalcoutRecord.h" 24 | #include "devStream.h" 25 | 26 | /* Up to version 2-6-1 of the SynApps calc module 27 | scalcout record has a bug: it never calls init_record 28 | of the device support. 29 | Fix: sCalcoutRecord.c, end of init_record() add 30 | 31 | if (pscalcoutDSET->init_record ) { 32 | return (*pscalcoutDSET->init_record)(pcalc); 33 | } 34 | */ 35 | 36 | static long readData(dbCommon *record, format_t *format) 37 | { 38 | scalcoutRecord *sco = (scalcoutRecord *)record; 39 | 40 | switch (format->type) 41 | { 42 | case DBF_DOUBLE: 43 | { 44 | if (streamScanf(record, format, &sco->val) == ERROR) return ERROR; 45 | return OK; 46 | } 47 | case DBF_LONG: 48 | case DBF_ULONG: 49 | case DBF_ENUM: 50 | { 51 | long lval; 52 | 53 | if (streamScanf(record, format, &lval) == ERROR) return ERROR; 54 | sco->val = lval; 55 | return OK; 56 | } 57 | case DBF_STRING: 58 | { 59 | if ((streamScanfN(record, format, 60 | sco->sval, sizeof(sco->val)) == ERROR)) return ERROR; 61 | return OK; 62 | } 63 | } 64 | return ERROR; 65 | } 66 | 67 | static long writeData(dbCommon *record, format_t *format) 68 | { 69 | scalcoutRecord *sco = (scalcoutRecord *)record; 70 | 71 | switch (format->type) 72 | { 73 | case DBF_DOUBLE: 74 | { 75 | return streamPrintf(record, format, sco->oval); 76 | } 77 | case DBF_LONG: 78 | case DBF_ULONG: 79 | case DBF_ENUM: 80 | { 81 | return streamPrintf(record, format, (long)sco->oval); 82 | } 83 | case DBF_STRING: 84 | { 85 | return streamPrintf(record, format, sco->osv); 86 | } 87 | } 88 | return ERROR; 89 | } 90 | 91 | static long initRecord(dbCommon *record) 92 | { 93 | scalcoutRecord *sco = (scalcoutRecord *)record; 94 | 95 | return streamInitRecord(record, &sco->out, readData, writeData); 96 | } 97 | 98 | struct { 99 | long number; 100 | DEVSUPFUN report; 101 | DEVSUPFUN init; 102 | DEVSUPFUN init_record; 103 | DEVSUPFUN get_ioint_info; 104 | DEVSUPFUN write; 105 | } devscalcoutStream = { 106 | 5, 107 | streamReport, 108 | streamInit, 109 | initRecord, 110 | streamGetIointInfo, 111 | streamWrite, 112 | }; 113 | 114 | epicsExportAddress(dset,devscalcoutStream); 115 | -------------------------------------------------------------------------------- /src/devstringinStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS stringin records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "stringinRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | stringinRecord *si = (stringinRecord *)record; 29 | 30 | if (format->type == DBF_STRING) 31 | { 32 | if (streamScanfN(record, format, si->val, sizeof(si->val)) == ERROR) return ERROR; 33 | return OK; 34 | } 35 | return ERROR; 36 | } 37 | 38 | static long writeData(dbCommon *record, format_t *format) 39 | { 40 | stringinRecord *si = (stringinRecord *)record; 41 | 42 | if (format->type == DBF_STRING) 43 | { 44 | return streamPrintf(record, format, si->val); 45 | } 46 | return ERROR; 47 | } 48 | 49 | static long initRecord(dbCommon *record) 50 | { 51 | stringinRecord *si = (stringinRecord *)record; 52 | 53 | return streamInitRecord(record, &si->inp, readData, writeData) == ERROR ? 54 | ERROR : OK; 55 | } 56 | 57 | struct { 58 | long number; 59 | DEVSUPFUN report; 60 | DEVSUPFUN init; 61 | DEVSUPFUN init_record; 62 | DEVSUPFUN get_ioint_info; 63 | DEVSUPFUN read; 64 | } devstringinStream = { 65 | 5, 66 | streamReport, 67 | streamInit, 68 | initRecord, 69 | streamGetIointInfo, 70 | streamRead 71 | }; 72 | 73 | epicsExportAddress(dset,devstringinStream); 74 | -------------------------------------------------------------------------------- /src/devstringoutStream.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * This is the StreamDevice interface for EPICS stringout records. 3 | * Please see ../docs/ for detailed documentation. 4 | * 5 | * (C) 1999,2005 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | * 7 | * This file is part of StreamDevice. 8 | * 9 | * StreamDevice is free software: You can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * StreamDevice is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | *************************************************************************/ 22 | 23 | #include "stringoutRecord.h" 24 | #include "devStream.h" 25 | 26 | static long readData(dbCommon *record, format_t *format) 27 | { 28 | stringoutRecord *so = (stringoutRecord *)record; 29 | unsigned short monitor_mask; 30 | 31 | if (format->type != DBF_STRING) return ERROR; 32 | if (streamScanfN(record, format, so->val, sizeof(so->val)) == ERROR) return ERROR; 33 | if (record->pact) return OK; 34 | /* In @init handler, no processing, enforce monitor updates. */ 35 | monitor_mask = recGblResetAlarms(record); 36 | #ifndef EPICS_3_13 37 | if (so->mpst == stringoutPOST_Always) 38 | monitor_mask |= DBE_VALUE; 39 | if (so->apst == stringoutPOST_Always) 40 | monitor_mask |= DBE_LOG; 41 | #endif 42 | if (monitor_mask != (DBE_VALUE|DBE_LOG) && 43 | strncmp(so->oval, so->val, sizeof(so->val))) 44 | { 45 | monitor_mask |= DBE_VALUE | DBE_LOG; 46 | strncpy(so->oval, so->val, sizeof(so->oval)); 47 | } 48 | if (monitor_mask) 49 | db_post_events(record, so->val, monitor_mask); 50 | return OK; 51 | } 52 | 53 | static long writeData(dbCommon *record, format_t *format) 54 | { 55 | stringoutRecord *so = (stringoutRecord *)record; 56 | 57 | if (format->type == DBF_STRING) 58 | { 59 | return streamPrintf(record, format, so->val); 60 | } 61 | return ERROR; 62 | } 63 | 64 | static long initRecord(dbCommon *record) 65 | { 66 | stringoutRecord *so = (stringoutRecord *)record; 67 | 68 | return streamInitRecord(record, &so->out, readData, writeData) == ERROR ? 69 | ERROR : OK; 70 | } 71 | 72 | struct { 73 | long number; 74 | DEVSUPFUN report; 75 | DEVSUPFUN init; 76 | DEVSUPFUN init_record; 77 | DEVSUPFUN get_ioint_info; 78 | DEVSUPFUN write; 79 | } devstringoutStream = { 80 | 5, 81 | streamReport, 82 | streamInit, 83 | initRecord, 84 | streamGetIointInfo, 85 | streamWrite 86 | }; 87 | 88 | epicsExportAddress(dset,devstringoutStream); 89 | -------------------------------------------------------------------------------- /src/makeStreamVersion.pl: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is a helper script for StreamDevice. 3 | # It generates a version file from git tags. 4 | # 5 | # (C) 2020 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | use strict; 24 | 25 | 26 | my ( $major, $minor, $patch, $dev, $date, $hash ); 27 | 28 | if (my $version = `git describe --tags --abbrev=0 --dirty --match "[0-9]*" 2>/dev/null`) { 29 | if ($version =~ m/(\d+)\.(\d+)\.(\d+)?(.*)?/) { 30 | $major = $1; $minor = $2; $patch = $3; $dev = $4; 31 | } 32 | if (`git log -1 --format="%H %ci"`=~ m/([[:xdigit:]]+) (.+)/) { 33 | $hash = $1; $date = $2; 34 | } 35 | } 36 | if (!$major) { 37 | if (open(my $fh, '<', '../../.VERSION')) { 38 | while (my $line = <$fh>) { 39 | if ($line =~ m/COMMIT: *([[:xdigit:]]+)/) { 40 | $hash = $1; 41 | } 42 | if ($line =~ m/REFS: .*tag: *(\d+)\.(\d+)\.?(\d+)?/) { 43 | $major = $1; $minor = $2; $patch = $3 or $patch = 0; 44 | } 45 | if ($line =~ m/DATE: *([-0-9:+ ]*)/) { 46 | $date = $1; 47 | } 48 | } 49 | } else { 50 | print "neither git repo nor .VERSION file found\n"; 51 | } 52 | } 53 | 54 | open my $out, '>', @ARGV or die $!; 55 | print $out < $@ 54 | 55 | include $(EPICS_BASE)/config/RULES.Vx 56 | include ../../config/RULES.munch 57 | 58 | # Rebuild when LIBOBJS changes 59 | $(LIBNAME): ../base-3-13LIBOBJS 60 | -------------------------------------------------------------------------------- /streamApp/checksums.cmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ########################################################################## 3 | # This is an example and debug EPICS startup script for StreamDevice. 4 | # 5 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | exec O.$EPICS_HOST_ARCH/streamApp $0 24 | dbLoadDatabase "O.Common/streamApp.dbd" 25 | streamApp_registerRecordDeviceDriver 26 | 27 | drvAsynIPPortConfigure "terminal", "localhost:40000" 28 | 29 | dbLoadRecords checksums.db 30 | 31 | #log debug output to file 32 | #streamSetLogfile StreamDebug.log 33 | var streamError 1 34 | 35 | iocInit 36 | #var streamDebug 1 37 | -------------------------------------------------------------------------------- /streamApp/checksums.db: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug EPICS database for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | record (stringout, "DZ:checksums") 23 | { 24 | field (DTYP, "stream") 25 | field (OUT, "@checksums.proto write terminal") 26 | field (VAL, "123456789") 27 | field (PINI, "YES") 28 | } 29 | -------------------------------------------------------------------------------- /streamApp/checksums.proto: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug protocol file for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | Terminator = NL; 23 | 24 | # Output string, checksum name and checksum value 25 | # Format checksums as ascii hex (%0 flag) 26 | # Ignore the 12 chars (.12) between the sting (%s) and the checksum (%<...) 27 | 28 | write { 29 | out "%s sum %0.12"; 30 | out "%s sum8 %0.12"; 31 | out "%s ~sum %0.12<~sum>"; 32 | out "%s notsum %0.12"; 33 | out "%s -sum %0.12<-sum>"; 34 | out "%s negsum %0.12"; 35 | out "%s sum16 %0.12"; 36 | out "%s sum32 %0.12"; 37 | out "%s xor %0.12"; 38 | out "%s xor8 %0.12"; 39 | out "%s xor7 %0.12"; 40 | out "%s crc8 %0.12"; 41 | out "%s ccitt8 %0.12"; 42 | out "%s crc16 %0.12"; 43 | out "%s crc16r %0.12"; 44 | out "%s modbus %0.12"; 45 | out "%s ccitt16 %0.12"; 46 | out "%s ccitt16a %0.12"; 47 | out "%s ccitt16x %0.12"; 48 | out "%s crc16c %0.12"; 49 | out "%s xmodem %0.12"; 50 | out "%s crc32 %0.12"; 51 | out "%s crc32r %0.12"; 52 | out "%s jamcrc %0.12"; 53 | out "%s adler32 %0.12"; 54 | out "%s hexsum8 %0.12"; 55 | out "%s cpi %0.12"; 56 | out "%s leybold %0.12"; 57 | out "%s lrc %0.12"; 58 | out "%s hexlrc %0.12"; 59 | } 60 | -------------------------------------------------------------------------------- /streamApp/example-3-13.cmd: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug EPICS startup script for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | BIN="" 23 | DBD="" 24 | HOME="" 25 | 26 | #where can protocols be located? 27 | STREAM_PROTOCOL_PATH=".:protocols:../protocols/" 28 | 29 | cd BIN 30 | ld < iocCore 31 | ld < streamApp.munch 32 | dbLoadDatabase "streamApp.dbd",DBD 33 | 34 | drvAsynIPPortConfigure "terminal", "xxx.xxx.xxx.xxx:40000" 35 | 36 | #load the records 37 | cd HOME 38 | dbLoadRecords "example.db","PREFIX=DZ" 39 | 40 | #lots of debug output 41 | #streamDebug=1 42 | iocInit 43 | -------------------------------------------------------------------------------- /streamApp/example.cmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ########################################################################## 3 | # This is an example and debug EPICS startup script for StreamDevice. 4 | # 5 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | exec O.$EPICS_HOST_ARCH/streamApp $0 24 | dbLoadDatabase "O.Common/streamApp.dbd" 25 | streamApp_registerRecordDeviceDriver 26 | 27 | #where can protocols be located? 28 | epicsEnvSet "STREAM_PROTOCOL_PATH", ".:protocols:../protocols/" 29 | 30 | #setup the busses 31 | 32 | #example serial port setup 33 | #drvAsynSerialPortConfigure "COM2", "/dev/ttyS1" 34 | #asynOctetSetInputEos "COM2",0,"\r\n" 35 | #asynOctetSetOutputEos "COM2",0,"\r\n" 36 | #asynSetOption ("COM2", 0, "baud", "9600") 37 | #asynSetOption ("COM2", 0, "bits", "8") 38 | #asynSetOption ("COM2", 0, "parity", "none") 39 | #asynSetOption ("COM2", 0, "stop", "1") 40 | #asynSetOption ("COM2", 0, "clocal", "Y") 41 | #asynSetOption ("COM2", 0, "crtscts", "N") 42 | 43 | #example telnet style IP port setup 44 | drvAsynIPPortConfigure "terminal", "localhost:40000" 45 | 46 | # Either set terminators here or in the protocol 47 | asynOctetSetInputEos "terminal",0,"\r\n" 48 | asynOctetSetOutputEos "terminal",0,"\r\n" 49 | 50 | #example VXI11 (GPIB via IP) port setup 51 | #vxi11Configure "GPIB","ins023",1,5.0,"hpib" 52 | 53 | #load the records 54 | dbLoadRecords "example.db","PREFIX=DZ" 55 | 56 | #log debug output to file 57 | #streamSetLogfile StreamDebug.log 58 | 59 | #lots(!) of debug output before iocInit 60 | #var streamDebug 1 61 | 62 | iocInit 63 | 64 | #enable debug output 65 | #var streamDebug 1 66 | -------------------------------------------------------------------------------- /streamApp/regexp.README: -------------------------------------------------------------------------------- 1 | How to use regular expressions in StreamDevice. 2 | 3 | First, you need the PCRE library. 4 | If it is already installed for your (Linux) system (try: rpm -ql pcre), 5 | set the following variables in your RELEASE file: 6 | PCRE_INCLUDE= 7 | PCRE_LIB= 8 | 9 | For vxWorks, Windows and others you're probably out of luck here. 10 | In that case, download the PCRE package from www.pcre.org and 11 | epics.web.psi.ch/software/streamdevice/pcre/Makefile and compile 12 | PCRE as an EPICS application. Use the variable PCRE in your RELEASE file 13 | to define the location of this application. 14 | 15 | If either PCRE or PCRE_INCLUDE or PCRE_LIB are set in the RELEASE file, 16 | StreamDevice is automatically build with regular expression support. 17 | 18 | The syntax is %/regexp/. It can only be used in input. It returns the 19 | next string that matches the regexp. Anything before this string is skipped. 20 | 21 | To use sub-expressions use %.n/rexexp/ where n is a number from 1 to 9 22 | to match the n-th sub-expression. 23 | 24 | It is possible to limit the input length to the match algorithm like 25 | %m/regexp/ where m is the maximal length. 26 | 27 | Example: 28 | in "%100.1/(.*)<\/title>/"; 29 | This searches the next 100 bytes and returns the string bewteen 30 | <title> and . Any input before is skipped. Any input 31 | after is left in the buffer (and can by matched by other formats). 32 | Note that the / in must be escaped. 33 | 34 | See regexp.cmd, regexp.proto, regexp.db for a working example. 35 | -------------------------------------------------------------------------------- /streamApp/regexp.cmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ########################################################################## 3 | # This is an example and debug EPICS startup script for StreamDevice. 4 | # 5 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | exec O.$EPICS_HOST_ARCH/streamApp $0 24 | dbLoadDatabase "O.Common/streamApp.dbd" 25 | streamApp_registerRecordDeviceDriver 26 | 27 | # no autoconnect for web servers (see regexp.proto) 28 | drvAsynIPPortConfigure web epics.web.psi.ch:80 0 1 29 | 30 | dbLoadRecords regexp.db 31 | 32 | #log debug output to file 33 | #streamSetLogfile StreamDebug.log 34 | 35 | iocInit 36 | #var streamDebug 1 37 | 38 | #let's see the title of the PSI EPICS web site 39 | epicsThreadSleep 1 40 | dbgf DZ:regexp 41 | -------------------------------------------------------------------------------- /streamApp/regexp.db: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug EPICS database for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | record (stringin, "DZ:regexp") 23 | { 24 | field (DTYP, "stream") 25 | field (INP, "@regexp.proto readTitle web") 26 | field (PINI, "YES") 27 | } 28 | -------------------------------------------------------------------------------- /streamApp/regexp.proto: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug protocol file for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | # regular expression example 23 | # extract the title of from a web page 24 | 25 | outterminator = NL; 26 | interminator = "" NL; # terminators can have arbitrary length 27 | 28 | # Web servers close the connection after sending a page. 29 | # Thus, we can't use autoconnect (see drvAsynIPPortConfigure) 30 | # Handle connection manually in protocol. 31 | 32 | readTitle { 33 | extraInput=ignore; 34 | 35 | connect 1000; # connect to server, 1 second timeout 36 | out "GET http://epics.web.psi.ch/"; # HTTP request 37 | in "%.1/(.*)<\/title>/"; # get string in <title> 38 | disconnect; # servers closes, so do we. 39 | } 40 | -------------------------------------------------------------------------------- /streamApp/simple.cmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ########################################################################## 3 | # This is an example and debug EPICS startup script for StreamDevice. 4 | # 5 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | exec O.$EPICS_HOST_ARCH/streamApp $0 24 | dbLoadDatabase "O.Common/streamApp.dbd" 25 | streamApp_registerRecordDeviceDriver 26 | 27 | #where can protocols be located? 28 | epicsEnvSet "STREAM_PROTOCOL_PATH", ".:protocols:../protocols/" 29 | 30 | #setup the hardware 31 | 32 | drvAsynIPPortConfigure "L0", "localhost:40000" 33 | #vxi11Configure "L0","gpib-hostname-or-ip",0,0.0,"gpib0" 34 | 35 | #load the records 36 | dbLoadRecords "simple.db","P=DZ,BUS=L0 28" 37 | 38 | #log debug output to file 39 | #streamSetLogfile StreamDebug.log 40 | 41 | iocInit 42 | 43 | #enable debug output 44 | #var streamDebug 1 45 | -------------------------------------------------------------------------------- /streamApp/simple.db: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug EPICS database for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | record (stringout, "$(P):cmd") 23 | { 24 | field (DTYP, "stream") 25 | field (OUT, "@simple.proto cmd $(BUS)") 26 | } 27 | record (stringout, "$(P):info") 28 | { 29 | field (DTYP, "stream") 30 | field (OUT, "@simple.proto info $(BUS)") 31 | } 32 | record (stringin, "$(P):read") 33 | { 34 | field (DTYP, "stream") 35 | field (INP, "@simple.proto read $(BUS)") 36 | } 37 | -------------------------------------------------------------------------------- /streamApp/simple.proto: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug protocol file for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | terminator = LF; 23 | 24 | cmd { 25 | out "%s"; 26 | } 27 | info { 28 | extrainput=ignore; 29 | out "%s"; 30 | in "%39c"; 31 | } 32 | read { 33 | in "%39c"; 34 | } 35 | -------------------------------------------------------------------------------- /streamApp/streamAppMain.cc: -------------------------------------------------------------------------------- 1 | /* Author: Marty Kraimer Date: 17MAR2000 */ 2 | 3 | #include "epicsThread.h" 4 | #include "iocsh.h" 5 | 6 | int main(int argc,char *argv[]) 7 | { 8 | if(argc>=2) { 9 | iocsh(argv[1]); 10 | epicsThreadSleep(.2); 11 | } 12 | iocsh(NULL); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /streamApp/test.cmd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ########################################################################## 3 | # This is an example and debug EPICS startup script for StreamDevice. 4 | # 5 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 6 | # 7 | # This file is part of StreamDevice. 8 | # 9 | # StreamDevice is free software: You can redistribute it and/or modify 10 | # it under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # StreamDevice is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Lesser General Public License 20 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 21 | #########################################################################/ 22 | 23 | exec O.$EPICS_HOST_ARCH/streamApp $0 24 | dbLoadDatabase "O.Common/streamApp.dbd" 25 | streamApp_registerRecordDeviceDriver 26 | 27 | epicsEnvSet "STREAM_PROTOCOL_PATH", "." 28 | 29 | drvAsynIPPortConfigure "terminal", "localhost:40000" 30 | 31 | dbLoadRecords "test.db","P=TEST" 32 | 33 | #log debug output to file 34 | #streamSetLogfile StreamDebug.log 35 | 36 | iocInit 37 | 38 | #var streamDebug 1 39 | -------------------------------------------------------------------------------- /streamApp/test.proto: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is an example and debug protocol file for StreamDevice. 3 | # 4 | # (C) 2010 Dirk Zimoch (dirk.zimoch@psi.ch) 5 | # 6 | # This file is part of StreamDevice. 7 | # 8 | # StreamDevice is free software: You can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # StreamDevice is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with StreamDevice. If not, see https://www.gnu.org/licenses/. 20 | #########################################################################/ 21 | 22 | terminator = LF; 23 | readtimeout = 10; 24 | pollperiod = 10; 25 | replytimeout = 1000; 26 | command { 27 | out "%s"; 28 | } 29 | info { 30 | out "%s"; 31 | in "%39c"; 32 | } 33 | request { 34 | out "%s"; 35 | in "%(\$1)39c"; 36 | } 37 | spy { 38 | extraInput=ignore; 39 | in "%39c"; 40 | } 41 | spybin { 42 | readtimeout = 1; 43 | terminator = ""; 44 | extraInput=ignore; 45 | in "%r"; 46 | } 47 | checksum { 48 | out "%s %0.1<\$1>"; 49 | } 50 | -------------------------------------------------------------------------------- /streamApp/test.readme: -------------------------------------------------------------------------------- 1 | Simple test environment: 2 | 3 | 1) Start device simulation: 4 | terminal.tcl & 5 | Or set up a real device. 6 | 7 | 2) Start ioc: 8 | xterm -e test.cmd & 9 | Or edit test.cmd first. 10 | 11 | 3) Start medm: 12 | medm -x -macro P=TEST test.adl & 13 | 14 | Records: 15 | TEST:cmd - writes string to device 16 | TEST:info - writes string and reads reply (result in same record) 17 | TEST:spy - gets any input line from device 18 | TEST:spybin - gets any input (binary waveform) 19 | TEST:log* - history of TEST:spy 20 | 21 | Try to write 'help' to TEST:cmd. 22 | -------------------------------------------------------------------------------- /streamApp/tests/printdouble: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=$$ 4 | trap "rm -f $filename.c $filename " EXIT TERM KILL 5 | 6 | cat > $filename.c << EOF 7 | #line 8 8 | #include 9 | #include 10 | 11 | int main (int argc, char** args) 12 | { 13 | union { 14 | float f; 15 | double d; 16 | unsigned char c [8]; 17 | } u; 18 | 19 | int i,j; 20 | 21 | for (i = 1; i < argc; i++) 22 | { 23 | u.f = atof (args[i]); 24 | for (j = 0; j < 4; j++) 25 | { 26 | printf ("\\\\x%02x", u.c[j]); 27 | } 28 | printf ("\n"); 29 | u.d = atof (args[i]); 30 | for (j = 0; j < 8; j++) 31 | { 32 | printf ("\\\\x%02x", u.c[j]); 33 | } 34 | printf ("\n"); 35 | } 36 | return 0; 37 | } 38 | EOF 39 | 40 | cc -Wall -pedantic $filename.c -o $filename && $filename "$@" 41 | -------------------------------------------------------------------------------- /streamApp/tests/test64Bit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ao, "DZ:ao") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto ao device") 14 | } 15 | record (longout, "DZ:longout") 16 | { 17 | field (DTYP, "stream") 18 | field (OUT, "@test.proto longout device") 19 | } 20 | record (bo, "DZ:bo") 21 | { 22 | field (DTYP, "stream") 23 | field (OUT, "@test.proto bo device") 24 | field (MASK, "-1") 25 | } 26 | record (mbbo, "DZ:mbbo") 27 | { 28 | field (DTYP, "stream") 29 | field (OUT, "@test.proto mbbo device") 30 | field (ZRVL, "0") 31 | field (ONVL, "-1") 32 | field (ZRST, "0") 33 | field (ONST, "-1") 34 | } 35 | record (mbboDirect, "DZ:mbboDirect") 36 | { 37 | field (DTYP, "stream") 38 | field (OUT, "@test.proto mbboDirect device") 39 | } 40 | record (ai, "DZ:ai") 41 | { 42 | field (DTYP, "stream") 43 | field (INP, "@test.proto ai device") 44 | } 45 | record (longin, "DZ:longin") 46 | { 47 | field (DTYP, "stream") 48 | field (INP, "@test.proto longin device") 49 | } 50 | } 51 | 52 | set protocol { 53 | Terminator = LF; 54 | # these records use signed values: %d 55 | ao {out "ao %.3f %d %(VAL).3f %(RVAL)d";} 56 | longout {out "longout %d %(VAL)d";} 57 | ai {out "ai?"; in "%d"; out "ai %d";} 58 | longin {out "longin?"; in "%d"; out "longin %d";} 59 | # these records use unsigned values: %u, %x 60 | bo {out "bo %u %x %b";} 61 | mbbo {out "mbbo %u %x %b";} 62 | mbboDirect {out "mbboDirect %u %x %b";} 63 | bi {out "bi?"; in "%d"; out "bi %d %x";} 64 | mbbi {out "mbbi?"; in "%d"; out "mbbi %d %x";} 65 | mbbiDirect {out "mbbiDirect?"; in "%d"; out "mbbiDirect %d %x";} 66 | } 67 | 68 | set startup { 69 | } 70 | 71 | set debug 0 72 | 73 | startioc 74 | put DZ:ao -1 75 | assure "ao -1.000 -1 -1.000 -1\n" 76 | put DZ:longout -1 77 | assure "longout -1 -1\n" 78 | put DZ:bo 1 79 | assure "bo 4294967295 ffffffff 11111111111111111111111111111111\n" 80 | put DZ:mbbo -1 81 | assure "mbbo 4294967295 ffffffff 11111111111111111111111111111111\n" 82 | put DZ:mbboDirect.B0 1 83 | assure "mbboDirect 1 1 1\n" 84 | #Writing to mbboDirect.VAL is not supported by EPICS 85 | #put DZ:mbboDirect -1 86 | #assure "mbboDirect 65535 ffff 1111111111111111\n" 87 | process DZ:ai 88 | assure "ai?\n" 89 | send "-1\n" 90 | assure "ai -1\n" 91 | process DZ:longin 92 | assure "longin?\n" 93 | send "-1\n" 94 | assure "longin -1\n" 95 | 96 | 97 | finish 98 | -------------------------------------------------------------------------------- /streamApp/tests/testBo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (bo, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | field (ZNAM, "OFF") 15 | field (ONAM, "ON") 16 | } 17 | } 18 | 19 | set protocol { 20 | test1 {out "%i %r %s";} 21 | } 22 | 23 | set startup { 24 | } 25 | 26 | set debug 0 27 | 28 | startioc 29 | 30 | put DZ:test1 0 31 | assure "0 \x00 OFF" 32 | put DZ:test1 1 33 | assure "1 \x01 ON" 34 | 35 | finish 36 | -------------------------------------------------------------------------------- /streamApp/tests/testCharset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto test1 device") 14 | } 15 | record (stringin, "DZ:test2") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto test2 device") 19 | } 20 | record (stringin, "DZ:test3") 21 | { 22 | field (DTYP, "stream") 23 | field (INP, "@test.proto test3 device") 24 | } 25 | record (stringin, "DZ:test4") 26 | { 27 | field (DTYP, "stream") 28 | field (INP, "@test.proto test4 device") 29 | } 30 | } 31 | 32 | set protocol { 33 | Terminator = LF; 34 | extraInput=ignore; 35 | @mismatch {out "mismatch";} 36 | test1 {in "%[a-zA-Z1-5]%(DESC) #s"; out "%s|%(DESC)s" } 37 | test2 {in "%[]A-Za-z ]%(DESC) #s"; out "%s|%(DESC)s" } 38 | test3 {in "%[^]A-Z]%(DESC) #s"; out "%s|%(DESC)s" } 39 | test4 {in "%[^]-A-Z]%(DESC) #s"; out "%s|%(DESC)s" } 40 | } 41 | 42 | set startup { 43 | } 44 | 45 | set debug 0 46 | 47 | startioc 48 | 49 | process DZ:test1 50 | send "This is a test\n" 51 | assure "This| is a test\n" 52 | process DZ:test1 53 | send "Test123]bla\n" 54 | assure "Test123|]bla\n" 55 | process DZ:test1 56 | send "Test123456\n" 57 | assure "Test12345|6\n" 58 | process DZ:test1 59 | send "Test43210\n" 60 | assure "Test4321|0\n" 61 | process DZ:test1 62 | send "test-bla\n" 63 | assure "test|-bla\n" 64 | process DZ:test1 65 | send " Space first\n" 66 | assure "| Space first\n" 67 | 68 | process DZ:test2 69 | send "This is a test\n" 70 | assure "This is a test|\n" 71 | process DZ:test2 72 | send "Test]xx123bla\n" 73 | assure "Test]xx|123bla\n" 74 | process DZ:test2 75 | send "test-bla\n" 76 | assure "test|-bla\n" 77 | process DZ:test2 78 | send " Space first\n" 79 | assure " Space first|\n" 80 | 81 | process DZ:test3 82 | send "this is a test\n" 83 | assure "this is a test|\n" 84 | process DZ:test3 85 | send "test]xx123bla\n" 86 | assure "test|]xx123bla\n" 87 | process DZ:test3 88 | send "test-bla\n" 89 | assure "test-bla|\n" 90 | process DZ:test3 91 | send " Space first\n" 92 | assure " |Space first\n" 93 | 94 | process DZ:test4 95 | send "this is a test\n" 96 | assure "this is a test|\n" 97 | process DZ:test4 98 | send "test]xx123bla\n" 99 | assure "test|]xx123bla\n" 100 | process DZ:test4 101 | send "test-bla\n" 102 | assure "test|-bla\n" 103 | process DZ:test4 104 | send " Space first\n" 105 | assure " |Space first\n" 106 | 107 | finish 108 | 109 | -------------------------------------------------------------------------------- /streamApp/tests/testCompare: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ao, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = LF; 19 | @mismatch { out "mismatch"; } 20 | test1 {out "set %.2f"; in "ack %=.2f X"; out "OK"; } 21 | } 22 | 23 | set startup { 24 | } 25 | 26 | set debug 0 27 | 28 | startioc 29 | 30 | put DZ:test1 3.14 31 | assure "set 3.14\n" 32 | send "ack 3.14 X\n" 33 | assure "OK\n" 34 | put DZ:test1 0 35 | assure "set 0.00\n" 36 | send "ack 0.00 X\n" 37 | assure "OK\n" 38 | put DZ:test1 1 39 | assure "set 1.00\n" 40 | send "ack 1.0 X\n" 41 | assure "mismatch\n" 42 | 43 | finish 44 | -------------------------------------------------------------------------------- /streamApp/tests/testDefaultInput: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (longin, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto integer device") 14 | } 15 | record (ai, "DZ:test2") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto double device") 19 | } 20 | } 21 | 22 | set protocol { 23 | Terminator = LF; 24 | integer {out "integer"; in "n: %?d xx"; out "n = %d"; } 25 | double {out "double"; in "n: %?g xx"; out "n = %.4f"; } 26 | } 27 | 28 | set startup { 29 | } 30 | 31 | set debug 0 32 | 33 | startioc 34 | 35 | process DZ:test1 36 | assure "integer\n"; 37 | send "n: -12 xx\n"; 38 | assure "n = -12\n"; 39 | 40 | process DZ:test1 41 | assure "integer\n"; 42 | send "n: xx\n"; 43 | assure "n = 0\n"; 44 | 45 | process DZ:test2 46 | assure "double\n"; 47 | send "n: 3.1415 xx\n"; 48 | assure "n = 3.1415\n"; 49 | 50 | process DZ:test2 51 | assure "double\n"; 52 | send "n: xx\n"; 53 | assure "n = 0.0000\n"; 54 | 55 | 56 | finish 57 | -------------------------------------------------------------------------------- /streamApp/tests/testDouble: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ai, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto test1 device") 14 | } 15 | record (ai, "DZ:test2") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto test2 device") 19 | } 20 | record (ai, "DZ:test3") 21 | { 22 | field (DTYP, "stream") 23 | field (INP, "@test.proto test3 device") 24 | } 25 | record (ai, "DZ:test4") 26 | { 27 | field (DTYP, "stream") 28 | field (INP, "@test.proto test4 device") 29 | } 30 | } 31 | 32 | set protocol { 33 | Terminator = LF; 34 | @mismatch {out "mismatch";} 35 | test1 {in "%f"; out "|%f|%10f|%.2f|%- 10.5f|% f|%+f|%-5.1f|%#f|"; } 36 | test2 {in "%6f%(DESC)s"; out "|%g|%(DESC)s|"; } 37 | test3 {in "% 6f%(DESC)s"; out "|%g|%(DESC)s|"; } 38 | test4 {in "%#f"; out "%f"; } 39 | } 40 | 41 | set startup { 42 | } 43 | 44 | startioc 45 | 46 | set inf [format %f inf] 47 | if [catch {set nan [format %f nan]}] {set nan nan} 48 | 49 | process DZ:test1 50 | send "3.14159265359\n" 51 | assure "|3.141593| 3.141593|3.14| 3.14159 | 3.141593|+3.141593|3.1 |3.141593|\n" 52 | process DZ:test1 53 | send "-3.14159265359\n" 54 | assure "|-3.141593| -3.141593|-3.14|-3.14159 |-3.141593|-3.141593|-3.1 |-3.141593|\n" 55 | process DZ:test1 56 | send "0\n" 57 | assure "|0.000000| 0.000000|0.00| 0.00000 | 0.000000|+0.000000|0.0 |0.000000|\n" 58 | process DZ:test1 59 | send "NAN\n" 60 | assure "|$nan| $nan|$nan| $nan | $nan|+$nan|$nan |$nan|\n" 61 | process DZ:test1 62 | send "-Inf\n" 63 | assure "|-$inf| -$inf|-$inf|-$inf |-$inf|-$inf|-$inf |-$inf|\n" 64 | process DZ:test1 65 | send "1e6\n" 66 | assure "|1000000.000000|1000000.000000|1000000.00| 1000000.00000| 1000000.000000|+1000000.000000|1000000.0|1000000.000000|\n" 67 | process DZ:test1 68 | send " - 3.14159265359\n" 69 | assure "mismatch\n" 70 | process DZ:test1 71 | send "bla\n" 72 | assure "mismatch\n" 73 | process DZ:test1 74 | send " bla\n" 75 | assure "mismatch\n" 76 | process DZ:test1 77 | send "-bla\n" 78 | assure "mismatch\n" 79 | 80 | process DZ:test2 81 | send "3.14159265359\n" 82 | assure "|3.1415|9265359|\n" 83 | process DZ:test2 84 | send " 3.14159265359\n" 85 | assure "|3.1415|9265359|\n" 86 | process DZ:test2 87 | send " 10blabla\n" 88 | assure "|10|blabla|\n" 89 | process DZ:test2 90 | send " 1\n" 91 | assure "|1||\n" 92 | 93 | process DZ:test3 94 | send "3.14159265359\n" 95 | assure "|3.1415|9265359|\n" 96 | process DZ:test3 97 | send " 3.14159265359\n" 98 | assure "|3|.14159265359|\n" 99 | process DZ:test3 100 | send " 10blabla\n" 101 | assure "|10|blabla|\n" 102 | process DZ:test3 103 | send " 1\n" 104 | assure "|1||\n" 105 | 106 | process DZ:test4 107 | send "3.14159265359\n" 108 | assure "3.141593\n" 109 | process DZ:test4 110 | send " -3.14159265359\n" 111 | assure "-3.141593\n" 112 | process DZ:test4 113 | send " - 3.14159265359\n" 114 | assure "-3.141593\n" 115 | process DZ:test4 116 | send " + 3.14159265359\n" 117 | assure "3.141593\n" 118 | process DZ:test4 119 | send " +- 3.14159265359\n" 120 | assure "mismatch\n" 121 | 122 | finish 123 | -------------------------------------------------------------------------------- /streamApp/tests/testEnum: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (longout, "DZ:testout") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto out device") 14 | } 15 | record (longin, "DZ:testin") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto in device") 19 | } 20 | record (longout, "DZ:testout1") 21 | { 22 | field (DTYP, "stream") 23 | field (OUT, "@test.proto out1 device") 24 | } 25 | record (longin, "DZ:testin1") 26 | { 27 | field (DTYP, "stream") 28 | field (INP, "@test.proto in1 device") 29 | } 30 | record (longout, "DZ:testout2") 31 | { 32 | field (DTYP, "stream") 33 | field (OUT, "@test.proto out2 device") 34 | } 35 | record (longin, "DZ:testin2") 36 | { 37 | field (DTYP, "stream") 38 | field (INP, "@test.proto in2 device") 39 | } 40 | record (longin, "DZ:testin3") 41 | { 42 | field (DTYP, "stream") 43 | field (INP, "@test.proto in3 device") 44 | } 45 | } 46 | 47 | set protocol { 48 | Terminator = LF; 49 | out {out "%{zero|one|two}bla";} 50 | in {in "%{zero|one|two}bla"; out "%d";} 51 | out1 {out "%#{zero|one|two}bla";} 52 | in1 {in "%#{zero|one|two}bla"; out "%d";} 53 | out2 {out "%#{zero=-1|one|two=5|default=?}bla";} 54 | in2 {in "%#{zero=-1|one|two=5}bla"; out "%d";} 55 | in3 {in "%{\x00|\r|}bla"; out "%d";} 56 | } 57 | 58 | set startup { 59 | var streamDebug 1 60 | } 61 | 62 | set debug 0 63 | 64 | startioc 65 | 66 | put DZ:testout 0 67 | assure "zerobla\n" 68 | put DZ:testout 1 69 | assure "onebla\n" 70 | put DZ:testout 2 71 | assure "twobla\n" 72 | put DZ:testout1 0 73 | assure "zerobla\n" 74 | put DZ:testout1 1 75 | assure "onebla\n" 76 | put DZ:testout1 2 77 | assure "twobla\n" 78 | put DZ:testout2 -1 79 | assure "zerobla\n" 80 | put DZ:testout2 0 81 | assure "onebla\n" 82 | put DZ:testout2 5 83 | assure "twobla\n" 84 | put DZ:testout2 17 85 | assure "defaultbla\n" 86 | 87 | process DZ:testin 88 | send "zerobla\n" 89 | assure "0\n" 90 | process DZ:testin 91 | send "onebla\n" 92 | assure "1\n" 93 | process DZ:testin 94 | send "twobla\n" 95 | assure "2\n" 96 | process DZ:testin1 97 | send "zerobla\n" 98 | assure "0\n" 99 | process DZ:testin1 100 | send "onebla\n" 101 | assure "1\n" 102 | process DZ:testin1 103 | send "twobla\n" 104 | assure "2\n" 105 | process DZ:testin2 106 | send "zerobla\n" 107 | assure "-1\n" 108 | process DZ:testin2 109 | send "onebla\n" 110 | assure "0\n" 111 | process DZ:testin2 112 | send "twobla\n" 113 | assure "5\n" 114 | 115 | process DZ:testin3 116 | send "\000bla\n" 117 | assure "0\n" 118 | process DZ:testin3 119 | send "\rbla\n" 120 | assure "1\n" 121 | process DZ:testin3 122 | send "bla\n" 123 | assure "2\n" 124 | 125 | 126 | finish 127 | -------------------------------------------------------------------------------- /streamApp/tests/testFormatm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ao, "DZ:ao") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto ao device") 14 | } 15 | record (ai, "DZ:ai") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto ai device") 19 | } 20 | } 21 | 22 | set protocol { 23 | Terminator = LF; 24 | ao {out "'%m' '%.4m' '%+.4m' '% .4m' '% +.4m' '%10.4m' '%-10.4m'";} 25 | ai {out "?"; in "%m"; out "%.4e";} 26 | } 27 | 28 | set startup { 29 | } 30 | 31 | set debug 0 32 | 33 | startioc 34 | 35 | put DZ:ao 0 36 | assure "'000000+00' '0000+00' '+0000+00' ' 0000+00' '+0000+00' ' 0000+00' '0000+00 '\n" 37 | put DZ:ao 1 38 | assure "'100000-05' '1000-03' '+1000-03' ' 1000-03' '+1000-03' ' 1000-03' '1000-03 '\n" 39 | put DZ:ao 1000 40 | assure "'100000-02' '1000+00' '+1000+00' ' 1000+00' '+1000+00' ' 1000+00' '1000+00 '\n" 41 | put DZ:ao 1000000 42 | assure "'100000+01' '1000+03' '+1000+03' ' 1000+03' '+1000+03' ' 1000+03' '1000+03 '\n" 43 | put DZ:ao -1 44 | assure "'-100000-05' '-1000-03' '-1000-03' '-1000-03' '-1000-03' ' -1000-03' '-1000-03 '\n" 45 | put DZ:ao 12345 46 | assure "'123450-01' '1235+01' '+1235+01' ' 1235+01' '+1235+01' ' 1235+01' '1235+01 '\n" 47 | put DZ:ao -1.2345e-15 48 | assure "'-123450-20' '-1235-18' '-1235-18' '-1235-18' '-1235-18' ' -1235-18' '-1235-18 '\n" 49 | put DZ:ao 1e-100 50 | assure "'100000-105' '1000-103' '+1000-103' ' 1000-103' '+1000-103' ' 1000-103' '1000-103 '\n" 51 | process DZ:ai 52 | assure "?\n" 53 | send "+1234+56\n" 54 | assure "1.2340e+59\n" 55 | process DZ:ai 56 | assure "?\n" 57 | send "-1234-56\n" 58 | assure "-1.2340e-53\n" 59 | process DZ:ai 60 | assure "?\n" 61 | send "-12340000-60\n" 62 | assure "-1.2340e-53\n" 63 | process DZ:ai 64 | assure "?\n" 65 | send "+00000000+0\n" 66 | assure "0.0000e+00\n" 67 | finish 68 | -------------------------------------------------------------------------------- /streamApp/tests/testHalfInputTerminator: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = CR LF; 19 | test1 {out "Give input"; in "%s"; out "%s"; } 20 | } 21 | 22 | set startup { 23 | } 24 | 25 | set debug 0 26 | 27 | startioc 28 | 29 | process DZ:test1 30 | assure "Give input\r\n" 31 | send "abc\r\n" 32 | assure "abc\r\n" 33 | 34 | process DZ:test1 35 | assure "Give input\r\n" 36 | send "x\r\n" 37 | assure "x\r\n" 38 | 39 | process DZ:test1 40 | assure "Give input\r\n" 41 | send "\r\n" 42 | assure "\r\n" 43 | 44 | finish 45 | -------------------------------------------------------------------------------- /streamApp/tests/testIoIntrPollTimeout: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (bo, "DZ:ready") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto ready device") 14 | field (PINI, "YES") 15 | } 16 | record (longin, "DZ:read") 17 | { 18 | field (DTYP, "stream") 19 | field (INP, "@test.proto readintr device") 20 | field (SCAN, "I/O Intr") 21 | field (FLNK, "DZ:count") 22 | } 23 | record (calc, "DZ:count") 24 | { 25 | field (INPA, "DZ:count") 26 | field (CALC, "A+1") 27 | field (FLNK, "DZ:errorcount") 28 | } 29 | record (calc, "DZ:errorcount") 30 | { 31 | field (INPA, "DZ:errorcount") 32 | field (INPB, "DZ:read") 33 | field (INPC, "DZ:count") 34 | field (CALC, "A+(B#C)") 35 | } 36 | record (longout, "DZ:printresult") 37 | { 38 | field (DTYP, "stream") 39 | field (DOL, "DZ:read") 40 | field (OMSL, "closed_loop") 41 | field (OUT, "@test.proto printresult device") 42 | } 43 | } 44 | 45 | set protocol { 46 | Terminator = LF; 47 | PollPeriod=10; 48 | ReadTimeout=50; 49 | ready {out "ready"; } 50 | readintr {in "This is a line in chunks with number %d"; } 51 | printresult {out "Last line received: %d"; 52 | out "Line count: %(DZ:count)d"; 53 | out "Error count: %(DZ:errorcount)d"; } 54 | } 55 | 56 | set startup { 57 | } 58 | 59 | set debug 0 60 | 61 | startioc 62 | 63 | set rep 10 64 | 65 | assure "ready\n" 66 | for {set i 1} {$i <= $rep} {incr i} { 67 | send "This " 68 | after 10 69 | send "is a " 70 | after 10 71 | send "line in chunks " 72 | after 10 73 | send "with number $i\n" 74 | after 100 75 | } 76 | process DZ:printresult 77 | assure "Last line received: $rep\n" 78 | assure "Line count: $rep\n" 79 | assure "Error count: 0\n" 80 | finish 81 | 82 | -------------------------------------------------------------------------------- /streamApp/tests/testLongInputTerminator: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | InTerminator = CR CR CR; 19 | OutTerminator = LF; 20 | test1 {out "Give input"; in "%39c"; out "%s"; } 21 | } 22 | 23 | set startup { 24 | } 25 | 26 | set debug 0 27 | 28 | startioc 29 | 30 | process DZ:test1 31 | assure "Give input\n" 32 | send "abc\r\r\r" 33 | assure "abc\n" 34 | 35 | process DZ:test1 36 | assure "Give input\n" 37 | send "klm\rxyz\r\r\r" 38 | assure "klm\rxyz\n" 39 | 40 | process DZ:test1 41 | assure "Give input\n" 42 | send "123\r\rxyz\r\r\r" 43 | assure "123\r\rxyz\n" 44 | 45 | finish 46 | -------------------------------------------------------------------------------- /streamApp/tests/testLongUnsolicitedInput: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (bo, "DZ:ready") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto ready device") 14 | field (PINI, "YES") 15 | } 16 | record (stringin, "DZ:read") 17 | { 18 | field (DTYP, "stream") 19 | field (INP, "@test.proto readintr device") 20 | field (SCAN, "I/O Intr") 21 | field (FLNK, "DZ:count") 22 | } 23 | record (calc, "DZ:count") 24 | { 25 | field (INPA, "DZ:count") 26 | field (CALC, "A+1") 27 | } 28 | record (longout, "DZ:countout") 29 | { 30 | field (DTYP, "stream") 31 | field (DOL, "DZ:count") 32 | field (OMSL, "closed_loop") 33 | field (OUT, "@test.proto printnum device") 34 | } 35 | record (stringout, "DZ:stringout") 36 | { 37 | field (DTYP, "stream") 38 | field (DOL, "DZ:read") 39 | field (OMSL, "closed_loop") 40 | field (OUT, "@test.proto printstr device") 41 | } 42 | } 43 | 44 | set protocol { 45 | Terminator = LF; 46 | ready {out "ready"; } 47 | readintr {extraInput=ignore; in "%39c"; } 48 | printnum {out "%d";} 49 | printstr {out "%s";} 50 | } 51 | 52 | set startup { 53 | var streamDebug 1 54 | } 55 | 56 | set debug 0 57 | set rep 500 58 | 59 | startioc 60 | 61 | assure "ready\n" 62 | after 1000 63 | for {set i 1} {$i <= $rep} {incr i} { 64 | append output "This is line $i.\n" 65 | } 66 | send $output 67 | after 2000 68 | process DZ:stringout 69 | assure "This is line $rep.\n" 70 | process DZ:countout 71 | assure "$rep\n" 72 | 73 | finish 74 | -------------------------------------------------------------------------------- /streamApp/tests/testOutTerminators: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringout, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | record (stringout, "DZ:test2") 16 | { 17 | field (DTYP, "stream") 18 | field (OUT, "@test.proto test2 device") 19 | } 20 | } 21 | 22 | set protocol { 23 | test1 {out "%s";} 24 | Terminator = "S" CR LF; 25 | test2 { out "%s";} 26 | } 27 | 28 | set startup { 29 | asynOctetSetOutputEos device -1 "A\n" 30 | } 31 | 32 | set debug 0 33 | 34 | startioc 35 | put DZ:test1 "string 1" 36 | assure "string 1A\n" 37 | put DZ:test2 "string 2" 38 | assure "string 2S\r\n" 39 | 40 | finish 41 | -------------------------------------------------------------------------------- /streamApp/tests/testPINI: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | foreach rtype {ao bo mbbo mbboDirect longout stringout calcout} { 10 | append records " 11 | record ($rtype, \"DZ:$rtype\") 12 | { 13 | field (DTYP, \"stream\") 14 | field (OUT, \"@test.proto init($rtype) device\") 15 | field (PINI, \"YES\") 16 | field (VAL, \"0\") 17 | } 18 | " 19 | } 20 | foreach rtype {ai bi mbbi mbbiDirect longin stringin waveform} { 21 | append records " 22 | record ($rtype, \"DZ:$rtype\") 23 | { 24 | field (DTYP, \"stream\") 25 | field (INP, \"@test.proto init($rtype) device\") 26 | field (PINI, \"YES\") 27 | } 28 | " 29 | } 30 | 31 | set protocol { 32 | Terminator = LF; 33 | init {out "init \$1"; } 34 | } 35 | 36 | set startup { 37 | } 38 | 39 | set debug 0 40 | 41 | startioc 42 | assure "init ao\n" \ 43 | "init bo\n" \ 44 | "init mbbo\n" \ 45 | "init mbboDirect\n" \ 46 | "init longout\n" \ 47 | "init stringout\n" \ 48 | "init ai\n" \ 49 | "init bi\n" \ 50 | "init mbbi\n" \ 51 | "init mbbiDirect\n" \ 52 | "init longin\n" \ 53 | "init stringin\n" \ 54 | "init calcout\n" \ 55 | "init waveform\n" \ 56 | 57 | finish 58 | -------------------------------------------------------------------------------- /streamApp/tests/testParallelAccess: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ao, "DZ:slow") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto slow device") 14 | } 15 | record (ao, "DZ:fast") 16 | { 17 | field (DTYP, "stream") 18 | field (OUT, "@test.proto fast device") 19 | } 20 | } 21 | 22 | set protocol { 23 | Terminator = LF; 24 | slow { out "slow start"; wait 1000; out "slow finished";} 25 | fast { out "fast"; } 26 | } 27 | 28 | set startup { 29 | } 30 | 31 | set debug 0 32 | 33 | startioc 34 | 35 | put DZ:slow 1 36 | put DZ:fast 1 37 | assure "slow start\n" 38 | assure "slow finished\n" 39 | assure "fast\n" 40 | 41 | finish 42 | -------------------------------------------------------------------------------- /streamApp/tests/testParenthesesInParameters: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record(ao, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1(ARG(10),20,30) device") 14 | } 15 | 16 | record(ao, "DZ:test2") 17 | { 18 | field (DTYP, "stream") 19 | field (OUT, "@test.proto test1 (ARG(10,20), 30) device") 20 | } 21 | record(ao, "DZ:test3") 22 | { 23 | field (DTYP, "stream") 24 | field (OUT, "@test.proto test1 ( ARG ( 10 , 20 ) , 30 ) device") 25 | } 26 | record(ao, "DZ:test4") 27 | { 28 | field (DTYP, "stream") 29 | field (OUT, "@test.proto test1( ARG \\( 10 , 20 , 30 ) device") 30 | } 31 | record(ao, "DZ:test5") 32 | { 33 | field (DTYP, "stream") 34 | field (OUT, "@test.proto test1(\\ ARG\\,\\\\(10,20)\\,30) device") 35 | } 36 | } 37 | 38 | set protocol { 39 | Terminator = LF; 40 | test1 { out "VAL:\$1:%d"} 41 | } 42 | 43 | set startup { 44 | } 45 | 46 | set debug 0 47 | 48 | startioc 49 | 50 | put DZ:test1 "1" 51 | assure "VAL:ARG(10):1\n" 52 | put DZ:test2 "1" 53 | assure "VAL:ARG(10,20):1\n" 54 | put DZ:test3 "1" 55 | assure "VAL:ARG ( 10 , 20 ):1\n" 56 | put DZ:test4 "1" 57 | assure "VAL: ARG ( 10 :1\n" 58 | put DZ:test5 "1" 59 | assure "VAL: ARG,\\(10,20),30:1\n" 60 | 61 | #finish 62 | -------------------------------------------------------------------------------- /streamApp/tests/testPercent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (longout, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = LF; 19 | test1 {out "\%\e%d%%\e\e\%";} 20 | } 21 | 22 | set startup { 23 | var streamDebug 1 24 | } 25 | 26 | set debug 0 27 | 28 | startioc 29 | 30 | put DZ:test1 1 31 | assure "%\0331%\033\033%\n" 32 | 33 | finish 34 | -------------------------------------------------------------------------------- /streamApp/tests/testPerformance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (waveform, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (FTVL, "DOUBLE") 14 | field (NELM, "1048576") 15 | field (INP, "@test.proto test1 device") 16 | } 17 | record (waveform, "DZ:test2") 18 | { 19 | field (DTYP, "stream") 20 | field (FTVL, "LONG") 21 | field (NELM, "1048576") 22 | field (INP, "@test.proto test2 device") 23 | } 24 | record (waveform, "DZ:test3") 25 | { 26 | field (DTYP, "stream") 27 | field (FTVL, "STRING") 28 | field (NELM, "1048576") 29 | field (INP, "@test.proto test3 device") 30 | } 31 | } 32 | 33 | set protocol { 34 | replyTimeout =600000; 35 | Terminator = LF; 36 | Separator = " "; 37 | test1 {in "%f"; out "%(NORD)d";} 38 | test2 {in "%i"; out "%(NORD)d";} 39 | test3 {in "%s"; out "%(NORD)d";} 40 | } 41 | 42 | set startup { 43 | } 44 | 45 | set debug 0 46 | 47 | set message "314156" 48 | set size 1 49 | set timeout 600000 50 | set type(1) "double" 51 | set type(2) "long " 52 | set type(3) "string" 53 | 54 | startioc 55 | send "$message\n" 56 | process DZ:test1 57 | assure "$size\n" 58 | send "$message\n" 59 | process DZ:test2 60 | assure "$size\n" 61 | send "$message\n" 62 | process DZ:test3 63 | assure "$size\n" 64 | 65 | ioccmd {var streamDebug 0} 66 | for {set log 1} {$log <= 21} {incr log} { 67 | foreach n { 1 2 3 } { 68 | send "$message\n" 69 | 70 | # make sure all output is available before we start 71 | after 100 72 | 73 | set starttime [clock clicks] 74 | process DZ:test$n 75 | assure "$size\n" 76 | set duration [expr [clock clicks] - $starttime] 77 | 78 | set performance($size) [expr $duration*1.0/$size] 79 | puts [format "%7d %s %9d ticks %9.2f ticks/element" $size $type($n) $duration $performance($size)] 80 | if {$performance($size) > $performance(1)} {incr faults} 81 | } 82 | set message "$message $message" 83 | set size [expr $size*2] 84 | } 85 | 86 | finish 87 | -------------------------------------------------------------------------------- /streamApp/tests/testQuotes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringout, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = LF; 19 | test1 { 20 | out "Escaped \"double\" quotes"; 21 | out 'Escaped \'single\' quotes'; 22 | out "Single 'quotes' in double quotes"; 23 | out 'Double "quotes" in single quotes'; } 24 | } 25 | 26 | set startup { 27 | var streamDebug 1 28 | } 29 | 30 | set debug 0 31 | 32 | startioc 33 | 34 | put DZ:test1 "X" 35 | assure "Escaped \"double\" quotes\n" 36 | assure "Escaped 'single' quotes\n" 37 | assure "Single 'quotes' in double quotes\n" 38 | assure "Double \"quotes\" in single quotes\n" 39 | 40 | finish 41 | -------------------------------------------------------------------------------- /streamApp/tests/testRawFloat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (ao, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = LF; 19 | test1 {out "%R"; out "%#R"; out "%4R"; out "%#4R"; out "%8R"; out "%#8R";} 20 | } 21 | 22 | set startup { 23 | } 24 | 25 | set debug 0 26 | 27 | startioc 28 | 29 | put DZ:test1 "0" 30 | assure "\x00\x00\x00\x00\n" 31 | assure "\x00\x00\x00\x00\n" 32 | assure "\x00\x00\x00\x00\n" 33 | assure "\x00\x00\x00\x00\n" 34 | assure "\x00\x00\x00\x00\x00\x00\x00\x00\n" 35 | assure "\x00\x00\x00\x00\x00\x00\x00\x00\n" 36 | 37 | put DZ:test1 "1" 38 | assure "\x3f\x80\x00\x00\n" 39 | assure "\x00\x00\x80\x3f\n" 40 | assure "\x3f\x80\x00\x00\n" 41 | assure "\x00\x00\x80\x3f\n" 42 | assure "\x3f\xf0\x00\x00\x00\x00\x00\x00\n" 43 | assure "\x00\x00\x00\x00\x00\x00\xf0\x3f\n" 44 | 45 | put DZ:test1 "-1" 46 | assure "\xbf\x80\x00\x00\n" 47 | assure "\x00\x00\x80\xbf\n" 48 | assure "\xbf\x80\x00\x00\n" 49 | assure "\x00\x00\x80\xbf\n" 50 | assure "\xbf\xf0\x00\x00\x00\x00\x00\x00\n" 51 | assure "\x00\x00\x00\x00\x00\x00\xf0\xbf\n" 52 | 53 | put DZ:test1 "3.1415" 54 | assure "\x40\x49\x0e\x56\n" 55 | assure "\x56\x0e\x49\x40\n" 56 | assure "\x40\x49\x0e\x56\n" 57 | assure "\x56\x0e\x49\x40\n" 58 | assure "\x40\x09\x21\xca\xc0\x83\x12\x6f\n" 59 | assure "\x6f\x12\x83\xc0\xca\x21\x09\x40\n" 60 | 61 | finish 62 | -------------------------------------------------------------------------------- /streamApp/tests/testSeverityAndStatus: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:readTimeout") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto read device") 14 | } 15 | record (bo, "DZ:echo") 16 | { 17 | field (DTYP, "stream") 18 | field (OUT, "@test.proto print(DZ:readTimeout) device") 19 | } 20 | } 21 | 22 | set protocol { 23 | Terminator = LF; 24 | read {out "Give me input"; in "%s";} 25 | print {out "Text:'%(\$1.VAL)s' SEVR=%(\$1.SEVR)d STAT=%(\$1.STAT)d";} 26 | } 27 | 28 | set startup { 29 | } 30 | 31 | set debug 0 32 | 33 | startioc 34 | 35 | # reply timeout 36 | process DZ:readTimeout 37 | assure "Give me input\n" 38 | after 1100 39 | process DZ:echo 40 | ioccmd {dbpr DZ:echo 1} 41 | assure "Text:'' SEVR=3 STAT=10\n" 42 | 43 | # read timeout 44 | process DZ:readTimeout 45 | assure "Give me input\n" 46 | send "Trulala" 47 | after 200 48 | process DZ:echo 49 | assure "Text:'Trulala' SEVR=3 STAT=1\n" 50 | 51 | # reply timeout again, old input stays 52 | process DZ:readTimeout 53 | assure "Give me input\n" 54 | after 1100 55 | process DZ:echo 56 | assure "Text:'Trulala' SEVR=3 STAT=10\n" 57 | 58 | # mismatch, partially parsed 59 | process DZ:readTimeout 60 | assure "Give me input\n" 61 | send "bla extra\n" 62 | after 200 63 | process DZ:echo 64 | assure "Text:'bla' SEVR=3 STAT=12\n" 65 | 66 | # success 67 | process DZ:readTimeout 68 | assure "Give me input\n" 69 | send "Input\n" 70 | after 200 71 | process DZ:echo 72 | assure "Text:'Input' SEVR=0 STAT=0\n" 73 | 74 | 75 | 76 | finish 77 | -------------------------------------------------------------------------------- /streamApp/tests/testSkeleton: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringout, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator = LF; 19 | test1 {out "%s";} 20 | } 21 | 22 | set startup { 23 | } 24 | 25 | set debug 0 26 | 27 | startioc 28 | 29 | put DZ:test1 "string 1" 30 | assure "string 1\n" 31 | 32 | finish 33 | -------------------------------------------------------------------------------- /streamApp/tests/testSpyOnLongInput: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:request") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto read device") 14 | } 15 | record (stringout, "DZ:echo") 16 | { 17 | field (DTYP, "stream") 18 | field (DOL, "DZ:request") 19 | field (OMSL, "closed_loop") 20 | field (OUT, "@test.proto printstr device") 21 | } 22 | record (stringin, "DZ:spy") 23 | { 24 | field (DTYP, "stream") 25 | field (INP, "@test.proto readintr device") 26 | field (SCAN, "I/O Intr") 27 | field (FLNK, "DZ:count") 28 | } 29 | record (calc, "DZ:count") 30 | { 31 | field (INPA, "DZ:count") 32 | field (CALC, "A+1") 33 | } 34 | record (longout, "DZ:countout") 35 | { 36 | field (DTYP, "stream") 37 | field (DOL, "DZ:count") 38 | field (OMSL, "closed_loop") 39 | field (OUT, "@test.proto printnum device") 40 | } 41 | record (stringout, "DZ:stringout") 42 | { 43 | field (DTYP, "stream") 44 | field (DOL, "DZ:spy") 45 | field (OMSL, "closed_loop") 46 | field (OUT, "@test.proto printstr device") 47 | } 48 | } 49 | 50 | set protocol { 51 | Terminator = LF; 52 | read {extraInput=ignore; InTerminator = ""; out "Give input"; in "%/.*253.*/"; } 53 | readintr {extraInput=ignore; in "%39c"; } 54 | printnum {out "%d";} 55 | printstr {out "%s";} 56 | } 57 | 58 | set startup { 59 | var streamDebug 1 60 | } 61 | 62 | set debug 0 63 | set rep 500 64 | 65 | startioc 66 | 67 | process DZ:request 68 | assure "Give input\n" 69 | for {set i 1} {$i <= $rep} {incr i} { 70 | append output "This is line $i.\n" 71 | } 72 | send $output 73 | after 2000 74 | process DZ:echo 75 | assure "This is line 253.\n" 76 | process DZ:stringout 77 | assure "This is line $rep.\n" 78 | process DZ:countout 79 | assure "$rep\n" 80 | 81 | finish 82 | -------------------------------------------------------------------------------- /streamApp/tests/testStrangesum: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringout, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (OUT, "@test.proto test1 device") 14 | } 15 | } 16 | 17 | set protocol { 18 | Terminator="\r\n"; 19 | test1 { 20 | out ":%s%01<-hexsum8>"; 21 | } 22 | } 23 | 24 | set startup { 25 | } 26 | 27 | set debug 0 28 | 29 | startioc 30 | put DZ:test1 "010304010001" 31 | assure ":010304010001F6\r\n" 32 | 33 | finish 34 | -------------------------------------------------------------------------------- /streamApp/tests/testStreamBuffer: -------------------------------------------------------------------------------- 1 | rm -f test.* 2 | 3 | cat > test.cc << EOF 4 | #include 5 | #include 6 | #include 7 | #include 8 | int main () { 9 | StreamBuffer haystack = "12345abc123xyz123"; 10 | StreamBuffer needle = "1n4m6p7q"; 11 | needle.remove(2,4); 12 | assert (needle.startswith("1n7q")); 13 | needle.append("2x3y"); 14 | assert (needle.startswith("1n7q2x3y")); 15 | needle.remove(4); 16 | assert (needle.startswith("2x3y")); 17 | needle.remove(1,1); 18 | assert (needle.startswith("23y")); 19 | needle.truncate(-1); 20 | assert (needle.startswith("23")); 21 | assert (haystack.find(needle) == 1); 22 | assert (haystack.find(needle, 2) == 9); 23 | assert (haystack.find(needle, -5) == 15); 24 | assert (haystack.find("23", -5) == 15); 25 | assert (haystack.find((char*)NULL, 10) == 10); 26 | assert (haystack.find(needle, -1) == -1); 27 | assert (haystack.find(needle, 100) == -1); 28 | assert (haystack.find(needle, 0) == 1); 29 | assert (haystack.find(needle, -100) == 1); 30 | haystack.set("12345xy67890xy"); 31 | needle.set("xy"); 32 | assert (haystack.find(needle) == 5); 33 | needle.set("x"); 34 | assert (haystack.find(needle) == 5); 35 | haystack.set("12345\n67890\n"); 36 | needle.set("\n"); 37 | assert (haystack.find(needle) == 5); 38 | haystack.set("12341234567890\n"); 39 | needle.set("2345"); 40 | assert (haystack.find(needle) == 5); 41 | needle="7890"; 42 | assert (haystack.find(needle) == 10); 43 | needle.append('\0'); 44 | assert (haystack.find(needle) == -1); 45 | haystack.clear(); 46 | assert (haystack.find(needle) == -1); 47 | haystack.set("deadbeef"); 48 | needle.clear(); 49 | assert (haystack.find(needle) == 0); 50 | haystack.clear(); 51 | assert (haystack.find(needle) == 0); 52 | haystack.reserve(10000); 53 | return 0; 54 | } 55 | EOF 56 | 57 | if [ "$1" = "-sls" ] 58 | then 59 | O=../../O.*_$EPICS_HOST_ARCH 60 | else 61 | O=../../src/O.$EPICS_HOST_ARCH 62 | fi 63 | 64 | for o in $O 65 | do 66 | g++ -I ../../src $o/StreamBuffer.o $o/StreamError.o test.cc -o test.exe 67 | ./test.exe 68 | if [ $? != 0 ] 69 | then 70 | echo -e "\033[31;7mTest failed.\033[0m" 71 | exit 1 72 | fi 73 | done 74 | rm test.* 75 | echo -e "\033[32mTest passed.\033[0m" 76 | -------------------------------------------------------------------------------- /streamApp/tests/testString: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | record (stringin, "DZ:test1") 11 | { 12 | field (DTYP, "stream") 13 | field (INP, "@test.proto test1 device") 14 | } 15 | record (stringin, "DZ:test2") 16 | { 17 | field (DTYP, "stream") 18 | field (INP, "@test.proto test2 device") 19 | } 20 | record (stringin, "DZ:test3") 21 | { 22 | field (DTYP, "stream") 23 | field (INP, "@test.proto test3 device") 24 | } 25 | record (stringin, "DZ:test4") 26 | { 27 | field (DTYP, "stream") 28 | field (INP, "@test.proto test4 device") 29 | } 30 | record (stringin, "DZ:test5") 31 | { 32 | field (DTYP, "stream") 33 | field (INP, "@test.proto test5 device") 34 | } 35 | } 36 | 37 | set protocol { 38 | Terminator = LF; 39 | extraInput=ignore; 40 | @mismatch {out "mismatch";} 41 | test1 {in "%s%(DESC) #s"; out "%s|%(DESC)s" } 42 | test2 {in "% s%(DESC) #s"; out "%s|%(DESC)s" } 43 | test3 {in "%#s%(DESC) #s"; out "%s|%(DESC)s" } 44 | test4 {in "%# s%(DESC) #s"; out "%s|%(DESC)s" } 45 | test5 {in "% #s%(DESC) #s"; out "%s|%(DESC)s" } 46 | } 47 | 48 | set startup { 49 | } 50 | 51 | set debug 0 52 | 53 | startioc 54 | 55 | process DZ:test1 56 | send "foobar\n" 57 | assure "foobar|\n" 58 | process DZ:test1 59 | send " foobar \n" 60 | assure "foobar| \n" 61 | process DZ:test1 62 | send " foo bar \n" 63 | assure "foo| bar \n" 64 | process DZ:test1 65 | send " \n" 66 | assure "|\n" 67 | process DZ:test1 68 | send "ThisIsAVeryLongInputStringThatExceedsFouryCharacters right?\n" 69 | assure "ThisIsAVeryLongInputStringThatExceedsFo| right?\n" 70 | 71 | process DZ:test2 72 | send "foobar\n" 73 | assure "foobar|\n" 74 | process DZ:test2 75 | send " foobar \n" 76 | assure " foobar| \n" 77 | process DZ:test2 78 | send " foo bar \n" 79 | assure " foo| bar \n" 80 | process DZ:test2 81 | send " \n" 82 | assure " |\n" 83 | 84 | process DZ:test3 85 | send "foobar\n" 86 | assure "foobar|\n" 87 | process DZ:test3 88 | send " foobar \n" 89 | assure "foobar |\n" 90 | process DZ:test3 91 | send " foo bar \n" 92 | assure "foo bar |\n" 93 | process DZ:test3 94 | send " \n" 95 | assure "|\n" 96 | 97 | process DZ:test4 98 | send "foobar\n" 99 | assure "foobar|\n" 100 | process DZ:test4 101 | send " foobar \n" 102 | assure " foobar |\n" 103 | process DZ:test4 104 | send " foo bar \n" 105 | assure " foo bar |\n" 106 | process DZ:test4 107 | send " \n" 108 | assure " |\n" 109 | 110 | process DZ:test5 111 | send "foobar\n" 112 | assure "foobar|\n" 113 | process DZ:test5 114 | send " foobar \n" 115 | assure " foobar |\n" 116 | process DZ:test5 117 | send " foo bar \n" 118 | assure " foo bar |\n" 119 | process DZ:test5 120 | send " \n" 121 | assure " |\n" 122 | 123 | finish 124 | 125 | -------------------------------------------------------------------------------- /streamApp/tests/testWaage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | source streamtestlib.tcl 3 | 4 | # Define records, protocol and startup (text goes to files) 5 | # The asynPort "device" is connected to a network TCP socket 6 | # Talk to the socket with send/receive/assure 7 | # Send commands to the ioc shell with ioccmd 8 | 9 | set records { 10 | 11 | record (bi, "DZ:sign") 12 | { 13 | field (DTYP, "stream") 14 | field (INP, "@test.proto m(DZ:weight.A) device") 15 | } 16 | 17 | record (calc, "DZ:weight") 18 | { 19 | field (INPB, "DZ:sign") 20 | field (CALC, "B?A:-A") 21 | field (FLNK, "DZ:out") 22 | } 23 | 24 | record (ao, "DZ:out") 25 | { 26 | field (DTYP, "stream") 27 | field (DOL, "DZ:weight") 28 | field (OMSL, "closed_loop") 29 | field (OUT, "@test.proto out device") 30 | } 31 | } 32 | 33 | set protocol { 34 | Terminator = LF; 35 | m {out "w"; in "%*/ */%{-|}%(\$1)f Kg";} 36 | out {out "%.2f";} 37 | } 38 | 39 | set startup { 40 | } 41 | 42 | set debug 0 43 | 44 | startioc 45 | 46 | process DZ:sign 47 | assure "w\n" 48 | send " - 15.20 Kg\n" 49 | assure "-15.20\n" 50 | 51 | process DZ:sign 52 | assure "w\n" 53 | send " 15.00 Kg\n" 54 | assure "15.00\n" 55 | 56 | finish 57 | -------------------------------------------------------------------------------- /streamApp/tests/testall: -------------------------------------------------------------------------------- 1 | rm -f test.* *.out *.ioclog StreamDebug.log 2 | for i in test* 3 | do 4 | if [ $i != testall -a -x $i ] 5 | then 6 | echo $i "$@" 7 | if ! ./$i "$@" 8 | then 9 | echo -e "\033[31;7m$i failed.\033[0m" 10 | (( fail+=1 )) 11 | fi 12 | fi 13 | done 14 | 15 | if [ "$fail" ] 16 | then echo -e "\033[31;7m$fail tests failed\033[0m" 17 | else echo -e "\033[32;7mAll tests passed.\033[0m" 18 | fi 19 | exit $fail 20 | --------------------------------------------------------------------------------