diff options
author | Rafael Laboissière <rafael@debian.org> | 2024-04-06 00:03:00 -0300 |
---|---|---|
committer | Rafael Laboissière <rafael@debian.org> | 2024-04-06 00:03:00 -0300 |
commit | d95945b9084fcac38e09b8f4b7d676f3e6f7b7a7 (patch) | |
tree | 3e12b18aaead54d0dee7022e5fab1cac3faa168c | |
parent | 556797a6b855516d7dcb0cdbadbd40b2e08ae5d9 (diff) | |
parent | 13cd6cc0b79849f9b653e952433c4dc0fb2df507 (diff) |
Update upstream source from tag 'upstream/0.9.3'
Update to upstream version '0.9.3'
with Debian dir 518c7f09ec999a4ed8db5a98367f6e984d40968e
27 files changed, 728 insertions, 92 deletions
diff --git a/DESCRIPTION b/DESCRIPTION index 54d45f7..bfaddd2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Name: instrument-control -Version: 0.9.2 -Date: 2024-01-04 +Version: 0.9.3 +Date: 2024-03-31 Author: Andrius Sutas <andrius.sutas@gmail.com>, Stefan Mahr <dac922@gmx.de>, John Donoghue <john.donoghue@ieee.org> Maintainer: Stefan Mahr <dac922@gmx.de>, John Donoghue <john.donoghue@ieee.org> Title: Instrument Control @@ -166,7 +166,8 @@ endif $(MAKE) distclean && $(RM) Makefile ## $(MAKE) -C "$@" docs - cd "$@" && $(RM) -rf "devel" && $(RM) -f doc/mkfuncdocs.py doc/mkqhcp.py + cd "$@" && $(RM) -rf "devel" + # && $(RM) -f doc/mkfuncdocs.py doc/mkqhcp.py ${FIX_PERMISSIONS} "$@" run_in_place = $(OCTAVE) --eval ' pkg ("local_list", "$(package_list)"); ' \ @@ -1,3 +1,16 @@ +Summary of important user-visible changes for instrument-control 0.9.3 +------------------------------------------------------------------- + + ** SERIALPORT: use max VTIME of 5, allow use of case insensive get properties + + ** TCPCLIENT: add enabletransferdelay property + + ** UDP, UDPPORT: use memmove for overlapped mem usage + + ** VXI11: use inst0 as default instrument name + + ** MODBUS: use input precision when specified in read + Summary of important user-visible changes for instrument-control 0.9.2 ------------------------------------------------------------------- diff --git a/doc/functions.texi b/doc/functions.texi index 5213855..358aeb9 100644 --- a/doc/functions.texi +++ b/doc/functions.texi @@ -2599,6 +2599,8 @@ Known input properties: name value @item Timeout Numeric timeout value or -1 to wait forever +@item EnableTransferDelay +Boolean to enable or disable the nagle algorithm for delay transfer. @item UserData User data value. @end table @@ -2631,6 +2633,8 @@ Byte order for data (currently not used) Terminator value used for string data (currently not used) @item UserData User data +@item EnableTransferDelay +Bool for whether transfer delay is enabled. (Read only) @end table @end deftypefn @c --------------------------------------------------- @@ -3632,7 +3636,7 @@ Upon successful completion, usbtmc_write() shall return the number of bytes writ Open vxi11 interface. @var{ip} - the ip address of type String. If omitted defaults to '127.0.0.1'. -@var{instr} - the instrument name of type String. If omitted defaults to 'instr0'. +@var{instr} - the instrument name of type String. If omitted defaults to 'inst0'. The vxi11() shall return instance of @var{octave_vxi11} class as the result @var{vxi11}. @end deftypefn diff --git a/doc/instrument-control.html b/doc/instrument-control.html index 7af5d18..1f20612 100644 --- a/doc/instrument-control.html +++ b/doc/instrument-control.html @@ -55,6 +55,7 @@ ul.toc-numbered-mark {list-style: none} + <div class="top-level-extent" id="Top"> <div class="nav-panel"> <p> @@ -403,7 +404,7 @@ octave-forge using the following command within <abbr class="acronym">GNU</abbr> <abbr class="acronym">GNU</abbr> Octave, the package can be installed using the following command within <abbr class="acronym">GNU</abbr> Octave: </p> <div class="example"> -<pre class="example-preformatted">pkg install instrument-control-0.9.2.tar.gz +<pre class="example-preformatted">pkg install instrument-control-0.9.3.tar.gz </pre></div> </div> @@ -3930,6 +3931,9 @@ Next: <a href="#TCP-Server" accesskey="n" rel="next">TCP Server</a>, Previous: < <dt>Timeout</dt> <dd><p>Numeric timeout value or -1 to wait forever </p></dd> +<dt>EnableTransferDelay</dt> +<dd><p>Boolean to enable or disable the nagle algorithm for delay transfer. +</p></dd> <dt>UserData</dt> <dd><p>User data value. </p></dd> @@ -3974,6 +3978,9 @@ Next: <a href="#TCP-Server" accesskey="n" rel="next">TCP Server</a>, Previous: < <dt>UserData</dt> <dd><p>User data </p></dd> +<dt>EnableTransferDelay</dt> +<dd><p>Bool for whether transfer delay is enabled. (Read only) +</p></dd> </dl> </dd></dl> <hr> @@ -5181,7 +5188,7 @@ Previous: <a href="#USBTMC" accesskey="p" rel="prev">USBTMC</a>, Up: <a href="#F <p>Open vxi11 interface. </p> <p><var class="var">ip</var> - the ip address of type String. If omitted defaults to ’127.0.0.1’. -<var class="var">instr</var> - the instrument name of type String. If omitted defaults to ’instr0’. +<var class="var">instr</var> - the instrument name of type String. If omitted defaults to ’inst0’. </p> <p>The vxi11() shall return instance of <var class="var">octave_vxi11</var> class as the result <var class="var">vxi11</var>. </p></dd></dl> diff --git a/doc/instrument-control.info b/doc/instrument-control.info index 37ee563..5b86d8a 100644 --- a/doc/instrument-control.info +++ b/doc/instrument-control.info @@ -1,6 +1,11 @@ This is instrument-control.info, produced by makeinfo version 7.0.3 from instrument-control.texi. +INFO-DIR-SECTION Math +START-INFO-DIR-ENTRY +* Octave Intrument Control: (instrument-control). Instrument Control Toolkit for Octave +END-INFO-DIR-ENTRY + File: instrument-control.info, Node: Top, Next: Installing and loading, Up: (dir) @@ -77,7 +82,7 @@ With the toolkit package already downloaded, and in the current directory when running GNU Octave, the package can be installed using the following command within GNU Octave: - pkg install instrument-control-0.9.2.tar.gz + pkg install instrument-control-0.9.3.tar.gz 1.5 Loading =========== @@ -3398,6 +3403,9 @@ File: instrument-control.info, Node: TCP Client, Next: TCP Server, Prev: TCP name value Timeout Numeric timeout value or -1 to wait forever + EnableTransferDelay + Boolean to enable or disable the nagle algorithm for delay + transfer. UserData User data value. @@ -3433,6 +3441,8 @@ File: instrument-control.info, Node: TCP Client, Next: TCP Server, Prev: TCP Terminator value used for string data (currently not used) UserData User data + EnableTransferDelay + Bool for whether transfer delay is enabled. (Read only) File: instrument-control.info, Node: TCP Server, Next: UDP (Deprecated), Prev: TCP Client, Up: Function Reference @@ -4581,7 +4591,7 @@ File: instrument-control.info, Node: VXI11, Prev: USBTMC, Up: Function Refere IP - the ip address of type String. If omitted defaults to ’127.0.0.1’. INSTR - the instrument name of type String. If - omitted defaults to ’instr0’. + omitted defaults to ’inst0’. The vxi11() shall return instance of OCTAVE_VXI11 class as the result VXI11. @@ -5563,33 +5573,33 @@ Index Tag Table: -Node: Top99 -Node: Installing and loading625 -Node: Basic Usage Overview2734 -Node: Authors3002 -Node: Available Interface3463 -Node: Basic Serial4575 -Node: Basic TCP6931 -Node: Basic UDP9316 -Node: Function Reference11517 -Node: Common Functions11984 -Node: General14409 -Node: GPIB17193 -Node: I2C21776 -Node: Modbus26543 -Node: Parallel33987 -Node: Serial (Deprecated)38352 -Node: Serial Port50559 -Node: SPI60377 -Node: TCP (Deprecated)67197 -Node: TCP Client76067 -Node: TCP Server80982 -Node: UDP (Deprecated)86159 -Node: UDP Port94795 -Node: USBTMC102559 -Node: VXI11105513 -Node: Copying108272 -Node: Index146004 +Node: Top259 +Node: Installing and loading785 +Node: Basic Usage Overview2894 +Node: Authors3162 +Node: Available Interface3623 +Node: Basic Serial4735 +Node: Basic TCP7091 +Node: Basic UDP9476 +Node: Function Reference11677 +Node: Common Functions12144 +Node: General14569 +Node: GPIB17353 +Node: I2C21936 +Node: Modbus26703 +Node: Parallel34147 +Node: Serial (Deprecated)38512 +Node: Serial Port50719 +Node: SPI60537 +Node: TCP (Deprecated)67357 +Node: TCP Client76227 +Node: TCP Server81348 +Node: UDP (Deprecated)86525 +Node: UDP Port95161 +Node: USBTMC102925 +Node: VXI11105879 +Node: Copying108637 +Node: Index146369 End Tag Table diff --git a/doc/instrument-control.pdf b/doc/instrument-control.pdf Binary files differindex 88b4a37..af6a7fa 100644 --- a/doc/instrument-control.pdf +++ b/doc/instrument-control.pdf diff --git a/doc/instrument-control.qch b/doc/instrument-control.qch Binary files differindex a07241b..df8169e 100644 --- a/doc/instrument-control.qch +++ b/doc/instrument-control.qch diff --git a/doc/instrument-control.qhc b/doc/instrument-control.qhc Binary files differindex a523871..8c07f60 100644 --- a/doc/instrument-control.qhc +++ b/doc/instrument-control.qhc diff --git a/doc/instrument-control.texi b/doc/instrument-control.texi index 4c3f6a0..c8d3720 100644 --- a/doc/instrument-control.texi +++ b/doc/instrument-control.texi @@ -63,6 +63,11 @@ To download a copy of the @acronym{GNU} Octave Instrument Control Toolkit, pleas @end titlepage @c %*** End of TITLEPAGE +@dircategory Math +@direntry +* Octave Intrument Control: (instrument-control). Instrument Control Toolkit for Octave +@end direntry + @c %*** Start of BODY @contents @ifnottex diff --git a/doc/mkfuncdocs.py b/doc/mkfuncdocs.py new file mode 100755 index 0000000..2e851ba --- /dev/null +++ b/doc/mkfuncdocs.py @@ -0,0 +1,382 @@ +#!/usr/bin/python3 + +## Copyright 2018-2023 John Donoghue +## +## This program is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see +## <https://www.gnu.org/licenses/>. + +## mkfuncdocs v1.0.7 +## mkfuncdocs.py will attempt to extract the help texts from functions in src +## dirs, extracting only those that are in the specifed INDEX file and output them +## to stdout in texi format +## +## It will extract from both .m and the help text for DEFUN_DLD help in .cc/.cpp +## files. +## +## It attempts to find the help text for each function in a file within the src search +## folders that match in order: [ functionname.m functionname.cc functionname.cpp +## functionname_withoutprefix.cc functionname_withoutprefix.cpp ] +## +## Usage: +## mkfundocs.py options INDEXfile +## Options can be 0 or more of: +## --verbose : Turn on verbose mode +## --src-dir=xxxxx : Add dir xxxxx to the dirs searched for the function file. +## If no directories are provided, it will default to looking in the +## 'inst' directory. +## --ignore=xxxxx : dont attempt to generate help for function xxxxx. +## --funcprefix=xxxxx : remove xxxxx from the function name when searching for matching +## source file. +## --allowscan : if can not find function, attemp to scan .cc,cpp,cxx files for match +## +## --standalone : generate a texinfo file expected to be used with being included in +## another document file. + +import sys +import os +import re +import tempfile +import shutil +import fnmatch +import subprocess +import glob +import calendar; +import time; + +class Group: + name = "Functions" + functions = [] + + def __init__ (self, name=""): + if name: + self.name = name + self.functions = [] + +class Index: + name = "" + groups = [] + +def texify_line(line): + # convert any special chars in a line to texinfo format + # currently just used for group formatting ? + line = line.replace("@", "@@") + line = line.replace("{", "@{") + line = line.replace("}", "@}") + line = line.replace(",", "@comma{}") + return line + +def find_defun_line_in_file(filename, fnname): + linecnt = 0 + + defun_line=re.compile(r"^DEFUN_DLD\s*\(\s*{}".format(fnname)) + with open(filename, 'rt') as f: + for line in f: + if re.match(defun_line, line): + return linecnt + + linecnt = linecnt + 1 + + return -1 + +def read_m_file(filename, skip=0): + help = [] + inhelp = False + havehelp = False; + with open(filename, 'rt') as f: + for line in f: + line = line.lstrip() + if skip > 0: + skip = skip - 1 + elif not havehelp: + if havehelp == False and inhelp == False and line.startswith('##'): + if "texinfo" in line: + inhelp = True + elif inhelp == True: + if not line.startswith('##'): + inhelp = False + havehelp = True + else: + if line.startswith("## @"): + line = line[3:] + else: + line = line[2:] + help.append (line.rstrip()); + + return help + +def read_cc_file(filename, skip=0): + help = [] + inhelp = False + havehelp = False; + with open(filename, 'rt') as f: + for line in f: + line = line.lstrip() + if skip > 0: + skip = skip - 1 + elif not havehelp: + if havehelp == False and inhelp == False: + if "texinfo" in line: + inhelp = True + elif inhelp == True: + line = line.rstrip() + if len(line) > 0 and line[-1] == '\\': + line = line[:-1] + line = line.rstrip() + + line = line.replace("\\n", "\n") + line = line.replace("\\\"", "\"") + + if len(line) > 0 and line[-1] == '\n': + line = line[:-1] + # endif a texinfo line + elif line.endswith('")'): + line = line[:-2] + + if line.startswith('{'): + inhelp = False + havehelp = True + else: + help.append (line); + + return help + +def read_help (filename, skip=0): + help = [] + + if filename[-2:] == ".m": + help = read_m_file(filename, skip) + else: + help = read_cc_file(filename, skip) + + return help + +def read_index (filename, ignore): + index = Index () + + with open(filename, 'rt') as f: + lines = f.read().splitlines() + + #print ("read", lines) + first = True + category = Group() + for l in lines: + if l.startswith("#"): + pass + elif first: + index.name = l; + first = False + elif l.startswith(" "): + l = l.strip() + # may be multiple functions here + funcs = l.split() + for f in funcs: + if f not in ignore: + category.functions.append(f); + else: + # new category name + if len(category.functions) > 0: + index.groups.append(category) + category = Group(l.strip()) + + # left over category ? + if len(category.functions) > 0: + index.groups.append(category) + + return index; + +def find_func_file(fname, paths, prefix, scanfiles=False): + for f in paths: + name = f + "/" + fname + ".m" + if os.path.isfile(name): + return name, 0 + # class constructor ? + name = f + "/@" + fname + "/" + fname + ".m" + if os.path.isfile(name): + return name, 0 + name = f + "/" + fname + ".cc" + name = f + "/" + fname + ".cc" + if os.path.isfile(name): + return name, 0 + name = f + "/" + fname + ".cpp" + if os.path.isfile(name): + return name, 0 + # if have a prefix, remove and try + if prefix and fname.startswith(prefix): + fname = fname[len(prefix):] + name = f + "/" + fname + ".cc" + if os.path.isfile(name): + return name, 0 + name = f + "/" + fname + ".cpp" + if os.path.isfile(name): + return name, 0 + + # if here, we still dont have a file match + # if allowed to scan files, do that + if scanfiles: + #sys.stderr.write("Warning: Scaning for {}\n".format(fname)) + for f in paths: + files = list(f + "/" + a for a in os.listdir(f)) + cc_files = fnmatch.filter(files, "*.cc") + cpp_files = fnmatch.filter(files, "*.cpp") + cxx_files = fnmatch.filter(files, "*.cxx") + + for fn in cc_files + cpp_files + cxx_files: + line = find_defun_line_in_file(fn, fname) + if line >= 0: + #sys.stderr.write("Warning: Found function for {} in {} at {}\n".format(fname, fn, line)) + return fn, line + + return None, -1 + +def display_standalone_header(): + # make a file that doesnt need to be included in a texinfo file to + # be valid + print("@c mkfuncdocs output for a standalone function list") + print("@include macros.texi") + print("@ifnottex") + print("@node Top") + print("@top Function Documentation") + print("Function documentation extracted from texinfo source in octave source files.") + print("@contents") + print("@end ifnottex") + print("@node Function Reference") + print("@chapter Function Reference") + print("@cindex Function Reference") + +def display_standalone_footer(): + print("@bye") + +def display_func(name, ref, help): + print ("@c -----------------------------------------") + print ("@subsection {}".format(name)) + print ("@cindex {}".format(ref)) + for l in help: + print ("{}".format(l)) + +def process (args): + options = { + "verbose": False, + "srcdir": [], + "funcprefix": "", + "ignore": [], + "standalone": False, + "allowscan": False + } + indexfile = "" + + for a in args: + #print ("{}".format(a)) + c=a.split("=") + key=c[0] + + if len(c) > 1: + val=c[1] + else: + val="" + + if key == "--verbose": + options["verbose"] = True; + if key == "--standalone": + options["standalone"] = True; + elif key == "--allowscan": + options["allowscan"] = True; + elif key == "--src-dir": + if val: + options["srcdir"].append(val); + elif key == "--ignore": + if val: + options["ignore"].append(val); + elif key == "--func-prefix": + if val: + options["funcprefix"] = val; + elif val == "": + if indexfile == "": + indexfile = key + + if indexfile == "": + raise Exception("No index filename") + + if len(options["srcdir"]) == 0: + options["srcdir"].append("inst") + + #print "options=", options + if options['standalone']: + display_standalone_header() + + idx = read_index(indexfile, options["ignore"]) + for g in idx.groups: + #print ("************ {}".format(g.name)) + g_name = texify_line(g.name) + print ("@c ---------------------------------------------------") + print ("@node {}".format(g_name)) + print ("@section {}".format(g_name)) + print ("@cindex {}".format(g_name)) + + for f in sorted(g.functions): + print ("@c {} {}".format(g_name, f)) + h = "" + filename = "" + path = "" + if "@" in f: + #print ("class func") + path = f + name = "@" + f + ref = f.split("/")[-1] + filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) + elif "." in f: + parts = f.split('.') + cnt = 0 + path = "" + for p in parts: + if cnt < len(parts)-1: + path = path + "/+" + else: + path = path + "/" + path = path + p + cnt = cnt + 1 + name = f; + ref = parts[-1] + filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) + elif "/" in f: + path = f + name = f + ref = f.split("/")[-1] + filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) + else: + path = f + name = f + ref = f + filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"], options['allowscan']) + + if not filename: + sys.stderr.write("Warning: Cant find source file for {}\n".format(path)) + else: + h = read_help (filename, lineno) + + if h: + display_func (name, ref, h) + + if options['standalone']: + display_standalone_footer() + + +def show_usage(): + print (sys.argv[0], "[options] indexfile") + +if __name__ == "__main__": + if len(sys.argv) > 1: + status = process(sys.argv[1:]) + sys.exit(status) + else: + show_usage() diff --git a/doc/mkqhcp.py b/doc/mkqhcp.py new file mode 100755 index 0000000..2cbee5b --- /dev/null +++ b/doc/mkqhcp.py @@ -0,0 +1,150 @@ +#!/usr/bin/python3 + +## mkqhcp.py +## Version 1.0.3 + +## Copyright 2022-2023 John Donoghue +## +## This program is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see +## <https://www.gnu.org/licenses/>. + +import sys +import os +import re + +def process(name): + with open(name + ".qhcp", 'wt') as f: + f.write ('<?xml version="1.0" encoding="UTF-8"?>\n') + f.write ('<QHelpCollectionProject version="1.0">\n') + f.write (' <docFiles>\n') + f.write (' <generate>\n') + f.write (' <file>\n') + f.write (' <input>{0}.qhp</input>\n'.format(name)) + f.write (' <output>{0}.qch</output>\n'.format(name)) + f.write (' </file>\n') + f.write (' </generate>\n') + f.write (' <register>\n') + f.write (' <file>{0}.qch</file>\n'.format(name)) + f.write (' </register>\n') + f.write (' </docFiles>\n') + f.write ('</QHelpCollectionProject>\n') + + title = name + pat_match = re.compile(r".*<title>(?P<title>[^<]+)</title>.*") + with open(name + ".html", 'rt') as fin: + # find html + for line in fin: + line = line.strip() + e = pat_match.match(line) + if e: + title = e.group("title") + break + + h2_match = re.compile(r'.*<h2 class="chapter"[^>]*>(?P<title>[^<]+)</h2>.*') + h3_match = re.compile(r'.*<h3 class="section"[^>]*>(?P<title>[^<]+)</h3>.*') + h4_match = re.compile(r'.*<h4 class="subsection"[^>]*>(?P<title>[^<]+)</h4>.*') + tag_match1 = re.compile(r'.*<span id="(?P<tag>[^"]+)"[^>]*></span>.*') + #tag_match2 = re.compile(r'.*<div class="[sub]*section" id="(?P<tag>[^"]+)"[^>]*>.*') + tag_match2 = re.compile(r'.*<div class="[sub]*section[^"]*" id="(?P<tag>[^"]+)"[^>]*>.*') + tag_match3 = re.compile(r'.*<div class="chapter-level-extent" id="(?P<tag>[^"]+)"[^>]*>.*') + index_match = re.compile(r'.*<h4 class="subsection"[^>]*>[\d\.\s]*(?P<name>[^<]+)</h4>.*') + + tag = "top" + has_h2 = False + has_h3 = False + + #pat_match = re.compile(r'.*<span id="(?P<tag>[^"])"></span>(?P<title>[.]+)$') + with open(name + ".html", 'rt') as fin: + with open(name + ".qhp", 'wt') as f: + f.write('<?xml version="1.0" encoding="UTF-8"?>\n') + f.write('<QtHelpProject version="1.0">\n') + f.write(' <namespace>octave.community.{}</namespace>\n'.format(name)) + f.write(' <virtualFolder>doc</virtualFolder>\n') + f.write(' <filterSection>\n') + f.write(' <toc>\n') + f.write(' <section title="{} Manual" ref="{}.html">\n'.format(title, name)) + # chapters here + for line in fin: + line = line.strip() + e = tag_match1.match(line) + if not e: + e = tag_match2.match(line) + if not e: + e = tag_match3.match(line) + if e: + tag = e.group("tag") + + e = h2_match.match(line) + if e: + if has_h3: + f.write(' </section>\n') + has_h3 = False + if has_h2: + f.write(' </section>\n') + has_h2 = True + f.write(' <section title="{}" ref="{}.html#{}">\n'.format(e.group("title"), name, tag)) + + e = h3_match.match(line) + if e: + if has_h3: + f.write(' </section>\n') + has_h3 = True + + f.write(' <section title="{}" ref="{}.html#{}">\n'.format(e.group("title"), name, tag)) + + e = h4_match.match(line) + if e: + f.write(' <section title="{}" ref="{}.html#{}"></section>\n'.format(e.group("title"), name, tag)) + + + if has_h3: + f.write(' </section>\n') + if has_h2: + f.write(' </section>\n') + + f.write(' </section>\n') + f.write(' </toc>\n') + f.write(' <keywords>\n') + + fin.seek(0) + for line in fin: + line = line.strip() + e = tag_match1.match(line) + if not e: + e = tag_match2.match(line) + if e: + tag = e.group("tag") + + e = index_match.match(line) + if e: + f.write(' <keyword name="{}" ref="{}.html#{}"></keyword>\n'.format(e.group("name"), name, tag)) + + f.write(' </keywords>\n') + f.write(' <files>\n') + f.write(' <file>{}.html</file>\n'.format(name)) + f.write(' <file>{}.css</file>\n'.format(name)) + f.write(' </files>\n') + f.write(' </filterSection>\n') + f.write('</QtHelpProject>\n') + + +def show_usage(): + print (sys.argv[0], "projname") + +if __name__ == "__main__": + if len(sys.argv) > 1: + status = process(sys.argv[1]) + sys.exit(status) + else: + show_usage() diff --git a/doc/version.texi b/doc/version.texi index 6695363..2ea47a9 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -1,4 +1,4 @@ @c autogenerated from Makefile -@set VERSION 0.9.2 +@set VERSION 0.9.3 @set PACKAGE instrument-control -@set DATE 2024-01-04 +@set DATE 2024-03-31 diff --git a/inst/@octave_modbus/read.m b/inst/@octave_modbus/read.m index a4ffd92..3459b99 100644 --- a/inst/@octave_modbus/read.m +++ b/inst/@octave_modbus/read.m @@ -67,42 +67,32 @@ function data = read (dev, target, address, count, serverid, precision) error ("Expected precision to be a character type"); endif - toread = count; - # precision only used for inputregs and holdingregs switch (precision) case {"int16" "short"} toclass = "int16"; - tosize = 2; - toread = toread * 2; + tosize = 1; case {"uint16" "ushort"} toclass = "uint16"; - tosize = 2; - toread = toread * 2; + tosize = 1; case {"int32" "int"} toclass = "int32"; - tosize = 4; - toread = toread * 4; + tosize = 2; case {"uint32" "uint"} toclass = "uint32"; - tosize = 4; - toread = toread * 4; + tosize = 2; case {"long" "int64"} toclass = "int64"; - toread = toread * 8; - tosize = 8; + tosize = 4; case {"ulong" "uint64"} toclass = "uint64"; - toread = toread * 8; - tosize = 8; + tosize = 4; case {"single" "float" "float32"} toclass = "single"; - tosize = 4; - toread = toread * 4; + tosize = 2; case {"double" "float64"} toclass = "double"; - tosize = 8; - toread = toread * 8; + tosize = 4; otherwise error ("precision not supported"); endswitch @@ -120,8 +110,21 @@ function data = read (dev, target, address, count, serverid, precision) error ("Invalid target type"); endswitch - data = __modbus_read__(dev, target, address, count, serverid); + # number of actual regs to read + toread = count * tosize; + + data = __modbus_read__(dev, target, address, toread, serverid); - # TODO: use precision to combine regs etc + # Check Word Endian settings, swap word order if required + mbwordendian = get(dev,"WordOrder"); # Modbus word endian + [a,b,cowordendian] = computer(); # machine endian + if ( tosize>1 && ( + strcmp(mbwordendian,"big-endian") && strcmp(cowordendian,"L") || ... + strcmp(mbwordendian,"littler-endian") && strcmp(cowordendian,"B") ) ) + # swap word order + data = reshape( flip( reshape( data, tosize, count ) ), 1, toread ) + end + # type conversion + data = typecast( data, toclass ); endfunction diff --git a/inst/@octave_serialport/get.m b/inst/@octave_serialport/get.m index 2db26cf..8b34906 100644 --- a/inst/@octave_serialport/get.m +++ b/inst/@octave_serialport/get.m @@ -46,7 +46,7 @@ function retval = get (serial, property) property = {property}; end - valid = ismember (property, properties); + valid = ismember (tolower(property), tolower(properties)); not_found = {property{!valid}}; if !isempty (not_found) diff --git a/inst/@octave_tcpclient/get.m b/inst/@octave_tcpclient/get.m index 1f4af75..ef7293d 100644 --- a/inst/@octave_tcpclient/get.m +++ b/inst/@octave_tcpclient/get.m @@ -34,7 +34,7 @@ function retval = get (tcpclient, property) properties = {'Name', 'Address', 'Port', ... 'Type', 'Status', 'Timeout', 'UserData', ... 'NumBytesAvailable', 'NumBytesWritten', ... - 'Terminator' }; + 'Terminator', 'EnableTransferDelay' }; if (nargin == 1) property = properties; diff --git a/src/configure b/src/configure index e85e7cb..c9f55a2 100755 --- a/src/configure +++ b/src/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for octave instrument control package 0.9.2. +# Generated by GNU Autoconf 2.71 for octave instrument control package 0.9.3. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -608,8 +608,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='octave instrument control package' PACKAGE_TARNAME='octave-instrument-control-package' -PACKAGE_VERSION='0.9.2' -PACKAGE_STRING='octave instrument control package 0.9.2' +PACKAGE_VERSION='0.9.3' +PACKAGE_STRING='octave instrument control package 0.9.3' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1296,7 +1296,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures octave instrument control package 0.9.2 to adapt to many kinds of systems. +\`configure' configures octave instrument control package 0.9.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1364,7 +1364,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of octave instrument control package 0.9.2:";; + short | recursive ) echo "Configuration of octave instrument control package 0.9.3:";; esac cat <<\_ACEOF @@ -1462,7 +1462,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -octave instrument control package configure 0.9.2 +octave instrument control package configure 0.9.3 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1618,7 +1618,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by octave instrument control package $as_me 0.9.2, which was +It was created by octave instrument control package $as_me 0.9.3, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -5463,7 +5463,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by octave instrument control package $as_me 0.9.2, which was +This file was extended by octave instrument control package $as_me 0.9.3, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5527,7 +5527,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -octave instrument control package config.status 0.9.2 +octave instrument control package config.status 0.9.3 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/src/configure.ac b/src/configure.ac index a43ee57..1ca88e8 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # -### Copyright (C) 2020-2023 John Donoghue <john.donoghue@ieee.org> +### Copyright (C) 2020-2024 John Donoghue <john.donoghue@ieee.org> ### ### This program is free software; you can redistribute it and/or ### modify it under the terms of the GNU General Public License as @@ -18,7 +18,7 @@ ### <http://www.gnu.org/licenses/>. AC_PREREQ([2.69]) -AC_INIT([octave instrument control package],[0.9.2]) +AC_INIT([octave instrument control package],[0.9.3]) AC_CONFIG_HEADERS([config.h]) # Avoid warnings for redefining AH-generated preprocessor symbols of @@ -489,7 +489,7 @@ fi if test $build_vxi11 = yes; then AC_DEFINE([BUILD_VXI11], [], [build VXI11 interface functions]) - AC_SUBST([BUILD_VXI11], [1], [build VXI11 interface functions]) + AC_SUBST([BUILD_VXI11], [1]) fi if test $build_visa = yes; then diff --git a/src/serialport/serialport_class_lin.cc b/src/serialport/serialport_class_lin.cc index ce34aa6..8ad192e 100644 --- a/src/serialport/serialport_class_lin.cc +++ b/src/serialport/serialport_class_lin.cc @@ -86,6 +86,10 @@ octave_serialport::open (const std::string &path) config.c_cc[VMIN] = 0; config.c_cc[VTIME] = 5; + // set an intial baudrate + cfsetospeed (&config, B9600); + cfsetispeed (&config, B9600); + if (tcsetattr (fd, TCSANOW, &config) < 0) { error ("serialport: Failed to set default terminal attributes: %s\n", strerror (errno)); @@ -148,6 +152,10 @@ octave_serialport::read (uint8_t *buf, unsigned int len) // Timeout while in non-blocking mode if (read_retval == 0 && !blocking_read) { + // no waiting + if (config.c_cc[VTIME] == 0) + break; + maxwait -= (double)config.c_cc[VTIME]/10.0; // actual timeout @@ -220,19 +228,19 @@ octave_serialport::set_timeout (double newtimeout) else { blocking_read = false; - if(newtimeout > 10) newtimeout = 5; - if(newtimeout < 1) newtimeout = 1; + if(newtimeout > 5) newtimeout = 5; } - - BITMASK_CLEAR (config.c_lflag, ICANON); // Set non-canonical mode - config.c_cc[VMIN] = 0; - config.c_cc[VTIME] = (unsigned) newtimeout; - - if (tcsetattr (fd, TCSANOW, &config) < 0) + if (config.c_cc[VTIME] != (unsigned char) newtimeout) { - error ("serialport: error setting timeout..."); - return -1; + config.c_cc[VMIN] = 0; + config.c_cc[VTIME] = (unsigned char) newtimeout; + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport: error setting timeout..."); + return -1; + } } return 1; @@ -463,8 +471,8 @@ octave_serialport::set_baudrate (unsigned int baud) return false; } - cfsetispeed (&config, baud_rate); cfsetospeed (&config, baud_rate); + cfsetispeed (&config, baud_rate); if (tcsetattr (fd, TCSANOW, &config) < 0) { @@ -486,7 +494,7 @@ octave_serialport::get_baudrate (void) const int retval = -1; - speed_t baudrate = cfgetispeed (&config); + speed_t baudrate = cfgetospeed (&config); if (baudrate == B0) retval = 0; diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc index a9e64aa..43409b2 100644 --- a/src/tcpclient/__tcpclient_properties__.cc +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -123,6 +123,8 @@ Undocumented internal function.\n\ return octave_value (tcpclient->get_userdata ()); else if (property == "terminator") return get_terminator (tcpclient); + else if (property == "enabletransferdelay") + return octave_value(tcpclient->get_enabletransferdelay ()); else (*current_liboctave_error_handler) ("invalid property name"); } @@ -148,6 +150,8 @@ Undocumented internal function.\n\ return octave_value (tcpclient->flush (args(2).int_value ())); else if (property == "terminator") return set_terminator (tcpclient, args.slice (2, args.length ()-2)); + else if (property == "enabletransferdelay") + (*current_liboctave_error_handler) ("can not set this property"); else (*current_liboctave_error_handler) ("invalid property name"); } diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc index 7a6f9f5..fcd7b2f 100644 --- a/src/tcpclient/tcpclient.cc +++ b/src/tcpclient/tcpclient.cc @@ -43,6 +43,8 @@ Known input properties:\n \ name value\n \ @item Timeout\n \ Numeric timeout value or -1 to wait forever\n \ +@item EnableTransferDelay\n \ +Boolean to enable or disable the nagle algorithm for delay transfer.\n \ @item UserData\n \ User data value.\n \ @end table\n \ @@ -75,6 +77,8 @@ Byte order for data (currently not used)\n \ Terminator value used for string data (currently not used)\n \ @item UserData\n \ User data\n \ +@item EnableTransferDelay\n \ +Bool for whether transfer delay is enabled. (Read only)\n \ @end table \n \ @end deftypefn") { @@ -94,6 +98,7 @@ User data\n \ std::string name = ""; int port = 23; double timeout = -1; + int ndelay = 1; octave_value userdata = Matrix(); // Parse the function arguments @@ -159,6 +164,28 @@ User data\n \ return octave_value (); } } + else if (propname == "enabletransferdelay") + { + if (propval.OV_ISINTEGER () || propval.OV_ISFLOAT ()) + { + ndelay = propval.int_value (); + if (ndelay != 0 && ndelay != 1) + { + error ("enabletranfserdelay should be 0 or 1"); + return octave_value (); + } + } + else if (propval.OV_ISLOGICAL ()) + { + if (! propval.bool_value()) + ndelay = 0; + } + else + { + error ("enabletranfserdelay should be 0 or 1"); + return octave_value (); + } + } else if (propname == "userdata") { userdata = propval; @@ -175,7 +202,7 @@ User data\n \ // Open the interface and connect octave_tcpclient* retval = new octave_tcpclient (); - if (retval->open (address, port) < 0) + if (retval->open (address, port, ndelay) < 0) { return octave_value (); } diff --git a/src/tcpclient/tcpclient_class.cc b/src/tcpclient/tcpclient_class.cc index c758d7e..f30d992 100644 --- a/src/tcpclient/tcpclient_class.cc +++ b/src/tcpclient/tcpclient_class.cc @@ -28,6 +28,7 @@ #include <unistd.h> #include <errno.h> #include <netinet/in.h> +#include <netinet/tcp.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> @@ -107,7 +108,7 @@ lookup_addr (const std::string &ip, sockaddr_in *in) DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_tcpclient, "octave_tcpclient", "octave_tcpclient"); octave_tcpclient::octave_tcpclient (void) -: fieldnames(11), fd (-1), timeout(-1), name("") +: fieldnames(12), fd (-1), timeout(-1), name("") { static bool type_registered = false; @@ -134,6 +135,7 @@ octave_tcpclient::octave_tcpclient (void) fieldnames[8] = "ByteOrder"; fieldnames[9] = "UserData"; fieldnames[10] = "Terminator"; + fieldnames[11] = "EnableTransferDelay"; } bool @@ -235,7 +237,7 @@ octave_tcpclient::subsasgn (const std::string& type, const std::list<octave_valu } int -octave_tcpclient::open (const std::string &address, int port) +octave_tcpclient::open (const std::string &address, int port, int nd) { int sockerr; @@ -274,6 +276,17 @@ octave_tcpclient::open (const std::string &address, int port) return -1; } + ndelay = nd; + +#ifdef __WIN32__ + DWORD sockval = nd; +#else + int sockval = nd; +#endif + socklen_t valsz = sizeof(sockval); + + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&sockval, valsz); + // get local socket info memset (&local_addr, 0, sizeof (local_addr)); socklen_t sz = sizeof (local_addr); diff --git a/src/tcpclient/tcpclient_class.h b/src/tcpclient/tcpclient_class.h index 19fd408..42035e3 100644 --- a/src/tcpclient/tcpclient_class.h +++ b/src/tcpclient/tcpclient_class.h @@ -42,7 +42,7 @@ public: int read (uint8_t *, unsigned int, double); - int open (const std::string &, int); + int open (const std::string &, int, int); int close (void); int get_fd (void) const { return fd; } @@ -134,6 +134,10 @@ public: return outterminator; } + bool get_enabletransferdelay (void) const + { + return ndelay; + } private: bool has_property(const std::string &name) const; @@ -151,6 +155,7 @@ private: unsigned int byteswritten; octave_value interminator; octave_value outterminator; + int ndelay; DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA }; diff --git a/src/udp/udp_class.cc b/src/udp/udp_class.cc index 889bf8a..3757108 100644 --- a/src/udp/udp_class.cc +++ b/src/udp/udp_class.cc @@ -424,7 +424,7 @@ octave_udp::read (uint8_t *buf, unsigned int len, double readtimeout) { read_retval = len - bytes_read; memcpy(&buf[bytes_read], input_buffer, read_retval); - memcpy(&input_buffer[0], &input_buffer[read_retval], buffer_pos-read_retval); + memmove(&input_buffer[0], &input_buffer[read_retval], buffer_pos-read_retval); buffer_pos -= read_retval; } else diff --git a/src/udpport/udpport_class.cc b/src/udpport/udpport_class.cc index d4778a6..1f44d13 100644 --- a/src/udpport/udpport_class.cc +++ b/src/udpport/udpport_class.cc @@ -496,7 +496,7 @@ octave_udpport::read (uint8_t *buf, unsigned int len, double readtimeout, sockad { read_retval = len - bytes_read; memcpy(&buf[bytes_read], input_buffer, read_retval); - memcpy(&input_buffer[0], &input_buffer[read_retval], buffer_pos-read_retval); + memmove(&input_buffer[0], &input_buffer[read_retval], buffer_pos-read_retval); buffer_pos -= read_retval; } diff --git a/src/vxi11/Makefile.in b/src/vxi11/Makefile.in index 93bc6a1..ec9ff2f 100644 --- a/src/vxi11/Makefile.in +++ b/src/vxi11/Makefile.in @@ -13,7 +13,7 @@ BUILD_VXI11 = @BUILD_VXI11@ RPC_GENERATED_FILES := vxi11.h vxi11_clnt.c vxi11_xdr.c -ifneq ($(BUILD_VXI11),1) +ifneq (X$(BUILD_VXI11),X1) VXI = VXCLASS = else @@ -34,6 +34,10 @@ include ../common.mk extraclean: distclean rm -f $(RPC_GENERATED_FILES) +ifeq (X$(BUILD_VXI11),X1) prebuild: $(RPC_GENERATED_FILES) +else +prebuild: +endif .PHONY: prebuild extraclean diff --git a/src/vxi11/vxi11.cc b/src/vxi11/vxi11.cc index 5febf07..26e3dd2 100644 --- a/src/vxi11/vxi11.cc +++ b/src/vxi11/vxi11.cc @@ -36,7 +36,7 @@ DEFUN_DLD (vxi11, args, nargout, Open vxi11 interface.\n \ \n\ @var{ip} - the ip address of type String. If omitted defaults to '127.0.0.1'.\n \ -@var{instr} - the instrument name of type String. If omitted defaults to 'instr0'.\n \ +@var{instr} - the instrument name of type String. If omitted defaults to 'inst0'.\n \ \n\ The vxi11() shall return instance of @var{octave_vxi11} class as the result @var{vxi11}.\n \ @end deftypefn") @@ -54,7 +54,7 @@ The vxi11() shall return instance of @var{octave_vxi11} class as the result @var // Default values string path ("127.0.0.1"); - string device ("instr0"); + string device ("inst0"); // Parse the function arguments if (args.length () > 0) |