diff --git a/site_ansto/docs/Copyright.txt b/site_ansto/docs/Copyright.txt new file mode 100644 index 00000000..67894671 --- /dev/null +++ b/site_ansto/docs/Copyright.txt @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + + Copyright: + + ANSTO Bragg Institute + New Illawarra Road + Lucas Heights NSW 2234 + Australia + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +-----------------------------------------------------------------------------*/ diff --git a/site_ansto/docs/sics_site.Doxyfile b/site_ansto/docs/sics_site.Doxyfile new file mode 100644 index 00000000..7585f8e5 --- /dev/null +++ b/site_ansto/docs/sics_site.Doxyfile @@ -0,0 +1,994 @@ +# Doxyfile 1.2.18 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for the Bragg Institute SICS project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Bragg Institute SICS" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = "Sycamore February 05" + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = /cygdrive/c/Office/workspace/sics_doc/sycamore + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. +# This list is created by putting \deprecated commands in the documentation. +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = NO + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consist of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = "../.." + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl + +FILE_PATTERNS = *.c *.cpp *.h *.i + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = "../../CVS" "../../dummy" "../../java" + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = ansto.* subsystem.* + +# *.tex *.o *.w *.cdtproject *.cvsignore *.log *.project *.rfl *.dic +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output dir. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non empty doxygen will try to run +# the html help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the Html help documentation and to the tree view. + +TOC_EXPAND = YES + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, +# or Internet explorer 4.0+). Note that for large projects the tree generation +# can take a very long time. In such cases it is better to disable this feature. +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = YES + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = YES + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superceded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yield more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermedate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = /usr/local/bin/ + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = + diff --git a/site_ansto/hardsup/README b/site_ansto/hardsup/README new file mode 100644 index 00000000..71597518 --- /dev/null +++ b/site_ansto/hardsup/README @@ -0,0 +1,4 @@ + + This directory contains support files for the SINQ drivers. + + All of the code; David Maden. diff --git a/site_ansto/hardsup/StrMatch.c b/site_ansto/hardsup/StrMatch.c new file mode 100644 index 00000000..6134a05c --- /dev/null +++ b/site_ansto/hardsup/StrMatch.c @@ -0,0 +1,96 @@ +#define ident "1A01" +#ifdef VAXC +#module StrMatch ident +#endif +#ifdef __DECC +#pragma module StrMatch ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Department ASQ | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]StrMatch.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1999 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]StrMatch - + tasmad_disk:[mad.lib.sinq]StrMatch + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrMatch debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrMatch +** +** Updates: +** 1A01 12-Nov-1999 DM. Initial version. +**============================================================================ +** The following entry points are included in this module: +** +**------------------------------------------------------------------------- +** #include +** +** char *StrMatch (&str_a, &str_b, min_len) +** ------- +** Input Args: +** char *str_a - Pointer to first string to be compared. +** char *str_b - Pointer to second string to be compared. +** int min_len - The minimum allowed match length. +** Output Args: +** none +** Modified Args: +** none +** Return value: +** True (non-zero) if the 2 strings match. +** Global variables modified: +** none +** Routines called: +** None +** Description: +** The routine compares 2 strings, str_a and str_b, ignoring case. +** The length of str_a must be less than or equal to the length of str_b. +** The length of str_a must be at least min_len. +**------------------------------------------------------------------------- +** Global Definitions +*/ +#include + +#define NIL '\0' +/* +**==================================================================== +*/ +/* +**==================================================================== +** StrMatch - compare two strings. +*/ + int StrMatch ( +/* ======== +*/ char *str_a, + char *str_b, + int min_len) { + + int i = 0; + + while ((tolower(str_a[i]) == tolower(str_b[i])) && (str_a[i] != '\0')) i++; + + return ((str_a[i] == '\0') && (i >= min_len)); + } +/*-------------------------------------------------- End of StrMatch.C =======*/ diff --git a/site_ansto/hardsup/asynsrv_def.h b/site_ansto/hardsup/asynsrv_def.h new file mode 100644 index 00000000..ccaed197 --- /dev/null +++ b/site_ansto/hardsup/asynsrv_def.h @@ -0,0 +1,51 @@ +#ifndef _asynsrv_def_ +#define _asynsrv_def_ +/*------------------------------------------------ AsynSrv_DEF.H Ident V01N +*/ +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif + +#ifndef _asynsrv_errcodes_ +#define _asynsrv_errcodes_ +#include +#endif + +#define AsynSrv_MAX_LINK 8 + /* + ** Structures needed by AsynSrv_Utility. + */ + struct AsynSrv__info { + int skt; /* The socket number of the connection */ + char host[20]; /* The name of RS-232-C server */ + int port; /* The TCP/IP port number of server */ + int chan; /* The RS-232-C channel number on server */ + int msg_id; + int protocol_code; /* Flag to identify the server's protocol level */ + char protocol_id[4]; /* ASCII version of server's protocol level */ + int cmnd_hdr_len; /* Header length for command strings */ + char cmnd_fmt[8]; /* "sprintf" format for cmnd header conversion */ + int rply_hdr_len; /* Header length for response strings */ + char rply_fmt[8]; /* "sscanf" format for rply header conversion */ + char chan_char[4]; /* ASCII encoded version of chan */ + char tmo[4]; /* ASCII encoded time-out (deci-secs) */ + char eot[4]; /* Expected terminators */ + int max_replies; /* Binary version of #replies in response */ + int n_replies; /* # of last response returned to caller */ + void (*idleHandler) (int, int); /* MZ. handler called when waiting .. + ** .. on a response */ + }; + + struct AsynSrv_HostPortSkt { + char host[30]; + int port; + int skt; + int protocol_code; + char protocol_id[4]; + int cmnd_hdr_len; + int rply_hdr_len; + int usage_cnt; + int status; + }; +/*------------------------------------------------ End of AsynSrv_DEF.H --*/ +#endif /* _asynsrv_def_ */ diff --git a/site_ansto/hardsup/asynsrv_errcodes.h b/site_ansto/hardsup/asynsrv_errcodes.h new file mode 100644 index 00000000..493e6083 --- /dev/null +++ b/site_ansto/hardsup/asynsrv_errcodes.h @@ -0,0 +1,34 @@ +/* +** TAS_SRC:[LIB]ASYNSRV_ERRCODES.H +** +** Include file generated from ASYNSRV_ERRCODES.OBJ +** +** 29-AUG-2000 09:49:15.56 +*/ + +#define ASYNSRV__NO_ROOM 0x86480CC +#define ASYNSRV__FORCED_CLOSED 0x86480C4 +#define ASYNSRV__BAD_SOCKET 0x86480BC +#define ASYNSRV__BAD_SEND_UNKN 0x86480B4 +#define ASYNSRV__BAD_SEND_PIPE 0x86480AC +#define ASYNSRV__BAD_SEND_NET 0x86480A4 +#define ASYNSRV__BAD_SEND_LEN 0x864809C +#define ASYNSRV__BAD_SEND 0x8648094 +#define ASYNSRV__BAD_REPLY 0x864808C +#define ASYNSRV__BAD_RECV1_PIPE 0x8648084 +#define ASYNSRV__BAD_RECV1_NET 0x864807C +#define ASYNSRV__BAD_RECV1 0x8648074 +#define ASYNSRV__BAD_RECV_UNKN 0x864806C +#define ASYNSRV__BAD_RECV_PIPE 0x8648064 +#define ASYNSRV__BAD_RECV_NET 0x864805C +#define ASYNSRV__BAD_RECV_LEN 0x8648054 +#define ASYNSRV__BAD_RECV 0x864804C +#define ASYNSRV__BAD_PROT_LVL 0x8648044 +#define ASYNSRV__BAD_PAR 0x864803C +#define ASYNSRV__BAD_NOT_BCD 0x8648034 +#define ASYNSRV__BAD_HOST 0x864802C +#define ASYNSRV__BAD_FLUSH 0x8648024 +#define ASYNSRV__BAD_CONNECT 0x864801C +#define ASYNSRV__BAD_CMND_LEN 0x8648014 +#define ASYNSRV__BAD_BIND 0x864800C +#define ASYNSRV__FACILITY 0x864 diff --git a/site_ansto/hardsup/asynsrv_utility.c b/site_ansto/hardsup/asynsrv_utility.c new file mode 100644 index 00000000..2214adfe --- /dev/null +++ b/site_ansto/hardsup/asynsrv_utility.c @@ -0,0 +1,2121 @@ +#define ident "1C06" +#ifdef VAXC +#module AsynSrv_Utility ident +#endif +#ifdef __DECC +#pragma module AsynSrv_Utility ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Department ASQ | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]AsynSrv_Utility.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Mar 1996 +** +** To compile this module, use: + + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]AsynSrv_Utility - + lnsa01::tasmad_disk:[mad.psi.lib.sinq]AsynSrv_Utility + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @lnsa01::tasmad_disk:[mad.psi.lib.sinq]sinq_olb AsynSrv_Utility debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @lnsa01::tasmad_disk:[mad.psi.lib.sinq]sinq_olb AsynSrv_Utility +** +** Updates: +** 1A01 21-Mar-1996 DM. Initial version. +** 1B01 12-Sep-1996 DM. Allow host name to be in dot format too. +** 1B02 5-May-1997 DM. Set 5 sec time-out on "connect" on VMS systems. +** 1B07 11-Mar-1998 DM. Allow range of msecTmo to be 0 - 999999 (it was +** 100 - 999999). +** 1C01 21-Mar-2000 MZ. Introduced idleHandler +** 1C02 30-Mar-2000 DM. Add trace and flush facilities. +** 1C06 30-Aug-2000 DM. Add AsynSrv_GetLenTerm. +**============================================================================ +** The entry points included in this module are described below. Prototypes +** can be defined via: +** +** #include +** +** AsynSrv_ChanClose - Send a "CLOSE CHAN" request to RS-232-C Server. +** AsynSrv_Close - Close a connection to an RS-232-C Server. +** AsynSrv_Config - Configure an open AsynSrv_Utility connection. +** AsynSrv_ConfigDflt - Set defaults for AsynSrv_Open. +** AsynSrv_ErrInfo - Return detailed status from last operation. +** AsynSrv_Flush - Send a "FLUSH" request to an RS-232-C Server. +** AsynSrv_GetLenTerm - Get length and terminator of a reply. +** AsynSrv_GetReply - Get next reply from a reply buffer. +** AsynSrv_Open - Open a connection to an RS-232-C Server. +** AsynSrv_OpenNew - Same as AsynSrv_Open but forces the opening +** of a new socket. +** AsynSrv_SendCmnds - Send commands to a channel of an RS-232-C Server. +** AsynSrv_SendCmndsBig - Similar to AsynSrv_SendCmnds but with user +** defined buffer sizes. +** AsynSrv_Trace - Send a "TRACE ON" or "TRACE OFF" request to +** an RS-232-C Server. +** AsynSrv_Trace_Write - Send a "TRACE WRITE" request to RS-232-C Server. +** Other entry points which are private (i.e. not in ): +** AsynSrv_SendSpecCmnd - Send a "special" command to an RS-232-C Server. +**--------------------------------------------------------------------- +** int AsynSrv_ChanClose (&asyn_info) +** ----------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** True if no problems detected, otherwise False and errcode (see +** AsynSrv_ErrInfo) is set to indicate the nature of the problem. +** See AsynSrv_SendSpecCmnd for possible error codes. +** Routines called: +** AsynSrv_SendSpecCmnd +** Description: +** AsynSrv_SendSpecCmnd is called to send the 4-byte "special" +** command "-006" to the server to cause it to close its serial ports. +**--------------------------------------------------------------------- +** int AsynSrv_Close (&asyn_info, force_flag) +** ------------- +** Input Args: +** int force_flag - if non-zero, all connections using the same socket +** will also be marked as force-closed (socket number +** set to -1) and the connection will really be +** closed. This is needed for error recovery operations. +** Output Args: +** none +** Modified Args: +** struct AsynSrv__info *asyn_info - a structure holding skt, host and +** port of the connection. On return +* skt = 0. +** Return status: +** True if no problems detected, otherwise False and AsynSrv_errcode +** is set to indicate the nature of the problem as follows: +** ASYNSRV__BAD_PAR --> skt does not match with host/port. +** Routines called: +** Socket library, "close". +** Description: +** The routine decrements the usage count on the connection to host/port. +** If the counter is still >0, the routine simply returns. +** If the counter is now 0, the routine sends a "-001" message to the +** server to inform it that we are about to close the link, waits for a +** possible 4 bytes of response and then closes the TCP/IP connection. +**--------------------------------------------------------------------- +** int AsynSrv_Config (&asyn_info, &par_id, par_val, ...) +** -------------- +** Input Args: +** char* par_id - Text string identifying the next argument (see below). +** NULL indicates the end of the argument list. +** par_val - The value to set for the argument. The type of the +** argument can depend on par_id. +** Output Args: +** none +** Modified Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It is used to hold the config +** info for the connection. +** Return status: +** True if no problems detected, otherwise False and AsynSrv_errcode +** is set to indicate the nature of the problem as follows: +** ASYNSRV__BAD_PAR --> Unrecognised par_id or msecTmo < 0 or +** msecTmo > 999'999 or bad eot or .. +** Routines called: +** None +** Description: +** AsynSrv_Config may be used for setting values of parameters for +** use in subsequent calls to AsynSrv_SendCmnds. Defaults for these +** parameters are set via a call to AsynSrv_ConfigDflt, prior to +** calling AsynSrv_Open. Values which may be taken by par_id (warning -- +** par_id is case-sensitive) and the corresponding variable type of +** par_val are: +** +** "msecTmo" int The time-out response for commands sent +** to a serial channel on the server. The +** valid range is 0 to 999'999. +** "eot" char* The expected terminators in responses to +** commands sent to a serial channel on the +** server. The first character specifies the +** number of terminators (max=3). +** "idleHdl" void (*hdl) (int msecTmo, int socket) MZ. +** A handler which is called in AsynSrv_SendCmds +** before receiving the response. The handler +** should contain a call to "select ()" and return +** on a read event on the socket passed as +** argument, or after the timeout specified +** has expired. +**--------------------------------------------------------------------- +** int AsynSrv_ConfigDflt (&par_id, par_val, ...) +** ------------------ +** Input Args: +** char* par_id - Text string identifying the next argument (see below). +** NULL indicates the end of the argument list. +** par_val - The value to set for the argument. The type of the +** argument can depend on par_id. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** True if no problems detected, otherwise False and AsynSrv_errcode +** is set to indicate the nature of the problem as follows: +** ASYNSRV__BAD_PAR --> Unrecognised par_id or msecTmo < 0 or +** msecTmo > 999'999 or bad eot or .. +** Routines called: +** None +** Description: +** AsynSrv_ConfigDflt may be used for setting default values of parameters +** for use in subsequent calls to AsynSrv_Open. Values which may be taken +** by par_id (warning -- par_id is case-sensitive) and the corresponding +** variable type of par_val are: +** +** "TmoC" int The time-out in seconds to be used when +** opening a connection to a server. This +** value is only effective on VMS systems. For +** UNIX systems, the systemwide default (usually +** 75 secs) cannot be changed. The initial +** setting for "TmoC" is 5 secs. +** "msecTmo" int The time-out response for commands sent +** to a serial channel on the server. The +** valid range is 0 to 999'999. The initial +** setting for "msecTmo" is 10'000 msec. +** "eot" char* The expected terminators in responses to +** commands sent to a serial channel on the +** server. The first character specifies the +** number of terminators (max=3). The initial +** setting for "eot" is "1\r". +**------------------------------------------------------------------------- +** void AsynSrv_ErrInfo (&entry_txt_ptr, &errcode, &my_errno, &vaxc_errno) +** --------------- +** Input Args: +** None +** Output Args: +** char **entry_txt_ptr - Pointer to a text string giving the call stack +** at the time that the error was detected. +** int *errcode - An internal error code indicating the detected error. +** int *my_errno - Saved value of errno. +** int *vaxc_errno - Saved value of vaxc$errno (OpenVMS only). +** Modified Args: +** none +** Return status: +** none +** Routines called: +** none +** Description: +** Returns detailed status of the last operation. Once an error has been +** detected, the error status is frozen until this routine has been called. +**------------------------------------------------------------------------- +** int AsynSrv_Flush (&asyn_info) +** ------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** Same as AsynSrv_ChanClose +** Routines called: +** Same as AsynSrv_ChanClose +** Description: +** AsynSrv_SendSpecCmnd is called to send the 4-byte "special" +** command "-004" to the server to cause it to close its serial ports. +**------------------------------------------------------------------------- +** int AsynSrv_GetLenTerm (&asyn_info, &rcve_buff, &rply, *len, &term) +** ------------------ +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It is used to hold status info +** between calls to this routine. +** struct RS__RespStruct *rcve_buff - address of receive buffer used +** in last call to AsynSrv_SendCmnds. +** char *rply - address of a reply in rcve_buff as +** returned by AsynSrv_GetReply. +** Output Args: +** int *len - address of location to receive the +** length of the reply. +** char *term - address of location to receive the +** terminator of the reply. +** Modified Args: +** none +** Return status: +** True if everything seems to be OK. Otherwise, False. +** Routines called: +** none +** Description: +** AsynSrv_GetLenTerm simply converts the length of the reply as saved +** in rply[-hdr_size-1] from ASCII to binary, subtracts 2 from it (to +** allow for the terminator byte and the null termination character) and +** returns it to the caller. *term is set to the value of the character +** at location rply[-1]. +**------------------------------------------------------------------------- +** char *AsynSrv_GetReply (&asyn_info, &rcve_buff, &last_rply) +** ---------------- +** Input Args: +** struct RS__RespStruct *rcve_buff - address of receive buffer used +** in last call to AsynSrv_SendCmnds. +** char *last_rply - Address of last reply processed +** or NULL. +** Output Args: +** none +** Modified Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It is used to hold status info +** between calls to this routine. +** Return status: +** Address of next reply in the buffer or NULL if no more. Note that this +** is a pointer to the reply and not to the head of the reply structure. +** The terminator byte found is therefore at index [-1] from this address. +** Routines called: +** none +** Description: +** AsynSrv_GetReply unpacks the replies in the response packet from the +** RS232C server which is an argument in the call to AsynSrv_SendCmnds. +** If the routine is called with last_rply = NULL, a pointer to the +** first reply is returned. On calling AsynSrv_GetReply again with +** last_rply set to this address, one receives the address of the second +** reply and so on, until NULL is returned, indicating that all responses +** have been exhausted. +** Warning: +** AsynSrv_GetReply keeps count of the number of responses it returns. +** Responses must therefore be processed in order. +**------------------------------------------------------------------------- +** int AsynSrv_Open (&asyn_info) +** ------------ +** Input Args: +** struct AsynSrv__info *asyn_info +** asyn_info->host - Name of host offering the RS-232-C service. The name +** can be either symbolic or numeric, e.g. +** "lnsw02.psi.ch" or "129.129.90.18". +** asyn_info->port - Number of TCP/IP port of TCP/IP server. +** asyn_info->chan - Number of RS-232-C channel to be used. +** Output Args: +** none +** Modified Args: +** struct AsynSrv__info *asyn_info - a structure holding skt, host and +** port of the connection. On return +** skt = socket number of connection. +** Set to 0 if error. +** Return status: +** If non-zero, no problems detected and asyn_info->skt is the socket to +** use for communicating with the server. Otherwise, a problem +** was detected and AsynSrv_errcode may be set as follows +** to indicate the nature of the problem: +** ASYNSRV__BAD_HOST --> Call to "gethostbyname" failed to get +** network addr of host. +** ASYNSRV__BAD_SOCKET --> Call to "socket" failed. +** ASYNSRV__BAD_BIND --> Call to "bind" failed. +** ASYNSRV__BAD_CONNECT --> Call to "connect" failed. +** ASYNSRV__BAD_PAR --> Bad parameter found. Probably +** asyn_info->port or asyn_info->chan +** are out of range. +** BAD_PROT_LVL --> Server protocol level is not valid. +** ASYNSRV__NO_ROOM --> Host/port table full or Active-link +** table full. +** Routines called: +** Socket library routine "open". +** Description: +** The routine maintains a list of hosts/ports to which it has open +** sockets. If an entry is found in the list, the socket is returned +** and the usage count of this connection is incremented. If no entry +** is found in the list, a connection to the host is established and +** entered into the list. +** The routine also maintains a table of active links so that the +** "force-close" function can be performed. The link is added to this +** table too. +**------------------------------------------------------------------------- +** int AsynSrv_OpenNew (&asyn_info) +** --------------- +** Input Args: +** struct AsynSrv__info *asyn_info +** asyn_info->host - Name of host offering the RS-232-C service. The name +** can be either symbolic or numeric, e.g. +** "lnsw02.psi.ch" or "129.129.90.18". +** asyn_info->port - Number of TCP/IP port of TCP/IP server. +** asyn_info->chan - Number of RS-232-C channel to be used. +** Output Args: +** none +** Modified Args: +** struct AsynSrv__info *asyn_info - a structure holding skt, host and +** port of the connection. On return +** skt = socket number of connection. +** Set to 0 if error. +** Return status: +** See AsynSrv_Open +** Routines called: +** See AsynSrv_Open +** Description: +** This routine is the same as AsynSrv_Open but forces the opening +** of a new socket. The socket will be marked to ensure that no other +** connections share this connection. +**------------------------------------------------------------------------- +** int AsynSrv_SendCmnds (&asyn_info, &send_buff, &rcve_buff, ...) +** ----------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** char * ... - A list of commands, terminated by NULL, for +** sending to the channel on the server. The commands +** must have any necessary \r characters included. +** Output Args: +** struct RS__RespStruct *rcve_buff - a buffer to receive the response +** from the server. +** Modified Args: +** struct RS__MsgStruct *send_buff - a buffer for holding the commands +** for sending to the server. +** Return status: +** True if no problems detected, otherwise False and errcode (see +** AsynSrv_ErrInfo) is set to indicate the nature of the problem. +** AsynSrv_errcode may be set as follows: +** ASYNSRV__BAD_SEND_LEN --> Too much to send; either too many +** commands or too long. The buffer +** is 232 bytes long and each command +** has a 2-byte header. +** ASYNSRV__BAD_CMND_LEN --> A command is too long - it's length cannot +** be encoded into the command header field +** The next 4 errors are related to network errors whilst sending the +** message buffer to the server: +** ASYNSRV__BAD_SEND --> Network problem - server has +** probably abended. +** ASYNSRV__BAD_SEND_PIPE --> Network pipe broken - probably same +** cause as ASYNSRV__BAD_SEND. +** ASYNSRV__BAD_SEND_NET --> Some other network problem. "errno" +** may be helpful. +** ASYNSRV__BAD_SEND_UNKN --> Some other network problem happened +** resulting in the message not +** getting sent completely. "errno" is +** probably not helpful in this case. +** ASYNSRV__BAD_RECV \ These are network errors whilst +** ASYNSRV__BAD_RECV_PIPE > receiving the 4-byte response header. +** ASYNSRV__BAD_RECV_NET / They are analogous to ASYNSRV__BAD_SEND +** ASYNSRV__BAD_RECV_UNKN / ... ASYNSRV__BAD_SEND_UNKN. +** ASYNSRV__BAD_NOT_BCD --> The 4-byte response header is not an +** ASCII coded decimal integer. +** ASYNSRV__BAD_RECV_LEN --> The body of the response would be too +** big to fit in the input buffer. The +** buffer is ??? bytes long and each +** response has a 5-byte header and a +** trailing zero-byte. The response +** is flushed. +** ASYNSRV__BAD_FLUSH --> Some network error was detected +** during flushing. This is an "or" +** of errors ASYNSRV__BAD_RECV to +** ASYNSRV__BAD_RECV_UNKN. +** ASYNSRV__FORCED_CLOSED --> The connection to the channel has been +** forcefully closed. See below. +** ASYNSRV__BAD_REPLY --> The n_rply field of the response was +** either non-numeric or <0, indicating +** that the Terminal Server detected an +** error. The reply is added to the +** routine call stack for debug purposes. +** +** ASYNSRV__BAD_RECV1 \ These are network errors whilst receiving +** ASYNSRV__BAD_RECV1_PIPE > the body of the response. They are +** ASYNSRV__BAD_RECV1_NET / equivalent to ASYNSRV__BAD_RECV, +** ASYNSRV__BAD_RECV_PIPE and +** ASYNSRV__BAD_RECV_NET. +** ASYNSRV__FORCED_CLOSED occurs if AsynSrv_Close has been called +** for another device on the same server and the 'force_flag' +** was set (see AsynSrv_Close). The caller should call +** AsynSrv_Close and then AsynSrv_Open to re-establish a +** connection to the server. +** Routines called: +** Socket library routines send and recv. +** Description: +** The list of commands is assembled into a message buffer with appropriate +** header information and sent off to the server. The response is then +** awaited and read in when it arrives. +** +** For any of the following errors: +** ASYNSRV__BAD_SEND (Note: ASYNSRV__BAD_SEND_LEN and +** ASYNSRV__BAD_SEND_PIPE ASYNSRV__BAD_RECV_LEN and +** ASYNSRV__BAD_SEND_NET ASYNSRV__BAD_REPLY +** ASYNSRV__BAD_SEND_UNKN do not cause a close) +** ASYNSRV__BAD_RECV +** ASYNSRV__BAD_RECV_PIPE +** ASYNSRV__BAD_RECV_NET +** ASYNSRV__BAD_RECV_UNKN +** ASYNSRV__BAD_NOT_BCD +** ASYNSRV__BAD_FLUSH +** ASYNSRV__BAD_RECV1 +** ASYNSRV__BAD_RECV1_PIPE +** ASYNSRV__BAD_RECV1_NET +** the network link to the server is force-closed via a call to +** AsynSrv_Close. Once the error has been corrected, the link can be +** re-opened via a call to AsynSrv_Open. As a result of the force-close, +** other active handles will need to be released via a call to +** AsynSrv_Close before AsynSrv_Open is called. +**------------------------------------------------------------------------- +** int AsynSrv_SendCmndsBig (&asyn_info, &send_buff, send_buff_size, +** -------------------- &rcve_buff, rcve_buff_size, ...) +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** int send_buff_size - The size of *send_buff in bytes. +** int rcve_buff_size - The size of *rcve_buff in bytes. +** int *c_len \ - a list of argument pairs specifying the commands +** char *cmd > to be sent. The list is terminated by +** ... / c_len == NULL. If *c_len > 0, it specifies the +** number of bytes in the command. Otherwise, *cmd +** is assumed to be a zero-terminated string. +** The *cmd string must include any terminator +** byte(s) but, if *c_len > 0, it does not need to +** be zero-terminated. +** Output Args: +** struct RS__RespStruct *rcve_buff - a buffer to receive the response +** from the server. Note that this structure must +** be extended to size rcve_buff_size by the use +** of suitable unions. +** Modified Args: +** struct RS__MsgStruct *send_buff - a buffer for holding the commands +** for sending to the server. Note that this +** structure must be extended to size +** send_buff_size by the use of suitable unions. +** Return status: +** Same as AsynSrv_SendCmnds with the addition of error code: +** ASYNSRV__BAD_SEND_PAR --> Either send_buff_size or rcve_buff_size +** is less than 64. +** Routines called: +** Socket library routines send and recv. +** Description: +** The procedure is similar to AsynSrv_SendCmnds except that the commands +** are specified by a pair of arguments (to allow for the binary +** transmission of zeros) and the send and receive structures are assumed +** to have been extended to the sizes specified by suitable declarations +** in the calling module. +**------------------------------------------------------------------------- +** int AsynSrv_SendSpecCmnd (&asyn_info, &cmnd) +** ------------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** char *cmnd - the 4-byte special command to be sent. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** True if no problems detected, otherwise False and errcode (see +** AsynSrv_ErrInfo) is set to indicate the nature of the problem. +** AsynSrv_errcode may be set as follows: +** The next 4 errors are related to network errors whilst sending the +** 4-byte message buffer to the server: +** ASYNSRV__BAD_SEND --> Network problem - server has +** probably abended. +** ASYNSRV__BAD_SEND_PIPE --> Network pipe broken - probably same +** cause as ASYNSRV__BAD_SEND. +** ASYNSRV__BAD_SEND_NET --> Some other network problem. "errno" +** may be helpful. +** ASYNSRV__BAD_SEND_UNKN --> Some other network problem happened +** resulting in the message not +** getting sent completely. "errno" is +** probably not helpful in this case. +** ASYNSRV__BAD_RECV \ These are network errors whilst +** ASYNSRV__BAD_RECV_PIPE > receiving the 4-byte response. +** ASYNSRV__BAD_RECV_NET / They are analogous to ASYNSRV__BAD_SEND +** ASYNSRV__BAD_RECV_UNKN / ... ASYNSRV__BAD_SEND_UNKN. +** ASYNSRV__BAD_NOT_BCD --> The 4-byte response header is not an +** echo of the 4 bytes which were sent. +** ASYNSRV__FORCED_CLOSED --> The connection to the channel has been +** forcefully closed. See below. +** ASYNSRV__FORCED_CLOSED occurs if AsynSrv_Close has been called +** for another device on the same server and the 'force_flag' +** was set (see AsynSrv_Close). The caller should call +** AsynSrv_Close and then AsynSrv_Open to re-establish a +** connection to the server. +** Routines called: +** Socket library routines send and recv. +** Description: +** AsynSrv_SendSpecCmnd sends the 4-byte "special" command, cmnd, to the +** server and reads the response. The response should be an echo of the +** command which was sent. +** Note: +** For any of the following errors: +** ASYNSRV__BAD_SEND +** ASYNSRV__BAD_SEND_PIPE +** ASYNSRV__BAD_SEND_NET +** ASYNSRV__BAD_SEND_UNKN +** ASYNSRV__BAD_RECV +** ASYNSRV__BAD_RECV_PIPE +** ASYNSRV__BAD_RECV_NET +** ASYNSRV__BAD_RECV_UNKN +** ASYNSRV__BAD_NOT_BCD +** the network link to the server is force-closed via a call to +** AsynSrv_Close. Once the error has been corrected, the link can be +** re-opened via a call to AsynSrv_Open. As a result of the force-close, +** other active handles will need to be released via a call to +** AsynSrv_Close before AsynSrv_Open is called. +**------------------------------------------------------------------------- +** int AsynSrv_Trace (&asyn_info, state) +** ------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** int state - True/False to turn tracing on/off. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** Same as AsynSrv_ChanClose +** Routines called: +** Same as AsynSrv_ChanClose +** Description: +** AsynSrv_SendSpecCmnd is called to send a 4-byte "special" command +** to the server. The command is "-002" to turn on tracing and "-003" +** to turn off tracing. + +** Description: +** To turn on tracing, the 4-byte message "-002" is sent to the server. +** To turn off tracing, the 4-byte message "-003" is sent to the server. +** The server is expected to respond by echoing the message. +** +**------------------------------------------------------------------------- +** int AsynSrv_Trace_Write (&asyn_info) +** ------------------- +** Input Args: +** struct AsynSrv__info *asyn_info - the structure used in the call to +** AsynSrv_Open. It contains settings required +** for setting up and sending send_buff. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** Same as AsynSrv_ChanClose +** Routines called: +** Same as AsynSrv_ChanClose +** Description: +** AsynSrv_SendSpecCmnd is called to send the 4-byte "special" +** command "-005" to the server to cause it to write its trace +** buffer to disk. +**============================================================================*/ +/* +**--------------------------------------------------------------------------- +** Global Definitions +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __VMS +#pragma nostandard /* The "$" characters in ucx$inetdef.h give trouble! */ +#include +#include +#else +#include +#endif +/*-----------------------------------------------------------------*/ +#include +#include +#include + +#define True 1 +#define False 0 + +#define MAX_OPEN 64 + + int AsynSrv_SendSpecCmnd ( /* A prototype for a local routine */ + struct AsynSrv__info *asyn_info, + char *cmnd); +/*-------------------------------------------------------------------------- +** Global Variables +*/ + static int AsynSrv_call_depth = 0; + static char AsynSrv_routine[5][64]; + static int AsynSrv_errcode = 0; + static int AsynSrv_errno, AsynSrv_vaxc_errno; + static int AsynSrv_connect_tmo = 5; /* Time-out on "connect" */ + static int AsynSrv_msec_tmo = 10000; /* Time-out for responses */ + static char AsynSrv_eot[] = {'1', '\r', '\0','\0'}; /* Terminators */ +/* +** The following is the list of open connections (= number of +** active sockets). +*/ + static int AsynSrv_n_cnct = 0; + static struct AsynSrv_HostPortSkt AsynSrv_HPS_list[AsynSrv_MAX_LINK]; +/* +** The following is the list of active calls to AsynSrv_Open. +*/ + static int AsynSrv_n_active = 0; + static struct AsynSrv__info *AsynSrv_active[MAX_OPEN]; +/* +**--------------------------------------------------------------------------- +** AsynSrv_ChanClose: Send a "CLOSE CHAN" request to +** RS232C server. +*/ + int AsynSrv_ChanClose ( +/* ================= +*/ struct AsynSrv__info *asyn_info) { + + int status; + char cmnd[8], rply[8]; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_ChanClose"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Send message and get reply. + */ + status = AsynSrv_SendSpecCmnd (asyn_info, "-006"); + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return status; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Close: Close a connection to an RS-232-C server. +*/ + int AsynSrv_Close ( +/* ============= +*/ struct AsynSrv__info *asyn_info, + int force_flag) { + + int i, j, k, my_skt; + char buff[4]; + /*----------------------------------------------- + */ + if (asyn_info == NULL) return True; /* Just return if nothing to do! */ + my_skt = asyn_info->skt; + if (my_skt <= 0) return True; /* Just return if nothing to do! */ + /*----------------------------------------------- + ** Pre-set the routinename (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_Close"); + AsynSrv_call_depth++; + } + /*------------------------------------------------------ + ** Start by finding the table entry for this connection + */ + for (i = 0; i < AsynSrv_n_cnct; i++) { + if (AsynSrv_HPS_list[i].skt != my_skt) continue; + if (AsynSrv_HPS_list[i].port != asyn_info->port) continue; + if (strcmp (AsynSrv_HPS_list[i].host, asyn_info->host) == 0) break; + } + if (i >= AsynSrv_n_cnct) { /* Did we find the entry? */ + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* No! */ + return False; + } + /*------------------------------------------------------ + ** Now find the table entry for the AsynSrvOpen call. + */ + for (j = 0; j < AsynSrv_n_active; j++) { + if ((AsynSrv_active[j] == asyn_info) && + (AsynSrv_active[j]->skt == my_skt)) { + break; + } + } + if (j >= AsynSrv_n_active) { /* Did we find the entry? */ + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* No! */ + return False; + } + /*------------------------------------------------------ + ** i is the index for the connection table entry. + ** j is the index for the caller's AsynSrvOpen call entry. + */ + if (AsynSrv_HPS_list[i].usage_cnt <= 0) { /* Is the connection active? */ + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* No */ + return False; + } + /*------------------------------------------------------ + ** For the caller, simply set his socket number to zero, + ** mark the AsynSrvOpen entry as free and decrease the + ** usage count (the entries will be compressed later). + */ + AsynSrv_active[j]->skt = 0; /* Mark the close .. */ + AsynSrv_active[j] = NULL; /* .. and flag entry to be removed. */ + AsynSrv_HPS_list[i].usage_cnt--; /* Decrease usage count */ + /*------------------------------------------------------ + ** If this is a force-close, go through all AsynSrv_Open + ** entries looking for a socket match, mark them as + ** free and decrease usage count. + */ + if (force_flag != 0) { + for (k = 0; k < AsynSrv_n_active; k++) { + if (AsynSrv_active[k] != NULL) { + if (AsynSrv_active[k]->skt == my_skt) { + AsynSrv_active[k]->skt = -1; /* Mark the force-close */ + AsynSrv_active[k] = NULL; /* Mark entry to be removed */ + AsynSrv_HPS_list[i].usage_cnt--; /* Decrease usage count */ + } + } + } + if (AsynSrv_HPS_list[i].usage_cnt != 0) { /* Use count should now be .. */ + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* .. zero or there's a bug. */ + return False; + } + } + /*------------------------------------------------------ + ** Compress the list of AsynSrv_Open entries + */ + j = 0; + for (k = 0; k < AsynSrv_n_active; k++) { + if (AsynSrv_active[k] != NULL) { + AsynSrv_active[j] = AsynSrv_active[k]; + j++; + } + } + for (k = j; k < AsynSrv_n_active; k++) AsynSrv_active[k] = NULL; + AsynSrv_n_active = j; + /*------------------------------------------------------ + ** If the link is now idle, really close it and compress + ** the connection table entry out of the list. + */ + if (AsynSrv_HPS_list[i].usage_cnt == 0) { + send (my_skt, "-001", 4, 0); /* Tell the TCP/IP server that .. + ** .. we are about to quit. + */ + recv (my_skt, buff, sizeof (buff), 0); /* And wait for his ack */ + close (my_skt); + for (j = i; j < AsynSrv_n_cnct; j++) { + memcpy ((char *) &AsynSrv_HPS_list[j], (char *) &AsynSrv_HPS_list[j+1], + sizeof (AsynSrv_HPS_list[0])); + } + AsynSrv_HPS_list[AsynSrv_n_cnct].skt = 0; /* Invalidate the free entry */ + AsynSrv_n_cnct--; + } + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Config: Configure an open connection. +*/ + int AsynSrv_Config ( +/* ============== +*/ struct AsynSrv__info *asyn_info, + ...) { + + char buff[16], my_eot[4]; + va_list ap; /* Pointer to variable args */ + char *txt_ptr; + int intval; + typedef void (*IdleHandler)(int,int); + /* + ** Pre-set the routinename (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_Config"); + AsynSrv_call_depth++; + } + + va_start (ap, asyn_info); /* Set up var arg machinery */ + txt_ptr = va_arg (ap, char *); /* Get pntr to first parameter ident */ + while (txt_ptr != NULL) { + if (strcmp (txt_ptr, "msecTmo") == 0) { + intval = va_arg (ap, int); + if ((intval < 0) || (intval > 999999)) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + sprintf (buff, "%04d", intval/100); /* Convert to ASCII as .. + ** .. deci-secs */ + memcpy (asyn_info->tmo, buff, 4); + }else if (strcmp (txt_ptr, "eot") == 0) { + txt_ptr = va_arg (ap, char *); + if (txt_ptr == NULL) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + memcpy (my_eot, "\0\0\0\0", 4); + switch (txt_ptr[0]) { + case '3': my_eot[3] = txt_ptr[3]; + case '2': my_eot[2] = txt_ptr[2]; + case '1': my_eot[1] = txt_ptr[1]; + case '0': + my_eot[0] = txt_ptr[0]; + break; + default: + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + memcpy (asyn_info->eot, my_eot, 4); + }else if (strcmp (txt_ptr, "idleHdl") == 0) { /* MZ. */ + asyn_info->idleHandler = va_arg (ap, IdleHandler); + }else { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + txt_ptr = va_arg (ap, char *); /* Get pntr to next parameter ident */ + } + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_ConfigDflt: Set default values in AsynSrv_Utility +** which will be used to initialise +** structures in AsynSrv_Open. +*/ + int AsynSrv_ConfigDflt ( +/* ================== +*/ char *par_id, + ...) { + int i; + char buff[4]; + va_list ap; /* Pointer to variable args */ + char *txt_ptr; + int intval; + /* + ** Pre-set the routinename (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_ConfigDflt"); + AsynSrv_call_depth++; + } + + va_start (ap, par_id); /* Set up var arg machinery */ + txt_ptr = par_id; /* Point to first arg */ + while (txt_ptr != NULL) { + if (strcmp (txt_ptr, "tmoC") == 0) { + intval = va_arg (ap, int); + if ((intval < 1) || (intval > 3600)) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + AsynSrv_connect_tmo = intval; + }else if (strcmp (txt_ptr, "msecTmo") == 0) { + intval = va_arg (ap, int); + if ((intval < 0) || (intval > 999999)) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + AsynSrv_msec_tmo = intval; + }else if (strcmp (txt_ptr, "eot") == 0) { + txt_ptr = va_arg (ap, char *); + if (txt_ptr == NULL) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + switch (txt_ptr[0]) { + case '3': AsynSrv_eot[3] = txt_ptr[3]; + case '2': AsynSrv_eot[2] = txt_ptr[2]; + case '1': AsynSrv_eot[1] = txt_ptr[1]; + case '0': + AsynSrv_eot[0] = txt_ptr[0]; + break; + default: + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + switch (txt_ptr[0]) { + case '0': AsynSrv_eot[1] = '\0'; + case '1': AsynSrv_eot[2] = '\0'; + case '2': AsynSrv_eot[3] = '\0'; + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_PAR; + return False; + } + txt_ptr = va_arg (ap, char *); /* Get pntr to next parameter ident */ + } + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_ErrInfo: Return detailed status from last operation. +*/ + void AsynSrv_ErrInfo ( +/* =============== +*/ char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno) { + + int i, j, k; + char buff[80]; + + if (AsynSrv_call_depth <= 0) { + strcpy (AsynSrv_routine[0], "AsynSrv_no_error_detected"); + *errcode = 0; + *my_errno = 0; + *vaxc_errno = 0; + }else { + if (AsynSrv_call_depth > 1) { /* Concatenate the names */ + for (i = 1; i < AsynSrv_call_depth; i++) { + strcat (AsynSrv_routine[0], "/"); + StrJoin (AsynSrv_routine[0], sizeof (AsynSrv_routine), + AsynSrv_routine[0], AsynSrv_routine[i]); + } + } + *errcode = AsynSrv_errcode; + *my_errno = AsynSrv_errno; + *vaxc_errno = AsynSrv_vaxc_errno; + switch (AsynSrv_errcode) { + case ASYNSRV__BAD_BIND: strcpy (buff, "/ASYNSRV__BAD_BIND"); break; + case ASYNSRV__BAD_CMND_LEN: strcpy (buff, "/ASYNSRV__BAD_CMND_LEN"); break; + case ASYNSRV__BAD_CONNECT: strcpy (buff, "/ASYNSRV__BAD_CONNECT"); break; + case ASYNSRV__BAD_FLUSH: strcpy (buff, "/ASYNSRV__BAD_FLUSH"); break; + case ASYNSRV__BAD_HOST: strcpy (buff, "/ASYNSRV__BAD_HOST"); break; + case ASYNSRV__BAD_NOT_BCD: strcpy (buff, "/ASYNSRV__BAD_NOT_BCD"); break; + case ASYNSRV__BAD_PAR: strcpy (buff, "/ASYNSRV__BAD_PAR"); break; + case ASYNSRV__BAD_PROT_LVL: strcpy (buff, "/ASYNSRV__BAD_PROT_LVL"); break; + case ASYNSRV__BAD_RECV: strcpy (buff, "/ASYNSRV__BAD_RECV"); break; + case ASYNSRV__BAD_RECV_LEN: strcpy (buff, "/ASYNSRV__BAD_RECV_LEN"); break; + case ASYNSRV__BAD_RECV_NET: strcpy (buff, "/ASYNSRV__BAD_RECV_NET"); break; + case ASYNSRV__BAD_RECV_PIPE: strcpy (buff, "/ASYNSRV__BAD_RECV_PIPE"); break; + case ASYNSRV__BAD_RECV_UNKN: strcpy (buff, "/ASYNSRV__BAD_RECV_UNKN"); break; + case ASYNSRV__BAD_RECV1: strcpy (buff, "/ASYNSRV__BAD_RECV1"); break; + case ASYNSRV__BAD_RECV1_NET: strcpy (buff, "/ASYNSRV__BAD_RECV1_NET"); break; + case ASYNSRV__BAD_RECV1_PIPE:strcpy (buff, "/ASYNSRV__BAD_RECV1_PIPE"); break; + case ASYNSRV__BAD_REPLY: strcpy (buff, "/ASYNSRV__BAD_REPLY"); break; + case ASYNSRV__BAD_SEND: strcpy (buff, "/ASYNSRV__BAD_SEND"); break; + case ASYNSRV__BAD_SEND_LEN: strcpy (buff, "/ASYNSRV__BAD_SEND_LEN"); break; + case ASYNSRV__BAD_SEND_NET: strcpy (buff, "/ASYNSRV__BAD_SEND_NET"); break; + case ASYNSRV__BAD_SEND_PIPE: strcpy (buff, "/ASYNSRV__BAD_SEND_PIPE"); break; + case ASYNSRV__BAD_SEND_UNKN: strcpy (buff, "/ASYNSRV__BAD_SEND_UNKN"); break; + case ASYNSRV__BAD_SOCKET: strcpy (buff, "/ASYNSRV__BAD_SOCKET"); break; + case ASYNSRV__FORCED_CLOSED: strcpy (buff, "/ASYNSRV__FORCED_CLOSED"); break; + case ASYNSRV__NO_ROOM: strcpy (buff, "/ASYNSRV__NO_ROOM"); break; + default: sprintf (buff, "/ASYNSRV__unkn_err_code: %d", AsynSrv_errcode); + } + StrJoin (AsynSrv_routine[0], sizeof(AsynSrv_routine), + AsynSrv_routine[0], buff); + } + *entry_txt = AsynSrv_routine[0]; + AsynSrv_call_depth = 0; + AsynSrv_errcode = 0; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Flush: Send a Flush command to RS232C server. +*/ + int AsynSrv_Flush ( +/* ============= +*/ struct AsynSrv__info *asyn_info) { + + int status; + char cmnd[8], rply[8]; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_Flush"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Send message and get reply. + */ + status = AsynSrv_SendSpecCmnd (asyn_info, "-004"); + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return status; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_GetLenTerm: Get length and terminator of given +** reply from reply buffer. +*/ + int AsynSrv_GetLenTerm ( +/* ================== +*/ struct AsynSrv__info *asyn_info, + struct RS__RespStruct *rcve_buff, + char *rply, /* In: Addr of a reply as got .. + ** .. got from _GetReply */ + int *len, /* Out: The returned length */ + char *term) { /* Out: The returned t'nator */ + + int i; + + i = sscanf ((rply - asyn_info->rply_hdr_len - 1), asyn_info->rply_fmt, len); + *len = (i == 1) ? (*len - 2) : 0; + *term = *(rply - 1); + + if (i != 1) return False; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_GetReply: Get next reply from a reply buffer. +*/ + char *AsynSrv_GetReply ( +/* ================ +*/ struct AsynSrv__info *asyn_info, + struct RS__RespStruct *rcve_buff, + char *last_rply) { + + char *pntr = NULL; + int i, rply_len; + + if (last_rply == NULL) { /* Start with first reply? */ + /* Yes */ + asyn_info->n_replies = 1; + if (asyn_info->max_replies > 0) { + pntr = rcve_buff->u.rplys; + pntr = pntr + 1 + asyn_info->rply_hdr_len; + } + }else { /* No - get next reply */ + if (asyn_info->n_replies < asyn_info->max_replies) { /* If there is one */ + i = sscanf ((last_rply - asyn_info->rply_hdr_len - 1), + asyn_info->rply_fmt, &rply_len); + if ((i == 1) && (rply_len >= 0)) { + pntr = last_rply + rply_len + asyn_info->rply_hdr_len; + } + } + } + return pntr; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Open: Open a connection to an RS-232-C Server. +*/ + int AsynSrv_Open ( +/* ============ +*/ struct AsynSrv__info *asyn_info) { + + int i, status; + int my_skt; + char old_time_out[4]; + union { + char chars[4]; + int val; + } time_out; + char buff[128]; + struct RS__MsgStruct s_buff; + struct RS__RespStruct r_buff; + unsigned int oto_len, oto_status; + struct hostent *rmt_hostent; + struct in_addr *rmt_inet_addr_pntr; + struct in_addr rmt_inet_addr; + int rmt_sockname_len; + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + + char *errtxt_ptr; + int errcode, my_errno, my_vaxc_errno; +/*-------------------------------------------------------- +*/ + asyn_info->skt = 0; +/*-------------------------------------------------------- +** Initialise the error info stack and pre-set the +** routine name (in case of error). +*/ + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + strcpy (AsynSrv_routine[0], "AsynSrv_Open"); + AsynSrv_call_depth = 1; +/*-------------------------------------------------------- +** Is there room for a new AsynSrv_Open table entry? +*/ + if (AsynSrv_n_active >= MAX_OPEN) { + AsynSrv_errcode = ASYNSRV__NO_ROOM; /* There isn't! */ + return False; + } +/*-------------------------------------------------------- +** See if a table entry for this connection already exists. +*/ + for (i = 0; i < AsynSrv_n_cnct; i++) { + if (AsynSrv_HPS_list[i].status != 0) continue; + if (AsynSrv_HPS_list[i].port != asyn_info->port) continue; + if (strcmp (AsynSrv_HPS_list[i].host, asyn_info->host) == 0) break; + } + if (i < AsynSrv_n_cnct) { /* Did we find an entry? */ + /* Yes */ + AsynSrv_HPS_list[i].usage_cnt++; /* Up the usage count and .. */ + AsynSrv_active[AsynSrv_n_active] = /* .. remember the open and .. */ + asyn_info; + AsynSrv_n_active++; + asyn_info->skt = /* .. return the socket. */ + AsynSrv_HPS_list[i].skt; + if (asyn_info->chan < 0) asyn_info->chan = 0; + if (asyn_info->chan > 255) asyn_info->chan = 0; + sprintf (buff, "%04d", asyn_info->chan); /* Convert channel # to ASCII */ + memcpy (asyn_info->chan_char, buff, sizeof (asyn_info->chan_char)); + + asyn_info->protocol_code = AsynSrv_HPS_list[i].protocol_code; + memcpy (asyn_info->protocol_id, + AsynSrv_HPS_list[i].protocol_id, + sizeof (asyn_info->protocol_id)); + asyn_info->cmnd_hdr_len = AsynSrv_HPS_list[i].cmnd_hdr_len; + sprintf (asyn_info->cmnd_fmt, "%%0%dd", asyn_info->cmnd_hdr_len); + asyn_info->rply_hdr_len = AsynSrv_HPS_list[i].rply_hdr_len; + sprintf (asyn_info->rply_fmt, "%%%dd", asyn_info->rply_hdr_len); + + sprintf (buff, "%04d", AsynSrv_msec_tmo/100); /* Set dflt time-out .. + ** ..(deci-secs) */ + memcpy (asyn_info->tmo, buff, sizeof (asyn_info->tmo)); + + memcpy (asyn_info->eot, /* Set dflt terminator(s) */ + AsynSrv_eot, sizeof (asyn_info->eot)); + + asyn_info->max_replies = asyn_info->n_replies = 0; + asyn_info->idleHandler = NULL; + AsynSrv_call_depth--; + return True; + } +/*-------------------------------------------------------- +** There is no existing connection. Open a new one. +*/ + status = AsynSrv_OpenNew (asyn_info); + if (!status) return False; +/*-------------------------------------------------------- +** Allow the entry to be shared (i.e. status = 0) +*/ + AsynSrv_HPS_list[AsynSrv_n_cnct-1].status = 0; +/*-------------------------------------------------------- +*/ + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + AsynSrv_call_depth = 0; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_OpenNew: Open a new connection to an RS-232-C Server. +*/ + int AsynSrv_OpenNew ( +/* =============== +*/ struct AsynSrv__info *asyn_info) { + + int i, status; + int my_skt; + char old_time_out[4]; + union { + char chars[4]; + int val; + } time_out; + char buff[128]; + struct RS__MsgStruct s_buff; + struct RS__RespStruct r_buff; + unsigned int oto_len, oto_status; + struct hostent *rmt_hostent; + struct in_addr *rmt_inet_addr_pntr; + struct in_addr rmt_inet_addr; + int rmt_sockname_len; + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + + char *errtxt_ptr; + int errcode, my_errno, my_vaxc_errno; +/*-------------------------------------------------------- +*/ + asyn_info->skt = 0; +/*-------------------------------------------------------- +** Initialise the error info stack and pre-set the +** routine name (in case of error). +*/ + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + if ((AsynSrv_call_depth == 1) && + (strcmp (AsynSrv_routine[0], "AsynSrv_Open") == 0)) { + strcpy (AsynSrv_routine[1], "AsynSrv_OpenNew"); + AsynSrv_call_depth = 2; + }else { + strcpy (AsynSrv_routine[0], "AsynSrv_OpenNew"); + AsynSrv_call_depth = 1; + } +/*-------------------------------------------------------- +** Is there room for a new AsynSrv_Open table entry? +*/ + if (AsynSrv_n_active >= MAX_OPEN) { + AsynSrv_errcode = ASYNSRV__NO_ROOM; /* There isn't! */ + return False; + } +/*-------------------------------------------------------- +** Is there room for a new connection entry? +*/ + if (AsynSrv_n_cnct >= AsynSrv_MAX_LINK) { + AsynSrv_errcode = ASYNSRV__NO_ROOM; /* There isn't! */ + return False; + } +/*-------------------------------------------------------- +** There's room for a new connection but, before going any +** further, do some quick checks on values in asyn_info. +*/ + if ((asyn_info->port <= 0) || + (asyn_info->port > 65535) || + (asyn_info->chan < 0) || + (asyn_info->chan > 255)) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; /* Something is bad! */ + return False; + } +/*-------------------------------------------------------- +** Set up a new connection. +*/ + StrJoin (AsynSrv_HPS_list[AsynSrv_n_cnct].host, + sizeof (AsynSrv_HPS_list[AsynSrv_n_cnct].host), + asyn_info->host, ""); + AsynSrv_HPS_list[AsynSrv_n_cnct].port = asyn_info->port; + /*--------------------------- + ** Get the Internet address of the server. + */ + rmt_inet_addr.s_addr = inet_addr (asyn_info->host); + if (rmt_inet_addr.s_addr != -1) { + rmt_inet_addr_pntr = &rmt_inet_addr; + }else { + rmt_hostent = gethostbyname (asyn_info->host); + if (rmt_hostent == NULL) { + AsynSrv_errcode = ASYNSRV__BAD_HOST; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save errno info */ + fprintf (stderr, "\nAsynSrv_OpenNew/gethostbyname: Failed to get Internet " + "address of \"%s\".\n", asyn_info->host); + return False; + } + rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0]; + } + /*--------------------------- + ** Create a TCP/IP socket for connecting to server and bind it. + */ + my_skt = socket (AF_INET, SOCK_STREAM, 0); + if (my_skt <= 0) { + AsynSrv_errcode = ASYNSRV__BAD_SOCKET; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, "\nAsynSrv_OpenNew/socket: Failed to create a socket.\n"); + return False; + } + lcl_sockname.sin_family = AF_INET; + lcl_sockname.sin_port = htons (0); + lcl_sockname.sin_addr.s_addr = 0; + status = bind (my_skt, (struct sockaddr *) &lcl_sockname, + sizeof (lcl_sockname)); + if (status == -1) { + close (my_skt); + AsynSrv_errcode = ASYNSRV__BAD_BIND; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, "\nAsynSrv_OpenNew/bind: Failed to bind socket.\n"); + return False; + } + /*--------------------------- + ** Set short time-out (VMS systems only) + */ +#ifdef __VMS + oto_len = sizeof (old_time_out); /* Save current time-out first */ + oto_status = getsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + old_time_out, &oto_len); + + if (oto_status == 0) { + time_out.val = AsynSrv_connect_tmo; /* Set new time-out */ + status = setsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + time_out.chars, sizeof (time_out)); + } +#endif + /*--------------------------- + ** Connect to RS-232-C Server. + */ + rmt_sockname_len = sizeof (rmt_sockname); + rmt_sockname.sin_family = AF_INET; + rmt_sockname.sin_port = htons (asyn_info->port); + rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr; + status = connect (my_skt, (struct sockaddr *) &rmt_sockname, + sizeof (rmt_sockname)); + if (status != 0) { + close (my_skt); + AsynSrv_errcode = ASYNSRV__BAD_CONNECT; + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); /* Save the errno info */ + fprintf (stderr, + "\nAsynSrv_OpenNew/connect: Failed to connect to server.\n"); + perror ("AsynSrv_OpenNew"); + return False; + } + /*--------------------------- + ** Restore time-out (VMS only) + */ +#ifdef __VMS + if (oto_status == 0) { + setsockopt (my_skt, IPPROTO_TCP, UCX$C_TCP_PROBE_IDLE, + old_time_out, oto_len); + } +#endif + /*--------------------------------------------------- + ** Setup the defaults in the AsynSrv__info data structure. + */ + asyn_info->skt = my_skt; /* Return socket number to caller */ + + asyn_info->protocol_code = 0; /* Ensure protocol_code set to "unknown" */ + memcpy (asyn_info->protocol_id, "\0\0\0\0", + sizeof (asyn_info->protocol_id)); + asyn_info->cmnd_hdr_len = 4; + strcpy (asyn_info->cmnd_fmt, "%04d"); + asyn_info->rply_hdr_len = 4; + strcpy (asyn_info->rply_fmt, "%4d"); + + sprintf (buff, "%04d", asyn_info->chan); /* Convert channel # to ASCII */ + memcpy (asyn_info->chan_char, buff, sizeof (asyn_info->chan_char)); + + sprintf (buff, "%04d", AsynSrv_msec_tmo/100); /* Set dflt time-out .. + ** .. (deci-secs) */ + memcpy (asyn_info->tmo, buff, sizeof (asyn_info->tmo)); + + memcpy (asyn_info->eot, AsynSrv_eot, sizeof (asyn_info->eot)); /* Set .. + ** .. dflt terminator(s) */ + asyn_info->max_replies = 0; + asyn_info->n_replies = 0; + asyn_info->idleHandler = NULL; + /* + ** Send a null command buffer to the server. This should give + ** a "protocol mismatch" error response and from this we can get + ** the actual protocol level supported by the server. + */ + status = AsynSrv_SendCmnds (asyn_info, &s_buff, &r_buff, NULL); + if (!status && (AsynSrv_errcode == ASYNSRV__BAD_PROT_LVL)) { + /* + ** As expected, we got a "protocol mismatch" error. + ** Save the server's protocol level for future use. + */ + memcpy (asyn_info->protocol_id, r_buff.s_pcol_lvl, + sizeof (r_buff.s_pcol_lvl)); + if (strncmp (r_buff.s_pcol_lvl, RS__PROTOCOL_ID_V01B, + strlen (RS__PROTOCOL_ID_V01B)) == 0) { + asyn_info->protocol_code = RS__PROTOCOL_CODE_V01B; + asyn_info->cmnd_hdr_len = 4; + strcpy (asyn_info->cmnd_fmt, "%04d"); + asyn_info->rply_hdr_len = 4; + strcpy (asyn_info->rply_fmt, "%4d"); + }else if (strncmp (r_buff.s_pcol_lvl, RS__PROTOCOL_ID, + strlen (RS__PROTOCOL_ID)) == 0) { + asyn_info->protocol_code = RS__PROTOCOL_CODE; + asyn_info->cmnd_hdr_len = 2; + strcpy (asyn_info->cmnd_fmt, "%02d"); + asyn_info->rply_hdr_len = 2; + strcpy (asyn_info->rply_fmt, "%2d"); + }else { + close (my_skt); + asyn_info->skt = 0; + fprintf (stderr, + "\nAsynSrv_OpenNew: Server protocol level is unrecognised.\n" + " Server level is \"%4s\"\n", r_buff.s_pcol_lvl); + return False; + } + }else { + close (my_skt); + asyn_info->skt = 0; + AsynSrv_errcode = ASYNSRV__BAD_PROT_LVL; + fprintf (stderr, + "\nAsynSrv_OpenNew: Problem getting protocol level of Server!\n"); + return False; + } + /*--------------------------------------------------- + ** Complete the setup of the connection table entry + */ + AsynSrv_HPS_list[AsynSrv_n_cnct].skt = my_skt; + AsynSrv_HPS_list[AsynSrv_n_cnct].protocol_code = asyn_info->protocol_code; + memcpy (AsynSrv_HPS_list[AsynSrv_n_cnct].protocol_id, + asyn_info->protocol_id, sizeof (asyn_info->protocol_id)); + AsynSrv_HPS_list[AsynSrv_n_cnct].cmnd_hdr_len = asyn_info->cmnd_hdr_len; + AsynSrv_HPS_list[AsynSrv_n_cnct].rply_hdr_len = asyn_info->rply_hdr_len; + AsynSrv_HPS_list[AsynSrv_n_cnct].usage_cnt = 1; + AsynSrv_HPS_list[AsynSrv_n_cnct].status = 1; + AsynSrv_n_cnct++; + + AsynSrv_active[AsynSrv_n_active] = /* Remember the open in case .. */ + asyn_info; /* .. there's a force-exit */ + AsynSrv_n_active++; + + AsynSrv_errcode = AsynSrv_errno = AsynSrv_vaxc_errno = 0; + AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_SendCmnds: Send commands to RS232C server. +*/ + int AsynSrv_SendCmnds ( +/* ================= +*/ struct AsynSrv__info *asyn_info, + struct RS__MsgStruct *send_buff, + struct RS__RespStruct *rcve_buff, + ...) { /* Now we have list of commands - + ** char *txt = pntr to cmnd strng + ** Terminate list with *txt = NULL. + */ + int i, status, c_len, size, max_size, ncmnds; + int bytes_to_come, bytes_left; + char *nxt_byte_ptr; + char err_text[80]; + char text[20]; + va_list ap; /* Pointer to variable args */ + char *txt_ptr; + char *cmnd_lst_ptr; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_SendCmnds"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + memset (rcve_buff->msg_size, + '0', sizeof (rcve_buff->msg_size)); + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Build message for server from the list of commands. + */ + asyn_info->max_replies = asyn_info->n_replies = 0; + + asyn_info->msg_id++; /* Set up an incrementing message id */ + if (asyn_info->msg_id > 9999) asyn_info->msg_id = 1; + sprintf (send_buff->msg_id, "%04d", asyn_info->msg_id); + + memcpy (send_buff->c_pcol_lvl, asyn_info->protocol_id, + sizeof (send_buff->c_pcol_lvl)); + + memcpy (send_buff->serial_port, asyn_info->chan_char, + sizeof (send_buff->serial_port)); + + memcpy (send_buff->tmo, asyn_info->tmo, sizeof (send_buff->tmo)); + + memcpy (send_buff->terms, asyn_info->eot, sizeof (send_buff->terms)); + + memcpy (send_buff->n_cmnds, "0000", sizeof (send_buff->n_cmnds)); + + va_start (ap, rcve_buff); /* Set up var arg machinery */ + + txt_ptr = va_arg (ap, char *); /* Get pntr to next cmnd string */ + ncmnds = 0; + cmnd_lst_ptr = &send_buff->cmnds[0]; + bytes_left = sizeof (*send_buff) - + OffsetOf (struct RS__MsgStruct, cmnds[0]); + + while (txt_ptr != NULL) { + c_len = strlen (txt_ptr); + size = asyn_info->cmnd_hdr_len + c_len; + if (size > bytes_left) { + AsynSrv_errcode = ASYNSRV__BAD_SEND_LEN; /* Too much to send */ + fprintf (stderr, "\nAsynSrv_SendCmnds/send: too much to send" + " - request ignored.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + }else { + sprintf (cmnd_lst_ptr, asyn_info->cmnd_fmt, c_len); + if (cmnd_lst_ptr[asyn_info->cmnd_hdr_len] != '\0') { + AsynSrv_errcode = ASYNSRV__BAD_CMND_LEN; + fprintf (stderr, "\nAsynSrv_SendCmnds/send: command too long -" + " - request ignored.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + } + cmnd_lst_ptr += asyn_info->cmnd_hdr_len; + strcpy (cmnd_lst_ptr, txt_ptr); + cmnd_lst_ptr += c_len; + ncmnds++; + bytes_left = bytes_left - size; + txt_ptr = va_arg (ap, char *); + } + } + sprintf (text, "%04d", ncmnds); + memcpy (send_buff->n_cmnds, text, sizeof (send_buff->n_cmnds)); + + size = cmnd_lst_ptr - send_buff->msg_id; + size = (size + 3) & (~3); /* Round up to multiple of 4 */ + sprintf (text, "%04d", size); + memcpy (send_buff->msg_size, text, sizeof (send_buff->msg_size)); + + size += sizeof (send_buff->msg_size); + status = send (asyn_info->skt, + (char *) send_buff, size, 0); + if (status != size) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_SEND; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/send: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_SEND_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/send: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_NET; /* It's some other net problem */ + perror ("AsynSrv_SendCmnds/send"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendCmnds/send: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + + if (asyn_info->idleHandler != NULL) { /* MZ. */ + sscanf(asyn_info->tmo, "%4d", &i); /* Decode timeout from ASCII .. + ** .. encoded deci-sec */ + asyn_info->idleHandler (i*150, asyn_info->skt); /* Wait for an event .. + ** .. on asyn_info->skt or a .. + ** .. timeout of 1.5*tmo */ + } + + size = sizeof (rcve_buff->msg_size); + status = recv (asyn_info->skt, rcve_buff->msg_size, size, 0); + if (status != size) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_RECV; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_RECV_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_NET; /* It's some other net problem */ + perror ("AsynSrv_SendCmnds/recv"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + if (sscanf (rcve_buff->msg_size, "%4d", &bytes_to_come) != 1) { + AsynSrv_errcode = ASYNSRV__BAD_NOT_BCD; /* Header not an ASCII BCD integer */ + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: non-BCD byte count" + " - link to server force-closed.\n"); + return False; + } + max_size = sizeof (*rcve_buff) - size; + if (bytes_to_come > max_size) { + AsynSrv_errcode = ASYNSRV__BAD_RECV_LEN; + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: pending message length too big" + " - flushing ...\n"); + nxt_byte_ptr = &rcve_buff->msg_size[size]; + while (bytes_to_come > 0) { /* Flush out the incoming message */ + bytes_left = bytes_to_come; + if (bytes_left > max_size) bytes_left = max_size; + status = recv (asyn_info->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + AsynSrv_errcode = ASYNSRV__BAD_FLUSH; /* TCP/IP problem during flush */ + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv: network problem during" + " flush.\nLink to server force-closed.\n"); + return False; + } + bytes_to_come = bytes_to_come - status; + } + fprintf (stderr, "\n flushed OK.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + }else { + nxt_byte_ptr = &rcve_buff->msg_size[size]; + bytes_left = bytes_to_come; + while (bytes_left > 0) { /* Read the rest of the response */ + status = recv (asyn_info->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_RECV1; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv/1: probable network " + "problem"); + }else { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_RECV1_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmnds/recv/1: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV1_NET; /* It's some other net fault */ + perror ("AsynSrv_SendCmnds/recv/1"); + } + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + bytes_left = bytes_left - status; + nxt_byte_ptr = nxt_byte_ptr + status; + } + if (strncmp (asyn_info->protocol_id, rcve_buff->s_pcol_lvl, + sizeof (rcve_buff->s_pcol_lvl)) != 0) { + AsynSrv_errcode = ASYNSRV__BAD_PROT_LVL; /* Protocol level is bad */ + return False; + } + if ((sscanf (rcve_buff->n_rply, "%4d", &asyn_info->max_replies) != 1) || + (asyn_info->max_replies < 0)) { + AsynSrv_errcode = ASYNSRV__BAD_REPLY; /* Reply is bad */ + if (AsynSrv_call_depth < 5) { /* Add reply to routine stack */ + bytes_to_come = bytes_to_come + 4; + if (bytes_to_come >= sizeof (AsynSrv_routine[0])) + bytes_to_come = sizeof (AsynSrv_routine[0]) - 1; + for (i=0; imsg_size[i] == '\0') + rcve_buff->msg_size[i] = '.'; + } + rcve_buff->msg_size[bytes_to_come] = '\0'; + strcpy (AsynSrv_routine[AsynSrv_call_depth], rcve_buff->msg_size); + AsynSrv_call_depth++; + } + return False; + } + } + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_SendCmndsBig: Same as AsynSrv_SendCmnds but with +** user defined buffer sizes. +*/ + int AsynSrv_SendCmndsBig ( +/* ==================== +*/ struct AsynSrv__info *asyn_info, + struct RS__MsgStruct *send_buff, + int send_buff_size, + struct RS__RespStruct *rcve_buff, + int rcve_buff_size, + ...) { /* Now we have list of commands - + ** char *txt = pntr to cmnd strng + ** Terminate list with *txt = NULL. + */ + int i, status, size, max_size, ncmnds; + int bytes_to_come, bytes_left; + char *nxt_byte_ptr; + char err_text[80]; + char text[20]; + va_list ap; /* Pointer to variable args */ + int *c_len, s_len; + char *txt_ptr; + char *cmnd_lst_ptr; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_SendCmndsBig"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + memset (rcve_buff->msg_size, + '0', sizeof (rcve_buff->msg_size)); + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Build message for server from the list of commands. + */ + if (send_buff_size < 64 || rcve_buff_size < 64) { + AsynSrv_errcode = ASYNSRV__BAD_PAR; return False;} + + asyn_info->max_replies = asyn_info->n_replies = 0; + + asyn_info->msg_id++; /* Set up an incrementing message id */ + if (asyn_info->msg_id > 9999) asyn_info->msg_id = 1; + sprintf (send_buff->msg_id, "%04d", asyn_info->msg_id); + + memcpy (send_buff->c_pcol_lvl, asyn_info->protocol_id, + sizeof (send_buff->c_pcol_lvl)); + + memcpy (send_buff->serial_port, asyn_info->chan_char, + sizeof (send_buff->serial_port)); + + memcpy (send_buff->tmo, asyn_info->tmo, sizeof (send_buff->tmo)); + + memcpy (send_buff->terms, asyn_info->eot, sizeof (send_buff->terms)); + + memcpy (send_buff->n_cmnds, "0000", sizeof (send_buff->n_cmnds)); + + va_start (ap, rcve_buff_size); /* Set up var arg machinery */ + + c_len = va_arg (ap, int *); /* Get pntr to length of next cmnd string */ + ncmnds = 0; + cmnd_lst_ptr = &send_buff->cmnds[0]; + bytes_left = send_buff_size - + OffsetOf (struct RS__MsgStruct, cmnds[0]); + + while (c_len != NULL) { + txt_ptr = va_arg (ap, char *); + s_len = *c_len; + if (s_len <= 0) s_len = strlen (txt_ptr); + size = asyn_info->cmnd_hdr_len + s_len; + if (size > bytes_left) { + AsynSrv_errcode = ASYNSRV__BAD_SEND_LEN; /* Too much to send */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/send: too much to send" + " - request ignored.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + } + sprintf (cmnd_lst_ptr, asyn_info->cmnd_fmt, s_len); + if (cmnd_lst_ptr[asyn_info->cmnd_hdr_len] != '\0') { + AsynSrv_errcode = ASYNSRV__BAD_CMND_LEN; + fprintf (stderr, "\nAsynSrv_SendCmndsBig/send: command too long -" + " - request ignored.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + } + cmnd_lst_ptr += asyn_info->cmnd_hdr_len; + memcpy (cmnd_lst_ptr, txt_ptr, s_len); + cmnd_lst_ptr += s_len; + ncmnds++; + bytes_left = bytes_left - size; + c_len = va_arg (ap, int *); + } + sprintf (text, "%04d", ncmnds); + memcpy (send_buff->n_cmnds, text, sizeof (send_buff->n_cmnds)); + + size = cmnd_lst_ptr - send_buff->msg_id; + size = (size + 3) & (~3); /* Round up to multiple of 4 */ + sprintf (text, "%04d", size); + memcpy (send_buff->msg_size, text, sizeof (send_buff->msg_size)); + + size += sizeof (send_buff->msg_size); + status = send (asyn_info->skt, + (char *) send_buff, size, 0); + if (status != size) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_SEND; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/send: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_SEND_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/send: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_NET; /* It's some other net problem */ + perror ("AsynSrv_SendCmndsBig/send"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/send: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + + size = sizeof (rcve_buff->msg_size); + status = recv (asyn_info->skt, rcve_buff->msg_size, size, 0); + if (status != size) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_RECV; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_RECV_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_NET; /* It's some other net problem */ + perror ("AsynSrv_SendCmndsBig/recv"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + if (sscanf (rcve_buff->msg_size, "%4d", &bytes_to_come) != 1) { + AsynSrv_errcode = ASYNSRV__BAD_NOT_BCD; /* Header not an ASCII BCD integer */ + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: non-BCD byte count" + " - link to server force-closed.\n"); + return False; + } + max_size = rcve_buff_size - size; + if (bytes_to_come > max_size) { + AsynSrv_errcode = ASYNSRV__BAD_RECV_LEN; + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: pending message length " + "too big - flushing ...\n"); + nxt_byte_ptr = &rcve_buff->msg_size[size]; + while (bytes_to_come > 0) { /* Flush out the incoming message */ + bytes_left = bytes_to_come; + if (bytes_left > max_size) bytes_left = max_size; + status = recv (asyn_info->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + AsynSrv_errcode = ASYNSRV__BAD_FLUSH; /* TCP/IP problem during flush */ + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv: network problem during" + " flush.\nLink to server force-closed.\n"); + return False; + } + bytes_to_come = bytes_to_come - status; + } + fprintf (stderr, "\n flushed OK.\n"); + memset (rcve_buff->msg_size, '0', sizeof (rcve_buff->msg_size)); + return False; + }else { + nxt_byte_ptr = &rcve_buff->msg_size[size]; + bytes_left = bytes_to_come; + while (bytes_left > 0) { /* Read the rest of the response */ + status = recv (asyn_info->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_RECV1; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv/1: probable network " + "problem"); + }else { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_RECV1_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendCmndsBig/recv/1: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV1_NET; /* It's some other net fault */ + perror ("AsynSrv_SendCmndsBig/recv/1"); + } + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + bytes_left = bytes_left - status; + nxt_byte_ptr = nxt_byte_ptr + status; + } + if (strncmp (asyn_info->protocol_id, rcve_buff->s_pcol_lvl, + sizeof (rcve_buff->s_pcol_lvl)) != 0) { + AsynSrv_errcode = ASYNSRV__BAD_PROT_LVL; /* Protocol level is bad */ + return False; + } + if ((sscanf (rcve_buff->n_rply, "%4d", &asyn_info->max_replies) != 1) || + (asyn_info->max_replies < 0)) { + AsynSrv_errcode = ASYNSRV__BAD_REPLY; /* Reply is bad */ + if (AsynSrv_call_depth < 5) { /* Add reply to routine stack */ + bytes_to_come = bytes_to_come + 4; + if (bytes_to_come >= sizeof (AsynSrv_routine[0])) + bytes_to_come = sizeof (AsynSrv_routine[0]) - 1; + for (i=0; imsg_size[i] == '\0') + rcve_buff->msg_size[i] = '.'; + } + rcve_buff->msg_size[bytes_to_come] = '\0'; + strcpy (AsynSrv_routine[AsynSrv_call_depth], rcve_buff->msg_size); + AsynSrv_call_depth++; + } + return False; + } + } + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_SendSpecCmnd: Send a "special" command to an +** RS232C server. +*/ + int AsynSrv_SendSpecCmnd ( +/* ==================== +*/ struct AsynSrv__info *asyn_info, + char *cmnd) { + + int status; + char rply[8]; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_SendSpecCmnd"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Send the message to the server. + */ + status = send (asyn_info->skt, cmnd, 4, 0); + if (status != 4) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_SEND; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/send: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_SEND_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/send: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_NET; /* It's some other net problem */ + perror ("AsynSrv_SendSpecCmnd/send"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_SEND_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/send: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + + status = recv (asyn_info->skt, rply, 4, 0); + if (status != 4) { + GetErrno (&AsynSrv_errno, &AsynSrv_vaxc_errno); + if (status == 0) { + AsynSrv_errcode = ASYNSRV__BAD_RECV; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/recv: probable network problem"); + }else if (status == -1) { + if (AsynSrv_errno == EPIPE) { + AsynSrv_errcode = ASYNSRV__BAD_RECV_PIPE; /* Server exited (probably) */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/recv: broken network pipe"); + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_NET; /* It's some other net problem */ + perror ("AsynSrv_SendSpecCmnd/recv"); + } + }else { + AsynSrv_errcode = ASYNSRV__BAD_RECV_UNKN; /* TCP/IP problems */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/recv: probable TCP/IP problem"); + } + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, " - link to server force-closed.\n"); + return False; + } + if (memcmp (cmnd, rply, 4) != 0) { + AsynSrv_errcode = ASYNSRV__BAD_NOT_BCD; /* Message not echoed OK */ + AsynSrv_Close (asyn_info, True); /* Force close TCP/IP connection */ + fprintf (stderr, "\nAsynSrv_SendSpecCmnd/recv: command not echoed correctly" + " - link to server force-closed.\n"); + return False; + } + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return True; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Trace: Send a "TRACE" request to RS232C server. +*/ + int AsynSrv_Trace ( +/* ============= +*/ struct AsynSrv__info *asyn_info, + int state) { + + int status; + char cmnd[8], rply[8]; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_Trace"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Select message for server according to value of state. + */ + if (state) { + strcpy (cmnd, "-002"); + }else { + strcpy (cmnd, "-003"); + } + /*---------------------------------------------- + ** Send message and get reply. + */ + status = AsynSrv_SendSpecCmnd (asyn_info, cmnd); + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return status; + } +/* +**--------------------------------------------------------------------------- +** AsynSrv_Trace_Write: Send a Trace_Write command to +** RS232C server. +*/ + int AsynSrv_Trace_Write ( +/* =================== +*/ struct AsynSrv__info *asyn_info) { + + int status; + char cmnd[8], rply[8]; + /*---------------------------------------------- + ** Pre-set the routine name (in case of error) + */ + if (AsynSrv_errcode == 0 && AsynSrv_call_depth < 5) { + strcpy (AsynSrv_routine[AsynSrv_call_depth], "AsynSrv_Trace_Write"); + AsynSrv_call_depth++; + } + /*---------------------------------------------- + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. The connection may + ** also be marked to have been forcefully closed. + */ + if (asyn_info->skt <= 0) { + if ((AsynSrv_errcode == 0) && (asyn_info->skt < 0)) { + AsynSrv_errcode = ASYNSRV__FORCED_CLOSED; + } + return False; + } + /*---------------------------------------------- + ** Send message and get reply. + */ + status = AsynSrv_SendSpecCmnd (asyn_info, "-005"); + + if (AsynSrv_errcode == 0) AsynSrv_call_depth--; + return status; + } +/*-------------------------------------------- End of AsynSrv_Utility.C -----*/ diff --git a/site_ansto/hardsup/c_interfaces.c b/site_ansto/hardsup/c_interfaces.c new file mode 100644 index 00000000..a514c64d --- /dev/null +++ b/site_ansto/hardsup/c_interfaces.c @@ -0,0 +1,472 @@ +#define ident "1A05" +#ifdef VAXC +#module C_INTERFACES ident +#endif +#ifdef __DECC +#pragma module C_INTERFACES ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Computing Section | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]C_INTERFACES.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1993 +** +** C_INTERFACES.C provides some routines which make it easier for C programs +** to call some of the Fortran routines in SINQ.OLB. +** +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/job sinq_c_tlb mad_lib:sinq_c_tlb.tlb + $ define/job sinq_olb mad_lib:sinq.olb + $ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces debug + $ + $ define/job sinq_olb mad_lib:sinq.olb + $ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces + +** +** Updates: +** 1A01 16-Nov-1993 DM. Initial version. +** 1A02 24-Nov-1994 DM. Make compatible with DEC C (as opposed to VAX C) +** 1A03 28-Nov-1994 DM. Add the TT_PORT_... entry points. +**==================================================================== +** The following entry pointd are included: +** C_log_arr_get : interface routine from C to LOG_ARR_GET. +** C_log_flt_get : interface routine from C to LOG_FLT_GET. +** C_log_int_get : interface routine from C to LOG_INT_GET. +** C_log_str_get : interface routine from C to LOG_STR_GET. +** +** C_str_edit : interface routine to STR_EDIT. +** +** C_tt_port_connect : interface routine to TT_PORT_CONNECT. +** C_tt_port_disconnect: interface routine to TT_PORT_DISCONNECT. +** C_tt_port_io : interface routine to TT_PORT_IO. +** C_tt_port_config : interface routine to TT_PORT_CONFIG. +**==================================================================== +** Global Definitions +*/ +#ifdef VAXC +#include stdio +#include descrip +#include string +#include sinq_prototypes +#else +#include +#include +#include +#include +#endif +/*-------------------------------------------------------------------------- +** Global Variables +*/ + extern int C_gbl_status = 0; + extern struct dsc$descriptor_s C_name_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; +/*-------------------------------------------------------------------------- +** Old-style prototypes of routines which we are +** bridging to. +*/ + int log_arr_get (); + int log_int_get (); + int log_flt_get (); + int log_str_get (); + + int str_edit (); + + int tt_port_connect (); + int tt_port_disconnect (); + int tt_port_io (); + int tt_port_config (); +/* --------------------------------------------------------------------------*/ + int C_log_arr_get (char *name, int arr_size, int *value, int indx) { +/* ============= +** +** This routine is useful for calling LOG_ARR_GET from a C program. +** +** Inputs: +** name - a pointer to the zero-terminated logical name. +** arr_size - the number of elements in the array value. +** indx - the index of the logical name. +** Outputs: +** value - an array of size arr_size set to the values converted +** to binary. +** Return status: +** the return status of the function is zero (false) if LOG_ARR_GET +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of LOG_ARR_GET. +** C_name_desc - set up as a string descriptor for name. It can +** be used to generate an error message if return status == 0. +*/ + C_name_desc.dsc$w_length = strlen (name); + C_name_desc.dsc$a_pointer = name; + + C_gbl_status = log_arr_get (&C_name_desc, &arr_size, value, &indx); + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_log_int_get (char *name, long int *value, int indx) { +/* ============= +** +** This routine is useful for calling LOG_INT_GET from a C program. +** +** Inputs: +** name - a pointer to the zero-terminated logical name. +** indx - the index of the logical name. +** Outputs: +** value - the value of the logical converted to binary. +** Return status: +** the return status of the function is zero (false) if LOG_INT_GET +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of LOG_INT_GET. +** C_name_desc - set up as a string descriptor for name. It can +** be used to generate an error message if return status == 0. +*/ + C_name_desc.dsc$w_length = strlen (name); + C_name_desc.dsc$a_pointer = name; + + C_gbl_status = log_int_get (&C_name_desc, value, &indx); + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_log_flt_get (char *name, float *value, int indx) { +/* ============= +** +** This routine is useful for calling LOG_FLT_GET from a C program. +** +** Inputs: +** name - a pointer to the zero-terminated logical name. +** indx - the index of the logical name. +** Outputs: +** value - the value of the logical converted to binary. +** Return status: +** the return status of the function is zero (false) if LOG_FLT_GET +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of LOG_FLT_GET. +** C_name_desc - set up as a string descriptor for name. It can +** be used to generate an error message if return status == 0. +*/ + C_name_desc.dsc$w_length = strlen (name); + C_name_desc.dsc$a_pointer = name; + + C_gbl_status = log_flt_get (&C_name_desc, value, &indx); + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_log_str_get (char *name, char *value, int val_size, int indx) { +/* ============= +** +** This routine is useful for calling LOG_STR_GET from a C program. +** +** Inputs: +** name - a pointer to the zero-terminated logical name. +** val_size - the size of the value string. +** indx - the index of the logical name. +** Outputs: +** value - zero-terminated string giving the value of the logical. +** Trailing space characters will have been stripped. +** Return status: +** the return status of the function is zero (false) if LOG_STR_GET +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of LOG_STR_GET. +** C_name_desc - set up as a string descriptor for name. It can +** be used to generate an error message if return status == 0. +*/ + struct dsc$descriptor_s my_val_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + + C_name_desc.dsc$w_length = strlen (name); + C_name_desc.dsc$a_pointer = name; + + my_val_desc.dsc$w_length = val_size - 1; + my_val_desc.dsc$a_pointer = value; + + C_gbl_status = log_str_get (&C_name_desc, &my_val_desc, &indx); + value[val_size - 1] = 0; /* Zero-terminate the string */ + + if (C_gbl_status & 1) { /* If success, strip trailing spaces */ + while ((strlen (value) > 0) && (value[strlen (value) - 1] == ' ')) { + value[strlen (value) - 1] = 0; + } + } + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_str_edit (char *out, char *in, char *ctrl, int *length) { +/* ========== +** +** This routine is useful for calling STR_EDIT from a C program. +** +** Inputs: +** in - the string to be edited. +** ctrl - the string specifying what editing is to be done. +** Outputs: +** out - the edited string. The maximum size of this string must +** be specified as input parameter *length. The string +** will be zero terminated on return. +** Modified: +** *length - an integer specifying, on input, the length of "out" in +** bytes. This must include room for the zero termination. +** On return, length will be set to the number of characters +** copied to "out" (not counting the zero termination byte). +** Return status: +** the return status of the function is zero (false) if STR_EDIT +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of STR_EDIT. +*/ + struct dsc$descriptor_s out_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + struct dsc$descriptor_s in_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + struct dsc$descriptor_s ctrl_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + + out_desc.dsc$w_length = *length - 1; + out_desc.dsc$a_pointer = out; + + in_desc.dsc$w_length = strlen (in); + in_desc.dsc$a_pointer = in; + + ctrl_desc.dsc$w_length = strlen (ctrl); + ctrl_desc.dsc$a_pointer = ctrl; + + C_gbl_status = str_edit (&out_desc, &in_desc, &ctrl_desc, length); + if (*length >= 0) { /* zero-terminate the output string */ + out[*length] = '\0'; + }else { + out[0] = '\0'; + } + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_tt_port_connect (int *hndl, int *chan, char *lognam, char *pwd) { +/* ================= +** +** This routine is useful for calling TT_PORT_CONNECT from a C program. +** +** Inputs: +** lognam - a zero-terminated string specifying a logical name which +** defines the RS-232-C port to be connected. See description +** of TT_PORT_CONNECT for full details. +** pwd - a zero-terminated string specifying an optional password. +** This is the password associated with a terminal server +** service. See description of TT_PORT_CONNECT for full +** details. Specify NULL if no password. +** Outputs: +** hndl - an integer handle identifying the connection. It will be +** the address of a dynamically allocated data structure. +** chan - an integer (actually only 16 bit) giving the I/O channel +** associated with the connection. This can be used in QIO +** system calls to the terminal driver. +** Return status: +** the return status of the function is zero (false) if TT_PORT_CONNECT +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONNECT. +*/ + struct dsc$descriptor_s lognam_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + struct dsc$descriptor_s pwd_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + lognam_desc.dsc$w_length = strlen (lognam); + lognam_desc.dsc$a_pointer = lognam; + + if (pwd != NULL) { + pwd_desc.dsc$w_length = strlen (pwd); + pwd_desc.dsc$a_pointer = pwd; + C_gbl_status = tt_port_connect ( + hndl, chan, &lognam_desc, &pwd_desc); + }else { + C_gbl_status = tt_port_connect (hndl, chan, &lognam_desc, NULL); + } + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_tt_port_disconnect (int *hndl) { +/* ==================== +** +** This routine is useful for calling TT_PORT_DISCONNECT from a C program. +** +** Inputs: +** hndl - the integer handle identifying the connection as returned +** by C_tt_port_connect. It is the address of a dynamically +** allocated data structure which will also be released +** after the connection has been closed. +** Return status: +** the return status of the function is zero (false) if TT_PORT_DISCONNECT +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of TT_PORT_DISCONNECT. +*/ + C_gbl_status = tt_port_disconnect (hndl); + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_tt_port_io ( +/* ============ +*/ int *hndl, + char *rqst, + char *term, + char *answ, + int *answ_len, /* Attention -- Read/Write argument!! */ + int flush, + int tmo) { +/* +** This routine is useful for calling TT_PORT_IO from a C program. +** Refer to the DELTAT.OLB description of TT_PORT_IO to clarify any +** uncertainties in the following description. Note that all arguments +** must be present (there is no portable method in C of getting the +** number of arguments in the call!). +** Inputs: +** hndl - the integer handle identifying the connection as returned +** by C_tt_port_connect. +** rqst - an optional zero-terminated string specifying a character +** string to be sent to the port. Specify NULL to not send +** any characters to the port. +** term - an optional zero-terminated string specifying a list of +** terminating characters for input read from the port. +** Specify NULL to terminate input on an exact character cnt. +** flush - an integer specifying if the type-ahead buffer should be +** flushed before the operation. If non-zero, the buffer +** is flushed. +** tmo - an integer (recommended value = 2) specifying a read +** time-out in seconds. Zero or negative indicates infinity. +** Outputs: +** answ - an optional string buffer to receive characters read from +** the port. If answ is not NULL, answ_len must also be +** not NULL. On return, answ will be zero terminated. The +** terminating character, if any (there is no terminating +** char if the buffer overflows) and if there is room in +** the buffer, will follow the zero character. No padding is +** done. If answ is NULL, no characters are read from the +** port. +** Modify: +** answ_len - an integer specifying, on input, the length of answ in +** bytes. This must include room for the zero termination. +** On return, answ_len will be set to the number of +** characters read (not counting the zero termination byte or +** any terminating character). +** Return status: +** the return status of the function is zero (false) if TT_PORT_IO +** returns an error (even) condition code. +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of TT_PORT_IO. +*/ + struct dsc$descriptor_s rqst_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + struct dsc$descriptor_s term_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + struct dsc$descriptor_s answ_desc = {0, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + 0}; + char *my_rqst = NULL; + char *my_term = NULL; + char *my_answ = NULL; + + int my_answ_len = 0; + int my_flush = 1; + int my_tmo = 2; + + my_tmo = tmo; + if (my_tmo < 0) my_tmo = 0; + my_flush = flush; + if (my_flush != 0) my_flush = 1; + if (answ != NULL) { + if (answ_len == 0) { + printf ("C_tt_port_io -- argument error.\n"); + printf (" %s\n", + "answ_len must be present if answ is present."); + C_gbl_status = FALSE; + return FALSE; + } + answ_desc.dsc$w_length = *answ_len - 1; + answ_desc.dsc$a_pointer = answ; + } + if (term != NULL) { + term_desc.dsc$w_length = strlen (term); + term_desc.dsc$a_pointer = term; + } + if (rqst != NULL) { + rqst_desc.dsc$w_length = strlen (rqst); + rqst_desc.dsc$a_pointer = rqst; + } + C_gbl_status = tt_port_io (hndl, &rqst_desc, &term_desc, + &answ_desc, &my_answ_len, &my_flush, &my_tmo); + if (answ_desc.dsc$w_length > 0) { /* Process any input string */ + if (answ_desc.dsc$w_length > my_answ_len) { /* Room for terminator? */ + answ[my_answ_len+1] = answ[my_answ_len]; /* Yes, so move it. */ + } + answ[my_answ_len] = '\0'; /* Put in null terminator */ + *answ_len = my_answ_len; /* Return value to caller */ + } + + return (C_gbl_status & 1); + } +/*--------------------------------------------------------------------------*/ + int C_tt_port_config ( +/* ================ +*/ int *hndl, + int mask) { +/* +** This routine is useful for calling TT_PORT_CONFIG from a C program. +** Refer to the DELTAT.OLB description of TT_PORT_CONFIG to clarify any +** uncertainties in the following description. +** Inputs: +** hndl - the integer handle identifying the connection as returned +** by C_tt_port_connect. +** mask - an integer specifying the configuration options. Set bits +** TT_PORT__NO_RETRY = 0x0001 to suppress retries on error +** TT_PORT__NO_SIG = 0x0002 to suppress signals on error +** Outputs: +** None +** Modify: +** None +** Return status: +** always non-zero (true). +** Global variables: +** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONFIG. +*/ + C_gbl_status = tt_port_config (hndl, &mask); + + return (C_gbl_status & 1); + } +/*=========================================== End of C_INTERFACES.C ========*/ diff --git a/site_ansto/hardsup/cd_obj b/site_ansto/hardsup/cd_obj new file mode 100644 index 00000000..fc5b4b65 --- /dev/null +++ b/site_ansto/hardsup/cd_obj @@ -0,0 +1 @@ +cd ../../obj/$SICS_VERSION/psi/hardsup diff --git a/site_ansto/hardsup/dillutil.h b/site_ansto/hardsup/dillutil.h new file mode 100644 index 00000000..b1ac9c33 --- /dev/null +++ b/site_ansto/hardsup/dillutil.h @@ -0,0 +1,108 @@ +/*--------------------------------------------------------------------------- + D I L U U T I L + + A few utility functions for talking to Dillution temperature controller + CCO-510/ AVSI via the SINQ setup: TCP/IP--MAC--RS-232--DILLU. + + This controller is weird in that way, that is accepts temperatures as + resistance values in Ohms. Therefore a translation table is required + in order to convert from Kelvin to Ohms. + + Mark Koennecke, October 1997 + +----------------------------------------------------------------------------*/ +#ifndef SINQDILLU +#define SINQDILLU +#include +#include "table.h" + +/*----------------------- ERRORCODES-------------------------------------- + Most functions return a negative error code on failure. Error codes + defined are those defined for serialsinq plus a few additional ones: +*/ +#define DILLU__FILENOTFOUND -710 +#define DILLU__NODILLFILE -711 +#define DILLU__ERRORTABLE -712 +#define DILLU__BADREAD -713 +#define DILLU__SILLYANSWER -714 +#define DILLU__READONLY -715 +#define DILLU__OUTOFRANGE -716 +#define DILLU__BADMALLOC -717 +#define DILLU__NODILLUFOUND -711 +/*------------------------------------------------------------------------*/ + typedef struct __DILLU { + void *pData; + pSTable pTranstable; + int iReadOnly; + } DILLU; + + typedef struct __DILLU *pDILLU; + +/*-----------------------------------------------------------------------*/ + int DILLU_Open(pDILLU *pData,char *pHost, int iPort, int iChannel, + int iMode, char *pTransFile); + /***** creates an DILLU datastructure and opens a connection to the ITCL4 + controller. Input Parameters are: + the hostname + the port number + the RS-232 channel number on the Mac. + iMode: 1 for ReadOnly, 0 for normal mode + pTransFile: name and path of the temperature ohms + trnslation file. + + Return values are 1 for success, a negative error code on + failure. + + */ + + void DILLU_Close(pDILLU *pData); + /****** close a connection to an DILLU controller and frees its + data structure. The only parameter is a pointer to the data + structure for this controller. This pointer will be invalid after + this call. + */ + + int DILLU_Config(pDILLU *pData, int iTmo); + /***** configure some aspects of a DILLU temperature controller. + The parameter are: + - a pointer to the data structure for the controller as + returned by Open_DILLU + - a value for the connection timeout + The function returns 1 on success, a negative error code on + failure. + */ + + int DILLU_Send(pDILLU *pData, char *pCommand, char *pReply, int iLen); + /******* send a the command in pCommand to the DILLU controller. + A possible reply is returned in the buffer pReply. + Maximum iLen characters are copied to pReply. + The first parameter is a pointer to a DILLU data structure + as returned by Open_DILLU. + + Return values are 1 for success, a negative error code on + failure. + */ + + int DILLU_Read(pDILLU *pData, float *fVal); + /****** + Reads the current temperature at the controller + + Return values are 1 for success, a negative error code on + failure. + */ + + int DILLU_Set(pDILLU *pData, float fVal); + /****** sets a new preset temperature in the DILL temperature + controller. Parameters are: + - a pointer to a DILLU data structure as returned by Open_DILLU. + - the new preset value. + + Return values are 1 for success, a negative error code on + failure. + */ + + void DILLU_Error2Text(pDILLU *pData, int iCode, char *pError, int iLen); + +#endif + + diff --git a/site_ansto/hardsup/el734_def.h b/site_ansto/hardsup/el734_def.h new file mode 100644 index 00000000..f3a64379 --- /dev/null +++ b/site_ansto/hardsup/el734_def.h @@ -0,0 +1,73 @@ +#ifndef _el734_def_ +#define _el734_def_ +/*------------------------------------------------ EL734_DEF.H Ident V01R +*/ +#include +#include +#include + +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif + +#ifndef _EL734_errcodes_ +#define _EL734_errcodes_ +#include +#endif + +#define MAX_MOT 12 + +enum EL734_Requests {FULL__STATUS, + SHORT__STATUS}; +/* +** Structure to which the EL734_Open handle points. +*/ + struct EL734info { + struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ + int motor; + int ored_msr, fp_cntr, fr_cntr; + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + }; +/* +** Structure holding everything that is known about a VME Motor Controller. +** It is also the structure of replies from the Server. +*/ + struct Motor_State { + int motor; /* Motor number */ + int exists; /* True if Motor exists */ + int msr; /* MSR - Motor Status Register */ + int ored_msr; /* Cumulated MSR */ + int fp_cntr; /* Counter for *FP reports */ + int fr_cntr; /* Counter for *FR reports */ + int ss; /* SS - Status Flags Register */ + char pos_real[16]; /* U - Position as read (degrees) */ + char name[16]; /* MN */ + int dec_pt; /* A - # of decimal places */ + int enc_factor[2]; /* FD - Encoder scaling factors (numer/denom) */ + int mot_factor[2]; /* FM - Motor scaling factors (numer/denom) */ + char inertia_tol[16];/* D - Inertia tol'nce (sec) (Schleppfehler) */ + int ramp; /* E - Start/stop ramp (kHz/sec) */ + int loop_mode; /* F - Open loop/Closed loop (0/1) */ + int slow_hz; /* G - Start/stop frequency (Mot-S/sec) */ + char lims[2][16]; /* H - Lower/Upper limits */ + int fast_hz; /* J - Top speed (Mot-S/sec) */ + int ref_mode; /* K - Reference mode */ + int backlash; /* L - Backlash par (Mot-S) (Spielausgleich) */ + int pos_tol; /* M - Position tolerance (Enc-Steps) */ + char ref_param[16]; /* Q - Parameter for "Goto Reference" */ + int is_sided; /* T - One-sided operation flag (0 = no) */ + char null_pt[16]; /* V - Null point */ + int ac_par; /* W - Air-cushion dependency */ + int enc_circ; /* Z - circumference of encoder (Enc-Steps) */ + int stat_pos; /* SP - # of positionings */ + int stat_pos_flt; /* ST - # of positioning faults (recovered) */ + int stat_pos_fail; /* SR - # of positioning fails (abandoned) */ + int stat_cush_fail; /* SA - # of air-cushion fails */ + char set_real[16]; /* P - Position as set (degrees) */ + int ac_state; /* AC - Air-cushion state (0 = down) */ + int out; /* SO - State of Output Signal */ + int in; /* RI - State of Input Signal */ + }; +/*------------------------------------------------ End of EL734_DEF.H --*/ +#endif /* _el734_def_ */ diff --git a/site_ansto/hardsup/el734_errcodes.h b/site_ansto/hardsup/el734_errcodes.h new file mode 100644 index 00000000..1a04d812 --- /dev/null +++ b/site_ansto/hardsup/el734_errcodes.h @@ -0,0 +1,28 @@ +/* +** TAS_SRC:[LIB]EL734_ERRCODES.H +** +** Include file generated from EL734_ERRCODES.OBJ +** +** 29-AUG-2000 09:49:19.60 +*/ + +#define EL734__VFY_ERR 0x865809C +#define EL734__NO_SOCKET 0x8658094 +#define EL734__NOT_OPEN 0x865808C +#define EL734__FORCED_CLOSED 0x8658084 +#define EL734__EMERG_STOP 0x865807C +#define EL734__BAD_TMO 0x8658074 +#define EL734__BAD_STP 0x865806C +#define EL734__BAD_SOCKET 0x8658064 +#define EL734__BAD_RNG 0x865805C +#define EL734__BAD_PAR 0x8658054 +#define EL734__BAD_OVFL 0x865804C +#define EL734__BAD_OFL 0x8658044 +#define EL734__BAD_MALLOC 0x865803C +#define EL734__BAD_LOC 0x8658034 +#define EL734__BAD_ILLG 0x865802C +#define EL734__BAD_DEV 0x8658024 +#define EL734__BAD_CMD 0x865801C +#define EL734__BAD_ASYNSRV 0x8658014 +#define EL734__BAD_ADR 0x865800C +#define EL734__FACILITY 0x865 diff --git a/site_ansto/hardsup/el734fix.h b/site_ansto/hardsup/el734fix.h new file mode 100644 index 00000000..e14df3a5 --- /dev/null +++ b/site_ansto/hardsup/el734fix.h @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------- + Fix file for David renaming lots of el734 error codes. + + Mark Koennecke, October 1998 +----------------------------------------------------------------------------*/ +#ifndef EL734FIX +#define EL734FIX +#include "asynsrv_errcodes.h" + +#define EL734__BAD_HOST ASYNSRV__BAD_HOST +#define EL734__BAD_BIND ASYNSRV__BAD_BIND +#define EL734__BAD_SENDLEN ASYNSRV__BAD_SEND_LEN +#define EL734__BAD_SEND ASYNSRV__BAD_SEND +#define EL734__BAD_SEND_PIPE ASYNSRV__BAD_SEND_PIPE +#define EL734__BAD_SEND_UNKN ASYNSRV__BAD_SEND_UNKN +#define EL734__BAD_RECV ASYNSRV__BAD_RECV +#define EL734__BAD_RECV_PIPE ASYNSRV__BAD_RECV_PIPE +#define EL734__BAD_RECV_NET ASYNSRV__BAD_RECV_NET +#define EL734__BAD_SEND_NET ASYNSRV__BAD_SEND_NET +#define EL734__BAD_RECV_UNKN ASYNSRV__BAD_RECV_UNKN +#define EL734__BAD_NOT_BCD ASYNSRV__BAD_NOT_BCD +#define EL734__BAD_RECVLEN ASYNSRV__BAD_RECV_LEN +#define EL734__BAD_FLUSH ASYNSRV__BAD_FLUSH +#define EL734__BAD_RECV1 ASYNSRV__BAD_RECV1 +#define EL734__BAD_RECV1_PIPE ASYNSRV__BAD_RECV1_PIPE +#define EL734__BAD_RECV1_NET ASYNSRV__BAD_RECV1_NET +#define EL734__BAD_CONNECT ASYNSRV__BAD_CONNECT +#define EL734__BAD_ID EL734__BAD_DEV +#endif /* el734fix */ diff --git a/site_ansto/hardsup/el737_def.h b/site_ansto/hardsup/el737_def.h new file mode 100644 index 00000000..997e6f32 --- /dev/null +++ b/site_ansto/hardsup/el737_def.h @@ -0,0 +1,67 @@ +#ifndef _el737_def_ +#define _el737_def_ +/*----------------------------------------- [...LIB.SINQ]EL737_DEF.H Ident V02J +** Definitions for the EL737 Neutron Counter +** +** On UNIX systems, this file is located in /public/lib/include +** On VMS systems, this file is a module in mad_lib:sinq_c.tlb +*/ +#include +#include + +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif + +#ifndef _EL737_errcodes_ +#define _EL737_errcodes_ +#include +#endif + +enum EL737_States { + UNKNOWN = -2, + OFFLINE = -1, + MS = 0x0, + PTS = 0x1, + PCS = 0x2, + LRTS = 0x5, + LRCS = 0x6, + PTSP = 0x9, + PCSP = 0xA, + LRTSP = 0xD, + LRCSP = 0xE}; + +enum EL737_Consts { + VMECNT__PRESET_COUNT, + VMECNT__PRESET_TIME, + + VMECNT__FULL, + VMECNT__SHORT, + VMECNT__INCR}; +/* +** Structure to which the EL737_Open handle points. +*/ + struct EL737info { + struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ + int c5, c6, c7, c8; + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + }; +/* +** Structure holding everything that is known about a VME Neutron Counter. +*/ + struct Counter_State { + int state; /* RS */ + char timer[16]; /* RT \ RA */ + int cntrs[8]; /* RC 1 ... RC 8 / */ + char rates[8][16]; /* RR 1 ... RR 8 */ + char thresh_integ_time[8][16]; /* DI 1 ... DI 8 */ + char rate_integ_time[16]; /* DT */ + int analog_indx; /* DA */ + int thresh_indx; /* DR */ + char threshes[8][16]; /* DL 1 ... DL 8 */ + int mon_preset; /* MP */ + char timer_preset[16]; /* TP */ + }; +/*----------------------------------------------------- End of EL737_DEF.H --*/ +#endif /* _el737_def_ */ diff --git a/site_ansto/hardsup/el737_errcodes.h b/site_ansto/hardsup/el737_errcodes.h new file mode 100644 index 00000000..600ff028 --- /dev/null +++ b/site_ansto/hardsup/el737_errcodes.h @@ -0,0 +1,27 @@ +/* +** TAS_SRC:[LIB]EL737_ERRCODES.H +** +** Include file generated from EL737_ERRCODES.OBJ +** +** 29-AUG-2000 09:49:21.56 +*/ + +#define EL737__NO_VALUE 0x8668094 +#define EL737__NO_SOCKET 0x866808C +#define EL737__NOT_OPEN 0x8668084 +#define EL737__FORCED_CLOSED 0x866807C +#define EL737__CNTR_OVFL 0x8668074 +#define EL737__BAD_TMO 0x866806C +#define EL737__BAD_SOCKET 0x8668064 +#define EL737__BAD_PAR 0x866805C +#define EL737__BAD_OVFL 0x8668054 +#define EL737__BAD_OFL 0x866804C +#define EL737__BAD_MALLOC 0x8668044 +#define EL737__BAD_LOC 0x866803C +#define EL737__BAD_ILLG 0x8668034 +#define EL737__BAD_DEV 0x866802C +#define EL737__BAD_CNTR 0x8668024 +#define EL737__BAD_CMD 0x866801C +#define EL737__BAD_BSY 0x8668014 +#define EL737__BAD_ASYNSRV 0x866800C +#define EL737__FACILITY 0x866 diff --git a/site_ansto/hardsup/el737fix.h b/site_ansto/hardsup/el737fix.h new file mode 100644 index 00000000..4c7d0a17 --- /dev/null +++ b/site_ansto/hardsup/el737fix.h @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------- + Fix file for David renaming lots of el734 error codes. + + Mark Koennecke, October 1998 +----------------------------------------------------------------------------*/ +#ifndef EL737FIX +#define EL737FIX +#include "asynsrv_errcodes.h" + +#define EL737__BAD_HOST ASYNSRV__BAD_HOST +#define EL737__BAD_BIND ASYNSRV__BAD_BIND +#define EL737__BAD_SENDLEN ASYNSRV__BAD_SEND_LEN +#define EL737__BAD_SEND ASYNSRV__BAD_SEND +#define EL737__BAD_SEND_PIPE ASYNSRV__BAD_SEND_PIPE +#define EL737__BAD_SEND_UNKN ASYNSRV__BAD_SEND_UNKN +#define EL737__BAD_RECV ASYNSRV__BAD_RECV +#define EL737__BAD_RECV_PIPE ASYNSRV__BAD_RECV_PIPE +#define EL737__BAD_RECV_NET ASYNSRV__BAD_RECV_NET +#define EL737__BAD_SEND_NET ASYNSRV__BAD_SEND_NET +#define EL737__BAD_RECV_UNKN ASYNSRV__BAD_RECV_UNKN +#define EL737__BAD_NOT_BCD ASYNSRV__BAD_NOT_BCD +#define EL737__BAD_RECVLEN ASYNSRV__BAD_RECV_LEN +#define EL737__BAD_FLUSH ASYNSRV__BAD_FLUSH +#define EL737__BAD_RECV1 ASYNSRV__BAD_RECV1 +#define EL737__BAD_RECV1_PIPE ASYNSRV__BAD_RECV1_PIPE +#define EL737__BAD_RECV1_NET ASYNSRV__BAD_RECV1_NET +#define EL737__BAD_CONNECT ASYNSRV__BAD_CONNECT +#define EL737__BAD_ID -99995 +#define EL737__BAD_SNTX -99991 +#define EL737__BAD_REPLY -99992 +#define EL737__BAD_ADR -99993 +#define EL737__BAD_RNG -99994 +#endif /* el734fix */ diff --git a/site_ansto/hardsup/el755_def.h b/site_ansto/hardsup/el755_def.h new file mode 100644 index 00000000..8cfe339d --- /dev/null +++ b/site_ansto/hardsup/el755_def.h @@ -0,0 +1,31 @@ +#ifndef _el755_def_ +#define _el755_def_ +/*------------------------------------------------ EL755_DEF.H Ident V01C +** Definitions for the EL755 Magnet Power Supply Controller +** +** On UNIX systems, this file is located in /public/lib/include +** On VMS systems, this file is a module in mad_lib:sinq_c.tlb +*/ +#include +#include + +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif + +#ifndef _EL755_errcodes_ +#define _EL755_errcodes_ +#include +#endif + +/* +** Structure to which the EL755_Open handle points. +*/ + struct EL755info { + struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ + int index; + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + }; +/*------------------------------------------------ End of EL755_DEF.H --*/ +#endif /* _el755_def_ */ diff --git a/site_ansto/hardsup/el755_errcodes.h b/site_ansto/hardsup/el755_errcodes.h new file mode 100644 index 00000000..3b9d2367 --- /dev/null +++ b/site_ansto/hardsup/el755_errcodes.h @@ -0,0 +1,27 @@ +/* +** TAS_SRC:[LIB]EL755_ERRCODES.H +** +** Include file generated from EL755_ERRCODES.OBJ +** +** 29-AUG-2000 09:49:23.51 +*/ + +#define EL755__TURNED_OFF 0x8678094 +#define EL755__TOO_MANY 0x867808C +#define EL755__TOO_LARGE 0x8678084 +#define EL755__OVFLOW 0x867807C +#define EL755__OUT_OF_RANGE 0x8678074 +#define EL755__OFFLINE 0x867806C +#define EL755__NO_SOCKET 0x8678064 +#define EL755__NOT_OPEN 0x867805C +#define EL755__FORCED_CLOSED 0x8678054 +#define EL755__BAD_TMO 0x867804C +#define EL755__BAD_SOCKET 0x8678044 +#define EL755__BAD_PAR 0x867803C +#define EL755__BAD_OFL 0x8678034 +#define EL755__BAD_MALLOC 0x867802C +#define EL755__BAD_ILLG 0x8678024 +#define EL755__BAD_DEV 0x867801C +#define EL755__BAD_CMD 0x8678014 +#define EL755__BAD_ASYNSRV 0x867800C +#define EL755__FACILITY 0x867 diff --git a/site_ansto/hardsup/err.c b/site_ansto/hardsup/err.c new file mode 100644 index 00000000..9ef0fad9 --- /dev/null +++ b/site_ansto/hardsup/err.c @@ -0,0 +1,105 @@ + +/*--------------------------------------------------------------------------- + + EL734Error2Text converts between an EL734 error code to text +-----------------------------------------------------------------------------*/ + void EL734Error2Text(char *pBuffer, int iErr) + { + switch(iErr) + { + case -28: + strcpy(pBuffer,"EL734__BAD_ADR"); + break; + case -8: + strcpy(pBuffer,"EL734__BAD_BIND"); + break; + case -30: + strcpy(pBuffer,"EL734__BAD_BSY"); + break; + case -3: + strcpy(pBuffer,"EL734__BAD_CMD"); + break; + case -9: + strcpy(pBuffer,"EL734__BAD_CONNECT"); + break; + case -23: + strcpy(pBuffer,"EL734__BAD_FLUSH"); + break; + case -6: + strcpy(pBuffer,"EL734__BAD_HOST"); + break; + case -10: + strcpy(pBuffer,"EL734__BAD_ID"); + break; + case -5: + strcpy(pBuffer,"EL734__BAD_ILLG"); + break; + case -2: + strcpy(pBuffer,"EL734__BAD_LOC"); + break; + case -11: + strcpy(pBuffer,"EL734__BAD_MALLOC"); + break; + case -21: + strcpy(pBuffer,"EL734__BAD_NOT_BCD"); + break; + case -4: + strcpy(pBuffer,"EL734__BAD_OFL"); + break; + case -29: + strcpy(pBuffer,"EL734__BAD_PAR"); + break; + + case -17: + strcpy(pBuffer,"EL734__BAD_RECV"); + break; + case -19: + strcpy(pBuffer,"EL734__BAD_RECV_NET"); + break; + case -18: + strcpy(pBuffer,"EL734__BAD_RECV_PIPE"); + break; + case -20: + strcpy(pBuffer,"EL734__BAD_RECV_UNKN"); + break; + case -22: + strcpy(pBuffer,"EL734__BAD_RECVLEN"); + break; + case -24: + strcpy(pBuffer,"EL734__BAD_RECV1"); + break; + case -26: + strcpy(pBuffer,"EL734__BAD_RECV1_NET"); + break; + case -25: + strcpy(pBuffer,"EL734__BAD_RECV1_PIPE"); + break; + case -27: + strcpy(pBuffer,"EL734__BAD_RNG"); + break; + case -13: + strcpy(pBuffer,"EL734__BAD_SEND"); + break; + case -14: + strcpy(pBuffer,"EL734__BAD_SEND_PIPE"); + break; + case -15: + strcpy(pBuffer,"EL734__BAD_SEND_NET"); + break; + case -16: + strcpy(pBuffer,"EL734__BAD_SEND_UNKN"); + break; + case -12: + strcpy(pBuffer,"EL734__BAD_SENDLEN"); + break; + case -7: + strcpy(pBuffer,"EL734__BAD_SOCKET"); + break; + case -1: + strcpy(pBuffer,"EL734__BAD_TMO"); + break; + default: + strcpy(pBuffer,"Unknown EL734 error"); + break; + } + } diff --git a/site_ansto/hardsup/failinet.c b/site_ansto/hardsup/failinet.c new file mode 100644 index 00000000..38c39e8f --- /dev/null +++ b/site_ansto/hardsup/failinet.c @@ -0,0 +1,109 @@ +#define ident "1B01" +#ifdef VAXC +#module FailInet ident +#endif +#ifdef __DECC +#pragma module FailInet ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Computing Section | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]FAILINET.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1995 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]FailInet - + tasmad_disk:[mad.lib.sinq]FailInet + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb FailInet debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb FailInet +** +** Updates: +** 1A01 2-Nov-1995 DM. Initial version. +** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB. +**============================================================================ +** The following entry points are included: +** + #include + + void FailInet (char *text) +** -------- +** Input Args: +** text - A text string to be printed. +** Output Args: +** none +** Modified Args: +** none +** Return status: +** none +** Global variables modified: +** none +** Routines called: +** GetErrno +** perror +** exit +** Description: +** The routine is useful if a fatal TCP/IP error occurs. +** The value of errno is printed and then "perror" is called. +** Then "exit" is called. +**============================================================================ +** Global Definitions +*/ +#ifdef VAXC +#include stdlib +#include stdio +#include errno +#include sinq_prototypes +#else +#include +#include +#include +#include +#endif +/*-------------------------------------------------------------------------- +** Global Variables +*/ + +/* +** FailInet: Some network failure has occurred. +*/ + void FailInet (char *text) { +/* ======== +** Output the given text and exit the process. +*/ + int my_errno, my_vaxc_errno; + + GetErrno (&my_errno, &my_vaxc_errno); + printf ("### Internet Error ###\n"); +#ifdef __VMS + printf (" ### errno = %d.\n", my_errno); + printf (" ### vaxc$errno = %d.\n", my_vaxc_errno); +#else + printf (" ### errno = %d.\n", my_errno); +#endif + perror (text); + exit (EXIT_FAILURE); + } +/*------------------------------------------------- End of FAILINET.C =======*/ diff --git a/site_ansto/hardsup/geterrno.c b/site_ansto/hardsup/geterrno.c new file mode 100644 index 00000000..c3edcf18 --- /dev/null +++ b/site_ansto/hardsup/geterrno.c @@ -0,0 +1,96 @@ +#define ident "1B01" +#ifdef VAXC +#module GetErrno ident +#endif +#ifdef __DECC +#pragma module GetErrno ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Computing Section | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]GETERRNO.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1995 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]GetErrno - + tasmad_disk:[mad.lib.sinq]GetErrno + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb GetErrno debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb GetErrno +** +** Updates: +** 1A01 2-Nov-1995 DM. Initial version. +** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB. +**============================================================================ +** The following entry points are included: +** + #include + + void GetErrno (int *his_errno, int *his_vaxc_errno) +** -------- +** Input Args: +** none +** Output Args: +** his_errno - value of "errno". +** his_vaxc_errno - on VMS systems only, value of "vaxc$errno". Otherwise +** set to 1. +** Modified Args: +** none +** Return status: +** none +** Global variables modified: +** none +** Description: +** GetErrno returns a copy of the universal error variable "errno" (and, +** on VMS systems, vaxc$errno) to a local variable supplied by the user. +** This can occasionally be useful when debugging since the debugger on +** VMS can't easily examine them. +**============================================================================ +** Global Definitions +*/ +#ifdef VAXC +#include errno +#else +#include +#endif +/*-------------------------------------------------------------------------- +** Global Variables +*/ + +/*-------------------------------------------------------------------------- +** GetErrno: Make copies of errno and vaxc$errno for debug. +*/ + void GetErrno (int *his_errno, int *his_vaxc_errno) { +/* ======== +*/ + *his_errno = errno; /* Make copy of errno */ +#ifdef __VMS + *his_vaxc_errno = vaxc$errno; /* Make copy of vaxc$errno */ +#else + *his_vaxc_errno = 1; +#endif + return; + } +/*------------------------------------------------- End of GETERRNO.C =======*/ diff --git a/site_ansto/hardsup/itc4util.c b/site_ansto/hardsup/itc4util.c new file mode 100644 index 00000000..f56e5a7c --- /dev/null +++ b/site_ansto/hardsup/itc4util.c @@ -0,0 +1,450 @@ +/*-------------------------------------------------------------------------- + + I T C 4 U T I L + + A few utility functions for dealing with a ITC4 temperature controller + within the SINQ setup: host -- TCP/IP -- MAC --- RS-232. + + Mark Koennecke, Juli 1997 + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +---------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "serialsinq.h" +#include "itc4util.h" +/* -------------------------------------------------------------------------*/ + + + int ITC4_Open(pITC4 *pData, char *pRS232, int iSensor, int iCTRL, int iMode) + { + int iRet; + char pCommand[80]; + char pReply[132]; + pITC4 self = NULL; + + self = (pITC4)malloc(sizeof(ITC4)); + if(self == NULL) + { + return ITC4__BADMALLOC; + } + *pData = self; + self->iControl = iCTRL; + self->iRead = iSensor; + self->iReadOnly = iMode; + self->fDiv = 10.; + self->fMult = 10.; + self->controller = NULL; + + self->controller = (prs232)FindCommandData(pServ->pSics,pRS232, + "RS232 Controller"); + if(!self->controller){ + /*SCWrite(pCon,"ERROR: motor controller not found",eError); */ + return ITC4__BADCOM; + } + + /* an identification test has been here, but I had to removed as not all + ITC4 controllers at SINQ answer the V command. Some versions of the + controller do not recognize it. Sighhhhhhh. I had to put it in again + in order to check for ITC-503, but I handle the thing by default as + an ITC4 if I do not get a proper response. + */ + self->i503 = 0; + sprintf(pCommand,"V"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + + if(iRet != 1) + { + return iRet; + } + if(strstr(pReply,"ITC503") != NULL) + { + self->i503 = 1; + } + + if(!self->iReadOnly) + { + /* switch to remote and unlocked operation pg48 */ + sprintf(pCommand,"C3"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Set heater and gas flow controls to manual pg51 */ + sprintf(pCommand,"A0"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Set heater sensor pg 52 */ + sprintf(pCommand,"H%1.1d",self->iControl); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return ITC4__BADCOM; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Display on control sensor on front panel pg51 */ + sprintf(pCommand,"F%1.1d",self->iControl); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Heater Auto, Gas Manual pg51 */ + sprintf(pCommand,"A1"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + /* reset timeout */ + /*iRet = SerialConfig(&self->pData, 10);*/ + if(iRet != 1) + { + return iRet; + } + } + return 1; + } +/*--------------------------------------------------------------------------*/ + void ITC4_Close(pITC4 *pData) + { + } +/*--------------------------------------------------------------------------*/ +/* Called by ansto/itc4driv.c:ConfigITC4 */ + int ITC4_Config(pITC4 *pData, int iTmo, int iRead, int iControl, + float fDiv,float fMult) + { + + int iRet; + char pReply[132]; + char pCommand[10]; + pITC4 self; + + self = *pData; + +/* 3 input channels see p52 */ +/* BUG ALLOWS iControl=4 */ + if (iControl < 1 || iControl > 3) { + return 1; + } else { + /* switch to remote and unlocked operation pg48 */ + sprintf(pCommand,"C3"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Set heater and gas flow controls to manual pg51 */ + sprintf(pCommand,"A0"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Set heater sensor pg 52 */ + sprintf(pCommand,"H%1.1d",iControl); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return ITC4__BADCOM; + } else if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } else { + self->iControl = iControl; + } + + /* Display on control sensor on front panel pg51 */ + sprintf(pCommand,"F%1.1d",iControl); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* Heater Auto, Gas Manual pg51 */ + sprintf(pCommand,"A1"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + /* reset timeout */ + /*iRet = SerialConfig(&self->pData, 10);*/ + if(iRet != 1) + { + return iRet; + } + + + } + } +/* --------------------------------------------------------------------------*/ + int ITC4_Send(pITC4 *pData, char *pCommand, char *pReply, int iLen) + { + pITC4 self; + + self = *pData; + + /* make sure, that there is a \r at the end of the command */ +/* if(strchr(pCommand,(int)'\r') == NULL) + { + strcat(pCommand,"\r"); + } */ + return transactRS232(self->controller,pCommand,strlen(pCommand),pReply,iLen); + } +/*--------------------------------------------------------------------------*/ + int ITC4_Read(pITC4 *pData, float *fVal) + { + char pCommand[10], pReply[132]; + int iRet; + float fRead = -9999999.; + pITC4 self; + + self = *pData; + + + /* format and send R command */ + sprintf(pCommand,"R%1.1d",self->iRead); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + /* analyse reply */ + if(pReply[0] != 'R') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + + iRet = sscanf(&pReply[1],"%f",&fRead); + if(iRet != 1) + { + return ITC4__BADREAD; + } + if(self->i503) + { + *fVal = fRead; + } + else + { + *fVal = fRead/self->fDiv; + } + return 1; + } +/* -------------------------------------------------------------------------*/ + int ITC4_Set(pITC4 *pData, float fVal) + { + char pCommand[10], pReply[132]; + int iRet, i, iRead; + const float fPrecision = 0.0001; + float fSet, fDelta, fRead, fDum; + pITC4 self; + int iSet; + + self = *pData; + + if(self->iReadOnly) + { + return ITC4__READONLY; + } + + /* format command */ + if(self->i503) + { + sprintf(pCommand,"T%-7.3f",fVal); + } + else + { + fSet = fVal; + iSet = (int)(fSet*self->fMult); + sprintf(pCommand,"T%05.5d",iSet); + } + + /* try three times: send, read, test, if OK return, else + resend. This must be done because the ITC4 tends to loose + characters + */ + for(i = 0; i < 3; i++) + { + /* send command */ + iRet = transactRS232(self->controller,pCommand,strlen(pCommand),pReply,131); + if(iRet != 1) + { + return iRet; + } + if(pReply[0] == '?') + { + strcpy(self->pAns,pReply); + return ITC4__BADCOM; + } + /* read the set value again */ + iRead = self->iRead; + self->iRead = 0; /* make a R0 */ + fDum = self->fDiv; + self->fDiv = self->fMult; + iRet = ITC4_Read(pData,&fRead); + self->iRead = iRead; + self->fDiv = fDum; + if(iRet != 1) + { + return iRet; + } + /* check the value read back */ + if(self->i503) + { + fDelta = fRead - fVal; + } + else + { + fDelta = fRead - fSet; + } + if(fDelta < 0) + fDelta = -fDelta; + if(fDelta < fPrecision) + { + /* Success, go home */ + return 1; + } + } + return ITC4__BADSET; + } +/* -------------------------------------------------------------------------*/ + void ITC4_ErrorTxt(pITC4 *pData,int iCode, char *pError, int iLen) + { + char pBueffel[512]; + pITC4 self; + + self = *pData; + + switch(iCode) + { + case ITC4__BADCOM: + sprintf(pBueffel,"ITC4: Invalid command or offline, got %s", + self->pAns); + strncpy(pError,pBueffel,iLen); + break; + case ITC4__BADPAR: + strncpy(pError,"ITC4: Invalid parameter specified",iLen); + break; + case ITC4__BADMALLOC: + strncpy(pError,"ITC4: Error allocating memory in ITC4",iLen); + break; + case ITC4__BADREAD: + strncpy(pError,"ITC4: Badly formatted answer",iLen); + break; + case ITC4__BADSET: + strncpy(pError,"ITC4: Failed three times to write new set value to ITC4",iLen); + break; + default: + SerialError(iCode, pError,iLen); + break; + } + } diff --git a/site_ansto/hardsup/itc4util.h b/site_ansto/hardsup/itc4util.h new file mode 100644 index 00000000..00c0e52d --- /dev/null +++ b/site_ansto/hardsup/itc4util.h @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------- + I T C L 4 U T I L + + A few utility functions for talking to a Oxford Instruments ITCL-4 + temperature controller via the SINQ setup: TCP/IP--MAC--RS-232-- + ITC-4. + + Mark Koennecke, Juli 1997 + +----------------------------------------------------------------------------*/ +#ifndef SINQITCL4 +#define SINQITCL4 + +/*----------------------- ERRORCODES-------------------------------------- + Most functions return a negative error code on failure. Error codes + defined are those defined for serialsinq plus a few additional ones: +*/ + +#define ITC4__BADCOM -501 +/* command not recognized */ +#define ITC4__BADPAR -502 +/* bad parameter to command */ +#define ITC4__BADMALLOC -503 +/* error allocating memory */ +#define ITC4__BADREAD -504 +/* error analysing command string on Read */ +#define ITC4__NOITC -510 +/* Controller is no ITC-4 */ +#define ITC4__BADSET -530 +/* failed three times to set temperature */ +#define ITC4__READONLY -531 +/*------------------------------------------------------------------------*/ + typedef struct __ITC4 { + int iRead; + int iControl; + void *pData; + char pAns[80]; + float fDiv; + float fMult; + int iReadOnly; + int i503; /* flag for model 503, understanding float*/ + prs232 controller; + } ITC4; + + typedef struct __ITC4 *pITC4; + +/*-----------------------------------------------------------------------*/ + int ITC4_Open(pITC4 *pData,char *pHost, int iPort, int iChannel, int iMode); + /***** creates an ITC4 datastructure and opens a connection to the ITCL4 + controller. Input Parameters are: + the hostname + the port number + the RS-232 channel number on the Mac. + iMode: 1 for ReadOnly, 0 for normal mode + + Return values are 1 for success, a negative error code on + failure. + + */ + + void ITC4_Close(pITC4 *pData); + /****** close a connection to an ITC4controller and frees its + data structure. The only parameter is a pointer to the data + structure for this controller. This pointer will be invalid after + this call. + */ + + int ITC4_Config(pITC4 *pData, int iTmo, int iRead, + int iControl, float fDiv, float fMult); + /***** configure some aspects of a ITC4temperature controller. + The parameter are: + - a pointer to the data structure for the controller as + returned by OpenITCL4 + - a value for the connection timeout + - the temperature sensor to use for reading the + temperature. + - the temperature sensor used by the ITC4controller + for regulating the temperature. + - the divisor needed to calculate the real temperature + from the sensor. + The function returns 1 on success, a negative error code on + failure. + */ + + int ITC4_Send(pITC4 *pData, char *pCommand, char *pReply, int iLen); + /******* send a the command in pCommand to the ITC4controller. + A possible reply is returned in the buffer pReply. + Maximum iLen characters are copied to pReply. + The first parameter is a pointer to a ITC4data structure + as returned by OpenITCL4. + + Return values are 1 for success, a negative error code on + failure. + */ + + int ITC4_Read(pITC4 *pData, float *fVal); + /******* reads the current actual temperature of the sensor + configured by ConfigITC4for reading. The value is returned + in fVal. The first parameter is a pointer to a ITCL4 + data structure as returned by OpenITCL4. + + Return values are 1 for success, a negative error code on + failure. + */ + + int ITC4_Set(pITC4 *pData, float fVal); + /****** sets a new preset temperature in the ITC4temperature + controller. Parameters are: + - a pointer to a ITC4data structure as returned by OpenITCL4. + - the new preset value. + + Return values are 1 for success, a negative error code on + failure. + */ + + void ITC4_ErrorTxt(pITC4 *pData, int iCode, char *pError, int iLen); + /******* translates one of the negative error ITC4error codes + into text. Maximum iLen bytes will be copied to the + buffer pError; + */ + + +#endif + + diff --git a/site_ansto/hardsup/lakeshore340util.c b/site_ansto/hardsup/lakeshore340util.c new file mode 100644 index 00000000..cb5505a3 --- /dev/null +++ b/site_ansto/hardsup/lakeshore340util.c @@ -0,0 +1,533 @@ +/*-------------------------------------------------------------------------- + + L A K E S H O R E 3 4 0 U T I L + + A few utility functions for dealing with a LAKESHORE340 temperature controller + within the SINQ setup: host -- TCP/IP -- MAC --- RS-232. + + Mark Koennecke, Juli 1997 + Mark Lesha, January 2006 (based on ITC4 code) + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +---------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "serialsinq.h" +#include "lakeshore340util.h" +/* -------------------------------------------------------------------------*/ + + int LAKESHORE340_Check_Status(pLAKESHORE340 self) + /* Can be called to check for correct operation of the LAKESHORE340 */ + { + int iRet, iRetry, busy, notbusy; + char pCommand[20]; + char pReply[132]; + /* Check the busy status. */ + /* While busy, wait but not too long - set an upper limit of about 100 queries, */ + /* should translate to about 1 or 2 seconds which is enough time for any commands */ + /* to complete. Since we don't issue any time-consuming commands, this shouldn't */ + /* be necessary anyway. */ + /* Register a comms failure if a not-busy response isn't able to be received. */ + iRetry=0; + printf("Checking status..."); + do + { + sprintf(pCommand,"BUSY?"); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0) + { + printf("Comms error!\n"); + return iRet; // Comms problem + } + busy=(strncmp(pReply,"1",15)==0); + notbusy=(strncmp(pReply,"0",15)==0); + if (notbusy) + { + printf("Status OK.\n"); + return 1; // Lakeshore 340 is ready to accept command + } + } while((++iRetry<100)&&busy); + /* If we fell out of the loop, the Lakeshore 340 is either still busy */ + /* or some bad response was received, log the response. */ + sprintf(self->pAns,"BUSY response=%s",pReply); + printf("Busy or bad response received!\n"); + return LAKESHORE340__BADREAD; + } + + int LAKESHORE340_ConfigureAndQueryGen(pLAKESHORE340 self, char *command, + char *configandqueryparameters, char *configonlyparameters,char *diagnosis) + /* Issue a command to the Lakeshore 340, if this works, */ + /* issue the corresponding query and check the result is correct. */ + /* Log and return any errors. */ + { + int iRet; + char pCommand[20]; + char pReply[132]; + /* Issue a command to the Lakeshore 340. */ + if (configandqueryparameters&&*configandqueryparameters) + sprintf(pCommand,"%s %s,%s",command,configandqueryparameters,configonlyparameters); + else + sprintf(pCommand,"%s %s",command,configonlyparameters); + printf("Issuing command: '%s'...\n",pCommand); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=writeRS232(self->controller,pCommand,strlen(pCommand)))!=1) + return iRet; + /* Issue the query corresponding to the command, */ + /* then check the parameters match what was set. */ + if (configandqueryparameters&&*configandqueryparameters) + sprintf(pCommand,"%s? %s",command,configandqueryparameters); + else + sprintf(pCommand,"%s?",command); + printf("Issuing query: '%s'...\n",pCommand); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0) + { + printf("transactRS232 error! Code=%d.\n",iRet); + printf("DEBUG: pReply='%s' len=%d configonlyparameters='%s' len=%d\n", + pReply,strlen(pReply),configonlyparameters,strlen(configonlyparameters)); + return iRet; + } + /* Query should return the same data parameters set in the configuration + (i.e. the configonlyparameters), the configandqueryparameters are used + to index objects and are common to both configuration and query. */ + printf("DEBUG: pReply='%s' len=%d configonlyparameters='%s' len=%d\n", + pReply,strlen(pReply),configonlyparameters,strlen(configonlyparameters)); + if (strcmp(pReply,configonlyparameters)!=0) + { + printf("Response was bad.\n"); + if (diagnosis&&*diagnosis) + sprintf(self->pAns,"%s response=%s (%s.)",command,pReply,diagnosis); + else + sprintf(self->pAns,"%s response=%s",command,pReply); + return LAKESHORE340__BADREAD; + } + printf("Response was good.\n"); + return 1; + } + + int LAKESHORE340_ConfigureAndQuery(pLAKESHORE340 self, char *command, + char *parameters, char *diagnosis) + /* Use for config/query transactions that don't require index parameters in the query. */ + { + return LAKESHORE340_ConfigureAndQueryGen(self,command,"",parameters,diagnosis); + } + + int LAKESHORE340_SetControl(pLAKESHORE340 self, int iControl) + { + /* Attempt to set the sensor used for temperature control. */ + /* Only use control loop #1 to do the control, use Kelvin units, */ + /* and leave control enabled at next power-on. */ + if (iControl==1) + return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","A,1,1,1",""); + else if (iControl==2) + return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","B,1,1,1",""); + else if (iControl==3) + return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","C,1,1,1",""); + else if (iControl==4) + return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","D,1,1,1",""); + else + return LAKESHORE340__BADPAR; + } + + int LAKESHORE340_Setup(pLAKESHORE340 self, int iControl) /* Operations common to both Open and Config functions */ + { + int iRet; + char pCommand[20]; + char pReply[132]; + + /* MJL enable RS232 debugging mode. */ + //setRS232Debug(self->controller,1); + //printf("***RS232 debug mode enabled for LAKESHORE340***\n");fflush(stdout); + + /* Setup the comms port (the baudrate etc. are probably just academic since */ + /* they must be correct if we have established comms, but the termination */ + /* character setting is relevant - use just \r. */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"COMM","3,5,2","bad comms setup"))!=1) + return iRet; + + /* Reset the controller to power-on state. */ + sprintf(pCommand,"*RST"); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1) + return iRet; + + /* Clear the interface status (and buffer, but that's irrelevant) */ + /* just in case we want to use the internal status flags later on. */ + /* Actually, we do *RST above, probably this isn't necessary. */ + sprintf(pCommand,"*CLS"); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1) + return iRet; + + /* Check the LAKESHORE340 status */ + /* Basically this just makes sure comms is up. */ + if ((iRet=LAKESHORE340_Check_Status(self))!=1) + return iRet; + + /* Check the POST status, it should be 0 and not 1. */ + sprintf(pCommand,"*TST?"); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0) + return iRet; + if (strcmp(pReply,"0")!=0) + { + if (strcmp(pReply,"1")==0) + { + strcpy(self->pAns,"*TST=1 - POST failure, Lakeshore 340 is faulty."); + return LAKESHORE340__FAULT; + } + else // Unexpected response from *TST? query. + { + sprintf(self->pAns,"*TST response=%s",pReply); + return LAKESHORE340__BADREAD; + } + } + + /* Check that the controller is a gen-new-wine Lakeshore 340 */ + /* There's also the *REV command to check the firmware revision, but */ + /* that would be going too far ;) */ + sprintf(pCommand,"*IDN?",command); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0) + return iRet; + if (strncmp(pReply,"LSCI,MODEL340",13)!=0) + { + strcpy(self->pAns,pReply); + return LAKESHORE340__NOLAKESHORE340; + } + + /* Switch to remote operation - but leave the keypad unlocked */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"MODE","2",""))!=1) + return iRet; + + /* Make sure the keypad isn't locked out via the LOCK setting too */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"LOCK","0,000",""))!=1) + return iRet; + + /* Clear any alarms. */ + sprintf(pCommand,"ALMRST"); + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1) + return iRet; + + /* Set up the front panel display on the Lakeshore 340. */ + /* Set 2 output fields, which we will use to display the set temp */ + /* and the actual temp at the controlling sensor selected. */ + /* Note: use 4,060,1 setting rather than just 4,60 so that the response */ + /* matches exactly and we can use LAKESHORE340_ConfigureAndQuery ;) */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"DISPLAY","4,060,1",""))!=1) + return iRet; + + /* Set up the 4 fields on the front panel display to show both sensor temps. */ + if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","1","A,1",""))!=1) + return iRet; + if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","2","B,1",""))!=1) + return iRet; + if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","3","C,1",""))!=1) + return iRet; + if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","4","D,1",""))!=1) + return iRet; + + /* Set the sensor used for controlling temperature. */ + /* Sets sensor A when iControl==1 and sensor B when iControl==2. */ + if ((LAKESHORE340_SetControl(self,iControl))!=1) + return iRet; + + /* Turn off the heater as a precaution. */ + /* The heater gets turned on when we do any set operation. */ + /* Also the heater will be turned off if SICS is shut down properly. */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"RANGE","0",""))!=1) + return iRet; + + /* Don't bother setting the controller's date & time + (not easy to code and probably wouldn't be useful). */ + + /* Check the LAKESHORE340 operating status one last time */ + if ((iRet=LAKESHORE340_Check_Status(self))!=1) + return iRet; + + return 1; /* Success */ + } + + int LAKESHORE340_Open(pLAKESHORE340 *pData, char *pRS232, int iSensor, int iCTRL, int iMode) + { + pLAKESHORE340 self = NULL; + + self = (pLAKESHORE340)malloc(sizeof(LAKESHORE340)); + if(self == NULL) + { + return LAKESHORE340__BADMALLOC; + } + *pData = self; + self->iControl = iCTRL; + self->iRead = iSensor; + self->iReadOnly = iMode; + + /* The LAKESHORE340 doesn't require divisors or multipliers + and they are always forced to 1.0 */ + self->fDiv = 1.0; + self->fMult = 1.0; + + self->controller = NULL; + + self->controller = (prs232)FindCommandData(pServ->pSics,pRS232, + "RS232 Controller"); + if(!self->controller){ + /*SCWrite(pCon,"ERROR: motor controller not found",eError); */ + return LAKESHORE340__BADCOM; + } + + if(!self->iReadOnly) + return LAKESHORE340_Setup(self, self->iControl); + } +/*--------------------------------------------------------------------------*/ + void LAKESHORE340_Close(pLAKESHORE340 *pData) + { + pLAKESHORE340 self; + + self = *pData; + if (!self) + return; // Just in case + + /* Try to turn off the heater as a precaution. */ + LAKESHORE340_ConfigureAndQuery(self,"RANGE","0",""); + + /* switch off remote operation */ + /* Not sure if this is really necessary but do it just in case */ + LAKESHORE340_ConfigureAndQuery(self,"MODE","1",""); + + return; + } +/*--------------------------------------------------------------------------*/ + int LAKESHORE340_Config(pLAKESHORE340 *pData, int iTmo, int iRead, int iControl, + float fDiv,float fMult) + { + pLAKESHORE340 self; + + self = *pData; + + return LAKESHORE340_Setup(self, iControl); + } +/* --------------------------------------------------------------------------*/ + int LAKESHORE340_Send(pLAKESHORE340 *pData, char *pCommand, char *pReply, int iLen) + { + int iRet,i,commandlen,isquery; + pLAKESHORE340 self; + + self = *pData; + + /* Send command direct to the LAKESHORE340 */ + /* Because the LAKESHORE340 only provides a response for query commands (those + ending in a '?'), just perform a write for others and not a full transaction. */ + commandlen=strlen(pCommand); + isquery=0; + for(i=0;icontroller,pCommand,commandlen); + *pReply='\0'; + } + else // LAKESHORE340 will send a response. + { + usleep(50000); // Required to meet Lakeshore340 spec. + iRet=transactRS232(self->controller,pCommand,commandlen,pReply,iLen); + } + + /* Check the LAKESHORE340 operating status after issuing the command, if it was successful */ + if (iRet>=1) + iRet=LAKESHORE340_Check_Status(self); + return iRet; + } +/*--------------------------------------------------------------------------*/ + int LAKESHORE340_Read(pLAKESHORE340 *pData, float *fVal) + { + char pCommand[20], pReply[132]; + int iRet; + float fRead = -9999999.; + pLAKESHORE340 self; + + self = *pData; + + + /* for the LAKESHORE340 there are three temp measurements available */ + /* as 'A', 'B', 'C' and 'D'. (This is a bit different from the manual) */ + /* We use the Kelvin readings (presumably the cryogenic 'furnace' */ + /* operates at low temperatures, so it probably makes more sense) */ + switch(self->iRead) + { + case 1: + sprintf(pCommand,"KRDG? A"); + break; + case 2: + sprintf(pCommand,"KRDG? B"); + break; + case 3: + sprintf(pCommand,"KRDG? C"); + break; + case 4: + sprintf(pCommand,"KRDG? D"); + break; + default: + return LAKESHORE340__BADPAR; // But shouldn't happen + } + + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0) + return iRet; + + iRet = sscanf(pReply,"%g",&fRead); // KRDG returns free-format exponentiated value + if(iRet != 1) // Not a number, probably an error response + { + return LAKESHORE340__BADREAD; + } + + *fVal = fRead; + + /* Check the LAKESHORE340 operating status after the read, and return */ + iRet=LAKESHORE340_Check_Status(self); + return iRet; + } +/* -------------------------------------------------------------------------*/ + int LAKESHORE340_Set(pLAKESHORE340 *pData, float fVal) + { + char pCommand[20], pCommandRead[20], pReply[132]; + int iRet, i; + const float fPrecision = 0.1; + float fDelta, fRead; + pLAKESHORE340 self; + + self = *pData; + + if(self->iReadOnly) + { + return LAKESHORE340__READONLY; + } + + /* Note we are using control loop #1 only for temperature control. */ + sprintf(pCommand,"SETP 1,%1.1f",fVal); + sprintf(pCommandRead,"SETP? 1"); // To read back and check the set value + + /* try three times: send, read, test, if OK return, else resend. */ + /* MJL doesn't think this is necessary... left over from itc4 */ + for(i = 0; i < 3; i++) + { + /* send SETP command, we don't get any response so use writeRS232 */ + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=writeRS232(self->controller,pCommand,strlen(pCommand)))!=1) + return iRet; + /* read the set value again using the SETP? command */ + usleep(50000); // Required to meet Lakeshore340 spec. + if ((iRet=transactRS232(self->controller,pCommandRead,strlen(pCommandRead),pReply,131))<=0) + return iRet; + printf("SETP: Response %d characters: '%s'\n",iRet,pReply); + if(pReply[0] == '-'&&strlen(pReply)>7) + { + strcpy(self->pAns,pReply); + return LAKESHORE340__BADCOM; + } + /* Convert the value read back. */ + /* Note SETP? will return free-format exponentiated number, so use %g. */ + if(sscanf(pReply,"%g",&fRead)!=1) + return LAKESHORE340__BADREAD; + printf(" Parsed response OK, value=%g\n",fRead); + /* check the value read back */ + printf(" Setpoint=%g actual=%g\n",fVal,fRead); + fDelta = fRead - fVal; + if(fDelta < 0) + fDelta = -fDelta; + printf(" delta=%g precision=%g\n",fDelta,fPrecision); + if(fDelta < fPrecision) + { + /* Turn on the heater. (but it will already be on if there has been a previous set) */ + /* Don't know what range is appropriate, but for the time being set to 50W */ + /* which is setting 5 (maximum range). */ + if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"RANGE","5",""))!=1) + return iRet; + /* Success, but check the LAKESHORE340 operating status afterwards, and return */ + /* Don't bother to repeat the write if we get an error here as it would indicate + a fault or overload in the LAKESHORE340, not a comms problem */ + printf("SETP OK, checking status and returning.\n"); + iRet=LAKESHORE340_Check_Status(self); + return iRet; + } + } + printf("SETP failed!\n"); + return LAKESHORE340__BADSET; + } +/* -------------------------------------------------------------------------*/ + void LAKESHORE340_ErrorTxt(pLAKESHORE340 *pData,int iCode, char *pError, int iLen) + { + char pBueffel[512]; + pLAKESHORE340 self; + + self = *pData; + + switch(iCode) + { + case LAKESHORE340__BADCOM: + sprintf(pBueffel,"LAKESHORE340: Invalid command or offline, got %s", + self->pAns); + strncpy(pError,pBueffel,iLen); + break; + case LAKESHORE340__BADPAR: + strncpy(pError,"LAKESHORE340: Invalid parameter specified",iLen); + break; + case LAKESHORE340__BADMALLOC: + strncpy(pError,"LAKESHORE340: Error allocating memory in LAKESHORE340",iLen); + break; + case LAKESHORE340__BADREAD: + strncpy(pError,"LAKESHORE340: Badly formatted answer",iLen); + break; + case LAKESHORE340__BADSET: + strncpy(pError,"LAKESHORE340: Failed three times to write new set value to LAKESHORE340",iLen); + break; + case LAKESHORE340__FAULT: // Covers various LAKESHORE340 self-diagnosed fault conditions + sprintf(pBueffel,"LAKESHORE340: Internal fault condition detected: %s",self->pAns); + strncpy(pError,pBueffel,iLen); + break; + case LAKESHORE340__NOLAKESHORE340: + sprintf(pBueffel,"LAKESHORE340: Wrong model number (driver is for Model 340 only): %s",self->pAns); + strncpy(pError,pBueffel,iLen); + break; + default: + SerialError(iCode, pError,iLen); + break; + } + } diff --git a/site_ansto/hardsup/lakeshore340util.h b/site_ansto/hardsup/lakeshore340util.h new file mode 100644 index 00000000..a2a66fa4 --- /dev/null +++ b/site_ansto/hardsup/lakeshore340util.h @@ -0,0 +1,130 @@ +/*--------------------------------------------------------------------------- + L A K E S H O R E 3 4 0 U T I L + + A few utility functions for talking to a Lakeshore 340 + temperature controller via the SINQ setup: TCP/IP--MAC--RS-232-- + LAKESHORE340. + + Mark Koennecke, Juli 1997 + Mark Lesha, January 2006 (based on ITC4 code) + +----------------------------------------------------------------------------*/ +#ifndef SINQLAKESHORE340 +#define SINQLAKESHORE340 + +/*----------------------- ERRORCODES-------------------------------------- + Most functions return a negative error code on failure. Error codes + defined are those defined for serialsinq plus a few additional ones: +*/ + +#define LAKESHORE340__BADCOM -501 +/* command not recognized */ +#define LAKESHORE340__BADPAR -502 +/* bad parameter to command */ +#define LAKESHORE340__BADMALLOC -503 +/* error allocating memory */ +#define LAKESHORE340__BADREAD -504 +/* error analysing command string on Read */ +#define LAKESHORE340__FAULT -505 +/* fault or overload condition exists in LAKESHORE340 */ +#define LAKESHORE340__NOLAKESHORE340 -510 +/* Controller is not LAKESHORE340 */ +#define LAKESHORE340__BADSET -530 +/* failed three times to set temperature */ +#define LAKESHORE340__READONLY -531 +/*------------------------------------------------------------------------*/ + typedef struct __LAKESHORE340 { + int iRead; + int iControl; + void *pData; + char pAns[80]; /* should be enough for LAKESHORE340 errors */ + /* The LAKESHORE340 does not need multipliers or dividers but + leave them in anyway for back compatibility or future use + but force the value to 1.0 all the time */ + float fDiv; + float fMult; + int iReadOnly; + prs232 controller; + } LAKESHORE340; + + typedef struct __LAKESHORE340 *pLAKESHORE340; + +/*-----------------------------------------------------------------------*/ + int LAKESHORE340_Open(pLAKESHORE340 *pData,char *pHost, int iPort, int iChannel, int iMode); + /***** creates an LAKESHORE340 datastructure and opens a connection to the LAKESHORE340 + controller. Input Parameters are: + the hostname + the port number + the RS-232 channel number on the Mac. + iMode: 1 for ReadOnly, 0 for normal mode + + Return values are 1 for success, a negative error code on + failure. + + */ + + void LAKESHORE340_Close(pLAKESHORE340 *pData); + /****** close a connection to an LAKESHORE340controller and frees its + data structure. The only parameter is a pointer to the data + structure for this controller. This pointer will be invalid after + this call. + */ + + int LAKESHORE340_Config(pLAKESHORE340 *pData, int iTmo, int iRead, + int iControl, float fDiv, float fMult); + /***** configure some aspects of a LAKESHORE340temperature controller. + The parameter are: + - a pointer to the data structure for the controller as + returned by LAKESHORE340_Open + - a value for the connection timeout + - the temperature sensor to use for reading the + temperature. + - the temperature sensor used by the LAKESHORE340controller + for regulating the temperature. + - the divisor needed to calculate the real temperature + from the sensor. + The function returns 1 on success, a negative error code on + failure. + */ + + int LAKESHORE340_Send(pLAKESHORE340 *pData, char *pCommand, char *pReply, int iLen); + /******* send a the command in pCommand to the LAKESHORE340controller. + A possible reply is returned in the buffer pReply. + Maximum iLen characters are copied to pReply. + The first parameter is a pointer to a LAKESHORE340data structure + as returned by LAKESHORE340_Open. + + Return values are 1 for success, a negative error code on + failure. + */ + + int LAKESHORE340_Read(pLAKESHORE340 *pData, float *fVal); + /******* reads the current actual temperature of the sensor + configured by ConfigLAKESHORE340for reading. The value is returned + in fVal. The first parameter is a pointer to a LAKESHORE340 + data structure as returned by LAKESHORE340_Open. + + Return values are 1 for success, a negative error code on + failure. + */ + + int LAKESHORE340_Set(pLAKESHORE340 *pData, float fVal); + /****** sets a new preset temperature in the LAKESHORE340temperature + controller. Parameters are: + - a pointer to a LAKESHORE340data structure as returned by LAKESHORE340_Open. + - the new preset value. + + Return values are 1 for success, a negative error code on + failure. + */ + + void LAKESHORE340_ErrorTxt(pLAKESHORE340 *pData, int iCode, char *pError, int iLen); + /******* translates one of the negative error LAKESHORE340error codes + into text. Maximum iLen bytes will be copied to the + buffer pError; + */ + + +#endif + + diff --git a/site_ansto/hardsup/lh45util.c b/site_ansto/hardsup/lh45util.c new file mode 100644 index 00000000..16dc07b2 --- /dev/null +++ b/site_ansto/hardsup/lh45util.c @@ -0,0 +1,390 @@ +/*-------------------------------------------------------------------------- + + L H 4 5 U T I L + + A few utility functions for dealing with a LH45 temperature controller + within the SINQ setup: host -- TCP/IP -- MAC --- RS-232. + + Mark Koennecke, Juli 1997 + Mark Lesha, January 2006 (based on ITC4 code) + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +---------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "serialsinq.h" +#include "lh45util.h" +/* -------------------------------------------------------------------------*/ + + int LH45_Check_Status(pLH45 self) /* Can be called to check for correct operation of the LH45 */ + { + int iRet; + char pCommand[20]; + char pReply[132]; + /* Check the status. It should read '03 REMOTE START' or possibly '03 REMOTE START,DEGASING'. */ + /* If there is any LH45 overload or other fault condition it will be detected here. */ + // printf("Checking LH45 status...");fflush(stdout); + sprintf(pCommand,"status"); + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + if(iRet <= 0) + { + //transactRS232(self->controller,"\nDEBUG: RS232 transaction bad.\n",28,pReply,79); + return iRet; + } + if (strncmp(pReply,"03 REMOTE START",15)!=0) + { + //transactRS232(self->controller,"\nDEBUG: RS232 response bad\n",27,pReply,79); + //transactRS232(self->controller,pReply,strlen(pReply),pReply,79); + strcpy(self->pAns,pReply); + return LH45__FAULT; + } + //transactRS232(self->controller,"\nDEBUG: Status reply is good!\n",30,pReply,79); + return 1; // 1 = no fault + } + + int LH45_Setup(pLH45 self, int iControl) /* Operations common to both Open and Config functions */ + { + int iRet; + char pCommand[20]; + //char pReply[132]; + + /* MJL enable RS232 debugging mode. */ + //setRS232Debug(self->controller,1); + //printf("***RS232 debug mode enabled for LH45***\n");fflush(stdout); + + /* switch to remote operation */ + /* NOTE: The Julabo does not provide any response for 'out' commands, + so we just use writeRS232 not transactRS232 for these */ + //printf("Issuing out_mode_05 1 command...");fflush(stdout); + sprintf(pCommand,"out_mode_05 1"); + iRet = writeRS232(self->controller, pCommand,strlen(pCommand)); + //printf("Response: '%s'\n",pReply);fflush(stdout); + if(iRet != 1) + { + return iRet; + } +/* if(pReply[0] == '-') // Probably an error response + { + strcpy(self->pAns,pReply); + return LH45__BADCOM; + } */ + + /* Check the LH45 operating status */ + if ((iRet=LH45_Check_Status(self))!=1) + return iRet; + + /* Set heater sensor */ + /* For the LH45 there is a choice of internal or external sensor control, + set internal when iControl==1 and external when iControl==2 */ + sprintf(pCommand,"out_mode_04 %1.1d",self->iControl - 1); + iRet = writeRS232(self->controller, pCommand,strlen(pCommand)); + if(iRet != 1) + { + return LH45__BADCOM; + } + /* else if(pReply[0] == '-') // Probably an error response + { + strcpy(self->pAns,pReply); + return LH45__BADCOM; + } */ + self->iControl=iControl; // Store control sensor setting since it was assigned to the LH45 successfully + + /* reset timeout - currently not being used */ + /* iRet = SerialConfig(&self->pData, 10); + if(iRet != 1) + { + return iRet; + } */ + + /* Check the LH45 operating status one last time */ + if ((iRet=LH45_Check_Status(self))!=1) + return iRet; + + return 1; /* Success */ + } + + int LH45_Open(pLH45 *pData, char *pRS232, int iSensor, int iCTRL, int iMode) + { + pLH45 self = NULL; + + self = (pLH45)malloc(sizeof(LH45)); + if(self == NULL) + { + return LH45__BADMALLOC; + } + *pData = self; + self->iControl = iCTRL; + self->iRead = iSensor; + self->iReadOnly = iMode; + + /* The LH45 doesn't require divisors or multipliers + and they are always forced to 1.0 */ + self->fDiv = 1.0; + self->fMult = 1.0; + + self->controller = NULL; + + self->controller = (prs232)FindCommandData(pServ->pSics,pRS232, + "RS232 Controller"); + if(!self->controller){ + /*SCWrite(pCon,"ERROR: motor controller not found",eError); */ + return LH45__BADCOM; + } + + if(!self->iReadOnly) + return LH45_Setup(self, self->iControl); + } +/*--------------------------------------------------------------------------*/ + void LH45_Close(pLH45 *pData) + { + int iRet; + //char pReply[132]; + char pCommand[20]; + pLH45 self; + + self = *pData; + if (!self) + return; // Just in case + + /* switch off remote operation */ + /* Not sure if this is really necessary but do it just in case */ + sprintf(pCommand,"out_mode_05 0"); + iRet = writeRS232(self->controller, pCommand,strlen(pCommand)); + /* Don't bother checking the status but record any error reply */ +/* if(pReply[0] == '-') // Probably an error response + strcpy(self->pAns,pReply); */ + + return; + } +/*--------------------------------------------------------------------------*/ + int LH45_Config(pLH45 *pData, int iTmo, int iRead, int iControl, + float fDiv,float fMult) + { + pLH45 self; + + self = *pData; + + return LH45_Setup(self, iControl); + } +/* --------------------------------------------------------------------------*/ + int LH45_Send(pLH45 *pData, char *pCommand, char *pReply, int iLen) + { + int iRet; + pLH45 self; + + self = *pData; + + /* make sure, that there is a \r at the end of the command */ +/* if(strchr(pCommand,(int)'\r') == NULL) + { + strcat(pCommand,"\r"); + } */ + + /* Send command direct to the LH45 */ + /* Because the Julabo LH45 only provides a response for the 'version', 'status' + and 'in' commands and not for the 'out' commands, just perform a write + for those and not a full transaction. */ + if (strncmp(pCommand,"out",3)==0) // 'out' command; LH45 does not send any response. + { + iRet=writeRS232(self->controller,pCommand,strlen(pCommand)); + *pReply='\0'; + } + else + iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,iLen); + if(iRet <= 0) + return iRet; + + /* Check the LH45 operating status after issuing the command, and return */ + iRet=LH45_Check_Status(self); + return iRet; + } +/*--------------------------------------------------------------------------*/ + int LH45_Read(pLH45 *pData, float *fVal) + { + char pCommand[20], pReply[132]; + int iRet; + float fRead = -9999999.; + pLH45 self; + + self = *pData; + + + /* for the LH45 there are three temp measurements available */ + switch(self->iRead) + { + case 1: + sprintf(pCommand,"in_pv_00"); + break; + case 2: + sprintf(pCommand,"in_pv_02"); + break; + case 3: + sprintf(pCommand,"in_pv_03"); + break; + default: + return LH45__BADPAR; // But shouldn't happen + } + + iRet = transactRS232(self->controller, pCommand,strlen(pCommand), + pReply,79); + + if(iRet <= 0) + { + return iRet; + } + if(pReply[0] == '-'&&strlen(pReply)>7) // Not a number (-XXX.X\r), probably an error response + { + strcpy(self->pAns,pReply); + return LH45__BADCOM; + } + + iRet = sscanf(pReply,"%f",&fRead); + if(iRet != 1) + { + return LH45__BADREAD; + } + + *fVal = fRead; + + /* Check the LH45 operating status after the read, and return */ + iRet=LH45_Check_Status(self); + return iRet; + } +/* -------------------------------------------------------------------------*/ + int LH45_Set(pLH45 *pData, float fVal) + { + char pCommand[20], pCommandRead[20], pReply[132]; + int iRet, i; + const float fPrecision = 0.1; + float fDelta, fRead; + pLH45 self; + + self = *pData; + + if(self->iReadOnly) + { + return LH45__READONLY; + } + + sprintf(pCommand,"out_sp_00 %1.1f",fVal); + sprintf(pCommandRead,"in_sp_00"); // To read back and check the set value + + /* try three times: send, read, test, if OK return, else resend. */ + for(i = 0; i < 3; i++) + { + /* send command, since it's an 'out' we don't get any response, so use writeRS232 */ + iRet = writeRS232(self->controller,pCommand,strlen(pCommand)); + //writeRS232(self->controller,pReply,strlen(pReply)); // MJL DEBUG + if(iRet != 1) + { + return iRet; + } + /* if(pReply[0] == '-') // Probably an error response + { + strcpy(self->pAns,pReply); + return LH45__BADCOM; + } */ + /* read the set value again using the 'in' command */ + iRet = transactRS232(self->controller,pCommandRead,strlen(pCommandRead),pReply,131); + //writeRS232(self->controller,pReply,strlen(pReply)); // MJL DEBUG + if(iRet <= 0) + { + return iRet; + } + if(pReply[0] == '-'&&strlen(pReply)>7) // Not a number (-XXX.X\r), probably an error response + { + strcpy(self->pAns,pReply); + return LH45__BADCOM; + } + /* Convert the value read back. */ + iRet=sscanf(pReply,"%f",&fRead); + if(iRet != 1) + { + return LH45__BADREAD; + } + /* check the value read back */ + fDelta = fRead - fVal; + if(fDelta < 0) + fDelta = -fDelta; + if(fDelta < fPrecision) + { + /* Success, but check the LH45 operating status afterwards, and return */ + /* Don't bother to repeat the write if we get an error here as it would indicate + a fault or overload in the LH45, not a comms problem */ + iRet=LH45_Check_Status(self); + return iRet; + } + } + return LH45__BADSET; + } +/* -------------------------------------------------------------------------*/ + void LH45_ErrorTxt(pLH45 *pData,int iCode, char *pError, int iLen) + { + char pBueffel[512]; + pLH45 self; + + self = *pData; + + switch(iCode) + { + case LH45__BADCOM: + sprintf(pBueffel,"LH45: Invalid command or offline, got %s", + self->pAns); + strncpy(pError,pBueffel,iLen); + break; + case LH45__BADPAR: + strncpy(pError,"LH45: Invalid parameter specified",iLen); + break; + case LH45__BADMALLOC: + strncpy(pError,"LH45: Error allocating memory in LH45",iLen); + break; + case LH45__BADREAD: + strncpy(pError,"LH45: Badly formatted answer",iLen); + break; + case LH45__BADSET: + strncpy(pError,"LH45: Failed three times to write new set value to LH45",iLen); + break; + case LH45__FAULT: // Covers various LH45 self-diagnosed fault conditions + sprintf(pBueffel,"LH45: Internal fault condition detected: %s",self->pAns); + strncpy(pError,pBueffel,iLen); + break; + default: + SerialError(iCode, pError,iLen); + break; + } + } diff --git a/site_ansto/hardsup/lh45util.h b/site_ansto/hardsup/lh45util.h new file mode 100644 index 00000000..53862c9e --- /dev/null +++ b/site_ansto/hardsup/lh45util.h @@ -0,0 +1,130 @@ +/*--------------------------------------------------------------------------- + L H 4 5 U T I L + + A few utility functions for talking to a Julabo LH45 + temperature controller via the SINQ setup: TCP/IP--MAC--RS-232-- + LH45. + + Mark Koennecke, Juli 1997 + Mark Lesha, January 2006 (based on ITC4 code) + +----------------------------------------------------------------------------*/ +#ifndef SINQLH45 +#define SINQLH45 + +/*----------------------- ERRORCODES-------------------------------------- + Most functions return a negative error code on failure. Error codes + defined are those defined for serialsinq plus a few additional ones: +*/ + +#define LH45__BADCOM -501 +/* command not recognized */ +#define LH45__BADPAR -502 +/* bad parameter to command */ +#define LH45__BADMALLOC -503 +/* error allocating memory */ +#define LH45__BADREAD -504 +/* error analysing command string on Read */ +#define LH45__FAULT -505 +/* fault or overload condition exists in LH45 */ +#define LH45__NOLH45 -510 +/* Controller is not LH45 */ +#define LH45__BADSET -530 +/* failed three times to set temperature */ +#define LH45__READONLY -531 +/*------------------------------------------------------------------------*/ + typedef struct __LH45 { + int iRead; + int iControl; + void *pData; + char pAns[80]; /* should be enough for LH45 errors */ + /* The LH45 does not need multipliers or dividers but + leave them in anyway for back compatibility or future use + but force the value to 1.0 all the time */ + float fDiv; + float fMult; + int iReadOnly; + prs232 controller; + } LH45; + + typedef struct __LH45 *pLH45; + +/*-----------------------------------------------------------------------*/ + int LH45_Open(pLH45 *pData,char *pHost, int iPort, int iChannel, int iMode); + /***** creates an LH45 datastructure and opens a connection to the LH45 + controller. Input Parameters are: + the hostname + the port number + the RS-232 channel number on the Mac. + iMode: 1 for ReadOnly, 0 for normal mode + + Return values are 1 for success, a negative error code on + failure. + + */ + + void LH45_Close(pLH45 *pData); + /****** close a connection to an LH45controller and frees its + data structure. The only parameter is a pointer to the data + structure for this controller. This pointer will be invalid after + this call. + */ + + int LH45_Config(pLH45 *pData, int iTmo, int iRead, + int iControl, float fDiv, float fMult); + /***** configure some aspects of a LH45temperature controller. + The parameter are: + - a pointer to the data structure for the controller as + returned by LH45_Open + - a value for the connection timeout + - the temperature sensor to use for reading the + temperature. + - the temperature sensor used by the LH45controller + for regulating the temperature. + - the divisor needed to calculate the real temperature + from the sensor. + The function returns 1 on success, a negative error code on + failure. + */ + + int LH45_Send(pLH45 *pData, char *pCommand, char *pReply, int iLen); + /******* send a the command in pCommand to the LH45controller. + A possible reply is returned in the buffer pReply. + Maximum iLen characters are copied to pReply. + The first parameter is a pointer to a LH45data structure + as returned by LH45_Open. + + Return values are 1 for success, a negative error code on + failure. + */ + + int LH45_Read(pLH45 *pData, float *fVal); + /******* reads the current actual temperature of the sensor + configured by ConfigLH45for reading. The value is returned + in fVal. The first parameter is a pointer to a LH45 + data structure as returned by LH45_Open. + + Return values are 1 for success, a negative error code on + failure. + */ + + int LH45_Set(pLH45 *pData, float fVal); + /****** sets a new preset temperature in the LH45temperature + controller. Parameters are: + - a pointer to a LH45data structure as returned by LH45_Open. + - the new preset value. + + Return values are 1 for success, a negative error code on + failure. + */ + + void LH45_ErrorTxt(pLH45 *pData, int iCode, char *pError, int iLen); + /******* translates one of the negative error LH45error codes + into text. Maximum iLen bytes will be copied to the + buffer pError; + */ + + +#endif + + diff --git a/site_ansto/hardsup/makefile b/site_ansto/hardsup/makefile new file mode 100644 index 00000000..59f99ce1 --- /dev/null +++ b/site_ansto/hardsup/makefile @@ -0,0 +1,21 @@ +#--------------------------------------------------------------------------- +# Makefile for the site hardware support library +# Paul Hathaway, Nov 2004 +#-------------------------------------------------------------------------- + +.SUFFIXES: +.SUFFIXES: .c .o + +SRC = . +CC = gcc +CFLAGS = -g -DLINUX $(DFORTIFY) -I$(SRC) -I../.. + +HOBJ= serialsinq.o itc4util.o lh45util.o lakeshore340util.o asynsrv_utility.o geterrno.o strjoin.o + +libhlib.a: $(HOBJ) + rm -f libhlib.a + ar cr libhlib.a $(HOBJ) + ranlib libhlib.a + +clean: + rm -f *.o *.a diff --git a/site_ansto/hardsup/makeprint.c b/site_ansto/hardsup/makeprint.c new file mode 100644 index 00000000..b35188e2 --- /dev/null +++ b/site_ansto/hardsup/makeprint.c @@ -0,0 +1,276 @@ +#define ident "1B02" +#ifdef VAXC +#module MakePrint ident +#endif +#ifdef __DECC +#pragma module MakePrint ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Department ASQ | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]MAKEPRINT.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1995 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]MakePrint - + tasmad_disk:[mad.lib.sinq]MakePrint + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb MakePrint debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb MakePrint +** +** Updates: +** 1A01 30-Nov-1995 DM. Initial version. +** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB. +**============================================================================ +** The entry points included in this module are described below. Prototypes +** can be defined via: +** +** #include +** +** MakeCharPrintable - routine used by MakePrintable and MakeMemPrintable. +** MakeMemPrintable - version of MakePrintable which will handle +** buffers containing a NUL character. +** MakePrint - ensure all characters in a buffer are printable. +** MakePrintable - extended version of MakePrint. +**--------------------------------------------------------------------- +** char *MakePrint (*text) +** --------- +** Input Args: +** none +** Output Args: +** none +** Modified Args: +** char *text +** Return status: +** A pointer to "text". +** Routines called: +** none +** Description: +** The routine ensures that all characters in "text" are 7-bit +** and then replaces any non-printing character with a ".". A trailing +** "\n" or "\r" is removed. +**--------------------------------------------------------------------------- +** int *MakeCharPrintable (*out, out_size, in) +** ----------------- +** Input Args: +** char in -- the character to be converted. +** int out_size -- the size of the out buffer. +** Output Args: +** char *out -- buffer to hold the converted text. +** Modified Args: +** none +** Return status: +** The number of characters put into the output buffer. +** Routines called: +** none +** Description: +** The routine puts a printable version of the character "in" into the +** "out" buffer. The printable version is generated as follows: +** +** a) If the parity bit of a char is set, a "^" is inserted into the +** output buffer, the parity bit of the char is cleared and processed +** further. +** b) If the char is "^", "\^" is inserted into the output buffer. +** c) If the char is "\", "\\" is inserted into the output buffer. +** d) If the char is a standard C-language control char, it gets replaced +** by a recognised backslash escape sequence. The following are +** recognised: +** NUL 0x00 --> \0 +** BEL 0x07 --> \a +** BS 0x08 --> \b +** HT 0x09 --> \t +** LF 0x0a --> \n +** VT 0x0b --> \v +** FF 0x0c --> \f +** CR 0x0d --> \r +** e) If the character is printable (i.e. between " "/0x20 and "~"/0x7e +** inclusive), it is inserted into the output buffer as is. +** f) Anything else gets inserted as "\xxx", where xxx is the octal +** representation of the character. +**--------------------------------------------------------------------------- +** char *MakePrintable (*out, out_size, *in) +** ------------- +** Input Args: +** char *in -- the text to be converted. +** int out_size -- the size of the out buffer. +** Output Args: +** char *out -- buffer to hold the converted text. +** Modified Args: +** none +** Return status: +** A pointer to "out". +** Routines called: +** none +** Description: +** The routine converts characters in the "in" string to a printable +** representation using MakeCharPrintable and copies them to "out" until +** a null is detected. +**--------------------------------------------------------------------------- +** char *MakeMemPrintable (*out, out_size, *in, in_len) +** ---------------- +** Input Args: +** int out_size -- the size of the out buffer. +** char *in -- the text to be converted. +** int in_len -- the number of characters to be converted. +** Output Args: +** char *out -- buffer to hold the converted text. +** Modified Args: +** none +** Return status: +** A pointer to "out". +** Routines called: +** none +** Description: +** The routine is the same as MakePrintable, except that it converts +** a given number of characters rather than a null terminated string. +**============================================================================*/ +/* +**--------------------------------------------------------------------------- +** Global Definitions +*/ +#include +#include +#include +#ifdef FORTIFY + #include +#endif + +#include + +#define NIL ('\0') +/*-------------------------------------------------------------------------- +** Global Variables +*/ +/* +**-------------------------------------------------------------------------- +** MakeCharPrintable: makes a single character printable. +*/ + int MakeCharPrintable (char *out, int out_size, char in) { +/* ================= +** +** Return value is number of chars put into *out. +*/ + char buff[8], *pntr; + + pntr = buff; + + if ((in & 0x80) != 0) { /* Parity bit set? */ + *pntr++ = '^'; /* Yes. Put a '^' in the buffer .. */ + in = in & 0x7f; /* .. and remove the parity bit. */ + } + + switch (in) { + case '^': *pntr++ = '\\'; *pntr++ = '^'; break; + case '\\': *pntr++ = '\\'; *pntr++ = '\\'; break; + case '\000': *pntr++ = '\\'; *pntr++ = '0'; break; + case '\007': *pntr++ = '\\'; *pntr++ = 'a'; break; + case '\010': *pntr++ = '\\'; *pntr++ = 'b'; break; + case '\011': *pntr++ = '\\'; *pntr++ = 't'; break; + case '\012': *pntr++ = '\\'; *pntr++ = 'n'; break; + case '\013': *pntr++ = '\\'; *pntr++ = 'v'; break; + case '\014': *pntr++ = '\\'; *pntr++ = 'f'; break; + case '\015': *pntr++ = '\\'; *pntr++ = 'r'; break; + default: + if ((in < ' ') || (in > '~')) { + pntr += sprintf (pntr, "\\%03.3o", in); + }else { + *pntr++ = in; + } + } + out_size = (out_size > (pntr - buff)) ? (pntr - buff) : out_size; + memcpy (out, buff, out_size); + return out_size; + } +/* +**-------------------------------------------------------------------------- +** MakeMemPrintable: alternative version of MakePrintable. +*/ + char *MakeMemPrintable ( +/* ================ +*/ char *out, + int out_size, + char *in, + int in_len) { + + int i; + char *pntr; + + if (out_size <= 0) return out; + + while ((out_size > 1) && (in_len > 0)) { + i = MakeCharPrintable (out, (out_size - 1), *in); + out += i; out_size -= i; + in++; in_len--; + } + *out = NIL; + return out; + } +/* +**-------------------------------------------------------------------------- +** MakePrint: Make all characters in a buffer printable. +*/ + char *MakePrint (char *chr) { +/* ========= +*/ + int len, i; + + for (i = 0; chr[i] != NIL; i++) chr[i] &= 0x7F; + + len = strlen (chr); + if (len <= 0) return chr; + + if (chr[len-1] == '\r') chr[len-1] = NIL; + if (chr[len-1] == '\n') chr[len-1] = NIL; + + for (i = 0; chr[i] != NIL; i++) { + if (chr[i] < ' ') chr[i] = '.'; + if (chr[i] == 0x7F) chr[i] = '.'; + } + + return chr; + } +/* +**-------------------------------------------------------------------------- +** MakePrintable: improved version of MakePrint. +*/ + char *MakePrintable ( +/* ============= +*/ char *out, + int out_size, + char *in) { + + int i; + char *pntr; + + if (out_size <= 0) return out; + + while ((out_size > 1) && (*in != NIL)) { + i = MakeCharPrintable (out, (out_size - 1), *in); + in++; out += i; out_size -= i; + } + *out = NIL; + return out; + } +/*-------------------------------------------- End of MakePrint.C =======*/ diff --git a/site_ansto/hardsup/rs232c_def.h b/site_ansto/hardsup/rs232c_def.h new file mode 100644 index 00000000..2753bd1b --- /dev/null +++ b/site_ansto/hardsup/rs232c_def.h @@ -0,0 +1,186 @@ +#ifndef _rs232c_def_ +#define _rs232c_def_ +/*------------------------------------------------ RS232C_DEF.H Ident V02G +** Definitions for the RS-232-C Server Protocol +** +** On UNIX systems, this file is located in /public/lib/include +** On VMS systems, this file is a module in mad_lib:sinq_c.tlb +*/ +#define RS__PROTOCOL_ID "V01A" +#define RS__PROTOCOL_ID_V01B "V01B" + +#define RS__PROTOCOL_CODE 1 /* Code corresponding to RS__PROTOCOL_ID */ +#define RS__PROTOCOL_CODE_V01B 2 /* Code corresponding to RS__PROTOCOL_ID_0 */ + +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif +/*---------------------------------------------------------------------------- +** Structure of Message from Client to Server - everything is sent in ASCII +** for LabView's benefit. +** Name #bytes Description +** ==== ====== =========== +** msg_size 4 Number of bytes following (rounded up to multiple +** of 4). +** msg_id 4 Message ident (an incrementing counter for debugging). +** c_pcol_lvl 4 Client-Protocol-Level (should be "V01A"). +** serial_port 4 Serial port to which commands should be sent. This +** is a small integer). +** tmo 4 Time-out in units of 0.1 secs (<0 = "wait for ever"). +** terms 1 + 3 Terminators. The first char gives the number of +** terminators (up to 3) and the following 3 chars +** are valid response terminators, e.g. "1\r\0\0". +** n_cmnds 4 Number of commands following. +** cmnds 356 The command buffer. This is a concatenated list of +** commands with the structure described below. +** +** Special Cases of msg_size +** ------------------------- +** "-001" ==> the client is just about to close his connection. +** "-002" ==> this is a request to the server for him to turn on tracing. +** The reply should be simply an echo of the 4 bytes "-002". +** "-003" ==> this is a request to the server for him to turn off tracing. +** The reply should be simply an echo of the 4 bytes "-003". +** "-004" ==> this is a request to the server for him to flush his buffers. +** The reply should be simply an echo of the 4 bytes "-004". +** +** Structure of a command item in the cmnds buffer. +** +** a) RS__PROTOCOL_ID = "V01A" +** +** Name #bytes Description +** ==== ====== =========== +** cmnd_len 2 The number of bytes following encoded as 2 ASCII +** decimal chars. +** cmnd The command to be sent on Serial Port . +** The string should contain any required terminator +** bytes but should not be zero-terminated (unless +** the zero-byte should be transmitted at the end +** of the command). cmnd_len should count the +** terminator byte. +** +** An example of a command item might be: "06RMT 1\r" +** +** b) RS__PROTOCOL_ID = "V01B" +** +** Name #bytes Description +** ==== ====== =========== +** cmnd_len 4 The number of bytes following encoded as 4 ASCII +** decimal chars. +** cmnd The command to be sent on Serial Port . +** The string should contain any required terminator +** bytes but should not be zero-terminated (unless +** the zero-byte should be transmitted at the end +** of the command). should count the +** terminator byte. +** +** An example of a command item might be: "0006RMT 1\r" +**--------------------------------------------------------------------------*/ + struct RS__MsgStruct { + char msg_size[4]; /* 4 ASCII decimal chars!! */ + char msg_id[4]; + char c_pcol_lvl[4]; /* Client protocol level */ + char serial_port[4]; + char tmo[4]; /* Units are 0.1 secs */ + char terms[4]; + char n_cmnds[4]; + char cmnds[356]; + }; + /* + ** The "cmnds" buffer in RS__MsgStruct is a concatenated + ** list of the following structures. + */ + struct RS__CmndStruct { + char cmnd_len[2]; + char cmnd[1]; + }; + struct RS__CmndStruct_V01B { + char cmnd_len[4]; + char cmnd[1]; + }; +/*---------------------------------------------------------------------------- +** Structure of Reply from Server to Client - everything is sent in ASCII +** for LabView's benefit. +** +** Name #bytes Description +** ==== ====== =========== +** msg_size 4 Number of bytes following (rounded up to multiple +** of 4). +** msg_id 4 Message ident (this is a copy of the msg_id field +** in the message from Client to Server). +** s_pcol_lvl 4 Server-Protocol-Level (should be "V01A" or "V01B"). +** n_rply 4 Number of replies following. If < 0, an error has +** been detected and sub_status may give additional +** information. +** rplys 496 The reply buffer. This is a concatenated list of +** replies with the structure described below. +** sub_status 12 A sub-status code. This field overlays the first 12 +** bytes of rplys and may provide additional +** information in the case that n_rply < 0. +** +** Structure of a reply item in the rplys buffer. +** +** a) RS__PROTOCOL_ID = "V01A" +** +** Name #bytes Description +** ==== ====== =========== +** rply_len 2 The number of bytes following encoded as 2 ASCII +** decimal chars. +** term 1 The terminating character which was detected at the +** end of the reply. This will be one of the +** characters specified in . +** rply The zero-terminated reply. This is effectively the +** reply as received with the terminating character +** replaced by '\0'. +** +** An example of a reply item might be: "08\r12.345\0" +** +** b) RS__PROTOCOL_ID = "V01B" +** +** Name #bytes Description +** ==== ====== =========== +** rply_len 4 The number of bytes following encoded as 4 ASCII +** decimal chars. +** term 1 The terminating character which was detected at the +** end of the reply. This will be one of the +** characters specified in . +** rply The zero-terminated reply. This is effectively the +** reply as received with the terminating character +** replaced by '\0'. +** +** An example of a reply item might be: "0009\r12.3456\0" +**--------------------------------------------------------------------------*/ + struct RS__RespStruct { + char msg_size[4]; + char msg_id[4]; + char s_pcol_lvl[4]; /* Server protocol level */ + char n_rply[4]; /* Error if < 0 */ + union { + char rplys[496]; + char sub_status[12]; + } u; + }; + /* + ** The "rplys" buffer in RS__RespStruct is a + ** concatenated list of the following structures. + */ + struct RS__RplyStruct { + char rply_len[2]; /* 2 ASCII decimal chars!! + ** The length includes the + ** terminator, term, and the + ** zero terminator of rply. + */ + char term; /* The terminating character */ + char rply[1]; /* Zero terminated string */ + }; + struct RS__RplyStruct_V01B { + char rply_len[4]; /* 4 ASCII decimal chars!! + ** The length includes the + ** terminator, term, and the + ** zero terminator of rply. + */ + char term; /* The terminating character */ + char rply[1]; /* Zero terminated string */ + }; +/*------------------------------------------------ End of RS232C_DEF.H --*/ +#endif /* _rs232c_def_ */ diff --git a/site_ansto/hardsup/serialsinq.c b/site_ansto/hardsup/serialsinq.c new file mode 100644 index 00000000..76028ea6 --- /dev/null +++ b/site_ansto/hardsup/serialsinq.c @@ -0,0 +1,914 @@ +/*------------------------------------------------------------------------- + S E R I A L S I N Q + Implementation file of the functions for talking with a RS--232 port + on a SINQ terminal server. This code has been adapted from code + provided by David Maden for the EL734 motor controller. A new version + became necessary as the Dornier velocity selector supports a + completely different protocoll than the EL734. The basics, however, are + the same. + + Mark Koennecke, Juli 1997 + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#ifdef FORTIFY +#include "fortify.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __VMS +#include +#else +#include +#endif + +/*-----------------------------------------------------------------*/ +#include "sinq_prototypes.h" +#include "el734_def.h" +#include "rs232c_def.h" +#include "el734fix.h" +#include "serialsinq.h" + +#define True 1 +#define False 0 + + struct SerialInfo { + int skt; + int iForce; + int port; + int chan; + char host[20]; + int tmo; + int msg_id; + int n_replies, max_replies; + char pTerms[4]; + char pSendTerm[10]; + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + SerialSleep pFunc; + void *pData; + struct AsynSrv__info sAsync; + }; +/*------------------- The default sleep function -----------------------*/ + static int SerialNccrrrh(void *pData, int iTime) + { + usleep(50); + return 1; + } + +/*-----------------------------------------------------------------------*/ + int SerialOpen(void **pData, char *pHost, int iPort, int iChannel) + { + int status; + struct SerialInfo *my_info; + void *my_hndl; + struct hostent *rmt_hostent; + struct in_addr *rmt_inet_addr_pntr; + int rmt_sockname_len; + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + char msr_cmnd[20]; + struct RS__RplyStruct *rply_ptr; + + *pData = NULL; + +/* +** allocate memory first +*/ + *pData = malloc (sizeof (struct SerialInfo)); + if (*pData == NULL) { + return EL734__BAD_MALLOC; /* malloc failed!! */ + } + my_info = *pData; + memset(my_info,0,sizeof(struct SerialInfo)); + +/* +**-------------------------- Set up the connection +*/ + my_info->sAsync.port = iPort; + strcpy(my_info->sAsync.host,pHost); + my_info->sAsync.chan = iChannel; + status = AsynSrv_Open (&(my_info->sAsync)); + if (status != 1) { + return OPENFAILURE; + } + + /* intialize data structures */ + StrJoin (my_info->host, sizeof (my_info->host), pHost, ""); + my_info->skt = my_info->sAsync.skt; + my_info->port = iPort; + my_info->chan = iChannel; + my_info->tmo = 100; + my_info->msg_id = 0; + my_info->pFunc = SerialNccrrrh; + my_info->pData = NULL; + strcpy(my_info->pTerms,"1\r\n\0"); + my_info->iForce = 0; + memset(my_info->pSendTerm,0,9); + strcpy(my_info->pSendTerm,"\r\n"); + + return 1; + } +/*-----------------------------------------------------------------------*/ + int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel) + { + int status; + struct SerialInfo *my_info; + void *my_hndl; + struct hostent *rmt_hostent; + struct in_addr *rmt_inet_addr_pntr; + int rmt_sockname_len; + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + char msr_cmnd[20]; + struct RS__RplyStruct *rply_ptr; + + *pData = NULL; + + /* create pData */ + *pData = malloc (sizeof (struct SerialInfo)); + if (*pData == NULL) { + return EL734__BAD_MALLOC; /* malloc failed!! */ + } + my_info = *pData; + memset(my_info,0,sizeof(struct SerialInfo)); + + +/* +**-------------------------- Set up the connection +*/ + my_info->sAsync.port = iPort; + strcpy(my_info->sAsync.host,pHost); + my_info->sAsync.chan = iChannel; + status = AsynSrv_OpenNew (&(my_info->sAsync)); + if (status != 1) { + return OPENFAILURE; + } + + /* intialize data structures */ + StrJoin (my_info->host, sizeof (my_info->host), pHost, ""); + my_info->skt = my_info->sAsync.skt; + my_info->port = iPort; + my_info->chan = iChannel; + my_info->tmo = 100; + my_info->msg_id = 0; + my_info->pFunc = SerialNccrrrh; + my_info->pData = NULL; + strcpy(my_info->pTerms,"1\r\n\0"); + my_info->iForce = 1; + memset(my_info->pSendTerm,0,9); + strcpy(my_info->pSendTerm,"\r\n"); + + return 1; + } +/*--------------------------------------------------------------------------*/ + int SerialConfig(void **pData, int iTmo) + { + struct SerialInfo *my_info = NULL; + + my_info = (struct SerialInfo *)*pData; + assert(my_info); + + if(iTmo < 100) + { + my_info->tmo = 1; + return 1; + } + else + { + my_info->tmo = iTmo/100; /* convert to deci seconds */ + if(my_info->tmo > 9999)my_info->tmo = 9999; + } + return 1; + } +/*--------------------------------------------------------------------------*/ + int GetSerialTmo(void **pData) + { + struct SerialInfo *my_info = NULL; + int iTmo; + + my_info = (struct SerialInfo *)*pData; + assert(my_info); + + iTmo = my_info->tmo*100-99; /* convert back to milli seconds */ + + return iTmo; + } + int SerialGetTmo(void **pData) + { + return GetSerialTmo(pData); + } +/*--------------------------------------------------------------------------*/ + int SerialGetSocket(void **pData) + { + struct SerialInfo *my_info = NULL; + int iTmo; + + my_info = (struct SerialInfo *)*pData; + assert(my_info); + + return my_info->skt; + + return 1; + } +/*--------------------------------------------------------------------------*/ + int SerialClose(void **pData) + { + + struct SerialInfo *info_ptr; + char buff[4]; + + info_ptr = (struct SerialInfo *) *pData; + if (info_ptr == NULL) return True; + + if (info_ptr->skt != 0) { + AsynSrv_Close (&(info_ptr->sAsync),0); + info_ptr->skt = 0; + } + free (*pData); + *pData = NULL; + return True; + } +/*--------------------------------------------------------------------------*/ + int SerialForceClose(void **pData) + { + + struct SerialInfo *info_ptr; + char buff[4]; + + info_ptr = (struct SerialInfo *) *pData; + if (info_ptr == NULL) return True; + + if (info_ptr->skt != 0) { + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + } + free (*pData); + *pData = NULL; + return True; + } +/*--------------------------------------------------------------------------*/ + int SerialATerm(void **pData, char *pTerm) + { + struct SerialInfo *my_info = NULL; + + my_info = (struct SerialInfo *)*pData; + if(my_info == NULL) + { + printf("Serious Programming problem: data = NULL\n"); + return 0; + } + + /* only three characters in this field */ + if(strlen(pTerm) > 4) + { + return 0; + } + memset(my_info->pTerms,0,4); + strcpy(my_info->pTerms,pTerm); + + return 1; + } +/*--------------------------------------------------------------------------*/ + int SerialAGetTerm(void **pData, char *pTerm, int iTermLen) + { + struct SerialInfo *my_info = NULL; + + my_info = (struct SerialInfo *)*pData; + assert(my_info); + + strncpy(pTerm,my_info->pTerms,iTermLen); + + return 1; + } +/*-------------------------------------------------------------------------*/ + int SerialSendTerm(void **pData, char *pTerm) + { + struct SerialInfo *my_info = NULL; + + my_info = (struct SerialInfo *)*pData; + assert(my_info); + + /* only 0 characters in this field */ + if(strlen(pTerm) > 9) + { + return 0; + } + strcpy(my_info->pSendTerm,pTerm); + + return 1; + } + +/*---------------------------------------------------------------------------*/ + + int SerialSend(void **pData, char *pCommand) + { + struct SerialInfo *info_ptr; + int status, c_len, size, max_size, ncmnds; + int bytes_to_come, bytes_left; + int iResult; + char *nxt_byte_ptr; + char err_text[80]; + char text[20]; + char *txt_ptr; + char *cmnd_lst_ptr; + char *pComCom = NULL; + + /* + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. + */ + info_ptr = (struct SerialInfo *) *pData; + if (info_ptr == NULL) return NOCONNECTION; + if (info_ptr->skt == 0) { + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return NOCONNECTION; + } + + info_ptr->msg_id++; /* Set up an incrementing message id */ + if (info_ptr->msg_id > 9999) info_ptr->msg_id = 1; + sprintf (info_ptr->to_host.msg_id, "%04.4d", info_ptr->msg_id); + + memcpy (info_ptr->to_host.c_pcol_lvl, RS__PROTOCOL_ID_V01B, + sizeof (info_ptr->to_host.c_pcol_lvl)); + sprintf (info_ptr->to_host.serial_port, "%04.4d", info_ptr->chan); + sprintf (info_ptr->to_host.tmo, "%04d", info_ptr->tmo); + + strncpy(info_ptr->sAsync.eot,info_ptr->pTerms,4); + memcpy (info_ptr->to_host.terms, info_ptr->pTerms, + sizeof (info_ptr->to_host.terms)); + memcpy (info_ptr->to_host.n_cmnds, "0000", + sizeof (info_ptr->to_host.n_cmnds)); + + + txt_ptr = pCommand; /* Get pntr to cmnd string */ + ncmnds = 0; + cmnd_lst_ptr = &info_ptr->to_host.cmnds[0]; + bytes_left = sizeof (info_ptr->to_host) - + OffsetOf (struct RS__MsgStruct, cmnds[0]); + + size = strlen (txt_ptr) + strlen(info_ptr->pSendTerm); + if (size > bytes_left) { + return EL734__BAD_SENDLEN; /* Too much to send */ + }else { + strcpy (cmnd_lst_ptr+4, txt_ptr); + /* make sure that the string is properly terminated */ + if((strstr(txt_ptr,info_ptr->pSendTerm) == 0) && + (strlen(txt_ptr) > 0) ) + { + strcpy(cmnd_lst_ptr+4+strlen(txt_ptr),info_ptr->pSendTerm); + c_len = strlen(txt_ptr) + strlen(info_ptr->pSendTerm); + } + else + { + c_len = strlen (txt_ptr); + } + sprintf (text, "%04.4d", c_len); + memcpy (cmnd_lst_ptr, text, 4); + cmnd_lst_ptr = cmnd_lst_ptr + c_len + 4; + ncmnds++; + bytes_left = bytes_left - size; + } + + sprintf (text, "%04.4d", ncmnds); + memcpy (info_ptr->to_host.n_cmnds, + text, sizeof (info_ptr->to_host.n_cmnds)); + + size = cmnd_lst_ptr - info_ptr->to_host.msg_id; + size = (size + 3) & (~3); /* Round up to multiple of 4 */ + sprintf (text, "%04.4d", size); + memcpy (info_ptr->to_host.msg_size, text, 4); + + status = send (info_ptr->skt, (char *) &info_ptr->to_host, size+4, 0); + if (status != (size+4)) { + if (status == 0) { + iResult = EL734__BAD_SEND; /* Server exited (probably) */ + }else if (status == -1) { + iResult = EL734__BAD_SEND_PIPE; /* Server exited (probably) */ + } + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + } + return 1; + } +/*-------------------------------------------------------------------------*/ + int SerialReceive(void **pData, char *pBuffer, int iBufLen) + { + struct SerialInfo *info_ptr; + int status, c_len, size, max_size, ncmnds; + int bytes_to_come, bytes_left; + int iResult; + char *nxt_byte_ptr; + char err_text[80]; + char text[20]; + char *txt_ptr; + char *cmnd_lst_ptr; + struct RS__RplyStruct_V01B *ptr = NULL; + long lMask = 0L; + struct timeval tmo = {0,1}; + + + /* + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. + */ + info_ptr = (struct SerialInfo *) *pData; + if (info_ptr == NULL) return NOCONNECTION; + if (info_ptr->skt == 0) { + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return NOCONNECTION; + } + + /* try with select if there is data */ +/* lMask = (1 << info_ptr->skt); + tmo.tv_usec = 10; + status = select((info_ptr->skt +1), (fd_set *)&lMask, NULL,NULL,&tmo); + if(status <= 0) + { + return SELECTFAIL; + } +*/ + + /* try read the message length to come */ + size = sizeof (info_ptr->from_host.msg_size); + status = recv (info_ptr->skt, info_ptr->from_host.msg_size, size, 0); + if (status != size) { + if(status > 0) + { + iResult = EL734__BAD_RECV; /* Server exited (probably) */ + } + else if (status == -1) { + iResult = EL734__BAD_RECV_NET; /* It's some other net problem */ + } + else + { + iResult = EL734__BAD_RECV_NET; + } + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + } + if (sscanf (info_ptr->from_host.msg_size, "%4d", &bytes_to_come) != 1) { + return EL734__BAD_NOT_BCD; /* Header not an ASCII BCD integer */ + } + + max_size = sizeof (info_ptr->from_host) - + sizeof (info_ptr->from_host.msg_size); + if (bytes_to_come > max_size) { + iResult = EL734__BAD_RECVLEN; + nxt_byte_ptr = &info_ptr->from_host.msg_size[size]; + while (bytes_to_come > 0) { /* Flush out the incoming message */ + bytes_left = bytes_to_come; + if (bytes_left > max_size) bytes_left = max_size; + status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + iResult = EL734__BAD_FLUSH; /* TCP/IP problem whilst flushing */ + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + } + bytes_to_come = bytes_to_come - status; + } + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + }else { + nxt_byte_ptr = &info_ptr->from_host.msg_size[size]; + bytes_left = bytes_to_come; + while (bytes_left > 0) { /* Read the rest of the response */ + status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + if (status == 0) { + iResult = EL734__BAD_RECV1; /* Server exited (probably) */ + }else { + iResult = EL734__BAD_RECV1_NET; /* It's some other net fault */ + } + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + return iResult; + } + bytes_left = bytes_left - status; + nxt_byte_ptr = nxt_byte_ptr + status; + } + } + /* well, we got data, make it available */ + if (sscanf (info_ptr->from_host.n_rply, "%4d", + &info_ptr->max_replies) != 1)info_ptr->max_replies = 0; + if (info_ptr->max_replies > 0) + ptr = (struct RS__RplyStruct_V01B *) info_ptr->from_host.u.rplys; + info_ptr->n_replies = 1; + if(ptr) + { + strncpy(pBuffer, ptr->rply,iBufLen); + } + else + { + return NOREPLY; + } + return True; + } +/*-------------------------------------------------------------------------*/ + int SerialReceiveWithTerm(void **pData, char *pBuffer, + int iBufLen, char *cTerm ) + { + struct SerialInfo *info_ptr; + int status, c_len, size, max_size, ncmnds; + int bytes_to_come, bytes_left; + int iResult; + char *nxt_byte_ptr; + char err_text[80]; + char text[20]; + char *txt_ptr; + char *cmnd_lst_ptr; + struct RS__RplyStruct_V01B *ptr = NULL; + long lMask = 0L; + struct timeval tmo = {0,1}; + + + /* + ** Do nothing if no connection - the connection gets + ** closed if an error is detected. + */ + info_ptr = (struct SerialInfo *) *pData; + if (info_ptr == NULL) return NOCONNECTION; + if (info_ptr->skt == 0) { + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return NOCONNECTION; + } + + /* try with select if there is data */ +/* lMask = (1 << info_ptr->skt); + tmo.tv_usec = 10; + status = select((info_ptr->skt +1), (fd_set *)&lMask, NULL,NULL,&tmo); + if(status <= 0) + { + return SELECTFAIL; + } +*/ + + /* try read the message length to come */ + size = sizeof (info_ptr->from_host.msg_size); + status = recv (info_ptr->skt, info_ptr->from_host.msg_size, size, 0); + if (status != size) { + if(status > 0) + { + iResult = EL734__BAD_RECV; /* Server exited (probably) */ + } + else if (status == -1) { + iResult = EL734__BAD_RECV_NET; /* It's some other net problem */ + } + else + { + iResult = EL734__BAD_RECV_NET; + } + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + } + if (sscanf (info_ptr->from_host.msg_size, "%4d", &bytes_to_come) != 1) { + return EL734__BAD_NOT_BCD; /* Header not an ASCII BCD integer */ + } + + max_size = sizeof (info_ptr->from_host) - + sizeof (info_ptr->from_host.msg_size); + if (bytes_to_come > max_size) { + iResult = EL734__BAD_RECVLEN; + nxt_byte_ptr = &info_ptr->from_host.msg_size[size]; + while (bytes_to_come > 0) { /* Flush out the incoming message */ + bytes_left = bytes_to_come; + if (bytes_left > max_size) bytes_left = max_size; + status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + iResult = EL734__BAD_FLUSH; /* TCP/IP problem whilst flushing */ + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + } + bytes_to_come = bytes_to_come - status; + } + memset (info_ptr->from_host.msg_size, + '0', sizeof (info_ptr->from_host.msg_size)); + return iResult; + }else { + nxt_byte_ptr = &info_ptr->from_host.msg_size[size]; + bytes_left = bytes_to_come; + while (bytes_left > 0) { /* Read the rest of the response */ + status = recv (info_ptr->skt, nxt_byte_ptr, bytes_left, 0); + if (status <= 0) { + if (status == 0) { + iResult = EL734__BAD_RECV1; /* Server exited (probably) */ + }else { + iResult = EL734__BAD_RECV1_NET; /* It's some other net fault */ + } + AsynSrv_Close (&(info_ptr->sAsync),1); + info_ptr->skt = 0; + return iResult; + } + bytes_left = bytes_left - status; + nxt_byte_ptr = nxt_byte_ptr + status; + } + } + /* well, we got data, make it available */ + if (sscanf (info_ptr->from_host.n_rply, "%4d", + &info_ptr->max_replies) != 1)info_ptr->max_replies = 0; + if (info_ptr->max_replies > 0) + ptr = (struct RS__RplyStruct_V01B *) info_ptr->from_host.u.rplys; + info_ptr->n_replies = 1; + if(ptr) + { + strncpy(pBuffer, ptr->rply,iBufLen); + *cTerm = ptr->term; + } + else + { + return NOREPLY; + } + return True; + } + +/*---------------------------------------------------------------------------*/ + int SerialError(int iErr, char *pBuffer, int iBufLen) + { + switch(iErr) + { + case -320: + strncpy(pBuffer,"Select failed to find data",iBufLen); + break; + case -300: + case NOCONNECTION: + strncpy(pBuffer,"Not connected",iBufLen); + break; + case -301: + strncpy(pBuffer,"No reply found", iBufLen); + break; + case -100: + strncpy(pBuffer,"No reply found", iBufLen); + break; + case EL734__BAD_ADR: + strncpy(pBuffer,"SERIAL__BAD_ADR",iBufLen); + break; + case EL734__BAD_BIND: + strncpy(pBuffer,"SERIAL__BAD_BIND",iBufLen); + break; + case EL734__BAD_CMD: + strncpy(pBuffer,"SERIAL__BAD_CMD",iBufLen); + break; + case EL734__BAD_CONNECT: + strncpy(pBuffer,"SERIAL__BAD_CONNECT",iBufLen); + break; + case EL734__BAD_FLUSH: + strncpy(pBuffer,"SERIAL__BAD_FLUSH",iBufLen); + break; + case EL734__BAD_HOST: + strncpy(pBuffer,"SERIAL__BAD_HOST",iBufLen); + break; + case EL734__BAD_ID: + strncpy(pBuffer,"SERIAL__BAD_ID",iBufLen); + break; + case EL734__BAD_ILLG: + strncpy(pBuffer,"SERIAL__BAD_ILLG",iBufLen); + break; + case EL734__BAD_LOC: + strncpy(pBuffer,"SERIAL__BAD_LOC",iBufLen); + break; + case EL734__BAD_MALLOC: + strncpy(pBuffer,"SERIAL__BAD_MALLOC",iBufLen); + break; + case EL734__BAD_NOT_BCD: + strncpy(pBuffer,"SERIAL__BAD_NOT_BCD",iBufLen); + break; + case EL734__BAD_OFL: + strncpy(pBuffer,"SERIAL__BAD_OFL",iBufLen); + break; + case EL734__BAD_PAR: + strncpy(pBuffer,"SERIAL__BAD_PAR",iBufLen); + break; + + case EL734__BAD_RECV: + strncpy(pBuffer,"SERIAL__BAD_RECV",iBufLen); + break; + case EL734__BAD_RECV_NET: + strncpy(pBuffer,"SERIAL__BAD_RECV_NET",iBufLen); + break; + case EL734__BAD_RECV_PIPE: + strncpy(pBuffer,"SERIAL__BAD_RECV_PIPE",iBufLen); + break; + case EL734__BAD_RECV_UNKN: + strncpy(pBuffer,"SERIAL__BAD_RECV_UNKN",iBufLen); + break; + case EL734__BAD_RECVLEN: + strncpy(pBuffer,"SERIAL__BAD_RECVLEN",iBufLen); + break; + case EL734__BAD_RECV1: + strncpy(pBuffer,"SERIAL__BAD_RECV1",iBufLen); + break; + case EL734__BAD_RECV1_NET: + strncpy(pBuffer,"SERIAL__BAD_RECV1_NET",iBufLen); + break; + case EL734__BAD_RECV1_PIPE: + strncpy(pBuffer,"SERIAL__BAD_RECV1_PIPE",iBufLen); + break; + case EL734__BAD_RNG: + strncpy(pBuffer,"SERIAL__BAD_RNG",iBufLen); + break; + case EL734__BAD_SEND: + strncpy(pBuffer,"SERIAL__BAD_SEND",iBufLen); + break; + case EL734__BAD_SEND_PIPE: + strncpy(pBuffer,"SERIAL__BAD_SEND_PIPE",iBufLen); + break; + case EL734__BAD_SEND_NET: + strncpy(pBuffer,"SERIAL__BAD_SEND_NET",iBufLen); + break; + case EL734__BAD_SEND_UNKN: + strncpy(pBuffer,"SERIAL__BAD_SEND_UNKN",iBufLen); + break; + case EL734__BAD_SENDLEN: + strncpy(pBuffer,"SERIAL__BAD_SENDLEN",iBufLen); + break; + case EL734__BAD_SOCKET: + strncpy(pBuffer,"SERIAL__BAD_SOCKET",iBufLen); + break; + case EL734__BAD_TMO: + strncpy(pBuffer,"SERIAL__BAD_TMO",iBufLen); + break; + case EL734__FORCED_CLOSED: + strncpy(pBuffer,"SERIAL__FORCED_CLOSED",iBufLen); + break; + case OPENFAILURE: + strncpy(pBuffer, + "FAILED to open connection to serial port server", iBufLen); + break; + default: + strcpy(pBuffer,"Unknown SERIAL error"); + break; + } + return 1; + } +/*---------------------------------------------------------------------------*/ + int SerialWriteRead(void **pData, char *pCommand, + char *pBuffer, int iBufLen) + { + + struct SerialInfo *pInfo = NULL; + int iRet; + time_t tTarget, tCurrent; + + pInfo = (struct SerialInfo *)*pData; + + /* write */ + iRet = SerialSend(pData,pCommand); + if(iRet != 1) + { + SerialError(iRet, pBuffer,iBufLen); + return iRet; + } + + /* check for answers for maximum time out */ + tTarget = tCurrent = time(&tCurrent); + tTarget += pInfo->tmo*100 - 90; + + while(tCurrent < tTarget) + { + pInfo->pFunc(pInfo->pData, 100); + iRet = SerialReceive(pData, pBuffer,iBufLen); + if( iRet != 1) + { + if(iRet != SELECTFAIL) + { + /* error ! */ + SerialError(iRet, pBuffer,iBufLen); + return iRet; + } + } + else + { + return 1; /* there is data read, we are done */ + } + tCurrent = time(&tCurrent); + } + return TIMEOUT; + } +/*---------------------------------------------------------------------------*/ + int SerialNoReply(void **pData, char *pCommand) + { + + struct SerialInfo *pInfo = NULL; + int iRet, iOld, i; + char pBuffer[30]; + + pInfo = (struct SerialInfo *)*pData; + + iOld = pInfo->tmo; + pInfo->tmo = 0; + + /* write */ + iRet = SerialSend(pData,pCommand); + if(iRet != 1) + { + pInfo->tmo = iOld; + return iRet; + } + + /* try some time to find a TMO */ + for(i = 0 ; i < 10; i++) + { + usleep(50); + SerialReceive(pData, pBuffer,29); + if(strcmp(pBuffer,"?TMO") == 0) + { + break; + } + } + if(i > 7) + { + printf("TMO received after %d cycles \n",i); + } + pInfo->tmo = iOld; + return 1; + } +/*-------------------------------------------------------------------------*/ + void SetSerialSleep(void **pData, SerialSleep pFun, void *pUserData) + { + struct SerialInfo *pInfo = NULL; + int iRet; + + pInfo = (struct SerialInfo *)*pData; + pInfo->pFunc = pFun; + pInfo->pData = pUserData; + + } + + + + + + + + + + + + + + + + + diff --git a/site_ansto/hardsup/serialsinq.h b/site_ansto/hardsup/serialsinq.h new file mode 100644 index 00000000..60e5dc8d --- /dev/null +++ b/site_ansto/hardsup/serialsinq.h @@ -0,0 +1,56 @@ + +#line 156 "velodorn.w" + +/*---------------------------------------------------------------------------- + S E R I A L S I N Q + + Utility functions for maintaining a connection to a RS--232 port on a + Macintosh computer running the SINQ terminal server application. + + Mark Koennecke, Juli 1997 + + copyright: see implementation file +------------------------------------------------------------------------------*/ +#ifndef SERIALSINQ +#define SERIALSINQ +#define NOREPLY -100 +#define NOCONNECTION -121 +#define SELECTFAIL -120 +#define TIMEOUT -730 +#define INTERRUPTED -132 +#define OPENFAILURE -133 + +#line 30 "velodorn.w" + + int SerialOpen(void **pData, char *pHost, int iPort, int iChannel); + int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel); + int SerialConfig(void **pData, int iTmo); + int SerialGetTmo(void **pData); + int SerialATerm(void **pData, char *pTerm); + int SerialAGetTerm(void **pData, char *pTerm, int iTermLen); + int SerialSendTerm(void **pData, char *pTerm); + int SerialGetSocket(void **pData); + int SerialClose(void **pData); + int SerialForceClose(void **pData); + + int SerialSend(void **pData, char *pCommand); + int SerialReceive(void **pData, char *pBuffer, int iBufLen); + int SerialReceiveWithTerm(void **pData, char *pBuffer, + int iBufLen,char *cTerm); + int SerialError(int iError, char *pError, int iErrLen); + int SerialWriteRead(void **pData, char *pCommand, + char *pBuffer, int iBufLen); + int SerialNoReply(void **pData, char *pCommand); + +#line 175 "velodorn.w" + +/*-------------------------- The sleeperette -----------------------------*/ + +#line 116 "velodorn.w" + + typedef int (*SerialSleep)(void *pData, int iTime); + void SetSerialSleep(void **pData, SerialSleep pFunc, void *pUserData); + +#line 177 "velodorn.w" + +#endif diff --git a/site_ansto/hardsup/sinq_defs.h b/site_ansto/hardsup/sinq_defs.h new file mode 100644 index 00000000..c437f8e7 --- /dev/null +++ b/site_ansto/hardsup/sinq_defs.h @@ -0,0 +1,108 @@ +/* +** TAS_SRC:[LIB]SINQ_DEFS.H +** +** Include file generated from SINQ_DEFS.OBJ +** +** 29-AUG-2000 09:49:31.72 +*/ + +#define SS__NORMAL 0x1 +#define SS__WASSET 0x9 +#define SS__ILLEFC 0xEC +#define SS__UNASEFC 0x234 +#define SEM_BIT 0x0 +#define SEM_PID 0x4 +#define SEM_WFLG 0x8 +#define SEM_IDNT 0xC +#define SEM_CNT0 0x1C +#define SEM_CNT1 0x20 +#define SEM_CNT2 0x24 +#define SEM_CNT3 0x28 +#define SEM_SUB_PID 0x2C +#define SEM_SIZE 0x40 +#define SEM__CAMAC_CSR 0x0 +#define SEM__CAMAC_IVG 0x40 +#define SEM__CAMAC_GPIB 0x80 +#define SEM__CAMAC_3344 0xC0 +#define MAP__CAMAC_FIELD_0 0x0 +#define MAP__CAMAC_FIELD_1 0x1 +#define MAP__CAMAC_FIELD_2 0x2 +#define MAP__CAMAC_FIELD_CSR 0x3 +#define MAP__CAMAC_SEMAPHORE 0x4 +#define MAP__DELTAT_CB 0x5 +#define MAP__DELTAT_SCALERS 0x6 +#define CAMIF__JCC 0x1 +#define CAMIF__GEC0 0x3 +#define CAMIF__CES 0x4 +#define CAMIF__BIRA 0x5 +#define CAMIF__GEC1 0x6 +#define CAMIF__GEC2 0x7 +#define CAMIF__GEC3 0x8 +#define CAMIF__CCP 0x9 +#define CAMIF__OS9 0xA +#define CAMIF__KCBD 0xB +#define CAMIF__VAN 0xC +#define CAMIF__KVCC 0xD +#define CAMIF__M_XQ 0x3 +#define CAMIF__X_Q 0x0 +#define CAMIF__X_NOQ 0x1 +#define CAMIF__NOX_Q 0x2 +#define CAMIF__NOX_NOQ 0x3 +#define CAMIF__NO_CAMIF 0x4 +#define CAMIF__TMOUT 0x8 +#define CAMIF__ILLPAR 0xC +#define CAMIF__RPTFAIL 0x14 +#define CAMIF__SEMTMO 0x18 +#define MSR__BUSY 0x1 +#define MSR__OK 0x2 +#define MSR__REF_OK 0x4 +#define MSR__STOPPED 0x8 +#define MSR__LO_LIM 0x10 +#define MSR__HI_LIM 0x20 +#define MSR__HALT 0x40 +#define MSR__RUN_FAULT 0x80 +#define MSR__RUN_FAIL 0x100 +#define MSR__POS_FAULT 0x200 +#define MSR__POS_FAIL 0x400 +#define MSR__REF_FAIL 0x800 +#define MSR__AC_FAIL 0x1000 +#define MSR__LIM_ERR 0x2000 +#define SS__HALT 0x1 +#define SS__CCW 0x2 +#define SS__STP 0x4 +#define SS__LS1 0x8 +#define SS__LS2 0x10 +#define SS__LSX 0x20 +#define EL737_STATE_UNKNOWN 0xFFFFFFFE +#define EL737_STATE_OFFLINE 0xFFFFFFFF +#define EL737_STATE_MS 0x0 +#define EL737_STATE_PTS 0x1 +#define EL737_STATE_PCS 0x2 +#define EL737_STATE_LRTS 0x5 +#define EL737_STATE_LRCS 0x6 +#define EL737_STATE_PTSP 0x9 +#define EL737_STATE_PCSP 0xA +#define EL737_STATE_LRTSP 0xD +#define EL737_STATE_LRCSP 0xE +#define SINQHM_CNCT 0x1 +#define SINQHM_CONFIG 0x2 +#define SINQHM_DECONFIG 0x3 +#define SINQHM_EXIT 0x4 +#define SINQHM_STATUS 0x5 +#define SINQHM_DBG 0x6 +#define SINQHM_CLOSE 0x101 +#define SINQHM_INH 0x102 +#define SINQHM_IOREG 0x103 +#define SINQHM_READ 0x104 +#define SINQHM_SET_TDC 0x105 +#define SINQHM_SHOW 0x106 +#define SINQHM_WRITE 0x107 +#define SINQHM_ZERO 0x108 +#define INH_SET 0x1 +#define INH_CLR 0x2 +#define INH_TST 0x3 +#define IO_SET 0x1 +#define IO_CLR 0x2 +#define IO_PULSE 0x3 +#define TT_PORT__NO_RETRY 0x1 +#define TT_PORT__NO_SIG 0x2 diff --git a/site_ansto/hardsup/sinq_prototypes.h b/site_ansto/hardsup/sinq_prototypes.h new file mode 100644 index 00000000..2be3165f --- /dev/null +++ b/site_ansto/hardsup/sinq_prototypes.h @@ -0,0 +1,674 @@ +#ifndef _sinq_prototypes_loaded_ +#define _sinq_prototypes_loaded_ +/*---------------------------------------------- SINQ_PROTOTYPES.H Ident V02T +** +** Prototype header file for entry points in SINQ.OLB +** +** Updates: +** V01A 21-Mar-1996 DM Initial version. +*/ +#ifdef VAXC +#include asynsrv_def +#include rs232c_def +#include el734_def +#include el737_def +#else +#include +#include +#include +#include +#endif +/* ---------------------------------------------------------------------*/ + int AsynSrv_ChanClose ( + struct AsynSrv__info *asyn_info); + int AsynSrv_Close ( + struct AsynSrv__info *asyn_info, + int force_flag); + int AsynSrv_Config ( + struct AsynSrv__info *asyn_info, + ...); + int AsynSrv_ConfigDflt ( + char *par_id, + ...); + void AsynSrv_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int AsynSrv_Flush ( + struct AsynSrv__info *asyn_info); + int AsynSrv_GetLenTerm ( + struct AsynSrv__info *asyn_info, + struct RS__RespStruct *rcve_buff, + char *rply, + int *len, + char *term); + char *AsynSrv_GetReply ( + struct AsynSrv__info *asyn_info, + struct RS__RespStruct *rcve_buff, + char *last_rply); + int AsynSrv_Open ( + struct AsynSrv__info *asyn_info); + int AsynSrv_OpenNew ( + struct AsynSrv__info *asyn_info); + int AsynSrv_SendCmnds ( + struct AsynSrv__info *asyn_info, + struct RS__MsgStruct *send_buff, + struct RS__RespStruct *rcve_buff, + ...); + int AsynSrv_SendCmndsBig ( + struct AsynSrv__info *asyn_info, + struct RS__MsgStruct *send_buff, + int send_buff_size, + struct RS__RespStruct *rcve_buff, + int rcve_buff_size, + ...); + int AsynSrv_Trace ( + struct AsynSrv__info *asyn_info, + int state); + int AsynSrv_Trace_Write ( + struct AsynSrv__info *asyn_info); +/* ---------------------------------------------------------------------*/ + int C_log_arr_get ( + char *name, + int arr_size, + int *value, + int indx); + int C_log_flt_get ( + char *name, + float *value, + int indx); + int C_log_int_get ( + char *name, + long int *value, + int indx); + int C_log_str_get ( + char *name, + char *value, + int val_size, + int indx); +/* ---------------------------------------------------------------------*/ + int C_str_edit ( + char *out, + char *in, + char *ctrl, + int *length); +/* ---------------------------------------------------------------------*/ + int C_tt_port_config ( + int *hndl, + int mask); + int C_tt_port_connect ( + int *hndl, + int *chan, + char *lognam, + char *pwd); + int C_tt_port_disconnect ( + int *hndl); + int C_tt_port_io ( + int *hndl, + char *rqst, + char *term, + char *answ, + int *answ_len, + int flush, + int tmo); +/* ---------------------------------------------------------------------*/ + int EL734_Close ( + void **handle, + int force_flag); + int EL734_Config ( + void **handle, + ...); + char *EL734_EncodeMSR ( + char *text, + int text_len, + int msr, + int ored_msr, + int fp_cntr, + int fr_cntr); + char *EL734_EncodeSS ( + char *text, + int text_len, + int ss); + void EL734_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int EL734_GetAirCush ( + void **handle, + int *present, + int *state); + int EL734_GetEncGearing ( + void **handle, + int *nominator, + int *denominator); + int EL734_GetId ( + void **handle, + char *id_txt, + int id_len); + int EL734_GetLimits ( + void **handle, + float *lo, + float *hi); + int EL734_GetMotorGearing ( + void **handle, + int *nominator, + int *denominator); + int EL734_GetNullPoint ( + void **handle, + int *null_pt); + int EL734_GetPosition ( + void **handle, + float *ist_posit); + int EL734_GetPrecision ( + void **handle, + int *n_dec); + int EL734_GetRefMode ( + void **handle, + int *mode); + int EL734_GetRefParam ( + void **handle, + float *param); + int EL734_GetSpeeds ( + void **handle, + int *lo, + int *hi, + int *ramp); + int EL734_GetStatus ( + void **handle, + int *msr, + int *ored_msr, + int *fp_cntr, + int *fr_cntr, + int *ss, + float *ist_posit); + int EL734_GetZeroPoint ( + void **handle, + float *zero_pt); + int EL734_MoveNoWait ( + void **handle, + float soll_posit); + int EL734_MoveWait ( + void **handle, + float soll_posit, + int *ored_msr, + int *fp_cntr, + int *fr_cntr, + float *ist_posit); + int EL734_Open ( + void **handle, + char *host, + int port, + int chan, + int motor, + char *id); + int EL734_PutOffline ( + void **handle); + int EL734_PutOnline ( + void **handle, + int echo); + int EL734_SendCmnd ( + void **handle, + char *cmnd, + char *rply, + int rply_size); + int EL734_SetAirCush ( + void **handle, + int state); + int EL734_SetErrcode ( + struct EL734info *info_ptr, + char *response, + char *cmnd); + int EL734_SetHighSpeed ( + void **handle, + int hi); + int EL734_SetLowSpeed ( + void **handle, + int lo); + int EL734_SetRamp ( + void **handle, + int ramp); + int EL734_Stop ( + void **handle); + int EL734_WaitIdle ( + void **handle, + int *ored_msr, + int *fp_cntr, + int *fr_cntr, + float *ist_posit); + void EL734_ZeroStatus ( + void **handle); +/* ---------------------------------------------------------------------*/ + int EL737_Close ( + void **handle, + int force_flag); + int EL737_Config ( + void **handle, + ...); + int EL737_Continue ( + void **handle, + int *status); + int EL737_EnableThresh ( + void **handle, + int indx); + void EL737_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int EL737_GetMonIntegTime ( + void **handle, + int indx, + float *mon_integ_time); + int EL737_GetRateIntegTime ( + void **handle, + float *rate_integ_time); + void *EL737_GetReply ( + void **handle, + void *last_rply); + int EL737_GetStatus ( + void **handle, + int *c1, + int *c2, + int *c3, + int *c4, + float *timer, + int *rs); + int EL737_GetStatusExtra ( + void **handle, + int *c5, + int *c6, + int *c7, + int *c8); + int EL737_GetThresh ( + void **handle, + int *indx, + float *val); + int EL737_Open ( + void **handle, + char *host, + int port, + int chan); + int EL737_Pause ( + void **handle, + int *status); + int EL737_SendCmnd ( + void **handle, + char *cmnd, + char *rply, + int rply_size); + int EL737_SetErrcode ( + struct EL737info *info_ptr, + char *response, + char *cmnd); + int EL737_SetThresh ( + void **handle, + int indx, + float val); + int EL737_StartCnt ( + void **handle, + int preset_count, + int *status); + int EL737_StartTime ( + void **handle, + float preset_time, + int *status); + int EL737_Stop ( + void **handle, + int *c1, + int *c2, + int *c3, + int *c4, + float *timer, + int *status); + int EL737_StopFast ( + void **handle); + int EL737_WaitIdle ( + void **handle, + int *c1, + int *c2, + int *c3, + int *c4, + float *timer); +/* ---------------------------------------------------------------------*/ + int EL755_Close ( + void **handle, + int force_flag); + int EL755_Config ( + void **handle, + ...); + void EL755_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int EL755_ErrorLog ( + char *routine_name, + char *text); + int EL755_GetConstant ( + void **handle, + float *value); + int EL755_GetCurrents ( + void **handle, + float *soll, + float *ist); + int EL755_GetId ( + void **handle, + char *id_txt, + int id_len); + int EL755_GetLimit ( + void **handle, + float *value); + int EL755_GetRamp ( + void **handle, + float *value); + int EL755_GetTimeConstant ( + void **handle, + float *value); + int EL755_GetVoltageRange ( + void **handle, + float *value); + int EL755_Open ( + void **handle, + char *host, + int port, + int chan, + int indx); + int EL755_PutOffline ( + void **handle); + int EL755_PutOnline ( + void **handle, + int echo); + int EL755_SendTillSameStr ( + void **handle, + char *cmnd, + char *rply, + int rply_len); + int EL755_SendTillSameVal ( + void **handle, + char *cmnd, + float *val); + int EL755_SendTillTwoVals ( + void **handle, + char *cmnd, + float *val0, + float *val1); + int EL755_SetConstant ( + void **handle, + float value); + int EL755_SetCurrent ( + void **handle, + float soll); + int EL755_SetLimit ( + void **handle, + float value); + int EL755_SetRamp ( + void **handle, + float value); + int EL755_SetTimeConstant ( + void **handle, + float value); + int EL755_SetVoltageRange ( + void **handle, + float value); +/* ---------------------------------------------------------------------*/ + int Fluke_Close ( + void **handle, + int force_flag); + int Fluke_Config ( + void **handle, + ...); + void Fluke_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int Fluke_ErrorLog ( + char *routine_name, + char *text); + int Fluke_Open ( + void **handle, + char *host, + int port, + int chan); + int Fluke_Read ( + void **handle, + float *ist); + int Fluke_SendTillSame ( + void **handle, + char *cmnd, + char *rply, + int rply_len); + int Fluke_SendTillSameVal ( + void **handle, + char *cmnd, + float *val); +/* ---------------------------------------------------------------------*/ + int ITC_Close ( + void **handle, + int force_flag); + int ITC_Config ( + void **handle, + ...); + int ITC_Dump_RAM ( + void **handle, + int buff_size, + char *buff, + int *dump_len, + int *n_diffs); + void ITC_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int ITC_GetConfig ( + void **handle, + ...); + int ITC_Load_RAM ( + void **handle, + int load_len, + char *buff); + int ITC_Load_Table ( + void **handle, + char *buff); + int ITC_Open ( + void **handle, + char *host, + int port, + int chan); + int ITC_Read_ITC_Sensor ( + void **handle, + int sensor, + float factor, + float *value); + int ITC_Read_LTC11_Sensor ( + void **handle, + int sensor, + float *value); + int ITC_Read_LTC11_SetPt ( + void **handle, + float *value); + int ITC_ReadAuxTemp ( + void **handle, + float *value); + int ITC_ReadControlTemp ( + void **handle, + float *value); + int ITC_ReadHeaterOp ( + void **handle, + float *op_level, + float *op_percent); + int ITC_ReadId ( + void **handle, + char *id_txt, + int id_txt_len, + int *id_len); + int ITC_ReadPID ( + void **handle, + float *p, + float *i, + float *d); + int ITC_ReadSampleTemp ( + void **handle, + float *s_temp); + int ITC_ReadSetPoint ( + void **handle, + float *sp_temp); + int ITC_ReadStatus ( + void **handle, + char *status_txt, + int status_txt_len, + int *status_len, + int *auto_state, + int *remote_state); + int ITC_SendTillAckOk ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd); + int ITC_SendTillSame ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd, + char *rply, + int rply_len); + int ITC_SendTillSameLen ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd, + char *rply, + int rply_len); + int ITC_SendTillSameLenAckOK ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd, + char *rply, + int rply_len); + int ITC_SetControlTemp ( + void **handle, + float s_temp); + int ITC_SetHeatLevel ( + void **handle, + float heat_percent); + int ITC_ErrorLog ( + char *routine_name, + char *text); +/* ---------------------------------------------------------------------*/ + int SPS_Close ( + void **handle, + int force_flag); + int SPS_Config ( + void **handle, + ...); + void SPS_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + int SPS_ErrorLog ( + char *routine_name, + char *text); + int SPS_GetStatus ( + void **handle, + unsigned char *status_vals, + int n_status_vals, + int *adc_vals, + int n_adc_vals); + int SPS_Open ( + void **handle, + char *host, + int port, + int chan); + int SPS_SendTillSame ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd, + char *rply, + int rply_len); + int SPS_SendTillSameLen ( + void **handle, + struct RS__MsgStruct *to_host, + struct RS__RespStruct *from_host, + char *cmnd, + char *rply, + int rply_len); +/* ---------------------------------------------------------------------*/ + int VelSel_Close ( + void **handle, + int force_flag); + void VelSel_Config ( + void **handle, + int msec_tmo, + char *eot_str); + void VelSel_ErrInfo ( + char **entry_txt, + int *errcode, + int *my_errno, + int *vaxc_errno); + void *VelSel_GetReply ( + void **handle, + void *last_rply); + int VelSel_GetStatus ( + void **handle, + char *status_str, + int status_str_len); + int VelSel_Open ( + void **handle, + char *host, + int port, + int chan); + int VelSel_SendCmnd ( + void **handle, + char *cmnd, + char *rply, + int rply_size); +/* ---------------------------------------------------------------------*/ + void FailInet ( + char *text); + void GetErrno ( + int *his_errno, + int *his_vaxc_errno); + int MakeCharPrintable ( + char *out, + int out_size, + char in); + char *MakePrint ( + char *text); + char *MakePrintable ( + char *out, + int out_size, + char *in); + void *Map_to_ACS (); + char *StrEdit ( + char *out, + char *in, + char *ctrl, + int *ln); + char *StrJoin ( + char *result, + int result_size, + char *str_a, + char *str_b); + int StrMatch ( + char *str_a, + char *str_b, + int min_len); + int Get_TASMAD_Info ( + char *file_name, + int *nItems, + ...); + int Get_TASMAD_Info_Filename ( + char *file_name, + char *buf, + int *bufSize); + int Update_TASMAD_Info ( + char *file_name, + int *nItems, + ...); +/*--------------------------------------------- End of SINQ_PROTOTYPES.H --*/ +#endif /* _sinq_prototypes_loaded_ */ diff --git a/site_ansto/hardsup/sinqhm.h b/site_ansto/hardsup/sinqhm.h new file mode 100644 index 00000000..ad692a16 --- /dev/null +++ b/site_ansto/hardsup/sinqhm.h @@ -0,0 +1,107 @@ + +#line 363 "sinqhm.w" + +/*--------------------------------------------------------------------------- + S I N Q H M + Some utility functions for interfacing to the SINQ histogram memory + server. + + David Maden, Mark Koennecke, April 1997 + + copyright: see implementation file. +-----------------------------------------------------------------------------*/ +#ifndef SINQHMUTILITY +#define SINQHMUTILITY +#include "sinqhm_def.h" + + typedef struct __SINQHM *pSINQHM; +/*------------------------------ Error codes -----------------------------*/ + +#line 341 "sinqhm.w" + +#define HMCOMPUTER_NOT_FOUND -2 +#define SOCKET_ERROR -3 +#define BIND_ERROR -4 +#define CONNECT_ERROR -5 +#define RECEIVE_ERROR -6 +#define INSUFFICIENT_DATA -7 +#define BYTE_ORDER_CHAOS -8 +#define HIST_BAD_CREATE -9 +#define HIST_BAD_STATE -10 +#define HIST_BAD_VALUE -11 +#define HIST_BAD_RECV -12 +#define HIST_BAD_ALLOC -13 +#define HIST_BAD_CODE -14 +#define SEND_ERROR -15 +#define CLOSE_ERROR -16 +#define INVALID_HARSH -17 +#define SOFTWARE_ERROR -18 +#define DAQ_INHIBIT -19 +#define DAQ_NOTSTOPPED -20 + +#line 379 "sinqhm.w" + + +/*------------------------------ Prototypes ------------------------------*/ + +#line 118 "sinqhm.w" + + pSINQHM CreateSINQHM(char *pHMComputer, int iMasterPort); + pSINQHM CopySINQHM(pSINQHM self); + void DeleteSINQHM(pSINQHM self); + void SINQHMSetPar(pSINQHM self, int iRank, int iLength, int iBinWidth); + void SINQHMSetPSD(pSINQHM self, int xSize, int xOff, int xFac, + int ySize, int yOff, int yFac); + +#line 142 "sinqhm.w" + + int SINQHMError2Text(int iErr, char *pBuffer, int iBufLen); + +#line 155 "sinqhm.w" + + int SINQHMConfigure(pSINQHM self, int iMode, int iRank, int iLength, + int iBinWidth, int iLowBin, int iCompress); + int SINQHMConfigurePSD(pSINQHM self, int iMode, + int xSize, int xOff, int xFac, + int ySize, int yOff, int yFac, + int iBinWidth, + float *iEdges, int iEdgeLength); + + int SINQHMDeconfigure(pSINQHM self, int iHarsh); + int SINQHMGetStatus(pSINQHM self,int *iMode, int *iDaq, + int *iRank, int *iBinWidth, + int *iLength, int *iClients); + int SINQHMDebug(pSINQHM self, int iLevel); + int SINQHMKill(pSINQHM self); + + +#line 261 "sinqhm.w" + + int SINQHMOpenDAQ(pSINQHM self); + int SINQHMCloseDAQ(pSINQHM self); + + int SINQHMStartDAQ(pSINQHM self); + int SINQHMStopDAQ(pSINQHM self); + int SINQHMInhibitDAQ(pSINQHM self); + int SINQHMContinueDAQ(pSINQHM self); + + int SINQHMWrite(pSINQHM self, int iNum, int iStart, int iEnd, + void *pData); + long SINQHMSize(pSINQHM self, int iNum, int iStart, int iEnd); + int SINQHMRead(pSINQHM self, int iNum, int iStart, int iEnd, + void *pData, int iDataLen); + int SINQHMProject(pSINQHM self, int code, int xStart, int nx, + int yStart, int ny, void *pData, int iDataLen); + int SINQHMZero(pSINQHM self, int iNum, int iStart, int iEnd); + +#line 382 "sinqhm.w" + + +#line 232 "sinqhm.w" + + int SINQHMDefineBank(pSINQHM self, int iBankNumber, int iStart, int iEnd, + float *iEdges, int iEdgeLength); + +#line 383 "sinqhm.w" + +#endif diff --git a/site_ansto/hardsup/sinqhm_def.h b/site_ansto/hardsup/sinqhm_def.h new file mode 100644 index 00000000..6b17b2ed --- /dev/null +++ b/site_ansto/hardsup/sinqhm_def.h @@ -0,0 +1,483 @@ +/*=================================================== [...SinqHM]SinqHM_def.h +** +** Definition Include file for SinqHM_SRV and its clients. +** +**------------------------------------------------------------------------------ +*/ +#define SINQHM_DEF_ID "V03C" + +#ifdef __alpha +#ifndef __vms +#pragma pack 1 +#endif +#endif +/*------------------------------------------------------------------------------ +*/ +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif +/*------------------------------------------------------------------------------ +** Define some defaults. +*/ +#define PORT_BASE 2400 /* The Internet Port for Server Requests */ +#define MAX_CLIENTS 8 /* The maximum number of active clients */ +#define MAX_TOF_CNTR 1024 /* The maximum number of individual counters .. + ** which can be handled in TOF mode */ +#define MAX_PSD_CNTR 1048576 /* maximum number of PSD elements */ +#define MAX_TOF_NBINS 32768 /* The maximum number of bins in a TOF histog */ +#define MAX_TOF_EDGE 16 /* The maximum number of TOF edge arrays */ +#define VMIO_BASE_ADDR 0x1900 /* VME address of a (possible) VMIO10 module */ +#define IDENT_MSGE_LEN 256 /* Length of Ident info for SQHM_IDENT */ + +#define uchar unsigned char +#define usint unsigned short int +#define uint unsigned int +/*------------------------------------------------------------------------------ +** Define some status values (similar to VAXeln). +*/ +#define KER__SUCCESS 1 +#define KER__BAD_CREATE -2 +#define KER__BAD_STATE -4 +#define KER__BAD_VALUE -6 +#define KER__EXIT_SIGNAL -10 +#define KER__BAD_RECV -14 +#define KER__BAD_ALLOC -16 + +#ifndef True +#define True 1 +#endif + +#ifndef False +#define False 0 +#endif + +#ifndef NIL +#define NIL '\0' +#endif +/*------------------------------------------------------------------------------ +** Define command verbs to SinqHM. +*/ +#define SQHM_CNCT 0x01 +#define SQHM_CLOSE 0x02 +#define SQHM_CONFIG 0x03 +#define SQHM_DAQ 0x04 +#define SQHM_DBG 0x05 +#define SQHM_DECONFIG 0x06 +#define SQHM_EXIT 0x07 +#define SQHM_IDENT 0x0e +#define SQHM_PROJECT 0x0d +#define SQHM_READ 0x08 +#define SQHM_SELECT 0x09 +#define SQHM_STATUS 0x0a +#define SQHM_WRITE 0x0b +#define SQHM_ZERO 0x0c + /* + ** Define the various operation modes + */ +#define SQHM__TRANS 0x1000 /* Transparent mode */ +#define SQHM__HM_DIG 0x2000 /* Hist mode (with digitised read-out) */ +#define SQHM__TOF 0x3000 /* Time-of-Flight mode */ +#define SQHM__HM_PSD 0x4000 /* Hist mode (with Pos-sens-detect read-out) */ +#define SQHM__HRPT 0x5000 /* Hist mode for HRPT */ + /* + ** Define the various sub-mode bits of the operation modes + */ +#define SQHM__SUB_MODE_MSK 0xff /* Mask for extracting "sub-mode" bits */ +#define SQHM__DEBUG 0x01 /* Debug flag - FILLER will suspend itself .. + ** .. after starting to allow debugging */ +#define SQHM__UD 0x02 /* Use Up/Down bit information */ + +#define SQHM__BO_MSK 0x18 /* Mask for extracting "bin-overflow" bits */ +#define SQHM__BO_IGN 0x00 /* Ignore bin-overflows (bin-contents wrap) */ +#define SQHM__BO_SMAX 0x08 /* On bin-overflow, stop at maximum */ +#define SQHM__BO_CNT 0x10 /* Keep counts of overflow bins */ + +#define SQHM__STROBO 0x20 /* Use strobo-bit information */ +#define SQHM__REFLECT 0x40 /* Reflect histograms */ +#define SQHM__NO_STAT 0x80 /* Suppress status info from "Filler" */ + /* + ** ---------------------------------------------------------- + ** SQHM_DAQ sub-function codes + */ +#define DAQ__EXIT 0xffffffff +#define DAQ__CLR 0x01 +#define DAQ__GO 0x02 +#define DAQ__INH 0x03 +#define DAQ__STOP 0x04 +#define DAQ__TST 0x05 + /* + ** ---------------------------------------------------------- + ** SQHM_PROJECT sub-codes + */ +#define PROJECT__ON_Y 0x0001 /* Project onto y-axis */ +#define PROJECT__1_DIM 0x0002 /* Make projection of a 1-dim histogram */ +#define PROJECT__COLL 0x0003 /* collapse PSD on one time channel */ +#define PROJECT__SAMPLE 0x0004 /* sum a rectangular part of the PSD + detector in time + */ + /* + ** ---------------------------------------------------------- + ** Definition of bits in of TOF edge-array + */ +#define FLAG__VAR_BIN 0x01 /* Bin span of histogram is variable */ + /* + ** ---------------------------------------------------------- + ** Definition of bits in of SQHM_STATUS response + */ +#define STATUS_FLAGS__PF 0x8000 /* PF - Power Fail */ +#define STATUS_FLAGS__SWC 0x4000 /* SWC - Status Word Changed */ +#define STATUS_FLAGS__NRL 0x2000 /* NRL - Neutron Rate Low */ +#define STATUS_FLAGS__DAQ 0x1000 /* DAQ on -- set if Hdr Mask Bits are + ** correct so that data acq is active */ +#define STATUS_FLAGS__SYNC3 0x0800 /* Ext Synch Bit #3 */ +#define STATUS_FLAGS__SYNC2 0x0400 /* Ext Synch Bit #2 */ +#define STATUS_FLAGS__SYNC1 0x0200 /* Ext Synch Bit #1 */ +#define STATUS_FLAGS__SYNC0 0x0100 /* Ext Synch Bit #0 */ +#define STATUS_FLAGS__UD 0x0080 /* UD - Up/Down */ +#define STATUS_FLAGS__GU 0x0040 /* GU - Gummi (i.e. Strobo) */ + /* + ** ---------------------------------------------------------- + */ +#define N_HISTS_MAX 64 /* Maximum number of histograms supported */ +#define N_BINS_MAX 0x00ffff /* Maximum histogram bin number permitted */ +#define N_TOTAL_BYTES 0x400000 /* Maximum total bytes of histogram */ +/* +**------------------------------------------------------------------------------ +** Definitions of Filler states in HRPT mode +*/ +#define HRPT__SRCH_FRAME 1 +#define HRPT__READ_FRAME 2 +/* +**------------------------------------------------------------------------------ +** Definitions for the LWL Datagrams +*/ +#define LWL_HDR_TYPE_MASK (0x1f000000) /* Mask for extracting main dgrm .. + ** .. hdr command-type bits */ +#define LWL_HDR_PF_MASK (0x80000000) /* Mask for extr Power Fail bit */ +#define LWL_HDR_SWC_MASK (0x40000000) /* Mask for extr Status Word Chng bit */ +#define LWL_HDR_NRL_MASK (0x20000000) /* Mask for extr Neutron Rate Low bit */ +#define LWL_HDR_SYNC3_MASK (0x00800000) /* Mask for one of ext synch bits */ +#define LWL_HDR_SYNC2_MASK (0x00400000) /* Mask for one of ext synch bits */ +#define LWL_HDR_SYNC1_MASK (0x00200000) /* Mask for one of ext synch bits */ +#define LWL_HDR_SYNC0_MASK (0x00100000) /* Mask for one of ext synch bits */ +#define LWL_HDR_UD_MASK LWL_HDR_SYNC1_MASK /* Mask for Up/Down bit */ +#define LWL_HDR_GU_MASK LWL_HDR_SYNC0_MASK /* Mask for GU bit */ +#define LWL_HDR_BA_MASK (0x00f00000) /* Mask for TSI Binning Addr */ +#define LWL_HDR_TS_MASK (0x000fffff) /* Mask for TSI Time Stamp */ + +#define LWL_FIFO_EMPTY (0x1e000000) /* FIFO Empty */ + +#define LWL_TSI_TR (0x1f000000) /* Time-Status-Info Transp-Mode */ +#define LWL_TSI_HM_NC (0x1f000000) /* Time-Status-Info Hist-Mode+No-Coinc */ +#define LWL_TSI_HM_C (0x0e000000) /* Time-Status-Info Hist-Mode+Coinc */ +#define LWL_TSI_TOF (0x1f000000) /* Time-Status-Info TOF-Mode */ +#define LWL_TSI_SM_NC (0x1f000000) /* Time-Status-Info Strobo-Mode+No-Coin */ +#define LWL_TSI_SM_C (0x0e000000) /* Time-Status-Info Strobo-Mode+Coinc */ +#define LWL_TSI_DT_MSK (0x000fffff) /* Mask for Dead-Time in TSI */ +#define LWL_TSI_DTS_MSK (0x000fffff) /* Mask for Delay-Time-to-Start in TSI */ + +#define LWL_TR_C1 (0x00000001) /* Transp. Mode Chan 1 */ +#define LWL_TR_C2 (0x00000002) /* Transp. Mode Chan 2 */ +#define LWL_TR_C3 (0x00000003) /* Transp. Mode Chan 3 */ +#define LWL_TR_C4 (0x00000004) /* Transp. Mode Chan 4 */ +#define LWL_TR_C5 (0x00000005) /* Transp. Mode Chan 5 */ +#define LWL_TR_C6 (0x00000006) /* Transp. Mode Chan 6 */ +#define LWL_TR_C7 (0x00000007) /* Transp. Mode Chan 7 */ +#define LWL_TR_C8 (0x00000008) /* Transp. Mode Chan 8 */ +#define LWL_TR_C9 (0x00000009) /* Transp. Mode Chan 9 */ + +#define LWL_HM_NC (0x10000000) /* Hist-Mode/No-Coinc 0 chan dgrm hdr */ +#define LWL_HM_NC_C1 (0x11000000) /* Hist-Mode/No-Coinc 1 chan dgrm hdr */ +#define LWL_HM_NC_C2 (0x12000000) /* Hist-Mode/No-Coinc 2 chan dgrm hdr */ +#define LWL_HM_NC_C3 (0x13000000) /* Hist-Mode/No-Coinc 3 chan dgrm hdr */ +#define LWL_HM_NC_C4 (0x14000000) /* Hist-Mode/No-Coinc 4 chan dgrm hdr */ +#define LWL_HM_NC_C5 (0x15000000) /* Hist-Mode/No-Coinc 5 chan dgrm hdr */ +#define LWL_HM_NC_C6 (0x16000000) /* Hist-Mode/No-Coinc 6 chan dgrm hdr */ +#define LWL_HM_NC_C7 (0x17000000) /* Hist-Mode/No-Coinc 7 chan dgrm hdr */ +#define LWL_HM_NC_C8 (0x18000000) /* Hist-Mode/No-Coinc 8 chan dgrm hdr */ +#define LWL_HM_NC_C9 (0x19000000) /* Hist-Mode/No-Coinc 9 chan dgrm hdr */ + +#define LWL_HM_CO (0x10000000) /* Hist-Mode+Coinc 0 chan dgrm hdr */ +#define LWL_HM_CO_C2 (0x12000000) /* Hist-Mode+Coinc 2 chan dgrm hdr */ +#define LWL_HM_CO_C3 (0x13000000) /* Hist-Mode+Coinc 3 chan dgrm hdr */ +#define LWL_HM_CO_C4 (0x14000000) /* Hist-Mode+Coinc 4 chan dgrm hdr */ +#define LWL_HM_CO_C5 (0x15000000) /* Hist-Mode+Coinc 5 chan dgrm hdr */ +#define LWL_HM_CO_C6 (0x16000000) /* Hist-Mode+Coinc 6 chan dgrm hdr */ +#define LWL_HM_CO_C7 (0x17000000) /* Hist-Mode+Coinc 7 chan dgrm hdr */ +#define LWL_HM_CO_C8 (0x18000000) /* Hist-Mode+Coinc 8 chan dgrm hdr */ +#define LWL_HM_CO_C9 (0x19000000) /* Hist-Mode+Coinc 9 chan dgrm hdr */ + +#define LWL_TOF_C1 (0x01000000) /* TOF-Mode 1 chan dgrm hdr */ +#define LWL_TOF_C2 (0x02000000) /* TOF-Mode 2 chan dgrm hdr */ +#define LWL_TOF_C3 (0x03000000) /* TOF-Mode 3 chan dgrm hdr */ +#define LWL_TOF_C4 (0x04000000) /* TOF-Mode 4 chan dgrm hdr */ +#define LWL_TOF_C5 (0x05000000) /* TOF-Mode 5 chan dgrm hdr */ +#define LWL_TOF_C6 (0x06000000) /* TOF-Mode 6 chan dgrm hdr */ +#define LWL_TOF_C7 (0x07000000) /* TOF-Mode 7 chan dgrm hdr */ +#define LWL_TOF_C8 (0x08000000) /* TOF-Mode 8 chan dgrm hdr */ +#define LWL_TOF_C9 (0x09000000) /* TOF-Mode 9 chan dgrm hdr */ + +#define LWL_PSD_TSI 0x0E000000 /* PSD-Mode TSI datagram */ +#define LWL_PSD_DATA 0x12000000 /* PSD-mode data datagram */ +#define LWL_PSD_PWF 0x20000000 /* PSD-mode Power Fail bit */ +#define LWL_PSD_TIME 0x000fffff /* PSD-mode time stamp extraction + mask */ +#define LWL_PSD_FLASH_MASK 0x00ff /* mask for flash count */ +#define LWL_PSD_XORF 0x2000 /* mask for TDC-XORF bit */ +#define LWL_PSD_CONF 0x0100 /* mask for TDC-CONF flag */ + +#define LWL_SM_NC (0x10000000) /* Strobo-Mode/No-Coinc 0 chan dgrm hdr */ +#define LWL_SM_NC_C1 (0x11000000) /* Strobo-Mode/No-Coinc 1 chan dgrm hdr */ +#define LWL_SM_NC_C2 (0x12000000) /* Strobo-Mode/No-Coinc 2 chan dgrm hdr */ +#define LWL_SM_NC_C3 (0x13000000) /* Strobo-Mode/No-Coinc 3 chan dgrm hdr */ +#define LWL_SM_NC_C4 (0x14000000) /* Strobo-Mode/No-Coinc 4 chan dgrm hdr */ +#define LWL_SM_NC_C5 (0x15000000) /* Strobo-Mode/No-Coinc 5 chan dgrm hdr */ +#define LWL_SM_NC_C6 (0x16000000) /* Strobo-Mode/No-Coinc 6 chan dgrm hdr */ +#define LWL_SM_NC_C7 (0x17000000) /* Strobo-Mode/No-Coinc 7 chan dgrm hdr */ +#define LWL_SM_NC_C8 (0x18000000) /* Strobo-Mode/No-Coinc 8 chan dgrm hdr */ +#define LWL_SM_NC_C9 (0x19000000) /* Strobo-Mode/No-Coinc 9 chan dgrm hdr */ + +#define LWL_SM_CO (0x10000000) /* Strobo-Mode + Coinc 0 chan dgrm hdr */ +#define LWL_SM_CO_C1 (0x11000000) /* Strobo-Mode + Coinc 1 chan dgrm hdr */ +#define LWL_SM_CO_C2 (0x12000000) /* Strobo-Mode + Coinc 2 chan dgrm hdr */ +#define LWL_SM_CO_C3 (0x13000000) /* Strobo-Mode + Coinc 3 chan dgrm hdr */ +#define LWL_SM_CO_C4 (0x14000000) /* Strobo-Mode + Coinc 4 chan dgrm hdr */ +#define LWL_SM_CO_C5 (0x15000000) /* Strobo-Mode + Coinc 5 chan dgrm hdr */ +#define LWL_SM_CO_C6 (0x16000000) /* Strobo-Mode + Coinc 6 chan dgrm hdr */ +#define LWL_SM_CO_C7 (0x17000000) /* Strobo-Mode + Coinc 7 chan dgrm hdr */ +#define LWL_SM_CO_C8 (0x18000000) /* Strobo-Mode + Coinc 8 chan dgrm hdr */ +#define LWL_SM_CO_C9 (0x19000000) /* Strobo-Mode + Coinc 9 chan dgrm hdr */ + +#define LWL_TSI_MODE_MASK (0x000e) /* Mask for mode in Time Status Info */ +#define LWL_TSI_MODE_TR (0x0000) /* TSI Transparent-Mode */ +#define LWL_TSI_MODE_HM (0x0002) /* TSI Hist-Mode */ +#define LWL_TSI_MODE_TOF (0x0004) /* TSI TOF-Mode */ +#define LWL_TSI_MODE_SM1 (0x0006) /* TSI Strobo-Mode 1 - time-stamp coded */ +#define LWL_TSI_MODE_TR_UD (0x0008) /* TSI Transparent-Mode Up-Down */ +#define LWL_TSI_MODE_HM_UD (0x000a) /* TSI Hist-Mode Up-Down */ +#define LWL_TSI_MODE_TOF_UD (0x000c) /* TSI TOF-Mode Up-Down */ +#define LWL_TSI_MODE_SM2 (0x000e) /* TSI Strobo-Mode 2 - h/w coded */ +/* +**------------------------------------------------------------------------------ +** Define structure of a TOF histogram data item. +*/ + struct tof_histog { + int cntr_nmbr; /* Counter number */ + uint lo_edge; /* Low edge of first bin (20-bit value) */ + uint hi_edge; /* Top edge of last bin (20-bit value) */ + usint flag; /* Bit mask giving info on histog -- may be + ** used to help optimise the code */ + usint bytes_per_bin; /* Number of bytes in each histogram bin */ + uint n_bins; /* Number of bins in histogram */ + uint cnt_early_up; /* Count of early events (pol'n up) */ + uint cnt_late_up; /* Count of late events (pol'n up) */ + uint cnt_early_down; /* Count of early events (pol'n down) */ + uint cnt_late_down; /* Count of late events (pol'n down) */ + uint *bin_edge; /* Pointer to array of bin edges */ + union { /* Pointer to histogram array */ + uchar *b_bin_data; /* .. pointer if it's 8-bit bins */ + usint *w_bin_data; /* .. pointer if it's 16-bit bins */ + uint *l_bin_data; /* .. pointer if it's 32-bit bins */ + } u; + }; + +/* Define a TOF 'edge-info' structure. This structure is created +** as a result of a TOF 'edge-array' in a SQHM__TOF config cmnd. +*/ + struct tof_edge_info { + uint n_bins; /* Number of bins in histogram */ + uint flag; /* Flag bits defining type of histo */ + uint bin_span; /* Time spanned by a histogram bin (20-bit + ** value) if bin width is constant. Otherwise + ** it is zero. */ + uint hi_edge; /* Top edge of last bin (20-bit value) */ + uint edges[2]; /* Array of edge data (20-bit values). There + ** are actually (n_bins+1) items in the array + ** and give the bottom edges of the bin */ + }; + +/* Define structure of a TOF 'edge-array' in SQHM__TOF config cmnd +*/ + struct tof_edge_arr { + uint n_bins; /* Number of bins in histogram */ + uint flag; /* Flag (0/1) for fixed/variable bin size */ + uint *edges; /* Array of bottom edges (20-bit values) */ + }; + +/* Define structure of a TOF 'bank' in SQHM__TOF config command +*/ + struct tof_bank { + usint first; /* Number of first counter in bank */ + usint n_cntrs; /* Number of counters in bank */ + usint edge_indx; /* Index of edge array */ + usint bytes_per_bin; /* Number of bytes per bin */ + }; +/* +**------------------------------------------------------------------------------ +** Define command structure. +*/ + struct req_buff_struct { /* For messages to SinqHM */ + uint bigend; + uint cmnd; + union { + char filler[56]; + + struct {uint max_pkt, + strt_mode;} cnct; + + struct {uint mode; + union { + struct { + uint n_buffs; + uint n_bytes; + } trans; + struct { + uint n_hists; + uint lo_bin; + uint num_bins; + uint bytes_per_bin; + uint compress; + } hm_dig; + struct { + uint n_extra_bytes; + usint n_edges; + usint n_banks; + uint preset_delay; + struct tof_edge_arr edge_0; + struct tof_bank bank_0; + } tof; + struct { + uint n_extra_bytes; + usint n_edges; + usint n_banks; + uint preset_delay; + usint xFactor; + usint yFactor; + usint xOffset; + usint yOffset; + usint xSize; + usint ySize; + struct tof_edge_arr edge_0; + struct tof_bank bank_0; + } psd; + } u; + } cnfg; + + struct {uint mask;} dbg; + + struct {uint sub_code;} decnfg; + + struct {uint sub_cmnd;} daq; + + struct {uint sub_code, + x_lo, + nx, + y_lo, + ny, + xdim, + nhist;} project; + + struct {uint hist_no, + first_bin, + n_bins;} read; + + struct {uint hist_no;} select; + + struct {uint hist_no, + first_bin, + n_bins, + bytes_per_bin;} write; + + struct {uint hist_no, + first_bin, + n_bins;} zero; + } u; + }; +/* +**------------------------------------------------------------------------------ +** Define status response structure. +*/ + struct rply_buff_struct { /* For messages from SinqHM */ + uint bigend; + uint status; + uint sub_status; + union { + char message[52]; + + struct {uint port; + uint pkt_size; + uint hm_mode; + uint n_hists; + uint num_bins; + uint bytes_per_bin; + uint curr_hist; + uint max_block; + uint total_bytes; + uint lo_cntr; + uint lo_bin; + uint compress; + uint up_time;} cnct; + + struct {usint daq_now; + usint daq_was; + usint filler_mask; + usint server_mask;} daq; + + struct {uint n_extra_bytes; + uint up_time; + usint offset_vxWorks_ident; + usint offset_vxWorks_date; + usint offset_instr; + usint offset_def_ident; + usint offset_sinqhm_main_ident; + usint offset_sinqhm_main_date; + usint offset_sinqhm_server_ident; + usint offset_sinqhm_server_date; + usint offset_sinqhm_filler_ident; + usint offset_sinqhm_filler_date; + usint offset_sinqhm_routines_ident; + usint offset_sinqhm_routines_date;} ident; + + struct {uint n_bins; + uint bytes_per_bin; + uint cnts_lo; + uint cnts_hi;} project; + + struct {uint first_bin; + uint n_bins; + uint bytes_per_bin; + uint cnts_lo; + uint cnts_hi;} read; + + struct {uint cfg_state; + usint n_hists, curr_hist; + uint num_bins; + uint max_n_hists; + uint max_num_bins; + uchar max_srvrs, act_srvrs, bytes_per_bin, compress; + usint daq_now, filler_mask; + uint max_block; + usint tsi_status, flags; + union { + uint dead_time; + uint dts; + uint both; + } dt_or_dts; + uint num_bad_events; + uint up_time;} status; + } u; + }; +/* +**------------------------------------------------------------------------------ +** Define structure of message to SinqHM-filler. +*/ + struct msg_to_filler_struct { /* For messages to SinqHM-filler */ + union { + char message[32]; /* Ensure buffer is 32 bytes total */ + struct { + uint cmnd; + uint index; + usint new_mask;} uu; + } u; + }; +/*======================================================= End of SinqHM_def.h */ diff --git a/site_ansto/hardsup/stredit.c b/site_ansto/hardsup/stredit.c new file mode 100644 index 00000000..27b61c4e --- /dev/null +++ b/site_ansto/hardsup/stredit.c @@ -0,0 +1,415 @@ +#define ident "1B03" +#ifdef VAXC +#module StrEdit ident +#endif +#ifdef __DECC +#pragma module StrEdit ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Department ASQ | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]StrEdit.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Jan 1996 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]StrEdit - + tasmad_disk:[mad.lib.sinq]StrEdit + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit +** +** Updates: +** 1A01 19-Jan-1996 DM. Initial version. +** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB. +**============================================================================ +** The following entry points are included in this module: +** +**------------------------------------------------------------------------- +** #include +** +** char *StrEdit (char *out, char *in, char *ctrl, int *ln) +** ------- +** Input Args: +** in - the string to be edited. +** ctrl - the string specifying what is to be done. See Description +** below. +** Output Args: +** out - the edited string. The maximum size of this string must +** be specified as input parameter *ln. The string +** will be zero terminated on return. +** Modified Args: +** *ln - an integer specifying, on input, the length of "out" in +** bytes. This must include room for the zero termination. +** On return, ln will be set to the number of characters +** copied to "out" (not counting the zero termination byte). +** Return value: +** If an error is detected, the return value is a NULL pointer. Otherwise +** it is a pointer to the resulting string (i.e. "out"). +** Global variables: +** none +** Routines called: +** none +** Description: +** StrEdit (out, in, ctrl, ln) - This routine is intended to mimic the +** OpenVMS DCL lexical function F$EDIT. +** +** It first processes the string "in" to convert any C-style +** escape sequences introduced by a '\' character. Recognised +** escape sequences are: +** \a --> \007 BEL +** \b --> \010 BS (backspace) +** \f --> \014 FF (formfeed) +** \n --> \012 LF (linefeed) +** \r --> \015 CR (carriage return) +** \t --> \011 HT (horizontal tab) +** \v --> \013 VT (vertical tab) +** \\ --> \ +** \' --> ' +** \" --> " +** \? --> ? +** \xhh --> hh are an arbitrary number of hex digits. +** \nnn --> nnn are up to 3 octal digits. +** Any unrecognised escape sequence will be left unchanged. +** +** The resulting string is then edited according to the +** keywords specified in the control string "ctrl". The result +** will be written to string "out". The "out" argument may be +** the same as "in". +** +** On entry, "ln" specifies the size of "out" in bytes, including +** space for a null terminating byte. On return, it is set to the +** length of the result (not counting the zero-terminator). +** +** The following control strings are recognised: +** +** COLLAPSE - Removes all spaces and tabs from the string. +** COMPRESS - Replaces multiple spaces and tabs with a +** single space. +** LOWERCASE - Makes the string lower case. +** TRIM - Removes leading and trailing spaces and tabs +** from the string. +** UNCOMMENT - Removes comments from the string. +** UPCASE - Makes the string upper case. +** +** All keywords must be specified in full. They may be separated +** by white-space or commas and be in upper or lower case. +** +** If the input string contains non-escaped double quotes ("), +** then the editing functions are not applied to substrings within +** these quotes ("), there must be an even number of such quotes +** and the quotes are not copied to the resulting string. On the +** other hand, escaped double quotes (\") are treated as normal +** characters. +** +** Return Status: +** StrEdit returns a pointer to "out". If any errors are detected (e.g. an +** odd number of quotes), string editing is abandoned and a null pointer +** is returned. +** +** Example: +** strcpy (in, " asdfg \"hello there\" folks "); +** len = sizeof (in); +** printf ("\"%s\"\n", StrEdit (in, in, "trim upcase compress", &len)); +** will generate +** "ASDFG hello there FOLKS" +**------------------------------------------------------------------------- +** Global Definitions +*/ +#include +#include +#include +#include +#include + +#define NIL '\0' +#define True 1 +#define False 0 +#define QUOTE ((char) (('\"' ^ 0xff) & 0xff)) +/* +**==================================================================== +*/ +/* +**==================================================================== +*/ +/*-------------------------------------------------------------------------- +** Global Variables +*/ +/* +**--------------------------------------------------------------------------- +** StrEdit - edit a string. +** Note: strncat is used exclusively rather than +** strncpy to be sure result is always +** null terminated. +*/ + char *StrEdit ( +/* ======= +*/ char *out, + char *in, + char *ctrl, + int *ln) { + + int i, j, k, l, m, len, inxt, out_size; + char my_ctrl[80]; + char *tok_nxt, *my_in, *my_out, *my_tmp, *nxt; + int do_collapse, do_compress, do_lowercase, do_trim; + int do_uncomment, do_upcase; + + out_size = *ln; + if (out_size < 1) {*ln = 0; return NULL;} /* Can't do anything!! */ + + if (strlen (in) <= 0) { + *out = NIL; *ln = 0; return out; /* Nothing to do!! */ + } + /* + ** Scan ctrl looking to see what has to be done. Do this by first + ** taking a copy of it (in case it is declared "const" in the calling + ** routine, convert to lowercase and split into tokens at any space, + ** tab or comma. + */ + len = strlen (ctrl); + if (len >= sizeof (my_ctrl)) { + *out = NIL; *ln = 0; return NULL; + } + for (i = 0; i <= len; i++) my_ctrl[i] = tolower (ctrl[i]); + + do_collapse = do_compress = do_lowercase = do_trim = do_uncomment = + do_upcase = False; + tok_nxt = strtok (my_ctrl, ", \t\f\v\n"); + while (tok_nxt != NULL) { + if (strcmp (tok_nxt, "collapse") == 0) { + do_collapse = True; + }else if (strcmp (tok_nxt, "compress") == 0) { + do_compress = True; + }else if (strcmp (tok_nxt, "lowercase") == 0) { + do_lowercase = True; + }else if (strcmp (tok_nxt, "trim") == 0) { + do_trim = True; + }else if (strcmp (tok_nxt, "uncomment") == 0) { + do_uncomment = True; + }else if (strcmp (tok_nxt, "upcase") == 0) { + do_upcase = True; + }else { + *out = NIL; *ln = 0; return NULL; /* Illegal ctrl verb */ + } + tok_nxt = strtok (NULL, ", \t\f\v\n"); + } + + len = strlen (in) + 1; + my_in = malloc (len); /* Get some working space */ + if (my_in == NULL) { + *out = NIL; *ln = 0; return NULL; + } + /* + ** Copy "in" to the "my_in" working space, processing any '\' escape + ** sequences as we go. Note that, since "my_in" is big enough to hold + ** "in" and the escape sequence processing can only shorten the length + ** of "in", there's no need to check for an overflow of "my_in". Any + ** non-escaped double quotes are converted to something special so + ** that they can be recognised at the editing stage. + */ + nxt = my_in; + while (*in != '\0') { + if (*in == '\\') { /* Look for escape sequence */ + in++; + switch (*in) { + case 'a': case 'A': *nxt++ = '\007'; in++; break; + case 'b': case 'B': *nxt++ = '\010'; in++; break; + case 'f': case 'F': *nxt++ = '\014'; in++; break; + case 'n': case 'N': *nxt++ = '\012'; in++; break; + case 'r': case 'R': *nxt++ = '\015'; in++; break; + case 't': case 'T': *nxt++ = '\011'; in++; break; + case 'v': case 'V': *nxt++ = '\013'; in++; break; + case '\\': *nxt++ = '\\'; in++; break; + case '\'': *nxt++ = '\''; in++; break; + case '\"': *nxt++ = '\"'; in++; break; + case '\?': *nxt++ = '\?'; in++; break; + case 'x': case 'X': + in++; + i = strspn (in, "0123456789abcdefABCDEF"); + if (i > 0) { + *nxt++ = strtol (in, &in, 16); break; + }else { + *nxt++ = '\\'; break; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + i = strspn (in, "01234567"); + if (i > 3) { + sscanf (in, "%3o", &j); + *nxt++ = j; + in += 3; + break; + }else if (i > 0) { + sscanf (in, "%o", &j); + *nxt++ = j; + in += i; + break; + }else { + *nxt++ = '\\'; + break; + } + default: + *nxt++ = '\\'; /* Invalid esc sequ - just copy it */ + } + }else if (*in == '\"') { /* Look for non-escaped double quotes */ + *nxt++ = QUOTE; *in++; /* Make it something unlikely */ + }else { + *nxt++ = *in++; + } + } + *nxt = '\0'; + + my_out = malloc (len); /* Get some working space */ + if (my_out == NULL) { + free (my_in); *out = NIL; *ln = 0; return NULL; + } + *my_out = NIL; + + my_tmp = malloc (len); /* Get some working space */ + if (my_tmp == NULL) { + free (my_out); free (my_in); + *out = NIL; *ln = 0; return NULL; + } + *my_tmp = NIL; + *out = NIL; + /* + ** Ensure "in" has an even number of non-escaped quotes. Return if not. + */ + i = 0; + for (j = 0; my_in[j] != NIL; j++) if (my_in[j] == QUOTE) i++; + if ((i & 1) == 1) { + free (my_tmp); + free (my_out); + free (my_in); + *ln = strlen (out); + return NULL; + } + /* + ** Scan through "in", substring by substring, to + ** handle quotation marks correctly. + */ + inxt = 0; + while (my_in[inxt] != NIL) { + if (my_in[inxt] == QUOTE) { /* Is there a quoted string next? */ + nxt = strchr (&my_in[inxt+1], QUOTE); /* Yes, find matching quote. */ + j = nxt - &my_in[inxt+1]; + memcpy (my_tmp, &my_in[inxt+1], j); /* Make copy of it */ + my_tmp[j] = NIL; + inxt = inxt + j + 2; + }else { + nxt = strchr (&my_in[inxt], QUOTE); /* Not a quoted string; .. + ** .. find next non-escaped .. + ** .. quote. + */ + if (nxt != NULL) { + j = nxt - my_in - inxt; + }else { + j = strlen (&my_in[inxt]); + } + memcpy (my_tmp, &my_in[inxt], j); /* Make copy for us to work on */ + my_tmp[j] = NIL; + inxt = inxt + j; + /* + ** For collapse and compress, start by turning all white space + ** chars to spaces. + */ + if (do_collapse || do_compress) { + for (k = 0; my_tmp[k] != NIL; k++) { + if (my_tmp[k] == '\t') my_tmp[k] = ' '; + if (my_tmp[k] == '\f') my_tmp[k] = ' '; + if (my_tmp[k] == '\v') my_tmp[k] = ' '; + if (my_tmp[k] == '\n') my_tmp[k] = ' '; + } + if (do_collapse) { + l = 0; + for (k = 0; my_tmp[k] != NIL; k++) { + if (my_tmp[k] != ' ') { + my_tmp[l] = my_tmp[k]; + l++; + } + } + my_tmp[l] = NIL; + }else if (do_compress) { + for (k = 0; my_tmp[k] != NIL; k++) { + if (my_tmp[k] == ' ') { + l = strspn (&my_tmp[k], " "); + if (l > 1) { + for (m = 0; my_tmp[k+l+m] != NIL; m++) { + my_tmp[k+m+1] = my_tmp[k+l+m]; + } + my_tmp[k+m+1] = NIL; + } + } + } + } + } + if (do_lowercase) { + for (k = 0; my_tmp[k] != NIL; k++) my_tmp[k] = _tolower (my_tmp[k]); + } + if (do_upcase) { + for (k = 0; my_tmp[k] != NIL; k++) my_tmp[k] = _toupper (my_tmp[k]); + } + if (do_uncomment) { + nxt = strchr (my_tmp, '!'); + if (nxt != NULL) { + *nxt = NIL; /* Truncate the string at the "!" */ + my_in[inxt] = NIL; /* Stop processing loop too */ + } + } + } + StrJoin (out, out_size, my_out, my_tmp); + strcpy (my_out, out); + } + + if (do_trim) { + i = strspn (my_out, " "); + if (i == strlen (my_out)) { /* If all spaces, result is a null string */ + *out = NIL; + }else { + for (j = strlen (my_out); my_out[j-1] == ' '; j--); + my_out[j] = NIL; + } + strcpy (out, &my_out[i]); + } + free (my_tmp); + free (my_out); + free (my_in); + *ln = strlen (out); + /* + ** Undo any encoded escape characters. + */ + for (i = 0; out[i] != NIL; i++) { + if (out[i] == ~'\"') out[i] = '\"'; + } + + return out; + } +/*-------------------------------------------------- End of StrEdit.C -------*/ diff --git a/site_ansto/hardsup/strjoin.c b/site_ansto/hardsup/strjoin.c new file mode 100644 index 00000000..88a8b721 --- /dev/null +++ b/site_ansto/hardsup/strjoin.c @@ -0,0 +1,142 @@ +#define ident "1B03" +#ifdef VAXC +#module StrJoin ident +#endif +#ifdef __DECC +#pragma module StrJoin ident +#endif +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | Department ASQ | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...LIB.SINQ]STRJOIN.C +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Nov 1995 +** +** To compile this module, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ cc /debug /noopt /obj=[]StrEdit - + tasmad_disk:[mad.lib.sinq]StrEdit + + sinq_c_tlb/lib + +** To include this module in SINQ.OLB, use: + + $ import tasmad + $ define/group sinq_c_tlb mad_lib:sinq_c.tlb + $ + $ define/group sinq_olb mad_lib:sinq_dbg.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit debug + $ + $ define/group sinq_olb mad_lib:sinq.olb + $ @tasmad_disk:[mad.lib.sinq]sinq_olb StrEdit +** +** Updates: +** 1A01 2-Nov-1995 DM. Initial version. +** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB. +** 1B03 28-May-1997 DM. Allow result string to be either of source +** strings. +**============================================================================ +** The following entry points are included in this module: +** +**------------------------------------------------------------------------- +** #include +** +** char *StrJoin (&result, result_size, &str_a, &str_b) +** ------- +** Input Args: +** int result_size - max size of "result". The resultant string will +** have a max length of (result_size - 1) to allow +** for the zero terminator +** char *str_a - Pointer to first string to be joined. +** char *str_b - Pointer to second string to be joined. +** Output Args: +** char *result - Pointer to resulting string. +** Modified Args: +** none +** Return value: +** Pointer to resulting string. +** Global variables modified: +** none +** Routines called: +** None +** Description: +** The routine joins 2 strings, checking for total string length and +** ensuring the result will be zero terminated. The "result" arg may be +** the same as "str_a" or "str_b". +**------------------------------------------------------------------------- +** Global Definitions +*/ +#include + +#define NIL '\0' +/* +**==================================================================== +*/ +/* +**==================================================================== +** StrJoin - join 2 strings. +** Note: strncat is used exclusively rather than +** strncpy to be sure result is always +** null terminated. +*/ + char *StrJoin ( +/* ======= +*/ char *result, + int result_size, + char *str_a, + char *str_b) { + + int i, size, size_a, size_b; + + size = result_size - 1; + + if (size < 0) return result; + + if (result == str_a) { /* Are the result and str_a the same? */ + size_a = strlen (str_a); /* Yes */ + if (size_a > size) { /* Check sizes anyway. */ + result[size] = NIL; /* Truncate str_a. No room for str_b! */ + }else { + size = size - strlen (result); /* And append str_b */ + if (size > 0) { + strncat (result, str_b, size); + } + } + }else if (result == str_b) { /* Are the result and str_b the same? */ + size_a = strlen (str_a); /* Yes, this is a bit complicated! */ + size_b = strlen (str_b); + if (size_a >= size) { /* If str_a completely fills result, .. */ + result[0] = NIL; /* .. then just copy in str_a */ + strncat (result, str_a, size); + }else { + /* + ** Otherwise, str_b must first be moved to + ** make room for str_a and then str_a must + ** be put at the front of the result. + */ + if ((size_a + size_b) > size) size_b = size - size_a; + result[size_a+size_b] = NIL; + for (i = (size_b-1); i >= 0; i--) { + result[size_a+i] = str_b[i]; + } + memcpy (result, str_a, size_a); + } + }else { /* Result is neither str_a nor str_b so .. */ + result[0] = NIL; /* .. str_a needs to be copied */ + strncat (result, str_a, size); + size = size - strlen (result); /* And str_a appended */ + if (size > 0) strncat (result, str_b, size); + } + return result; + } +/*-------------------------------------------------- End of STRJOIN.C =======*/ diff --git a/site_ansto/hardsup/table.h b/site_ansto/hardsup/table.h new file mode 100644 index 00000000..7d98b299 --- /dev/null +++ b/site_ansto/hardsup/table.h @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------- + A general purpose translation table and interpolation module. + Interpolation tables are read from a file, which is meant to + contain pairs of val1 val2 per line. + + + Mark Koennecke, October 1997 + + copyright: see copyright.h + +-----------------------------------------------------------------------------*/ +#ifndef SICSTABLE +#define SICSTABLE + typedef struct __SicsTable *pSTable; + +/*------------------------- live & death ----------------------------------*/ + pSTable CreateTable(FILE *fd); + /* + creates a new table from a given file. The file is meant to have + been positioned to the first entry for the table in the file. + This leaves the caller free to examine a header, if any. + */ + void DeleteTable(pSTable self); +/*------------------------- Interpolation --------------------------------*/ + int InterpolateVal1(pSTable pTable, float fKey, float *fResult); + /* + Returns a result from the second column for a key from the + first column. + */ + int InterpolateVal2(pSTable pTable, float fKey, float *fResult); + /* + Returns a result from the first column for a key from the + second column. + */ +#endif diff --git a/site_ansto/hardsup/velsel_def.h b/site_ansto/hardsup/velsel_def.h new file mode 100644 index 00000000..276eb65b --- /dev/null +++ b/site_ansto/hardsup/velsel_def.h @@ -0,0 +1,58 @@ +#ifndef _velsel_def_ +#define _velsel_def_ +/*------------------------------------------------ VelSel_DEF.H Ident V01B +*/ +#include +#include + +#ifndef OffsetOf +#define OffsetOf(type, identifier) ((size_t)(&((type*) NULL)->identifier)) +#endif + +enum VelSel_Errors {VELSEL__BAD_TMO = -1, + VELSEL__BAD_CMD = -3, + VELSEL__BAD_OFL = -4, + VELSEL__BAD_ILLG = -5, + VELSEL__BAD_HOST = -6, + VELSEL__BAD_SOCKET = -7, + VELSEL__BAD_BIND = -8, + VELSEL__BAD_CONNECT = -9, + VELSEL__BAD_DEV = -10, + VELSEL__BAD_MALLOC = -11, + VELSEL__BAD_SENDLEN = -12, + VELSEL__BAD_SEND = -13, + VELSEL__BAD_SEND_PIPE = -14, + VELSEL__BAD_SEND_NET = -15, + VELSEL__BAD_SEND_UNKN = -16, + VELSEL__BAD_RECV = -17, + VELSEL__BAD_RECV_PIPE = -18, + VELSEL__BAD_RECV_NET = -19, + VELSEL__BAD_RECV_UNKN = -20, + VELSEL__BAD_NOT_BCD = -21, + VELSEL__BAD_RECVLEN = -22, + VELSEL__BAD_FLUSH = -23, + VELSEL__BAD_RECV1 = -24, + VELSEL__BAD_RECV1_PIPE = -25, + VELSEL__BAD_RECV1_NET = -26, + VELSEL__BAD_PAR = -29, + VELSEL__BAD_BSY = -30, + VELSEL__BAD_OPEN = -31, + VELSEL__FORCED_CLOSED = -32, + VELSEL__BAD_STP = -33, + VELSEL__NOT_OPEN = -35, + VELSEL__BAD_ASYNSRV = -36, + VELSEL__BAD_REPLY = -34}; +/* +** Structure to which the VelSel_Open handle points. +*/ + struct VelSel_info { + struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ + int tmo; + char eot[4]; + int msg_id; + int n_replies, max_replies; + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + }; +/*------------------------------------------------ End of VelSel_DEF.H --*/ +#endif /* _velsel_def_ */ diff --git a/site_ansto/instrument/SICSHome.tgz b/site_ansto/instrument/SICSHome.tgz new file mode 100644 index 00000000..24a77b48 Binary files /dev/null and b/site_ansto/instrument/SICSHome.tgz differ diff --git a/site_ansto/instrument/genCLOSLOOP.tcl b/site_ansto/instrument/genCLOSLOOP.tcl new file mode 100644 index 00000000..e2355ad2 --- /dev/null +++ b/site_ansto/instrument/genCLOSLOOP.tcl @@ -0,0 +1,83 @@ +#TODO Version stamp this code and write the version number to the generated code +# axis = A B C D E F +# encodercounts = number of encoder counts per revolution +# quadcounts = number of quadrature counts per revolution +# tolquadcounts = tolerance in quadrature counts +proc genMOVE {axis encodercounts quadcounts tolquadcounts} { +puts "NO CLOSE MOTION LOOP FOR ${axis} AXIS + NO If the motor is within ${axis}TOLQC quadrature counts of the target + NO position then adjust it. + ${axis}DIFF=${axis}QTARGET - _TP${axis} + IF ( ((100*${axis}TOLQC) > @ABS\[${axis}DIFF\]) & (@ABS\[${axis}DIFF\] > ${axis}TOLQC) ) + ${axis}SHLDFIX=1 + ELSE + ${axis}SHLDFIX=0 + ENDIF + IF (${axis}FIXPOS=1) + ${axis}OLDQT=${axis}QTARGET + ${axis}count=10 + SH${axis} +#${axis}LOOP + NO Abort if target position changes + IF (${axis}OLDQT <> ${axis}QTARGET) + JP#${axis}ENDCLP + ENDIF + ${axis}count=${axis}count-1 + PR${axis}=${encodercounts}*(${axis}DIFF/${quadcounts}) + IF (_SP${axis}>${axis}MINSP) + SP${axis}=@ABS\[_PR${axis}\]/2.0 + IF (_SP${axis} < ${axis}MINSP) + SP${axis}=${axis}MINSP + ENDIF + IF (_SP${axis} > ${axis}MAXSP) + SP${axis}=${axis}MAXSP + ENDIF + ENDIF + BG${axis} + MC${axis} + ${axis}DIFF=${axis}QTARGET - _TP${axis} + IF ( ((100*${axis}TOLQC) > @ABS\[${axis}DIFF\]) & (@ABS\[${axis}DIFF\] > ${axis}TOLQC) ) + JP#${axis}LOOP,${axis}count>0 + ENDIF +#${axis}ENDCLP + NO Restore speed to maximum + ${axis}FIXPOS=0 + ${axis}SHLDFIX=0 + SP${axis}=${axis}MAXSP + ENDIF" +} + + +# Generate subroutine to start the servo loop thread +puts "#CLSLOOP" +set tolquadcounts 1 +set encodercounts 25000 +set quadcounts 8192 +puts "NO Initilise tolerance, max and min speeds +ATOLQC=100 +AMAXSP=${encodercounts} +AMINSP=100*(${encodercounts}/93207) +AFIXPOS=0" +foreach {axis} {B C D E F} { +puts "${axis}TOLQC=${tolquadcounts} +${axis}MAXSP=${encodercounts} +${axis}MINSP=100*(${encodercounts}/$quadcounts) +${axis}FIXPOS=0" +} +foreach {axis} {A B C D E F} { + puts "${axis}DIFF=${axis}QTARGET - _TP${axis} + IF ( ((100*${axis}TOLQC) > @ABS\[${axis}DIFF\]) & (@ABS\[${axis}DIFF\] > ${axis}TOLQC) ) + ${axis}SHLDFIX=1 + ELSE + ${axis}SHLDFIX=0 + ENDIF" +} +puts "XQ#SERVOLP,1 +EN" +# Generate servo loop +puts "#SERVOLP" +genMOVE A $encodercounts -93165 $tolquadcounts +foreach {axis} {B C D E F} { + genMOVE $axis $encodercounts $quadcounts $tolquadcounts +} +puts "JP#SERVOLP" diff --git a/site_ansto/instrument/gen_home_slits.tcl b/site_ansto/instrument/gen_home_slits.tcl new file mode 100644 index 00000000..16b35f97 --- /dev/null +++ b/site_ansto/instrument/gen_home_slits.tcl @@ -0,0 +1,25 @@ +proc move_away_from_switch {axis} { +puts "NO Move slit forward 10mm if it is against the reverse limit switch +IF ((_TS${axis} & 4) = 0) +SH${axis} +PR${axis}=200000 +BG${axis} +ENDIF" +} + +puts "#HOME" +foreach {axis} {A B C D} { +move_away_from_switch $axis +} +puts "AM" +puts "NO Drive all slits into reverse limit switch" +puts "SH +JG -25000,-25000,-25000,-25000 +BGABCD +AM" +puts "NO Move forward from switch by 2mm and set zero" +puts "PR 40000,40000,40000,40000 +BGABCD +AM +DP 0,0,0,0" +puts "EN" diff --git a/site_ansto/instrument/hipd/hipd_configuration.tcl b/site_ansto/instrument/hipd/hipd_configuration.tcl new file mode 100644 index 00000000..4b67b47f --- /dev/null +++ b/site_ansto/instrument/hipd/hipd_configuration.tcl @@ -0,0 +1,473 @@ +# $Revision: 1.1 $ +# $Date: 2006-05-08 22:31:50 $ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) +# Last revision by: $Author: ffr $ + +#START SERVER CONFIGURATION SECTION +installprotocolhandler +# Use this to create an array of named parameters to inilise motors. +proc params {args} { + upvar 1 "" x; + if [info exists x] {unset x} + eval "array set x [list $args]" +} + +ServerOption statusfile log/status.tcl +ServerOption RedirectFile log/stdout +ServerOption LogFileBaseName log/serverlog +ServerOption LogFileDir log +ServerOption QuieckPort 60004 +ServerOption ServerPort 60003 +ServerOption InterruptPort 60002 +ServerOption TelWord sicslogin +ServerOption TelnetPort 60001 +ServerOption ReadUserPasswdTimeout 600000 +ServerOption AcceptTimeOut 10 +ServerOption ReadTimeOut 10 +SicsUser manager ansto 1 +SicsUser user sydney 2 +SicsUser spy 007 3 +MakeDataNumber SicsDataNumber data/DataNumber +VarMake SicsDataPath Text Internal +SicsDataPath data/ +SicsDataPath lock +VarMake SicsDataPrefix Text Internal +SicsDataPrefix smp +SicsDataPrefix lock +VarMake SicsDataPostFix Text Internal +SicsDataPostFix .hdf +SicsDataPostFix lock +VarMake Title Text User +VarMake Sample Text User +VarMake User Text User +VarMake starttime Text User +VarMake currentfile Text User +VarMake batchroot Text User +VarMake Instrument Text Internal +Instrument HRPD +Instrument lock +MakeDrive +#END SERVER CONFIGURATION SECTION + +######################################## +# INSTRUMENT SPECIFIC CONFIGURATION + +#XXX WHICH CONTROLLER DO ECHI AND EPHI BELONG TO +#Motor echi DMC2280 [params \ +# host hhh\ +# port ppp\ +# axis A\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#echi hardlowerlim 0 +#echi hardupperlim 360 +#echi softlowerlim 0 +#echi softupperlim 360 +#echi home 0 + +#Motor ephi DMC2280 [params \ +# host hhh\ +# port ppp\ +# axis A?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#ephi hardlowerlim 0 +#ephi hardupperlim 360 +#ephi softlowerlim 0 +#ephi softupperlim 360 +#ephi home 0 + +# Setup addresses of Galil DMC2280 controllers. +set dmc2280_controller1(host) 137.157.201.66 +set dmc2280_controller1(port) 1034 + +set dmc2280_controller2(host) localhost +#set dmc2280_controller2(host) 137.157.201.67 1034 +set dmc2280_controller2(port) 1034 + +set dmc2280_controller3(host) localhost +#set dmc2280_controller3(host) 137.157.201.67 +set dmc2280_controller3(port) 1035 +#set dmc2280_controller3(port) 1034 + +set dmc2280_controller4(host) 137.157.201.68 +set dmc2280_controller4(port) 1034 + +#Motor mth DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mth hardlowerlim -180 +#mth hardupperlim 180 +#mth softlowerlim -180 +#mth softupperlim 180 +#mth home 0 +# +#Motor mom DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mom hardlowerlim -180 +#mom hardupperlim 180 +#mom softlowerlim -180 +#mom softupperlim 180 +#mom home 0 +# +#Motor mtth DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mtth hardlowerlim 85 +#mtth hardupperlim 155 +#mtth softlowerlim 85 +#mtth softupperlim 155 +#mtth home 120 +# +#Motor mchi DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mchi hardlowerlim 70 +#mchi hardupperlim 110 +#mchi softlowerlim 70 +#mchi softupperlim 110 +#mchi home 90 +# +#Motor mphi DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mphi hardlowerlim -20 +#mphi hardupperlim 20 +#mphi softlowerlim -20 +#mphi softupperlim 20 +#mphi home 0 +# +#Motor mx DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mx hardlowerlim -20 +#mx hardupperlim 20 +#mx softlowerlim -20 +#mx softupperlim 20 +#mx home 0 +# +#Motor my DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#my hardlowerlim -20 +#my hardupperlim 20 +#my softlowerlim -20 +#my softupperlim 20 +#my home 0 +# +#Motor mr DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mr hardlowerlim HLL +#mr hardupperlim HUL +#mr softlowerlim SLL +#mr softupperlim SUL +#mr home 0 +# +#Motor pc1 DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis F\ +# stepsPerX XXX] +#pc1 hardlowerlim HLL +#pc1 hardupperlim HUL +#pc1 softlowerlim SLL +#pc1 softupperlim SUL +#pc1 home 0 +# +#Motor pc2 DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis G\ +# stepsPerX XXX] +#pc2 hardlowerlim HLL +#pc2 hardupperlim HUL +#pc2 softlowerlim SLL +#pc2 softupperlim SUL +#pc2 home 0 +# +#Motor sth DMC2280 [params \ +# host $dmc2280_controller2(host)\ +# port $dmc2280_controller2(port)\ +# axis A?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#sth hardlowerlim -180 +#sth hardupperlim 180 +#sth softlowerlim -180 +#sth softupperlim 180 +#sth home 0 + +Motor som DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis B\ + stepsPerX 25000\ + absEnc 1\ + absEncHome 17694127\ + cntsPerX 8192] +som hardlowerlim -180 +som hardupperlim 180 +som softlowerlim -1.9 +som softupperlim 1.9 +som home 0 + +Motor stth DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis A\ + stepsPerX 125000\ + motorHome 11250000\ + absEnc 1\ + absEncHome 6559259\ + cntsPerX -93207] +stth hardlowerlim 85 +stth hardupperlim 155 +stth softlowerlim 85 +stth softupperlim 155 +stth home 120 + +Motor schi DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis E\ + stepsPerX -25000\ + motorHome 500000\ + absEnc 1\ + absEncHome 7581355\ + cntsPerX -8192] +schi hardlowerlim 70 +schi hardupperlim 110 +schi softlowerlim 70 +schi softupperlim 110 +schi home 90 +Motor sphi DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis F\ + stepsPerX -25000\ + motorHome 500000\ + absEnc 1\ + absEncHome 7934290\ + cntsPerX -8192] +sphi hardlowerlim -20 +sphi hardupperlim 20 +sphi softlowerlim -20 +sphi softupperlim 20 +sphi home 0 + +Motor sx DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis D\ + stepsPerX -25000\ + absEnc 1\ + absEncHome 7562793\ + cntsPerX -8192] +sx hardlowerlim -20 +sx hardupperlim 20 +sx softlowerlim -20 +sx softupperlim 20 +sx home 0 + +Motor sy DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis C\ + stepsPerX -25000\ + absEnc 1\ + absEncHome 7562793\ + cntsPerX -8192] +sy hardlowerlim -20 +sy hardupperlim 20 +sy softlowerlim -20 +sy softupperlim 20 +sy home 0 + +Motor ss1u DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis C\ + stepsPerX -20000\ + motorHome 2040518] +ss1u hardlowerlim 0 +ss1u hardupperlim 50 +ss1u softlowerlim 0 +ss1u softupperlim 50 +ss1u home 0 + +Motor ss1d DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis D\ + stepsPerX -20000\ + motorHome 2040518] +ss1d hardlowerlim 0 +ss1d hardupperlim 50 +ss1d softlowerlim 0 +ss1d softupperlim 50 +ss1d home 0 + +Motor ss1l DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis A\ + stepsPerX -20000\ + motorHome 542093] +ss1l hardlowerlim 0 +ss1l hardupperlim 50 +ss1l softlowerlim 0 +ss1l softupperlim 50 +ss1l home 0 + +Motor ss1r DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis B\ + stepsPerX -20000\ + motorHome 542093] +ss1r hardlowerlim 0 +ss1r hardupperlim 50 +ss1r softlowerlim 0 +ss1r softupperlim 50 +ss1r home 0 + +#Motor ss2u DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 2043085] +#ss2u hardlowerlim 0 +#ss2u hardupperlim 50 +#ss2u softlowerlim 0 +#ss2u softupperlim 50 +#ss2u home 0 +# +#Motor ss2d DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 2043085] +#ss2d hardlowerlim 0 +#ss2d hardupperlim 50 +#ss2d softlowerlim 0 +#ss2d softupperlim 50 +#ss2d home 0 +# +#Motor ss2l DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 500000] +#ss2l hardlowerlim 0 +#ss2l hardupperlim 50 +#ss2l softlowerlim 0 +#ss2l softupperlim 50 +#ss2l home 0 +# +#Motor ss2r DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 500000] +#ss2r hardlowerlim 0 +#ss2r hardupperlim 50 +#ss2r softlowerlim 0 +#ss2r softupperlim 50 +#ss2r home 0 + + +proc SplitReply { text } { + set l [split $text =] + return [lindex $l 1] +} +# virtual motor d1(h)orizontal (width) +#-------------------------------------------------------- +proc widthscript {val} { + set currentWidth [expr [SplitReply [ss1r]] + [SplitReply [ss1l]]] + set diff [expr $val - $currentWidth] + set newD1R [expr [SplitReply [ss1r]] + $diff/2] + set newD1L [expr [SplitReply [ss1l]] + $diff/2] + return "ss1r=$newD1R,ss1l=$newD1L" +} +publish widthscript user +#------------------------------------------------------- +proc readwidth {} { + return [expr [SplitReply [ss1r]] + [SplitReply [ss1l]]] +} +publish readwidth user +#------------------------------------------------------- +MakeConfigurableMotor ss1hg +ss1hg drivescript widthscript +ss1hg readscript readwidth +# virtual motor d1v(ertical), height +#----------------------------------------------------- +proc heightscript {val} { + set currentWidth [expr [SplitReply [ss1u]] + [SplitReply [ss1d]]] + set diff [expr $val - $currentWidth] + set newD1B [expr [SplitReply [ss1d]] + $diff/2] + set newD1T [expr [SplitReply [ss1u]] + $diff/2] + return "ss1d=$newD1B,ss1u=$newD1T" +} +publish heightscript user +#------------------------------------------------------- +proc readheight {} { + return [expr [SplitReply [ss1u]] + [SplitReply [ss1d]]] +} +publish readheight user +#--------------------------------------------------------- +MakeConfigurableMotor ss1vg +ss1vg drivescript heightscript +ss1vg readscript readheight + diff --git a/site_ansto/instrument/hrpd/hrpd_configuration.tcl b/site_ansto/instrument/hrpd/hrpd_configuration.tcl new file mode 100644 index 00000000..d07d183e --- /dev/null +++ b/site_ansto/instrument/hrpd/hrpd_configuration.tcl @@ -0,0 +1,513 @@ +# $Revision: 1.1 $ +# $Date: 2006-05-08 22:31:50 $ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) +# Last revision by: $Author: ffr $ + +#START SERVER CONFIGURATION SECTION +installprotocolhandler +# Use this to create an array of named parameters to inilise motors. +proc params {args} { + upvar 1 "" x; + if [info exists x] {unset x} + eval "array set x [list $args]" +} + +ServerOption statusfile log/status.tcl +ServerOption RedirectFile log/stdout +ServerOption LogFileBaseName log/serverlog +ServerOption LogFileDir log +ServerOption QuieckPort 60004 +ServerOption ServerPort 60003 +ServerOption InterruptPort 60002 +ServerOption TelWord sicslogin +ServerOption TelnetPort 60001 +ServerOption ReadUserPasswdTimeout 600000 +ServerOption AcceptTimeOut 10 +ServerOption ReadTimeOut 10 +SicsUser manager ansto 1 +SicsUser user sydney 2 +SicsUser spy 007 3 +MakeDataNumber SicsDataNumber data/DataNumber +VarMake SicsDataPath Text Internal +SicsDataPath data/ +SicsDataPath lock +VarMake SicsDataPrefix Text Internal +SicsDataPrefix smp +SicsDataPrefix lock +VarMake SicsDataPostFix Text Internal +SicsDataPostFix .hdf +SicsDataPostFix lock +VarMake Title Text User +VarMake Sample Text User +VarMake User Text User +VarMake starttime Text User +VarMake currentfile Text User +VarMake batchroot Text User +VarMake Instrument Text Internal +Instrument HRPD +Instrument lock +MakeDrive +#END SERVER CONFIGURATION SECTION + +######################################## +# INSTRUMENT SPECIFIC CONFIGURATION + +#XXX WHICH CONTROLLER DO ECHI AND EPHI BELONG TO +#Motor echi DMC2280 [params \ +# host hhh\ +# port ppp\ +# axis A\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#echi hardlowerlim 0 +#echi hardupperlim 360 +#echi softlowerlim 0 +#echi softupperlim 360 +#echi home 0 + +#Motor ephi DMC2280 [params \ +# host hhh\ +# port ppp\ +# axis A?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#ephi hardlowerlim 0 +#ephi hardupperlim 360 +#ephi softlowerlim 0 +#ephi softupperlim 360 +#ephi home 0 + +# Setup addresses of Galil DMC2280 controllers. +set dmc2280_controller1(host) 137.157.201.66 +set dmc2280_controller1(port) 1034 + +set dmc2280_controller2(host) localhost +#set dmc2280_controller2(host) 137.157.201.67 1034 +set dmc2280_controller2(port) 1034 + +set dmc2280_controller3(host) localhost +#set dmc2280_controller3(host) 137.157.201.67 +set dmc2280_controller3(port) 1035 +#set dmc2280_controller3(port) 1034 + +set dmc2280_controller4(host) 137.157.201.68 +set dmc2280_controller4(port) 1034 + +#Motor mth DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mth hardlowerlim -180 +#mth hardupperlim 180 +#mth softlowerlim -180 +#mth softupperlim 180 +#mth home 0 +# +#Motor mom DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mom hardlowerlim -180 +#mom hardupperlim 180 +#mom softlowerlim -180 +#mom softupperlim 180 +#mom home 0 +# +#Motor mtth DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mtth hardlowerlim 85 +#mtth hardupperlim 155 +#mtth softlowerlim 85 +#mtth softupperlim 155 +#mtth home 120 +# +#Motor mchi DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mchi hardlowerlim 70 +#mchi hardupperlim 110 +#mchi softlowerlim 70 +#mchi softupperlim 110 +#mchi home 90 +# +#Motor mphi DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mphi hardlowerlim -20 +#mphi hardupperlim 20 +#mphi softlowerlim -20 +#mphi softupperlim 20 +#mphi home 0 +# +#Motor mx DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mx hardlowerlim -20 +#mx hardupperlim 20 +#mx softlowerlim -20 +#mx softupperlim 20 +#mx home 0 +# +#Motor my DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#my hardlowerlim -20 +#my hardupperlim 20 +#my softlowerlim -20 +#my softupperlim 20 +#my home 0 +# +#Motor mr DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis X?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#mr hardlowerlim HLL +#mr hardupperlim HUL +#mr softlowerlim SLL +#mr softupperlim SUL +#mr home 0 +# +#Motor pc1 DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis F\ +# stepsPerX XXX] +#pc1 hardlowerlim HLL +#pc1 hardupperlim HUL +#pc1 softlowerlim SLL +#pc1 softupperlim SUL +#pc1 home 0 +# +#Motor pc2 DMC2280 [params \ +# host $dmc2280_controller1(host)\ +# port $dmc2280_controller1(port)\ +# axis G\ +# stepsPerX XXX] +#pc2 hardlowerlim HLL +#pc2 hardupperlim HUL +#pc2 softlowerlim SLL +#pc2 softupperlim SUL +#pc2 home 0 +# +#Motor sth DMC2280 [params \ +# host $dmc2280_controller2(host)\ +# port $dmc2280_controller2(port)\ +# axis A?\ +# stepsPerX XXX\ +# absEnc 1\ +# absEncHome YYY\ +# cntsPerX ZZZ] +#sth hardlowerlim -180 +#sth hardupperlim 180 +#sth softlowerlim -180 +#sth softupperlim 180 +#sth home 0 + +Motor som DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis B\ + units degrees\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX 25000\ + absEnc 1\ + absEncHome 17694127\ + cntsPerX 8192] +som hardlowerlim -180 +som hardupperlim 180 +som softlowerlim -1.9 +som softupperlim 1.9 +som home 0 + +Motor stth DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis A\ + units degrees\ + maxSpeed 0.2\ + maxAccel 0.2\ + maxDecel 0.2\ + stepsPerX 125000\ + motorHome 11250000\ + absEnc 1\ + absEncHome 6559259\ + cntsPerX -93207] +stth hardlowerlim 85 +stth hardupperlim 155 +stth softlowerlim 85 +stth softupperlim 155 +stth home 120 + +Motor schi DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis E\ + units degrees\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -25000\ + motorHome 500000\ + absEnc 1\ + absEncHome 7581355\ + cntsPerX -8192] +schi hardlowerlim 70 +schi hardupperlim 110 +schi softlowerlim 70 +schi softupperlim 110 +schi home 90 +Motor sphi DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis F\ + units degrees\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -25000\ + motorHome 500000\ + absEnc 1\ + absEncHome 7934290\ + cntsPerX -8192] +sphi hardlowerlim -20 +sphi hardupperlim 20 +sphi softlowerlim -20 +sphi softupperlim 20 +sphi home 0 + +Motor sx DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis D\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -25000\ + absEnc 1\ + absEncHome 7562793\ + cntsPerX -8192] +sx hardlowerlim -20 +sx hardupperlim 20 +sx softlowerlim -20 +sx softupperlim 20 +sx home 0 + +Motor sy DMC2280 [params \ + host $dmc2280_controller2(host)\ + port $dmc2280_controller2(port)\ + axis C\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -25000\ + absEnc 1\ + absEncHome 7562793\ + cntsPerX -8192] +sy hardlowerlim -20 +sy hardupperlim 20 +sy softlowerlim -20 +sy softupperlim 20 +sy home 0 + +Motor ss1u DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis C\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -20000\ + motorHome 2040518] +ss1u hardlowerlim 0 +ss1u hardupperlim 50 +ss1u softlowerlim 0 +ss1u softupperlim 50 +ss1u home 0 + +Motor ss1d DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis D\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -20000\ + motorHome 2040518] +ss1d hardlowerlim 0 +ss1d hardupperlim 50 +ss1d softlowerlim 0 +ss1d softupperlim 50 +ss1d home 0 + +Motor ss1l DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis A\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -20000\ + motorHome 542093] +ss1l hardlowerlim 0 +ss1l hardupperlim 50 +ss1l softlowerlim 0 +ss1l softupperlim 50 +ss1l home 0 + +Motor ss1r DMC2280 [params \ + host $dmc2280_controller3(host)\ + port $dmc2280_controller3(port)\ + axis B\ + units mm\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -20000\ + motorHome 542093] +ss1r hardlowerlim 0 +ss1r hardupperlim 50 +ss1r softlowerlim 0 +ss1r softupperlim 50 +ss1r home 0 + +#Motor ss2u DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 2043085] +#ss2u hardlowerlim 0 +#ss2u hardupperlim 50 +#ss2u softlowerlim 0 +#ss2u softupperlim 50 +#ss2u home 0 +# +#Motor ss2d DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 2043085] +#ss2d hardlowerlim 0 +#ss2d hardupperlim 50 +#ss2d softlowerlim 0 +#ss2d softupperlim 50 +#ss2d home 0 +# +#Motor ss2l DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 500000] +#ss2l hardlowerlim 0 +#ss2l hardupperlim 50 +#ss2l softlowerlim 0 +#ss2l softupperlim 50 +#ss2l home 0 +# +#Motor ss2r DMC2280 [params \ +# host $dmc2280_controller4(host)\ +# port $dmc2280_controller4(port)\ +# axis F?\ +# stepsPerX -20000\ +# motorHome 500000] +#ss2r hardlowerlim 0 +#ss2r hardupperlim 50 +#ss2r softlowerlim 0 +#ss2r softupperlim 50 +#ss2r home 0 + + +proc SplitReply { text } { + set l [split $text =] + return [lindex $l 1] +} +# virtual motor d1(h)orizontal (width) +#-------------------------------------------------------- +proc widthscript {val} { + set currentWidth [expr [SplitReply [ss1r]] + [SplitReply [ss1l]]] + set diff [expr $val - $currentWidth] + set newD1R [expr [SplitReply [ss1r]] + $diff/2] + set newD1L [expr [SplitReply [ss1l]] + $diff/2] + return "ss1r=$newD1R,ss1l=$newD1L" +} +publish widthscript user +#------------------------------------------------------- +proc readwidth {} { + return [expr [SplitReply [ss1r]] + [SplitReply [ss1l]]] +} +publish readwidth user +#------------------------------------------------------- +MakeConfigurableMotor ss1hg +ss1hg drivescript widthscript +ss1hg readscript readwidth +# virtual motor d1v(ertical), height +#----------------------------------------------------- +proc heightscript {val} { + set currentWidth [expr [SplitReply [ss1u]] + [SplitReply [ss1d]]] + set diff [expr $val - $currentWidth] + set newD1B [expr [SplitReply [ss1d]] + $diff/2] + set newD1T [expr [SplitReply [ss1u]] + $diff/2] + return "ss1d=$newD1B,ss1u=$newD1T" +} +publish heightscript user +#------------------------------------------------------- +proc readheight {} { + return [expr [SplitReply [ss1u]] + [SplitReply [ss1d]]] +} +publish readheight user +#--------------------------------------------------------- +MakeConfigurableMotor ss1vg +ss1vg drivescript heightscript +ss1vg readscript readheight + diff --git a/site_ansto/instrument/make_sics_tar.tcl b/site_ansto/instrument/make_sics_tar.tcl new file mode 100755 index 00000000..b6a29ee3 --- /dev/null +++ b/site_ansto/instrument/make_sics_tar.tcl @@ -0,0 +1,19 @@ +#!/bin/bash +# Creates a tarball containing a SICS server distribution for a given instrument. +serverHome=Server +mkdir -p INST_TMP/SICS +rm -fr INST_TMP/SICS/* +mkdir INST_TMP/SICS/log +mkdir INST_TMP/SICS/tmp +mkdir INST_TMP/SICS/$serverHome +mkdir INST_TMP/SICS/data +touch INST_TMP/SICS/data/DataNumber +cp $serverHome/${serverHome}Configuration.tcl INST_TMP/SICS/$serverHome +cp $serverHome/${serverHome}.hdd INST_TMP/SICS/$serverHome +cp ../SICServer INST_TMP/SICS/$serverHome +cp dmc2280.tcl INST_TMP/SICS/$serverHome +cp ../../sycFormat.tcl INST_TMP/SICS/$serverHome +cd INST_TMP +tar -czf ../$serverHome.tgz SICS +cd - +rm -fr INST_TMP