From 54dd6906ae6b06df1e6f225c58e800f024cbdbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sat, 27 Feb 2021 06:18:49 -0300 Subject: Import octave-instrument-control_0.7.0.orig.tar.gz [dgit import orig octave-instrument-control_0.7.0.orig.tar.gz] --- COPYING | 101 + DESCRIPTION | 11 + INDEX | 175 + Makefile | 280 ++ NEWS | 307 ++ README.md | 53 + doc/functions.texi | 3119 +++++++++++++ doc/gpl.texi | 718 +++ doc/instrument-control.info | 4950 +++++++++++++++++++++ doc/instrument-control.pdf | Bin 0 -> 341355 bytes doc/instrument-control.texi | 476 ++ doc/macros.texi | 117 + inst/@octave_gpib/fclose.m | 26 + inst/@octave_gpib/fopen.m | 26 + inst/@octave_gpib/fprintf.m | 65 + inst/@octave_gpib/fread.m | 106 + inst/@octave_gpib/fscanf.m | 64 + inst/@octave_gpib/fwrite.m | 85 + inst/@octave_i2c/fclose.m | 26 + inst/@octave_i2c/fopen.m | 27 + inst/@octave_i2c/fread.m | 108 + inst/@octave_i2c/fwrite.m | 68 + inst/@octave_i2c/get.m | 70 + inst/@octave_i2c/set.m | 85 + inst/@octave_parallel/fclose.m | 28 + inst/@octave_parallel/fopen.m | 27 + inst/@octave_parallel/fread.m | 106 + inst/@octave_parallel/fwrite.m | 68 + inst/@octave_serial/fclose.m | 29 + inst/@octave_serial/flushinput.m | 31 + inst/@octave_serial/flushoutput.m | 31 + inst/@octave_serial/fopen.m | 27 + inst/@octave_serial/fprintf.m | 50 + inst/@octave_serial/fread.m | 108 + inst/@octave_serial/fwrite.m | 68 + inst/@octave_serial/get.m | 72 + inst/@octave_serial/serialbreak.m | 41 + inst/@octave_serial/set.m | 111 + inst/@octave_serial/srl_baudrate.m | 46 + inst/@octave_serial/srl_bytesize.m | 47 + inst/@octave_serial/srl_close.m | 38 + inst/@octave_serial/srl_flush.m | 51 + inst/@octave_serial/srl_parity.m | 47 + inst/@octave_serial/srl_stopbits.m | 44 + inst/@octave_serial/srl_timeout.m | 45 + inst/@octave_serialport/configureTerminator.m | 47 + inst/@octave_serialport/flush.m | 49 + inst/@octave_serialport/fprintf.m | 50 + inst/@octave_serialport/fread.m | 51 + inst/@octave_serialport/fwrite.m | 40 + inst/@octave_serialport/get.m | 70 + inst/@octave_serialport/getpinstatus.m | 33 + inst/@octave_serialport/read.m | 107 + inst/@octave_serialport/serialbreak.m | 41 + inst/@octave_serialport/set.m | 110 + inst/@octave_serialport/setDTR.m | 39 + inst/@octave_serialport/setRTS.m | 39 + inst/@octave_serialport/write.m | 68 + inst/@octave_spi/fclose.m | 23 + inst/@octave_spi/fopen.m | 27 + inst/@octave_spi/fread.m | 108 + inst/@octave_spi/fwrite.m | 68 + inst/@octave_spi/get.m | 91 + inst/@octave_spi/read.m | 38 + inst/@octave_spi/set.m | 91 + inst/@octave_spi/write.m | 36 + inst/@octave_spi/writeAndRead.m | 37 + inst/@octave_tcp/fclose.m | 26 + inst/@octave_tcp/flush.m | 49 + inst/@octave_tcp/flushinput.m | 31 + inst/@octave_tcp/flushoutput.m | 31 + inst/@octave_tcp/fopen.m | 27 + inst/@octave_tcp/fprintf.m | 50 + inst/@octave_tcp/fread.m | 108 + inst/@octave_tcp/fwrite.m | 68 + inst/@octave_tcp/get.m | 70 + inst/@octave_tcp/read.m | 83 + inst/@octave_tcp/set.m | 89 + inst/@octave_tcp/write.m | 65 + inst/@octave_tcpclient/configureTerminator.m | 47 + inst/@octave_tcpclient/flush.m | 49 + inst/@octave_tcpclient/get.m | 70 + inst/@octave_tcpclient/read.m | 90 + inst/@octave_tcpclient/set.m | 85 + inst/@octave_tcpclient/write.m | 67 + inst/@octave_udp/fclose.m | 23 + inst/@octave_udp/flush.m | 49 + inst/@octave_udp/flushinput.m | 31 + inst/@octave_udp/flushoutput.m | 31 + inst/@octave_udp/fopen.m | 26 + inst/@octave_udp/fprintf.m | 49 + inst/@octave_udp/fread.m | 108 + inst/@octave_udp/fwrite.m | 68 + inst/@octave_udp/get.m | 71 + inst/@octave_udp/read.m | 83 + inst/@octave_udp/set.m | 92 + inst/@octave_udp/write.m | 94 + inst/@octave_udpport/configureMulticast.m | 49 + inst/@octave_udpport/configureTerminator.m | 47 + inst/@octave_udpport/flush.m | 49 + inst/@octave_udpport/fprintf.m | 49 + inst/@octave_udpport/fread.m | 108 + inst/@octave_udpport/fwrite.m | 67 + inst/@octave_udpport/get.m | 72 + inst/@octave_udpport/read.m | 90 + inst/@octave_udpport/set.m | 88 + inst/@octave_udpport/write.m | 90 + inst/@octave_usbtmc/fclose.m | 28 + inst/@octave_usbtmc/fopen.m | 26 + inst/@octave_usbtmc/fread.m | 108 + inst/@octave_usbtmc/fwrite.m | 68 + inst/@octave_vxi11/fclose.m | 26 + inst/@octave_vxi11/fopen.m | 26 + inst/@octave_vxi11/fread.m | 108 + inst/@octave_vxi11/fwrite.m | 68 + inst/__instrument_control__.m | 78 + inst/clrdevice.m | 37 + inst/flushinput.m | 78 + inst/flushoutput.m | 72 + inst/instrhelp.m | 56 + inst/instrhwinfo.m | 157 + inst/seriallist.m | 39 + inst/serialportlist.m | 64 + inst/spoll.m | 65 + inst/tcpip.m | 78 + inst/trigger.m | 37 + inst/udp_demo.m | 87 + src/Makefile.in | 55 + src/aclocal.m4 | 359 ++ src/bootstrap | 9 + src/common.mk | 44 + src/common.mk.in | 44 + src/config.h.in | 158 + src/configure | 5779 +++++++++++++++++++++++++ src/configure.ac | 439 ++ src/gpib/Makefile.in | 6 + src/gpib/__gpib_clrdevice__.cc | 59 + src/gpib/__gpib_pkg_lock__.cc | 51 + src/gpib/__gpib_spoll__.cc | 68 + src/gpib/__gpib_trigger__.cc | 60 + src/gpib/gpib.cc | 121 + src/gpib/gpib_class.cc | 406 ++ src/gpib/gpib_class.h | 78 + src/gpib/gpib_close.cc | 57 + src/gpib/gpib_read.cc | 98 + src/gpib/gpib_timeout.cc | 76 + src/gpib/gpib_write.cc | 88 + src/hwinfo/Makefile.in | 7 + src/hwinfo/__instr_hwinfo__.cc | 86 + src/i2c/Makefile.in | 6 + src/i2c/__i2c_pkg_lock__.cc | 51 + src/i2c/__i2c_properties__.cc | 78 + src/i2c/i2c.cc | 125 + src/i2c/i2c_addr.cc | 78 + src/i2c/i2c_class.cc | 345 ++ src/i2c/i2c_class.h | 99 + src/i2c/i2c_close.cc | 60 + src/i2c/i2c_read.cc | 97 + src/i2c/i2c_write.cc | 84 + src/m4/octave-forge.m4 | 116 + src/oct-alt-includes.h | 20 + src/parallel/Makefile.in | 6 + src/parallel/__parallel_pkg_lock__.cc | 51 + src/parallel/parallel.cc | 131 + src/parallel/parallel_class.cc | 312 ++ src/parallel/parallel_class.h | 79 + src/parallel/pp_close.cc | 76 + src/parallel/pp_ctrl.cc | 89 + src/parallel/pp_data.cc | 91 + src/parallel/pp_datadir.cc | 95 + src/parallel/pp_stat.cc | 73 + src/resolvehost/Makefile.in | 6 + src/resolvehost/resolvehost.cc | 232 + src/serial/Makefile.in | 11 + src/serial/__serial_pkg_lock__.cc | 51 + src/serial/__srl_properties__.cc | 377 ++ src/serial/serial.cc | 163 + src/serial/serial_class.cc | 117 + src/serial/serial_class.h | 188 + src/serial/serial_class_lin.cc | 724 ++++ src/serial/serial_class_lin.h | 74 + src/serial/serial_class_win32.cc | 608 +++ src/serial/serial_class_win32.h | 76 + src/serial/srl_read.cc | 95 + src/serial/srl_write.cc | 86 + src/serialport/Makefile.in | 11 + src/serialport/__serialport_pkg_lock__.cc | 51 + src/serialport/__srlp_properties__.cc | 441 ++ src/serialport/__srlp_read__.cc | 95 + src/serialport/__srlp_write__.cc | 86 + src/serialport/serialport.cc | 258 ++ src/serialport/serialport_class.cc | 196 + src/serialport/serialport_class.h | 207 + src/serialport/serialport_class_lin.cc | 801 ++++ src/serialport/serialport_class_lin.h | 76 + src/serialport/serialport_class_win32.cc | 667 +++ src/serialport/serialport_class_win32.h | 78 + src/spi/Makefile.in | 6 + src/spi/__spi_pkg_lock__.cc | 51 + src/spi/__spi_properties__.cc | 86 + src/spi/spi.cc | 207 + src/spi/spi_class.cc | 446 ++ src/spi/spi_class.h | 110 + src/spi/spi_close.cc | 60 + src/spi/spi_read.cc | 96 + src/spi/spi_write.cc | 83 + src/spi/spi_writeAndRead.cc | 105 + src/tcp/Makefile.in | 7 + src/tcp/__tcp_pkg_lock__.cc | 51 + src/tcp/__tcp_properties__.cc | 140 + src/tcp/tcp.cc | 228 + src/tcp/tcp_class.cc | 492 +++ src/tcp/tcp_class.h | 118 + src/tcp/tcp_close.cc | 71 + src/tcp/tcp_read.cc | 141 + src/tcp/tcp_timeout.cc | 96 + src/tcp/tcp_write.cc | 107 + src/tcpclient/Makefile.in | 7 + src/tcpclient/__tcpclient_pkg_lock__.cc | 51 + src/tcpclient/__tcpclient_properties__.cc | 193 + src/tcpclient/__tcpclient_read__.cc | 139 + src/tcpclient/__tcpclient_write__.cc | 105 + src/tcpclient/tcpclient.cc | 218 + src/tcpclient/tcpclient_class.cc | 584 +++ src/tcpclient/tcpclient_class.h | 154 + src/udp/Makefile.in | 6 + src/udp/__udp_pkg_lock__.cc | 51 + src/udp/__udp_properties__.cc | 152 + src/udp/udp.cc | 220 + src/udp/udp_class.cc | 561 +++ src/udp/udp_class.h | 125 + src/udp/udp_close.cc | 71 + src/udp/udp_read.cc | 143 + src/udp/udp_timeout.cc | 106 + src/udp/udp_write.cc | 120 + src/udpport/Makefile.in | 6 + src/udpport/__udpport_pkg_lock__.cc | 51 + src/udpport/__udpport_properties__.cc | 223 + src/udpport/__udpport_read__.cc | 157 + src/udpport/__udpport_write__.cc | 141 + src/udpport/udpport.cc | 214 + src/udpport/udpport_class.cc | 847 ++++ src/udpport/udpport_class.h | 186 + src/undef-ah-octave.h | 27 + src/usbtmc/Makefile.in | 6 + src/usbtmc/__usbtmc_pkg_lock__.cc | 51 + src/usbtmc/usbtmc.cc | 92 + src/usbtmc/usbtmc_class.cc | 138 + src/usbtmc/usbtmc_class.h | 66 + src/usbtmc/usbtmc_close.cc | 61 + src/usbtmc/usbtmc_read.cc | 108 + src/usbtmc/usbtmc_write.cc | 94 + src/vxi11/Makefile.in | 39 + src/vxi11/__vxi11_pkg_lock__.cc | 51 + src/vxi11/vxi11.cc | 91 + src/vxi11/vxi11.h | 369 ++ src/vxi11/vxi11.x | 183 + src/vxi11/vxi11_class.cc | 392 ++ src/vxi11/vxi11_class.h | 75 + src/vxi11/vxi11_clnt.c | 206 + src/vxi11/vxi11_close.cc | 56 + src/vxi11/vxi11_read.cc | 96 + src/vxi11/vxi11_svc.c | 316 ++ src/vxi11/vxi11_write.cc | 83 + src/vxi11/vxi11_xdr.c | 504 +++ 265 files changed, 44007 insertions(+) create mode 100644 COPYING create mode 100644 DESCRIPTION create mode 100644 INDEX create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README.md create mode 100644 doc/functions.texi create mode 100644 doc/gpl.texi create mode 100644 doc/instrument-control.info create mode 100644 doc/instrument-control.pdf create mode 100644 doc/instrument-control.texi create mode 100644 doc/macros.texi create mode 100644 inst/@octave_gpib/fclose.m create mode 100644 inst/@octave_gpib/fopen.m create mode 100644 inst/@octave_gpib/fprintf.m create mode 100644 inst/@octave_gpib/fread.m create mode 100644 inst/@octave_gpib/fscanf.m create mode 100644 inst/@octave_gpib/fwrite.m create mode 100644 inst/@octave_i2c/fclose.m create mode 100644 inst/@octave_i2c/fopen.m create mode 100644 inst/@octave_i2c/fread.m create mode 100644 inst/@octave_i2c/fwrite.m create mode 100644 inst/@octave_i2c/get.m create mode 100644 inst/@octave_i2c/set.m create mode 100644 inst/@octave_parallel/fclose.m create mode 100644 inst/@octave_parallel/fopen.m create mode 100644 inst/@octave_parallel/fread.m create mode 100644 inst/@octave_parallel/fwrite.m create mode 100644 inst/@octave_serial/fclose.m create mode 100644 inst/@octave_serial/flushinput.m create mode 100644 inst/@octave_serial/flushoutput.m create mode 100644 inst/@octave_serial/fopen.m create mode 100644 inst/@octave_serial/fprintf.m create mode 100644 inst/@octave_serial/fread.m create mode 100644 inst/@octave_serial/fwrite.m create mode 100644 inst/@octave_serial/get.m create mode 100644 inst/@octave_serial/serialbreak.m create mode 100644 inst/@octave_serial/set.m create mode 100644 inst/@octave_serial/srl_baudrate.m create mode 100644 inst/@octave_serial/srl_bytesize.m create mode 100644 inst/@octave_serial/srl_close.m create mode 100644 inst/@octave_serial/srl_flush.m create mode 100644 inst/@octave_serial/srl_parity.m create mode 100644 inst/@octave_serial/srl_stopbits.m create mode 100644 inst/@octave_serial/srl_timeout.m create mode 100644 inst/@octave_serialport/configureTerminator.m create mode 100644 inst/@octave_serialport/flush.m create mode 100644 inst/@octave_serialport/fprintf.m create mode 100644 inst/@octave_serialport/fread.m create mode 100644 inst/@octave_serialport/fwrite.m create mode 100644 inst/@octave_serialport/get.m create mode 100644 inst/@octave_serialport/getpinstatus.m create mode 100644 inst/@octave_serialport/read.m create mode 100644 inst/@octave_serialport/serialbreak.m create mode 100644 inst/@octave_serialport/set.m create mode 100644 inst/@octave_serialport/setDTR.m create mode 100644 inst/@octave_serialport/setRTS.m create mode 100644 inst/@octave_serialport/write.m create mode 100644 inst/@octave_spi/fclose.m create mode 100644 inst/@octave_spi/fopen.m create mode 100644 inst/@octave_spi/fread.m create mode 100644 inst/@octave_spi/fwrite.m create mode 100644 inst/@octave_spi/get.m create mode 100644 inst/@octave_spi/read.m create mode 100644 inst/@octave_spi/set.m create mode 100644 inst/@octave_spi/write.m create mode 100644 inst/@octave_spi/writeAndRead.m create mode 100644 inst/@octave_tcp/fclose.m create mode 100644 inst/@octave_tcp/flush.m create mode 100644 inst/@octave_tcp/flushinput.m create mode 100644 inst/@octave_tcp/flushoutput.m create mode 100644 inst/@octave_tcp/fopen.m create mode 100644 inst/@octave_tcp/fprintf.m create mode 100644 inst/@octave_tcp/fread.m create mode 100644 inst/@octave_tcp/fwrite.m create mode 100644 inst/@octave_tcp/get.m create mode 100644 inst/@octave_tcp/read.m create mode 100644 inst/@octave_tcp/set.m create mode 100644 inst/@octave_tcp/write.m create mode 100644 inst/@octave_tcpclient/configureTerminator.m create mode 100644 inst/@octave_tcpclient/flush.m create mode 100644 inst/@octave_tcpclient/get.m create mode 100644 inst/@octave_tcpclient/read.m create mode 100644 inst/@octave_tcpclient/set.m create mode 100644 inst/@octave_tcpclient/write.m create mode 100644 inst/@octave_udp/fclose.m create mode 100644 inst/@octave_udp/flush.m create mode 100644 inst/@octave_udp/flushinput.m create mode 100644 inst/@octave_udp/flushoutput.m create mode 100644 inst/@octave_udp/fopen.m create mode 100644 inst/@octave_udp/fprintf.m create mode 100644 inst/@octave_udp/fread.m create mode 100644 inst/@octave_udp/fwrite.m create mode 100644 inst/@octave_udp/get.m create mode 100644 inst/@octave_udp/read.m create mode 100644 inst/@octave_udp/set.m create mode 100644 inst/@octave_udp/write.m create mode 100644 inst/@octave_udpport/configureMulticast.m create mode 100644 inst/@octave_udpport/configureTerminator.m create mode 100644 inst/@octave_udpport/flush.m create mode 100644 inst/@octave_udpport/fprintf.m create mode 100644 inst/@octave_udpport/fread.m create mode 100644 inst/@octave_udpport/fwrite.m create mode 100644 inst/@octave_udpport/get.m create mode 100644 inst/@octave_udpport/read.m create mode 100644 inst/@octave_udpport/set.m create mode 100644 inst/@octave_udpport/write.m create mode 100644 inst/@octave_usbtmc/fclose.m create mode 100644 inst/@octave_usbtmc/fopen.m create mode 100644 inst/@octave_usbtmc/fread.m create mode 100644 inst/@octave_usbtmc/fwrite.m create mode 100644 inst/@octave_vxi11/fclose.m create mode 100644 inst/@octave_vxi11/fopen.m create mode 100644 inst/@octave_vxi11/fread.m create mode 100644 inst/@octave_vxi11/fwrite.m create mode 100644 inst/__instrument_control__.m create mode 100644 inst/clrdevice.m create mode 100644 inst/flushinput.m create mode 100644 inst/flushoutput.m create mode 100644 inst/instrhelp.m create mode 100644 inst/instrhwinfo.m create mode 100644 inst/seriallist.m create mode 100644 inst/serialportlist.m create mode 100644 inst/spoll.m create mode 100644 inst/tcpip.m create mode 100644 inst/trigger.m create mode 100644 inst/udp_demo.m create mode 100644 src/Makefile.in create mode 100644 src/aclocal.m4 create mode 100755 src/bootstrap create mode 100644 src/common.mk create mode 100644 src/common.mk.in create mode 100644 src/config.h.in create mode 100755 src/configure create mode 100644 src/configure.ac create mode 100644 src/gpib/Makefile.in create mode 100644 src/gpib/__gpib_clrdevice__.cc create mode 100644 src/gpib/__gpib_pkg_lock__.cc create mode 100644 src/gpib/__gpib_spoll__.cc create mode 100644 src/gpib/__gpib_trigger__.cc create mode 100644 src/gpib/gpib.cc create mode 100644 src/gpib/gpib_class.cc create mode 100644 src/gpib/gpib_class.h create mode 100644 src/gpib/gpib_close.cc create mode 100644 src/gpib/gpib_read.cc create mode 100644 src/gpib/gpib_timeout.cc create mode 100644 src/gpib/gpib_write.cc create mode 100644 src/hwinfo/Makefile.in create mode 100644 src/hwinfo/__instr_hwinfo__.cc create mode 100644 src/i2c/Makefile.in create mode 100644 src/i2c/__i2c_pkg_lock__.cc create mode 100644 src/i2c/__i2c_properties__.cc create mode 100644 src/i2c/i2c.cc create mode 100644 src/i2c/i2c_addr.cc create mode 100644 src/i2c/i2c_class.cc create mode 100644 src/i2c/i2c_class.h create mode 100644 src/i2c/i2c_close.cc create mode 100644 src/i2c/i2c_read.cc create mode 100644 src/i2c/i2c_write.cc create mode 100644 src/m4/octave-forge.m4 create mode 100644 src/oct-alt-includes.h create mode 100644 src/parallel/Makefile.in create mode 100644 src/parallel/__parallel_pkg_lock__.cc create mode 100644 src/parallel/parallel.cc create mode 100644 src/parallel/parallel_class.cc create mode 100644 src/parallel/parallel_class.h create mode 100644 src/parallel/pp_close.cc create mode 100644 src/parallel/pp_ctrl.cc create mode 100644 src/parallel/pp_data.cc create mode 100644 src/parallel/pp_datadir.cc create mode 100644 src/parallel/pp_stat.cc create mode 100644 src/resolvehost/Makefile.in create mode 100644 src/resolvehost/resolvehost.cc create mode 100644 src/serial/Makefile.in create mode 100644 src/serial/__serial_pkg_lock__.cc create mode 100644 src/serial/__srl_properties__.cc create mode 100644 src/serial/serial.cc create mode 100644 src/serial/serial_class.cc create mode 100644 src/serial/serial_class.h create mode 100644 src/serial/serial_class_lin.cc create mode 100644 src/serial/serial_class_lin.h create mode 100644 src/serial/serial_class_win32.cc create mode 100644 src/serial/serial_class_win32.h create mode 100644 src/serial/srl_read.cc create mode 100644 src/serial/srl_write.cc create mode 100644 src/serialport/Makefile.in create mode 100644 src/serialport/__serialport_pkg_lock__.cc create mode 100644 src/serialport/__srlp_properties__.cc create mode 100644 src/serialport/__srlp_read__.cc create mode 100644 src/serialport/__srlp_write__.cc create mode 100644 src/serialport/serialport.cc create mode 100644 src/serialport/serialport_class.cc create mode 100644 src/serialport/serialport_class.h create mode 100644 src/serialport/serialport_class_lin.cc create mode 100644 src/serialport/serialport_class_lin.h create mode 100644 src/serialport/serialport_class_win32.cc create mode 100644 src/serialport/serialport_class_win32.h create mode 100644 src/spi/Makefile.in create mode 100644 src/spi/__spi_pkg_lock__.cc create mode 100644 src/spi/__spi_properties__.cc create mode 100644 src/spi/spi.cc create mode 100644 src/spi/spi_class.cc create mode 100644 src/spi/spi_class.h create mode 100644 src/spi/spi_close.cc create mode 100644 src/spi/spi_read.cc create mode 100644 src/spi/spi_write.cc create mode 100644 src/spi/spi_writeAndRead.cc create mode 100644 src/tcp/Makefile.in create mode 100644 src/tcp/__tcp_pkg_lock__.cc create mode 100644 src/tcp/__tcp_properties__.cc create mode 100644 src/tcp/tcp.cc create mode 100644 src/tcp/tcp_class.cc create mode 100644 src/tcp/tcp_class.h create mode 100644 src/tcp/tcp_close.cc create mode 100644 src/tcp/tcp_read.cc create mode 100644 src/tcp/tcp_timeout.cc create mode 100644 src/tcp/tcp_write.cc create mode 100644 src/tcpclient/Makefile.in create mode 100644 src/tcpclient/__tcpclient_pkg_lock__.cc create mode 100644 src/tcpclient/__tcpclient_properties__.cc create mode 100644 src/tcpclient/__tcpclient_read__.cc create mode 100644 src/tcpclient/__tcpclient_write__.cc create mode 100644 src/tcpclient/tcpclient.cc create mode 100644 src/tcpclient/tcpclient_class.cc create mode 100644 src/tcpclient/tcpclient_class.h create mode 100644 src/udp/Makefile.in create mode 100644 src/udp/__udp_pkg_lock__.cc create mode 100644 src/udp/__udp_properties__.cc create mode 100644 src/udp/udp.cc create mode 100644 src/udp/udp_class.cc create mode 100644 src/udp/udp_class.h create mode 100644 src/udp/udp_close.cc create mode 100644 src/udp/udp_read.cc create mode 100644 src/udp/udp_timeout.cc create mode 100644 src/udp/udp_write.cc create mode 100644 src/udpport/Makefile.in create mode 100644 src/udpport/__udpport_pkg_lock__.cc create mode 100644 src/udpport/__udpport_properties__.cc create mode 100644 src/udpport/__udpport_read__.cc create mode 100644 src/udpport/__udpport_write__.cc create mode 100644 src/udpport/udpport.cc create mode 100644 src/udpport/udpport_class.cc create mode 100644 src/udpport/udpport_class.h create mode 100644 src/undef-ah-octave.h create mode 100644 src/usbtmc/Makefile.in create mode 100644 src/usbtmc/__usbtmc_pkg_lock__.cc create mode 100644 src/usbtmc/usbtmc.cc create mode 100644 src/usbtmc/usbtmc_class.cc create mode 100644 src/usbtmc/usbtmc_class.h create mode 100644 src/usbtmc/usbtmc_close.cc create mode 100644 src/usbtmc/usbtmc_read.cc create mode 100644 src/usbtmc/usbtmc_write.cc create mode 100644 src/vxi11/Makefile.in create mode 100644 src/vxi11/__vxi11_pkg_lock__.cc create mode 100644 src/vxi11/vxi11.cc create mode 100644 src/vxi11/vxi11.h create mode 100644 src/vxi11/vxi11.x create mode 100644 src/vxi11/vxi11_class.cc create mode 100644 src/vxi11/vxi11_class.h create mode 100644 src/vxi11/vxi11_clnt.c create mode 100644 src/vxi11/vxi11_close.cc create mode 100644 src/vxi11/vxi11_read.cc create mode 100644 src/vxi11/vxi11_svc.c create mode 100644 src/vxi11/vxi11_write.cc create mode 100644 src/vxi11/vxi11_xdr.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..6f3b0e1 --- /dev/null +++ b/COPYING @@ -0,0 +1,101 @@ +devel/testtcp.m GPLv3+ +inst/clrdevice.m GPLv3+ +inst/instrhwinfo.m GPLv3+ +inst/@octave_gpib/fclose.m GPLv3+ +inst/@octave_gpib/fopen.m GPLv3+ +inst/@octave_gpib/fprintf.m GPLv3+ +inst/@octave_gpib/fscanf.m GPLv3+ +inst/@octave_gpib/fwrite.m GPLv3+ +inst/@octave_i2c/fclose.m GPLv3+ +inst/@octave_i2c/fopen.m GPLv3+ +inst/@octave_serial/fclose.m GPLv3+ +inst/@octave_serial/fopen.m GPLv3+ +inst/@octave_serial/get.m GPLv3+ +inst/@octave_serial/set.m GPLv3+ +inst/@octave_serial/srl_baudrate.m GPLv3+ +inst/@octave_serial/srl_bytesize.m GPLv3+ +inst/@octave_serial/srl_close.m GPLv3+ +inst/@octave_serial/srl_flush.m GPLv3+ +inst/@octave_serial/srl_parity.m GPLv3+ +inst/@octave_serial/srl_stopbits.m GPLv3+ +inst/@octave_serial/srl_timeout.m GPLv3+ +inst/@octave_tcpip/fclose.m GPLv3+ +inst/@octave_tcpip/fopen.m GPLv3+ +inst/@octave_udp/fclose.m GPLv3+ +inst/@octave_udp/fopen.m GPLv3+ +inst/@octave_udp/fprintf.m GPLv3+ +inst/@octave_udp/fread.m GPLv3+ +inst/@octave_udp/fwrite.m GPLv3+ +inst/@octave_udp/get.m GPLv3+ +inst/@octave_udp/set.m GPLv3+ +inst/@octave_usbtmc/fclose.m GPLv3+ +inst/@octave_usbtmc/fopen.m GPLv3+ +inst/@octave_vxi11/fclose.m GPLv3+ +inst/@octave_vxi11/fopen.m GPLv3+ +inst/spoll.m GPLv3+ +inst/trigger.m GPLv3+ +inst/udp_demo.m GPLv3+ +src/gpib/gpib.cc GPLv3+ +src/gpib/gpib_class.cc GPLv3+ +src/gpib/gpib_class.h GPLv3+ +src/gpib/gpib_close.cc GPLv3+ +src/gpib/__gpib_clrdevice__.cc GPLv3+ +src/gpib/gpib_read.cc GPLv3+ +src/gpib/__gpib_spoll__.cc GPLv3+ +src/gpib/gpib_timeout.cc GPLv3+ +src/gpib/__gpib_trigger__.cc GPLv3+ +src/gpib/gpib_write.cc GPLv3+ +src/i2c/i2c_addr.cc GPLv3+ +src/i2c/i2c.cc GPLv3+ +src/i2c/i2c_class.cc GPLv3+ +src/i2c/i2c_class.h GPLv3+ +src/i2c/i2c_close.cc GPLv3+ +src/i2c/i2c_read.cc GPLv3+ +src/i2c/i2c_write.cc GPLv3+ +src/parallel/parallel.cc GPLv3+ +src/parallel/parallel_class.cc GPLv3+ +src/parallel/parallel_class.h GPLv3+ +src/parallel/pp_close.cc GPLv3+ +src/parallel/pp_ctrl.cc GPLv3+ +src/parallel/pp_data.cc GPLv3+ +src/parallel/pp_datadir.cc GPLv3+ +src/parallel/pp_stat.cc GPLv3+ +src/resolvehost/resolvehost.cc GPLv3+ +src/serial/serial.cc GPLv3+ +src/serial/serial_class.h GPLv3+ +src/serial/serial_class_lin.cc GPLv3+ +src/serial/serial_class_lin.h GPLv3+ +src/serial/serial_class_win32.cc GPLv3+ +src/serial/serial_class_win32.h GPLv3+ +src/serial/__srl_properties__.cc GPLv3+ +src/serial/srl_read.cc GPLv3+ +src/serial/srl_write.cc GPLv3+ +src/octave-wrappers.h.in GPLv3+ +src/tcp/tcp.cc GPLv3+ +src/tcp/tcp_class.cc GPLv3+ +src/tcp/tcp_class.h GPLv3+ +src/tcp/tcp_close.cc GPLv3+ +src/tcp/tcp_read.cc GPLv3+ +src/tcp/tcp_timeout.cc GPLv3+ +src/tcp/tcp_write.cc GPLv3+ +src/udp/__udp_properties__.cc GPLv3+ +src/udp/udp.cc GPLv3+ +src/udp/udp_class.cc GPLv3+ +src/udp/udp_class.h GPLv3+ +src/udp/udp_close.cc GPLv3+ +src/udp/udp_read.cc GPLv3+ +src/udp/udp_timeout.cc GPLv3+ +src/udp/udp_write.cc GPLv3+ +src/usbtmc/usbtmc.cc GPLv3+ +src/usbtmc/usbtmc_class.cc GPLv3+ +src/usbtmc/usbtmc_class.h GPLv3+ +src/usbtmc/usbtmc_close.cc GPLv3+ +src/usbtmc/usbtmc_read.cc GPLv3+ +src/usbtmc/usbtmc_write.cc GPLv3+ +src/vxi11/vxi11.cc GPLv3+ +src/vxi11/vxi11_class.cc GPLv3+ +src/vxi11/vxi11_class.h GPLv3+ +src/vxi11/vxi11_close.cc GPLv3+ +src/vxi11/vxi11_read.cc GPLv3+ +src/vxi11/vxi11_write.cc GPLv3+ +src/vxi11/vxi11.x public domain diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..7bb5853 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,11 @@ +Name: instrument-control +Version: 0.7.0 +Date: 2021-02-22 +Author: Andrius Sutas , Stefan Mahr , John Donoghue +Maintainer: Stefan Mahr , John Donoghue +Title: Instrument Control +Description: Low level I/O functions for serial, i2c, spi, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces. +Categories: instrument-control +Depends: octave (>= 3.8.0) +Autoload: no +License: GPLv3+ diff --git a/INDEX b/INDEX new file mode 100644 index 0000000..ed4deaa --- /dev/null +++ b/INDEX @@ -0,0 +1,175 @@ +instrument-control >> Low level I/O functions +Common Functions + flushinput + flushoutput +General + instrhelp + instrhwinfo + resolvehost +GPIB + clrdevice + gpib + gpib_read + gpib_write + gpib_timeout + gpib_close + spoll + trigger + @octave_gpib/fclose + @octave_gpib/fopen + @octave_gpib/fprintf + @octave_gpib/fread + @octave_gpib/fscanf + @octave_gpib/fwrite +I2C + i2c + i2c_addr + i2c_close + i2c_read + i2c_write + @octave_i2c/fclose + @octave_i2c/fopen + @octave_i2c/fread + @octave_i2c/fwrite + @octave_i2c/get + @octave_i2c/set +Parallel + parallel + pp_close + pp_ctrl + pp_data + pp_datadir + pp_stat + @octave_parallel/fclose + @octave_parallel/fopen + @octave_parallel/fread + @octave_parallel/fwrite +Serial (Depreciated) + serial + seriallist + srl_read + srl_write + @octave_serial/fopen + @octave_serial/fclose + @octave_serial/flushinput + @octave_serial/flushoutput + @octave_serial/fprintf + @octave_serial/fread + @octave_serial/fwrite + @octave_serial/get + @octave_serial/serialbreak + @octave_serial/set + @octave_serial/srl_baudrate + @octave_serial/srl_bytesize + @octave_serial/srl_close + @octave_serial/srl_flush + @octave_serial/srl_parity + @octave_serial/srl_stopbits + @octave_serial/srl_timeout +Serial Port + serialport + serialportlist + @octave_serialport/configureTerminator + @octave_serialport/flush + @octave_serialport/fprintf + @octave_serialport/fread + @octave_serialport/fwrite + @octave_serialport/get + @octave_serialport/getpinstatus + @octave_serialport/read + @octave_serialport/serialbreak + @octave_serialport/set + @octave_serialport/setDTR + @octave_serialport/setRTS + @octave_serialport/write +SPI + spi + spi_close + spi_read + spi_write + spi_writeAndRead + @octave_spi/fclose + @octave_spi/fopen + @octave_spi/fread + @octave_spi/fwrite + @octave_spi/get + @octave_spi/read + @octave_spi/set + @octave_spi/write + @octave_spi/writeAndRead +TCP (Depreciated) + tcp + tcp_close + tcp_read + tcp_write + tcp_timeout + tcpip + @octave_tcp/fclose + @octave_tcp/flush + @octave_tcp/flushinput + @octave_tcp/flushoutput + @octave_tcp/fopen + @octave_tcp/fprintf + @octave_tcp/fread + @octave_tcp/fwrite + @octave_tcp/get + @octave_tcp/read + @octave_tcp/set + @octave_tcp/write +TCP Client + tcpclient + @octave_tcpclient/configureTerminator + @octave_tcpclient/flush + @octave_tcpclient/get + @octave_tcpclient/read + @octave_tcpclient/set + @octave_tcpclient/write +UDP (Depreciated) + udp + udp_close + udp_demo + udp_read + udp_timeout + udp_write + @octave_udp/fclose + @octave_udp/flush + @octave_udp/flushinput + @octave_udp/flushoutput + @octave_udp/fopen + @octave_udp/fprintf + @octave_udp/fread + @octave_udp/fwrite + @octave_udp/get + @octave_udp/read + @octave_udp/set + @octave_udp/write +UDP Port + udpport + @octave_udpport/configureMulticast + @octave_udpport/configureTerminator + @octave_udpport/flush + @octave_udpport/fread + @octave_udpport/fwrite + @octave_udpport/fprintf + @octave_udpport/get + @octave_udpport/read + @octave_udpport/set + @octave_udpport/write +USBTMC + usbtmc + usbtmc_read + usbtmc_write + usbtmc_close + @octave_usbtmc/fclose + @octave_usbtmc/fopen + @octave_usbtmc/fread + @octave_usbtmc/fwrite +VXI11 + vxi11 + vxi11_close + vxi11_read + vxi11_write + @octave_vxi11/fclose + @octave_vxi11/fopen + @octave_vxi11/fread + @octave_vxi11/fwrite diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..274123e --- /dev/null +++ b/Makefile @@ -0,0 +1,280 @@ +## Copyright 2015-2016 Carnë Draug +## Copyright 2015-2016 Oliver Heimlich +## Copyright 2017 Julien Bect +## Copyright 2017 Olaf Till +## Copyright 2018-2020 John Donoghue +## +## Copying and distribution of this file, with or without modification, +## are permitted in any medium without royalty provided the copyright +## notice and this notice are preserved. This file is offered as-is, +## without any warranty. + +TOPDIR := $(shell pwd) + +## Some basic tools (can be overriden using environment variables) +SED ?= sed +TAR ?= tar +GREP ?= grep +CUT ?= cut +TR ?= tr +TEXI2PDF ?= texi2pdf -q + +## Note the use of ':=' (immediate set) and not just '=' (lazy set). +## http://stackoverflow.com/a/448939/1609556 +package := $(shell $(GREP) "^Name: " DESCRIPTION | $(CUT) -f2 -d" " | \ +$(TR) '[:upper:]' '[:lower:]') +version := $(shell $(GREP) "^Version: " DESCRIPTION | $(CUT) -f2 -d" ") + +## These are the paths that will be created for the releases. +target_dir := target +release_dir := $(target_dir)/$(package)-$(version) +release_tarball := $(target_dir)/$(package)-$(version).tar.gz +html_dir := $(target_dir)/$(package)-html +html_tarball := $(target_dir)/$(package)-html.tar.gz +## Using $(realpath ...) avoids problems with symlinks due to bug +## #50994 in Octaves scripts/pkg/private/install.m. But at least the +## release directory above is needed in the relative form, for 'git +## archive --format=tar --prefix=$(release_dir). +real_target_dir := $(realpath .)/$(target_dir) +installation_dir := $(real_target_dir)/.installation +package_list := $(installation_dir)/.octave_packages +install_stamp := $(installation_dir)/.install_stamp + +## These can be set by environment variables which allow to easily +## test with different Octave versions. +ifndef OCTAVE +OCTAVE := octave +endif +OCTAVE := $(OCTAVE) --no-gui --silent --norc +MKOCTFILE ?= mkoctfile +OCTAVE_CONFIG ?= octave-config + +## Command used to set permissions before creating tarballs +FIX_PERMISSIONS ?= chmod -R a+rX,u+w,go-w,ug-s + +HG := hg +HG_CMD = $(HG) --config alias.$(1)=$(1) --config defaults.$(1)= $(1) +HG_ID := $(shell $(call HG_CMD,identify) --id | sed -e 's/+//' ) +HG_TIMESTAMP := $(firstword $(shell $(call HG_CMD,log) --rev $(HG_ID) --template '{date|hgdate}')) + +TAR_REPRODUCIBLE_OPTIONS := --sort=name --mtime="@$(HG_TIMESTAMP)" --owner=0 --group=0 --numeric-owner +TAR_OPTIONS := --format=ustar $(TAR_REPRODUCIBLE_OPTIONS) + +## Detect which VCS is used +vcs := $(if $(wildcard .hg),hg,$(if $(wildcard .git),git,unknown)) +ifeq ($(vcs),hg) +release_dir_dep := .hg/dirstate +endif +ifeq ($(vcs),git) +release_dir_dep := .git/index +endif + + +## .PHONY indicates targets that are not filenames +## (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html) +.PHONY: help + +## make will display the command before runnning them. Use @command +## to not display it (makes specially sense for echo). +help: + @echo "Targets:" + @echo " dist - Create $(release_tarball) for release." + @echo " html - Create $(html_tarball) for release." + @echo " release - Create both of the above and show md5sums." + @echo " install - Install the package in $(installation_dir), where it is not visible in a normal Octave session." + @echo " check - Execute package tests." + @echo " doctest - Test the help texts with the doctest package." + @echo " run - Run Octave with the package installed in $(installation_dir) in the path." + @echo " clean - Remove everything made with this Makefile." + + +## +## Recipes for release tarballs (package + html) +## + +.PHONY: release dist html clean-tarballs clean-unpacked-release + +## To make a release, build the distribution and html tarballs. +release: dist html + md5sum $(release_tarball) $(html_tarball) + @echo "Upload @ https://sourceforge.net/p/octave/package-releases/new/" + @echo " and note the changeset the release corresponds to" + +## dist and html targets are only PHONY/alias targets to the release +## and html tarballs. +dist: $(release_tarball) +html: $(html_tarball) + +## An implicit rule with a recipe to build the tarballs correctly. +%.tar.gz: % + $(TAR) -cf - $(TAR_OPTIONS) -C "$(target_dir)/" "$(notdir $<)" | gzip -9n > "$@" + +clean-tarballs: + @echo "## Cleaning release tarballs (package + html)..." + -$(RM) $(release_tarball) $(html_tarball) + @echo + +## Create the unpacked package. +## +## Notes: +## * having ".hg/dirstate" (or ".git/index") as a prerequesite means it is +## only rebuilt if we are at a different commit. +## * the variable RM usually defaults to "rm -f" +## * having this recipe separate from the one that makes the tarball +## makes it easy to have packages in alternative formats (such as zip) +## * note that if a commands needs to be run in a specific directory, +## the command to "cd" needs to be on the same line. Each line restores +## the original working directory. +$(release_dir): $(release_dir_dep) + -$(RM) -r "$@" +ifeq (${vcs},hg) + hg archive --exclude ".hg*" --type files "$@" +endif +ifeq (${vcs},git) + git archive --format=tar --prefix="$@/" HEAD | $(TAR) -x + $(RM) "$@/.gitignore" +endif +## Don't fall back to run the supposed necessary contents of +## 'bootstrap' here. Users are better off if they provide +## 'bootstrap'. Administrators, checking build reproducibility, can +## put in the missing 'bootstrap' file if they feel they know its +## necessary contents. +ifneq (,$(wildcard src/bootstrap)) + cd "$@/src" && ./bootstrap && $(RM) -r "autom4te.cache" +endif +## Uncomment this if your src/Makefile.in has these targets for +## pre-building something for the release (e.g. documentation). + cd "$@/src" && ./configure && $(MAKE) prebuild && \ + $(MAKE) distclean && $(RM) Makefile +## + $(MAKE) -C "$@" docs + cd "$@" && $(RM) -rf "devel" && $(RM) -f doc/mkfuncdocs.py + ${FIX_PERMISSIONS} "$@" + +run_in_place = $(OCTAVE) --eval ' pkg ("local_list", "$(package_list)"); ' \ + --eval ' pkg ("load", "$(package)"); ' + +# html_options = --eval 'options = get_html_options ("octave-forge");' +## Uncomment this for package documentation. +html_options = --eval 'options = get_html_options ("octave-forge");' \ + --eval 'options.package_doc = "$(package).texi";' +$(html_dir): $(install_stamp) + $(RM) -r "$@"; + $(run_in_place) \ + --eval ' pkg load generate_html; ' \ + $(html_options) \ + --eval ' generate_package_html ("$(package)", "$@", options); '; + $(FIX_PERMISSIONS) "$@"; + +clean-unpacked-release: + @echo "## Cleaning unpacked release tarballs (package + html)..." + -$(RM) -r $(release_dir) $(html_dir) + @echo + +.PHONY: docs +docs: doc/$(package).pdf doc/$(package).info + +doc/$(package).info: doc/$(package).texi doc/functions.texi + cd doc && $(MAKEINFO) $(package).texi + +doc/$(package).pdf: doc/$(package).texi doc/functions.texi + cd doc && SOURCE_DATE_EPOCH=$(HG_TIMESTAMP) $(TEXI2PDF) $(package).texi + #cd doc && texi2html --split=n --output $(package).html $(package).texi + cd doc && $(RM) -f $(package).aux $(package).cp $(package).cps $(package).fn $(package).fns $(package).log $(package).toc + +doc/functions.texi: + $(eval src_dirs = $(shell cd doc && find ../src -type d -printf '--src-dir=%p ')) + cd doc && ./mkfuncdocs.py --src-dir=../inst/ $(src_dirs) ../INDEX | $(SED) 's/@seealso/@xseealso/g' > functions.texi + +.PHONY: clean-docs +clean-docs: + $(RM) -f doc/$(package).info + $(RM) -f doc/$(package).pdf + $(RM) -f doc/functions.texi + +## +## Recipes for installing the package. +## + +.PHONY: install clean-install + +octave_install_commands = \ +' llist_path = pkg ("local_list"); \ + mkdir ("$(installation_dir)"); \ + load (llist_path); \ + local_packages(cellfun (@ (x) strcmp ("$(package)", x.name), local_packages)) = []; \ + save ("$(package_list)", "local_packages"); \ + pkg ("local_list", "$(package_list)"); \ + pkg ("prefix", "$(installation_dir)", "$(installation_dir)"); \ + pkg ("install", "-local", "-verbose", "$(release_tarball)"); ' + +## Install unconditionally. Maybe useful for testing installation with +## different versions of Octave. +install: $(release_tarball) + @echo "Installing package under $(installation_dir) ..." + $(OCTAVE) --eval $(octave_install_commands) + touch $(install_stamp) + +## Install only if installation (under target/...) is not current. +$(install_stamp): $(release_tarball) + @echo "Installing package under $(installation_dir) ..." + $(OCTAVE) --eval $(octave_install_commands) + touch $(install_stamp) + +clean-install: + @echo "## Cleaning installation under $(installation_dir) ..." + -$(RM) -r $(installation_dir) + @echo + + +## +## Recipes for testing purposes +## + +.PHONY: run doctest check + +## Start an Octave session with the package directories on the path for +## interactice test of development sources. +run: $(install_stamp) + $(run_in_place) --persist + +rungui: $(install_stamp) + $(run_in_place) --gui --persist + +## Test example blocks in the documentation. Needs doctest package +## https://octave.sourceforge.io/doctest/index.html +doctest: $(install_stamp) + $(run_in_place) --eval 'pkg load doctest;' \ + --eval "targets = pkg('list', '$(package)'){1}.dir;" \ + --eval "doctest (targets);" + +## Test package. +octave_test_commands = \ +' pkgs = pkg("list", "instrument-control"); \ + dirs = {pkgs{1}.dir}; \ + __run_test_suite__ (dirs, {}); ' + +## the following works, too, but provides no overall summary output as +## __run_test_suite__ does: +## +## else cellfun (@runtests, horzcat (cellfun (@ (dir) ostrsplit (([~, dirs] = system (sprintf ("find %s -type d", dir))), "\n\r", true), dirs, "UniformOutput", false){:})); endif ' +check: $(install_stamp) + $(run_in_place) --eval $(octave_test_commands) + + +## +## CLEAN +## + +.PHONY: clean + +ARCHDIR := "$(shell $(OCTAVE_CONFIG) -p CANONICAL_HOST_TYPE)-$(shell $(OCTAVE_CONFIG) -p API_VERSION)" +clean: clean-tarballs clean-unpacked-release clean-install clean-docs + test -e inst/$(ARCHDIR) && rmdir inst/$(ARCHDIR) || true + test -e $(target_dir)/fntests.log && rm -f $(target_dir)/fntests.log || true + @echo "## Removing target directory (if empty)..." + test -e $(target_dir) && rmdir $(target_dir) || true + @echo + @echo "## Cleaning done" + @echo + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..265a32f --- /dev/null +++ b/NEWS @@ -0,0 +1,307 @@ +Summary of important user-visible changes for instrument-control 0.7.0 +------------------------------------------------------------------- + + ** Update get function for instrument controls to not use cellfun (Bug #59581) + + ** UDPPORT: Added new udpport class + + ** TCPCLIENT: Added new tcpclient class + + ** SERIALPORT: update property access to proper case usage + +Summary of important user-visible changes for instrument-control 0.6.0 +------------------------------------------------------------------- + + ** SPI: added new spi object and functions + + ** TCP: + added tcpclient, depreciated tcpip + + added methods flush, read, write + + ** UDP: + added methods flush, read, write + +Summary of important user-visible changes for instrument-control 0.5.0 +------------------------------------------------------------------- + + ** General updates to support Octave 6+ + + ** Added common functions + flushinput + flushoutput + instrhelp + + ** SERIALPORT: added new serialport object and functions + + ** SERIAL: use extended win32 serial name for comports so > 10 work. + + New serial functions: + serialbreak + + Added overload functions for: + fprintf + fread + fwrite + + Added properties: + port + + Added .property access + + ** UDP: add .property access to the object + + Added properties: + localhost + + Updates property timeout to be seconds + + Updated udp constructor to be closer to matlab compatible + + ** TCP: add .property access to the object + + Updates property timeout to be seconds + + Updated constructor to be closer to matlab compatible + + ** I2C: + Implement object properties + + Added overload functions for: + fread + fwrite + get + set + + ** PARALLEL: + Added overload functions for: + fclose + fopen + fread + fwrite + + ** USBTMC: + Added overload functions for: + fread + fwrite + + ** VXI11: + Added overload functions for: + fread + fwrite + + ** insthwinfo: updated to show i2c ports + + ** added toolkit manual + +Summary of important user-visible changes for instrument-control 0.4.0 +------------------------------------------------------------------- + + ** SERIAL: added 'status', 'bytesavailable', 'name' and 'type' + properties, and the following functions: + seriallist + flushinput + flushoutput + + ** UDP: added 'status' and 'bytesavailable' properties and the + following functions: + flushinput + flushoutput + + ** TCP: added properties to object, added overridden functions: + get + set + fprintf + fread + fwrite + flushinput + flushoutput + + ** tcpip(): added wrapper to be matlab compatible(ish) + + ** distribute rpc generated files + + ** verify -M option will work on rpcgen + + ** detect if rpc_error functions allow use of const inputs + + ** prefer libtirpc over builtin rpc when detecting vxi11 functionality + + ** add lock functions used on pkg load/unlock to lock .oct files + + ** implemented instrhwinfo serial list for mac + +Summary of important user-visible changes for instrument-control 0.3.1: +------------------------------------------------------------------- + + ** Updated build to allow install on octave 4.4 + + ** using polling rather than signal handling to break from instrument reads + + ** insthwinfo() updated to show enabled modules + + ** added initial builtin tests for each instrument + +Summary of important user-visible changes for instrument-control 0.3.0: +------------------------------------------------------------------- + + ** SERIAL: allow non standard baudrates in win32 + + ** TCP: new functions: + resolvehost + + ** UDP: new interface with functions for: + udp + udp_timeout + udp_read + udp_write + udp_close + udp_demo + + ** UDP overload functions for: + fprintf + fread + fwrite + fclose + fopen + get + set + +Summary of important user-visible changes for instrument-control 0.2.3: +------------------------------------------------------------------- + + ** New function: + instrhwinfo + + ** GPIB: Fix EOI handling + + ** SERIAL: Fix display of bytesize setting + + ** SERIAL: Win32: Fix srl_read + + ** TCP: Fix infinite loop on connection lost + + +Summary of important user-visible changes for instrument-control 0.2.2: +------------------------------------------------------------------- + + ** GPIB: new function: + fread + + ** SERIAL: Add pinstatus property + + ** SERIAL: Change display for serial object + + ** SERIAL: Fix MACOS compilation error + + ** Fix warnings when using Octave 4.0 + + +Summary of important user-visible changes for instrument-control 0.2.1: +------------------------------------------------------------------- + + ** GPIB: New functions: + spoll + trigger + clrdevice + fopen + fclose + fwrite + fprintf + fscanf + + ** I2C, TCPIP, USBTMC, VXI11: New functions: + fopen + fclose + + ** SERIAL: Add Win32 support + + ** SERIAL: New functions: + fclose + fopen + get + set + + ** SERIAL: Deprecate functions, use set and get instead: + srl_baudrate + srl_bytesize + srl_close + srl_flush + srl_parity + srl_stopbits + srl_timeout + + +Summary of important user-visible changes for instrument-control 0.2.0: +------------------------------------------------------------------- + + ** Support for TCP interface I/O + + ** Support for USBTMC interface I/O + + ** Support for GPIB interface I/O + + ** Support for VXI11 interface I/O + + ** The following functions are new: + tcp + tcp_read + tcp_write + tcp_timeout + tcp_close + usbtmc + usbtmc_read + usbtmc_write + usbtmc_close + gpib + gpib_read + gpib_write + gpib_timeout + gpib_close + vxi11 + vxi11_read + vxi11_write + vxi11_close + + ** Interfaces are now compiled seperately (i.e. failed compilation of one + interface does not mean fail of whole package) + + ** Parallel and i2c interface support for FreeBSD platform + + ** i2c_write no longer accepts strings for data parameter + + +Summary of important user-visible changes for instrument-control 0.1.0: +------------------------------------------------------------------- + + ** Initial release + + ** Support for Parallel interface I/O + + ** Support for Serial interface I/O + + ** Support for i2c interface I/O + + ** The following functions are new: + serial + srl_close + srl_read + srl_write + srl_baudrate + srl_flush + srl_stopbits + srl_bytesize + srl_parity + srl_timeout + i2c + i2c_addr + i2c_read + i2c_close + i2c_write + parallel + pp_ctrl + pp_stat + pp_close + pp_data + pp_datadir + diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b41a2d --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +Introduction +============ + +The Instrument control package provides low level I/O functions for serial, i2c, spi, parallel, tcp, gpib, vxi11, +udp and usbtmc interfaces. + +It attempts to provide the same function calls as the Matlab toolkit, as well as additional functionality. + +Requirements +============ + +* Octave >= 3.8.0 + +* linux-gpib (Linux only) + +* rpcgen and libtirpc for VXI11 support + + +Installing +========== + +To install, run the octave package manager: + +1. If running Windows, the package may already be installed: + type pkg list, to view the installed packages. + +2. To install from source forge: + pkg install -forge instrument-control + +3. To install from a local tarball. + pkg install instrument-control-XXXXXXX.tar.gz + Where XXXXXXX is the version of the the downloaded tarball. + +Usage: +====== + +1. Load the package. + pkg load instrument-control + (Required each time Octave is started) + +2. Use the function calls to control the instrument hardware. + +Documentation +============== + +See the function list for instrument-control on [octave forge](https://octave.sourceforge.io/instrument-control/overview.html) for function documentation. + +Read the Octave [instrument-control wiki](https://wiki.octave.org/Instrument_control_package) for install tips and examples. + +Known limitations and bugs +========================== + +None provided diff --git a/doc/functions.texi b/doc/functions.texi new file mode 100644 index 0000000..501223a --- /dev/null +++ b/doc/functions.texi @@ -0,0 +1,3119 @@ +@c --------------------------------------------------- +@node Common Functions +@section Common Functions +@cindex Common Functions +@c Common Functions flushinput +@c ----------------------------------------- +@subsection flushinput +@cindex flushinput + @deftypefn {} {} flushinput (@var{dev}) + Flush the instruments input buffers + + @subsubheading Inputs + @var{dev} - connected device or array of devices + + @subsubheading Outputs + None + + @xseealso{flushoutput} + @end deftypefn +@c Common Functions flushoutput +@c ----------------------------------------- +@subsection flushoutput +@cindex flushoutput + @deftypefn {} {} flushoutput (@var{dev}) + Flush the instruments output buffers + + @subsubheading Inputs + @var{dev} - connected device or array of devices + + @subsubheading Outputs + None + + @xseealso{flushinput} + @end deftypefn +@c --------------------------------------------------- +@node General +@section General +@cindex General +@c General instrhelp +@c ----------------------------------------- +@subsection instrhelp +@cindex instrhelp + @deftypefn {} {} instrhelp () + @deftypefnx {} {} instrhelp (@var{funcname}) + @deftypefnx {} {} instrhelp (@var{obj}) + Display instrument help + + @subsubheading Inputs + @var{funcname} - function to display help about.@* + @var{obj} - object to display help about.@* + + If no input is provided, the function will display and overview + of the package functionality. + + @subsubheading Outputs + None + + @end deftypefn +@c General instrhwinfo +@c ----------------------------------------- +@subsection instrhwinfo +@cindex instrhwinfo + @deftypefn {Function File} {[@var{list}] =} instrhwinfo () + @deftypefnx {Function File} {@var{list} =} instrhwinfo (@var{interface}) + Query available hardware for instrument-control + + When run without any input parameters, instrhwinfo will provide the toolbox + information and a list of supported interfaces. + + @subsubheading Inputs + @var{interface} is the instrument interface to query. When provided, instrhwinfo + will provide information on the specified interface. + + Currently only interface "serialport","i2c" and "spi" and is supported, which will provide a list of + available serial ports or i2c ports. + + @subsubheading Outputs + If an output variable is provided, the function will store the information + to the variable, otherwise it will be displayed to the screen. + + @subsubheading Example + @example + instrhwinfo + scalar structure containing the fields: + + ToolboxVersion = 0.4.0 + ToolboxName = octave instrument control package + SupportedInterfaces = + @{ + [1,1] = i2c + [1,2] = parallel + [1,3] = serialport + [1,4] = tcp + [1,5] = udp + [1,6] = usbtmc + [1,7] = vxi11 + @} + + @end example + + @end deftypefn +@c General resolvehost +@c ----------------------------------------- +@subsection resolvehost +@cindex resolvehost +@deftypefn {Loadable Function} {@var{name} = } resolvehost (@var{host}) +@deftypefnx {Loadable Function} {[@var{name}, @var{address}] = } resolvehost (@var{host}) +@deftypefnx {Loadable Function} {@var{out} = } resolvehost (@var{host}, @var{returntype}) + +Resolve a network host name or address to network name and address + +@subsubheading Inputs +@var{host} - Host name or IP address string to resolve.@* +@var{name} - Resolved IP host name.@* +@var{returntype} - 'name' to get host name, 'address' to get IP address. + +@subsubheading Outputs +@var{name} - Resolved IP host name.@* +@var{address} - Resolved IP host address.@* +@var{out} - host name if @var{returntype} is 'name', ipaddress if @var{returntype} is 'address'@* + +@subsubheading Example +@example +%% get resolved ip name and address pf www.gnu.org +[name, address] = resolvehost ('www.gnu.org'); + +%% get ip address of www.gnu.org +ipaddress = resolvehost ('www.gnu.org', 'address'); + +@end example + +@xseealso{tcp, udp} + +@end deftypefn +@c --------------------------------------------------- +@node GPIB +@section GPIB +@cindex GPIB +@c GPIB @octave_gpib/fclose +@c ----------------------------------------- +@subsection @@octave_gpib/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes connection to GPIB device @var{obj} + @end deftypefn +@c GPIB @octave_gpib/fopen +@c ----------------------------------------- +@subsection @@octave_gpib/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens connection to GPIB device @var{obj} + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c GPIB @octave_gpib/fprintf +@c ----------------------------------------- +@subsection @@octave_gpib/fprintf +@cindex fprintf + @deftypefn {Function File} {} fprintf (@var{obj}, @var{cmd}) + @deftypefnx {Function File} {} fprintf (@var{obj}, @var{format}, @var{cmd}) + @deftypefnx {Function File} {} fprintf (@var{obj}, @var{cmd}, @var{mode}) + @deftypefnx {Function File} {} fprintf (@var{obj}, @var{format}, @var{cmd}, @var{mode}) + Writes string @var{cmd} to GPIB instrument + + @var{obj} is a GPIB object + + @var{cmd} String + @var{format} Format specifier + @var{mode} sync + + @end deftypefn +@c GPIB @octave_gpib/fread +@c ----------------------------------------- +@subsection @@octave_gpib/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from GPIB instrument + + @var{obj} is a GPIB object + + @var{size} Number of values to read. (Default: 100) + @var{precision} precision of data + + @var{count} values read + @var{errmsg} read operation error message + + @end deftypefn +@c GPIB @octave_gpib/fscanf +@c ----------------------------------------- +@subsection @@octave_gpib/fscanf +@cindex fscanf + @deftypefn {Function File} {@var{res} =} fscanf (@var{obj}) + @deftypefnx {Function File} {@var{res} =} fscanf (@var{obj}, @var{format}) + @deftypefnx {Function File} {@var{res} =} fscanf (@var{obj}, @var{format}, @var{size}) + @deftypefnx {Function File} {[@var{res},@var{count}] =} fscanf (@var{obj}, ...) + @deftypefnx {Function File} {[@var{res},@var{count},@var{errmsg}] =} fscanf (@var{obj}, ...) + Reads data @var{res} from GPIB instrument + + @var{obj} is a GPIB object + + @var{format} Format specifier + @var{size} number of values + + @var{count} values read + @var{errmsg} read operation error message + + @end deftypefn +@c GPIB @octave_gpib/fwrite +@c ----------------------------------------- +@subsection @@octave_gpib/fwrite +@cindex fwrite + @deftypefn {Function File} {} fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{precision}) + @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{mode}) + @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{precision}, @var{mode}) + Writes @var{data} to GPIB instrument + + @var{obj} is a GPIB object + + @var{data} data to write + @var{precision} precision of data + @var{mode} sync + + @end deftypefn +@c GPIB clrdevice +@c ----------------------------------------- +@subsection clrdevice +@cindex clrdevice + @deftypefn {Function File} {} clrdevice (@var{obj}) + Send clear command to Clear GPIB instrument. + + @var{obj} is a GPIB object + + @end deftypefn +@c GPIB gpib +@c ----------------------------------------- +@subsection gpib +@cindex gpib +@deftypefn {Loadable Function} {@var{gpib} = } gpib ([@var{gpibid}], [@var{timeout}]) + +Open gpib interface. + +@var{gpibid} - the interface number.@* +@var{timeout} - the interface timeout value. If omitted defaults to blocking call. + +The gpib() shall return instance of @var{octave_gpib} class as the result @var{gpib}. +@end deftypefn +@c GPIB gpib_close +@c ----------------------------------------- +@subsection gpib_close +@cindex gpib_close +@deftypefn {Loadable Function} {} gpib_close (@var{gpib}) + +Close the interface and release a file descriptor. + +@var{gpib} - instance of @var{octave_gpib} class. +@end deftypefn +@c GPIB gpib_read +@c ----------------------------------------- +@subsection gpib_read +@cindex gpib_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}, @var{eoi}] = } gpib_read (@var{gpib}, @var{n}) + +Read from gpib interface. + +@var{gpib} - instance of @var{octave_gpib} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +The gpib_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@var{eoi} indicates read operation complete +@end deftypefn +@c GPIB gpib_timeout +@c ----------------------------------------- +@subsection gpib_timeout +@cindex gpib_timeout +@deftypefn {Loadable Function} {} gpib_timeout (@var{gpib}, @var{timeout}) +@deftypefnx {Loadable Function} {@var{t} = } gpib_timeout (@var{gpib}) + +Set new or get existing gpib interface timeout parameter. The timeout value is valid from 0 to 17. + +@var{gpib} - instance of @var{octave_gpib} class.@* +@var{timeout} - Value of 0 means never timeout, 11 means one second and 17 means 1000 seconds (see GPIB documentation (ibtmo) for further details) + +If @var{timeout} parameter is omitted, the gpib_timeout() shall return current timeout value as the result @var{t}. +@end deftypefn +@c GPIB gpib_write +@c ----------------------------------------- +@subsection gpib_write +@cindex gpib_write +@deftypefn {Loadable Function} {@var{n} = } gpib_write (@var{gpib}, @var{data}) + +Write data to a gpib interface. + +@var{gpib} - instance of @var{octave_gpib} class.@* +@var{data} - data to be written to the gpib interface. Can be either of String or uint8 type. + +Upon successful completion, gpib_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c GPIB spoll +@c ----------------------------------------- +@subsection spoll +@cindex spoll + @deftypefn {Function File} {@var{out} =} spoll (@var{obj}) + @deftypefnx {Function File} {[@var{out},@var{statusByte}] =} spoll (@var{obj}) + Serial polls GPIB instruments. + + @var{obj} is a GPIB object or a cell array of GPIB objects + + @var{out} GPIB objects ready for service + @var{statusByte} status Byte + + @end deftypefn +@c GPIB trigger +@c ----------------------------------------- +@subsection trigger +@cindex trigger + @deftypefn {Function File} {} trigger (@var{obj}) + Triggers GPIB instrument. + + @var{obj} is a GPIB object + + @end deftypefn +@c --------------------------------------------------- +@node I2C +@section I2C +@cindex I2C +@c I2C @octave_i2c/fclose +@c ----------------------------------------- +@subsection @@octave_i2c/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes I2C connection @var{obj} + @end deftypefn +@c I2C @octave_i2c/fopen +@c ----------------------------------------- +@subsection @@octave_i2c/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens I2C connection @var{obj} + + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c I2C @octave_i2c/fread +@c ----------------------------------------- +@subsection @@octave_i2c/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from I2C instrument + + @subsubheading Inputs + @var{obj} is a I2C object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} data values.@* + @var{count} number of values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c I2C @octave_i2c/fwrite +@c ----------------------------------------- +@subsection @@octave_i2c/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to I2C instrument + + @subsubheading Inputs + @var{obj} is a I2C object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c I2C @octave_i2c/get +@c ----------------------------------------- +@subsection @@octave_i2c/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{i2c}) + @deftypefnx {Function File} {@var{field} = } get (@var{i2c}, @var{property}) + Get the properties of i2c object. + + @subsubheading Inputs + @var{i2c} - instance of @var{octave_i2c} class.@* + + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_i2c/set} + @end deftypefn +@c I2C @octave_i2c/set +@c ----------------------------------------- +@subsection @@octave_i2c/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of i2c object. + + @subsubheading Inputs + @var{obj} - instance of @var{octave_i2c} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'name' + Set the name for the i2c socket. + + @item 'remoteaddress' + Set the remote address for the i2c socket. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_i2c/get} + @end deftypefn +@c I2C i2c +@c ----------------------------------------- +@subsection i2c +@cindex i2c +@deftypefn {Loadable Function} {@var{i2c} = } i2c ([@var{port_path}], [@var{address}]) + +Open i2c interface. + +@subsubheading Inputs +@var{port_path} - the interface device port/path of type String. If omitted defaults to +'/dev/i2c-0'. @* +@var{address} - the slave device address. If omitted must be set using i2c_addr() call. + +@subsubheading Outputs +@var{i2c} - An instance of @var{octave_i2c} class. + +@subsubheading Properties +The i2c object has the following properties: +@table @asis +@item name +Name of the object +@item remoteaddress +the slave device address +@item port +The interface driver port (readonly) +@end table +@end deftypefn +@c I2C i2c_addr +@c ----------------------------------------- +@subsection i2c_addr +@cindex i2c_addr +@deftypefn {Loadable Function} {} i2c_addr (@var{i2c}, @var{address}) +@deftypefnx {Loadable Function} {@var{addr} = } i2c_addr (@var{i2c}) + +Set new or get existing i2c slave device address. + +@subsubheading Inputs +@var{i2c} - instance of @var{octave_i2c} class.@* +@var{address} - i2c slave device address of type Integer. +The address is passed in the 7 or 10 lower bits of the argument. + +@subsubheading Outputs +@var{addr} - If @var{address} parameter is omitted, the i2c_addr() shall return +current i2c slave device address. +@end deftypefn +@c I2C i2c_close +@c ----------------------------------------- +@subsection i2c_close +@cindex i2c_close +@deftypefn {Loadable Function} {} i2c_close (@var{i2c}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{i2c} - instance of @var{octave_i2c} class.@* + +@subsubheading Outputs +None +@end deftypefn +@c I2C i2c_read +@c ----------------------------------------- +@subsection i2c_read +@cindex i2c_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } i2c_read (@var{i2c}, @var{n}) + +Read from i2c slave device. + +@subsubheading Inputs +@var{i2c} - instance of @var{octave_i2c} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +@subsubheading Outputs +The i2c_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@end deftypefn +@c I2C i2c_write +@c ----------------------------------------- +@subsection i2c_write +@cindex i2c_write +@deftypefn {Loadable Function} {@var{n} = } i2c_write (@var{i2c}, @var{data}) + +Write data to a i2c slave device. + +@subsubheading Inputs +@var{i2c} - instance of @var{octave_i2c} class.@* +@var{data} - data, of type uint8, to be written to the slave device. + +@subsubheading Outputs +Upon successful completion, i2c_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c --------------------------------------------------- +@node Parallel +@section Parallel +@cindex Parallel +@c Parallel @octave_parallel/fclose +@c ----------------------------------------- +@subsection @@octave_parallel/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes parallel connection @var{obj} + @end deftypefn +@c Parallel @octave_parallel/fopen +@c ----------------------------------------- +@subsection @@octave_parallel/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens parallel interface @var{obj} + + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c Parallel @octave_parallel/fread +@c ----------------------------------------- +@subsection @@octave_parallel/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from parallel instrument + + @subsubheading Inputs + @var{obj} is a parallel object.@* + @var{size} Number of values to read. (Default: 1).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} The read data.@* + @var{count} values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c Parallel @octave_parallel/fwrite +@c ----------------------------------------- +@subsection @@octave_parallel/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to parallel instrument + + @subsubheading Inputs + @var{obj} is a parallel object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c Parallel parallel +@c ----------------------------------------- +@subsection parallel +@cindex parallel +@deftypefn {Loadable Function} {@var{parallel} = } parallel ([@var{path}], [@var{direction}]) + +Open Parallel interface. + +@subsubheading Inputs +@var{path} - the interface path of type String. If omitted defaults to '/dev/parport0'.@* +@var{direction} - the direction of interface drivers of type Integer, see: PP_DATADIR for more info. +If omitted defaults to 1 (Input). + +@subsubheading Outputs +The parallel() shall return instance of @var{octave_parallel} class as the result @var{parallel}. +@end deftypefn +@c Parallel pp_close +@c ----------------------------------------- +@subsection pp_close +@cindex pp_close +@deftypefn {Loadable Function} {} pp_close (@var{parallel}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{parallel} - instance of @var{octave_serial} class.@* +@subsubheading Outputs +None +@end deftypefn +@c Parallel pp_ctrl +@c ----------------------------------------- +@subsection pp_ctrl +@cindex pp_ctrl +@deftypefn {Loadable Function} {} pp_ctrl (@var{parallel}, @var{ctrl}) +@deftypefnx {Loadable Function} {@var{c} = } pp_ctrl (@var{parallel}) + +Sets or Read the Control lines. + +@subsubheading Inputs +@var{parallel} - instance of @var{octave_parallel} class.@* +@var{ctrl} - control parameter to be set of type Byte. + +@subsubheading Outputs +If @var{ctrl} parameter is omitted, the pp_ctrl() shall return current Control lines state as the result @var{c}. +@end deftypefn +@c Parallel pp_data +@c ----------------------------------------- +@subsection pp_data +@cindex pp_data +@deftypefn {Loadable Function} {} pp_data (@var{parallel}, @var{data}) +@deftypefnx {Loadable Function} {@var{d} = } pp_data (@var{parallel}) + +Sets or Read the Data lines. + +@subsubheading Inputs +@var{parallel} - instance of @var{octave_parallel} class.@* +@var{data} - data parameter to be set of type Byte. + +@subsubheading Outputs +If @var{data} parameter is omitted, the pp_data() shall return current Data lines state as the result @var{d}. +@end deftypefn +@c Parallel pp_datadir +@c ----------------------------------------- +@subsection pp_datadir +@cindex pp_datadir +@deftypefn {Loadable Function} {} pp_datadir (@var{parallel}, @var{direction}) +@deftypefnx {Loadable Function} {@var{dir} = } pp_datadir (@var{parallel}) + +Controls the Data line drivers. + +Normally the computer's parallel port will drive the data lines, +but for byte-wide transfers from the peripheral to the host it is useful to turn off those drivers +and let the peripheral drive the signals. (If the drivers on the computer's parallel port are left +on when this happens, the port might be damaged.) + +@subsubheading Inputs +@var{parallel} - instance of @var{octave_parallel} class.@* +@var{direction} - direction parameter of type Integer. Supported values: 0 - the drivers are turned on +(Output/Forward direction); 1 - the drivers are turned off (Input/Reverse direction). + +@subsubheading Outputs +If @var{direction} parameter is omitted, the pp_datadir() shall return current Data direction as the result @var{dir}. +@end deftypefn +@c Parallel pp_stat +@c ----------------------------------------- +@subsection pp_stat +@cindex pp_stat +@deftypefn {Loadable Function} {@var{stat} = } pp_stat (@var{parallel}) + +Reads the Status lines. + +@subsubheading Inputs +@var{parallel} - instance of @var{octave_parallel} class.@* + +@subsubheading Outputs +The pp_stat() shall return current Status lines state as the result @var{stat}. +@end deftypefn +@c --------------------------------------------------- +@node Serial (Depreciated) +@section Serial (Depreciated) +@cindex Serial (Depreciated) +@c Serial (Depreciated) @octave_serial/fclose +@c ----------------------------------------- +@subsection @@octave_serial/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes SERIAL connection @var{obj} + @end deftypefn +@c Serial (Depreciated) @octave_serial/flushinput +@c ----------------------------------------- +@subsection @@octave_serial/flushinput +@cindex flushinput + @deftypefn {Loadable Function} {} flushinput (@var{serial}) + + Flush the pending input, which will also make the BytesAvailable property be 0. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class. + + @subsubheading Outputs + None + + @xseealso{srl_flush, flushoutput} + @end deftypefn +@c Serial (Depreciated) @octave_serial/flushoutput +@c ----------------------------------------- +@subsection @@octave_serial/flushoutput +@cindex flushoutput + @deftypefn {Loadable Function} {} flushoutput (@var{serial}) + + Flush the output buffer. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class. + + @subsubheading Outputs + None + + @xseealso{srl_flush, flushinput} + @end deftypefn +@c Serial (Depreciated) @octave_serial/fopen +@c ----------------------------------------- +@subsection @@octave_serial/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens SERIAL interface @var{obj} + + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c Serial (Depreciated) @octave_serial/fprintf +@c ----------------------------------------- +@subsection @@octave_serial/fprintf +@cindex fprintf + @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) + Writes formatted string @var{template} using optional parameters to + serial instrument + + @subsubheading Inputs + @var{obj} is a serial object.@* + @var{template} Format template string + + @subsubheading Outputs + @var{numbytes} - number of bytes written to the serial device. + + @end deftypefn +@c Serial (Depreciated) @octave_serial/fread +@c ----------------------------------------- +@subsection @@octave_serial/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from serial instrument + + @subsubheading Inputs + @var{obj} is a serial object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} The read data.@* + @var{count} values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c Serial (Depreciated) @octave_serial/fwrite +@c ----------------------------------------- +@subsection @@octave_serial/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to serial instrument + + @subsubheading Inputs + @var{obj} is a serial object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c Serial (Depreciated) @octave_serial/get +@c ----------------------------------------- +@subsection @@octave_serial/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{serial}) + @deftypefnx {Function File} {@var{field} = } get (@var{serial}, @var{property}) + Get the properties of serial object. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_serial/set} + @end deftypefn +@c Serial (Depreciated) @octave_serial/serialbreak +@c ----------------------------------------- +@subsection @@octave_serial/serialbreak +@cindex serialbreak + @deftypefn {Function File} {} serialbreak (@var{serial}) + @deftypefnx {Function File} {} serialbreak (@var{serial}, @var{time}) + Send a break to the serial port + + @subsubheading Inputs + @var{serial} - serial object@* + @var{time} - number of milliseconds to break for. If not specified a value of 10 will be used. + + @subsubheading Outputs + None + + @xseealso{serial} + @end deftypefn +@c Serial (Depreciated) @octave_serial/set +@c ----------------------------------------- +@subsection @@octave_serial/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of serial object. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'baudrate' + Set the baudrate of serial port. Supported values by instrument-control: + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, + 19200, 38400, 57600, 115200 and 230400. The supported baudrate of your + serial port may be different. + + @item 'bytesize' + Set the bytesize. Supported values: 5, 6, 7 and 8. + + @item 'name' + Set the stored string name of the serial object. + + @item 'parity' + Set the parity value. Supported values: Even/Odd/None. This Parameter + must be of type string. It is case insensitive and can be abbreviated + to the first letter only + + @item 'stopbits' + Set the number of stopbits. Supported values: 1, 2. + + @item 'timeout' + Set the timeout value in tenths of a second. Value of -1 means a + blocking call. Maximum value of 255 (i.e. 25.5 seconds). + + @item 'requesttosend' + Set the requesttosend (RTS) line. + + @item 'dataterminalready' + Set the dataterminalready (DTR) line. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_serial/get} + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_baudrate +@c ----------------------------------------- +@subsection @@octave_serial/srl_baudrate +@cindex srl_baudrate + @deftypefn {Loadable Function} {} srl_baudrate (@var{serial}, @var{baudrate})\ + @deftypefnx {Loadable Function} {@var{br} = } srl_baudrate (@var{serial}) + + Set new or get existing serial interface baudrate parameter. Only standard values are supported. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{baudrate} - the baudrate value used. Supported values: 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600 19200, 38400, 57600, 115200 and 230400.@* + + If @var{baudrate} parameter is omitted, the srl_baudrate() shall return current baudrate value as the result @var{br}. + + @subsubheading Outputs + @var{br} - The currently set baudrate + + This function is obsolete. Use get and set method instead. + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_bytesize +@c ----------------------------------------- +@subsection @@octave_serial/srl_bytesize +@cindex srl_bytesize + @deftypefn {Loadable Function} {} srl_bytesize (@var{serial}, @var{bsize}) + @deftypefnx {Loadable Function} {@var{bs} = } srl_bytesize (@var{serial}) + + Set new or get existing serial interface byte size parameter. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{bsize} - byte size of type Integer. Supported values: 5/6/7/8.@* + + If @var{bsize} parameter is omitted, the srl_bytesize() shall return current byte size value + or in case of unsupported setting -1, as the result @var{bs}. + + This function is obsolete. Use get and set method instead. + + @subsubheading Outputs + @var{bs} -the currently set byte size. + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_close +@c ----------------------------------------- +@subsection @@octave_serial/srl_close +@cindex srl_close + @deftypefn {Loadable Function} {} srl_close (@var{serial}) + + Close the interface and release a file descriptor. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class. + + This function is obsolete. Use fclose() method instead. + + @subsubheading Outputs + None + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_flush +@c ----------------------------------------- +@subsection @@octave_serial/srl_flush +@cindex srl_flush + @deftypefn {Loadable Function} {} srl_flush (@var{serial}, [@var{q}]) + +Flush the pending input/output. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{q} - queue selector of type Integer. Supported values:@* + @table @asis + @item 0 + flush untransmitted output + @item 1 + flush pending input + @item 2 + flush both pending input and untransmitted output. + @end table + + If @var{q} parameter is omitted, the srl_flush() shall flush both, input and output buffers. + + @subsubheading Outputs + None + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_parity +@c ----------------------------------------- +@subsection @@octave_serial/srl_parity +@cindex srl_parity + @deftypefn {Loadable Function} {} srl_parity (@var{serial}, @var{parity}) + @deftypefnx {Loadable Function} {@var{p} = } srl_parity (@var{serial}) + + Set new or get existing serial interface parity parameter. Even/Odd/None values are supported. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{parity} - parity value of type String. Supported values: + Even/Odd/None (case insensitive, can be abbreviated to the first letter only)@* + + If @var{parity} parameter is omitted, the srl_parity() shall return current parity value as the result @var{p}. + + This function is obsolete. Use get and set method instead. + + @subsubheading Outputs + @var{p} - The currently set parity + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_stopbits +@c ----------------------------------------- +@subsection @@octave_serial/srl_stopbits +@cindex srl_stopbits + @deftypefn {Loadable Function} {} srl_stopbits (@var{serial}, @var{stopb}) + @deftypefnx {Loadable Function} {@var{sb} = } srl_stopbits (@var{serial}) + + Set new or get existing serial interface stop bits parameter. Only 1 or 2 stop bits are supported. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{stopb} - number of stop bits used. Supported values: 1, 2.@* + + @subsubheading Outputs + If @var{stopb} parameter is omitted, the srl_stopbits() shall return current stop bits value as the result @var{sb}. + + This function is obsolete. Use get and set method instead. + + @end deftypefn +@c Serial (Depreciated) @octave_serial/srl_timeout +@c ----------------------------------------- +@subsection @@octave_serial/srl_timeout +@cindex srl_timeout + @deftypefn {Loadable Function} {} srl_timeout (@var{serial}, @var{timeout}) + @deftypefnx {Loadable Function} {@var{t} = } srl_timeout (@var{serial}) + + Set new or get existing serial interface timeout parameter used for srl_read() requests. The timeout value is specified in tenths of a second. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serial} class.@* + @var{timeout} - srl_read() timeout value in tenths of a second. + A value of -1 means a blocking call. Maximum value of 255 (i.e. 25.5 seconds).@* + + @subsubheading Outputs + If @var{timeout} parameter is omitted, the srl_timeout() shall return current timeout value as the result @var{t}. + + This function is obsolete. Use get and set method instead. + + @end deftypefn +@c Serial (Depreciated) serial +@c ----------------------------------------- +@subsection serial +@cindex serial +@deftypefn {Loadable Function} {@var{serial} = } serial ([@var{path}], [@var{baudrate}], [@var{timeout}]) + +Open serial interface. + +@subsubheading Inputs +@var{path} - the interface path of type String. @* +@var{baudrate} - the baudrate of interface. If omitted defaults to 115200. @* +@var{timeout} - the interface timeout value. If omitted defaults to blocking call. + +@subsubheading Outputs +The serial() shall return an instance of @var{octave_serial} class as the result @var{serial}. +@subsubheading Properties +The serial object has the following public properties: +@table @asis +@item name +name assigned to the object +@item type +instrument type 'serial' (readonly) +@item port +OS specific port name (readonly) +@item status +status of the object 'open' or 'closed' (readonly) +@item timeout +timeout value used for waiting for data +@item bytesavailable +number of bytes currently available to read (readonly) +@item stopbits +number of stopbits to use +@item requesttosend +request to send state - 'on' or 'off' +@item parity +Parity setting 'none', 'even', 'odd' +@item bytesize +Number of bits to a byte (7 or 8) +@item baudrate +Baudrate setting +@item dataterminalready +state of dataterminal ready - 'on' or 'off' +@item pinstatus +current state of pins (readonly) +@end table +@end deftypefn +@c Serial (Depreciated) seriallist +@c ----------------------------------------- +@subsection seriallist +@cindex seriallist + @deftypefn {Function File} {@var{list} = } seriallist () + Returns a list of all serial ports detected in the system. + + @subsubheading Inputs + None + + @subsubheading Outputs + @var{list} is a string cell array of serial ports names detected + in the system. + + @xseealso{instrhwinfo("serial")} + @end deftypefn +@c Serial (Depreciated) srl_read +@c ----------------------------------------- +@subsection srl_read +@cindex srl_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } srl_read (@var{serial}, @var{n}) + +Read from serial interface. + +@subsubheading Inputs +@var{serial} - instance of @var{octave_serial} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +@subsubheading Outputs +The srl_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@end deftypefn +@c Serial (Depreciated) srl_write +@c ----------------------------------------- +@subsection srl_write +@cindex srl_write +@deftypefn {Loadable Function} {@var{n} = } srl_write (@var{serial}, @var{data}) + +Write data to a serial interface. + +@subsubheading Inputs +@var{serial} - instance of @var{octave_serial} class.@* +@var{data} - data to be written to the serial interface. Can be either of String or uint8 type. + +@subsubheading Outputs +Upon successful completion, srl_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c --------------------------------------------------- +@node Serial Port +@section Serial Port +@cindex Serial Port +@c Serial Port @octave_serialport/configureTerminator +@c ----------------------------------------- +@subsection @@octave_serialport/configureTerminator +@cindex configureTerminator + @deftypefn {Function File} {} configureTerminator (@var{serial}, @var{term}) + @deftypefnx {Function File} {} configureTerminator (@var{serial}, @var{readterm}, @var{writeterm}) + Set terminator for ASCII string manipulation + + @subsubheading Inputs + @var{serial} - serialport object@* + @var{term} - terminal value for both read and write@* + @var{readterm} = terminal value type for read data@* + @var{writeterm} = terminal value for written data@* + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. + + @subsubheading Outputs + None + + @xseealso{serialport} + @end deftypefn +@c Serial Port @octave_serialport/flush +@c ----------------------------------------- +@subsection @@octave_serialport/flush +@cindex flush + @deftypefn {} {@var{data} =} flush (@var{dev}) + @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") + @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") + Flush the serial port buffers + + @subsubheading Inputs + @var{dev} - connected serialport device + + If an additional parameter is provided of "input" or "output", + then only the input or output buffer will be flushed + + @subsubheading Outputs + None + + @xseealso{serialport} + @end deftypefn +@c Serial Port @octave_serialport/fprintf +@c ----------------------------------------- +@subsection @@octave_serialport/fprintf +@cindex fprintf + @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) + Writes formatted string @var{template} using optional parameters to + serialport instrument + + @subsubheading Inputs + @var{obj} is a serialport object.@* + @var{template} Format template string + + @subsubheading Outputs + @var{numbytes} - number of bytes written to the serial device. + + @end deftypefn +@c Serial Port @octave_serialport/fread +@c ----------------------------------------- +@subsection @@octave_serialport/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from serial port instrument + + @subsubheading Inputs + @var{obj} is a serialport object.@* + @var{size} Number of values to read.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} The read data.@* + @var{count} number of values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c Serial Port @octave_serialport/fwrite +@c ----------------------------------------- +@subsection @@octave_serialport/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to serial port instrument + + @subsubheading Inputs + @var{obj} is a serial port object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c Serial Port @octave_serialport/get +@c ----------------------------------------- +@subsection @@octave_serialport/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{serial}) + @deftypefnx {Function File} {@var{field} = } get (@var{serial}, @var{property}) + Get the properties of serialport object. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serialport} class.@* + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_serial/set} + @end deftypefn +@c Serial Port @octave_serialport/getpinstatus +@c ----------------------------------------- +@subsection @@octave_serialport/getpinstatus +@cindex getpinstatus + @deftypefn {Function File} {@var{status}} getpinstatus (@var{serial}) + Get status of serial pins + + @subsubheading Inputs + @var{serial} - serial object@* + + @subsubheading Outputs + @var{status} - a structure with the logic names of ClearToSend, DataSetReady, CarrierDetect, and RingIndicator + + @xseealso{serialport} + @end deftypefn +@c Serial Port @octave_serialport/read +@c ----------------------------------------- +@subsection @@octave_serialport/read +@cindex read + @deftypefn {} {@var{data} =} read (@var{dev}, @var{count}) + @deftypefnx {} {@var{data} =} read (@var{dev}, @var{count}, @var{precision}) + Read a specified number of values from a serialport + using optional precision for valuesize. + + @subsubheading Inputs + @var{dev} - connected serialport device + + @var{count} - number of elements to read + + @var{precision} - Optional precision for the output data read data. + Currently known precision values are uint8 (default), int8, uint16, int16, uint32, int32, uint64, uint64 + + @subsubheading Outputs + @var{data} - data read from the device + + @xseealso{serialport} + @end deftypefn +@c Serial Port @octave_serialport/serialbreak +@c ----------------------------------------- +@subsection @@octave_serialport/serialbreak +@cindex serialbreak + @deftypefn {Function File} {} serialbreak (@var{serial}) + @deftypefnx {Function File} {} serialbreak (@var{serial}, @var{time}) + Send a break to the serial port + + @subsubheading Inputs + @var{serial} - serialport object@* + @var{time} - number of milliseconds to break for. If not specified a value of 10 will be used. + + @subsubheading Outputs + None + + @xseealso{serial} + @end deftypefn +@c Serial Port @octave_serialport/set +@c ----------------------------------------- +@subsection @@octave_serialport/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of serialport object. + + @subsubheading Inputs + @var{serial} - instance of @var{octave_serialport} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'baudrate' + Set the baudrate of serial port. Supported values by instrument-control: + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, + 19200, 38400, 57600, 115200 and 230400. The supported baudrate of your + serial port may be different. + + @item 'bytesize' + Set the bytesize. Supported values: 5, 6, 7 and 8. + + @item 'name' + Set the stored string name of the serial object. + + @item 'parity' + Set the parity value. Supported values: Even/Odd/None. This Parameter + must be of type string. It is case insensitive and can be abbreviated + to the first letter only + + @item 'stopbits' + Set the number of stopbits. Supported values: 1, 2. + + @item 'timeout' + Set the timeout value in tenths of a second. Value of -1 means a + blocking call. Maximum value of 255 (i.e. 25.5 seconds). + + @item 'requesttosend' + Set the requesttosend (RTS) line. + + @item 'dataterminalready' + Set the dataterminalready (DTR) line. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_serialport/-get} + @end deftypefn +@c Serial Port @octave_serialport/setDTR +@c ----------------------------------------- +@subsection @@octave_serialport/setDTR +@cindex setDTR + @deftypefn {} {} setDTR (@var{dev}, @var{true_false}) + Set the state of the DTR line + + @subsubheading Inputs + @var{dev} - connected serial device.@* + @var{true_false} - state to set the line.@* + + @subsubheading Outputs + None + + @xseealso{serialport, getpinstatus, setRTS} + @end deftypefn +@c Serial Port @octave_serialport/setRTS +@c ----------------------------------------- +@subsection @@octave_serialport/setRTS +@cindex setRTS + @deftypefn {} {} setRTS (@var{dev}, @var{true_false}) + Set the state of the RTS line + + @subsubheading Inputs + @var{dev} - connected serial device.@* + @var{true_false} - state to set the line.@* + + @subsubheading Outputs + None + + @xseealso{serialport, getpinstatus} + @end deftypefn +@c Serial Port @octave_serialport/write +@c ----------------------------------------- +@subsection @@octave_serialport/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to serialport instrument + + @subsubheading Inputs + @var{obj} is a serialport object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c Serial Port serialport +@c ----------------------------------------- +@subsection serialport +@cindex serialport +@deftypefn {Loadable Function} {@var{serial} = } serialport ([@var{path}], [@var{baudrate}]) +@deftypefnx {Loadable Function} {@var{serial} = } serialport ([@var{path}], [@var{propname}, @var{propvalue}]) + +Open serial port interface. + +@subsubheading Inputs +@var{path} - the interface path of type String. @* +@var{baudrate} - the baudrate of interface.@* +@var{propname},@var{propvalue} - property name/value pairs. + +Known input properties: +@table @asis +@item BaudRate +Numeric baudrate value +@item Timeout +Numeric timeout value in seconds or -1 to wait forever +@item StopBits +number of stopbits to use +@item Parity +Parity setting 'none', 'even', 'odd' +@item DataBits +Number of bits to a byte (5 to 8) +@item FlowControl +Number of bits to a byte 'none', 'hardware', 'software' +@end table + +@subsubheading Outputs +The serialport() shall return an instance of @var{octave_serialport} class as the result @var{serial}. + +@subsubheading Properties +The serial object has the following public properties: +@table @asis +@item Name +name assigned to the object +@item Type +instrument type 'serial' (readonly) +@item Port +OS specific port name (readonly) +@item Status +status of the object 'open' or 'closed' (readonly) +@item Timeout +timeout value used for waiting for data +@item NumBytesAvailable +number of bytes currently available to read (readonly) +@item NumBytesWritten +number of bytes written (readonly) +@item StopBits +number of stopbits to use +@item Parity +Parity setting 'none', 'even', 'odd' +@item DataBits +Number of bits to a byte (5 to 8) +@item BaudRate +Baudrate setting +@item FlowControl +Number of bits to a byte 'none', 'hardware', 'software' +@item PinStatus +current state of pins (readonly) +@item UserData +user defined data +@end table +@end deftypefn +@c Serial Port serialportlist +@c ----------------------------------------- +@subsection serialportlist +@cindex serialportlist + @deftypefn {Function File} {@var{list} = } serialportlist () + @deftypefnx {Function File} {@var{list} = } serialportlist ("all") + @deftypefnx {Function File} {@var{list} = } serialportlist ("available") + Returns a list of all serial ports detected in the system. + + @subsubheading Inputs + 'all' - show all serial ports (same as providing no arguments) + 'available' - show only serial ports that are available for use + + @subsubheading Outputs + @var{list} is a string cell array of serial ports names detected + in the system. + + @xseealso{instrhwinfo("serialport")} + @end deftypefn +@c --------------------------------------------------- +@node SPI +@section SPI +@cindex SPI +@c SPI @octave_spi/fclose +@c ----------------------------------------- +@subsection @@octave_spi/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes SPI connection @var{obj} + @end deftypefn +@c SPI @octave_spi/fopen +@c ----------------------------------------- +@subsection @@octave_spi/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens SPI connection @var{obj} + + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c SPI @octave_spi/fread +@c ----------------------------------------- +@subsection @@octave_spi/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from a SPI instrument + + @subsubheading Inputs + @var{obj} is a SPI object.@* + @var{size} Number of values to read. (Default: 10).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} data values.@* + @var{count} number of values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c SPI @octave_spi/fwrite +@c ----------------------------------------- +@subsection @@octave_spi/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to SPI instrument + + @subsubheading Inputs + @var{obj} is a SPI object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c SPI @octave_spi/get +@c ----------------------------------------- +@subsection @@octave_spi/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{spi}) + @deftypefnx {Function File} {@var{field} = } get (@var{spi}, @var{property}) + Get the properties of spi object. + + @subsubheading Inputs + @var{spi} - instance of @var{octave_spi} class.@* + + @var{property} - name of property.@* + + @subsubheading Properties + @table @var + @item 'name' + Name for the spi socket. + + @item 'bitrate' + The bitrate for the spi object. + + @item 'clockpolarity' + The clock polarity for the spi object of 'idlehigh' or 'idlelow'. + + @item 'clockphase' + The clock phase for the spi object of 'firstedge' or 'secondedge'. + + @item 'port' + The device port name. + + @item 'status' + The device status of 'open' or 'closed' + @end table + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_spi/set} + @end deftypefn +@c SPI @octave_spi/read +@c ----------------------------------------- +@subsection @@octave_spi/read +@cindex read + @deftypefn {Function File} {@var{data} =} read (@var{obj}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) + Reads @var{data} from SPI instrument + + @subsubheading Inputs + @var{obj} is a SPI object.@* + @var{size} Number of values to read. (Default: 10).@* + + @subsubheading Outputs + @var{data} data values.@* + + @end deftypefn +@c SPI @octave_spi/set +@c ----------------------------------------- +@subsection @@octave_spi/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of spi object. + + @subsubheading Inputs + @var{obj} - instance of @var{octave_spi} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'name' + Set the name for the spi socket. + + @item 'bitrate' + Set the bitrate for the spi object. + + @item 'clockpolarity' + Set the clock polarity for the spi object of 'idlehigh' or 'idlelow'. + + @item 'clockphase' + Set the clock phase for the spi object of 'firstedge' or 'secondedge'. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_spi/get} + @end deftypefn +@c SPI @octave_spi/write +@c ----------------------------------------- +@subsection @@octave_spi/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + Writes @var{data} to SPI instrument + + @subsubheading Inputs + @var{obj} is a SPI object.@* + @var{data} data to write.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c SPI @octave_spi/writeAndRead +@c ----------------------------------------- +@subsection @@octave_spi/writeAndRead +@cindex writeAndRead + @deftypefn {Function File} {@var{data} =} writeAndRead (@var{obj}, @var{wrdata}) + Writes and reads @var{data} from SPI instrument + + @subsubheading Inputs + @var{obj} is a SPI object.@* + @var{wrdata} Data to write.@* + + @subsubheading Outputs + @var{data} data values read.@* + + @end deftypefn +@c SPI spi +@c ----------------------------------------- +@subsection spi +@cindex spi +@deftypefn {Loadable Function} {@var{spi} = } spi ([@var{port_path}]) +@deftypefnx {Loadable Function} {@var{spi} = } spi ([@var{port_path}], [@var{propname}, @var{propvalue}]) + +Open a spi interface. + +@subsubheading Inputs +@var{port_path} - the interface device port/path of type String. If omitted defaults to +'/dev/spi-0'. @* +@var{propname},@var{propvalue} - property name/value pairs. + +Known input properties: +@table @asis +@item name +Name of the object +@item bitrate +Numeric bitrate value +@item clockpolarity +Clock polarity: idlehigh or idlelow. +@item clockphase +Clock phase value: firstedge or secondedge +@end table + +@subsubheading Outputs +@var{spi} - An instance of @var{octave_spi} class. + +@subsubheading Properties +The spi object has the following properties: +@table @asis +@item name +Name of the object +@item status +Open or closed status of object (readonly). +@item bitrate +Numeric bitrate value +@item clockpolarity +Clock polarity: idlehigh or idlelow. +@item clockphase +Clock phase value: firstedge or secondedge +@item port +The interface driver port (readonly) +@end table +@end deftypefn +@c SPI spi_close +@c ----------------------------------------- +@subsection spi_close +@cindex spi_close +@deftypefn {Loadable Function} {} spi_close (@var{spi}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{spi} - instance of @var{octave_spi} class.@* + +@subsubheading Outputs +None +@end deftypefn +@c SPI spi_read +@c ----------------------------------------- +@subsection spi_read +@cindex spi_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } spi_read (@var{spi}, @var{n}) + +Read from spi slave device. + +@subsubheading Inputs +@var{spi} - instance of @var{octave_spi} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +@subsubheading Outputs +The spi_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@end deftypefn +@c SPI spi_write +@c ----------------------------------------- +@subsection spi_write +@cindex spi_write +@deftypefn {Loadable Function} {@var{n} = } spi_write (@var{spi}, @var{data}) + +Write data to a spi slave device. + +@subsubheading Inputs +@var{spi} - instance of @var{octave_spi} class.@* +@var{data} - data, of type uint8, to be written to the slave device. + +@subsubheading Outputs +Upon successful completion, spi_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c SPI spi_writeAndRead +@c ----------------------------------------- +@subsection spi_writeAndRead +@cindex spi_writeAndRead +@deftypefn {Loadable Function} {@var{rddata} = } spi_writeAndRead (@var{spi}, @var{wrdata}) + +Write data to a spi slave device and then read same number of values. + +@subsubheading Inputs +@var{spi} - instance of @var{octave_spi} class.@* +@var{wrdata} - data, of type uint8, to be written to the slave device.@* + +@subsubheading Outputs +Upon successful completion, spi_writeAndRead() shall return the bytes read. +@end deftypefn +@c --------------------------------------------------- +@node TCP (Depreciated) +@section TCP (Depreciated) +@cindex TCP (Depreciated) +@c TCP (Depreciated) @octave_tcp/fclose +@c ----------------------------------------- +@subsection @@octave_tcp/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes TCP connection @var{obj} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/flush +@c ----------------------------------------- +@subsection @@octave_tcp/flush +@cindex flush + @deftypefn {} {@var{data} =} flush (@var{dev}) + @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") + @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") + Flush the tcp socket buffers + + @subsubheading Inputs + @var{dev} - connected tcp device + + If an additional parameter is provided of "input" or "output", + then only the input or output buffer will be flushed + + @subsubheading Outputs + None + + @xseealso{serialport} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/flushinput +@c ----------------------------------------- +@subsection @@octave_tcp/flushinput +@cindex flushinput + @deftypefn {Loadable Function} {} flushinput (@var{tcp}) + + Flush the pending input, which will also make the BytesAvailable property be 0. + + @subsubheading Inputs + @var{tcp} - instance of @var{octave_tcp} class. + + @subsubheading Outputs + None. + + @xseealso{flushoutput} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/flushoutput +@c ----------------------------------------- +@subsection @@octave_tcp/flushoutput +@cindex flushoutput + @deftypefn {Loadable Function} {} flushoutput (@var{tcp}) + + Flush the output buffer. + + @subsubheading Inputs + @var{tcp} - instance of @var{octave_tcp} class. + + @subsubheading Outputs + None. + + @xseealso{flushinput} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/fopen +@c ----------------------------------------- +@subsection @@octave_tcp/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens TCP connection @var{obj} + + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c TCP (Depreciated) @octave_tcp/fprintf +@c ----------------------------------------- +@subsection @@octave_tcp/fprintf +@cindex fprintf + @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) + Writes formatted string @var{template} using optional parameters to + TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{template} Format template string + + @subsubheading Outputs + Number of characters written + + @end deftypefn +@c TCP (Depreciated) @octave_tcp/fread +@c ----------------------------------------- +@subsection @@octave_tcp/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} data read.@* + @var{count} values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c TCP (Depreciated) @octave_tcp/fwrite +@c ----------------------------------------- +@subsection @@octave_tcp/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c TCP (Depreciated) @octave_tcp/get +@c ----------------------------------------- +@subsection @@octave_tcp/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{tcp}) + @deftypefnx {Function File} {@var{field} = } get (@var{tcp}, @var{property}) + Get the properties of tcp object. + + @subsubheading Inputs + @var{tcp} - instance of @var{octave_tcp} class.@* + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_tcp/set} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/read +@c ----------------------------------------- +@subsection @@octave_tcp/read +@cindex read + @deftypefn {Function File} {@var{data} =} read (@var{obj}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) + Reads @var{data} from TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{datatype} datatype of data.@* + + @subsubheading Outputs + @var{data} data read.@* + + @end deftypefn +@c TCP (Depreciated) @octave_tcp/set +@c ----------------------------------------- +@subsection @@octave_tcp/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of tcp object. + + @subsubheading Inputs + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'name' + Set the name for the tcp socket. + + @item 'remotehost' + Set the remote host name for the tcp socket. + + @item 'remoteport' + Set the remote port for the tcp socket. + + @item 'timeout' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_tcp/get} + @end deftypefn +@c TCP (Depreciated) @octave_tcp/write +@c ----------------------------------------- +@subsection @@octave_tcp/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) + Writes @var{data} to TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{data} data to write.@* + @var{datatype} datatype of data. If not specified, it defaults to "uint8".@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c TCP (Depreciated) tcp +@c ----------------------------------------- +@subsection tcp +@cindex tcp +@deftypefn {Loadable Function} {@var{tcp} = } tcp () +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}) +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port}) +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port}, @var{timeout}) +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, [@var{propertyname}, @var{propertyvalue}]) +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port}, [@var{propertyname}, @var{propertyvalue}]) + +Open tcp interface. + +@subsubheading Inputs +@var{ipaddress} - the ip address of type String. If omitted defaults to '127.0.0.1'.@* +@var{port} - the port number to connect. If omitted defaults to 23.@* +@var{timeout} - the interface timeout value. If omitted defaults to blocking call.@* +@var{propname},@var{propvalue} - property name/value pairs. + +Known input properties: +@table @asis +@item name +name value +@item timeout +Numeric timeout value or -1 to wait forever +@end table + +@subsubheading Outputs +The tcp() shall return instance of @var{octave_tcp} class as the result @var{tcp}. +@subsubheading Properties +The tcp object has the following public properties: +@table @asis +@item name +name assigned to the tcp object +@item type +instrument type 'tcp' (readonly) +@item localport +local port number (readonly) +@item remoteport +remote port number +@item remotehost +remote host +@item status +status of the object 'open' or 'closed' (readonly) +@item timeout +timeout value in seconds used for waiting for data +@item bytesavailable +number of bytes currently available to read (readonly) +@end table +@end deftypefn +@c TCP (Depreciated) tcp_close +@c ----------------------------------------- +@subsection tcp_close +@cindex tcp_close +@deftypefn {Loadable Function} {} tcp_close (@var{tcp}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{tcp} - instance of @var{octave_tcp} class. + +@subsubheading Outputs +None +@end deftypefn +@c TCP (Depreciated) tcp_read +@c ----------------------------------------- +@subsection tcp_read +@cindex tcp_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } tcp_read (@var{tcp}, @var{n}, @var{timeout}) + +Read from tcp interface. + +@subsubheading Inputs +@var{tcp} - instance of @var{octave_tcp} class.@* +@var{n} - number of bytes to attempt to read of type Integer@* +@var{timeout} - timeout in ms if different from default of type Integer + +@subsubheading Outputs +@var{count} - number of bytes successfully read as an Integer@* +@var{data} - data bytes themselves as uint8 array. +@end deftypefn +@c TCP (Depreciated) tcp_timeout +@c ----------------------------------------- +@subsection tcp_timeout +@cindex tcp_timeout +@deftypefn {Loadable Function} {} tcp_timeout (@var{tcp}, @var{timeout}) +@deftypefnx {Loadable Function} {@var{t} = } tcp_timeout (@var{tcp}) + +Set new or get existing tcp interface timeout parameter used for tcp_read() requests. The timeout value is specified in milliseconds. + +@subsubheading Inputs +@var{tcp} - instance of @var{octave_tcp} class.@* +@var{timeout} - tcp_read() timeout value in milliseconds. Value of -1 means a blocking call. + +@subsubheading Outputs +If @var{timeout} parameter is omitted, the tcp_timeout() shall return current timeout value as the result @var{t}. +@end deftypefn +@c TCP (Depreciated) tcp_write +@c ----------------------------------------- +@subsection tcp_write +@cindex tcp_write +@deftypefn {Loadable Function} {@var{n} = } tcp_write (@var{tcp}, @var{data}) + +Write data to a tcp interface. + +@subsubheading Inputs +@var{tcp} - instance of @var{octave_tcp} class.@* +@var{data} - data to be written to the tcp interface. Can be either of String or uint8 type. + +@subsubheading Outputs +Upon successful completion, tcp_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c TCP (Depreciated) tcpip +@c ----------------------------------------- +@subsection tcpip +@cindex tcpip + @deftypefn {Function File} {@var{tcp} = } tcpip (@var{host}, [@var{port}], [@var{PropertyName}, @var{PropertyValue}...]) + Matlab compatible wrapper to the tcp interface. + + NOTE: tcpip has been depreciated. Use tcpclient instead + + @subsubheading Inputs + @var{host} - the host name or ip.@* + @var{port} - the port number to connect. If omitted defaults to 80.@* + @var{PropertyName}, @var{PropertyValue} - Optional property name, value pairs to set on the tcp object.@* + + @subsubheading Properties + Currently the only known properties are "timeout" and "name". + + @subsubheading Outputs + tcpip will return an instance of @var{octave_tcp} class as the result. + @end deftypefn +@c --------------------------------------------------- +@node TCP Client +@section TCP Client +@cindex TCP Client +@c TCP Client @octave_tcpclient/configureTerminator +@c ----------------------------------------- +@subsection @@octave_tcpclient/configureTerminator +@cindex configureTerminator + @deftypefn {Function File} {} configureTerminator (@var{tcp}, @var{term}) + @deftypefnx {Function File} {} configureTerminator (@var{tcp}, @var{readterm}, @var{writeterm}) + Set terminator on a tcpclient object for ASCII string manipulation + + @subsubheading Inputs + @var{tcp} - tcpclient object@* + @var{term} - terminal value for both read and write@* + @var{readterm} = terminal value type for read data@* + @var{writeterm} = terminal value for written data@* + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. + + @subsubheading Outputs + None + + @xseealso{tcpport} + @end deftypefn +@c TCP Client @octave_tcpclient/flush +@c ----------------------------------------- +@subsection @@octave_tcpclient/flush +@cindex flush + @deftypefn {} {@var{data} =} flush (@var{dev}) + @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") + @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") + Flush the tcpclient socket buffers + + @subsubheading Inputs + @var{dev} - connected tcpclient device + + If an additional parameter is provided of "input" or "output", + then only the input or output buffer will be flushed + + @subsubheading Outputs + None + + @xseealso{serialport} + @end deftypefn +@c TCP Client @octave_tcpclient/get +@c ----------------------------------------- +@subsection @@octave_tcpclient/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{tcpclient}) + @deftypefnx {Function File} {@var{field} = } get (@var{tcpclient}, @var{property}) + Get the properties of tcpclient object. + + @subsubheading Inputs + @var{tcpclient} - instance of @var{octave_tcpclient} class.@* + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_tcpclient/set} + @end deftypefn +@c TCP Client @octave_tcpclient/read +@c ----------------------------------------- +@subsection @@octave_tcpclient/read +@cindex read + @deftypefn {Function File} {@var{data} =} read (@var{obj}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) + Reads @var{data} from TCP instrument + + @subsubheading Inputs + @var{obj} is a TCP object.@* + @var{size} Number of values to read. (Default: NumBytesAvailable).@* + @var{datatype} datatype of data.@* + + @subsubheading Outputs + @var{data} data read.@* + + @end deftypefn +@c TCP Client @octave_tcpclient/set +@c ----------------------------------------- +@subsection @@octave_tcpclient/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of tcpclient object. + + @subsubheading Inputs + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'Name' + Set the name for the tcpclient socket. + + @item 'UserData' + Set user data for the tcpclient socket. + + @item 'Timeout' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_tcpclient/get} + @end deftypefn +@c TCP Client @octave_tcpclient/write +@c ----------------------------------------- +@subsection @@octave_tcpclient/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) + Writes @var{data} to TCP instrument + + @subsubheading Inputs + @var{obj} is a TCPclient object.@* + @var{data} data to write.@* + @var{datatype} datatype of data. If not specified, it defaults to "uint8".@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c TCP Client tcpclient +@c ----------------------------------------- +@subsection tcpclient +@cindex tcpclient +@deftypefn {Loadable Function} {@var{tcpclient} = } tcpclient (@var{ipaddress}, @var{port}) +@deftypefnx {Loadable Function} {@var{tcpclient} = } tcpclient (@var{ipaddress}, @var{port}, [@var{propertyname}, @var{propertyvalue}]) + +Open tcpclient interface. + +@subsubheading Inputs +@var{ipaddress} - the ip address of type String.@* +@var{port} - the port number to connect.@* +@var{propname},@var{propvalue} - property name/value pairs. + +Known input properties: +@table @asis +@item Name +name value +@item Timeout +Numeric timeout value or -1 to wait forever +@item UserData +User data value. +@end table + +@subsubheading Outputs +The tcpclient() shall return instance of @var{octave_tcpclient} class as the result @var{tcpclient}. + +@subsubheading Properties +The tcpclient object has the following public properties: +@table @asis +@item Name +name assigned to the tcpclient object +@item Type +instrument type 'tcpclient' (readonly) +@item Port +remote port number (Readonly) +@item Address +remote host address (Readonly) +@item Status +status of the object 'open' or 'closed' (readonly) +@item Timeout +timeout value in seconds used for waiting for data +@item NumBytesAvailable +number of bytes currently available to read (readonly) +@item NumBytesWritten +number of bytes currently available to read (readonly) +@item ByteOrder +Byte order for data (currently not used) +@item Terminator +Terminator value used for string data (currently not used) +@item UserData +User data +@end table +@end deftypefn +@c --------------------------------------------------- +@node UDP (Depreciated) +@section UDP (Depreciated) +@cindex UDP (Depreciated) +@c UDP (Depreciated) @octave_udp/fclose +@c ----------------------------------------- +@subsection @@octave_udp/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes UDP connection @var{obj} + @end deftypefn +@c UDP (Depreciated) @octave_udp/flush +@c ----------------------------------------- +@subsection @@octave_udp/flush +@cindex flush + @deftypefn {} {@var{data} =} flush (@var{dev}) + @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") + @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") + Flush the udp socket buffers + + @subsubheading Inputs + @var{dev} - open udp device + + If an additional parameter is provided of "input" or "output", + then only the input or output buffer will be flushed + + @subsubheading Outputs + None + + @xseealso{udp} + @end deftypefn +@c UDP (Depreciated) @octave_udp/flushinput +@c ----------------------------------------- +@subsection @@octave_udp/flushinput +@cindex flushinput + @deftypefn {Loadable Function} {} flushinput (@var{udp}) + + Flush the pending input, which will also make the BytesAvailable property be 0. + + @subsubheading Inputs + @var{udp} - instance of @var{octave_udp} class. + + @subsubheading Outputs + None + + @xseealso{flushoutput} + @end deftypefn +@c UDP (Depreciated) @octave_udp/flushoutput +@c ----------------------------------------- +@subsection @@octave_udp/flushoutput +@cindex flushoutput + @deftypefn {Loadable Function} {} flushoutput (@var{udp}) + + Flush the output buffer. + + @subsubheading Inputs + @var{udp} - instance of @var{octave_udp} class. + + @subsubheading Outputs + None + + @xseealso{flushinput} + @end deftypefn +@c UDP (Depreciated) @octave_udp/fopen +@c ----------------------------------------- +@subsection @@octave_udp/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens UDP connection @var{obj} + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c UDP (Depreciated) @octave_udp/fprintf +@c ----------------------------------------- +@subsection @@octave_udp/fprintf +@cindex fprintf + @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) + Writes formatted string @var{template} using optional parameters to + UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{template} Format template string.@* + + @subsubheading Outputs + @var{numbytes} is the number of bytes written to the device + @end deftypefn +@c UDP (Depreciated) @octave_udp/fread +@c ----------------------------------------- +@subsection @@octave_udp/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} data values.@* + @var{count} number of values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c UDP (Depreciated) @octave_udp/fwrite +@c ----------------------------------------- +@subsection @@octave_udp/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c UDP (Depreciated) @octave_udp/get +@c ----------------------------------------- +@subsection @@octave_udp/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{udp}) + @deftypefnx {Function File} {@var{field} = } get (@var{udp}, @var{property}) + Get the properties of udp object. + + @subsubheading Inputs + @var{udp} - instance of @var{octave_udp} class.@* + + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_udp/set} + @end deftypefn +@c UDP (Depreciated) @octave_udp/read +@c ----------------------------------------- +@subsection @@octave_udp/read +@cindex read + @deftypefn {Function File} {@var{data} =} read (@var{obj}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) + Reads @var{data} from UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{size} Number of values to read. (Default: BytesAvailable).@* + @var{datatype} datatype of data.@* + + @subsubheading Outputs + @var{data} data read.@* + + @end deftypefn +@c UDP (Depreciated) @octave_udp/set +@c ----------------------------------------- +@subsection @@octave_udp/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of udp object. + + @subsubheading Inputs + @var{obj} - instance of @var{octave_udp} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'name' + Set the name for the udp socket. + + @item 'remotehost' + Set the remote host name for the udp socket. + + @item 'remoteport' + Set the remote port for the udp socket. + + @item 'timeout' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_udp/get} + @end deftypefn +@c UDP (Depreciated) @octave_udp/write +@c ----------------------------------------- +@subsection @@octave_udp/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}, @var{destinationAddress}, @var{destinationPort})) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}, @var{destinationAddress}, @var{destinationPort}) + Writes @var{data} to UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{data} data to write.@* + @var{datatype} datatype of data. If not specified defaults to uint8.@* + @var{destinationAddress} ipaddress to send to. If not specified, use the remote address.@* + @var{destinationPort} port to send to. If not specified, use the remote port.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c UDP (Depreciated) udp +@c ----------------------------------------- +@subsection udp +@cindex udp +@deftypefn {Loadable Function} {@var{udp} = } udp () +@deftypefnx {Loadable Function} {@var{udp} = } udp (@var{remoteipaddress}, @var{remoteport}) +@deftypefnx {Loadable Function} {@var{udp} = } udp (@var{remoteipaddress}, @var{remoteport}, [@var{propertyname}, @var{propertyvalue} ...]) + +Open udp interface. + +@subsubheading Inputs +@var{remoteipaddress} - the ip address of type String. If omitted defaults to '127.0.0.1'.@* +@var{remoteport} - the port number to connect. If omitted defaults to 23.@* +@var{localport} - the local port number to bind. If omitted defaults to 0@* +@var{propertyname}, @var{propertyvalue} - property name/value pair + +@subsubheading Outputs +The udp() shall return instance of @var{octave_udp} class as the result @var{udp}. + +@subsubheading Properties +The udp object has the following public properties: +@table @asis +@item name +name assigned to the udp object +@item type +instrument type 'udp' (readonly) +@item localport +local port number (readonly) +@item localhost +local host address (readonly) +@item remoteport +remote port number +@item remotehost +remote host +@item status +status of the object 'open' or 'closed' (readonly) +@item timeout +timeout value in seconds used for waiting for data +@item bytesavailable +number of bytes currently available to read (readonly) +@end table +@end deftypefn +@c UDP (Depreciated) udp_close +@c ----------------------------------------- +@subsection udp_close +@cindex udp_close +@deftypefn {Loadable Function} {} udp_close (@var{udp}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{udp} - instance of @var{octave_udp} class. + +@subsubheading Inputs +None +@end deftypefn +@c UDP (Depreciated) udp_demo +@c ----------------------------------------- +@subsection udp_demo +@cindex udp_demo + @deftypefn {Function File} {@var{result} =} udp_demo () + Run test SNTP demonstration for udp class + + @xseealso{udp} + @end deftypefn +@c UDP (Depreciated) udp_read +@c ----------------------------------------- +@subsection udp_read +@cindex udp_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } udp_read (@var{udp}, @var{n}, @var{timeout}) + +Read from udp interface. + +@subsubheading Inputs +@var{udp} - instance of @var{octave_udp} class.@* +@var{n} - number of bytes to attempt to read of type Integer@* +@var{timeout} - timeout in ms if different from default of type Integer + +@subsubheading Outputs +The udp_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@end deftypefn +@c UDP (Depreciated) udp_timeout +@c ----------------------------------------- +@subsection udp_timeout +@cindex udp_timeout +@deftypefn {Loadable Function} {} udp_timeout (@var{udp}, @var{timeout}) +@deftypefnx {Loadable Function} {@var{t} = } udp_timeout (@var{udp}) + +Set new or get existing udp interface timeout parameter used for udp_read() requests. The timeout value is specified in milliseconds. + +@subsubheading Inputs +@var{udp} - instance of @var{octave_udp} class.@* +@var{timeout} - udp_read() timeout value in milliseconds. Value of -1 means a blocking call. + +@subsubheading Outputs +If @var{timeout} parameter is omitted, the udp_timeout() shall return current timeout value as the result @var{t}. +@end deftypefn +@c UDP (Depreciated) udp_write +@c ----------------------------------------- +@subsection udp_write +@cindex udp_write +@deftypefn {Loadable Function} {@var{n} = } udp_write (@var{udp}, @var{data}) + +Write data to a udp interface. + +@subsubheading Inputs +@var{udp} - instance of @var{octave_udp} class.@* +@var{data} - data to be written to the udp interface. Can be either of String or uint8 type. + +@subsubheading Outputs +Upon successful completion, udp_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c --------------------------------------------------- +@node UDP Port +@section UDP Port +@cindex UDP Port +@c UDP Port @octave_udpport/configureMulticast +@c ----------------------------------------- +@subsection @@octave_udpport/configureMulticast +@cindex configureMulticast + @deftypefn {} {@var{data} =} configureMulticast((@var{dev}, @var{address}) + @deftypefnx {} {@var{data} =} configureMulticast((@var{dev}, @var{"off"}) + Configure udpport device to receive multicast data + + @subsubheading Inputs + @var{dev} - open udpport device + + If @var{address} is 'off' disable udp multicast. Otherwise it is the multicast address to use. + + @subsubheading Outputs + None + + @xseealso{udpport} + @end deftypefn +@c UDP Port @octave_udpport/configureTerminator +@c ----------------------------------------- +@subsection @@octave_udpport/configureTerminator +@cindex configureTerminator + @deftypefn {Function File} {} configureTerminator (@var{udp}, @var{term}) + @deftypefnx {Function File} {} configureTerminator (@var{udp}, @var{readterm}, @var{writeterm}) + Set terminator for ASCII string manipulation + + @subsubheading Inputs + @var{udp} - udpport object@* + @var{term} - terminal value for both read and write@* + @var{readterm} = terminal value type for read data@* + @var{writeterm} = terminal value for written data@* + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. + + @subsubheading Outputs + None + + @xseealso{udpport} + @end deftypefn +@c UDP Port @octave_udpport/flush +@c ----------------------------------------- +@subsection @@octave_udpport/flush +@cindex flush + @deftypefn {} {@var{data} =} flush (@var{dev}) + @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") + @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") + Flush the udpport socket buffers + + @subsubheading Inputs + @var{dev} - open udpport device + + If an additional parameter is provided of "input" or "output", + then only the input or output buffer will be flushed + + @subsubheading Outputs + None + + @xseealso{udpport} + @end deftypefn +@c UDP Port @octave_udpport/fprintf +@c ----------------------------------------- +@subsection @@octave_udpport/fprintf +@cindex fprintf + @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) + Writes formatted string @var{template} using optional parameters to + UDP instrument + + @subsubheading Inputs + @var{obj} is a UDPPort object.@* + @var{template} Format template string.@* + + @subsubheading Outputs + @var{numbytes} is the number of bytes written to the device + @end deftypefn +@c UDP Port @octave_udpport/fread +@c ----------------------------------------- +@subsection @@octave_udpport/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP port object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} data values.@* + @var{count} number of values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c UDP Port @octave_udpport/fwrite +@c ----------------------------------------- +@subsection @@octave_udpport/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP port object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c UDP Port @octave_udpport/get +@c ----------------------------------------- +@subsection @@octave_udpport/get +@cindex get + @deftypefn {Function File} {@var{struct} = } get (@var{udpport}) + @deftypefnx {Function File} {@var{field} = } get (@var{udpport}, @var{property}) + Get the properties of udpport object. + + @subsubheading Inputs + @var{udpport} - instance of @var{octave_udpport} class.@* + + @var{property} - name of property.@* + + @subsubheading Outputs + When @var{property} was specified, return the value of that property.@* + otherwise return the values of all properties as a structure.@* + + @xseealso{@@octave_udpport/set} + @end deftypefn +@c UDP Port @octave_udpport/read +@c ----------------------------------------- +@subsection @@octave_udpport/read +@cindex read + @deftypefn {Function File} {@var{data} =} read (@var{obj}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) + Reads @var{data} from UDP instrument + + @subsubheading Inputs + @var{obj} is a UDP object.@* + @var{size} Number of values to read. (Default: BytesAvailable).@* + @var{datatype} datatype of data.@* + + @subsubheading Outputs + @var{data} data read.@* + + @end deftypefn +@c UDP Port @octave_udpport/set +@c ----------------------------------------- +@subsection @@octave_udpport/set +@cindex set + @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) + @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) + Set the properties of udpport object. + + @subsubheading Inputs + @var{obj} - instance of @var{octave_udpport} class.@* + @var{property} - name of property.@* + + If @var{property} is a cell so must be @var{value}, it sets the values of + all matching properties. + + The function also accepts property-value pairs. + + @subsubheading Properties + @table @var + @item 'Name' + Set the name for the udpport socket. + + @item 'UserData' + Set the user data of the object. + + @item 'Timeout' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + @end table + + @subsubheading Outputs + None + + @xseealso{@@octave_udpport/get} + @end deftypefn +@c UDP Port @octave_udpport/write +@c ----------------------------------------- +@subsection @@octave_udpport/write +@cindex write + @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}, @var{destinationAddress}, @var{destinationPort})) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) + @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}, @var{destinationAddress}, @var{destinationPort}) + Writes @var{data} to UDP instrument + + @subsubheading Inputs + @var{obj} is a UDPPort object.@* + @var{data} data to write.@* + @var{datatype} datatype of data. If not specified defaults to uint8.@* + @var{destinationAddress} ipaddress to send to. If not specified, use the previously used remote address.@* + @var{destinationPort} port to send to. If not specified, use the remote port.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c UDP Port udpport +@c ----------------------------------------- +@subsection udpport +@cindex udpport +@deftypefn {Loadable Function} {@var{udp} = } udpport () +@deftypefnx {Loadable Function} {@var{udp} = } udpport (@var{propertyname}, @var{propertyvalue} ...) + +Open udpport interface. + +@subsubheading Inputs +@var{propertyname}, @var{propertyvalue} - property name/value pair + +Known input properties: +@table @asis +@item Name +name assigned to the udp object +@item LocalPort +local port number +@item LocalHost +local host address +@item Timeout +timeout value in seconds used for waiting for data +@item EnablePortSharing +Boolean if the socket has port sharing enabled (readonly) +@end table + +@subsubheading Outputs +The udpport() shall return instance of @var{octave_udp} class as the result @var{udp}. + +@subsubheading Properties +The udp object has the following public properties: +@table @asis +@item Name +name assigned to the udp object +@item Type +instrument type 'udpport' (readonly) +@item LocalPort +local port number (readonly) +@item LocalHost +local host address (readonly) +@item Status +status of the object 'open' or 'closed' (readonly) +@item Timeout +timeout value in seconds used for waiting for data +@item NumBytesAvailable +number of bytes currently available to read (readonly) +@item MulticastGroup +multicast group socket is subscribed to (readonly) +@item EnableMultcast +Boolean if the socket has any multicast group it is subscribed to (readonly) +@item EnablePortSharing +Boolean if the socket has port sharing enabled (readonly) +@item Terminator +Terminator value used for string data (currently not used) +@end table +@end deftypefn +@c --------------------------------------------------- +@node USBTMC +@section USBTMC +@cindex USBTMC +@c USBTMC @octave_usbtmc/fclose +@c ----------------------------------------- +@subsection @@octave_usbtmc/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes USBTMC connection @var{obj} + + @subsubheading Inputs + @var{obj} is a usbtmc object.@* + @end deftypefn +@c USBTMC @octave_usbtmc/fopen +@c ----------------------------------------- +@subsection @@octave_usbtmc/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens USBTMC connection @var{obj} + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c USBTMC @octave_usbtmc/fread +@c ----------------------------------------- +@subsection @@octave_usbtmc/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from usbtmc instrument + + @subsubheading Inputs + @var{obj} is a usbtmc object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} The read data.@* + @var{count} values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c USBTMC @octave_usbtmc/fwrite +@c ----------------------------------------- +@subsection @@octave_usbtmc/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to an usbtmc instrument + + @subsubheading Inputs + @var{obj} is a usbtmc object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c USBTMC usbtmc +@c ----------------------------------------- +@subsection usbtmc +@cindex usbtmc +@deftypefn {Loadable Function} {@var{usbtmc} = } usbtmc (@var{path}) + +Open usbtmc interface. + +@subsubheading Inputs +@var{path} - the interface path of type String. If omitted defaults to '/dev/usbtmc0'. + +@subsubheading Outputs +The usbtmc() shall return instance of @var{octave_usbtmc} class as the result @var{usbtmc}. +@end deftypefn +@c USBTMC usbtmc_close +@c ----------------------------------------- +@subsection usbtmc_close +@cindex usbtmc_close +@deftypefn {Loadable Function} {} usbtmc_close (@var{usbtmc}) + +Close the interface and release a file descriptor. + +@subsubheading Inputs +@var{usbtmc} - instance of @var{octave_usbtmc} class. +@subsubheading Outputs +None +@end deftypefn +@c USBTMC usbtmc_read +@c ----------------------------------------- +@subsection usbtmc_read +@cindex usbtmc_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } usbtmc_read (@var{usbtmc}, @var{n}) + +Read from usbtmc slave device. + +@subsubheading Inputs +@var{usbtmc} - instance of @var{octave_usbtmc} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +@subsubheading Outputs +@var{count} - the number of bytes successfully read as an Integer.@* +@var{data} - the read bytes as a uint8 array. +@end deftypefn +@c USBTMC usbtmc_write +@c ----------------------------------------- +@subsection usbtmc_write +@cindex usbtmc_write +@deftypefn {Loadable Function} {@var{n} = } usbtmc_write (@var{usbtmc}, @var{data}) + +Write data to a usbtmc slave device. + +@subsubheading Inputs +@var{usbtmc} - instance of @var{octave_usbtmc} class.@* +@var{data} - data, of type uint8, to be written to the slave device. + +@subsubheading Outputs +Upon successful completion, usbtmc_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn +@c --------------------------------------------------- +@node VXI11 +@section VXI11 +@cindex VXI11 +@c VXI11 @octave_vxi11/fclose +@c ----------------------------------------- +@subsection @@octave_vxi11/fclose +@cindex fclose + @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) + Closes VXI11 connection @var{obj} + @end deftypefn +@c VXI11 @octave_vxi11/fopen +@c ----------------------------------------- +@subsection @@octave_vxi11/fopen +@cindex fopen + @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) + Opens VXI11 connection @var{obj} + This currently is a dummy function to improve compatibility to MATLAB + + @end deftypefn +@c VXI11 @octave_vxi11/fread +@c ----------------------------------------- +@subsection @@octave_vxi11/fread +@cindex fread + @deftypefn {Function File} {@var{data} =} fread (@var{obj}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) + @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) + @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) + @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) + Reads @var{data} from vxi11 instrument + + @subsubheading Inputs + @var{obj} is a vxi11 object.@* + @var{size} Number of values to read. (Default: 100).@* + @var{precision} precision of data.@* + + @subsubheading Outputs + @var{data} The read data.@* + @var{count} values read.@* + @var{errmsg} read operation error message.@* + + @end deftypefn +@c VXI11 @octave_vxi11/fwrite +@c ----------------------------------------- +@subsection @@octave_vxi11/fwrite +@cindex fwrite + @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) + @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) + Writes @var{data} to vxi11 instrument + + @subsubheading Inputs + @var{obj} is a vxi11 object.@* + @var{data} data to write.@* + @var{precision} precision of data.@* + + @subsubheading Outputs + returns number of bytes written. + @end deftypefn +@c VXI11 vxi11 +@c ----------------------------------------- +@subsection vxi11 +@cindex vxi11 +@deftypefn {Loadable Function} {@var{vxi11} = } vxi11 (@var{ip}) + +Open vxi11 interface. + +@var{path} - the ip address of type String. If omitted defaults to '127.0.0.1'. + +The vxi11() shall return instance of @var{octave_vxi11} class as the result @var{vxi11}. +@end deftypefn +@c VXI11 vxi11_close +@c ----------------------------------------- +@subsection vxi11_close +@cindex vxi11_close +@deftypefn {Loadable Function} {} vxi11_close (@var{vxi11}) + +Close the interface and release a file descriptor. + +@var{vxi11} - instance of @var{octave_vxi11} class. +@end deftypefn +@c VXI11 vxi11_read +@c ----------------------------------------- +@subsection vxi11_read +@cindex vxi11_read +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } vxi11_read (@var{vxi11}, @var{n}) + +Read from vxi11 slave device. + +@var{vxi11} - instance of @var{octave_vxi11} class.@* +@var{n} - number of bytes to attempt to read of type Integer. + +The vxi11_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array. +@end deftypefn +@c VXI11 vxi11_write +@c ----------------------------------------- +@subsection vxi11_write +@cindex vxi11_write +@deftypefn {Loadable Function} {@var{n} = } vxi11_write (@var{vxi11}, @var{data}) + +Write data to a vxi11 slave device. + +@var{vxi11} - instance of @var{octave_vxi11} class.@* +@var{data} - data to be written to the slave device. Can be either of String or uint8 type. + +Upon successful completion, vxi11_write() shall return the number of bytes written as the result @var{n}. +@end deftypefn diff --git a/doc/gpl.texi b/doc/gpl.texi new file mode 100644 index 0000000..7afdb76 --- /dev/null +++ b/doc/gpl.texi @@ -0,0 +1,718 @@ +@node Copying +@appendix GNU General Public License +@cindex warranty +@cindex copyright + +@center Version 3, 29 June 2007 + +@display +Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. +@end display + +@heading Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program---to make sure it remains +free software for all its users. We, the Free Software Foundation, +use the GNU General Public License for most of our software; it +applies also to any other work released this way by its authors. You +can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, +receive or can get the source code. And you must show them these +terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +@heading TERMS AND CONDITIONS + +@enumerate 0 +@item Definitions. + +``This License'' refers to version 3 of the GNU General Public License. + +``Copyright'' also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +``The Program'' refers to any copyrightable work licensed under this +License. Each licensee is addressed as ``you''. ``Licensees'' and +``recipients'' may be individuals or organizations. + +To ``modify'' a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a ``modified version'' of +the earlier work or a work ``based on'' the earlier work. + +A ``covered work'' means either the unmodified Program or a work based +on the Program. + +To ``propagate'' a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To ``convey'' a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays ``Appropriate Legal Notices'' to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +@item Source Code. + +The ``source code'' for a work means the preferred form of the work for +making modifications to it. ``Object code'' means any non-source form +of a work. + +A ``Standard Interface'' means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The ``System Libraries'' of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +``Major Component'', in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The ``Corresponding Source'' for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +@item Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +@item Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +@item Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +@item Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +@enumerate a +@item +The work must carry prominent notices stating that you modified it, +and giving a relevant date. + +@item +The work must carry prominent notices stating that it is released +under this License and any conditions added under section 7. This +requirement modifies the requirement in section 4 to ``keep intact all +notices''. + +@item +You must license the entire work, as a whole, under this License to +anyone who comes into possession of a copy. This License will +therefore apply, along with any applicable section 7 additional terms, +to the whole of the work, and all its parts, regardless of how they +are packaged. This License gives no permission to license the work in +any other way, but it does not invalidate such permission if you have +separately received it. + +@item +If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your work +need not make them do so. +@end enumerate + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +``aggregate'' if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +@item Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +@enumerate a +@item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium customarily +used for software interchange. + +@item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a written +offer, valid for at least three years and valid for as long as you +offer spare parts or customer support for that product model, to give +anyone who possesses the object code either (1) a copy of the +Corresponding Source for all the software in the product that is +covered by this License, on a durable physical medium customarily used +for software interchange, for a price no more than your reasonable +cost of physically performing this conveying of source, or (2) access +to copy the Corresponding Source from a network server at no charge. + +@item +Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is +allowed only occasionally and noncommercially, and only if you +received the object code with such an offer, in accord with subsection +6b. + +@item +Convey the object code by offering access from a designated place +(gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to copy +the object code is a network server, the Corresponding Source may be +on a different server (operated by you or a third party) that supports +equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. +Regardless of what server hosts the Corresponding Source, you remain +obligated to ensure that it is available for as long as needed to +satisfy these requirements. + +@item +Convey the object code using peer-to-peer transmission, provided you +inform other peers where the object code and Corresponding Source of +the work are being offered to the general public at no charge under +subsection 6d. + +@end enumerate + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A ``User Product'' is either (1) a ``consumer product'', which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +``normally used'' refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +``Installation Information'' for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +@item Additional Terms. + +``Additional permissions'' are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +@enumerate a +@item +Disclaiming warranty or limiting liability differently from the terms +of sections 15 and 16 of this License; or + +@item +Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices +displayed by works containing it; or + +@item +Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + +@item +Limiting the use for publicity purposes of names of licensors or +authors of the material; or + +@item +Declining to grant rights under trademark law for use of some trade +names, trademarks, or service marks; or + +@item +Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with +contractual assumptions of liability to the recipient, for any +liability that these contractual assumptions directly impose on those +licensors and authors. +@end enumerate + +All other non-permissive additional terms are considered ``further +restrictions'' within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +@item Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +@item Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +@item Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An ``entity transaction'' is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +@item Patents. + +A ``contributor'' is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's ``contributor version''. + +A contributor's ``essential patent claims'' are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, ``control'' includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a ``patent license'' is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To ``grant'' such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. ``Knowingly relying'' means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is ``discriminatory'' if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +@item No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey +a covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree +to terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +@item Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +@item Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If +the Program does not specify a version number of the GNU General +Public License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +@item Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +@item Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +@item Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +@end enumerate + +@heading END OF TERMS AND CONDITIONS + +@heading How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +@smallexample +@var{one line to give the program's name and a brief idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see @url{http://www.gnu.org/licenses/}. +@end smallexample + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +@smallexample +@var{program} Copyright (C) @var{year} @var{name of author} +This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. +This is free software, and you are welcome to redistribute it +under certain conditions; type @samp{show c} for details. +@end smallexample + +The hypothetical commands @samp{show w} and @samp{show c} should show +the appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an ``about box''. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a ``copyright disclaimer'' for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +@url{http://www.gnu.org/licenses/}. + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. But +first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. diff --git a/doc/instrument-control.info b/doc/instrument-control.info new file mode 100644 index 0000000..48f482a --- /dev/null +++ b/doc/instrument-control.info @@ -0,0 +1,4950 @@ +This is instrument-control.info, produced by makeinfo version 6.7 from +instrument-control.texi. + + +File: instrument-control.info, Node: Top, Next: Installing and loading, Up: (dir) + +Introduction +************ + +The Instrument Control toolkit is a set of low level I/O functions for +serial, i2c, spi, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces + +* Menu: + +* Installing and loading:: Installing and loading the toolkit +* Basic Usage Overview:: Basic Usage Overview +* Function Reference:: Instrument Control functions +* Copying:: Copying +* Index:: Index + + +File: instrument-control.info, Node: Installing and loading, Next: Basic Usage Overview, Prev: Top, Up: Top + +1 Installing and loading +************************ + +The Instrument Control toolkit must be installed and then loaded to be +used. + +It can be installed in GNU Octave directly from octave-forge, or can be +installed in an off-line mode via a downloaded tarball. + +The toolkit must be then be loaded once per each GNU Octave session in +order to use its functionality. + +1.1 Requirements +================ + +For GPIB support (Linux only), linux-gpib must be installed before +installing instrument-control. GPIB support is also available for +windows by following the information from the wiki: +https://wiki.octave.org/Instrument_control_package#Requirements + +For VXI11 support, rpcgen, and libtirpc-devel must be installed before +installing instrument-control. + +1.2 Windows install +=================== + +If using the GNU Octave installer in Windows, the toolkit will have +already been installed, and does not need to be re-installed unless a +newer version is available. + +Run the following command to verify if the toolkit is available: + + pkg list instrument-control + +1.3 Online Direct install +========================= + +With an internet connection available, toolkit can be installed from +octave-forge using the following command within GNU Octave: + + pkg install -forge instrument-control + +The latest released version of the toolkit will be downloaded, compiled +and installed. + +1.4 Off-line install +==================== + +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.7.0.tar.gz + +1.5 Loading +=========== + +Regardless of the method of installing the toolkit, in order to use its +functions, the toolkit must be loaded using the pkg load command: + + pkg load instrument-control + +The toolkit must be loaded on each GNU Octave session. + + +File: instrument-control.info, Node: Basic Usage Overview, Next: Function Reference, Prev: Installing and loading, Up: Top + +2 Basic Usage Overview +********************** + +* Menu: + +* Authors:: +* Available Interface:: +* Basic Serial:: +* Basic TCP:: +* Basic UDP:: + + +File: instrument-control.info, Node: Authors, Next: Available Interface, Up: Basic Usage Overview + +2.1 Authors +=========== + +The Instrument control package provides low level I/O functions for +serial, i2c, spi, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces. + +It was written mainly by the following developers: + + * Andrius Sutas + * Stefan Mahr + * John Donoghue + + +File: instrument-control.info, Node: Available Interface, Next: Basic Serial, Prev: Authors, Up: Basic Usage Overview + +2.2 Available Interfaces +======================== + +The ability to use each interface is dependent on OS and what libraries +were available during the toolkit install. + +To verify the available interfaces, run the following command in octave: + + instrhwinfo + +The function will return information on the supported interfaces that +are available, similar to below: + + ToolboxVersion = 0.7.0 + ToolboxName = octave instrument control package + SupportedInterfaces = + { + [1,1] = gpib + [1,2] = i2c + [1,3] = parallel + [1,4] = serial + [1,5] = serialport + [1,6] = tcp + [1,7] = tcpclient + [1,8] = udp + [1,9] = udpport + [1,10] = usbtmc + [1,11] = vxi11 + } + +Most interfaces have two types of functions: + + * somewhat compatible matlab functions such as fread, fwrite + + * interface specific lower level functions such as udp_read, + udp_write + + +File: instrument-control.info, Node: Basic Serial, Next: Basic TCP, Prev: Available Interface, Up: Basic Usage Overview + +2.3 Basic Serial +================ + +2.3.1 Serial +------------ + +The serial object has been depreciated and may not appear in newer +versions of the instrument-control toolbox. Instead new code should use +the serialport object. + +The serial port can be opened using the serial function: + + s = serial("/dev/ttyUSB1", 115200) + +The first parameter is the device name and is OS specific. The second +parameter is the baudrate. + +A list of available serial ports can be retrieved using the function: + + seriallist + +After creating the interface object, properties of the device can be set +or retrieved using get or set functions or as property access. + + s = serial("/dev/ttyUSB1", 115200) + br = get(s, "baudrate") # gets the baudrate + br = s.baudrate # also gets the baudrate + + set(s, "baudrate", 9600) # set the baudrate + s.baudrate = 9600 # also sets the baudrate + +The device can be written and read from using fread, fwrite and srl_read +and slr_write functions. + + srl_write(s, "hello world") # write hello world + fprintf(s, "hello again") + + val = srl_read(s, 10) # attempt to read + val = fread(s, 10) + +The device can be closed using fclose or srl_close. + + fclose(s) + +2.3.2 SerialPort +---------------- + +The recommended method of accessing serial ports is through the +serialport object. + +The serial port can be opened using the serialport function: + + s = serialport("/dev/ttyUSB1", 115200) + +The first parameter is the device name and is OS specific. The second +parameter is the baudrate. + +A list of available serial ports can be retrieved using the function: + + serialportlist + +After creating the interface object, properties of the device can be set +or retrieved using get or set functions or as property access. + + s = serialport("/dev/ttyUSB1", 115200) + br = get(s, "BaudRate") # gets the baudrate + br = s.BaudRate # also gets the baudrate + + set(s, "BaudRate", 9600) # set the baudrate + s.BaudRate = 9600 # also sets the baudrate + +The device can be written and read from using read and write functions. + + write(s, "hello world") # write hello world + + val = read(s, 10) + +The device can be closed by clearing the serialport object. + + clear s + + +File: instrument-control.info, Node: Basic TCP, Next: Basic UDP, Prev: Basic Serial, Up: Basic Usage Overview + +2.4 Basic TCP +============= + +2.4.1 TCP +--------- + +The TCP object has been depreciated and may not appear in newer versions +of the instrument-control toolbox. Instead new code should use the +tcpclient object. + +A TCP connection can be opened using the tcp or tcpip function: + + s = tcp("127.0.0.1", 80) + +The first parameter is the IP address to connect to. The second +parameter is the port number. And optional timeout value can be also be +provided. + +A more matlab compatible function is available as tcpip to also open a +tcp port: + + s = tcpip("gnu.org", 80) + +The first parameter is a hostname or ip address, the second the port +number. Additional parameter/value pairs can be provided after the +port. + +After creating the interface object, properties of the device can be set +or retrieved using get or set functions or as property access. + + s = tcp("127.0.0.1", 80) + oldtimeout = get(s, "timeout") # get timeout + + set(s, "timeout", 10) # set the timeout + s.timeout = oldtimeout # also sets the timeout + +The device can be written and read from using fread, fwrite and tcp_read +and tcp_write functions. + + tcp_write(s, "HEAD / HTTP/1.1\r\n\r\n") + + val = tcp_read(s, 100, 500) # attempt to read 100 bytes + +The device can be closed using fclose or tcp_close. + + fclose(s) + +2.4.2 TCP Client +---------------- + +The recommended method of creating a tcp connection is through the +tcpclient object. + +A TCP connection can be opened using the tcpclient function: + + s = tcpclient("127.0.0.1", 80) + +The first parameter is the IP address or hostname to connect to. The +second parameter is the port number. + +Additional parameter/value pairs can be provided after the port. + +After creating the interface object, properties of the device can be set +or retrieved using get or set functions or as property access. + + s = tcpclient("127.0.0.1", 80) + oldtimeout = get(s, "Timeout") # get timeout + + set(s, "Timeout", 10) # set the timeout + s.Timeout = oldtimeout # also sets the timeout + +The device can be written and read from using read and write functions. + + write(s, "HEAD / HTTP/1.1\r\n\r\n") + + val = read(s, 100) # attempt to read 100 bytes + +The device can be closed by clearing the object variable. + + clear s + + +File: instrument-control.info, Node: Basic UDP, Prev: Basic TCP, Up: Basic Usage Overview + +2.5 Basic UDP +============= + +2.5.1 UDP +--------- + +The UDP object has been depreciated and may not appear in newer versions +of the instrument-control toolbox. Instead new code should use the +udpport object. + +A UDP connection can be opened using the udp function: + + s = udp("127.0.0.1", 80) + +The first parameter is the IP address data will be to. The second +parameter is the port number. + +If and ip address and port is not provides, it will default to +"127.0.0.1" and 23. + +The address and port can be changed after creation using the remotehost +and remoteport properties. + + s = udp() + s.remotehost = "127.0.0.1"; + s.remoteport = 100; + +After creating the interface object, other properties of the device can +be set or retrieved using get or set functions or as property access. + + s = udp("127.0.0.1", 80) + oldtimeout = get(s, "timeout") # get timeout + + set(s, "timeout", 10) # set the timeout + s.timeout = oldtimeout # also sets the timeout + +The device can be written and read from using fread, fwrite and udp_read +and udp_write functions. + + udp_write(s, "test") + + val = udp_read(s, 5) + +The device can be closed using fclose or udp_close. + + fclose(s) + +2.5.2 UDP Port +-------------- + +The recommended method of creating a udp socket is through the udpport +object. + +A udpport object can be created using the udpport function: + + s = udpport() + +Additional parameter/value pairs can be provided during creation of the +object. + +After creating the interface object, properties of the device can be set +or retrieved using get or set functions or as property access. + + s = udpport() + oldtimeout = get(s, "Timeout") # get timeout + + set(s, "Timeout", 10) # set the timeout + s.Timeout = oldtimeout # also sets the timeout + +The device can be written and read from using read and write functions. + +The destination address and port to send data to must be specified at +least on the first time write is used. + + write(s, "test", "127.0.0.1", s.LocalPort) + + val = read(s) + +The device can be closed by clearing the object variable. + + clear s + + +File: instrument-control.info, Node: Function Reference, Next: Copying, Prev: Basic Usage Overview, Up: Top + +3 Function Reference +******************** + +The functions currently available in the toolkit are described below. + +* Menu: + +* Common Functions:: +* General:: +* GPIB:: +* I2C:: +* Parallel:: +* Serial (Depreciated):: +* Serial Port:: +* SPI:: +* TCP (Depreciated):: +* TCP Client:: +* UDP (Depreciated):: +* UDP Port:: +* USBTMC:: +* VXI11:: + + +File: instrument-control.info, Node: Common Functions, Next: General, Up: Function Reference + +3.1 Common Functions +==================== + +3.1.1 flushinput +---------------- + + -- : flushinput (DEV) + Flush the instruments input buffers + + Inputs + ...... + + DEV - connected device or array of devices + + Outputs + ....... + + None + + See also: flushoutput. + +3.1.2 flushoutput +----------------- + + -- : flushoutput (DEV) + Flush the instruments output buffers + + Inputs + ...... + + DEV - connected device or array of devices + + Outputs + ....... + + None + + See also: flushinput. + + +File: instrument-control.info, Node: General, Next: GPIB, Prev: Common Functions, Up: Function Reference + +3.2 General +=========== + +3.2.1 instrhelp +--------------- + + -- : instrhelp () + -- : instrhelp (FUNCNAME) + -- : instrhelp (OBJ) + Display instrument help + + Inputs + ...... + + FUNCNAME - function to display help about. + OBJ - object to display help about. + + If no input is provided, the function will display and overview of + the package functionality. + + Outputs + ....... + + None + +3.2.2 instrhwinfo +----------------- + + -- Function File: [LIST] = instrhwinfo () + -- Function File: LIST = instrhwinfo (INTERFACE) + Query available hardware for instrument-control + + When run without any input parameters, instrhwinfo will provide the + toolbox information and a list of supported interfaces. + + Inputs + ...... + + INTERFACE is the instrument interface to query. When provided, + instrhwinfo will provide information on the specified interface. + + Currently only interface "serialport","i2c" and "spi" and is + supported, which will provide a list of available serial ports or + i2c ports. + + Outputs + ....... + + If an output variable is provided, the function will store the + information to the variable, otherwise it will be displayed to the + screen. + + Example + ....... + + instrhwinfo + scalar structure containing the fields: + + ToolboxVersion = 0.4.0 + ToolboxName = octave instrument control package + SupportedInterfaces = + { + [1,1] = i2c + [1,2] = parallel + [1,3] = serialport + [1,4] = tcp + [1,5] = udp + [1,6] = usbtmc + [1,7] = vxi11 + } + + +3.2.3 resolvehost +----------------- + + -- Loadable Function: NAME = resolvehost (HOST) + -- Loadable Function: [NAME, ADDRESS] = resolvehost (HOST) + -- Loadable Function: OUT = resolvehost (HOST, RETURNTYPE) + + Resolve a network host name or address to network name and address + + Inputs + ...... + + HOST - Host name or IP address string to resolve. + NAME - Resolved IP host name. + RETURNTYPE - 'name' to get host name, 'address' to get IP address. + + Outputs + ....... + + NAME - Resolved IP host name. + ADDRESS - Resolved IP host address. + OUT - host name if RETURNTYPE is 'name', ipaddress if RETURNTYPE is + 'address' + + Example + ....... + + %% get resolved ip name and address pf www.gnu.org + [name, address] = resolvehost ('www.gnu.org'); + + %% get ip address of www.gnu.org + ipaddress = resolvehost ('www.gnu.org', 'address'); + + + See also: tcp, udp. + + +File: instrument-control.info, Node: GPIB, Next: I2C, Prev: General, Up: Function Reference + +3.3 GPIB +======== + +3.3.1 @octave_gpib/fclose +------------------------- + + -- Function File: RES = fclose (OBJ) + Closes connection to GPIB device OBJ + +3.3.2 @octave_gpib/fopen +------------------------ + + -- Function File: RES = fopen (OBJ) (dummy) + Opens connection to GPIB device OBJ This currently is a dummy + function to improve compatibility to MATLAB + +3.3.3 @octave_gpib/fprintf +-------------------------- + + -- Function File: fprintf (OBJ, CMD) + -- Function File: fprintf (OBJ, FORMAT, CMD) + -- Function File: fprintf (OBJ, CMD, MODE) + -- Function File: fprintf (OBJ, FORMAT, CMD, MODE) + Writes string CMD to GPIB instrument + + OBJ is a GPIB object + + CMD String FORMAT Format specifier MODE sync + +3.3.4 @octave_gpib/fread +------------------------ + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from GPIB instrument + + OBJ is a GPIB object + + SIZE Number of values to read. (Default: 100) PRECISION precision + of data + + COUNT values read ERRMSG read operation error message + +3.3.5 @octave_gpib/fscanf +------------------------- + + -- Function File: RES = fscanf (OBJ) + -- Function File: RES = fscanf (OBJ, FORMAT) + -- Function File: RES = fscanf (OBJ, FORMAT, SIZE) + -- Function File: [RES,COUNT] = fscanf (OBJ, ...) + -- Function File: [RES,COUNT,ERRMSG] = fscanf (OBJ, ...) + Reads data RES from GPIB instrument + + OBJ is a GPIB object + + FORMAT Format specifier SIZE number of values + + COUNT values read ERRMSG read operation error message + +3.3.6 @octave_gpib/fwrite +------------------------- + + -- Function File: fwrite (OBJ, DATA) + -- Function File: fwrite (OBJ, DATA, PRECISION) + -- Function File: fwrite (OBJ, DATA, MODE) + -- Function File: fwrite (OBJ, DATA, PRECISION, MODE) + Writes DATA to GPIB instrument + + OBJ is a GPIB object + + DATA data to write PRECISION precision of data MODE sync + +3.3.7 clrdevice +--------------- + + -- Function File: clrdevice (OBJ) + Send clear command to Clear GPIB instrument. + + OBJ is a GPIB object + +3.3.8 gpib +---------- + + -- Loadable Function: GPIB = gpib ([GPIBID], [TIMEOUT]) + + Open gpib interface. + + GPIBID - the interface number. + TIMEOUT - the interface timeout value. If omitted defaults to + blocking call. + + The gpib() shall return instance of OCTAVE_GPIB class as the result + GPIB. + +3.3.9 gpib_close +---------------- + + -- Loadable Function: gpib_close (GPIB) + + Close the interface and release a file descriptor. + + GPIB - instance of OCTAVE_GPIB class. + +3.3.10 gpib_read +---------------- + + -- Loadable Function: [DATA, COUNT, EOI] = gpib_read (GPIB, N) + + Read from gpib interface. + + GPIB - instance of OCTAVE_GPIB class. + N - number of bytes to attempt to read of type Integer. + + The gpib_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + EOI indicates read operation complete + +3.3.11 gpib_timeout +------------------- + + -- Loadable Function: gpib_timeout (GPIB, TIMEOUT) + -- Loadable Function: T = gpib_timeout (GPIB) + + Set new or get existing gpib interface timeout parameter. The + timeout value is valid from 0 to 17. + + GPIB - instance of OCTAVE_GPIB class. + TIMEOUT - Value of 0 means never timeout, 11 means one second and + 17 means 1000 seconds (see GPIB documentation (ibtmo) for further + details) + + If TIMEOUT parameter is omitted, the gpib_timeout() shall return + current timeout value as the result T. + +3.3.12 gpib_write +----------------- + + -- Loadable Function: N = gpib_write (GPIB, DATA) + + Write data to a gpib interface. + + GPIB - instance of OCTAVE_GPIB class. + DATA - data to be written to the gpib interface. Can be either of + String or uint8 type. + + Upon successful completion, gpib_write() shall return the number of + bytes written as the result N. + +3.3.13 spoll +------------ + + -- Function File: OUT = spoll (OBJ) + -- Function File: [OUT,STATUSBYTE] = spoll (OBJ) + Serial polls GPIB instruments. + + OBJ is a GPIB object or a cell array of GPIB objects + + OUT GPIB objects ready for service STATUSBYTE status Byte + +3.3.14 trigger +-------------- + + -- Function File: trigger (OBJ) + Triggers GPIB instrument. + + OBJ is a GPIB object + + +File: instrument-control.info, Node: I2C, Next: Parallel, Prev: GPIB, Up: Function Reference + +3.4 I2C +======= + +3.4.1 @octave_i2c/fclose +------------------------ + + -- Function File: RES = fclose (OBJ) + Closes I2C connection OBJ + +3.4.2 @octave_i2c/fopen +----------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens I2C connection OBJ + + This currently is a dummy function to improve compatibility to + MATLAB + +3.4.3 @octave_i2c/fread +----------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from I2C instrument + + Inputs + ...... + + OBJ is a I2C object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA data values. + COUNT number of values read. + ERRMSG read operation error message. + +3.4.4 @octave_i2c/fwrite +------------------------ + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to I2C instrument + + Inputs + ...... + + OBJ is a I2C object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.4.5 @octave_i2c/get +--------------------- + + -- Function File: STRUCT = get (I2C) + -- Function File: FIELD = get (I2C, PROPERTY) + Get the properties of i2c object. + + Inputs + ...... + + I2C - instance of OCTAVE_I2C class. + + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_i2c/set. + +3.4.6 @octave_i2c/set +--------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of i2c object. + + Inputs + ...... + + OBJ - instance of OCTAVE_I2C class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the i2c socket. + + 'REMOTEADDRESS' + Set the remote address for the i2c socket. + + Outputs + ....... + + None + + See also: @octave_i2c/get. + +3.4.7 i2c +--------- + + -- Loadable Function: I2C = i2c ([PORT_PATH], [ADDRESS]) + + Open i2c interface. + + Inputs + ...... + + PORT_PATH - the interface device port/path of type String. If + omitted defaults to '/dev/i2c-0'. + ADDRESS - the slave device address. If omitted must be set using + i2c_addr() call. + + Outputs + ....... + + I2C - An instance of OCTAVE_I2C class. + + Properties + .......... + + The i2c object has the following properties: + name + Name of the object + remoteaddress + the slave device address + port + The interface driver port (readonly) + +3.4.8 i2c_addr +-------------- + + -- Loadable Function: i2c_addr (I2C, ADDRESS) + -- Loadable Function: ADDR = i2c_addr (I2C) + + Set new or get existing i2c slave device address. + + Inputs + ...... + + I2C - instance of OCTAVE_I2C class. + ADDRESS - i2c slave device address of type Integer. The address is + passed in the 7 or 10 lower bits of the argument. + + Outputs + ....... + + ADDR - If ADDRESS parameter is omitted, the i2c_addr() shall return + current i2c slave device address. + +3.4.9 i2c_close +--------------- + + -- Loadable Function: i2c_close (I2C) + + Close the interface and release a file descriptor. + + Inputs + ...... + + I2C - instance of OCTAVE_I2C class. + + Outputs + ....... + + None + +3.4.10 i2c_read +--------------- + + -- Loadable Function: [DATA, COUNT] = i2c_read (I2C, N) + + Read from i2c slave device. + + Inputs + ...... + + I2C - instance of OCTAVE_I2C class. + N - number of bytes to attempt to read of type Integer. + + Outputs + ....... + + The i2c_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + +3.4.11 i2c_write +---------------- + + -- Loadable Function: N = i2c_write (I2C, DATA) + + Write data to a i2c slave device. + + Inputs + ...... + + I2C - instance of OCTAVE_I2C class. + DATA - data, of type uint8, to be written to the slave device. + + Outputs + ....... + + Upon successful completion, i2c_write() shall return the number of + bytes written as the result N. + + +File: instrument-control.info, Node: Parallel, Next: Serial (Depreciated), Prev: I2C, Up: Function Reference + +3.5 Parallel +============ + +3.5.1 @octave_parallel/fclose +----------------------------- + + -- Function File: RES = fclose (OBJ) + Closes parallel connection OBJ + +3.5.2 @octave_parallel/fopen +---------------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens parallel interface OBJ + + This currently is a dummy function to improve compatibility to + MATLAB + +3.5.3 @octave_parallel/fread +---------------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from parallel instrument + + Inputs + ...... + + OBJ is a parallel object. + SIZE Number of values to read. (Default: 1). + PRECISION precision of data. + + Outputs + ....... + + DATA The read data. + COUNT values read. + ERRMSG read operation error message. + +3.5.4 @octave_parallel/fwrite +----------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to parallel instrument + + Inputs + ...... + + OBJ is a parallel object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.5.5 parallel +-------------- + + -- Loadable Function: PARALLEL = parallel ([PATH], [DIRECTION]) + + Open Parallel interface. + + Inputs + ...... + + PATH - the interface path of type String. If omitted defaults to + '/dev/parport0'. + DIRECTION - the direction of interface drivers of type Integer, + see: PP_DATADIR for more info. If omitted defaults to 1 (Input). + + Outputs + ....... + + The parallel() shall return instance of OCTAVE_PARALLEL class as + the result PARALLEL. + +3.5.6 pp_close +-------------- + + -- Loadable Function: pp_close (PARALLEL) + + Close the interface and release a file descriptor. + + Inputs + ...... + + PARALLEL - instance of OCTAVE_SERIAL class. + + Outputs + ....... + + None + +3.5.7 pp_ctrl +------------- + + -- Loadable Function: pp_ctrl (PARALLEL, CTRL) + -- Loadable Function: C = pp_ctrl (PARALLEL) + + Sets or Read the Control lines. + + Inputs + ...... + + PARALLEL - instance of OCTAVE_PARALLEL class. + CTRL - control parameter to be set of type Byte. + + Outputs + ....... + + If CTRL parameter is omitted, the pp_ctrl() shall return current + Control lines state as the result C. + +3.5.8 pp_data +------------- + + -- Loadable Function: pp_data (PARALLEL, DATA) + -- Loadable Function: D = pp_data (PARALLEL) + + Sets or Read the Data lines. + + Inputs + ...... + + PARALLEL - instance of OCTAVE_PARALLEL class. + DATA - data parameter to be set of type Byte. + + Outputs + ....... + + If DATA parameter is omitted, the pp_data() shall return current + Data lines state as the result D. + +3.5.9 pp_datadir +---------------- + + -- Loadable Function: pp_datadir (PARALLEL, DIRECTION) + -- Loadable Function: DIR = pp_datadir (PARALLEL) + + Controls the Data line drivers. + + Normally the computer's parallel port will drive the data lines, + but for byte-wide transfers from the peripheral to the host it is + useful to turn off those drivers and let the peripheral drive the + signals. (If the drivers on the computer's parallel port are left + on when this happens, the port might be damaged.) + + Inputs + ...... + + PARALLEL - instance of OCTAVE_PARALLEL class. + DIRECTION - direction parameter of type Integer. Supported values: + 0 - the drivers are turned on (Output/Forward direction); 1 - the + drivers are turned off (Input/Reverse direction). + + Outputs + ....... + + If DIRECTION parameter is omitted, the pp_datadir() shall return + current Data direction as the result DIR. + +3.5.10 pp_stat +-------------- + + -- Loadable Function: STAT = pp_stat (PARALLEL) + + Reads the Status lines. + + Inputs + ...... + + PARALLEL - instance of OCTAVE_PARALLEL class. + + Outputs + ....... + + The pp_stat() shall return current Status lines state as the result + STAT. + + +File: instrument-control.info, Node: Serial (Depreciated), Next: Serial Port, Prev: Parallel, Up: Function Reference + +3.6 Serial (Depreciated) +======================== + +3.6.1 @octave_serial/fclose +--------------------------- + + -- Function File: RES = fclose (OBJ) + Closes SERIAL connection OBJ + +3.6.2 @octave_serial/flushinput +------------------------------- + + -- Loadable Function: flushinput (SERIAL) + + Flush the pending input, which will also make the BytesAvailable + property be 0. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + + Outputs + ....... + + None + + See also: srl_flush, flushoutput. + +3.6.3 @octave_serial/flushoutput +-------------------------------- + + -- Loadable Function: flushoutput (SERIAL) + + Flush the output buffer. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + + Outputs + ....... + + None + + See also: srl_flush, flushinput. + +3.6.4 @octave_serial/fopen +-------------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens SERIAL interface OBJ + + This currently is a dummy function to improve compatibility to + MATLAB + +3.6.5 @octave_serial/fprintf +---------------------------- + + -- Function File: NUMBYTES = fprintf (OBJ, TEMPLATE ...) + Writes formatted string TEMPLATE using optional parameters to + serial instrument + + Inputs + ...... + + OBJ is a serial object. + TEMPLATE Format template string + + Outputs + ....... + + NUMBYTES - number of bytes written to the serial device. + +3.6.6 @octave_serial/fread +-------------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from serial instrument + + Inputs + ...... + + OBJ is a serial object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA The read data. + COUNT values read. + ERRMSG read operation error message. + +3.6.7 @octave_serial/fwrite +--------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to serial instrument + + Inputs + ...... + + OBJ is a serial object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.6.8 @octave_serial/get +------------------------ + + -- Function File: STRUCT = get (SERIAL) + -- Function File: FIELD = get (SERIAL, PROPERTY) + Get the properties of serial object. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_serial/set. + +3.6.9 @octave_serial/serialbreak +-------------------------------- + + -- Function File: serialbreak (SERIAL) + -- Function File: serialbreak (SERIAL, TIME) + Send a break to the serial port + + Inputs + ...... + + SERIAL - serial object + TIME - number of milliseconds to break for. If not specified a + value of 10 will be used. + + Outputs + ....... + + None + + See also: serial. + +3.6.10 @octave_serial/set +------------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of serial object. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'BAUDRATE' + Set the baudrate of serial port. Supported values by + instrument-control: 0, 50, 75, 110, 134, 150, 200, 300, 600, + 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200 and + 230400. The supported baudrate of your serial port may be + different. + + 'BYTESIZE' + Set the bytesize. Supported values: 5, 6, 7 and 8. + + 'NAME' + Set the stored string name of the serial object. + + 'PARITY' + Set the parity value. Supported values: Even/Odd/None. This + Parameter must be of type string. It is case insensitive and + can be abbreviated to the first letter only + + 'STOPBITS' + Set the number of stopbits. Supported values: 1, 2. + + 'TIMEOUT' + Set the timeout value in tenths of a second. Value of -1 + means a blocking call. Maximum value of 255 (i.e. 25.5 + seconds). + + 'REQUESTTOSEND' + Set the requesttosend (RTS) line. + + 'DATATERMINALREADY' + Set the dataterminalready (DTR) line. + + Outputs + ....... + + None + + See also: @octave_serial/get. + +3.6.11 @octave_serial/srl_baudrate +---------------------------------- + + -- Loadable Function: srl_baudrate (SERIAL, BAUDRATE)\ + -- Loadable Function: BR = srl_baudrate (SERIAL) + + Set new or get existing serial interface baudrate parameter. Only + standard values are supported. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + BAUDRATE - the baudrate value used. Supported values: 0, 50, 75, + 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600 19200, + 38400, 57600, 115200 and 230400. + + If BAUDRATE parameter is omitted, the srl_baudrate() shall return + current baudrate value as the result BR. + + Outputs + ....... + + BR - The currently set baudrate + + This function is obsolete. Use get and set method instead. + +3.6.12 @octave_serial/srl_bytesize +---------------------------------- + + -- Loadable Function: srl_bytesize (SERIAL, BSIZE) + -- Loadable Function: BS = srl_bytesize (SERIAL) + + Set new or get existing serial interface byte size parameter. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + BSIZE - byte size of type Integer. Supported values: 5/6/7/8. + + If BSIZE parameter is omitted, the srl_bytesize() shall return + current byte size value or in case of unsupported setting -1, as + the result BS. + + This function is obsolete. Use get and set method instead. + + Outputs + ....... + + BS -the currently set byte size. + +3.6.13 @octave_serial/srl_close +------------------------------- + + -- Loadable Function: srl_close (SERIAL) + + Close the interface and release a file descriptor. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + + This function is obsolete. Use fclose() method instead. + + Outputs + ....... + + None + +3.6.14 @octave_serial/srl_flush +------------------------------- + + -- Loadable Function: srl_flush (SERIAL, [Q]) + + Flush the pending input/output. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + Q - queue selector of type Integer. Supported values: + 0 + flush untransmitted output + 1 + flush pending input + 2 + flush both pending input and untransmitted output. + + If Q parameter is omitted, the srl_flush() shall flush both, input + and output buffers. + + Outputs + ....... + + None + +3.6.15 @octave_serial/srl_parity +-------------------------------- + + -- Loadable Function: srl_parity (SERIAL, PARITY) + -- Loadable Function: P = srl_parity (SERIAL) + + Set new or get existing serial interface parity parameter. + Even/Odd/None values are supported. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + PARITY - parity value of type String. Supported values: + Even/Odd/None (case insensitive, can be abbreviated to the first + letter only) + + If PARITY parameter is omitted, the srl_parity() shall return + current parity value as the result P. + + This function is obsolete. Use get and set method instead. + + Outputs + ....... + + P - The currently set parity + +3.6.16 @octave_serial/srl_stopbits +---------------------------------- + + -- Loadable Function: srl_stopbits (SERIAL, STOPB) + -- Loadable Function: SB = srl_stopbits (SERIAL) + + Set new or get existing serial interface stop bits parameter. Only + 1 or 2 stop bits are supported. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + STOPB - number of stop bits used. Supported values: 1, 2. + + Outputs + ....... + + If STOPB parameter is omitted, the srl_stopbits() shall return + current stop bits value as the result SB. + + This function is obsolete. Use get and set method instead. + +3.6.17 @octave_serial/srl_timeout +--------------------------------- + + -- Loadable Function: srl_timeout (SERIAL, TIMEOUT) + -- Loadable Function: T = srl_timeout (SERIAL) + + Set new or get existing serial interface timeout parameter used for + srl_read() requests. The timeout value is specified in tenths of a + second. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + TIMEOUT - srl_read() timeout value in tenths of a second. A value + of -1 means a blocking call. Maximum value of 255 (i.e. 25.5 + seconds). + + Outputs + ....... + + If TIMEOUT parameter is omitted, the srl_timeout() shall return + current timeout value as the result T. + + This function is obsolete. Use get and set method instead. + +3.6.18 serial +------------- + + -- Loadable Function: SERIAL = serial ([PATH], [BAUDRATE], [TIMEOUT]) + + Open serial interface. + + Inputs + ...... + + PATH - the interface path of type String. + BAUDRATE - the baudrate of interface. If omitted defaults to + 115200. + TIMEOUT - the interface timeout value. If omitted defaults to + blocking call. + + Outputs + ....... + + The serial() shall return an instance of OCTAVE_SERIAL class as the + result SERIAL. + + Properties + .......... + + The serial object has the following public properties: + name + name assigned to the object + type + instrument type 'serial' (readonly) + port + OS specific port name (readonly) + status + status of the object 'open' or 'closed' (readonly) + timeout + timeout value used for waiting for data + bytesavailable + number of bytes currently available to read (readonly) + stopbits + number of stopbits to use + requesttosend + request to send state - 'on' or 'off' + parity + Parity setting 'none', 'even', 'odd' + bytesize + Number of bits to a byte (7 or 8) + baudrate + Baudrate setting + dataterminalready + state of dataterminal ready - 'on' or 'off' + pinstatus + current state of pins (readonly) + +3.6.19 seriallist +----------------- + + -- Function File: LIST = seriallist () + Returns a list of all serial ports detected in the system. + + Inputs + ...... + + None + + Outputs + ....... + + LIST is a string cell array of serial ports names detected in the + system. + + See also: instrhwinfo("serial"). + +3.6.20 srl_read +--------------- + + -- Loadable Function: [DATA, COUNT] = srl_read (SERIAL, N) + + Read from serial interface. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + N - number of bytes to attempt to read of type Integer. + + Outputs + ....... + + The srl_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + +3.6.21 srl_write +---------------- + + -- Loadable Function: N = srl_write (SERIAL, DATA) + + Write data to a serial interface. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIAL class. + DATA - data to be written to the serial interface. Can be either + of String or uint8 type. + + Outputs + ....... + + Upon successful completion, srl_write() shall return the number of + bytes written as the result N. + + +File: instrument-control.info, Node: Serial Port, Next: SPI, Prev: Serial (Depreciated), Up: Function Reference + +3.7 Serial Port +=============== + +3.7.1 @octave_serialport/configureTerminator +-------------------------------------------- + + -- Function File: configureTerminator (SERIAL, TERM) + -- Function File: configureTerminator (SERIAL, READTERM, WRITETERM) + Set terminator for ASCII string manipulation + + Inputs + ...... + + SERIAL - serialport object + TERM - terminal value for both read and write + READTERM = terminal value type for read data + WRITETERM = terminal value for written data + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or + an integer between 0 to 255. + + Outputs + ....... + + None + + See also: serialport. + +3.7.2 @octave_serialport/flush +------------------------------ + + -- : DATA = flush (DEV) + -- : DATA = flush (DEV, "input") + -- : DATA = flush (DEV, "output") + Flush the serial port buffers + + Inputs + ...... + + DEV - connected serialport device + + If an additional parameter is provided of "input" or "output", then + only the input or output buffer will be flushed + + Outputs + ....... + + None + + See also: serialport. + +3.7.3 @octave_serialport/fprintf +-------------------------------- + + -- Function File: NUMBYTES = fprintf (OBJ, TEMPLATE ...) + Writes formatted string TEMPLATE using optional parameters to + serialport instrument + + Inputs + ...... + + OBJ is a serialport object. + TEMPLATE Format template string + + Outputs + ....... + + NUMBYTES - number of bytes written to the serial device. + +3.7.4 @octave_serialport/fread +------------------------------ + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from serial port instrument + + Inputs + ...... + + OBJ is a serialport object. + SIZE Number of values to read. + PRECISION precision of data. + + Outputs + ....... + + DATA The read data. + COUNT number of values read. + ERRMSG read operation error message. + +3.7.5 @octave_serialport/fwrite +------------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to serial port instrument + + Inputs + ...... + + OBJ is a serial port object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.7.6 @octave_serialport/get +---------------------------- + + -- Function File: STRUCT = get (SERIAL) + -- Function File: FIELD = get (SERIAL, PROPERTY) + Get the properties of serialport object. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIALPORT class. + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_serial/set. + +3.7.7 @octave_serialport/getpinstatus +------------------------------------- + + -- Function File: STATUS getpinstatus (SERIAL) + Get status of serial pins + + Inputs + ...... + + SERIAL - serial object + + Outputs + ....... + + STATUS - a structure with the logic names of ClearToSend, + DataSetReady, CarrierDetect, and RingIndicator + + See also: serialport. + +3.7.8 @octave_serialport/read +----------------------------- + + -- : DATA = read (DEV, COUNT) + -- : DATA = read (DEV, COUNT, PRECISION) + Read a specified number of values from a serialport using optional + precision for valuesize. + + Inputs + ...... + + DEV - connected serialport device + + COUNT - number of elements to read + + PRECISION - Optional precision for the output data read data. + Currently known precision values are uint8 (default), int8, uint16, + int16, uint32, int32, uint64, uint64 + + Outputs + ....... + + DATA - data read from the device + + See also: serialport. + +3.7.9 @octave_serialport/serialbreak +------------------------------------ + + -- Function File: serialbreak (SERIAL) + -- Function File: serialbreak (SERIAL, TIME) + Send a break to the serial port + + Inputs + ...... + + SERIAL - serialport object + TIME - number of milliseconds to break for. If not specified a + value of 10 will be used. + + Outputs + ....... + + None + + See also: serial. + +3.7.10 @octave_serialport/set +----------------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of serialport object. + + Inputs + ...... + + SERIAL - instance of OCTAVE_SERIALPORT class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'BAUDRATE' + Set the baudrate of serial port. Supported values by + instrument-control: 0, 50, 75, 110, 134, 150, 200, 300, 600, + 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200 and + 230400. The supported baudrate of your serial port may be + different. + + 'BYTESIZE' + Set the bytesize. Supported values: 5, 6, 7 and 8. + + 'NAME' + Set the stored string name of the serial object. + + 'PARITY' + Set the parity value. Supported values: Even/Odd/None. This + Parameter must be of type string. It is case insensitive and + can be abbreviated to the first letter only + + 'STOPBITS' + Set the number of stopbits. Supported values: 1, 2. + + 'TIMEOUT' + Set the timeout value in tenths of a second. Value of -1 + means a blocking call. Maximum value of 255 (i.e. 25.5 + seconds). + + 'REQUESTTOSEND' + Set the requesttosend (RTS) line. + + 'DATATERMINALREADY' + Set the dataterminalready (DTR) line. + + Outputs + ....... + + None + + See also: @octave_serialport/-get. + +3.7.11 @octave_serialport/setDTR +-------------------------------- + + -- : setDTR (DEV, TRUE_FALSE) + Set the state of the DTR line + + Inputs + ...... + + DEV - connected serial device. + TRUE_FALSE - state to set the line. + + Outputs + ....... + + None + + See also: serialport, getpinstatus, setRTS. + +3.7.12 @octave_serialport/setRTS +-------------------------------- + + -- : setRTS (DEV, TRUE_FALSE) + Set the state of the RTS line + + Inputs + ...... + + DEV - connected serial device. + TRUE_FALSE - state to set the line. + + Outputs + ....... + + None + + See also: serialport, getpinstatus. + +3.7.13 @octave_serialport/write +------------------------------- + + -- Function File: NUMBYTES = write (OBJ, DATA) + -- Function File: NUMBYTES = write (OBJ, DATA, PRECISION) + Writes DATA to serialport instrument + + Inputs + ...... + + OBJ is a serialport object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.7.14 serialport +----------------- + + -- Loadable Function: SERIAL = serialport ([PATH], [BAUDRATE]) + -- Loadable Function: SERIAL = serialport ([PATH], [PROPNAME, + PROPVALUE]) + + Open serial port interface. + + Inputs + ...... + + PATH - the interface path of type String. + BAUDRATE - the baudrate of interface. + PROPNAME,PROPVALUE - property name/value pairs. + + Known input properties: + BaudRate + Numeric baudrate value + Timeout + Numeric timeout value in seconds or -1 to wait forever + StopBits + number of stopbits to use + Parity + Parity setting 'none', 'even', 'odd' + DataBits + Number of bits to a byte (5 to 8) + FlowControl + Number of bits to a byte 'none', 'hardware', 'software' + + Outputs + ....... + + The serialport() shall return an instance of OCTAVE_SERIALPORT + class as the result SERIAL. + + Properties + .......... + + The serial object has the following public properties: + Name + name assigned to the object + Type + instrument type 'serial' (readonly) + Port + OS specific port name (readonly) + Status + status of the object 'open' or 'closed' (readonly) + Timeout + timeout value used for waiting for data + NumBytesAvailable + number of bytes currently available to read (readonly) + NumBytesWritten + number of bytes written (readonly) + StopBits + number of stopbits to use + Parity + Parity setting 'none', 'even', 'odd' + DataBits + Number of bits to a byte (5 to 8) + BaudRate + Baudrate setting + FlowControl + Number of bits to a byte 'none', 'hardware', 'software' + PinStatus + current state of pins (readonly) + UserData + user defined data + +3.7.15 serialportlist +--------------------- + + -- Function File: LIST = serialportlist () + -- Function File: LIST = serialportlist ("all") + -- Function File: LIST = serialportlist ("available") + Returns a list of all serial ports detected in the system. + + Inputs + ...... + + 'all' - show all serial ports (same as providing no arguments) + 'available' - show only serial ports that are available for use + + Outputs + ....... + + LIST is a string cell array of serial ports names detected in the + system. + + See also: instrhwinfo("serialport"). + + +File: instrument-control.info, Node: SPI, Next: TCP (Depreciated), Prev: Serial Port, Up: Function Reference + +3.8 SPI +======= + +3.8.1 @octave_spi/fclose +------------------------ + + -- Function File: RES = fclose (OBJ) + Closes SPI connection OBJ + +3.8.2 @octave_spi/fopen +----------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens SPI connection OBJ + + This currently is a dummy function to improve compatibility to + MATLAB + +3.8.3 @octave_spi/fread +----------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from a SPI instrument + + Inputs + ...... + + OBJ is a SPI object. + SIZE Number of values to read. (Default: 10). + PRECISION precision of data. + + Outputs + ....... + + DATA data values. + COUNT number of values read. + ERRMSG read operation error message. + +3.8.4 @octave_spi/fwrite +------------------------ + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to SPI instrument + + Inputs + ...... + + OBJ is a SPI object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.8.5 @octave_spi/get +--------------------- + + -- Function File: STRUCT = get (SPI) + -- Function File: FIELD = get (SPI, PROPERTY) + Get the properties of spi object. + + Inputs + ...... + + SPI - instance of OCTAVE_SPI class. + + PROPERTY - name of property. + + Properties + .......... + + 'NAME' + Name for the spi socket. + + 'BITRATE' + The bitrate for the spi object. + + 'CLOCKPOLARITY' + The clock polarity for the spi object of 'idlehigh' or + 'idlelow'. + + 'CLOCKPHASE' + The clock phase for the spi object of 'firstedge' or + 'secondedge'. + + 'PORT' + The device port name. + + 'STATUS' + The device status of 'open' or 'closed' + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_spi/set. + +3.8.6 @octave_spi/read +---------------------- + + -- Function File: DATA = read (OBJ) + -- Function File: DATA = read (OBJ, SIZE) + Reads DATA from SPI instrument + + Inputs + ...... + + OBJ is a SPI object. + SIZE Number of values to read. (Default: 10). + + Outputs + ....... + + DATA data values. + +3.8.7 @octave_spi/set +--------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of spi object. + + Inputs + ...... + + OBJ - instance of OCTAVE_SPI class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the spi socket. + + 'BITRATE' + Set the bitrate for the spi object. + + 'CLOCKPOLARITY' + Set the clock polarity for the spi object of 'idlehigh' or + 'idlelow'. + + 'CLOCKPHASE' + Set the clock phase for the spi object of 'firstedge' or + 'secondedge'. + + Outputs + ....... + + None + + See also: @octave_spi/get. + +3.8.8 @octave_spi/write +----------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + Writes DATA to SPI instrument + + Inputs + ...... + + OBJ is a SPI object. + DATA data to write. + + Outputs + ....... + + returns number of bytes written. + +3.8.9 @octave_spi/writeAndRead +------------------------------ + + -- Function File: DATA = writeAndRead (OBJ, WRDATA) + Writes and reads DATA from SPI instrument + + Inputs + ...... + + OBJ is a SPI object. + WRDATA Data to write. + + Outputs + ....... + + DATA data values read. + +3.8.10 spi +---------- + + -- Loadable Function: SPI = spi ([PORT_PATH]) + -- Loadable Function: SPI = spi ([PORT_PATH], [PROPNAME, PROPVALUE]) + + Open a spi interface. + + Inputs + ...... + + PORT_PATH - the interface device port/path of type String. If + omitted defaults to '/dev/spi-0'. + PROPNAME,PROPVALUE - property name/value pairs. + + Known input properties: + name + Name of the object + bitrate + Numeric bitrate value + clockpolarity + Clock polarity: idlehigh or idlelow. + clockphase + Clock phase value: firstedge or secondedge + + Outputs + ....... + + SPI - An instance of OCTAVE_SPI class. + + Properties + .......... + + The spi object has the following properties: + name + Name of the object + status + Open or closed status of object (readonly). + bitrate + Numeric bitrate value + clockpolarity + Clock polarity: idlehigh or idlelow. + clockphase + Clock phase value: firstedge or secondedge + port + The interface driver port (readonly) + +3.8.11 spi_close +---------------- + + -- Loadable Function: spi_close (SPI) + + Close the interface and release a file descriptor. + + Inputs + ...... + + SPI - instance of OCTAVE_SPI class. + + Outputs + ....... + + None + +3.8.12 spi_read +--------------- + + -- Loadable Function: [DATA, COUNT] = spi_read (SPI, N) + + Read from spi slave device. + + Inputs + ...... + + SPI - instance of OCTAVE_SPI class. + N - number of bytes to attempt to read of type Integer. + + Outputs + ....... + + The spi_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + +3.8.13 spi_write +---------------- + + -- Loadable Function: N = spi_write (SPI, DATA) + + Write data to a spi slave device. + + Inputs + ...... + + SPI - instance of OCTAVE_SPI class. + DATA - data, of type uint8, to be written to the slave device. + + Outputs + ....... + + Upon successful completion, spi_write() shall return the number of + bytes written as the result N. + +3.8.14 spi_writeAndRead +----------------------- + + -- Loadable Function: RDDATA = spi_writeAndRead (SPI, WRDATA) + + Write data to a spi slave device and then read same number of + values. + + Inputs + ...... + + SPI - instance of OCTAVE_SPI class. + WRDATA - data, of type uint8, to be written to the slave device. + + Outputs + ....... + + Upon successful completion, spi_writeAndRead() shall return the + bytes read. + + +File: instrument-control.info, Node: TCP (Depreciated), Next: TCP Client, Prev: SPI, Up: Function Reference + +3.9 TCP (Depreciated) +===================== + +3.9.1 @octave_tcp/fclose +------------------------ + + -- Function File: RES = fclose (OBJ) + Closes TCP connection OBJ + +3.9.2 @octave_tcp/flush +----------------------- + + -- : DATA = flush (DEV) + -- : DATA = flush (DEV, "input") + -- : DATA = flush (DEV, "output") + Flush the tcp socket buffers + + Inputs + ...... + + DEV - connected tcp device + + If an additional parameter is provided of "input" or "output", then + only the input or output buffer will be flushed + + Outputs + ....... + + None + + See also: serialport. + +3.9.3 @octave_tcp/flushinput +---------------------------- + + -- Loadable Function: flushinput (TCP) + + Flush the pending input, which will also make the BytesAvailable + property be 0. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + + Outputs + ....... + + None. + + See also: flushoutput. + +3.9.4 @octave_tcp/flushoutput +----------------------------- + + -- Loadable Function: flushoutput (TCP) + + Flush the output buffer. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + + Outputs + ....... + + None. + + See also: flushinput. + +3.9.5 @octave_tcp/fopen +----------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens TCP connection OBJ + + This currently is a dummy function to improve compatibility to + MATLAB + +3.9.6 @octave_tcp/fprintf +------------------------- + + -- Function File: NUMBYTES = fprintf (OBJ, TEMPLATE ...) + Writes formatted string TEMPLATE using optional parameters to TCP + instrument + + Inputs + ...... + + OBJ is a TCP object. + TEMPLATE Format template string + + Outputs + ....... + + Number of characters written + +3.9.7 @octave_tcp/fread +----------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from TCP instrument + + Inputs + ...... + + OBJ is a TCP object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA data read. + COUNT values read. + ERRMSG read operation error message. + +3.9.8 @octave_tcp/fwrite +------------------------ + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to TCP instrument + + Inputs + ...... + + OBJ is a TCP object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.9.9 @octave_tcp/get +--------------------- + + -- Function File: STRUCT = get (TCP) + -- Function File: FIELD = get (TCP, PROPERTY) + Get the properties of tcp object. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_tcp/set. + +3.9.10 @octave_tcp/read +----------------------- + + -- Function File: DATA = read (OBJ) + -- Function File: DATA = read (OBJ, SIZE) + -- Function File: DATA = read (OBJ, SIZE, DATATYPE) + Reads DATA from TCP instrument + + Inputs + ...... + + OBJ is a TCP object. + SIZE Number of values to read. (Default: 100). + DATATYPE datatype of data. + + Outputs + ....... + + DATA data read. + +3.9.11 @octave_tcp/set +---------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of tcp object. + + Inputs + ...... + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the tcp socket. + + 'REMOTEHOST' + Set the remote host name for the tcp socket. + + 'REMOTEPORT' + Set the remote port for the tcp socket. + + 'TIMEOUT' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + Outputs + ....... + + None + + See also: @octave_tcp/get. + +3.9.12 @octave_tcp/write +------------------------ + + -- Function File: NUMBYTES = write (OBJ, DATA) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE) + Writes DATA to TCP instrument + + Inputs + ...... + + OBJ is a TCP object. + DATA data to write. + DATATYPE datatype of data. If not specified, it defaults to + "uint8". + + Outputs + ....... + + returns number of bytes written. + +3.9.13 tcp +---------- + + -- Loadable Function: TCP = tcp () + -- Loadable Function: TCP = tcp (IPADDRESS) + -- Loadable Function: TCP = tcp (IPADDRESS, PORT) + -- Loadable Function: TCP = tcp (IPADDRESS, PORT, TIMEOUT) + -- Loadable Function: TCP = tcp (IPADDRESS, [PROPERTYNAME, + PROPERTYVALUE]) + -- Loadable Function: TCP = tcp (IPADDRESS, PORT, [PROPERTYNAME, + PROPERTYVALUE]) + + Open tcp interface. + + Inputs + ...... + + IPADDRESS - the ip address of type String. If omitted defaults to + '127.0.0.1'. + PORT - the port number to connect. If omitted defaults to 23. + TIMEOUT - the interface timeout value. If omitted defaults to + blocking call. + PROPNAME,PROPVALUE - property name/value pairs. + + Known input properties: + name + name value + timeout + Numeric timeout value or -1 to wait forever + + Outputs + ....... + + The tcp() shall return instance of OCTAVE_TCP class as the result + TCP. + + Properties + .......... + + The tcp object has the following public properties: + name + name assigned to the tcp object + type + instrument type 'tcp' (readonly) + localport + local port number (readonly) + remoteport + remote port number + remotehost + remote host + status + status of the object 'open' or 'closed' (readonly) + timeout + timeout value in seconds used for waiting for data + bytesavailable + number of bytes currently available to read (readonly) + +3.9.14 tcp_close +---------------- + + -- Loadable Function: tcp_close (TCP) + + Close the interface and release a file descriptor. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + + Outputs + ....... + + None + +3.9.15 tcp_read +--------------- + + -- Loadable Function: [DATA, COUNT] = tcp_read (TCP, N, TIMEOUT) + + Read from tcp interface. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + N - number of bytes to attempt to read of type Integer + TIMEOUT - timeout in ms if different from default of type Integer + + Outputs + ....... + + COUNT - number of bytes successfully read as an Integer + DATA - data bytes themselves as uint8 array. + +3.9.16 tcp_timeout +------------------ + + -- Loadable Function: tcp_timeout (TCP, TIMEOUT) + -- Loadable Function: T = tcp_timeout (TCP) + + Set new or get existing tcp interface timeout parameter used for + tcp_read() requests. The timeout value is specified in + milliseconds. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + TIMEOUT - tcp_read() timeout value in milliseconds. Value of -1 + means a blocking call. + + Outputs + ....... + + If TIMEOUT parameter is omitted, the tcp_timeout() shall return + current timeout value as the result T. + +3.9.17 tcp_write +---------------- + + -- Loadable Function: N = tcp_write (TCP, DATA) + + Write data to a tcp interface. + + Inputs + ...... + + TCP - instance of OCTAVE_TCP class. + DATA - data to be written to the tcp interface. Can be either of + String or uint8 type. + + Outputs + ....... + + Upon successful completion, tcp_write() shall return the number of + bytes written as the result N. + +3.9.18 tcpip +------------ + + -- Function File: TCP = tcpip (HOST, [PORT], [PROPERTYNAME, + PROPERTYVALUE...]) + Matlab compatible wrapper to the tcp interface. + + NOTE: tcpip has been depreciated. Use tcpclient instead + + Inputs + ...... + + HOST - the host name or ip. + PORT - the port number to connect. If omitted defaults to 80. + PROPERTYNAME, PROPERTYVALUE - Optional property name, value pairs + to set on the tcp object. + + Properties + .......... + + Currently the only known properties are "timeout" and "name". + + Outputs + ....... + + tcpip will return an instance of OCTAVE_TCP class as the result. + + +File: instrument-control.info, Node: TCP Client, Next: UDP (Depreciated), Prev: TCP (Depreciated), Up: Function Reference + +3.10 TCP Client +=============== + +3.10.1 @octave_tcpclient/configureTerminator +-------------------------------------------- + + -- Function File: configureTerminator (TCP, TERM) + -- Function File: configureTerminator (TCP, READTERM, WRITETERM) + Set terminator on a tcpclient object for ASCII string manipulation + + Inputs + ...... + + TCP - tcpclient object + TERM - terminal value for both read and write + READTERM = terminal value type for read data + WRITETERM = terminal value for written data + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or + an integer between 0 to 255. + + Outputs + ....... + + None + + See also: tcpport. + +3.10.2 @octave_tcpclient/flush +------------------------------ + + -- : DATA = flush (DEV) + -- : DATA = flush (DEV, "input") + -- : DATA = flush (DEV, "output") + Flush the tcpclient socket buffers + + Inputs + ...... + + DEV - connected tcpclient device + + If an additional parameter is provided of "input" or "output", then + only the input or output buffer will be flushed + + Outputs + ....... + + None + + See also: serialport. + +3.10.3 @octave_tcpclient/get +---------------------------- + + -- Function File: STRUCT = get (TCPCLIENT) + -- Function File: FIELD = get (TCPCLIENT, PROPERTY) + Get the properties of tcpclient object. + + Inputs + ...... + + TCPCLIENT - instance of OCTAVE_TCPCLIENT class. + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_tcpclient/set. + +3.10.4 @octave_tcpclient/read +----------------------------- + + -- Function File: DATA = read (OBJ) + -- Function File: DATA = read (OBJ, SIZE) + -- Function File: DATA = read (OBJ, SIZE, DATATYPE) + Reads DATA from TCP instrument + + Inputs + ...... + + OBJ is a TCP object. + SIZE Number of values to read. (Default: NumBytesAvailable). + DATATYPE datatype of data. + + Outputs + ....... + + DATA data read. + +3.10.5 @octave_tcpclient/set +---------------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of tcpclient object. + + Inputs + ...... + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the tcpclient socket. + + 'USERDATA' + Set user data for the tcpclient socket. + + 'TIMEOUT' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + Outputs + ....... + + None + + See also: @octave_tcpclient/get. + +3.10.6 @octave_tcpclient/write +------------------------------ + + -- Function File: NUMBYTES = write (OBJ, DATA) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE) + Writes DATA to TCP instrument + + Inputs + ...... + + OBJ is a TCPclient object. + DATA data to write. + DATATYPE datatype of data. If not specified, it defaults to + "uint8". + + Outputs + ....... + + returns number of bytes written. + +3.10.7 tcpclient +---------------- + + -- Loadable Function: TCPCLIENT = tcpclient (IPADDRESS, PORT) + -- Loadable Function: TCPCLIENT = tcpclient (IPADDRESS, PORT, + [PROPERTYNAME, PROPERTYVALUE]) + + Open tcpclient interface. + + Inputs + ...... + + IPADDRESS - the ip address of type String. + PORT - the port number to connect. + PROPNAME,PROPVALUE - property name/value pairs. + + Known input properties: + Name + name value + Timeout + Numeric timeout value or -1 to wait forever + UserData + User data value. + + Outputs + ....... + + The tcpclient() shall return instance of OCTAVE_TCPCLIENT class as + the result TCPCLIENT. + + Properties + .......... + + The tcpclient object has the following public properties: + Name + name assigned to the tcpclient object + Type + instrument type 'tcpclient' (readonly) + Port + remote port number (Readonly) + Address + remote host address (Readonly) + Status + status of the object 'open' or 'closed' (readonly) + Timeout + timeout value in seconds used for waiting for data + NumBytesAvailable + number of bytes currently available to read (readonly) + NumBytesWritten + number of bytes currently available to read (readonly) + ByteOrder + Byte order for data (currently not used) + Terminator + Terminator value used for string data (currently not used) + UserData + User data + + +File: instrument-control.info, Node: UDP (Depreciated), Next: UDP Port, Prev: TCP Client, Up: Function Reference + +3.11 UDP (Depreciated) +====================== + +3.11.1 @octave_udp/fclose +------------------------- + + -- Function File: RES = fclose (OBJ) + Closes UDP connection OBJ + +3.11.2 @octave_udp/flush +------------------------ + + -- : DATA = flush (DEV) + -- : DATA = flush (DEV, "input") + -- : DATA = flush (DEV, "output") + Flush the udp socket buffers + + Inputs + ...... + + DEV - open udp device + + If an additional parameter is provided of "input" or "output", then + only the input or output buffer will be flushed + + Outputs + ....... + + None + + See also: udp. + +3.11.3 @octave_udp/flushinput +----------------------------- + + -- Loadable Function: flushinput (UDP) + + Flush the pending input, which will also make the BytesAvailable + property be 0. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + + Outputs + ....... + + None + + See also: flushoutput. + +3.11.4 @octave_udp/flushoutput +------------------------------ + + -- Loadable Function: flushoutput (UDP) + + Flush the output buffer. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + + Outputs + ....... + + None + + See also: flushinput. + +3.11.5 @octave_udp/fopen +------------------------ + + -- Function File: RES = fopen (OBJ) (dummy) + Opens UDP connection OBJ This currently is a dummy function to + improve compatibility to MATLAB + +3.11.6 @octave_udp/fprintf +-------------------------- + + -- Function File: NUMBYTES = fprintf (OBJ, TEMPLATE ...) + Writes formatted string TEMPLATE using optional parameters to UDP + instrument + + Inputs + ...... + + OBJ is a UDP object. + TEMPLATE Format template string. + + Outputs + ....... + + NUMBYTES is the number of bytes written to the device + +3.11.7 @octave_udp/fread +------------------------ + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from UDP instrument + + Inputs + ...... + + OBJ is a UDP object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA data values. + COUNT number of values read. + ERRMSG read operation error message. + +3.11.8 @octave_udp/fwrite +------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to UDP instrument + + Inputs + ...... + + OBJ is a UDP object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.11.9 @octave_udp/get +---------------------- + + -- Function File: STRUCT = get (UDP) + -- Function File: FIELD = get (UDP, PROPERTY) + Get the properties of udp object. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_udp/set. + +3.11.10 @octave_udp/read +------------------------ + + -- Function File: DATA = read (OBJ) + -- Function File: DATA = read (OBJ, SIZE) + -- Function File: DATA = read (OBJ, SIZE, DATATYPE) + Reads DATA from UDP instrument + + Inputs + ...... + + OBJ is a UDP object. + SIZE Number of values to read. (Default: BytesAvailable). + DATATYPE datatype of data. + + Outputs + ....... + + DATA data read. + +3.11.11 @octave_udp/set +----------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of udp object. + + Inputs + ...... + + OBJ - instance of OCTAVE_UDP class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the udp socket. + + 'REMOTEHOST' + Set the remote host name for the udp socket. + + 'REMOTEPORT' + Set the remote port for the udp socket. + + 'TIMEOUT' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + Outputs + ....... + + None + + See also: @octave_udp/get. + +3.11.12 @octave_udp/write +------------------------- + + -- Function File: NUMBYTES = write (OBJ, DATA) + -- Function File: NUMBYTES = write (OBJ, DATA, DESTINATIONADDRESS, + DESTINATIONPORT)) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE, + DESTINATIONADDRESS, DESTINATIONPORT) + Writes DATA to UDP instrument + + Inputs + ...... + + OBJ is a UDP object. + DATA data to write. + DATATYPE datatype of data. If not specified defaults to uint8. + DESTINATIONADDRESS ipaddress to send to. If not specified, use the + remote address. + DESTINATIONPORT port to send to. If not specified, use the remote + port. + + Outputs + ....... + + returns number of bytes written. + +3.11.13 udp +----------- + + -- Loadable Function: UDP = udp () + -- Loadable Function: UDP = udp (REMOTEIPADDRESS, REMOTEPORT) + -- Loadable Function: UDP = udp (REMOTEIPADDRESS, REMOTEPORT, + [PROPERTYNAME, PROPERTYVALUE ...]) + + Open udp interface. + + Inputs + ...... + + REMOTEIPADDRESS - the ip address of type String. If omitted + defaults to '127.0.0.1'. + REMOTEPORT - the port number to connect. If omitted defaults to + 23. + LOCALPORT - the local port number to bind. If omitted defaults to + 0 + PROPERTYNAME, PROPERTYVALUE - property name/value pair + + Outputs + ....... + + The udp() shall return instance of OCTAVE_UDP class as the result + UDP. + + Properties + .......... + + The udp object has the following public properties: + name + name assigned to the udp object + type + instrument type 'udp' (readonly) + localport + local port number (readonly) + localhost + local host address (readonly) + remoteport + remote port number + remotehost + remote host + status + status of the object 'open' or 'closed' (readonly) + timeout + timeout value in seconds used for waiting for data + bytesavailable + number of bytes currently available to read (readonly) + +3.11.14 udp_close +----------------- + + -- Loadable Function: udp_close (UDP) + + Close the interface and release a file descriptor. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + + Inputs + ...... + + None + +3.11.15 udp_demo +---------------- + + -- Function File: RESULT = udp_demo () + Run test SNTP demonstration for udp class + + See also: udp. + +3.11.16 udp_read +---------------- + + -- Loadable Function: [DATA, COUNT] = udp_read (UDP, N, TIMEOUT) + + Read from udp interface. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + N - number of bytes to attempt to read of type Integer + TIMEOUT - timeout in ms if different from default of type Integer + + Outputs + ....... + + The udp_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + +3.11.17 udp_timeout +------------------- + + -- Loadable Function: udp_timeout (UDP, TIMEOUT) + -- Loadable Function: T = udp_timeout (UDP) + + Set new or get existing udp interface timeout parameter used for + udp_read() requests. The timeout value is specified in + milliseconds. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + TIMEOUT - udp_read() timeout value in milliseconds. Value of -1 + means a blocking call. + + Outputs + ....... + + If TIMEOUT parameter is omitted, the udp_timeout() shall return + current timeout value as the result T. + +3.11.18 udp_write +----------------- + + -- Loadable Function: N = udp_write (UDP, DATA) + + Write data to a udp interface. + + Inputs + ...... + + UDP - instance of OCTAVE_UDP class. + DATA - data to be written to the udp interface. Can be either of + String or uint8 type. + + Outputs + ....... + + Upon successful completion, udp_write() shall return the number of + bytes written as the result N. + + +File: instrument-control.info, Node: UDP Port, Next: USBTMC, Prev: UDP (Depreciated), Up: Function Reference + +3.12 UDP Port +============= + +3.12.1 @octave_udpport/configureMulticast +----------------------------------------- + + -- : DATA = configureMulticast((DEV, ADDRESS) + -- : DATA = configureMulticast((DEV, "OFF") + Configure udpport device to receive multicast data + + Inputs + ...... + + DEV - open udpport device + + If ADDRESS is 'off' disable udp multicast. Otherwise it is the + multicast address to use. + + Outputs + ....... + + None + + See also: udpport. + +3.12.2 @octave_udpport/configureTerminator +------------------------------------------ + + -- Function File: configureTerminator (UDP, TERM) + -- Function File: configureTerminator (UDP, READTERM, WRITETERM) + Set terminator for ASCII string manipulation + + Inputs + ...... + + UDP - udpport object + TERM - terminal value for both read and write + READTERM = terminal value type for read data + WRITETERM = terminal value for written data + + The terminal can be either strings "cr", "lf" (default), "lf/cr" or + an integer between 0 to 255. + + Outputs + ....... + + None + + See also: udpport. + +3.12.3 @octave_udpport/flush +---------------------------- + + -- : DATA = flush (DEV) + -- : DATA = flush (DEV, "input") + -- : DATA = flush (DEV, "output") + Flush the udpport socket buffers + + Inputs + ...... + + DEV - open udpport device + + If an additional parameter is provided of "input" or "output", then + only the input or output buffer will be flushed + + Outputs + ....... + + None + + See also: udpport. + +3.12.4 @octave_udpport/fprintf +------------------------------ + + -- Function File: NUMBYTES = fprintf (OBJ, TEMPLATE ...) + Writes formatted string TEMPLATE using optional parameters to UDP + instrument + + Inputs + ...... + + OBJ is a UDPPort object. + TEMPLATE Format template string. + + Outputs + ....... + + NUMBYTES is the number of bytes written to the device + +3.12.5 @octave_udpport/fread +---------------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from UDP instrument + + Inputs + ...... + + OBJ is a UDP port object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA data values. + COUNT number of values read. + ERRMSG read operation error message. + +3.12.6 @octave_udpport/fwrite +----------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to UDP instrument + + Inputs + ...... + + OBJ is a UDP port object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.12.7 @octave_udpport/get +-------------------------- + + -- Function File: STRUCT = get (UDPPORT) + -- Function File: FIELD = get (UDPPORT, PROPERTY) + Get the properties of udpport object. + + Inputs + ...... + + UDPPORT - instance of OCTAVE_UDPPORT class. + + PROPERTY - name of property. + + Outputs + ....... + + When PROPERTY was specified, return the value of that property. + otherwise return the values of all properties as a structure. + + See also: @octave_udpport/set. + +3.12.8 @octave_udpport/read +--------------------------- + + -- Function File: DATA = read (OBJ) + -- Function File: DATA = read (OBJ, SIZE) + -- Function File: DATA = read (OBJ, SIZE, DATATYPE) + Reads DATA from UDP instrument + + Inputs + ...... + + OBJ is a UDP object. + SIZE Number of values to read. (Default: BytesAvailable). + DATATYPE datatype of data. + + Outputs + ....... + + DATA data read. + +3.12.9 @octave_udpport/set +-------------------------- + + -- Function File: set (OBJ, PROPERTY,VALUE) + -- Function File: set (OBJ, PROPERTY,VALUE,...) + Set the properties of udpport object. + + Inputs + ...... + + OBJ - instance of OCTAVE_UDPPORT class. + PROPERTY - name of property. + + If PROPERTY is a cell so must be VALUE, it sets the values of all + matching properties. + + The function also accepts property-value pairs. + + Properties + .......... + + 'NAME' + Set the name for the udpport socket. + + 'USERDATA' + Set the user data of the object. + + 'TIMEOUT' + Set the timeout value in seconds. Value of -1 means a + blocking call. + + Outputs + ....... + + None + + See also: @octave_udpport/get. + +3.12.10 @octave_udpport/write +----------------------------- + + -- Function File: NUMBYTES = write (OBJ, DATA) + -- Function File: NUMBYTES = write (OBJ, DATA, DESTINATIONADDRESS, + DESTINATIONPORT)) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE) + -- Function File: NUMBYTES = write (OBJ, DATA, DATATYPE, + DESTINATIONADDRESS, DESTINATIONPORT) + Writes DATA to UDP instrument + + Inputs + ...... + + OBJ is a UDPPort object. + DATA data to write. + DATATYPE datatype of data. If not specified defaults to uint8. + DESTINATIONADDRESS ipaddress to send to. If not specified, use the + previously used remote address. + DESTINATIONPORT port to send to. If not specified, use the remote + port. + + Outputs + ....... + + returns number of bytes written. + +3.12.11 udpport +--------------- + + -- Loadable Function: UDP = udpport () + -- Loadable Function: UDP = udpport (PROPERTYNAME, PROPERTYVALUE ...) + + Open udpport interface. + + Inputs + ...... + + PROPERTYNAME, PROPERTYVALUE - property name/value pair + + Known input properties: + Name + name assigned to the udp object + LocalPort + local port number + LocalHost + local host address + Timeout + timeout value in seconds used for waiting for data + EnablePortSharing + Boolean if the socket has port sharing enabled (readonly) + + Outputs + ....... + + The udpport() shall return instance of OCTAVE_UDP class as the + result UDP. + + Properties + .......... + + The udp object has the following public properties: + Name + name assigned to the udp object + Type + instrument type 'udpport' (readonly) + LocalPort + local port number (readonly) + LocalHost + local host address (readonly) + Status + status of the object 'open' or 'closed' (readonly) + Timeout + timeout value in seconds used for waiting for data + NumBytesAvailable + number of bytes currently available to read (readonly) + MulticastGroup + multicast group socket is subscribed to (readonly) + EnableMultcast + Boolean if the socket has any multicast group it is subscribed + to (readonly) + EnablePortSharing + Boolean if the socket has port sharing enabled (readonly) + Terminator + Terminator value used for string data (currently not used) + + +File: instrument-control.info, Node: USBTMC, Next: VXI11, Prev: UDP Port, Up: Function Reference + +3.13 USBTMC +=========== + +3.13.1 @octave_usbtmc/fclose +---------------------------- + + -- Function File: RES = fclose (OBJ) + Closes USBTMC connection OBJ + + Inputs + ...... + + OBJ is a usbtmc object. + +3.13.2 @octave_usbtmc/fopen +--------------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens USBTMC connection OBJ This currently is a dummy function to + improve compatibility to MATLAB + +3.13.3 @octave_usbtmc/fread +--------------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from usbtmc instrument + + Inputs + ...... + + OBJ is a usbtmc object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA The read data. + COUNT values read. + ERRMSG read operation error message. + +3.13.4 @octave_usbtmc/fwrite +---------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to an usbtmc instrument + + Inputs + ...... + + OBJ is a usbtmc object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.13.5 usbtmc +------------- + + -- Loadable Function: USBTMC = usbtmc (PATH) + + Open usbtmc interface. + + Inputs + ...... + + PATH - the interface path of type String. If omitted defaults to + '/dev/usbtmc0'. + + Outputs + ....... + + The usbtmc() shall return instance of OCTAVE_USBTMC class as the + result USBTMC. + +3.13.6 usbtmc_close +------------------- + + -- Loadable Function: usbtmc_close (USBTMC) + + Close the interface and release a file descriptor. + + Inputs + ...... + + USBTMC - instance of OCTAVE_USBTMC class. + + Outputs + ....... + + None + +3.13.7 usbtmc_read +------------------ + + -- Loadable Function: [DATA, COUNT] = usbtmc_read (USBTMC, N) + + Read from usbtmc slave device. + + Inputs + ...... + + USBTMC - instance of OCTAVE_USBTMC class. + N - number of bytes to attempt to read of type Integer. + + Outputs + ....... + + COUNT - the number of bytes successfully read as an Integer. + DATA - the read bytes as a uint8 array. + +3.13.8 usbtmc_write +------------------- + + -- Loadable Function: N = usbtmc_write (USBTMC, DATA) + + Write data to a usbtmc slave device. + + Inputs + ...... + + USBTMC - instance of OCTAVE_USBTMC class. + DATA - data, of type uint8, to be written to the slave device. + + Outputs + ....... + + Upon successful completion, usbtmc_write() shall return the number + of bytes written as the result N. + + +File: instrument-control.info, Node: VXI11, Prev: USBTMC, Up: Function Reference + +3.14 VXI11 +========== + +3.14.1 @octave_vxi11/fclose +--------------------------- + + -- Function File: RES = fclose (OBJ) + Closes VXI11 connection OBJ + +3.14.2 @octave_vxi11/fopen +-------------------------- + + -- Function File: RES = fopen (OBJ) (dummy) + Opens VXI11 connection OBJ This currently is a dummy function to + improve compatibility to MATLAB + +3.14.3 @octave_vxi11/fread +-------------------------- + + -- Function File: DATA = fread (OBJ) + -- Function File: DATA = fread (OBJ, SIZE) + -- Function File: DATA = fread (OBJ, SIZE, PRECISION) + -- Function File: [DATA,COUNT] = fread (OBJ, ...) + -- Function File: [DATA,COUNT,ERRMSG] = fread (OBJ, ...) + Reads DATA from vxi11 instrument + + Inputs + ...... + + OBJ is a vxi11 object. + SIZE Number of values to read. (Default: 100). + PRECISION precision of data. + + Outputs + ....... + + DATA The read data. + COUNT values read. + ERRMSG read operation error message. + +3.14.4 @octave_vxi11/fwrite +--------------------------- + + -- Function File: NUMBYTES = fwrite (OBJ, DATA) + -- Function File: NUMBYTES = fwrite (OBJ, DATA, PRECISION) + Writes DATA to vxi11 instrument + + Inputs + ...... + + OBJ is a vxi11 object. + DATA data to write. + PRECISION precision of data. + + Outputs + ....... + + returns number of bytes written. + +3.14.5 vxi11 +------------ + + -- Loadable Function: VXI11 = vxi11 (IP) + + Open vxi11 interface. + + PATH - the ip address of type String. If omitted defaults to + '127.0.0.1'. + + The vxi11() shall return instance of OCTAVE_VXI11 class as the + result VXI11. + +3.14.6 vxi11_close +------------------ + + -- Loadable Function: vxi11_close (VXI11) + + Close the interface and release a file descriptor. + + VXI11 - instance of OCTAVE_VXI11 class. + +3.14.7 vxi11_read +----------------- + + -- Loadable Function: [DATA, COUNT] = vxi11_read (VXI11, N) + + Read from vxi11 slave device. + + VXI11 - instance of OCTAVE_VXI11 class. + N - number of bytes to attempt to read of type Integer. + + The vxi11_read() shall return number of bytes successfully read in + COUNT as Integer and the bytes themselves in DATA as uint8 array. + +3.14.8 vxi11_write +------------------ + + -- Loadable Function: N = vxi11_write (VXI11, DATA) + + Write data to a vxi11 slave device. + + VXI11 - instance of OCTAVE_VXI11 class. + DATA - data to be written to the slave device. Can be either of + String or uint8 type. + + Upon successful completion, vxi11_write() shall return the number + of bytes written as the result N. + + +File: instrument-control.info, Node: Copying, Next: Index, Prev: Function Reference, Up: Top + +Appendix A GNU General Public License +************************************* + + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies of this + license document, but changing it is not allowed. + +Preamble +======== + +The GNU General Public License is a free, copyleft license for software +and other kinds of works. + +The licenses for most software and other practical works are designed to +take away your freedom to share and change the works. By contrast, the +GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for them if +you wish), that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these +rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis +or for a fee, you must pass on to the recipients the same freedoms that +you received. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) +assert copyright on the software, and (2) offer you this License giving +you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS +==================== + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public + License. + + "Copyright" also means copyright-like laws that apply to other + kinds of works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this + License. Each licensee is addressed as "you". "Licensees" and + "recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the + work in a fashion requiring copyright permission, other than the + making of an exact copy. The resulting work is called a "modified + version" of the earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work + based on the Program. + + To "propagate" a work means to do anything with it that, without + permission, would make you directly or secondarily liable for + infringement under applicable copyright law, except executing it on + a computer or modifying a private copy. Propagation includes + copying, distribution (with or without modification), making + available to the public, and in some countries other activities as + well. + + To "convey" a work means any kind of propagation that enables other + parties to make or receive copies. Mere interaction with a user + through a computer network, with no transfer of a copy, is not + conveying. + + An interactive user interface displays "Appropriate Legal Notices" + to the extent that it includes a convenient and prominently visible + feature that (1) displays an appropriate copyright notice, and (2) + tells the user that there is no warranty for the work (except to + the extent that warranties are provided), that licensees may convey + the work under this License, and how to view a copy of this + License. If the interface presents a list of user commands or + options, such as a menu, a prominent item in the list meets this + criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work + for making modifications to it. "Object code" means any non-source + form of a work. + + A "Standard Interface" means an interface that either is an + official standard defined by a recognized standards body, or, in + the case of interfaces specified for a particular programming + language, one that is widely used among developers working in that + language. + + The "System Libraries" of an executable work include anything, + other than the work as a whole, that (a) is included in the normal + form of packaging a Major Component, but which is not part of that + Major Component, and (b) serves only to enable use of the work with + that Major Component, or to implement a Standard Interface for + which an implementation is available to the public in source code + form. A "Major Component", in this context, means a major + essential component (kernel, window system, and so on) of the + specific operating system (if any) on which the executable work + runs, or a compiler used to produce the work, or an object code + interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all + the source code needed to generate, install, and (for an executable + work) run the object code and to modify the work, including scripts + to control those activities. However, it does not include the + work's System Libraries, or general-purpose tools or generally + available free programs which are used unmodified in performing + those activities but which are not part of the work. For example, + Corresponding Source includes interface definition files associated + with source files for the work, and the source code for shared + libraries and dynamically linked subprograms that the work is + specifically designed to require, such as by intimate data + communication or control flow between those subprograms and other + parts of the work. + + The Corresponding Source need not include anything that users can + regenerate automatically from other parts of the Corresponding + Source. + + The Corresponding Source for a work in source code form is that + same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of + copyright on the Program, and are irrevocable provided the stated + conditions are met. This License explicitly affirms your unlimited + permission to run the unmodified Program. The output from running + a covered work is covered by this License only if the output, given + its content, constitutes a covered work. This License acknowledges + your rights of fair use or other equivalent, as provided by + copyright law. + + You may make, run and propagate covered works that you do not + convey, without conditions so long as your license otherwise + remains in force. You may convey covered works to others for the + sole purpose of having them make modifications exclusively for you, + or provide you with facilities for running those works, provided + that you comply with the terms of this License in conveying all + material for which you do not control copyright. Those thus making + or running the covered works for you must do so exclusively on your + behalf, under your direction and control, on terms that prohibit + them from making any copies of your copyrighted material outside + their relationship with you. + + Conveying under any other circumstances is permitted solely under + the conditions stated below. Sublicensing is not allowed; section + 10 makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological + measure under any applicable law fulfilling obligations under + article 11 of the WIPO copyright treaty adopted on 20 December + 1996, or similar laws prohibiting or restricting circumvention of + such measures. + + When you convey a covered work, you waive any legal power to forbid + circumvention of technological measures to the extent such + circumvention is effected by exercising rights under this License + with respect to the covered work, and you disclaim any intention to + limit operation or modification of the work as a means of + enforcing, against the work's users, your or third parties' legal + rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you + receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice; + keep intact all notices stating that this License and any + non-permissive terms added in accord with section 7 apply to the + code; keep intact all notices of the absence of any warranty; and + give all recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, + and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to + produce it from the Program, in the form of source code under the + terms of section 4, provided that you also meet all of these + conditions: + + a. The work must carry prominent notices stating that you + modified it, and giving a relevant date. + + b. The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in + section 4 to "keep intact all notices". + + c. You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable + section 7 additional terms, to the whole of the work, and all + its parts, regardless of how they are packaged. This License + gives no permission to license the work in any other way, but + it does not invalidate such permission if you have separately + received it. + + d. If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has + interactive interfaces that do not display Appropriate Legal + Notices, your work need not make them do so. + + A compilation of a covered work with other separate and independent + works, which are not by their nature extensions of the covered + work, and which are not combined with it such as to form a larger + program, in or on a volume of a storage or distribution medium, is + called an "aggregate" if the compilation and its resulting + copyright are not used to limit the access or legal rights of the + compilation's users beyond what the individual works permit. + Inclusion of a covered work in an aggregate does not cause this + License to apply to the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms + of sections 4 and 5, provided that you also convey the + machine-readable Corresponding Source under the terms of this + License, in one of these ways: + + a. Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b. Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that + product model, to give anyone who possesses the object code + either (1) a copy of the Corresponding Source for all the + software in the product that is covered by this License, on a + durable physical medium customarily used for software + interchange, for a price no more than your reasonable cost of + physically performing this conveying of source, or (2) access + to copy the Corresponding Source from a network server at no + charge. + + c. Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, + and only if you received the object code with such an offer, + in accord with subsection 6b. + + d. Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to + the Corresponding Source in the same way through the same + place at no further charge. You need not require recipients + to copy the Corresponding Source along with the object code. + If the place to copy the object code is a network server, the + Corresponding Source may be on a different server (operated by + you or a third party) that supports equivalent copying + facilities, provided you maintain clear directions next to the + object code saying where to find the Corresponding Source. + Regardless of what server hosts the Corresponding Source, you + remain obligated to ensure that it is available for as long as + needed to satisfy these requirements. + + e. Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the + general public at no charge under subsection 6d. + + A separable portion of the object code, whose source code is + excluded from the Corresponding Source as a System Library, need + not be included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means + any tangible personal property which is normally used for personal, + family, or household purposes, or (2) anything designed or sold for + incorporation into a dwelling. In determining whether a product is + a consumer product, doubtful cases shall be resolved in favor of + coverage. For a particular product received by a particular user, + "normally used" refers to a typical or common use of that class of + product, regardless of the status of the particular user or of the + way in which the particular user actually uses, or expects or is + expected to use, the product. A product is a consumer product + regardless of whether the product has substantial commercial, + industrial or non-consumer uses, unless such uses represent the + only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, + procedures, authorization keys, or other information required to + install and execute modified versions of a covered work in that + User Product from a modified version of its Corresponding Source. + The information must suffice to ensure that the continued + functioning of the modified object code is in no case prevented or + interfered with solely because modification has been made. + + If you convey an object code work under this section in, or with, + or specifically for use in, a User Product, and the conveying + occurs as part of a transaction in which the right of possession + and use of the User Product is transferred to the recipient in + perpetuity or for a fixed term (regardless of how the transaction + is characterized), the Corresponding Source conveyed under this + section must be accompanied by the Installation Information. But + this requirement does not apply if neither you nor any third party + retains the ability to install modified object code on the User + Product (for example, the work has been installed in ROM). + + The requirement to provide Installation Information does not + include a requirement to continue to provide support service, + warranty, or updates for a work that has been modified or installed + by the recipient, or for the User Product in which it has been + modified or installed. Access to a network may be denied when the + modification itself materially and adversely affects the operation + of the network or violates the rules and protocols for + communication across the network. + + Corresponding Source conveyed, and Installation Information + provided, in accord with this section must be in a format that is + publicly documented (and with an implementation available to the + public in source code form), and must require no special password + or key for unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of + this License by making exceptions from one or more of its + conditions. Additional permissions that are applicable to the + entire Program shall be treated as though they were included in + this License, to the extent that they are valid under applicable + law. If additional permissions apply only to part of the Program, + that part may be used separately under those permissions, but the + entire Program remains governed by this License without regard to + the additional permissions. + + When you convey a copy of a covered work, you may at your option + remove any additional permissions from that copy, or from any part + of it. (Additional permissions may be written to require their own + removal in certain cases when you modify the work.) You may place + additional permissions on material, added by you to a covered work, + for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material + you add to a covered work, you may (if authorized by the copyright + holders of that material) supplement the terms of this License with + terms: + + a. Disclaiming warranty or limiting liability differently from + the terms of sections 15 and 16 of this License; or + + b. Requiring preservation of specified reasonable legal notices + or author attributions in that material or in the Appropriate + Legal Notices displayed by works containing it; or + + c. Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked + in reasonable ways as different from the original version; or + + d. Limiting the use for publicity purposes of names of licensors + or authors of the material; or + + e. Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f. Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified + versions of it) with contractual assumptions of liability to + the recipient, for any liability that these contractual + assumptions directly impose on those licensors and authors. + + All other non-permissive additional terms are considered "further + restrictions" within the meaning of section 10. If the Program as + you received it, or any part of it, contains a notice stating that + it is governed by this License along with a term that is a further + restriction, you may remove that term. If a license document + contains a further restriction but permits relicensing or conveying + under this License, you may add to a covered work material governed + by the terms of that license document, provided that the further + restriction does not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in + the form of a separately written license, or stated as exceptions; + the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights + under this License (including any patent licenses granted under the + third paragraph of section 11). + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, you do not qualify to receive new licenses + for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer + transmission to receive a copy likewise does not require + acceptance. However, nothing other than this License grants you + permission to propagate or modify any covered work. These actions + infringe copyright if you do not accept this License. Therefore, + by modifying or propagating a covered work, you indicate your + acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not + responsible for enforcing compliance by third parties with this + License. + + An "entity transaction" is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a + covered work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party's predecessor in interest had or + could give under the previous paragraph, plus a right to possession + of the Corresponding Source of the work from the predecessor in + interest, if the predecessor has it or can get it with reasonable + efforts. + + You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you + may not impose a license fee, royalty, or other charge for exercise + of rights granted under this License, and you may not initiate + litigation (including a cross-claim or counterclaim in a lawsuit) + alleging that any patent claim is infringed by making, using, + selling, offering for sale, or importing the Program or any portion + of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. + The work thus licensed is called the contributor's "contributor + version". + + A contributor's "essential patent claims" are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, + permitted by this License, of making, using, or selling its + contributor version, but do not include claims that would be + infringed only as a consequence of further modification of the + contributor version. For purposes of this definition, "control" + includes the right to grant patent sublicenses in a manner + consistent with the requirements of this License. + + Each contributor grants you a non-exclusive, worldwide, + royalty-free patent license under the contributor's essential + patent claims, to make, use, sell, offer for sale, import and + otherwise run, modify and propagate the contents of its contributor + version. + + In the following three paragraphs, a "patent license" is any + express agreement or commitment, however denominated, not to + enforce a patent (such as an express permission to practice a + patent or covenant not to sue for patent infringement). To "grant" + such a patent license to a party means to make such an agreement or + commitment not to enforce a patent against the party. + + If you convey a covered work, knowingly relying on a patent + license, and the Corresponding Source of the work is not available + for anyone to copy, free of charge and under the terms of this + License, through a publicly available network server or other + readily accessible means, then you must either (1) cause the + Corresponding Source to be so available, or (2) arrange to deprive + yourself of the benefit of the patent license for this particular + work, or (3) arrange, in a manner consistent with the requirements + of this License, to extend the patent license to downstream + recipients. "Knowingly relying" means you have actual knowledge + that, but for the patent license, your conveying the covered work + in a country, or your recipient's use of the covered work in a + country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, + modify or convey a specific copy of the covered work, then the + patent license you grant is automatically extended to all + recipients of the covered work and works based on it. + + A patent license is "discriminatory" if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that + are specifically granted under this License. You may not convey a + covered work if you are a party to an arrangement with a third + party that is in the business of distributing software, under which + you make payment to the third party based on the extent of your + activity of conveying the work, and under which the third party + grants, to any of the parties who would receive the covered work + from you, a discriminatory patent license (a) in connection with + copies of the covered work conveyed by you (or copies made from + those copies), or (b) primarily for and in connection with specific + products or compilations that contain the covered work, unless you + entered into that arrangement, or that patent license was granted, + prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, they + do not excuse you from the conditions of this License. If you + cannot convey a covered work so as to satisfy simultaneously your + obligations under this License and any other pertinent obligations, + then as a consequence you may not convey it at all. For example, + if you agree to terms that obligate you to collect a royalty for + further conveying from those to whom you convey the Program, the + only way you could satisfy both those terms and this License would + be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have + permission to link or combine any covered work with a work licensed + under version 3 of the GNU Affero General Public License into a + single combined work, and to convey the resulting work. The terms + of this License will continue to apply to the part which is the + covered work, but the special requirements of the GNU Affero + General Public License, section 13, concerning interaction through + a network will apply to the combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new + versions of the GNU General Public License from time to time. Such + new versions will be similar in spirit to the present version, but + may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU + General Public License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that numbered version or of any later version published by the Free + Software Foundation. If the Program does not specify a version + number of the GNU General Public License, you may choose any + version ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future + versions of the GNU General Public License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Program. + + Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE + COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE + RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. + SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES + AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE + THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA + BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF + THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely + approximates an absolute waiver of all civil liability in + connection with the Program, unless a warranty or assumption of + liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS +=========================== + +How to Apply These Terms to Your New Programs +============================================= + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively state +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice +like this when it starts in an interactive mode: + + PROGRAM Copyright (C) YEAR NAME OF AUTHOR + This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the +appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an "about box". + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. For more information on this, and how to apply and follow +the GNU GPL, see . + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. But first, +please read . + + +File: instrument-control.info, Node: Index, Prev: Copying, Up: Top + +Index +***** + +[index] +* Menu: + +* Basic Usage Overview: Basic Usage Overview. + (line 5) +* clrdevice: GPIB. (line 81) +* Common Functions: Common Functions. (line 5) +* configureMulticast: UDP Port. (line 9) +* configureTerminator: Serial Port. (line 9) +* configureTerminator <1>: TCP Client. (line 9) +* configureTerminator <2>: UDP Port. (line 31) +* copyright: Copying. (line 6) +* fclose: GPIB. (line 9) +* fclose <1>: I2C. (line 9) +* fclose <2>: Parallel. (line 9) +* fclose <3>: Serial (Depreciated). + (line 9) +* fclose <4>: SPI. (line 9) +* fclose <5>: TCP (Depreciated). (line 9) +* fclose <6>: UDP (Depreciated). (line 9) +* fclose <7>: USBTMC. (line 9) +* fclose <8>: VXI11. (line 9) +* flush: Serial Port. (line 34) +* flush <1>: TCP (Depreciated). (line 15) +* flush <2>: TCP Client. (line 34) +* flush <3>: UDP (Depreciated). (line 15) +* flush <4>: UDP Port. (line 56) +* flushinput: Common Functions. (line 9) +* flushinput <1>: Serial (Depreciated). + (line 15) +* flushinput <2>: TCP (Depreciated). (line 38) +* flushinput <3>: UDP (Depreciated). (line 38) +* flushoutput: Common Functions. (line 27) +* flushoutput <1>: Serial (Depreciated). + (line 35) +* flushoutput <2>: TCP (Depreciated). (line 58) +* flushoutput <3>: UDP (Depreciated). (line 58) +* fopen: GPIB. (line 15) +* fopen <1>: I2C. (line 15) +* fopen <2>: Parallel. (line 15) +* fopen <3>: Serial (Depreciated). + (line 54) +* fopen <4>: SPI. (line 15) +* fopen <5>: TCP (Depreciated). (line 77) +* fopen <6>: UDP (Depreciated). (line 77) +* fopen <7>: USBTMC. (line 20) +* fopen <8>: VXI11. (line 15) +* fprintf: GPIB. (line 22) +* fprintf <1>: Serial (Depreciated). + (line 63) +* fprintf <2>: Serial Port. (line 57) +* fprintf <3>: TCP (Depreciated). (line 86) +* fprintf <4>: UDP (Depreciated). (line 84) +* fprintf <5>: UDP Port. (line 79) +* fread: GPIB. (line 35) +* fread <1>: I2C. (line 24) +* fread <2>: Parallel. (line 24) +* fread <3>: Serial (Depreciated). + (line 81) +* fread <4>: Serial Port. (line 75) +* fread <5>: SPI. (line 24) +* fread <6>: TCP (Depreciated). (line 104) +* fread <7>: UDP (Depreciated). (line 102) +* fread <8>: UDP Port. (line 97) +* fread <9>: USBTMC. (line 27) +* fread <10>: VXI11. (line 22) +* fscanf: GPIB. (line 52) +* Function Reference: Function Reference. (line 6) +* fwrite: GPIB. (line 68) +* fwrite <1>: I2C. (line 48) +* fwrite <2>: Parallel. (line 48) +* fwrite <3>: Serial (Depreciated). + (line 105) +* fwrite <4>: Serial Port. (line 99) +* fwrite <5>: SPI. (line 48) +* fwrite <6>: TCP (Depreciated). (line 128) +* fwrite <7>: UDP (Depreciated). (line 126) +* fwrite <8>: UDP Port. (line 121) +* fwrite <9>: USBTMC. (line 51) +* fwrite <10>: VXI11. (line 46) +* General: General. (line 5) +* get: I2C. (line 67) +* get <1>: Serial (Depreciated). + (line 124) +* get <2>: Serial Port. (line 118) +* get <3>: SPI. (line 67) +* get <4>: TCP (Depreciated). (line 147) +* get <5>: TCP Client. (line 57) +* get <6>: UDP (Depreciated). (line 145) +* get <7>: UDP Port. (line 140) +* getpinstatus: Serial Port. (line 139) +* GPIB: GPIB. (line 5) +* gpib: GPIB. (line 89) +* gpib_close: GPIB. (line 103) +* gpib_read: GPIB. (line 112) +* gpib_timeout: GPIB. (line 126) +* gpib_write: GPIB. (line 143) +* I2C: I2C. (line 5) +* i2c: I2C. (line 123) +* i2c_addr: I2C. (line 154) +* i2c_close: I2C. (line 175) +* i2c_read: I2C. (line 192) +* i2c_write: I2C. (line 211) +* Installing and loading: Installing and loading. + (line 6) +* instrhelp: General. (line 9) +* instrhwinfo: General. (line 31) +* Loading: Installing and loading. + (line 60) +* Off-line install: Installing and loading. + (line 51) +* Online install: Installing and loading. + (line 40) +* Parallel: Parallel. (line 5) +* parallel: Parallel. (line 67) +* pp_close: Parallel. (line 88) +* pp_ctrl: Parallel. (line 105) +* pp_data: Parallel. (line 125) +* pp_datadir: Parallel. (line 145) +* pp_stat: Parallel. (line 173) +* read: Serial Port. (line 158) +* read <1>: SPI. (line 112) +* read <2>: TCP (Depreciated). (line 168) +* read <3>: TCP Client. (line 78) +* read <4>: UDP (Depreciated). (line 167) +* read <5>: UDP Port. (line 162) +* Requirements: Installing and loading. + (line 18) +* resolvehost: General. (line 78) +* serial: Serial (Depreciated). + (line 400) +* Serial (Depreciated): Serial (Depreciated). + (line 5) +* Serial Port: Serial Port. (line 5) +* serialbreak: Serial (Depreciated). + (line 145) +* serialbreak <1>: Serial Port. (line 184) +* seriallist: Serial (Depreciated). + (line 453) +* serialport: Serial Port. (line 322) +* serialportlist: Serial Port. (line 391) +* set: I2C. (line 89) +* set <1>: Serial (Depreciated). + (line 166) +* set <2>: Serial Port. (line 205) +* set <3>: SPI. (line 130) +* set <4>: TCP (Depreciated). (line 188) +* set <5>: TCP Client. (line 98) +* set <6>: UDP (Depreciated). (line 187) +* set <7>: UDP Port. (line 182) +* setDTR: Serial Port. (line 265) +* setRTS: Serial Port. (line 284) +* SPI: SPI. (line 5) +* spi: SPI. (line 206) +* spi_close: SPI. (line 253) +* spi_read: SPI. (line 270) +* spi_write: SPI. (line 289) +* spi_writeAndRead: SPI. (line 308) +* spoll: GPIB. (line 157) +* srl_baudrate: Serial (Depreciated). + (line 226) +* srl_bytesize: Serial (Depreciated). + (line 253) +* srl_close: Serial (Depreciated). + (line 278) +* srl_flush: Serial (Depreciated). + (line 297) +* srl_parity: Serial (Depreciated). + (line 324) +* srl_read: Serial (Depreciated). + (line 472) +* srl_stopbits: Serial (Depreciated). + (line 351) +* srl_timeout: Serial (Depreciated). + (line 374) +* srl_write: Serial (Depreciated). + (line 491) +* tcp: TCP (Depreciated). (line 246) +* TCP (Depreciated): TCP (Depreciated). (line 5) +* TCP Client: TCP Client. (line 5) +* tcpclient: TCP Client. (line 153) +* tcpip: TCP (Depreciated). (line 383) +* tcp_close: TCP (Depreciated). (line 303) +* tcp_read: TCP (Depreciated). (line 320) +* tcp_timeout: TCP (Depreciated). (line 340) +* tcp_write: TCP (Depreciated). (line 363) +* trigger: GPIB. (line 168) +* udp: UDP (Depreciated). (line 255) +* UDP (Depreciated): UDP (Depreciated). (line 5) +* UDP Port: UDP Port. (line 5) +* udpport: UDP Port. (line 247) +* udp_close: UDP (Depreciated). (line 305) +* udp_demo: UDP (Depreciated). (line 322) +* udp_read: UDP (Depreciated). (line 330) +* udp_timeout: UDP (Depreciated). (line 350) +* udp_write: UDP (Depreciated). (line 373) +* USBTMC: USBTMC. (line 5) +* usbtmc: USBTMC. (line 70) +* usbtmc_close: USBTMC. (line 89) +* usbtmc_read: USBTMC. (line 106) +* usbtmc_write: USBTMC. (line 125) +* VXI11: VXI11. (line 5) +* vxi11: VXI11. (line 65) +* vxi11_close: VXI11. (line 78) +* vxi11_read: VXI11. (line 87) +* vxi11_write: VXI11. (line 100) +* warranty: Copying. (line 6) +* Windows install: Installing and loading. + (line 29) +* write: Serial Port. (line 303) +* write <1>: SPI. (line 172) +* write <2>: TCP (Depreciated). (line 226) +* write <3>: TCP Client. (line 133) +* write <4>: UDP (Depreciated). (line 228) +* write <5>: UDP Port. (line 220) +* writeAndRead: SPI. (line 189) + + + +Tag Table: +Node: Top97 +Node: Installing and loading615 +Node: Basic Usage Overview2627 +Node: Authors2895 +Node: Available Interface3350 +Node: Basic Serial4458 +Node: Basic TCP6807 +Node: Basic UDP9185 +Node: Function Reference11379 +Node: Common Functions11823 +Node: General12450 +Node: GPIB15218 +Node: I2C19801 +Node: Parallel24558 +Node: Serial (Depreciated)28913 +Node: Serial Port41051 +Node: SPI50770 +Node: TCP (Depreciated)57507 +Node: TCP Client66311 +Node: UDP (Depreciated)71210 +Node: UDP Port79817 +Node: USBTMC87025 +Node: VXI1189975 +Node: Copying92638 +Node: Index130152 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/doc/instrument-control.pdf b/doc/instrument-control.pdf new file mode 100644 index 0000000..935bf0c Binary files /dev/null and b/doc/instrument-control.pdf differ diff --git a/doc/instrument-control.texi b/doc/instrument-control.texi new file mode 100644 index 0000000..28d7848 --- /dev/null +++ b/doc/instrument-control.texi @@ -0,0 +1,476 @@ +\input texinfo @c -*-texinfo-*- +@c Copyright (c) 2019-2021, John Donoghue +@c Octave Instrument Control Toolkit - Low level I/O functions for serial, i2c, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces. + +@c %*** Start of HEADER +@setfilename instrument-control.info +@settitle Octave Instrument Control Toolkit +@afourpaper +@paragraphindent 0 +@finalout +@set VERSION 0.7.0 +@set COPYRIGHT_DATE 2019-2021 +@c @afourwide +@c %*** End of the HEADER + +@include macros.texi + +@c %*** Start of TITLEPAGE +@titlepage +@title Octave Instrument Control Toolkit @value{VERSION} +@subtitle Low level instrumentation functions for @acronym{GNU} Octave. +@author John Donoghue +@page +@vskip 0pt plus 1filll +Copyright @copyright{} @value{COPYRIGHT_DATE} John Donoghue + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the same conditions as for modified versions. + +@page +@heading Distribution +The @acronym{GNU} Octave Instrument Control Toolkit is @dfn{free} software. +Free software is a matter of the users' freedom to run, copy, distribute, +study, change and improve the software. +This means that everyone is free to use it and free to redistribute it +on certain conditions. The @acronym{GNU} Octave Instrument Control toolkit +is not, however, in the public domain. It is copyrighted and there are +restrictions on its distribution, but the restrictions are designed to +ensure that others will have the same freedom to use and redistribute +Octave that you have. The precise conditions can be found in the +@acronym{GNU} General Public License that comes with the @acronym{GNU} +Octave Instrument Control toolkit and that also appears in @ref{Copying}. + +To download a copy of the @acronym{GNU} Octave Instrument Control Toolkit, please visit +@url{http://octave.sourceforge.net/instrument-control/}. + +@end titlepage +@c %*** End of TITLEPAGE + +@c %*** Start of BODY +@contents +@ifnottex +@node Top +@top Introduction +The Instrument Control toolkit is a set of low level I/O functions for serial, i2c, spi, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces +@end ifnottex + +@menu +* Installing and loading:: Installing and loading the toolkit +* Basic Usage Overview:: Basic Usage Overview +* Function Reference:: Instrument Control functions +* Copying:: Copying +* Index:: Index +@end menu + +@c ------------------------------------------------------------------------- +@node Installing and loading +@chapter Installing and loading +@cindex Installing and loading + +The Instrument Control toolkit must be installed and then loaded to be used. + +It can be installed in @acronym{GNU} Octave directly from octave-forge, +or can be installed in an off-line mode via a downloaded tarball. + +The toolkit must be then be loaded once per each @acronym{GNU} Octave session in order to use its functionality. + +@section Requirements +@cindex Requirements +For GPIB support (Linux only), linux-gpib must be installed before installing instrument-control. +GPIB support is also available for windows by following the information from the wiki: +https://wiki.octave.org/Instrument_control_package#Requirements + +For VXI11 support, rpcgen, and libtirpc-devel must be installed before installing instrument-control. + + +@section Windows install +@cindex Windows install + +If using the @acronym{GNU} Octave installer in Windows, the toolkit will have already been installed, and does not need to be re-installed +unless a newer version is available. + +Run the following command to verify if the toolkit is available: + +@example +pkg list instrument-control +@end example + +@section Online Direct install +@cindex Online install +With an internet connection available, toolkit can be installed from +octave-forge using the following command within @acronym{GNU} Octave: + +@example +pkg install -forge instrument-control +@end example + +The latest released version of the toolkit will be downloaded, compiled and installed. + +@section Off-line install +@cindex Off-line install +With the toolkit package already downloaded, and in the current directory when running +@acronym{GNU} Octave, the package can be installed using the following command within @acronym{GNU} Octave: + +@example +pkg install instrument-control-@value{VERSION}.tar.gz +@end example + +@section Loading +@cindex Loading +Regardless of the method of installing the toolkit, in order to use its functions, +the toolkit must be loaded using the pkg load command: + +@example +pkg load instrument-control +@end example + +The toolkit must be loaded on each @acronym{GNU} Octave session. + +@c ------------------------------------------------------------------------- +@node Basic Usage Overview +@chapter Basic Usage Overview +@cindex Basic Usage Overview + +@node Authors +@section Authors +The Instrument control package provides low level I/O functions for serial, i2c, spi, parallel, tcp, gpib, vxi11, udp and usbtmc interfaces. + +It was written mainly by the following developers: + +@itemize +@item Andrius Sutas +@item Stefan Mahr +@item John Donoghue +@end itemize + +@node Available Interface +@section Available Interfaces +The ability to use each interface is dependent on OS and what libraries were available during the toolkit install. + +To verify the available interfaces, run the following command in octave: + +@example +instrhwinfo +@end example + +The function will return information on the supported interfaces that are available, similar to below: + +@example + ToolboxVersion = 0.7.0 + ToolboxName = octave instrument control package + SupportedInterfaces = + @{ + [1,1] = gpib + [1,2] = i2c + [1,3] = parallel + [1,4] = serial + [1,5] = serialport + [1,6] = tcp + [1,7] = tcpclient + [1,8] = udp + [1,9] = udpport + [1,10] = usbtmc + [1,11] = vxi11 + @} +@end example + +Most interfaces have two types of functions: + +@itemize +@item somewhat compatible matlab functions such as fread, fwrite + +@item interface specific lower level functions such as udp_read, udp_write +@end itemize + + +@node Basic Serial +@section Basic Serial + +@subsection Serial +The serial object has been depreciated and may not appear in newer versions of the instrument-control toolbox. Instead new code should use the serialport object. + +The serial port can be opened using the serial function: + +@example +s = serial("/dev/ttyUSB1", 115200) +@end example + +The first parameter is the device name and is OS specific. The second parameter is the baudrate. + +A list of available serial ports can be retrieved using the function: + +@example +seriallist +@end example + +After creating the interface object, properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = serial("/dev/ttyUSB1", 115200) +br = get(s, "baudrate") # gets the baudrate +br = s.baudrate # also gets the baudrate + +set(s, "baudrate", 9600) # set the baudrate +s.baudrate = 9600 # also sets the baudrate +@end example + +The device can be written and read from using fread, fwrite and srl_read and slr_write functions. + +@example +srl_write(s, "hello world") # write hello world +fprintf(s, "hello again") + +val = srl_read(s, 10) # attempt to read +val = fread(s, 10) +@end example + +The device can be closed using fclose or srl_close. + +@example +fclose(s) +@end example + +@subsection SerialPort + +The recommended method of accessing serial ports is through the serialport object. + +The serial port can be opened using the serialport function: + +@example +s = serialport("/dev/ttyUSB1", 115200) +@end example + +The first parameter is the device name and is OS specific. The second parameter is the baudrate. + +A list of available serial ports can be retrieved using the function: + +@example +serialportlist +@end example + +After creating the interface object, properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = serialport("/dev/ttyUSB1", 115200) +br = get(s, "BaudRate") # gets the baudrate +br = s.BaudRate # also gets the baudrate + +set(s, "BaudRate", 9600) # set the baudrate +s.BaudRate = 9600 # also sets the baudrate +@end example + +The device can be written and read from using read and write functions. + +@example +write(s, "hello world") # write hello world + +val = read(s, 10) +@end example + +The device can be closed by clearing the serialport object. + +@example +clear s +@end example + +@node Basic TCP +@section Basic TCP + +@subsection TCP +The TCP object has been depreciated and may not appear in newer versions of the instrument-control toolbox. Instead new code should use the tcpclient object. + +A TCP connection can be opened using the tcp or tcpip function: + +@example +s = tcp("127.0.0.1", 80) +@end example + +The first parameter is the IP address to connect to. The second parameter is the port number. And optional timeout value can be also be provided. + +A more matlab compatible function is available as tcpip to also open a tcp port: + +@example +s = tcpip("gnu.org", 80) +@end example + +The first parameter is a hostname or ip address, the second the port number. Additional parameter/value pairs can be provided after the port. + + +After creating the interface object, properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = tcp("127.0.0.1", 80) +oldtimeout = get(s, "timeout") # get timeout + +set(s, "timeout", 10) # set the timeout +s.timeout = oldtimeout # also sets the timeout +@end example + +The device can be written and read from using fread, fwrite and tcp_read and tcp_write functions. + +@example +tcp_write(s, "HEAD / HTTP/1.1\r\n\r\n") + +val = tcp_read(s, 100, 500) # attempt to read 100 bytes +@end example + +The device can be closed using fclose or tcp_close. + +@example +fclose(s) +@end example + +@subsection TCP Client + +The recommended method of creating a tcp connection is through the tcpclient object. + +A TCP connection can be opened using the tcpclient function: + +@example +s = tcpclient("127.0.0.1", 80) +@end example + +The first parameter is the IP address or hostname to connect to. The second parameter is the port number. + +Additional parameter/value pairs can be provided after the port. + +After creating the interface object, properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = tcpclient("127.0.0.1", 80) +oldtimeout = get(s, "Timeout") # get timeout + +set(s, "Timeout", 10) # set the timeout +s.Timeout = oldtimeout # also sets the timeout +@end example + +The device can be written and read from using read and write functions. + +@example +write(s, "HEAD / HTTP/1.1\r\n\r\n") + +val = read(s, 100) # attempt to read 100 bytes +@end example + +The device can be closed by clearing the object variable. + +@example +clear s +@end example + +@node Basic UDP +@section Basic UDP + +@subsection UDP +The UDP object has been depreciated and may not appear in newer versions of the instrument-control toolbox. Instead new code should use the udpport object. + +A UDP connection can be opened using the udp function: + +@example +s = udp("127.0.0.1", 80) +@end example + +The first parameter is the IP address data will be to. The second parameter is the port number. + +If and ip address and port is not provides, it will default to "127.0.0.1" and 23. + +The address and port can be changed after creation using the remotehost and remoteport properties. + +@example +s = udp() +s.remotehost = "127.0.0.1"; +s.remoteport = 100; +@end example + +After creating the interface object, other properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = udp("127.0.0.1", 80) +oldtimeout = get(s, "timeout") # get timeout + +set(s, "timeout", 10) # set the timeout +s.timeout = oldtimeout # also sets the timeout +@end example + +The device can be written and read from using fread, fwrite and udp_read and udp_write functions. + +@example +udp_write(s, "test") + +val = udp_read(s, 5) +@end example + +The device can be closed using fclose or udp_close. + +@example +fclose(s) +@end example + +@subsection UDP Port + +The recommended method of creating a udp socket is through the udpport object. + +A udpport object can be created using the udpport function: + +@example +s = udpport() +@end example + +Additional parameter/value pairs can be provided during creation of the object. + +After creating the interface object, properties of the device can be set or retrieved using get or set functions or as property access. + +@example +s = udpport() +oldtimeout = get(s, "Timeout") # get timeout + +set(s, "Timeout", 10) # set the timeout +s.Timeout = oldtimeout # also sets the timeout +@end example + +The device can be written and read from using read and write functions. + +The destination address and port to send data to must be specified at least on the first time write is used. + +@example +write(s, "test", "127.0.0.1", s.LocalPort) + +val = read(s) +@end example + +The device can be closed by clearing the object variable. + +@example +clear s +@end example + +@c ------------------------------------------------------------------------- +@node Function Reference +@chapter Function Reference +@cindex Function Reference + +The functions currently available in the toolkit are described below. + +@include functions.texi + +@c ------------------------------------------------------------------------- + +@include gpl.texi + +@c ------------------------------------------------------------------------- +@node Index +@unnumbered Index + +@printindex cp + +@bye diff --git a/doc/macros.texi b/doc/macros.texi new file mode 100644 index 0000000..291bcc4 --- /dev/null +++ b/doc/macros.texi @@ -0,0 +1,117 @@ +@c Copyright (C) 2012-2019 John W. Eaton +@c +@c This file is part of Octave. +@c +@c Octave is free software: you can redistribute it and/or modify it +@c under the terms of the GNU General Public License as published by +@c the Free Software Foundation, either version 3 of the License, or +@c (at your option) any later version. +@c +@c Octave is distributed in the hope that it will be useful, but +@c WITHOUT ANY WARRANTY; without even the implied warranty of +@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with Octave; see the file COPYING. If not, see +@c . + +@c The following macro marks words that aspell should ignore during +@c spellchecking. Within Texinfo it has no effect as it merely replaces +@c the macro call with the argument itself. + +@macro nospell {arg} +\arg\ +@end macro + +@c The following macro works around the Info/plain text expansion of @code{XXX} +@c which is `XXX'. This looks particularly bad when the macro body is +@c single or double-quoted text, such as a property value `"position"' +@ifinfo +@macro qcode{arg} +\arg\ +@end macro +@end ifinfo +@ifnotinfo +@macro qcode{arg} +@code{\arg\} +@end macro +@end ifnotinfo + +@c The following macro is used for the on-line help system, but we don't +@c want lots of `See also: foo, bar, and baz' strings cluttering the +@c printed manual (that information should be in the supporting text for +@c each group of functions and variables). +@c +@c Implementation Note: +@c For TeX, @vskip produces a nice separation. +@c For Texinfo, '@sp 1' should work, but in practice produces ugly results +@c for HTML. We use a simple blank line to produce the correct +@c behavior. +@c +@c We use @xseealso now because Texinfo introduced its own @seealso +@c command. But instead of modifying all source files, we'll have the +@c munge-texi script convert @seealso to @xseealso. + +@macro xseealso {args} +@iftex +@vskip 2pt +@end iftex +@ifnottex + +@end ifnottex +@ifnotinfo +@noindent +@strong{See also:} \args\. +@end ifnotinfo +@ifinfo +@noindent +See also: \args\. +@end ifinfo +@end macro + +@c The following macro works around a situation where the Info/plain text +@c expansion of the @code{XXX} macro is `XXX'. The use of the apostrophe +@c can be confusing if the code segment itself ends with a transpose operator. +@ifinfo +@macro tcode{arg} +\arg\ +@end macro +@end ifinfo +@ifnotinfo +@macro tcode{arg} +@code{\arg\} +@end macro +@end ifnotinfo + +@c FIXME: someday, when Texinfo 5.X is standard, we might replace this with +@c @backslashchar, which is a new addition to Texinfo. + +@macro xbackslashchar +\\ +@end macro + +@c These may be useful for all, not just for octave.texi. +@tex + \ifx\rgbDarkRed\thisisundefined + \def\rgbDarkRed{0.50 0.09 0.12} + \fi + \ifx\linkcolor\thisisundefined + \relax + \else + \global\def\linkcolor{\rgbDarkRed} + \fi + \ifx\urlcolor\thisisundefined + \relax + \else + \global\def\urlcolor{\rgbDarkRed} + \fi + \ifx\urefurlonlylinktrue\thisisundefined + \relax + \else + \global\urefurlonlylinktrue + \fi +@end tex + +@c Make the apostrophe in code examples cut-and-paste friendly. +@codequoteundirected on diff --git a/inst/@octave_gpib/fclose.m b/inst/@octave_gpib/fclose.m new file mode 100644 index 0000000..b5bc6b1 --- /dev/null +++ b/inst/@octave_gpib/fclose.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes connection to GPIB device @var{obj} +## @end deftypefn + +## TODO: +function fclose(fd) + +gpib_close(fd); + +end diff --git a/inst/@octave_gpib/fopen.m b/inst/@octave_gpib/fopen.m new file mode 100644 index 0000000..2c40f55 --- /dev/null +++ b/inst/@octave_gpib/fopen.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens connection to GPIB device @var{obj} +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_gpib/fprintf.m b/inst/@octave_gpib/fprintf.m new file mode 100644 index 0000000..af4f4c9 --- /dev/null +++ b/inst/@octave_gpib/fprintf.m @@ -0,0 +1,65 @@ +## Copyright (C) 2013-2019 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fprintf (@var{obj}, @var{cmd}) +## @deftypefnx {Function File} {} fprintf (@var{obj}, @var{format}, @var{cmd}) +## @deftypefnx {Function File} {} fprintf (@var{obj}, @var{cmd}, @var{mode}) +## @deftypefnx {Function File} {} fprintf (@var{obj}, @var{format}, @var{cmd}, @var{mode}) +## Writes string @var{cmd} to GPIB instrument +## +## @var{obj} is a GPIB object +## +## @var{cmd} String +## @var{format} Format specifier +## @var{mode} sync +## +## @end deftypefn + +## TODO: +function fprintf (obj, format, cmd, mode) + +defaultformat = '%s\n'; +defaultmode = 'sync'; + +if ((nargin < 2) || (nargin > 4)) + print_usage (); +elseif (nargin < 3) + format = defaultformat; + mode = defaultmode; +elseif (nargin < 4) + %% decide for syntax + if (!isempty (find (format == '%'))) + %% detected: fprintf (obj, format, cmd)) + mode = defaultmode; + else + %% fprintf (obj, cmd, mode) + mode = cmd; + cmd = format; + format = defaultformat; + end +end + +if (! ( ischar (format) && ischar (mode) )) + print_usage (); +end + +if (strcmp (mode, 'async')) + error ("async mode not supported yet"); +end + +gpib_write (obj, sprintf (format, cmd)) + +end diff --git a/inst/@octave_gpib/fread.m b/inst/@octave_gpib/fread.m new file mode 100644 index 0000000..7425d57 --- /dev/null +++ b/inst/@octave_gpib/fread.m @@ -0,0 +1,106 @@ +## Copyright (C) 2015 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from GPIB instrument +## +## @var{obj} is a GPIB object +## +## @var{size} Number of values to read. (Default: 100) +## @var{precision} precision of data +## +## @var{count} values read +## @var{errmsg} read operation error message +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + [tmp1,wasread,eoi] = gpib_read (obj, toread); + %% if successful tmp is never negative (uint8) + count = count + wasread; + toread = toread - wasread; + if ((eoi) || (tmp1 < 0)) + break; + end + tmp = [tmp tmp1]; +end + +## TODO: omit warning messages (if any) and output warning text to errmsg instead +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_gpib/fscanf.m b/inst/@octave_gpib/fscanf.m new file mode 100644 index 0000000..d306bc4 --- /dev/null +++ b/inst/@octave_gpib/fscanf.m @@ -0,0 +1,64 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fscanf (@var{obj}) +## @deftypefnx {Function File} {@var{res} =} fscanf (@var{obj}, @var{format}) +## @deftypefnx {Function File} {@var{res} =} fscanf (@var{obj}, @var{format}, @var{size}) +## @deftypefnx {Function File} {[@var{res},@var{count}] =} fscanf (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{res},@var{count},@var{errmsg}] =} fscanf (@var{obj}, ...) +## Reads data @var{res} from GPIB instrument +## +## @var{obj} is a GPIB object +## +## @var{format} Format specifier +## @var{size} number of values +## +## @var{count} values read +## @var{errmsg} read operation error message +## +## @end deftypefn + +## TODO: +function [res, count, errmsg] = fscanf (obj, format, size) + +if (nargin < 1) + print_usage (); +end + +if (nargin < 2) + format = '%c'; +end + +% TODO: use a max buffer property? +buffersize = 1e6; + +eoi=0; tmp = []; +while (!eoi) + [tmp1,~,eoi] = gpib_read (obj, buffersize); + %% if successful tmp is never negative (uint8) + if ((!eoi) || (tmp < 0)) + break; + end + tmp = [tmp tmp1]; +end + +if (nargin < 3) + [res,count,errmsg]=sscanf (tmp,format); +else + [res,count,errmsg]=sscanf (tmp,format,size); +end + +end diff --git a/inst/@octave_gpib/fwrite.m b/inst/@octave_gpib/fwrite.m new file mode 100644 index 0000000..397856b --- /dev/null +++ b/inst/@octave_gpib/fwrite.m @@ -0,0 +1,85 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{precision}) +## @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{mode}) +## @deftypefnx {Function File} {} fwrite (@var{obj}, @var{data}, @var{precision}, @var{mode}) +## Writes @var{data} to GPIB instrument +## +## @var{obj} is a GPIB object +## +## @var{data} data to write +## @var{precision} precision of data +## @var{mode} sync +## +## @end deftypefn + +## TODO: +function fwrite(obj, data, precision, mode) + +defaultmode = "sync"; + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; + mode = defaultmode; +elseif (nargin < 4) + %% is 3rd argument precision or mode + if (strcmp (precision,'sync') || strcmp (precision,'async')) + mode = precision; + precision = []; + else + mode = "sync"; + end +end + +if (strcmp (mode,'async')) + error ("async mode not supported yet"); +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +gpib_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_i2c/fclose.m b/inst/@octave_i2c/fclose.m new file mode 100644 index 0000000..cc83371 --- /dev/null +++ b/inst/@octave_i2c/fclose.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes I2C connection @var{obj} +## @end deftypefn + +## TODO: +function fclose(fd) + +i2c_close(fd); + +end diff --git a/inst/@octave_i2c/fopen.m b/inst/@octave_i2c/fopen.m new file mode 100644 index 0000000..f48b871 --- /dev/null +++ b/inst/@octave_i2c/fopen.m @@ -0,0 +1,27 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens I2C connection @var{obj} +## +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_i2c/fread.m b/inst/@octave_i2c/fread.m new file mode 100644 index 0000000..f31cbc5 --- /dev/null +++ b/inst/@octave_i2c/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from I2C instrument +## +## @subsubheading Inputs +## @var{obj} is a I2C object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} data values.@* +## @var{count} number of values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = i2c_read (obj, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_i2c/fwrite.m b/inst/@octave_i2c/fwrite.m new file mode 100644 index 0000000..2ec8962 --- /dev/null +++ b/inst/@octave_i2c/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to I2C instrument +## +## @subsubheading Inputs +## @var{obj} is a I2C object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = i2c_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_i2c/get.m b/inst/@octave_i2c/get.m new file mode 100644 index 0000000..87e5cd5 --- /dev/null +++ b/inst/@octave_i2c/get.m @@ -0,0 +1,70 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{i2c}) +## @deftypefnx {Function File} {@var{field} = } get (@var{i2c}, @var{property}) +## Get the properties of i2c object. +## +## @subsubheading Inputs +## @var{i2c} - instance of @var{octave_i2c} class.@* +## +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_i2c/set} +## @end deftypefn + +function retval = get (i2c, property) + + properties = {'name', 'remoteaddress', 'status', ... + 'port'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + property = tolower(property); + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("i2c:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __i2c_properties__ (i2c, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_i2c/set.m b/inst/@octave_i2c/set.m new file mode 100644 index 0000000..0b7d4bd --- /dev/null +++ b/inst/@octave_i2c/set.m @@ -0,0 +1,85 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of i2c object. +## +## @subsubheading Inputs +## @var{obj} - instance of @var{octave_i2c} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'name' +## Set the name for the i2c socket. +## +## @item 'remoteaddress' +## Set the remote address for the i2c socket. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_i2c/get} +## @end deftypefn + +function set (i2c, varargin) + + properties = {'remoteaddress', 'name' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + end + + if numel (property) != numel (value) + error ('i2c:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + end + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("i2c:set:InvalidArgument", ... + "Property '%s' not found in i2c object.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __i2c_properties__ (i2c, property{i}, value{i}); + end + +end diff --git a/inst/@octave_parallel/fclose.m b/inst/@octave_parallel/fclose.m new file mode 100644 index 0000000..1cf1c60 --- /dev/null +++ b/inst/@octave_parallel/fclose.m @@ -0,0 +1,28 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes parallel connection @var{obj} +## @end deftypefn + +function fclose(pp) + + if (nargin == 1) + pp_close (pp); + else + print_usage(); + end +end diff --git a/inst/@octave_parallel/fopen.m b/inst/@octave_parallel/fopen.m new file mode 100644 index 0000000..5bdb275 --- /dev/null +++ b/inst/@octave_parallel/fopen.m @@ -0,0 +1,27 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens parallel interface @var{obj} +## +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_parallel/fread.m b/inst/@octave_parallel/fread.m new file mode 100644 index 0000000..318bdfa --- /dev/null +++ b/inst/@octave_parallel/fread.m @@ -0,0 +1,106 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from parallel instrument +## +## @subsubheading Inputs +## @var{obj} is a parallel object.@* +## @var{size} Number of values to read. (Default: 1).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} The read data.@* +## @var{count} values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + size = 1; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + [tmp1,tmpc] = pp_data (obj); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_parallel/fwrite.m b/inst/@octave_parallel/fwrite.m new file mode 100644 index 0000000..43ccc19 --- /dev/null +++ b/inst/@octave_parallel/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to parallel instrument +## +## @subsubheading Inputs +## @var{obj} is a parallel object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = pp_data (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_serial/fclose.m b/inst/@octave_serial/fclose.m new file mode 100644 index 0000000..ea982ca --- /dev/null +++ b/inst/@octave_serial/fclose.m @@ -0,0 +1,29 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes SERIAL connection @var{obj} +## @end deftypefn + +## TODO: +function fclose(serial) + + if (nargin == 1) + __srl_properties__ (serial, 'close'); + else + print_usage(); + end +end diff --git a/inst/@octave_serial/flushinput.m b/inst/@octave_serial/flushinput.m new file mode 100644 index 0000000..93c72f3 --- /dev/null +++ b/inst/@octave_serial/flushinput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushinput (@var{serial}) +## +## Flush the pending input, which will also make the BytesAvailable property be 0. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class. +## +## @subsubheading Outputs +## None +## +## @seealso{srl_flush, flushoutput} +## @end deftypefn +function flushinput (serial, q) + __srl_properties__ (serial, 'flush', 1); +end diff --git a/inst/@octave_serial/flushoutput.m b/inst/@octave_serial/flushoutput.m new file mode 100644 index 0000000..653e121 --- /dev/null +++ b/inst/@octave_serial/flushoutput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushoutput (@var{serial}) +## +## Flush the output buffer. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class. +## +## @subsubheading Outputs +## None +## +## @seealso{srl_flush, flushinput} +## @end deftypefn +function flushoutput (serial, q) + __srl_properties__ (serial, 'flush', 0); +end diff --git a/inst/@octave_serial/fopen.m b/inst/@octave_serial/fopen.m new file mode 100644 index 0000000..2072182 --- /dev/null +++ b/inst/@octave_serial/fopen.m @@ -0,0 +1,27 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens SERIAL interface @var{obj} +## +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_serial/fprintf.m b/inst/@octave_serial/fprintf.m new file mode 100644 index 0000000..4b403fc --- /dev/null +++ b/inst/@octave_serial/fprintf.m @@ -0,0 +1,50 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) +## Writes formatted string @var{template} using optional parameters to +## serial instrument +## +## @subsubheading Inputs +## @var{obj} is a serial object.@* +## @var{template} Format template string +## +## @subsubheading Outputs +## @var{numbytes} - number of bytes written to the serial device. +## +## @end deftypefn + +function numbytes = fprintf (varargin) + +defaultformat = '%s\n'; + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + formargs = varargin(2); + format = defaultformat; +else(nargin < 4) + formargs = varargin(3:nargin); + format = varargin{2}; +end + +if (! ( ischar (format))) + print_usage (); +end + +numbytes = srl_write (varargin{1}, sprintf (format, formargs{:})); + +end diff --git a/inst/@octave_serial/fread.m b/inst/@octave_serial/fread.m new file mode 100644 index 0000000..0c12800 --- /dev/null +++ b/inst/@octave_serial/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from serial instrument +## +## @subsubheading Inputs +## @var{obj} is a serial object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} The read data.@* +## @var{count} values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = srl_read (obj, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_serial/fwrite.m b/inst/@octave_serial/fwrite.m new file mode 100644 index 0000000..78f4f96 --- /dev/null +++ b/inst/@octave_serial/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to serial instrument +## +## @subsubheading Inputs +## @var{obj} is a serial object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = srl_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_serial/get.m b/inst/@octave_serial/get.m new file mode 100644 index 0000000..9913a18 --- /dev/null +++ b/inst/@octave_serial/get.m @@ -0,0 +1,72 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 John D +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{serial}) +## @deftypefnx {Function File} {@var{field} = } get (@var{serial}, @var{property}) +## Get the properties of serial object. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_serial/set} +## @end deftypefn + +function retval = get (serial, property) + + properties = {'name', 'type', 'status', 'baudrate', 'bytesize', 'parity', ... + 'stopbits', 'timeout', 'requesttosend', ... + 'dataterminalready', 'pinstatus', 'bytesavailable', ... + 'port'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + property = tolower(property); + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("serial:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __srl_properties__ (serial, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_serial/serialbreak.m b/inst/@octave_serial/serialbreak.m new file mode 100644 index 0000000..5d3c783 --- /dev/null +++ b/inst/@octave_serial/serialbreak.m @@ -0,0 +1,41 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} serialbreak (@var{serial}) +## @deftypefnx {Function File} {} serialbreak (@var{serial}, @var{time}) +## Send a break to the serial port +## +## @subsubheading Inputs +## @var{serial} - serial object@* +## @var{time} - number of milliseconds to break for. If not specified a value of 10 will be used. +## +## @subsubheading Outputs +## None +## +## @seealso{serial} +## @end deftypefn + +function serialbreak (serial, mstime) + + if (nargin == 1) + mstime = 10; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + __srl_properties__ (serial, 'break', mstime); + +end diff --git a/inst/@octave_serial/set.m b/inst/@octave_serial/set.m new file mode 100644 index 0000000..0b35c46 --- /dev/null +++ b/inst/@octave_serial/set.m @@ -0,0 +1,111 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of serial object. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'baudrate' +## Set the baudrate of serial port. Supported values by instrument-control: +## 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, +## 19200, 38400, 57600, 115200 and 230400. The supported baudrate of your +## serial port may be different. +## +## @item 'bytesize' +## Set the bytesize. Supported values: 5, 6, 7 and 8. +## +## @item 'name' +## Set the stored string name of the serial object. +## +## @item 'parity' +## Set the parity value. Supported values: Even/Odd/None. This Parameter +## must be of type string. It is case insensitive and can be abbreviated +## to the first letter only +## +## @item 'stopbits' +## Set the number of stopbits. Supported values: 1, 2. +## +## @item 'timeout' +## Set the timeout value in tenths of a second. Value of -1 means a +## blocking call. Maximum value of 255 (i.e. 25.5 seconds). +## +## @item 'requesttosend' +## Set the requesttosend (RTS) line. +## +## @item 'dataterminalready' +## Set the dataterminalready (DTR) line. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_serial/get} +## @end deftypefn + +function set (serial, varargin) + + properties = {'name', 'baudrate','bytesize','parity','stopbits','timeout', ... + 'requesttosend','dataterminalready'}; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + end + + if numel (property) != numel (value) + error ('serial:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + end + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("serial:set:InvalidArgument", ... + "Property '%s' not found in serial object.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __srl_properties__ (serial, property{i}, value{i}); + end + +end diff --git a/inst/@octave_serial/srl_baudrate.m b/inst/@octave_serial/srl_baudrate.m new file mode 100644 index 0000000..75f1976 --- /dev/null +++ b/inst/@octave_serial/srl_baudrate.m @@ -0,0 +1,46 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_baudrate (@var{serial}, @var{baudrate})\ +## @deftypefnx {Loadable Function} {@var{br} = } srl_baudrate (@var{serial}) +## +## Set new or get existing serial interface baudrate parameter. Only standard values are supported. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{baudrate} - the baudrate value used. Supported values: 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600 19200, 38400, 57600, 115200 and 230400.@* +## +## If @var{baudrate} parameter is omitted, the srl_baudrate() shall return current baudrate value as the result @var{br}. +## +## @subsubheading Outputs +## @var{br} - The currently set baudrate +## +## This function is obsolete. Use get and set method instead. +## +## @end deftypefn +function retval = srl_baudrate (serial, baudrate) + + try + if (nargin>1) + __srl_properties__ (serial, 'baudrate', baudrate); + else + retval = __srl_properties__ (serial, 'baudrate'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_bytesize.m b/inst/@octave_serial/srl_bytesize.m new file mode 100644 index 0000000..b6746e5 --- /dev/null +++ b/inst/@octave_serial/srl_bytesize.m @@ -0,0 +1,47 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_bytesize (@var{serial}, @var{bsize}) +## @deftypefnx {Loadable Function} {@var{bs} = } srl_bytesize (@var{serial}) +## +## Set new or get existing serial interface byte size parameter. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{bsize} - byte size of type Integer. Supported values: 5/6/7/8.@* +## +## If @var{bsize} parameter is omitted, the srl_bytesize() shall return current byte size value +## or in case of unsupported setting -1, as the result @var{bs}. +## +## This function is obsolete. Use get and set method instead. +## +## @subsubheading Outputs +## @var{bs} -the currently set byte size. +## +## @end deftypefn +function retval = srl_bytesize (serial, bytesize) + + try + if (nargin>1) + __srl_properties__ (serial, 'bytesize', bytesize); + else + retval = __srl_properties__ (serial, 'bytesize'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_close.m b/inst/@octave_serial/srl_close.m new file mode 100644 index 0000000..332b95d --- /dev/null +++ b/inst/@octave_serial/srl_close.m @@ -0,0 +1,38 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_close (@var{serial}) +## +## Close the interface and release a file descriptor. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class. +## +## This function is obsolete. Use fclose() method instead. +## +## @subsubheading Outputs +## None +## +## @end deftypefn +function srl_close (serial) + + try + __srl_properties__ (serial, 'close'); + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_flush.m b/inst/@octave_serial/srl_flush.m new file mode 100644 index 0000000..cba4284 --- /dev/null +++ b/inst/@octave_serial/srl_flush.m @@ -0,0 +1,51 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_flush (@var{serial}, [@var{q}]) +## +##Flush the pending input/output. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{q} - queue selector of type Integer. Supported values:@* +## @table @asis +## @item 0 +## flush untransmitted output +## @item 1 +## flush pending input +## @item 2 +## flush both pending input and untransmitted output. +## @end table +## +## If @var{q} parameter is omitted, the srl_flush() shall flush both, input and output buffers. +## +## @subsubheading Outputs +## None +## +## @end deftypefn +function srl_flush (serial, q) + + try + if (nargin>1) + __srl_properties__ (serial, 'flush', q); + else + __srl_properties__ (serial, 'flush'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_parity.m b/inst/@octave_serial/srl_parity.m new file mode 100644 index 0000000..781f87a --- /dev/null +++ b/inst/@octave_serial/srl_parity.m @@ -0,0 +1,47 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_parity (@var{serial}, @var{parity}) +## @deftypefnx {Loadable Function} {@var{p} = } srl_parity (@var{serial}) +## +## Set new or get existing serial interface parity parameter. Even/Odd/None values are supported. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{parity} - parity value of type String. Supported values: +## Even/Odd/None (case insensitive, can be abbreviated to the first letter only)@* +## +## If @var{parity} parameter is omitted, the srl_parity() shall return current parity value as the result @var{p}. +## +## This function is obsolete. Use get and set method instead. +## +## @subsubheading Outputs +## @var{p} - The currently set parity +## +## @end deftypefn +function retval = srl_parity (serial, parity) + + try + if (nargin>1) + __srl_properties__ (serial, 'parity', parity); + else + retval = __srl_properties__ (serial, 'parity'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_stopbits.m b/inst/@octave_serial/srl_stopbits.m new file mode 100644 index 0000000..4aa4d18 --- /dev/null +++ b/inst/@octave_serial/srl_stopbits.m @@ -0,0 +1,44 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_stopbits (@var{serial}, @var{stopb}) +## @deftypefnx {Loadable Function} {@var{sb} = } srl_stopbits (@var{serial}) +## +## Set new or get existing serial interface stop bits parameter. Only 1 or 2 stop bits are supported. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{stopb} - number of stop bits used. Supported values: 1, 2.@* +## +## @subsubheading Outputs +## If @var{stopb} parameter is omitted, the srl_stopbits() shall return current stop bits value as the result @var{sb}. +## +## This function is obsolete. Use get and set method instead. +## +## @end deftypefn +function retval = srl_stopbits (serial, stopbits) + + try + if (nargin>1) + __srl_properties__ (serial, 'stopbits', stopbits); + else + retval = __srl_properties__ (serial, 'stopbits'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serial/srl_timeout.m b/inst/@octave_serial/srl_timeout.m new file mode 100644 index 0000000..5ac9b75 --- /dev/null +++ b/inst/@octave_serial/srl_timeout.m @@ -0,0 +1,45 @@ +## Copyright (C) 2014 Stefan Mahr +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} srl_timeout (@var{serial}, @var{timeout}) +## @deftypefnx {Loadable Function} {@var{t} = } srl_timeout (@var{serial}) +## +## Set new or get existing serial interface timeout parameter used for srl_read() requests. The timeout value is specified in tenths of a second. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serial} class.@* +## @var{timeout} - srl_read() timeout value in tenths of a second. +## A value of -1 means a blocking call. Maximum value of 255 (i.e. 25.5 seconds).@* +## +## @subsubheading Outputs +## If @var{timeout} parameter is omitted, the srl_timeout() shall return current timeout value as the result @var{t}. +## +## This function is obsolete. Use get and set method instead. +## +## @end deftypefn +function retval = srl_timeout (serial, timeout) + + try + if (nargin>1) + __srl_properties__ (serial, 'timeout', timeout); + else + retval = __srl_properties__ (serial, 'timeout'); + end + catch + print_usage(); + end +end diff --git a/inst/@octave_serialport/configureTerminator.m b/inst/@octave_serialport/configureTerminator.m new file mode 100644 index 0000000..f57f0fc --- /dev/null +++ b/inst/@octave_serialport/configureTerminator.m @@ -0,0 +1,47 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} configureTerminator (@var{serial}, @var{term}) +## @deftypefnx {Function File} {} configureTerminator (@var{serial}, @var{readterm}, @var{writeterm}) +## Set terminator for ASCII string manipulation +## +## @subsubheading Inputs +## @var{serial} - serialport object@* +## @var{term} - terminal value for both read and write@* +## @var{readterm} = terminal value type for read data@* +## @var{writeterm} = terminal value for written data@* +## +## The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. +## +## @subsubheading Outputs +## None +## +## @seealso{serialport} +## @end deftypefn + +function configureTerminator (serial, readterm, writeterm) + + if nargin < 2 + error ("Expected terminal"); + elseif nargin == 2 + __srlp_properties__ (serial, 'terminator', readterm); + elseif nargin == 3 + __srlp_properties__ (serial, 'terminator', readterm, writeterm); + else + error ("Expected read and write terminal only"); + endif + +endfunction diff --git a/inst/@octave_serialport/flush.m b/inst/@octave_serialport/flush.m new file mode 100644 index 0000000..1310b10 --- /dev/null +++ b/inst/@octave_serialport/flush.m @@ -0,0 +1,49 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} flush (@var{dev}) +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") +## Flush the serial port buffers +## +## @subsubheading Inputs +## @var{dev} - connected serialport device +## +## If an additional parameter is provided of "input" or "output", +## then only the input or output buffer will be flushed +## +## @subsubheading Outputs +## None +## +## @seealso{serialport} +## @end deftypefn + +function flush (dev, flushdir) + + if nargin < 2 + __srlp_properties__ (dev, '__flush__', 0); + __srlp_properties__ (dev, '__flush__', 1); + else + if !ischar (flushdir) + error("flush: expected flushdir to be a string"); + endif + + if strcmp(flushdir, "output") + __srlp_properties__ (dev, '__flush__', 0); + elseif strcmp(flushdir, "input") + __srlp_properties__ (dev, '__flush__', 1); + else + error("flush: invalid flushdir '%s'", flushdir); + endif + endif +endfunction diff --git a/inst/@octave_serialport/fprintf.m b/inst/@octave_serialport/fprintf.m new file mode 100644 index 0000000..a73a648 --- /dev/null +++ b/inst/@octave_serialport/fprintf.m @@ -0,0 +1,50 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) +## Writes formatted string @var{template} using optional parameters to +## serialport instrument +## +## @subsubheading Inputs +## @var{obj} is a serialport object.@* +## @var{template} Format template string +## +## @subsubheading Outputs +## @var{numbytes} - number of bytes written to the serial device. +## +## @end deftypefn + +function numbytes = fprintf (varargin) + + defaultformat = '%s\n'; + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + formargs = varargin(2); + format = defaultformat; + else(nargin < 4) + formargs = varargin(3:nargin); + format = varargin{2}; + endif + + if (! ( ischar (format))) + print_usage (); + endif + + numbytes = __srlp_write__ (varargin{1}, sprintf (format, formargs{:})); + +endfunction diff --git a/inst/@octave_serialport/fread.m b/inst/@octave_serialport/fread.m new file mode 100644 index 0000000..f1c01e5 --- /dev/null +++ b/inst/@octave_serialport/fread.m @@ -0,0 +1,51 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from serial port instrument +## +## @subsubheading Inputs +## @var{obj} is a serialport object.@* +## @var{size} Number of values to read.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} The read data.@* +## @var{count} number of values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + size = get(obj, 'NumBytesAvailable'); +end + +if (nargin < 3) + precision = 'uchar'; +end + + +data = read(obj,size, precision); +errmsg = ''; +count = numel(data); + +endfunction diff --git a/inst/@octave_serialport/fwrite.m b/inst/@octave_serialport/fwrite.m new file mode 100644 index 0000000..4b16acd --- /dev/null +++ b/inst/@octave_serialport/fwrite.m @@ -0,0 +1,40 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to serial port instrument +## +## @subsubheading Inputs +## @var{obj} is a serial port object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + precision = []; + endif + + numbytes = write (obj, data, precision); + +endfunction diff --git a/inst/@octave_serialport/get.m b/inst/@octave_serialport/get.m new file mode 100644 index 0000000..2db26cf --- /dev/null +++ b/inst/@octave_serialport/get.m @@ -0,0 +1,70 @@ +## Copyright (C) 2019 John D +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{serial}) +## @deftypefnx {Function File} {@var{field} = } get (@var{serial}, @var{property}) +## Get the properties of serialport object. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serialport} class.@* +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_serial/set} +## @end deftypefn + +function retval = get (serial, property) + + properties = {'Port', 'BaudRate', 'NumBytesAvailable', 'NumBytesWritten', ... + 'ByteOrder', 'DataBits', 'StopBits', 'Parity', 'FlowControl', ... + 'Timeout', 'Terminator', 'UserData'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + # TODO: multi properties ? + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("serialport:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __srlp_properties__ (serial, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_serialport/getpinstatus.m b/inst/@octave_serialport/getpinstatus.m new file mode 100644 index 0000000..4b9b2cb --- /dev/null +++ b/inst/@octave_serialport/getpinstatus.m @@ -0,0 +1,33 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{status}} getpinstatus (@var{serial}) +## Get status of serial pins +## +## @subsubheading Inputs +## @var{serial} - serial object@* +## +## @subsubheading Outputs +## @var{status} - a structure with the logic names of ClearToSend, DataSetReady, CarrierDetect, and RingIndicator +## +## @seealso{serialport} +## @end deftypefn + +function status = getpinstatus (serial) + + status = __srlp_properties__ (serial, '__pinstatus__'); + +endfunction diff --git a/inst/@octave_serialport/read.m b/inst/@octave_serialport/read.m new file mode 100644 index 0000000..b1776c5 --- /dev/null +++ b/inst/@octave_serialport/read.m @@ -0,0 +1,107 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} read (@var{dev}, @var{count}) +## @deftypefnx {} {@var{data} =} read (@var{dev}, @var{count}, @var{precision}) +## Read a specified number of values from a serialport +## using optional precision for valuesize. +## +## @subsubheading Inputs +## @var{dev} - connected serialport device +## +## @var{count} - number of elements to read +## +## @var{precision} - Optional precision for the output data read data. +## Currently known precision values are uint8 (default), int8, uint16, int16, uint32, int32, uint64, uint64 +## +## @subsubheading Outputs +## @var{data} - data read from the device +## +## @seealso{serialport} +## @end deftypefn + +function data = read (dev, count, precision) + if nargin < 2 + print_usage(); + endif + if nargin < 3 + precision = "uint8"; + endif + + if !ischar(precision) + error ("Expected precision to be a character type"); + endif + + toread = count; + + switch (precision) + case {"string"} + toclass = "char"; + tosize = 1; + case {"char" "schar" "int8"} + toclass = "int8"; + tosize = 1; + case {"uchar" "uint8"} + toclass = "uint8"; + tosize = 1; + case {"int16" "short"} + toclass = "int16"; + tosize = 2; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + tosize = 2; + case {"int32" "int"} + toclass = "int32"; + tosize = 4; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + tosize = 4; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + tosize = 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + tosize = 8; + case {"single" "float" "float32"} + toclass = "single"; + tosize = 4; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + tosize = 8; + toread = toread * 8; + otherwise + error ("precision not supported"); + endswitch + + eoi=0; tmp=[]; count=0; + while ((!eoi) && (toread > 0)) + tmp1 = __srlp_read__ (dev, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; + end + + data = typecast(tmp,toclass); + +endfunction diff --git a/inst/@octave_serialport/serialbreak.m b/inst/@octave_serialport/serialbreak.m new file mode 100644 index 0000000..25ca486 --- /dev/null +++ b/inst/@octave_serialport/serialbreak.m @@ -0,0 +1,41 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} serialbreak (@var{serial}) +## @deftypefnx {Function File} {} serialbreak (@var{serial}, @var{time}) +## Send a break to the serial port +## +## @subsubheading Inputs +## @var{serial} - serialport object@* +## @var{time} - number of milliseconds to break for. If not specified a value of 10 will be used. +## +## @subsubheading Outputs +## None +## +## @seealso{serial} +## @end deftypefn + +function serialbreak (serial, mstime) + + if (nargin == 1) + mstime = 10; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + __srlp_properties__ (serial, '__break__', mstime); + +end diff --git a/inst/@octave_serialport/set.m b/inst/@octave_serialport/set.m new file mode 100644 index 0000000..442dbf9 --- /dev/null +++ b/inst/@octave_serialport/set.m @@ -0,0 +1,110 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of serialport object. +## +## @subsubheading Inputs +## @var{serial} - instance of @var{octave_serialport} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'baudrate' +## Set the baudrate of serial port. Supported values by instrument-control: +## 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, +## 19200, 38400, 57600, 115200 and 230400. The supported baudrate of your +## serial port may be different. +## +## @item 'bytesize' +## Set the bytesize. Supported values: 5, 6, 7 and 8. +## +## @item 'name' +## Set the stored string name of the serial object. +## +## @item 'parity' +## Set the parity value. Supported values: Even/Odd/None. This Parameter +## must be of type string. It is case insensitive and can be abbreviated +## to the first letter only +## +## @item 'stopbits' +## Set the number of stopbits. Supported values: 1, 2. +## +## @item 'timeout' +## Set the timeout value in tenths of a second. Value of -1 means a +## blocking call. Maximum value of 255 (i.e. 25.5 seconds). +## +## @item 'requesttosend' +## Set the requesttosend (RTS) line. +## +## @item 'dataterminalready' +## Set the dataterminalready (DTR) line. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_serialport/-get} +## @end deftypefn + +function set (serial, varargin) + + properties = {'name', 'baudrate','databits','parity','stopbits','timeout', ... + 'flowcontrol', 'userdata'}; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + end + + if numel (property) != numel (value) + error ('serial:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + end + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("serial:set:InvalidArgument", ... + "Property '%s' not found in serial object.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __srlp_properties__ (serial, property{i}, value{i}); + end + +end diff --git a/inst/@octave_serialport/setDTR.m b/inst/@octave_serialport/setDTR.m new file mode 100644 index 0000000..02964f7 --- /dev/null +++ b/inst/@octave_serialport/setDTR.m @@ -0,0 +1,39 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {} setDTR (@var{dev}, @var{true_false}) +## Set the state of the DTR line +## +## @subsubheading Inputs +## @var{dev} - connected serial device.@* +## @var{true_false} - state to set the line.@* +## +## @subsubheading Outputs +## None +## +## @seealso{serialport, getpinstatus, setRTS} +## @end deftypefn + +function setDTR (dev, tf) + + if nargin < 2 + print_usage(); + else + if !islogical (tf) && !isnumeric(tf) + error("setDTR expected pin state to be true or false"); + endif + + __srlp_properties__ (dev, "__dataterminalready__", tf); + + endif +endfunction diff --git a/inst/@octave_serialport/setRTS.m b/inst/@octave_serialport/setRTS.m new file mode 100644 index 0000000..5e8e003 --- /dev/null +++ b/inst/@octave_serialport/setRTS.m @@ -0,0 +1,39 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {} setRTS (@var{dev}, @var{true_false}) +## Set the state of the RTS line +## +## @subsubheading Inputs +## @var{dev} - connected serial device.@* +## @var{true_false} - state to set the line.@* +## +## @subsubheading Outputs +## None +## +## @seealso{serialport, getpinstatus} +## @end deftypefn + +function setRTS (dev, tf) + + if nargin < 2 + print_usage(); + else + if !islogical (tf) && !isnumeric(tf) + error("setRTS expected pin state to be true or false"); + endif + + __srlp_properties__ (dev, "__requesttosend__", tf); + + endif +endfunction diff --git a/inst/@octave_serialport/write.m b/inst/@octave_serialport/write.m new file mode 100644 index 0000000..697e0f0 --- /dev/null +++ b/inst/@octave_serialport/write.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to serialport instrument +## +## @subsubheading Inputs +## @var{obj} is a serialport object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data, precision) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + precision = []; + endif + + switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); + endswitch + + %% should we handle endianess ? + numbytes = __srlp_write__ (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_spi/fclose.m b/inst/@octave_spi/fclose.m new file mode 100644 index 0000000..bb821bf --- /dev/null +++ b/inst/@octave_spi/fclose.m @@ -0,0 +1,23 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes SPI connection @var{obj} +## @end deftypefn + +function fclose(fd) + spi_close(fd); +endfunction diff --git a/inst/@octave_spi/fopen.m b/inst/@octave_spi/fopen.m new file mode 100644 index 0000000..9764001 --- /dev/null +++ b/inst/@octave_spi/fopen.m @@ -0,0 +1,27 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens SPI connection @var{obj} +## +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +endfunction diff --git a/inst/@octave_spi/fread.m b/inst/@octave_spi/fread.m new file mode 100644 index 0000000..ca3dda8 --- /dev/null +++ b/inst/@octave_spi/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from a SPI instrument +## +## @subsubheading Inputs +## @var{obj} is a SPI object.@* +## @var{size} Number of values to read. (Default: 10).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} data values.@* +## @var{count} number of values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 10 as default"); + size = 10; +endif + +if (nargin < 3) + precision = 'uchar'; +endif + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +endswitch + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = spi_read (obj, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +endwhile + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +endif + +endfunction diff --git a/inst/@octave_spi/fwrite.m b/inst/@octave_spi/fwrite.m new file mode 100644 index 0000000..5ac1f5f --- /dev/null +++ b/inst/@octave_spi/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to SPI instrument +## +## @subsubheading Inputs +## @var{obj} is a SPI object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +endif + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +endswitch + +%% should we handle endianess ? +numbytes = spi_write (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_spi/get.m b/inst/@octave_spi/get.m new file mode 100644 index 0000000..9d3aeb6 --- /dev/null +++ b/inst/@octave_spi/get.m @@ -0,0 +1,91 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{spi}) +## @deftypefnx {Function File} {@var{field} = } get (@var{spi}, @var{property}) +## Get the properties of spi object. +## +## @subsubheading Inputs +## @var{spi} - instance of @var{octave_spi} class.@* +## +## @var{property} - name of property.@* +## +## @subsubheading Properties +## @table @var +## @item 'name' +## Name for the spi socket. +## +## @item 'bitrate' +## The bitrate for the spi object. +## +## @item 'clockpolarity' +## The clock polarity for the spi object of 'idlehigh' or 'idlelow'. +## +## @item 'clockphase' +## The clock phase for the spi object of 'firstedge' or 'secondedge'. +## +## @item 'port' +## The device port name. +## +## @item 'status' +## The device status of 'open' or 'closed' +## @end table +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_spi/set} +## @end deftypefn + +function retval = get (spi, property) + + properties = {'name', 'bitrate', 'status', ... + 'port', 'clockpolarity', 'clockphase'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + endif + + if !iscell (property) + property = {property}; + endif + property = tolower(property); + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("spi:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + endif + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __spi_properties__ (spi, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + endif + +endfunction diff --git a/inst/@octave_spi/read.m b/inst/@octave_spi/read.m new file mode 100644 index 0000000..3dd00fa --- /dev/null +++ b/inst/@octave_spi/read.m @@ -0,0 +1,38 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} read (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) +## Reads @var{data} from SPI instrument +## +## @subsubheading Inputs +## @var{obj} is a SPI object.@* +## @var{size} Number of values to read. (Default: 10).@* +## +## @subsubheading Outputs +## @var{data} data values.@* +## +## @end deftypefn + +function data = read (obj, size) + + if (nargin < 2) + error("read: Size expected"); + endif + + data = spi_read (obj, size); + +endfunction diff --git a/inst/@octave_spi/set.m b/inst/@octave_spi/set.m new file mode 100644 index 0000000..71e654d --- /dev/null +++ b/inst/@octave_spi/set.m @@ -0,0 +1,91 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of spi object. +## +## @subsubheading Inputs +## @var{obj} - instance of @var{octave_spi} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'name' +## Set the name for the spi socket. +## +## @item 'bitrate' +## Set the bitrate for the spi object. +## +## @item 'clockpolarity' +## Set the clock polarity for the spi object of 'idlehigh' or 'idlelow'. +## +## @item 'clockphase' +## Set the clock phase for the spi object of 'firstedge' or 'secondedge'. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_spi/get} +## @end deftypefn + +function set (spi, varargin) + + properties = {'bitrate', 'name', 'clockpolarity', 'clockphase' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + endif + + if numel (property) != numel (value) + error ('spi:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + endif + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("spi:set:InvalidArgument", ... + "Property '%s' not found in spi object.\n",x); + cellfun (msg, not_found); + endif + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __spi_properties__ (spi, property{i}, value{i}); + endfor + +endfunction diff --git a/inst/@octave_spi/write.m b/inst/@octave_spi/write.m new file mode 100644 index 0000000..a02eeb4 --- /dev/null +++ b/inst/@octave_spi/write.m @@ -0,0 +1,36 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## Writes @var{data} to SPI instrument +## +## @subsubheading Inputs +## @var{obj} is a SPI object.@* +## @var{data} data to write.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data) + + if (nargin < 2) + print_usage (); + endif + + numbytes = spi_write (obj, uint8(data)); + +endfunction diff --git a/inst/@octave_spi/writeAndRead.m b/inst/@octave_spi/writeAndRead.m new file mode 100644 index 0000000..42203c2 --- /dev/null +++ b/inst/@octave_spi/writeAndRead.m @@ -0,0 +1,37 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} writeAndRead (@var{obj}, @var{wrdata}) +## Writes and reads @var{data} from SPI instrument +## +## @subsubheading Inputs +## @var{obj} is a SPI object.@* +## @var{wrdata} Data to write.@* +## +## @subsubheading Outputs +## @var{data} data values read.@* +## +## @end deftypefn + +function data = writeAndRead (obj, wrdata) + +if (nargin < 2) + error("expected data to write"); +endif + +data = spi_writeAndRead(obj, uint8(wrdata)); + +endfunction diff --git a/inst/@octave_tcp/fclose.m b/inst/@octave_tcp/fclose.m new file mode 100644 index 0000000..bf18a7e --- /dev/null +++ b/inst/@octave_tcp/fclose.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes TCP connection @var{obj} +## @end deftypefn + +## TODO: +function fclose(fd) + +tcp_close(fd); + +end diff --git a/inst/@octave_tcp/flush.m b/inst/@octave_tcp/flush.m new file mode 100644 index 0000000..f1be8fa --- /dev/null +++ b/inst/@octave_tcp/flush.m @@ -0,0 +1,49 @@ +## Copyright (C) 2020 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} flush (@var{dev}) +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") +## Flush the tcp socket buffers +## +## @subsubheading Inputs +## @var{dev} - connected tcp device +## +## If an additional parameter is provided of "input" or "output", +## then only the input or output buffer will be flushed +## +## @subsubheading Outputs +## None +## +## @seealso{serialport} +## @end deftypefn + +function flush (dev, flushdir) + + if nargin < 2 + __tcp_properties__ (dev, 'flush', 0); + __tcp_properties__ (dev, 'flush', 1); + else + if !ischar (flushdir) + error("flush: expected flushdir to be a string"); + endif + + if strcmp(flushdir, "output") + __tcp_properties__ (dev, 'flush', 0); + elseif strcmp(flushdir, "input") + __tcp_properties__ (dev, 'flush', 1); + else + error("flush: invalid flushdir '%s'", flushdir); + endif + endif +endfunction diff --git a/inst/@octave_tcp/flushinput.m b/inst/@octave_tcp/flushinput.m new file mode 100644 index 0000000..c79eb58 --- /dev/null +++ b/inst/@octave_tcp/flushinput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushinput (@var{tcp}) +## +## Flush the pending input, which will also make the BytesAvailable property be 0. +## +## @subsubheading Inputs +## @var{tcp} - instance of @var{octave_tcp} class. +## +## @subsubheading Outputs +## None. +## +## @seealso{flushoutput} +## @end deftypefn +function flushinput (tcp, q) + __tcp_properties__ (tcp, 'flush', 1); +end diff --git a/inst/@octave_tcp/flushoutput.m b/inst/@octave_tcp/flushoutput.m new file mode 100644 index 0000000..32b3c68 --- /dev/null +++ b/inst/@octave_tcp/flushoutput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushoutput (@var{tcp}) +## +## Flush the output buffer. +## +## @subsubheading Inputs +## @var{tcp} - instance of @var{octave_tcp} class. +## +## @subsubheading Outputs +## None. +## +## @seealso{flushinput} +## @end deftypefn +function flushoutput (tcp) + __tcp_properties__ (tcp, 'flush', 0); +end diff --git a/inst/@octave_tcp/fopen.m b/inst/@octave_tcp/fopen.m new file mode 100644 index 0000000..c6ddc79 --- /dev/null +++ b/inst/@octave_tcp/fopen.m @@ -0,0 +1,27 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens TCP connection @var{obj} +## +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_tcp/fprintf.m b/inst/@octave_tcp/fprintf.m new file mode 100644 index 0000000..057404c --- /dev/null +++ b/inst/@octave_tcp/fprintf.m @@ -0,0 +1,50 @@ +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) +## Writes formatted string @var{template} using optional parameters to +## TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{template} Format template string +## +## @subsubheading Outputs +## Number of characters written +## +## @end deftypefn + +function numbytes = fprintf (varargin) + +defaultformat = '%s\n'; + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + formargs = varargin(2); + format = defaultformat; +else(nargin < 4) + formargs = varargin(3:nargin); + format = varargin{2}; +end + +if (! ( ischar (format))) + print_usage (); +end + +numbytes = tcp_write (varargin{1}, sprintf (format, formargs{:})); + +end diff --git a/inst/@octave_tcp/fread.m b/inst/@octave_tcp/fread.m new file mode 100644 index 0000000..d2e153f --- /dev/null +++ b/inst/@octave_tcp/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} data read.@* +## @var{count} values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = tcp_read (obj, toread, get(obj, 'timeout')*1000); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_tcp/fwrite.m b/inst/@octave_tcp/fwrite.m new file mode 100644 index 0000000..aca9373 --- /dev/null +++ b/inst/@octave_tcp/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = tcp_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_tcp/get.m b/inst/@octave_tcp/get.m new file mode 100644 index 0000000..484ea14 --- /dev/null +++ b/inst/@octave_tcp/get.m @@ -0,0 +1,70 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{tcp}) +## @deftypefnx {Function File} {@var{field} = } get (@var{tcp}, @var{property}) +## Get the properties of tcp object. +## +## @subsubheading Inputs +## @var{tcp} - instance of @var{octave_tcp} class.@* +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_tcp/set} +## @end deftypefn + +function retval = get (tcp, property) + + properties = {'name', 'remoteport', 'remotehost', ... + 'localport', 'type', ... + 'status', 'timeout', 'bytesavailable'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + property = tolower(property); + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("tcp:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __tcp_properties__ (tcp, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_tcp/read.m b/inst/@octave_tcp/read.m new file mode 100644 index 0000000..76d1fbb --- /dev/null +++ b/inst/@octave_tcp/read.m @@ -0,0 +1,83 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} read (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) +## Reads @var{data} from TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{datatype} datatype of data.@* +## +## @subsubheading Outputs +## @var{data} data read.@* +## +## @end deftypefn + +function data = read (obj, cnt, datatype) + + if (nargin < 3) + datatype = 'uint8'; + endif + + switch (datatype) + case {"char" "schar" "int8"} + toclass = "int8"; + tosize=1; + case {"uchar" "uint8"} + toclass = "uint8"; + tosize=1; + case {"int16" "short"} + toclass = "int16"; + tosize=2; + case {"uint16" "ushort"} + toclass = "uint16"; + tosize=2; + case {"int32" "int"} + toclass = "int32"; + tosize=4; + case {"uint32" "uint"} + toclass = "uint32"; + tosize=4; + case {"long" "int64"} + toclass = "int64"; + tosize=8; + case {"ulong" "uint64"} + toclass = "uint64"; + tosize=8; + case {"single" "float" "float32"} + toclass = "single"; + tosize=4; + case {"double" "float64"} + toclass = "double"; + tosize=8; + otherwise + error ("precision not supported"); + endswitch + + if (nargin < 2) + cnt = int32(obj.bytesavailable/tosize); + else + cnt = cnt*tosize; + endif + + tmp = tcp_read (obj, cnt, get(obj, 'timeout')*1000); + + data = typecast(tmp,toclass); + +endfunction diff --git a/inst/@octave_tcp/set.m b/inst/@octave_tcp/set.m new file mode 100644 index 0000000..ff92bd8 --- /dev/null +++ b/inst/@octave_tcp/set.m @@ -0,0 +1,89 @@ +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of tcp object. +## +## @subsubheading Inputs +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'name' +## Set the name for the tcp socket. +## +## @item 'remotehost' +## Set the remote host name for the tcp socket. +## +## @item 'remoteport' +## Set the remote port for the tcp socket. +## +## @item 'timeout' +## Set the timeout value in seconds. Value of -1 means a +## blocking call. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_tcp/get} +## @end deftypefn + +function set (tcp, varargin) + + properties = {'timeout', 'name' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + end + + if numel (property) != numel (value) + error ('tcp:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + end + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("tcp:set:InvalidArgument", ... + "Property '%s' not found in tcp object.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __tcp_properties__ (tcp, property{i}, value{i}); + end + +end diff --git a/inst/@octave_tcp/write.m b/inst/@octave_tcp/write.m new file mode 100644 index 0000000..e7fbcd7 --- /dev/null +++ b/inst/@octave_tcp/write.m @@ -0,0 +1,65 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) +## Writes @var{data} to TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{data} data to write.@* +## @var{datatype} datatype of data. If not specified, it defaults to "uint8".@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data, datatype) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + datatype = "uint8"; + endif + + switch (datatype) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + otherwise + error ("precision not supported"); + endswitch + + numbytes = tcp_write (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_tcpclient/configureTerminator.m b/inst/@octave_tcpclient/configureTerminator.m new file mode 100644 index 0000000..d0625d8 --- /dev/null +++ b/inst/@octave_tcpclient/configureTerminator.m @@ -0,0 +1,47 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} configureTerminator (@var{tcp}, @var{term}) +## @deftypefnx {Function File} {} configureTerminator (@var{tcp}, @var{readterm}, @var{writeterm}) +## Set terminator on a tcpclient object for ASCII string manipulation +## +## @subsubheading Inputs +## @var{tcp} - tcpclient object@* +## @var{term} - terminal value for both read and write@* +## @var{readterm} = terminal value type for read data@* +## @var{writeterm} = terminal value for written data@* +## +## The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. +## +## @subsubheading Outputs +## None +## +## @seealso{tcpport} +## @end deftypefn + +function configureTerminator (tcp, readterm, writeterm) + + if nargin < 2 + error ("Expected terminal"); + elseif nargin == 2 + __tcpclient_properties__ (tcp, 'terminator', readterm); + elseif nargin == 3 + __tcpclient_properties__ (tcp, 'terminator', readterm, writeterm); + else + error ("Expected read and write terminal only"); + endif + +endfunction diff --git a/inst/@octave_tcpclient/flush.m b/inst/@octave_tcpclient/flush.m new file mode 100644 index 0000000..805eea3 --- /dev/null +++ b/inst/@octave_tcpclient/flush.m @@ -0,0 +1,49 @@ +## Copyright (C) 2021 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} flush (@var{dev}) +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") +## Flush the tcpclient socket buffers +## +## @subsubheading Inputs +## @var{dev} - connected tcpclient device +## +## If an additional parameter is provided of "input" or "output", +## then only the input or output buffer will be flushed +## +## @subsubheading Outputs +## None +## +## @seealso{serialport} +## @end deftypefn + +function flush (dev, flushdir) + + if nargin < 2 + __tcpclient_properties__ (dev, 'flush', 0); + __tcpclient_properties__ (dev, 'flush', 1); + else + if !ischar (flushdir) + error("flush: expected flushdir to be a string"); + endif + + if strcmp(flushdir, "output") + __tcpclient_properties__ (dev, 'flush', 0); + elseif strcmp(flushdir, "input") + __tcpclient_properties__ (dev, 'flush', 1); + else + error("flush: invalid flushdir '%s'", flushdir); + endif + endif +endfunction diff --git a/inst/@octave_tcpclient/get.m b/inst/@octave_tcpclient/get.m new file mode 100644 index 0000000..1f4af75 --- /dev/null +++ b/inst/@octave_tcpclient/get.m @@ -0,0 +1,70 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{tcpclient}) +## @deftypefnx {Function File} {@var{field} = } get (@var{tcpclient}, @var{property}) +## Get the properties of tcpclient object. +## +## @subsubheading Inputs +## @var{tcpclient} - instance of @var{octave_tcpclient} class.@* +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_tcpclient/set} +## @end deftypefn + +function retval = get (tcpclient, property) + + properties = {'Name', 'Address', 'Port', ... + 'Type', 'Status', 'Timeout', 'UserData', ... + 'NumBytesAvailable', 'NumBytesWritten', ... + 'Terminator' }; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("tcpclient:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __tcpclient_properties__ (tcpclient, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_tcpclient/read.m b/inst/@octave_tcpclient/read.m new file mode 100644 index 0000000..f6a6d45 --- /dev/null +++ b/inst/@octave_tcpclient/read.m @@ -0,0 +1,90 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} read (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) +## Reads @var{data} from TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCP object.@* +## @var{size} Number of values to read. (Default: NumBytesAvailable).@* +## @var{datatype} datatype of data.@* +## +## @subsubheading Outputs +## @var{data} data read.@* +## +## @end deftypefn + +function data = read (obj, cnt, datatype) + + if (nargin < 3) + datatype = 'uint8'; + endif + + switch (datatype) + case {"string"} + toclass = "char"; + tosize=1; + case {"char" "schar" "int8"} + toclass = "int8"; + tosize=1; + case {"uchar" "uint8"} + toclass = "uint8"; + tosize=1; + case {"int16" "short"} + toclass = "int16"; + tosize=2; + case {"uint16" "ushort"} + toclass = "uint16"; + tosize=2; + case {"int32" "int"} + toclass = "int32"; + tosize=4; + case {"uint32" "uint"} + toclass = "uint32"; + tosize=4; + case {"long" "int64"} + toclass = "int64"; + tosize=8; + case {"ulong" "uint64"} + toclass = "uint64"; + tosize=8; + case {"single" "float" "float32"} + toclass = "single"; + tosize=4; + case {"double" "float64"} + toclass = "double"; + tosize=8; + otherwise + error ("precision not supported"); + endswitch + + if (nargin < 2) + cnt = int32(obj.numbytesavailable/tosize); + endif + + cnt = cnt*tosize; + + if cnt > 0 + tmp = __tcpclient_read__ (obj, cnt, get(obj, 'Timeout')*1000); + else + tmp = []; + endif + + data = typecast(tmp,toclass); + +endfunction diff --git a/inst/@octave_tcpclient/set.m b/inst/@octave_tcpclient/set.m new file mode 100644 index 0000000..127b8be --- /dev/null +++ b/inst/@octave_tcpclient/set.m @@ -0,0 +1,85 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of tcpclient object. +## +## @subsubheading Inputs +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'Name' +## Set the name for the tcpclient socket. +## +## @item 'UserData' +## Set user data for the tcpclient socket. +## +## @item 'Timeout' +## Set the timeout value in seconds. Value of -1 means a +## blocking call. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_tcpclient/get} +## @end deftypefn + +function set (tcpclient, varargin) + + properties = {'Timeout', 'Name', 'UserData' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + endif + + if numel (property) != numel (value) + error ('tcpclient:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + endif + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("tcpclient:set:InvalidArgument", ... + "Property '%s' not found in tcpclient object.\n",x); + cellfun (msg, not_found); + endif + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __tcpclient_properties__ (tcpclient, property{i}, value{i}); + endfor + +endfunction diff --git a/inst/@octave_tcpclient/write.m b/inst/@octave_tcpclient/write.m new file mode 100644 index 0000000..a51bc26 --- /dev/null +++ b/inst/@octave_tcpclient/write.m @@ -0,0 +1,67 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) +## Writes @var{data} to TCP instrument +## +## @subsubheading Inputs +## @var{obj} is a TCPclient object.@* +## @var{data} data to write.@* +## @var{datatype} datatype of data. If not specified, it defaults to "uint8".@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data, datatype) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + datatype = "uint8"; + endif + + switch (datatype) + case {"string"} + data = int8 (data); + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + otherwise + error ("precision not supported"); + endswitch + + numbytes = __tcpclient_write__ (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_udp/fclose.m b/inst/@octave_udp/fclose.m new file mode 100644 index 0000000..5bede12 --- /dev/null +++ b/inst/@octave_udp/fclose.m @@ -0,0 +1,23 @@ +## Copyright (C) 2016 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes UDP connection @var{obj} +## @end deftypefn + +function fclose(fd) + udp_close(fd); +end diff --git a/inst/@octave_udp/flush.m b/inst/@octave_udp/flush.m new file mode 100644 index 0000000..05d141b --- /dev/null +++ b/inst/@octave_udp/flush.m @@ -0,0 +1,49 @@ +## Copyright (C) 2020 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} flush (@var{dev}) +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") +## Flush the udp socket buffers +## +## @subsubheading Inputs +## @var{dev} - open udp device +## +## If an additional parameter is provided of "input" or "output", +## then only the input or output buffer will be flushed +## +## @subsubheading Outputs +## None +## +## @seealso{udp} +## @end deftypefn + +function flush (dev, flushdir) + + if nargin < 2 + __udp_properties__ (dev, 'flush', 0); + __udp_properties__ (dev, 'flush', 1); + else + if !ischar (flushdir) + error("flush: expected flushdir to be a string"); + endif + + if strcmp(flushdir, "output") + __udp_properties__ (dev, 'flush', 0); + elseif strcmp(flushdir, "input") + __udp_properties__ (dev, 'flush', 1); + else + error("flush: invalid flushdir '%s'", flushdir); + endif + endif +endfunction diff --git a/inst/@octave_udp/flushinput.m b/inst/@octave_udp/flushinput.m new file mode 100644 index 0000000..04aa44f --- /dev/null +++ b/inst/@octave_udp/flushinput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushinput (@var{udp}) +## +## Flush the pending input, which will also make the BytesAvailable property be 0. +## +## @subsubheading Inputs +## @var{udp} - instance of @var{octave_udp} class. +## +## @subsubheading Outputs +## None +## +## @seealso{flushoutput} +## @end deftypefn +function flushinput (udp, q) + __udp_properties__ (udp, 'flush', 1); +end diff --git a/inst/@octave_udp/flushoutput.m b/inst/@octave_udp/flushoutput.m new file mode 100644 index 0000000..2de9d94 --- /dev/null +++ b/inst/@octave_udp/flushoutput.m @@ -0,0 +1,31 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} flushoutput (@var{udp}) +## +## Flush the output buffer. +## +## @subsubheading Inputs +## @var{udp} - instance of @var{octave_udp} class. +## +## @subsubheading Outputs +## None +## +## @seealso{flushinput} +## @end deftypefn +function flushoutput (udp) + __udp_properties__ (udp, 'flush', 0); +end diff --git a/inst/@octave_udp/fopen.m b/inst/@octave_udp/fopen.m new file mode 100644 index 0000000..fd3ba0b --- /dev/null +++ b/inst/@octave_udp/fopen.m @@ -0,0 +1,26 @@ +## Copyright (C) 2016 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens UDP connection @var{obj} +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_udp/fprintf.m b/inst/@octave_udp/fprintf.m new file mode 100644 index 0000000..fd7ea61 --- /dev/null +++ b/inst/@octave_udp/fprintf.m @@ -0,0 +1,49 @@ +## Copyright (C) 2016-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) +## Writes formatted string @var{template} using optional parameters to +## UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{template} Format template string.@* +## +## @subsubheading Outputs +## @var{numbytes} is the number of bytes written to the device +## @end deftypefn + +function numbytes = fprintf (varargin) + +defaultformat = '%s\n'; + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + formargs = varargin(2); + format = defaultformat; +else(nargin < 4) + formargs = varargin(3:nargin); + format = varargin{2}; +end + +if (! ( ischar (format))) + print_usage (); +end + +numbytes = udp_write (varargin{1}, sprintf (format, formargs{:})); + +end diff --git a/inst/@octave_udp/fread.m b/inst/@octave_udp/fread.m new file mode 100644 index 0000000..2f9b1e9 --- /dev/null +++ b/inst/@octave_udp/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2016-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} data values.@* +## @var{count} number of values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = udp_read (obj, toread, get(obj, 'timeout')*1000); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_udp/fwrite.m b/inst/@octave_udp/fwrite.m new file mode 100644 index 0000000..585ddef --- /dev/null +++ b/inst/@octave_udp/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2016-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = udp_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/@octave_udp/get.m b/inst/@octave_udp/get.m new file mode 100644 index 0000000..3d6c590 --- /dev/null +++ b/inst/@octave_udp/get.m @@ -0,0 +1,71 @@ +## Copyright (C) 2016-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{udp}) +## @deftypefnx {Function File} {@var{field} = } get (@var{udp}, @var{property}) +## Get the properties of udp object. +## +## @subsubheading Inputs +## @var{udp} - instance of @var{octave_udp} class.@* +## +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_udp/set} +## @end deftypefn + +function retval = get (udp, property) + + properties = {'name', 'remoteport', 'remotehost', ... + 'localport', 'localhost', 'type', ... + 'status', 'timeout', 'bytesavailable'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + end + + if !iscell (property) + property = {property}; + end + property = tolower(property); + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("udp:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __udp_properties__ (udp, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + end + +end diff --git a/inst/@octave_udp/read.m b/inst/@octave_udp/read.m new file mode 100644 index 0000000..11e6618 --- /dev/null +++ b/inst/@octave_udp/read.m @@ -0,0 +1,83 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} read (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) +## Reads @var{data} from UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{size} Number of values to read. (Default: BytesAvailable).@* +## @var{datatype} datatype of data.@* +## +## @subsubheading Outputs +## @var{data} data read.@* +## +## @end deftypefn + +function data = read (obj, cnt, datatype) + + if (nargin < 3) + datatype = 'uint8'; + endif + + switch (datatype) + case {"char" "schar" "int8"} + toclass = "int8"; + tosize=1; + case {"uchar" "uint8"} + toclass = "uint8"; + tosize=1; + case {"int16" "short"} + toclass = "int16"; + tosize=2; + case {"uint16" "ushort"} + toclass = "uint16"; + tosize=2; + case {"int32" "int"} + toclass = "int32"; + tosize=4; + case {"uint32" "uint"} + toclass = "uint32"; + tosize=4; + case {"long" "int64"} + toclass = "int64"; + tosize=8; + case {"ulong" "uint64"} + toclass = "uint64"; + tosize=8; + case {"single" "float" "float32"} + toclass = "single"; + tosize=4; + case {"double" "float64"} + toclass = "double"; + tosize=8; + otherwise + error ("precision not supported"); + endswitch + + if (nargin < 2) + cnt = int32(obj.bytesavailable/tosize); + else + cnt = cnt*tosize; + endif + + tmp = udp_read (obj, cnt, get(obj, 'timeout')*1000); + + data = typecast(tmp,toclass); + +endfunction diff --git a/inst/@octave_udp/set.m b/inst/@octave_udp/set.m new file mode 100644 index 0000000..bfb23d0 --- /dev/null +++ b/inst/@octave_udp/set.m @@ -0,0 +1,92 @@ +## Copyright (C) 2016 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of udp object. +## +## @subsubheading Inputs +## @var{obj} - instance of @var{octave_udp} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'name' +## Set the name for the udp socket. +## +## @item 'remotehost' +## Set the remote host name for the udp socket. +## +## @item 'remoteport' +## Set the remote port for the udp socket. +## +## @item 'timeout' +## Set the timeout value in seconds. Value of -1 means a +## blocking call. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_udp/get} +## @end deftypefn + +function set (udp, varargin) + + properties = {'remotehost','remoteport','timeout', 'name' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + end + + if numel (property) != numel (value) + error ('udp:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + end + + property = tolower(property); + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("udp:set:InvalidArgument", ... + "Property '%s' not found in udp object.\n",x); + cellfun (msg, not_found); + end + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __udp_properties__ (udp, property{i}, value{i}); + end + +end diff --git a/inst/@octave_udp/write.m b/inst/@octave_udp/write.m new file mode 100644 index 0000000..cffe10c --- /dev/null +++ b/inst/@octave_udp/write.m @@ -0,0 +1,94 @@ +## Copyright (C) 2020 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}, @var{destinationAddress}, @var{destinationPort})) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}, @var{destinationAddress}, @var{destinationPort}) +## Writes @var{data} to UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{data} data to write.@* +## @var{datatype} datatype of data. If not specified defaults to uint8.@* +## @var{destinationAddress} ipaddress to send to. If not specified, use the remote address.@* +## @var{destinationPort} port to send to. If not specified, use the remote port.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data, varargin) + + if (nargin < 2) + print_usage (); + endif + + datatype = "uint8"; + destinationAddress = obj.remotehost; + destinationPort = obj.remoteport; + + if (nargin == 3) + datatype = varargin{1}; + elseif (nargin == 4) + destinationAddress = varargin{1}; + destinationPort = varargin{2}; + elseif (nargin == 5) + datatype = varargin{1}; + destinationAddress = varargin{2}; + destinationPort = varargin{3}; + elseif nargin > 5 + print_usage (); + endif + + switch (datatype) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + otherwise + error ("datatype not supported"); + endswitch + + oldaddr = obj.remotehost; + oldport = obj.remoteport; + try + obj.remotehost = destinationAddress; + obj.remoteport = destinationPort; + catch + obj.remotehost = oldaddr; + obj.remoteport = oldport; + rethrow (lasterror) + end_try_catch + + numbytes = udp_write (obj, typecast(data,'uint8')); +endfunction diff --git a/inst/@octave_udpport/configureMulticast.m b/inst/@octave_udpport/configureMulticast.m new file mode 100644 index 0000000..afcedef --- /dev/null +++ b/inst/@octave_udpport/configureMulticast.m @@ -0,0 +1,49 @@ +## Copyright (C) 2021 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} configureMulticast((@var{dev}, @var{address}) +## @deftypefnx {} {@var{data} =} configureMulticast((@var{dev}, @var{"off"}) +## Configure udpport device to receive multicast data +## +## @subsubheading Inputs +## @var{dev} - open udpport device +## +## If @var{address} is 'off' disable udp multicast. Otherwise it is the multicast address to use. +## +## @subsubheading Outputs +## None +## +## @seealso{udpport} +## @end deftypefn + +function configureMulticast(dev, address, loopback) + + if nargin < 2 + error("configureMulticast: expected udp object and address"); + endif + + if nargin < 3 + loopback = 1; + endif + + if !ischar (address) + error("configureMulticast: expected address to be a string"); + endif + + if !islogical(loopback) && !isscalar(loopback) + error("configureMulticast: expected loopback to be a boolean"); + endif + + __udpport_properties__ (dev, 'multicastgroup', address); + __udpport_properties__ (dev, 'enablemulticastloopback', loopback); +endfunction diff --git a/inst/@octave_udpport/configureTerminator.m b/inst/@octave_udpport/configureTerminator.m new file mode 100644 index 0000000..43c29a6 --- /dev/null +++ b/inst/@octave_udpport/configureTerminator.m @@ -0,0 +1,47 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} configureTerminator (@var{udp}, @var{term}) +## @deftypefnx {Function File} {} configureTerminator (@var{udp}, @var{readterm}, @var{writeterm}) +## Set terminator for ASCII string manipulation +## +## @subsubheading Inputs +## @var{udp} - udpport object@* +## @var{term} - terminal value for both read and write@* +## @var{readterm} = terminal value type for read data@* +## @var{writeterm} = terminal value for written data@* +## +## The terminal can be either strings "cr", "lf" (default), "lf/cr" or an integer between 0 to 255. +## +## @subsubheading Outputs +## None +## +## @seealso{udpport} +## @end deftypefn + +function configureTerminator (udp, readterm, writeterm) + + if nargin < 2 + error ("Expected terminal"); + elseif nargin == 2 + __udpport_properties__ (udp, 'terminator', readterm); + elseif nargin == 3 + __udpport_properties__ (udp, 'terminator', readterm, writeterm); + else + error ("Expected read and write terminal only"); + endif + +endfunction diff --git a/inst/@octave_udpport/flush.m b/inst/@octave_udpport/flush.m new file mode 100644 index 0000000..920ec46 --- /dev/null +++ b/inst/@octave_udpport/flush.m @@ -0,0 +1,49 @@ +## Copyright (C) 2021 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. + +## -*- texinfo -*- +## @deftypefn {} {@var{data} =} flush (@var{dev}) +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") +## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") +## Flush the udpport socket buffers +## +## @subsubheading Inputs +## @var{dev} - open udpport device +## +## If an additional parameter is provided of "input" or "output", +## then only the input or output buffer will be flushed +## +## @subsubheading Outputs +## None +## +## @seealso{udpport} +## @end deftypefn + +function flush (dev, flushdir) + + if nargin < 2 + __udpport_properties__ (dev, 'flush', 0); + __udpport_properties__ (dev, 'flush', 1); + else + if !ischar (flushdir) + error("flush: expected flushdir to be a string"); + endif + + if strcmp(flushdir, "output") + __udpport_properties__ (dev, 'flush', 0); + elseif strcmp(flushdir, "input") + __udpport_properties__ (dev, 'flush', 1); + else + error("flush: invalid flushdir '%s'", flushdir); + endif + endif +endfunction diff --git a/inst/@octave_udpport/fprintf.m b/inst/@octave_udpport/fprintf.m new file mode 100644 index 0000000..e03bea0 --- /dev/null +++ b/inst/@octave_udpport/fprintf.m @@ -0,0 +1,49 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} =} fprintf (@var{obj}, @var{template} ...) +## Writes formatted string @var{template} using optional parameters to +## UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDPPort object.@* +## @var{template} Format template string.@* +## +## @subsubheading Outputs +## @var{numbytes} is the number of bytes written to the device +## @end deftypefn + +function numbytes = fprintf (varargin) + + defaultformat = '%s\n'; + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + formargs = varargin(2); + format = defaultformat; + else(nargin < 4) + formargs = varargin(3:nargin); + format = varargin{2}; + endif + + if (! ( ischar (format))) + print_usage (); + endif + + numbytes = __udpport_write__ (varargin{1}, sprintf (format, formargs{:})); + +endfunction diff --git a/inst/@octave_udpport/fread.m b/inst/@octave_udpport/fread.m new file mode 100644 index 0000000..9a054dc --- /dev/null +++ b/inst/@octave_udpport/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP port object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} data values.@* +## @var{count} number of values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + + if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; + endif + + if (nargin < 3) + precision = 'uchar'; + endif + + if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); + elseif (numel(size) == 1) + toread = size; + else + print_usage(); + endif + + switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); + endswitch + + eoi=0; tmp=[]; count=0; + while ((!eoi) && (toread > 0)) + tmp1 = __udpport_read__ (obj, toread, get(obj, 'Timeout')*1000); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + endif + tmp = [tmp tmp1]; + endwhile + + errmsg = ''; + + data = typecast(tmp,toclass); + if (numel(size) > 1) + data = reshape(data,size); + endif + +endfunction diff --git a/inst/@octave_udpport/fwrite.m b/inst/@octave_udpport/fwrite.m new file mode 100644 index 0000000..b5c5344 --- /dev/null +++ b/inst/@octave_udpport/fwrite.m @@ -0,0 +1,67 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP port object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + precision = []; + endif + + switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); + endswitch + + numbytes = __udpport_write__ (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_udpport/get.m b/inst/@octave_udpport/get.m new file mode 100644 index 0000000..7edb05b --- /dev/null +++ b/inst/@octave_udpport/get.m @@ -0,0 +1,72 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{struct} = } get (@var{udpport}) +## @deftypefnx {Function File} {@var{field} = } get (@var{udpport}, @var{property}) +## Get the properties of udpport object. +## +## @subsubheading Inputs +## @var{udpport} - instance of @var{octave_udpport} class.@* +## +## @var{property} - name of property.@* +## +## @subsubheading Outputs +## When @var{property} was specified, return the value of that property.@* +## otherwise return the values of all properties as a structure.@* +## +## @seealso{@@octave_udpport/set} +## @end deftypefn + +function retval = get (udpport, property) + + properties = {'Name', 'UserData', "IPAddressVersion", ... + 'LocalPort', 'LocalHost', 'Type', 'Terminator', ... + 'Status', 'Timeout', 'NumBytesAvailable', 'NumBytesWritten', ... + 'MulticastGroup', 'EnableMulticast', 'EnableMulticastLoopback', ... + 'EnablePortSharing', 'EnableBroadcast', 'ByteOrder'}; + + if (nargin == 1) + property = properties; + elseif (nargin > 2) + error ("Too many arguments.\n"); + endif + + if !iscell (property) + property = {property}; + endif + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error("udpport:get:InvalidArgument", ... + "Unknown property '%s'.\n",x); + cellfun (msg, not_found); + endif + + property = {property{valid}}; + retval = {}; + for i=1:length(property) + retval{end+1} = __udpport_properties__ (udpport, property{i}); + endfor + + if numel(property) == 1 + retval = retval{1}; + elseif (nargin == 1) + retval = cell2struct (retval',properties); + endif + +endfunction diff --git a/inst/@octave_udpport/read.m b/inst/@octave_udpport/read.m new file mode 100644 index 0000000..b1b2132 --- /dev/null +++ b/inst/@octave_udpport/read.m @@ -0,0 +1,90 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} read (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} read (@var{obj}, @var{size}, @var{datatype}) +## Reads @var{data} from UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDP object.@* +## @var{size} Number of values to read. (Default: BytesAvailable).@* +## @var{datatype} datatype of data.@* +## +## @subsubheading Outputs +## @var{data} data read.@* +## +## @end deftypefn + +function data = read (obj, cnt, datatype) + + if (nargin < 3) + datatype = 'uint8'; + endif + + switch (datatype) + case {"string"} + toclass = "char"; + tosize=1; + case {"char" "schar" "int8"} + toclass = "int8"; + tosize=1; + case {"uchar" "uint8"} + toclass = "uint8"; + tosize=1; + case {"int16" "short"} + toclass = "int16"; + tosize=2; + case {"uint16" "ushort"} + toclass = "uint16"; + tosize=2; + case {"int32" "int"} + toclass = "int32"; + tosize=4; + case {"uint32" "uint"} + toclass = "uint32"; + tosize=4; + case {"long" "int64"} + toclass = "int64"; + tosize=8; + case {"ulong" "uint64"} + toclass = "uint64"; + tosize=8; + case {"single" "float" "float32"} + toclass = "single"; + tosize=4; + case {"double" "float64"} + toclass = "double"; + tosize=8; + otherwise + error ("precision not supported"); + endswitch + + if (nargin < 2) + cnt = int32(obj.numbytesavailable/tosize); + endif + + cnt = cnt*tosize; + + if cnt > 0 + tmp = __udpport_read__ (obj, cnt, get(obj, 'Timeout')*1000); + else + tmp = []; + endif + + data = typecast(tmp,toclass); + +endfunction diff --git a/inst/@octave_udpport/set.m b/inst/@octave_udpport/set.m new file mode 100644 index 0000000..5d505a3 --- /dev/null +++ b/inst/@octave_udpport/set.m @@ -0,0 +1,88 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} set (@var{obj}, @var{property},@var{value}) +## @deftypefnx {Function File} set (@var{obj}, @var{property},@var{value},@dots{}) +## Set the properties of udpport object. +## +## @subsubheading Inputs +## @var{obj} - instance of @var{octave_udpport} class.@* +## @var{property} - name of property.@* +## +## If @var{property} is a cell so must be @var{value}, it sets the values of +## all matching properties. +## +## The function also accepts property-value pairs. +## +## @subsubheading Properties +## @table @var +## @item 'Name' +## Set the name for the udpport socket. +## +## @item 'UserData' +## Set the user data of the object. +## +## @item 'Timeout' +## Set the timeout value in seconds. Value of -1 means a +## blocking call. +## +## @end table +## +## @subsubheading Outputs +## None +## +## @seealso{@@octave_udpport/get} +## @end deftypefn + +function set (udpport, varargin) + + properties = {'UserData','Timeout', 'Name', 'EnableBroadcast' }; + + if numel (varargin) == 1 && isstruct (varargin{1}) + property = fieldnames (varargin{1}); + func = @(x) getfield (varargin{1}, x); + value = cellfun (func, property, 'UniformOutput', false); + elseif numel (varargin) == 2 && iscell (varargin{1}) && iscell (varargin{2}) + %% The arguments are two cells, expecting fields and values. + property = varargin{1}; + value = varargin{2}; + else + property = {varargin{1:2:end}}; + value = {varargin{2:2:end}}; + endif + + if numel (property) != numel (value) + error ('udpport:set:InvalidArgument', ... + 'PROPERIES and VALUES must have the same number of elements.'); + endif + + valid = ismember (property, properties); + not_found = {property{!valid}}; + + if !isempty (not_found) + msg = @(x) error ("udpport:set:InvalidArgument", ... + "Property '%s' not found in udpport object.\n",x); + cellfun (msg, not_found); + endif + + property = {property{valid}}; + value = {value{valid}}; + + for i=1:length(property) + __udpport_properties__ (udpport, property{i}, value{i}); + endfor + +endfunction diff --git a/inst/@octave_udpport/write.m b/inst/@octave_udpport/write.m new file mode 100644 index 0000000..77fd047 --- /dev/null +++ b/inst/@octave_udpport/write.m @@ -0,0 +1,90 @@ +## Copyright (C) 2021 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} = } write (@var{obj}, @var{data}, @var{destinationAddress}, @var{destinationPort})) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}) +## @deftypefnx {Function File} {@var{numbytes} =} write (@var{obj}, @var{data}, @var{datatype}, @var{destinationAddress}, @var{destinationPort}) +## Writes @var{data} to UDP instrument +## +## @subsubheading Inputs +## @var{obj} is a UDPPort object.@* +## @var{data} data to write.@* +## @var{datatype} datatype of data. If not specified defaults to uint8.@* +## @var{destinationAddress} ipaddress to send to. If not specified, use the previously used remote address.@* +## @var{destinationPort} port to send to. If not specified, use the remote port.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = write(obj, data, varargin) + + if (nargin < 2) + print_usage (); + endif + + datatype = "uint8"; + destinationAddress = ""; + destinationPort = 0; + + if (nargin == 3) + datatype = varargin{1}; + elseif (nargin == 4) + destinationAddress = varargin{1}; + destinationPort = varargin{2}; + elseif (nargin == 5) + datatype = varargin{1}; + destinationAddress = varargin{2}; + destinationPort = varargin{3}; + elseif nargin > 5 + print_usage (); + endif + + switch (datatype) + case {"char" "schar" "int8", "string"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + otherwise + error ("datatype not supported"); + endswitch + + if !isempty(destinationAddress) + if !ischar(destinationAddress) + error ("Expected address as a string"); + endif + numbytes = __udpport_write__ (obj, typecast(data,'uint8'), destinationAddress, destinationPort); + else + numbytes = __udpport_write__ (obj, typecast(data,'uint8')); + endif +endfunction diff --git a/inst/@octave_usbtmc/fclose.m b/inst/@octave_usbtmc/fclose.m new file mode 100644 index 0000000..913e522 --- /dev/null +++ b/inst/@octave_usbtmc/fclose.m @@ -0,0 +1,28 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes USBTMC connection @var{obj} +## +## @subsubheading Inputs +## @var{obj} is a usbtmc object.@* +## @end deftypefn + +function fclose(fd) + +usbtmc_close(fd); + +end diff --git a/inst/@octave_usbtmc/fopen.m b/inst/@octave_usbtmc/fopen.m new file mode 100644 index 0000000..ebf4204 --- /dev/null +++ b/inst/@octave_usbtmc/fopen.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens USBTMC connection @var{obj} +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_usbtmc/fread.m b/inst/@octave_usbtmc/fread.m new file mode 100644 index 0000000..d4d8e7b --- /dev/null +++ b/inst/@octave_usbtmc/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from usbtmc instrument +## +## @subsubheading Inputs +## @var{obj} is a usbtmc object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} The read data.@* +## @var{count} values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + + if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; + endif + + if (nargin < 3) + precision = 'uchar'; + endif + + if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); + elseif (numel(size) == 1) + toread = size; + else + print_usage(); + endif + + switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); + endswitch + + eoi=0; tmp=[]; count=0; + while ((!eoi) && (toread > 0)) + tmp1 = usbtmc_read (obj, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + endif + tmp = [tmp tmp1]; + endwhile + + errmsg = ''; + + data = typecast(tmp,toclass); + if (numel(size) > 1) + data = reshape(data,size); + endif + +endfunction diff --git a/inst/@octave_usbtmc/fwrite.m b/inst/@octave_usbtmc/fwrite.m new file mode 100644 index 0000000..b998157 --- /dev/null +++ b/inst/@octave_usbtmc/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to an usbtmc instrument +## +## @subsubheading Inputs +## @var{obj} is a usbtmc object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + + if (nargin < 2) + print_usage (); + elseif (nargin < 3) + precision = []; + endif + + switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); + endswitch + + %% should we handle endianess ? + numbytes = vxi11_write (obj, typecast(data,'uint8')); + +endfunction diff --git a/inst/@octave_vxi11/fclose.m b/inst/@octave_vxi11/fclose.m new file mode 100644 index 0000000..0441940 --- /dev/null +++ b/inst/@octave_vxi11/fclose.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fclose (@var{obj}) +## Closes VXI11 connection @var{obj} +## @end deftypefn + +## TODO: +function fclose(fd) + +vxi11_close(fd); + +end diff --git a/inst/@octave_vxi11/fopen.m b/inst/@octave_vxi11/fopen.m new file mode 100644 index 0000000..b6435ea --- /dev/null +++ b/inst/@octave_vxi11/fopen.m @@ -0,0 +1,26 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{res} =} fopen (@var{obj}) (dummy) +## Opens VXI11 connection @var{obj} +## This currently is a dummy function to improve compatibility to MATLAB +## +## @end deftypefn +function fopen(fd) + +% dummy for matlab compatibility + +end diff --git a/inst/@octave_vxi11/fread.m b/inst/@octave_vxi11/fread.m new file mode 100644 index 0000000..be3e321 --- /dev/null +++ b/inst/@octave_vxi11/fread.m @@ -0,0 +1,108 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{data} =} fread (@var{obj}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}) +## @deftypefnx {Function File} {@var{data} =} fread (@var{obj}, @var{size}, @var{precision}) +## @deftypefnx {Function File} {[@var{data},@var{count}] =} fread (@var{obj}, ...) +## @deftypefnx {Function File} {[@var{data},@var{count},@var{errmsg}] =} fread (@var{obj}, ...) +## Reads @var{data} from vxi11 instrument +## +## @subsubheading Inputs +## @var{obj} is a vxi11 object.@* +## @var{size} Number of values to read. (Default: 100).@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## @var{data} The read data.@* +## @var{count} values read.@* +## @var{errmsg} read operation error message.@* +## +## @end deftypefn + +function [data, count, errmsg] = fread (obj, size, precision) + +if (nargin < 2) + ## TODO: InputBufferSize property not implemented yet + warning("fread: InputBufferSize property not implemented yet, using 100 as default"); + size = 100; +end + +if (nargin < 3) + precision = 'uchar'; +end + +if ((rows(size) == 1) && (columns(size) == 2)) + toread = size(1) * size(2); +elseif (numel(size) == 1) + toread = size; +else + print_usage(); +endif + +switch (precision) + case {"char" "schar" "int8"} + toclass = "int8"; + case {"uchar" "uint8"} + toclass = "uint8"; + case {"int16" "short"} + toclass = "int16"; + toread = toread * 2; + case {"uint16" "ushort"} + toclass = "uint16"; + case {"int32" "int"} + toclass = "int32"; + toread = toread * 4; + case {"uint32" "uint"} + toclass = "uint32"; + toread = toread * 4; + case {"long" "int64"} + toclass = "int64"; + toread = toread * 8; + case {"ulong" "uint64"} + toclass = "uint64"; + toread = toread * 8; + case {"single" "float" "float32"} + toclass = "single"; + toread = toread * 4; + case {"double" "float64"} + toclass = "double"; + toread = toread * 8; + otherwise + error ("precision not supported"); +end + +eoi=0; tmp=[]; count=0; +while ((!eoi) && (toread > 0)) + tmp1 = vxi11_read (obj, toread); + if !isempty(tmp1) + wasread = numel(tmp1); + count = count + wasread; + toread = toread - wasread; + else + break; + end + tmp = [tmp tmp1]; +end + +errmsg = ''; + +data = typecast(tmp,toclass); +if (numel(size) > 1) + data = reshape(data,size); +end + +endfunction diff --git a/inst/@octave_vxi11/fwrite.m b/inst/@octave_vxi11/fwrite.m new file mode 100644 index 0000000..51eb2c8 --- /dev/null +++ b/inst/@octave_vxi11/fwrite.m @@ -0,0 +1,68 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{numbytes} = } fwrite (@var{obj}, @var{data}) +## @deftypefnx {Function File} {@var{numbytes} =} fwrite (@var{obj}, @var{data}, @var{precision}) +## Writes @var{data} to vxi11 instrument +## +## @subsubheading Inputs +## @var{obj} is a vxi11 object.@* +## @var{data} data to write.@* +## @var{precision} precision of data.@* +## +## @subsubheading Outputs +## returns number of bytes written. +## @end deftypefn + +function numbytes = fwrite(obj, data, precision) + +if (nargin < 2) + print_usage (); +elseif (nargin < 3) + precision = []; +end + +switch (precision) + case {"char" "schar" "int8"} + data = int8 (data); + case {"uchar" "uint8"} + data = uint8 (data); + case {"int16" "short"} + data = int16 (data); + case {"uint16" "ushort"} + data = uint16 (data); + case {"int32" "int"} + data = int32 (data); + case {"uint32" "uint"} + data = uint32 (data); + case {"long" "int64"} + data = int64 (data); + case {"ulong" "uint64"} + data = uint64 (data); + case {"single" "float" "float32"} + data = single (data); + case {"double" "float64"} + data = double (data); + case [] + %% use data as it is + otherwise + error ("precision not supported"); +end + +%% should we handle endianess ? +numbytes = vxi11_write (obj, typecast(data,'uint8')); + +end diff --git a/inst/__instrument_control__.m b/inst/__instrument_control__.m new file mode 100644 index 0000000..4aaa2c7 --- /dev/null +++ b/inst/__instrument_control__.m @@ -0,0 +1,78 @@ +## Copyright (C) 2019-202 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. + +## -*- texinfo -*- +## @subsubheading Overview +## The Instrument control package provides low level I/O functions for serial, i2c, parallel, spi, tcp, gpib, +## vxi11, udp and usbtmc interfaces. +## +## It attempts to provide the same function calls as the Matlab toolkit, as well as additional functionality. +## +## @subsubheading Interfaces +## The following interfaces have been implemented: +## @table @asis +## @item serial (depreciated) +## serial port functionality. It has been depreciated in favor of the serialport interface. +## @item serialport +## serial port functionality. +## @item spi +## spi device functionality. +## @item tcp / tcpip +## tcp socket functionality +## @item udp +## udp socket functionality +## @item i2c +## i2c device functionality +## @item usbtmc +## usbtmc device functionality +## @item vxi11 +## vxi11 device functionality +## @item parallel +## parallel port functionality +## @item gpip +## gpip device functionality +## @end table +## +## Use of the actual devices depend on whether teh functionality was enabled during package installation. +## +## To verify the available interfaces, run the following command in octave: +## +## @example +## instrhwinfo +## @end example +## +## The function will return information on the supported interfaces that are available, similar to below: +## +## @example +## ToolboxVersion = 0.4.0 +## ToolboxName = octave instrument control package +## SupportedInterfaces = +## @{ +## [1,1] = gpib +## [1,2] = i2c +## [1,3] = parallel +## [1,4] = serial +## [1,5] = tcp +## [1,6] = udp +## [1,7] = usbtmc +## [1,8] = vxi11 +## @} +## @end example +## +## Information on each device type can be obtained using: +## +## @example +## instrhelp . +## @end example +function __instrument_control__ () + # do nothing +endfunction diff --git a/inst/clrdevice.m b/inst/clrdevice.m new file mode 100644 index 0000000..01a845d --- /dev/null +++ b/inst/clrdevice.m @@ -0,0 +1,37 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} clrdevice (@var{obj}) +## Send clear command to Clear GPIB instrument. +## +## @var{obj} is a GPIB object +## +## @end deftypefn + +## TODO: + +function clrdevice (obj) +# + +if (nargin < 1) + print_usage(); +end + +if (!isa (obj,'octave_gpib')) + error ('clrdevice: need octave_gpib object'); +end + +__gpib_clrdevice__ (obj); diff --git a/inst/flushinput.m b/inst/flushinput.m new file mode 100644 index 0000000..fc8e960 --- /dev/null +++ b/inst/flushinput.m @@ -0,0 +1,78 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {} flushinput (@var{dev}) +## Flush the instruments input buffers +## +## @subsubheading Inputs +## @var{dev} - connected device or array of devices +## +## @subsubheading Outputs +## None +## +## @seealso{flushoutput} +## @end deftypefn + +function flushinput (dev) + + if nargin < 1 + error ('expected instrument control device'); + endif + + if iscell(dev) + for i=1:length(dev) + flushinput(dev{i}); + endfor + else + if !strncmp(typeinfo(dev), "octave_", 7) + error ('expected instrument control device'); + endif + + # handle instruments we have a valid way of flushing input + if (isa (dev,'octave_serialport')) + flush(dev, "input"); + elseif (isa (dev,'octave_serial')) + __srl_properties__ (dev, 'flush', 1); + elseif (isa (dev,'octave_udp')) + __udp_properties__ (dev, 'flush', 1); + elseif (isa (dev,'octave_udpport')) + __udpport_properties__ (dev, 'flush', 1); + elseif (isa (dev,'octave_tcp')) + __tcp_properties__ (dev, 'flush', 1); + elseif (isa (dev,'octave_tcpclient')) + __tcpclient_properties__ (dev, 'flush', 1); + elseif (isa (dev,'octave_gpib')) + __gpib_clrdevice__ (obj); + else + # anything not handled specifically + data = [1]; + while (~isempty(data)) + data = fread(obj,100); + endwhile + endif + endif +endfunction + +%!error flushinput +%!error flushinput (1) + +%!test +%! a = udp (); +%! flushinput(a); +%! clear a + +%!test +%! a = udp (); +%! b = udp (); +%! flushinput({a b}); +%! clear a b diff --git a/inst/flushoutput.m b/inst/flushoutput.m new file mode 100644 index 0000000..91ec6ec --- /dev/null +++ b/inst/flushoutput.m @@ -0,0 +1,72 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {} flushoutput (@var{dev}) +## Flush the instruments output buffers +## +## @subsubheading Inputs +## @var{dev} - connected device or array of devices +## +## @subsubheading Outputs +## None +## +## @seealso{flushinput} +## @end deftypefn + +function flushoutput (dev) + + if nargin < 1 + error ('expected instrument control device'); + endif + + if iscell(dev) + for i=1:length(dev) + flushoutput(dev{i}); + endfor + else + if !strncmp(typeinfo(dev), "octave_", 7) + error ('expected instrument control device'); + endif + + # handle instruments we have a valid way of flushing input + if (isa (dev,'octave_serialport')) + flush(dev, "output"); + elseif (isa (dev,'octave_serial')) + __srl_properties__ (dev, 'flush', 0); + elseif (isa (dev,'octave_udp')) + __udp_properties__ (dev, 'flush', 0); + elseif (isa (dev,'octave_udpport')) + __udpport_properties__ (dev, 'flush', 0); + elseif (isa (dev,'octave_tcp')) + __tcp_properties__ (dev, 'flush', 0); + elseif (isa (dev,'octave_tcpclient')) + __tcpclient_properties__ (dev, 'flush', 0); + elseif (isa (dev,'octave_gpib')) + __gpib_clrdevice__ (obj); + endif + endif +endfunction + +%!error flushoutput +%!error flushoutput (1) + +%!test +%! a = udp (); +%! flushoutput(a); +%! clear a + +%!test +%! a = udp (); +%! b = udp (); +%! flushoutput({a b}); +%! clear a b diff --git a/inst/instrhelp.m b/inst/instrhelp.m new file mode 100644 index 0000000..576eb08 --- /dev/null +++ b/inst/instrhelp.m @@ -0,0 +1,56 @@ +## Copyright (C) 2019 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. + +## -*- texinfo -*- +## @deftypefn {} {} instrhelp () +## @deftypefnx {} {} instrhelp (@var{funcname}) +## @deftypefnx {} {} instrhelp (@var{obj}) +## Display instrument help +## +## @subsubheading Inputs +## @var{funcname} - function to display help about.@* +## @var{obj} - object to display help about.@* +## +## If no input is provided, the function will display and overview +## of the package functionality. +## +## @subsubheading Outputs +## None +## +## @end deftypefn + +function out = instrhelp (varargin) + if nargin < 1 + v = "__instrument_control__"; + else + v = varargin{1}; + if !ischar(v) + v = typeinfo(v); + if !strncmp(v, "octave_", 7) + error ('expected instrument control device'); + endif + + v = strrep(v, "octave_", ""); + endif + endif + + if nargout > 0 + out = help(v); + else + help(v); + endif + +endfunction + +%!assert (! isempty (strfind (help ("instrhelp"), "Display instrument help"))) + +%!error instrhelp (1) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m new file mode 100644 index 0000000..ac59af4 --- /dev/null +++ b/inst/instrhwinfo.m @@ -0,0 +1,157 @@ +## Copyright (C) 2018-2020 John Donoghue +## Copyright (C) 2016 Andreas Weber +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{list}] =} instrhwinfo () +## @deftypefnx {Function File} {@var{list} =} instrhwinfo (@var{interface}) +## Query available hardware for instrument-control +## +## When run without any input parameters, instrhwinfo will provide the toolbox +## information and a list of supported interfaces. +## +## @subsubheading Inputs +## @var{interface} is the instrument interface to query. When provided, instrhwinfo +## will provide information on the specified interface. +## +## Currently only interface "serialport","i2c" and "spi" and is supported, which will provide a list of +## available serial ports or i2c ports. +## +## @subsubheading Outputs +## If an output variable is provided, the function will store the information +## to the variable, otherwise it will be displayed to the screen. +## +## @subsubheading Example +## @example +## instrhwinfo +## scalar structure containing the fields: +## +## ToolboxVersion = 0.4.0 +## ToolboxName = octave instrument control package +## SupportedInterfaces = +## @{ +## [1,1] = i2c +## [1,2] = parallel +## [1,3] = serialport +## [1,4] = tcp +## [1,5] = udp +## [1,6] = usbtmc +## [1,7] = vxi11 +## @} +## +## @end example +## +## @end deftypefn + +function out = instrhwinfo (interface) + + if (nargin == 0) + a = __instr_hwinfo__(); + if (nargout == 0) + disp(a); + else + out = a; + endif + elseif (nargin != 1) + print_usage (); + elseif (strcmpi (interface, "serial")) + + if (ispc ()) # windoze + + Skey = 'HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM'; + ## Find connected serial devices and clean up the output + [~, list] = dos(['REG QUERY ' Skey]); + [~, ~, ~, out]=regexp (list, "COM[0-9]+"); + + elseif (ismac ()) + + tmp = glob ("/dev/tty.*"); + out = strrep (tmp, "/dev/", ""); + + elseif (isunix ()) # GNU/Linux, BSD... + + ## only devices with device/driver + tmp = glob ("/sys/class/tty/*/device/driver"); + tmp = strrep (tmp, "/sys/class/tty/", ""); + out = strrep (tmp, "/device/driver", ""); + + endif + elseif (strcmpi (interface, "serialport")) + if (ispc ()) # windoze + + Skey = 'HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM'; + ## Find connected serial devices and clean up the output + [~, list] = dos(['REG QUERY ' Skey]); + [~, ~, ~, out]=regexp (list, "COM[0-9]+"); + + elseif (ismac ()) + + out = glob ("/dev/tty.*"); + + elseif (isunix ()) # GNU/Linux, BSD... + + ## only devices with device/driver + #/sys/class/tty/ttyS0/device/driver + tmp = glob ("/sys/class/tty/*/device/driver"); + tmp = strrep (tmp, "/sys/class/tty", "/dev"); + out = strrep (tmp, "/device/driver", ""); + endif + + elseif (strcmpi (interface, "i2c")) + if (isunix ()) # GNU/Linux, BSD... + + ## only devices with device/driver + tmp = glob ("/sys/class/i2c-adapter/*/device/driver"); + tmp = strrep (tmp, "/sys/class/i2c-adapter/", ""); + out = strrep (tmp, "/device/driver", ""); + else + out = []; + endif + + elseif (strcmpi (interface, "spi")) + if (isunix ()) # GNU/Linux, BSD... + + ## only devices with device/driver + tmp = glob ("/sys/class/spidev/*/device/driver"); + tmp = strrep (tmp, "/sys/class/spidev/", ""); + out = strrep (tmp, "/device/driver", ""); + else + out = []; + endif + + else + error ("Interface '%s' not yet implemented...", interface); + endif + +endfunction + +%!test +%! a = instrhwinfo(); +%! assert(! isempty (a)) + +%!xtest +%! # could fail if no serial ports? +%! assert(!isempty(instrhwinfo("serial"))) + +%!error instrhwinfo("serial", "2ndarg") + +%!xtest +%! # could fail if no i2c ports or not configured +%! assert(!isempty(instrhwinfo("i2c"))) + +%!test +%! p = pkg('describe', 'instrument-control'); +%! hw = instrhwinfo (); +%! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/seriallist.m b/inst/seriallist.m new file mode 100644 index 0000000..0ad1f38 --- /dev/null +++ b/inst/seriallist.m @@ -0,0 +1,39 @@ +## Copyright (C) 2018 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{list} = } seriallist () +## Returns a list of all serial ports detected in the system. +## +## @subsubheading Inputs +## None +## +## @subsubheading Outputs +## @var{list} is a string cell array of serial ports names detected +## in the system. +## +## @seealso{instrhwinfo("serial")} +## @end deftypefn + +function out = seriallist () + + if nargin != 0 + print_usage (); + endif + + out = instrhwinfo("serial"); +endfunction + +%!assert(seriallist, instrhwinfo("serial")) diff --git a/inst/serialportlist.m b/inst/serialportlist.m new file mode 100644 index 0000000..e8c8864 --- /dev/null +++ b/inst/serialportlist.m @@ -0,0 +1,64 @@ +## Copyright (C) 2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{list} = } serialportlist () +## @deftypefnx {Function File} {@var{list} = } serialportlist ("all") +## @deftypefnx {Function File} {@var{list} = } serialportlist ("available") +## Returns a list of all serial ports detected in the system. +## +## @subsubheading Inputs +## 'all' - show all serial ports (same as providing no arguments) +## 'available' - show only serial ports that are available for use +## +## @subsubheading Outputs +## @var{list} is a string cell array of serial ports names detected +## in the system. +## +## @seealso{instrhwinfo("serialport")} +## @end deftypefn + +function out = serialportlist (listtype) + + if nargin > 1 + print_usage (); + endif + + if nargin < 1 + listtype = "all"; + endif + + ports = instrhwinfo("serialport"); + + if strcmpi(listtype, "available") + tmp = {}; + for i=1:numel(ports) + try + portname = ports{i}; + s = serialport (portname, 9600); + clear s; + tmp{end+1} = portname; + catch err + # no nothing here + end_try_catch + endfor + out = tmp; + else + out = ports; + endif +endfunction + +%!assert(serialportlist, instrhwinfo("serialport")) +%!assert(serialportlist("all"), instrhwinfo("serialport")) diff --git a/inst/spoll.m b/inst/spoll.m new file mode 100644 index 0000000..422bd65 --- /dev/null +++ b/inst/spoll.m @@ -0,0 +1,65 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} spoll (@var{obj}) +## @deftypefnx {Function File} {[@var{out},@var{statusByte}] =} spoll (@var{obj}) +## Serial polls GPIB instruments. +## +## @var{obj} is a GPIB object or a cell array of GPIB objects +## +## @var{out} GPIB objects ready for service +## @var{statusByte} status Byte +## +## @end deftypefn + +## TODO: + +function [out,statusByte] = spoll (obj) +# + +if (nargin < 1) + print_usage (); +end + +if iscell (obj) && numel (obj) > 0 + if ~all (cellfun (@(x) isa (x,'octave_gpib'),obj)) + error ("obj contains wrong elements"); + end + + out = {}; + statusByte = []; + for i = 1:numel (obj) + tmp_status = uint8 (__gpib_spoll__ (obj{i})); + if (bitget (tmp_status,7) == 0) + out{end+1} = obj{i}; + statusByte(end+1) = tmp_status; + end + end + + return + +elseif (!isa (obj,'octave_gpib')) + error ('spoll: need octave_gpib object'); +end + +out = []; +statusByte = []; + +tmp_status = uint8 (__gpib_spoll__ (obj)); +if (bitget (tmp_status,7) == 0) + out = obj; + statusByte = tmp_status; +end diff --git a/inst/tcpip.m b/inst/tcpip.m new file mode 100644 index 0000000..2e4bba8 --- /dev/null +++ b/inst/tcpip.m @@ -0,0 +1,78 @@ +## Copyright (C) 2018-2019 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{tcp} = } tcpip (@var{host}, [@var{port}], [@var{PropertyName}, @var{PropertyValue}...]) +## Matlab compatible wrapper to the tcp interface. +## +## NOTE: tcpip has been depreciated. Use tcpclient instead +## +## @subsubheading Inputs +## @var{host} - the host name or ip.@* +## @var{port} - the port number to connect. If omitted defaults to 80.@* +## @var{PropertyName}, @var{PropertyValue} - Optional property name, value pairs to set on the tcp object.@* +## +## @subsubheading Properties +## Currently the only known properties are "timeout" and "name". +## +## @subsubheading Outputs +## tcpip will return an instance of @var{octave_tcp} class as the result. +## @end deftypefn + +function out = tcpip (varargin) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "tcpip is obsolete and will be removed from a future version of instrument-control, please use 'tcpclient' instead"); + endif + + if nargin == 0 || (nargin > 1 && !isnumeric(varargin{2})) + print_usage (); + endif + + host = varargin{1}; + + if nargin > 1 + port = varargin{2}; + else + port = 80; + endif + + if nargin > 2 + if mod(nargin, 2) != 0 + error ("tcpip: expected property name, value pairs"); + endif + if !iscellstr (varargin(3:2:nargin)) + error ("tcpip: expected property names to be strings"); + endif + endif + + out = tcp (resolvehost(host, "address"), port); + + for i = 3:2:nargin + propname = tolower(varargin{i}); + propvalue = varargin{i+1}; + + __tcp_properties__ (out, propname, propvalue); + endfor + +endfunction + +%!test +%! a = tcpip ("octave.org", 80); +%! assert(isa(a, "octave_tcp")); +%! fclose(a); diff --git a/inst/trigger.m b/inst/trigger.m new file mode 100644 index 0000000..46ebe76 --- /dev/null +++ b/inst/trigger.m @@ -0,0 +1,37 @@ +## Copyright (C) 2013 Stefan Mahr +## +## 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {} trigger (@var{obj}) +## Triggers GPIB instrument. +## +## @var{obj} is a GPIB object +## +## @end deftypefn + +## TODO: + +function trigger (obj) +# + +if (nargin < 1) + print_usage(); +end + +if (!isa (obj,'octave_gpib')) + error ('trigger: need octave_gpib object'); +end + +__gpib_trigger__ (obj); diff --git a/inst/udp_demo.m b/inst/udp_demo.m new file mode 100644 index 0000000..448c59c --- /dev/null +++ b/inst/udp_demo.m @@ -0,0 +1,87 @@ +## Copyright (C) 2016 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 . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{result} =} udp_demo () +## Run test SNTP demonstration for udp class +## +## @seealso{udp} +## @end deftypefn + +## Author: john donoghue +## Created: 2016-11-23 + +function result = udp_demo () + + result = false; + server = 'pool.ntp.org'; + + fprintf ('getting time from %s\n', server); + + # query time using SNTP + s = udp (server, 123); + + # send request packet + data = [uint8(0x1b) uint8(zeros (1,47))]; + res = udp_write (s, data); + + # recieve packet + data = udp_read (s,48, 4000); + + # should have 48 bytes reply + if length (data) == 48 + + # convert uint8s to integer32 + dataL = typecast (data, 'uint32'); + + # convert to little endian if we are on a little endian machine + if typecast (uint8([1 0]), 'uint16') == 1 + dataL = swapbytes (dataL); + endif + + # network time + ntimeval = dataL(11) - 2208988800; + # get system time + ltimeval = uint32 (time()); + + fprintf ('network time=%lu local time=%lu\n', ... + ntimeval, ltimeval); + + result = true; + endif + + fclose (s); +endfunction + +%!test +% assert(udp_demo) + +%!test +% s = udp('127.0.0.1', 80); +% assert(!isempty(s)); +% assert(get(s,'name'), 'UDP-127.0.0.1'); +% assert(get(s,'remoteport'), 80); +% assert(get(s,'remotehost','127.0.0.1'); +% assert(get(s,'localport')) +% set(s,'name', 'test'); +% assert(get(s,'name'), 'test'); +% udp_close(s); + +%!test +% s = udp('127.0.0.1', 80); +% assert(get(s,'status'), 'open'); +% fclose(s); +% assert(get(s,'status'), 'closed'); + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..fc8eebb --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,55 @@ + +SUBDIRS = serial parallel i2c spi usbtmc tcp tcpclient udp udpport gpib vxi11 resolvehost hwinfo serialport + +MKOCTFILE ?= mkoctfile +GREP ?= grep + +.PHONY: clean +.PHONY: realclean +.PHONY: distclean +.PHONY: $(SUBDIRS) +.PHONY: make-pkg-add_file + +all: $(SUBDIRS) make-pkg-add-file.cc + +$(SUBDIRS): + $(MAKE) -C $@ + +# pkg install doesnt look in subdirs of src to make pkgadd/del so we +# make a source file that it will see +CC_SOURCES = $(wildcard */*.cc) +make-pkg-add-file.cc: $(CC_SOURCES) + @echo "Generating pkg add/del $@ ..." + @( echo "// Generated file for PKG_ADD/DEL inclusion"; \ + $(GREP) -h '// PKG_' $^) > "$@" + + +CLEANDIRS = $(SUBDIRS:%=clean-%) +DISTCLEANDIRS = $(SUBDIRS:%=distclean-%) + +.PHONY: $(CLEANDIRS) +.PHONY: $(DISTCLEANDIRS) + +$(CLEANDIRS): + $(MAKE) -C $(@:clean-%=%) clean + +$(DISTCLEANDIRS): + $(MAKE) -C $(@:distclean-%=%) distclean + +clean: $(CLEANDIRS) + +realclean: + -rm -f *.oct + -rm -f make-pkg-add-file.cc: + +distclean: realclean $(DISTCLEANDIRS) + -rm -rf autom4te.cache + -rm -f Makefile config.status config.log config.h + +maintainer-clean: distclean + -rm -f configure + +# and prebuild stuff we need do +prebuild: + $(MAKE) -C vxi11 prebuild + diff --git a/src/aclocal.m4 b/src/aclocal.m4 new file mode 100644 index 0000000..04d16a4 --- /dev/null +++ b/src/aclocal.m4 @@ -0,0 +1,359 @@ +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- + +# Copyright (C) 1996-2018 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 11 (pkg-config-0.29.1) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + +m4_include([m4/octave-forge.m4]) diff --git a/src/bootstrap b/src/bootstrap new file mode 100755 index 0000000..f7dd283 --- /dev/null +++ b/src/bootstrap @@ -0,0 +1,9 @@ +#!/bin/bash +## Octave-Forge: video package bootstrap script +## Run this to generate the configure script + +set -e # halt if unhandled error +aclocal +autoconf # generate configure script +autoheader -f + diff --git a/src/common.mk b/src/common.mk new file mode 100644 index 0000000..b982440 --- /dev/null +++ b/src/common.mk @@ -0,0 +1,44 @@ +OCTAVE_CONFIG ?= octave-config +MKOCTFILE ?= mkoctfile +GREP ?= /usr/bin/grep + +all: $(OCT) archtests + + +ARCHDIR := "$(shell $(OCTAVE_CONFIG) -p CANONICAL_HOST_TYPE)-$(shell $(OCTAVE_CONFIG) -p API_VERSION)" +CC_SOURCES := $(wildcard *.cc) +CC_TST_SOURCES := $(shell $(GREP) --files-with-matches '^%!' $(CC_SOURCES)) +TST_SOURCES := $(patsubst %.cc,../../inst/$(ARCHDIR)/%.cc-tst,$(CC_TST_SOURCES)) + +$(TST_SOURCES): ../../inst/$(ARCHDIR)/%.cc-tst: %.cc | ../../inst/$(ARCHDIR) + @echo "Extracting tests from $< ..." + @$(RM) -f "$@" "$@-t" + @( echo "## Generated from $<"; \ + $(GREP) '^%!' "$<") > "$@" + +PHONY: archtests +archtests: $(TST_SOURCES) + +PHONY: cleanarchtests +cleanarchtests: + rm -f $(TST_SOURCES) + +../../inst/$(ARCHDIR): + @mkdir -p "$@" + +%.o: %.c + $(MKOCTFILE) $(CFLAGS) -c $^ + +%.o: %.cc + $(MKOCTFILE) $(CFLAGS) -c $^ + +%.oct: $(OBJ) + $(MKOCTFILE) $^ $(LFLAGS) $(TCPLIBS) -o $@ + +clean: cleanarchtests + rm -f $(OCT) *.o + +distclean: clean + rm Makefile + +.PHONY: all clean diff --git a/src/common.mk.in b/src/common.mk.in new file mode 100644 index 0000000..5031d7f --- /dev/null +++ b/src/common.mk.in @@ -0,0 +1,44 @@ +OCTAVE_CONFIG ?= octave-config +MKOCTFILE ?= mkoctfile +GREP ?= @GREP@ + +all: $(OCT) archtests + + +ARCHDIR := "$(shell $(OCTAVE_CONFIG) -p CANONICAL_HOST_TYPE)-$(shell $(OCTAVE_CONFIG) -p API_VERSION)" +CC_SOURCES := $(wildcard *.cc) +CC_TST_SOURCES := $(shell $(GREP) --files-with-matches '^%!' $(CC_SOURCES)) +TST_SOURCES := $(patsubst %.cc,../../inst/$(ARCHDIR)/%.cc-tst,$(CC_TST_SOURCES)) + +$(TST_SOURCES): ../../inst/$(ARCHDIR)/%.cc-tst: %.cc | ../../inst/$(ARCHDIR) + @echo "Extracting tests from $< ..." + @$(RM) -f "$@" "$@-t" + @( echo "## Generated from $<"; \ + $(GREP) '^%!' "$<") > "$@" + +PHONY: archtests +archtests: $(TST_SOURCES) + +PHONY: cleanarchtests +cleanarchtests: + rm -f $(TST_SOURCES) + +../../inst/$(ARCHDIR): + @mkdir -p "$@" + +%.o: %.c + $(MKOCTFILE) $(CFLAGS) -c $^ + +%.o: %.cc + $(MKOCTFILE) $(CFLAGS) -c $^ + +%.oct: $(OBJ) + $(MKOCTFILE) $^ $(LFLAGS) $(TCPLIBS) -o $@ + +clean: cleanarchtests + rm -f $(OCT) *.o + +distclean: clean + rm Makefile + +.PHONY: all clean diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..6f6efcd --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,158 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +#include "undef-ah-octave.h" + +/* build GPIB interface functions */ +#undef BUILD_GPIB + +/* build I2C interface functions */ +#undef BUILD_I2C + +/* build PARALLEL interface functions */ +#undef BUILD_PARALLEL + +/* build resolvehost function */ +#undef BUILD_RESOLVEHOST + +/* build SERIAL interface functions */ +#undef BUILD_SERIAL + +/* build SPI interface functions */ +#undef BUILD_SPI + +/* build TCP interface functions */ +#undef BUILD_TCP + +/* build UDP interface functions */ +#undef BUILD_UDP + +/* build USBTMC interface functions */ +#undef BUILD_USBTMC + +/* build VISA interface functions */ +#undef BUILD_VISA + +/* build VXI11 interface functions */ +#undef BUILD_VXI11 + +/* clnt allows const inputs */ +#undef CONST_CLNT_SUPPORT + +/* Define to 1 if you have the header file. */ +#undef HAVE_DEV_IICBUS_IIC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DEV_PPBUS_PPBCONF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DEV_PPBUS_PPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GPIB_IB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_I2C_DEV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_PARPORT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_PPDEV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SPI_SPIDEV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_INTERPRETER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_LO_SYSDEP_H + +/* Have for octave::sys::u8_to_wstring */ +#undef HAVE_OCTAVE_U8_TO_WSTRING + +/* Define to 1 if you have the header file. */ +#undef HAVE_RPC_RPC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_VISA_VISA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* macro for alternative Octave symbols */ +#undef OCTAVE__FEVAL + +/* Use new register_binary_op */ +#undef OCTAVE__NEW_REGISTER_OP + +/* macro for alternative Octave symbols */ +#undef OCTAVE__REGISTER_BINARY_OP + +/* macro for alternative Octave symbols */ +#undef OCTAVE__UNWIND_PROTECT + +/* macro for alternative Octave symbols */ +#undef OV_ISFLOAT + +/* macro for alternative Octave symbols */ +#undef OV_ISINTEGER + +/* macro for alternative Octave symbols */ +#undef OV_ISLOGICAL + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +#include "oct-alt-includes.h" diff --git a/src/configure b/src/configure new file mode 100755 index 0000000..c564bcd --- /dev/null +++ b/src/configure @@ -0,0 +1,5779 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for octave instrument control package 0.7.0. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='octave instrument control package' +PACKAGE_TARNAME='octave-instrument-control-package' +PACKAGE_VERSION='0.7.0' +PACKAGE_STRING='octave instrument control package 0.7.0' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +BUILD_VXI11 +VISALIBS +RPCGENOPTS +RPCGEN +RPCLIBS +RPCINCLUDE +TIRPC_LIBS +TIRPC_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +GPIBLIBS +TCPLIBS +EGREP +CXXCPP +BUILD_FOR_WINDOWS +GREP +OCTAVE_CONFIG +MKOCTFILE +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_librpc +' + ac_precious_vars='build_alias +host_alias +target_alias +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CXXCPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +TIRPC_CFLAGS +TIRPC_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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.7.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root + [DATAROOTDIR/doc/octave-instrument-control-package] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of octave instrument control package 0.7.0:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-librpc=tirpc|sunrpc|auto|none + Choose use/selection of librpc used + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + TIRPC_CFLAGS + C compiler flags for TIRPC, overriding pkg-config + TIRPC_LIBS linker flags for TIRPC, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +octave instrument control package configure 0.7.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link +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.7.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers config.h" + + +# Avoid warnings for redefining AH-generated preprocessor symbols of +# Octave. + + + + +# Checks for programs. +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +# Define macros needed +#AC_DEFINE(__STDC_CONSTANT_MACROS, [], [workaround for C++ programs to use C99 macros]) + +# Extract the first word of "mkoctfile", so it can be a program name with args. +set dummy mkoctfile; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MKOCTFILE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MKOCTFILE"; then + ac_cv_prog_MKOCTFILE="$MKOCTFILE" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MKOCTFILE="mkoctfile" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_MKOCTFILE" && ac_cv_prog_MKOCTFILE="none" +fi +fi +MKOCTFILE=$ac_cv_prog_MKOCTFILE +if test -n "$MKOCTFILE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKOCTFILE" >&5 +$as_echo "$MKOCTFILE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "$MKOCTFILE" = "none"; then + as_fn_error $? "mkoctfile required to install $PACKAGE_NAME" "$LINENO" 5 +fi + +# Extract the first word of "octave-config", so it can be a program name with args. +set dummy octave-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OCTAVE_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OCTAVE_CONFIG"; then + ac_cv_prog_OCTAVE_CONFIG="$OCTAVE_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OCTAVE_CONFIG="octave-config" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OCTAVE_CONFIG=$ac_cv_prog_OCTAVE_CONFIG +if test -n "$OCTAVE_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCTAVE_CONFIG" >&5 +$as_echo "$OCTAVE_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +test -z "$OCTAVE_CONFIG" && OCTAVE_CONFIG=$MKOCTFILE + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + + +## Simple symbol alternatives of different Octave versions. +save_altsyms_CXX="$CXX" +save_altsyms_CXXFLAGS="$CXXFLAGS" +save_altsyms_LDFLAGS="$LDFLAGS" +save_altsyms_LIBS="$LIBS" +OCTINCLUDEDIR=${OCTINCLUDEDIR:-`$MKOCTFILE -p INCFLAGS`} +OCTLIBDIR=${OCTLIBDIR:-`$MKOCTFILE -p OCTLIBDIR`} +CXX=`${MKOCTFILE} -p CXX` +CXXFLAGS="$OCTINCLUDEDIR $CXXFLAGS" +LDFLAGS="-L$OCTLIBDIR $LDFLAGS" +LIBS="-loctinterp $LIBS" + +# includes + +for ac_header in octave/interpreter.h +do : + ac_fn_cxx_check_header_compile "$LINENO" "octave/interpreter.h" "ac_cv_header_octave_interpreter_h" "#include + +" +if test "x$ac_cv_header_octave_interpreter_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_INTERPRETER_H 1 +_ACEOF + +fi + +done + + +for ac_header in octave/lo-sysdep.h +do : + ac_fn_cxx_check_header_compile "$LINENO" "octave/lo-sysdep.h" "ac_cv_header_octave_lo_sysdep_h" "#include + +" +if test "x$ac_cv_header_octave_lo_sysdep_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_LO_SYSDEP_H 1 +_ACEOF + +fi + +done + + + + +echo '/* generated by configure */' > oct-alt-includes.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking feval or octave::feval" >&5 +$as_echo_n "checking feval or octave::feval... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +octave::feval ("date"); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__FEVAL octave::feval" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::feval" >&5 +$as_echo "octave::feval" >&6; } + echo '#include +' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__FEVAL="octave::feval" +else + +$as_echo "#define OCTAVE__FEVAL feval" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: feval" >&5 +$as_echo " feval" >&6; } + echo '#include ' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__FEVAL=" feval" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_float_type or isfloat" >&5 +$as_echo_n "checking is_float_type or isfloat... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().isfloat (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISFLOAT isfloat" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: isfloat" >&5 +$as_echo "isfloat" >&6; } + echo ' +' >> oct-alt-includes.h + ac_cv_octsym_OV_ISFLOAT="isfloat" +else + +$as_echo "#define OV_ISFLOAT is_float_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_float_type" >&5 +$as_echo " is_float_type" >&6; } + echo '' >> oct-alt-includes.h + ac_cv_octsym_OV_ISFLOAT=" is_float_type" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_integer_type or isinteger" >&5 +$as_echo_n "checking is_integer_type or isinteger... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().isinteger (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISINTEGER isinteger" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: isinteger" >&5 +$as_echo "isinteger" >&6; } + echo ' +' >> oct-alt-includes.h + ac_cv_octsym_OV_ISINTEGER="isinteger" +else + +$as_echo "#define OV_ISINTEGER is_integer_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_integer_type" >&5 +$as_echo " is_integer_type" >&6; } + echo '' >> oct-alt-includes.h + ac_cv_octsym_OV_ISINTEGER=" is_integer_type" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_bool_type or islogical" >&5 +$as_echo_n "checking is_bool_type or islogical... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().islogical (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISLOGICAL islogical" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: islogical" >&5 +$as_echo "islogical" >&6; } + echo ' +' >> oct-alt-includes.h + ac_cv_octsym_OV_ISLOGICAL="islogical" +else + +$as_echo "#define OV_ISLOGICAL is_bool_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_bool_type" >&5 +$as_echo " is_bool_type" >&6; } + echo '' >> oct-alt-includes.h + ac_cv_octsym_OV_ISLOGICAL=" is_bool_type" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking unwind_protect or octave::unwind_protect" >&5 +$as_echo_n "checking unwind_protect or octave::unwind_protect... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + #include + + +int +main () +{ +octave::unwind_protect frame; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__UNWIND_PROTECT octave::unwind_protect" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::unwind_protect" >&5 +$as_echo "octave::unwind_protect" >&6; } + echo '#include + #include + +' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__UNWIND_PROTECT="octave::unwind_protect" +else + +$as_echo "#define OCTAVE__UNWIND_PROTECT unwind_protect" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unwind_protect" >&5 +$as_echo " unwind_protect" >&6; } + echo '#include + #include + ' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__UNWIND_PROTECT=" unwind_protect" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking octave_value_typeinfo::register_binary_op or octave::type_info::register_binary_op" >&5 +$as_echo_n "checking octave_value_typeinfo::register_binary_op or octave::type_info::register_binary_op... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + #include + #include + + + + +int +main () +{ + + octave::type_info& ti = octave::interpreter::the_interpreter ()->get_type_info (); + ti.register_binary_op(octave_value::op_eq, 1,1,0); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__REGISTER_BINARY_OP octave::type_info::register_binary_op" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::type_info::register_binary_op" >&5 +$as_echo "octave::type_info::register_binary_op" >&6; } + echo ' + #include + #include + + + +' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__REGISTER_BINARY_OP="octave::type_info::register_binary_op" +else + +$as_echo "#define OCTAVE__REGISTER_BINARY_OP octave_value_typeinfo::register_binary_op" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave_value_typeinfo::register_binary_op" >&5 +$as_echo " octave_value_typeinfo::register_binary_op" >&6; } + echo '#include ' >> oct-alt-includes.h + ac_cv_octsym_OCTAVE__REGISTER_BINARY_OP=" octave_value_typeinfo::register_binary_op" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + + + + +if test $ac_cv_octsym_OCTAVE__REGISTER_BINARY_OP == "octave::type_info::register_binary_op"; then + +$as_echo "#define OCTAVE__NEW_REGISTER_OP /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for octave::sys::u8_to_wstring" >&5 +$as_echo_n "checking for octave::sys::u8_to_wstring... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + #include + + +int +main () +{ + + std::wstring s = octave::sys::u8_to_wstring("test"); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_OCTAVE_U8_TO_WSTRING 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +CXX=$save_altsyms_CXX +CXXFLAGS=$save_altsyms_CXXFLAGS +LDFLAGS=$save_altsyms_LDFLAGS +LIBS=$save_altsyms_LIBS + +build_parallel=no +build_serial=no +build_i2c=no +build_spi=no +build_usbtmc=no +build_tcp=no +build_udp=no +build_gpib=no +build_vxi11=no +build_visa=no +build_resolvehost=no + +# Check for Windows +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for windows" >&5 +$as_echo_n "checking for windows... " >&6; } +have_windows=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #ifndef __WIN32__ + #error "Not windows!" + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_windows=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# if windows, we can build some of the packages just by having +# windows.h +if test $have_windows = yes; then + build_serial=yes + BUILD_FOR_WINDOWS=1 + +fi + +# check for i2c +# if linux/i2c-dev.h exists we are probably under linux, so build usbtmc as well +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in linux/i2c-dev.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "linux/i2c-dev.h" "ac_cv_header_linux_i2c_dev_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_i2c_dev_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_I2C_DEV_H 1 +_ACEOF + build_i2c=yes build_usbtmc=yes +fi + +done + +for ac_header in dev/iicbus/iic.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "dev/iicbus/iic.h" "ac_cv_header_dev_iicbus_iic_h" "$ac_includes_default" +if test "x$ac_cv_header_dev_iicbus_iic_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DEV_IICBUS_IIC_H 1 +_ACEOF + build_i2c=yes +fi + +done + + +# check for spi +for ac_header in linux/spi/spidev.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "linux/spi/spidev.h" "ac_cv_header_linux_spi_spidev_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_spi_spidev_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_SPI_SPIDEV_H 1 +_ACEOF + build_spi=yes +fi + +done + + +# check for serial +for ac_header in termios.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default" +if test "x$ac_cv_header_termios_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TERMIOS_H 1 +_ACEOF + build_serial=yes +fi + +done + + +# check for parallel +for ac_header in linux/parport.h linux/ppdev.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + build_parallel=yes +fi + +done + +for ac_header in dev/ppbus/ppi.h dev/ppbus/ppbconf.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + build_parallel=yes +fi + +done + + +# build tcp, available for most platforms +for ac_header in sys/socket.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_socket_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SOCKET_H 1 +_ACEOF + build_tcp=yes +fi + +done + + +# Check for winsock2 and ws2_32 +have_winsock2=no +for ac_header in winsock2.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" +if test "x$ac_cv_header_winsock2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINSOCK2_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing _head_libws2_32_a" >&5 +$as_echo_n "checking for library containing _head_libws2_32_a... " >&6; } +if ${ac_cv_search__head_libws2_32_a+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _head_libws2_32_a (); +int +main () +{ +return _head_libws2_32_a (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ws2_32; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search__head_libws2_32_a=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search__head_libws2_32_a+:} false; then : + break +fi +done +if ${ac_cv_search__head_libws2_32_a+:} false; then : + +else + ac_cv_search__head_libws2_32_a=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search__head_libws2_32_a" >&5 +$as_echo "$ac_cv_search__head_libws2_32_a" >&6; } +ac_res=$ac_cv_search__head_libws2_32_a +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_winsock2=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing _head_lib32_libws2_32_a" >&5 +$as_echo_n "checking for library containing _head_lib32_libws2_32_a... " >&6; } +if ${ac_cv_search__head_lib32_libws2_32_a+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _head_lib32_libws2_32_a (); +int +main () +{ +return _head_lib32_libws2_32_a (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ws2_32; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search__head_lib32_libws2_32_a=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search__head_lib32_libws2_32_a+:} false; then : + break +fi +done +if ${ac_cv_search__head_lib32_libws2_32_a+:} false; then : + +else + ac_cv_search__head_lib32_libws2_32_a=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search__head_lib32_libws2_32_a" >&5 +$as_echo "$ac_cv_search__head_lib32_libws2_32_a" >&6; } +ac_res=$ac_cv_search__head_lib32_libws2_32_a +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_winsock2=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing _head_lib64_libws2_32_a" >&5 +$as_echo_n "checking for library containing _head_lib64_libws2_32_a... " >&6; } +if ${ac_cv_search__head_lib64_libws2_32_a+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _head_lib64_libws2_32_a (); +int +main () +{ +return _head_lib64_libws2_32_a (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ws2_32; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search__head_lib64_libws2_32_a=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search__head_lib64_libws2_32_a+:} false; then : + break +fi +done +if ${ac_cv_search__head_lib64_libws2_32_a+:} false; then : + +else + ac_cv_search__head_lib64_libws2_32_a=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search__head_lib64_libws2_32_a" >&5 +$as_echo "$ac_cv_search__head_lib64_libws2_32_a" >&6; } +ac_res=$ac_cv_search__head_lib64_libws2_32_a +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_winsock2=yes +fi + + +fi + +done + + +if test $have_winsock2 = yes; then + TCPLIBS="-lws2_32" + + build_tcp=yes + build_resolvehost=yes +fi + +# if can build tcp, can build udp +if test $build_tcp = yes; then + build_udp=yes +fi + +# checks for resolve host +if test $build_tcp = yes; then + if test $build_resolvehost = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getnameinfo" >&5 +$as_echo_n "checking for library containing getnameinfo... " >&6; } +if ${ac_cv_search_getnameinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getnameinfo (); +int +main () +{ +return getnameinfo (); + ; + return 0; +} +_ACEOF +for ac_lib in '' inet6 socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_getnameinfo=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getnameinfo+:} false; then : + break +fi +done +if ${ac_cv_search_getnameinfo+:} false; then : + +else + ac_cv_search_getnameinfo=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getnameinfo" >&5 +$as_echo "$ac_cv_search_getnameinfo" >&6; } +ac_res=$ac_cv_search_getnameinfo +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + build_resolvehost=yes +fi + + if test "x$ac_cv_search_getnameinfo" != "xno"; then + test "x$ac_cv_search_getnameinfo" = "xnone required" || TCPLIBS=$ac_cv_search_getnameinfo + + fi + fi +fi + +# Checks for GPIB +for ac_header in gpib/ib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "gpib/ib.h" "ac_cv_header_gpib_ib_h" "$ac_includes_default" +if test "x$ac_cv_header_gpib_ib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GPIB_IB_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ibrd" >&5 +$as_echo_n "checking for library containing ibrd... " >&6; } +if ${ac_cv_search_ibrd+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ibrd (); +int +main () +{ +return ibrd (); + ; + return 0; +} +_ACEOF +for ac_lib in '' gpib; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_ibrd=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_ibrd+:} false; then : + break +fi +done +if ${ac_cv_search_ibrd+:} false; then : + +else + ac_cv_search_ibrd=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ibrd" >&5 +$as_echo "$ac_cv_search_ibrd" >&6; } +ac_res=$ac_cv_search_ibrd +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + build_gpib=yes +fi + +fi + +done + + +if test "x$ac_cv_search_ibrd" != "xno"; then + test "x$ac_cv_search_ibrd" = "xnone required" || GPIBLIBS=$ac_cv_search_ibrd + +fi + + +# Checks for RPC/VXI11 + +# Check whether --with-librpc was given. +if test "${with_librpc+set}" = set; then : + withval=$with_librpc; with_libtirpc="$with_librpc" +else + with_librpc="auto" +fi + + +if test "x${with_librpc}" = "xyes"; then + with_librpc="auto" +fi +if test "x${with_librpc}" = "xno"; then + with_librpc="none" +fi + +if test "x${with_librpc}" = "xauto" || test "x${with_librpc}" = "xtirpc"; then + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIRPC" >&5 +$as_echo_n "checking for TIRPC... " >&6; } + +if test -n "$TIRPC_CFLAGS"; then + pkg_cv_TIRPC_CFLAGS="$TIRPC_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtirpc\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libtirpc") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TIRPC_CFLAGS=`$PKG_CONFIG --cflags "libtirpc" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$TIRPC_LIBS"; then + pkg_cv_TIRPC_LIBS="$TIRPC_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtirpc\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libtirpc") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TIRPC_LIBS=`$PKG_CONFIG --libs "libtirpc" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + TIRPC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtirpc" 2>&1` + else + TIRPC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtirpc" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$TIRPC_PKG_ERRORS" >&5 + + RPCINCLUDE="$RPCINCLUDE" +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + RPCINCLUDE="$RPCINCLUDE" +else + TIRPC_CFLAGS=$pkg_cv_TIRPC_CFLAGS + TIRPC_LIBS=$pkg_cv_TIRPC_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + with_librpc="yes"; build_vxi11=yes; RPCINCLUDE="$RPCINCLUDE $TIRPC_CFLAGS"; RPCLIBS="$RPCLIBS $TIRPC_LIBS"; +fi +fi + +if test "x${with_librpc}" = "xauto" || test "x${with_librpc}" = "xsunrpc"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clnt_create" >&5 +$as_echo_n "checking for library containing clnt_create... " >&6; } +if ${ac_cv_search_clnt_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clnt_create (); +int +main () +{ +return clnt_create (); + ; + return 0; +} +_ACEOF +for ac_lib in '' tirpc; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_clnt_create=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clnt_create+:} false; then : + break +fi +done +if ${ac_cv_search_clnt_create+:} false; then : + +else + ac_cv_search_clnt_create=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clnt_create" >&5 +$as_echo "$ac_cv_search_clnt_create" >&6; } +ac_res=$ac_cv_search_clnt_create +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + with_librpc="yes" +fi + + if test "x$ac_cv_search_clnt_create" != "xnone required"; then + RPCLIBS="$RPCLIBS $ac_cv_search_clnt_create" + fi + for ac_header in rpc/rpc.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "rpc/rpc.h" "ac_cv_header_rpc_rpc_h" "$ac_includes_default" +if test "x$ac_cv_header_rpc_rpc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_RPC_RPC_H 1 +_ACEOF + RPCINCLUDE="$RPC_CFLAGS" +else + with_librpc="no"; build_vxi11=no +fi + +done + +fi +if test "x${with_librpc}" = "xauto"; then + with_librpc="none" +fi + + + + +# with_librpc should now be yes, if found +# none if was never wanted or not auto detected + +if test "x${with_librpc}" != "xyes" && test "x${with_librpc}" != "xnone"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Did not find valid rpc libraries - disabling vxi11 interface" >&5 +$as_echo "$as_me: Did not find valid rpc libraries - disabling vxi11 interface" >&6;} +fi + +if test "x${with_librpc}" = "xyes"; then + build_vxi11=yes + + # we support const input into clnt_create ? + { $as_echo "$as_me:${as_lineno-$LINENO}: checking const input allowed into clnt_perror" >&5 +$as_echo_n "checking const input allowed into clnt_perror... " >&6; } + const_clnt_perror=no + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + save_LIBS=$LIBS + save_CPPFLAGS=$CPPFLAGS + LIBS=$RPCLIBS + CPPFLAGS=$RPCINCLUDE + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + +int +main () +{ + + const char * msg = "const message"; + CLIENT *clnt = 0; + clnt_perror(clnt, msg); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + const_clnt_perror=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + LIBS=$save_LIBS= + CPPFLAGS=$save_CPPFLAGS + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + if test $const_clnt_perror = yes; then + +$as_echo "#define CONST_CLNT_SUPPORT 1" >>confdefs.h + + fi +fi + +# we have rpcgen ? +for ac_prog in rpcgen rpcgen-mt +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RPCGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RPCGEN"; then + ac_cv_prog_RPCGEN="$RPCGEN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RPCGEN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RPCGEN=$ac_cv_prog_RPCGEN +if test -n "$RPCGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPCGEN" >&5 +$as_echo "$RPCGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$RPCGEN" && break +done +test -n "$RPCGEN" || RPCGEN="none" + + +if test "xRPCGEN" = "xnone"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No rpcgen found - if rpc sources are modified, the build will fail" >&5 +$as_echo "$as_me: WARNING: No rpcgen found - if rpc sources are modified, the build will fail" >&2;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${RPCGEN} accepts -M option" >&5 +$as_echo_n "checking whether ${RPCGEN} accepts -M option... " >&6; } + rm -f rpcgen_test.* +cat > rpcgen_test.x < /dev/null 2>&1 + if test -f rpcgen_test.h; then + _rpcgen_result=yes + RPCGENOPTS="-M" + else + _rpcgen_result=no + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_rpcgen_result" >&5 +$as_echo "$_rpcgen_result" >&6; } + RPCGENOPTS=$RPCGENOPTS + + rm -f rpcgen_test.* + rm -f rpcgen_test_* +fi + +# Checks for openvisa +for ac_header in visa/visa.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "visa/visa.h" "ac_cv_header_visa_visa_h" "$ac_includes_default" +if test "x$ac_cv_header_visa_visa_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VISA_VISA_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing viOpenDefaultRM" >&5 +$as_echo_n "checking for library containing viOpenDefaultRM... " >&6; } +if ${ac_cv_search_viOpenDefaultRM+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char viOpenDefaultRM (); +int +main () +{ +return viOpenDefaultRM (); + ; + return 0; +} +_ACEOF +for ac_lib in '' openvisa; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_viOpenDefaultRM=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_viOpenDefaultRM+:} false; then : + break +fi +done +if ${ac_cv_search_viOpenDefaultRM+:} false; then : + +else + ac_cv_search_viOpenDefaultRM=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_viOpenDefaultRM" >&5 +$as_echo "$ac_cv_search_viOpenDefaultRM" >&6; } +ac_res=$ac_cv_search_viOpenDefaultRM +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + build_visa=yes +fi + +fi + +done + + +if test "x$ac_cv_search_viOpenDefaultRM" != "xno"; then + test "x$ac_cv_search_viOpenDefaultRM" = "xnone required" || VISALIBS=$ac_cv_search_viOpenDefaultRM + +fi + +# + +if test $build_parallel = yes; then + +$as_echo "#define BUILD_PARALLEL /**/" >>confdefs.h + +fi + +if test $build_serial = yes; then + +$as_echo "#define BUILD_SERIAL /**/" >>confdefs.h + +fi + +if test $build_i2c = yes; then + +$as_echo "#define BUILD_I2C /**/" >>confdefs.h + +fi + +if test $build_spi = yes; then + +$as_echo "#define BUILD_SPI /**/" >>confdefs.h + +fi + +if test $build_usbtmc = yes; then + +$as_echo "#define BUILD_USBTMC /**/" >>confdefs.h + +fi + +if test $build_tcp = yes; then + +$as_echo "#define BUILD_TCP /**/" >>confdefs.h + +fi + +if test $build_udp = yes; then + +$as_echo "#define BUILD_UDP /**/" >>confdefs.h + +fi + +if test $build_gpib = yes; then + +$as_echo "#define BUILD_GPIB /**/" >>confdefs.h + +fi + +if test $build_vxi11 = yes; then + +$as_echo "#define BUILD_VXI11 /**/" >>confdefs.h + + BUILD_VXI11=1 + +fi + +if test $build_visa = yes; then + +$as_echo "#define BUILD_VISA /**/" >>confdefs.h + +fi + +if test $build_resolvehost = yes; then + +$as_echo "#define BUILD_RESOLVEHOST /**/" >>confdefs.h + +fi + + +# all done + +ac_config_files="$ac_config_files common.mk Makefile gpib/Makefile tcp/Makefile tcpclient/Makefile udp/Makefile udpport/Makefile vxi11/Makefile usbtmc/Makefile spi/Makefile serial/Makefile parallel/Makefile i2c/Makefile resolvehost/Makefile hwinfo/Makefile serialport/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# 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.7.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +octave instrument control package config.status 0.7.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "common.mk") CONFIG_FILES="$CONFIG_FILES common.mk" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "gpib/Makefile") CONFIG_FILES="$CONFIG_FILES gpib/Makefile" ;; + "tcp/Makefile") CONFIG_FILES="$CONFIG_FILES tcp/Makefile" ;; + "tcpclient/Makefile") CONFIG_FILES="$CONFIG_FILES tcpclient/Makefile" ;; + "udp/Makefile") CONFIG_FILES="$CONFIG_FILES udp/Makefile" ;; + "udpport/Makefile") CONFIG_FILES="$CONFIG_FILES udpport/Makefile" ;; + "vxi11/Makefile") CONFIG_FILES="$CONFIG_FILES vxi11/Makefile" ;; + "usbtmc/Makefile") CONFIG_FILES="$CONFIG_FILES usbtmc/Makefile" ;; + "spi/Makefile") CONFIG_FILES="$CONFIG_FILES spi/Makefile" ;; + "serial/Makefile") CONFIG_FILES="$CONFIG_FILES serial/Makefile" ;; + "parallel/Makefile") CONFIG_FILES="$CONFIG_FILES parallel/Makefile" ;; + "i2c/Makefile") CONFIG_FILES="$CONFIG_FILES i2c/Makefile" ;; + "resolvehost/Makefile") CONFIG_FILES="$CONFIG_FILES resolvehost/Makefile" ;; + "hwinfo/Makefile") CONFIG_FILES="$CONFIG_FILES hwinfo/Makefile" ;; + "serialport/Makefile") CONFIG_FILES="$CONFIG_FILES serialport/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: + +$PACKAGE_NAME is now configured with + + BUILD SERIAL: $build_serial + BUILD PARALLEL: $build_parallel + BUILD I2C: $build_i2c + BUILD SPI: $build_spi + BUILD TCP: $build_tcp + BUILD UDP: $build_udp + BUILD USBTMC: $build_usbtmc + BUILD GPIB: $build_gpib + BUILD VXI11: $build_vxi11 + BUILD RESOLVEHOST: $build_resolvehost + + GPIB LIBS: $GPIBLIBS + VXI11 LIBS: $RPCLIBS + VXI11 INCLUDE: $RPCINCLUDE + VISA LIBS: $VISALIBS + TCP LIBS: $TCPLIBS + +" >&5 +$as_echo "$as_me: + +$PACKAGE_NAME is now configured with + + BUILD SERIAL: $build_serial + BUILD PARALLEL: $build_parallel + BUILD I2C: $build_i2c + BUILD SPI: $build_spi + BUILD TCP: $build_tcp + BUILD UDP: $build_udp + BUILD USBTMC: $build_usbtmc + BUILD GPIB: $build_gpib + BUILD VXI11: $build_vxi11 + BUILD RESOLVEHOST: $build_resolvehost + + GPIB LIBS: $GPIBLIBS + VXI11 LIBS: $RPCLIBS + VXI11 INCLUDE: $RPCINCLUDE + VISA LIBS: $VISALIBS + TCP LIBS: $TCPLIBS + +" >&6;} diff --git a/src/configure.ac b/src/configure.ac new file mode 100644 index 0000000..7b7180d --- /dev/null +++ b/src/configure.ac @@ -0,0 +1,439 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +# +### Copyright (C) 2020-2021 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 +### . + +AC_PREREQ([2.67]) +AC_INIT([octave instrument control package], [0.7.0]) +AC_CONFIG_HEADERS([config.h]) + +# Avoid warnings for redefining AH-generated preprocessor symbols of +# Octave. +AH_TOP([#include "undef-ah-octave.h"]) + +AC_CONFIG_MACRO_DIRS([m4]) + +# Checks for programs. +AC_PROG_CXX +AC_LANG(C++) + +# Define macros needed +#AC_DEFINE(__STDC_CONSTANT_MACROS, [], [workaround for C++ programs to use C99 macros]) + +AC_CHECK_PROG([MKOCTFILE], [mkoctfile], [mkoctfile], [none]) +if [test "$MKOCTFILE" = "none"]; then + AC_MSG_ERROR([mkoctfile required to install $PACKAGE_NAME]) +fi + +AC_CHECK_PROG(OCTAVE_CONFIG,octave-config,octave-config) +test -z "$OCTAVE_CONFIG" && OCTAVE_CONFIG=$MKOCTFILE + +AC_PROG_GREP + +## Simple symbol alternatives of different Octave versions. +save_altsyms_CXX="$CXX" +save_altsyms_CXXFLAGS="$CXXFLAGS" +save_altsyms_LDFLAGS="$LDFLAGS" +save_altsyms_LIBS="$LIBS" +OCTINCLUDEDIR=${OCTINCLUDEDIR:-`$MKOCTFILE -p INCFLAGS`} +OCTLIBDIR=${OCTLIBDIR:-`$MKOCTFILE -p OCTLIBDIR`} +CXX=`${MKOCTFILE} -p CXX` +CXXFLAGS="$OCTINCLUDEDIR $CXXFLAGS" +LDFLAGS="-L$OCTLIBDIR $LDFLAGS" +LIBS="-loctinterp $LIBS" + +# includes +AC_CHECK_HEADERS([octave/interpreter.h], + [], + [], + [#include ] +) + +AC_CHECK_HEADERS([octave/lo-sysdep.h], + [], + [], + [#include ] +) + +OF_OCTAVE_LIST_ALT_SYMS([ +[dnl + [feval], + [octave::feval], + [[octave::feval ("date");]], + [OCTAVE__FEVAL], + [[#include ]], + [[#include ]] +], + +[dnl + [is_float_type], + [isfloat], + [[octave_value ().isfloat ();]], + [OV_ISFLOAT], + [], + [] +], + +[dnl + [is_integer_type], + [isinteger], + [[octave_value ().isinteger ();]], + [OV_ISINTEGER], + [], + [] +], + +[dnl + [is_bool_type], + [islogical], + [[octave_value ().islogical ();]], + [OV_ISLOGICAL], + [], + [] +], + +[dnl + [unwind_protect], + [octave::unwind_protect], + [[octave::unwind_protect frame;]], + [OCTAVE__UNWIND_PROTECT], + [[#include ] + [#include ] + ], + [[#include ] + [#include ] + ] +], + +[dnl + [octave_value_typeinfo::register_binary_op], + [octave::type_info::register_binary_op], + [ + [octave::type_info& ti = octave::interpreter::the_interpreter ()->get_type_info ();] + [ti.register_binary_op(octave_value::op_eq, 1,1,0);] + ], + [OCTAVE__REGISTER_BINARY_OP], + [[#include ]], + [ + [#include ] + [#include ] + ] +] + +],[oct-alt-includes.h]) + +if test $ac_cv_octsym_OCTAVE__REGISTER_BINARY_OP == "octave::type_info::register_binary_op"; then + AC_DEFINE([OCTAVE__NEW_REGISTER_OP], [], [Use new register_binary_op]) +fi + +OF_OCTAVE_CHECK_SYM( + [for octave::sys::u8_to_wstring], + [ + std::wstring s = octave::sys::u8_to_wstring("test"); + ], + [HAVE_OCTAVE_U8_TO_WSTRING], + [ + #include + ] +) + +CXX=$save_altsyms_CXX +CXXFLAGS=$save_altsyms_CXXFLAGS +LDFLAGS=$save_altsyms_LDFLAGS +LIBS=$save_altsyms_LIBS + +build_parallel=no +build_serial=no +build_i2c=no +build_spi=no +build_usbtmc=no +build_tcp=no +build_udp=no +build_gpib=no +build_vxi11=no +build_visa=no +build_resolvehost=no + +# Check for Windows +AC_MSG_CHECKING([for windows]) +have_windows=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #ifndef __WIN32__ + #error "Not windows!" + #endif + ]], [])], + [AC_MSG_RESULT([yes]) + have_windows=yes], + [AC_MSG_RESULT([no])]) + +# if windows, we can build some of the packages just by having +# windows.h +if test $have_windows = yes; then + build_serial=yes + AC_SUBST([BUILD_FOR_WINDOWS], [1], [build using native windows functions]) +fi + +# check for i2c +# if linux/i2c-dev.h exists we are probably under linux, so build usbtmc as well +AC_CHECK_HEADERS([linux/i2c-dev.h],[build_i2c=yes build_usbtmc=yes]) +AC_CHECK_HEADERS([dev/iicbus/iic.h],[build_i2c=yes]) + +# check for spi +AC_CHECK_HEADERS([linux/spi/spidev.h],[build_spi=yes]) + +# check for serial +AC_CHECK_HEADERS([termios.h],[build_serial=yes]) + +# check for parallel +AC_CHECK_HEADERS([linux/parport.h linux/ppdev.h],[build_parallel=yes]) +AC_CHECK_HEADERS([dev/ppbus/ppi.h dev/ppbus/ppbconf.h],[build_parallel=yes]) + +# build tcp, available for most platforms +AC_CHECK_HEADERS([sys/socket.h],[build_tcp=yes]) + +# Check for winsock2 and ws2_32 +have_winsock2=no +AC_CHECK_HEADERS([winsock2.h], + [AC_SEARCH_LIBS([_head_libws2_32_a], [ws2_32], + [have_winsock2=yes] , [] ) + AC_SEARCH_LIBS([_head_lib32_libws2_32_a], [ws2_32], + [have_winsock2=yes] , [] ) + AC_SEARCH_LIBS([_head_lib64_libws2_32_a], [ws2_32], + [have_winsock2=yes] , [] ) + ], []) + +if test $have_winsock2 = yes; then + AC_SUBST(TCPLIBS, ["-lws2_32"]) + build_tcp=yes + build_resolvehost=yes +fi + +# if can build tcp, can build udp +if test $build_tcp = yes; then + build_udp=yes +fi + +# checks for resolve host +if test $build_tcp = yes; then + if test $build_resolvehost = no; then + AC_SEARCH_LIBS(getnameinfo, [inet6 socket], [build_resolvehost=yes]) + if test "x$ac_cv_search_getnameinfo" != "xno"; then + test "x$ac_cv_search_getnameinfo" = "xnone required" || AC_SUBST(TCPLIBS, [$ac_cv_search_getnameinfo]) + fi + fi +fi + +# Checks for GPIB +AC_CHECK_HEADERS([gpib/ib.h], + [AC_SEARCH_LIBS([ibrd], [gpib], [build_gpib=yes], [])] , [] ) + +if test "x$ac_cv_search_ibrd" != "xno"; then + test "x$ac_cv_search_ibrd" = "xnone required" || AC_SUBST(GPIBLIBS, [$ac_cv_search_ibrd]) +fi + + +# Checks for RPC/VXI11 +AC_ARG_WITH([librpc], + [AC_HELP_STRING([--with-librpc=tirpc|sunrpc|auto|none], [Choose use/selection of librpc used])], + [with_libtirpc="$with_librpc"], [with_librpc="auto"]) + +if test "x${with_librpc}" = "xyes"; then + with_librpc="auto" +fi +if test "x${with_librpc}" = "xno"; then + with_librpc="none" +fi + +if test "x${with_librpc}" = "xauto" || test "x${with_librpc}" = "xtirpc"; then + PKG_CHECK_MODULES([TIRPC], [libtirpc], + [with_librpc="yes"; build_vxi11=yes; RPCINCLUDE="$RPCINCLUDE $TIRPC_CFLAGS"; RPCLIBS="$RPCLIBS $TIRPC_LIBS";], + [RPCINCLUDE="$RPCINCLUDE"]) +fi + +if test "x${with_librpc}" = "xauto" || test "x${with_librpc}" = "xsunrpc"; then + AC_SEARCH_LIBS([clnt_create], [tirpc], + [with_librpc="yes"], + []) + if test "x$ac_cv_search_clnt_create" != "xnone required"; then + RPCLIBS="$RPCLIBS $ac_cv_search_clnt_create" + fi + AC_CHECK_HEADERS([rpc/rpc.h],[RPCINCLUDE="$RPC_CFLAGS"],[with_librpc="no"; build_vxi11=no]) +fi +if test "x${with_librpc}" = "xauto"; then + with_librpc="none" +fi + +AC_SUBST(RPCINCLUDE) +AC_SUBST(RPCLIBS) + +# with_librpc should now be yes, if found +# none if was never wanted or not auto detected + +if test "x${with_librpc}" != "xyes" && test "x${with_librpc}" != "xnone"; then + AC_MSG_NOTICE([Did not find valid rpc libraries - disabling vxi11 interface]) +fi + +if test "x${with_librpc}" = "xyes"; then + build_vxi11=yes + + # we support const input into clnt_create ? + AC_MSG_CHECKING([const input allowed into clnt_perror]) + const_clnt_perror=no + AC_LANG_PUSH([C++]) + save_LIBS=$LIBS + save_CPPFLAGS=$CPPFLAGS + LIBS=$RPCLIBS + CPPFLAGS=$RPCINCLUDE + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + ]], [[ + const char * msg = "const message"; + CLIENT *clnt = 0; + clnt_perror(clnt, msg); + ]])], + [AC_MSG_RESULT([yes]) + const_clnt_perror=yes], + [AC_MSG_RESULT([no])] + ) + LIBS=$save_LIBS= + CPPFLAGS=$save_CPPFLAGS + AC_LANG_POP([C++]) + + if test $const_clnt_perror = yes; then + AC_DEFINE([CONST_CLNT_SUPPORT], [1], [clnt allows const inputs]) + fi +fi + +# we have rpcgen ? +AC_CHECK_PROGS([RPCGEN], [rpcgen rpcgen-mt], [none]) + +if test "xRPCGEN" = "xnone"; then + AC_MSG_WARN([No rpcgen found - if rpc sources are modified, the build will fail]) +else + AC_MSG_CHECKING([whether ${RPCGEN} accepts -M option]) + rm -f rpcgen_test.* +cat > rpcgen_test.x < /dev/null 2>&1 + if test -f rpcgen_test.h; then + _rpcgen_result=yes + RPCGENOPTS="-M" + else + _rpcgen_result=no + fi + AC_MSG_RESULT([$_rpcgen_result]) + AC_SUBST([RPCGENOPTS], [$RPCGENOPTS]) + rm -f rpcgen_test.* + rm -f rpcgen_test_* +fi + +# Checks for openvisa +AC_CHECK_HEADERS([visa/visa.h], + [AC_SEARCH_LIBS([viOpenDefaultRM], [openvisa], [build_visa=yes], [])] , [] ) + +if test "x$ac_cv_search_viOpenDefaultRM" != "xno"; then + test "x$ac_cv_search_viOpenDefaultRM" = "xnone required" || AC_SUBST(VISALIBS, [$ac_cv_search_viOpenDefaultRM]) +fi + +# + +if test $build_parallel = yes; then + AC_DEFINE([BUILD_PARALLEL], [], [build PARALLEL interface functions]) +fi + +if test $build_serial = yes; then + AC_DEFINE([BUILD_SERIAL], [], [build SERIAL interface functions]) +fi + +if test $build_i2c = yes; then + AC_DEFINE([BUILD_I2C], [], [build I2C interface functions]) +fi + +if test $build_spi = yes; then + AC_DEFINE([BUILD_SPI], [], [build SPI interface functions]) +fi + +if test $build_usbtmc = yes; then + AC_DEFINE([BUILD_USBTMC], [], [build USBTMC interface functions]) +fi + +if test $build_tcp = yes; then + AC_DEFINE([BUILD_TCP], [], [build TCP interface functions]) +fi + +if test $build_udp = yes; then + AC_DEFINE([BUILD_UDP], [], [build UDP interface functions]) +fi + +if test $build_gpib = yes; then + AC_DEFINE([BUILD_GPIB], [], [build GPIB interface functions]) +fi + +if test $build_vxi11 = yes; then + AC_DEFINE([BUILD_VXI11], [], [build VXI11 interface functions]) + AC_SUBST([BUILD_VXI11], [1], [build VXI11 interface functions]) +fi + +if test $build_visa = yes; then + AC_DEFINE([BUILD_VISA], [], [build VISA interface functions]) +fi + +if test $build_resolvehost = yes; then + AC_DEFINE([BUILD_RESOLVEHOST], [], [build resolvehost function]) +fi + + +# all done + +AC_CONFIG_FILES([common.mk Makefile gpib/Makefile + tcp/Makefile tcpclient/Makefile + udp/Makefile udpport/Makefile + vxi11/Makefile usbtmc/Makefile spi/Makefile + serial/Makefile parallel/Makefile i2c/Makefile + resolvehost/Makefile hwinfo/Makefile + serialport/Makefile]) +AC_OUTPUT + +AC_MSG_NOTICE([ + +$PACKAGE_NAME is now configured with + + BUILD SERIAL: $build_serial + BUILD PARALLEL: $build_parallel + BUILD I2C: $build_i2c + BUILD SPI: $build_spi + BUILD TCP: $build_tcp + BUILD UDP: $build_udp + BUILD USBTMC: $build_usbtmc + BUILD GPIB: $build_gpib + BUILD VXI11: $build_vxi11 + BUILD RESOLVEHOST: $build_resolvehost + + GPIB LIBS: $GPIBLIBS + VXI11 LIBS: $RPCLIBS + VXI11 INCLUDE: $RPCINCLUDE + VISA LIBS: $VISALIBS + TCP LIBS: $TCPLIBS + +]) diff --git a/src/gpib/Makefile.in b/src/gpib/Makefile.in new file mode 100644 index 0000000..467454e --- /dev/null +++ b/src/gpib/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../gpib.oct +OBJ := gpib.o gpib_timeout.o gpib_write.o gpib_close.o gpib_read.o __gpib_spoll__.o __gpib_trigger__.o __gpib_clrdevice__.o gpib_class.o __gpib_pkg_lock__.o +LFLAGS = $(LIBS) @GPIBLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/gpib/__gpib_clrdevice__.cc b/src/gpib/__gpib_clrdevice__.cc new file mode 100644 index 0000000..bdf2bf3 --- /dev/null +++ b/src/gpib/__gpib_clrdevice__.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include + +#include "gpib_class.h" +#endif + +// PKG_ADD: autoload ("__gpib_clrdevice__", "gpib.oct"); +DEFUN_DLD (__gpib_clrdevice__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} __gpib_clrdevice__ (@var{gpib})\n \ +\n\ +Sends clear command to gpib device.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@*\ +\n\ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + gpib->cleardevice (); + + return octave_value (); +#endif +} diff --git a/src/gpib/__gpib_pkg_lock__.cc b/src/gpib/__gpib_pkg_lock__.cc new file mode 100644 index 0000000..982f697 --- /dev/null +++ b/src/gpib/__gpib_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__gpib_pkg_lock__", "gpib.oct"); +// PKG_ADD: __gpib_pkg_lock__(1); +// PKG_DEL: __gpib_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__gpib_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__gpib_pkg_lock__")) + interp.munlock("__gpib_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__gpib_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/gpib/__gpib_spoll__.cc b/src/gpib/__gpib_spoll__.cc new file mode 100644 index 0000000..f5dd392 --- /dev/null +++ b/src/gpib/__gpib_spoll__.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include + +#include "gpib_class.h" + +#endif + + +// PKG_ADD: autoload ("__gpib_spoll__", "gpib.oct"); +DEFUN_DLD (__gpib_spoll__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{sb} = } __gpib_spoll__ (@var{gpib})\n \ +\n\ +serial poll gpib interface.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@*\ +\n\ +Upon successful completion, gpib_spoll() shall return the status byte @var{sb}.\n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + char rqs; + + retval = gpib->spoll (&rqs); + if (retval == -1) + return octave_value (); + + return octave_value (rqs); + +#endif +} diff --git a/src/gpib/__gpib_trigger__.cc b/src/gpib/__gpib_trigger__.cc new file mode 100644 index 0000000..8a5e26d --- /dev/null +++ b/src/gpib/__gpib_trigger__.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include + +#include "gpib_class.h" + +#endif + +// PKG_ADD: autoload ("__gpib_trigger__", "gpib.oct"); +DEFUN_DLD (__gpib_trigger__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} __gpib_trigger__ (@var{gpib})\n \ +\n\ +triggers gpib device.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@*\ +\n\ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + gpib->trigger (); + + return octave_value (); +#endif +} diff --git a/src/gpib/gpib.cc b/src/gpib/gpib.cc new file mode 100644 index 0000000..604e718 --- /dev/null +++ b/src/gpib/gpib.cc @@ -0,0 +1,121 @@ +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include +//#include + +#include "gpib_class.h" + +#endif + +// PKG_ADD: autoload ("gpib", "gpib.oct"); +DEFUN_DLD (gpib, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{gpib} = } gpib ([@var{gpibid}], [@var{timeout}])\n \ +\n\ +Open gpib interface.\n \ +\n\ +@var{gpibid} - the interface number.@* \ +@var{timeout} - the interface timeout value. If omitted defaults to blocking call.\n \ +\n\ +The gpib() shall return instance of @var{octave_gpib} class as the result @var{gpib}.\n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + int gpibid; + const int minor = 0; + int timeout = -1; + const int secid = 0; + const int send_eoi = 1; + const int eos_mode = 0; + + + // Parse the function arguments + if (args.length() > 0) + { + if (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) + { + gpibid = args (0).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + else + { + print_usage (); + return octave_value (); + } + + // is_float_type() is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + if (args.length() > 1) + { + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + timeout = args (1).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + // Open the interface + octave_gpib* retval = new octave_gpib (); + + retval->open (minor, gpibid, secid, timeout, send_eoi, eos_mode); + + //retval->set_timeout(timeout); + //retval->set_sad(eot); + //retval->set_send_eoi(eot); + //retval->set_eos_mode(eot); + + return octave_value (retval); +#endif +} +#if 0 + +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "gpib")) +%! fail ("gpib ()", "Invalid call to gpib"); +%! else +%! fail ("gpib ()", "gpib: Your system doesn't support the GPIB interface"); +%! endif + +#endif diff --git a/src/gpib/gpib_class.cc b/src/gpib/gpib_class.cc new file mode 100644 index 0000000..1bad9a1 --- /dev/null +++ b/src/gpib/gpib_class.cc @@ -0,0 +1,406 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include +#include +#include + +#include +#include +#include "gpib/ib.h" + +#define GPIB_USEBLOCKREAD + +#include "gpib_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_gpib, "octave_gpib", "octave_gpib"); + +static void close_fd (int fd) +{ + ibonl(fd,0); +} + +octave_gpib::octave_gpib () +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + minor = -1; + gpibid = -1; +} + +octave_gpib::~octave_gpib () +{ + octave_gpib::close (); +} + +void +octave_gpib::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_gpib::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_gpib::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << gpibid; +} + +int +octave_gpib::open (int minor, int gpibid, int sad, int timeout, int send_eoi, int eos_mode) +{ + this->minor = minor; + this->gpibid = gpibid; + this->sad = sad; + this->timeout = timeout; + this->send_eoi = send_eoi; + this->eos_mode = eos_mode; + + return 1; +} + +int +octave_gpib::read (uint8_t *buf, unsigned int len, bool *eoi) +{ + int gperr,fd; + int bytes_read = 0; + + if (this->minor < 0) + { + error ("gpib_read: Interface must be opened first..."); + return -1; + } + + fd = ibdev (this->minor, this->gpibid, this->sad, this->timeout, this->send_eoi, this->eos_mode); + if (fd < 0) + { + error ("gpib_read: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + +#if defined(GPIB_USEBLOCKREAD) + // blocking read - not interruptable + gperr = ibrd (fd,(void *)buf,len); + if (gperr & ERR) + { + if (gperr & TIMO) + { + warning ("gpib_read: read timeout"); + } + else + { + int localiberr = ThreadIberr (); + error ("gpib_read: Error while reading: %d - %d\n", gperr, localiberr); + if (localiberr == 0) + { + localiberr = ThreadIbcnt (); + warning ("gpib_read: failed system call: %d - %s\n", localiberr, strerror (localiberr)); + } + return -1; + } + } + +#else + // async read - not interruptable as well + gperr = ibrda (fd, (void *)buf, len); + + if (gperr & ERR) + { + error ("gpib_read: Error while reading: %d\n", ThreadIberr()); + return -1; + } + + while (1) + { + OCTAVE_QUIT; + + gperr = ibwait (fd,CMPL); + warning ("gpib_read: read timeout %d - %d - %d",gperr, ThreadIberr (),ThreadIbcnt ()); + if (gperr & ERR) + { + if (gperr & TIMO) + { + warning ("gpib_read: read timeout"); + } + else + { + int localiberr = ThreadIberr (); + error ("gpib_read: Error while reading: %d - %d\n", gperr, localiberr); + if (localiberr == 0) + { + localiberr = ThreadIbcnt(); + warning ("gpib_read: failed system call: %d - %s\n", localiberr, strerror (localiberr)); + } + return -1; + } + } + } +#endif + + bytes_read = ThreadIbcnt (); + *eoi = (ThreadIbsta () & 0x2000) ? true : false; + + return bytes_read; +} + +int +octave_gpib::write (const std::string &str) +{ + int gperr,fd; + + if (minor < 0) + { + error ("gpib_write: Interface must be opened first..."); + return -1; + } + + fd = ibdev (minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error ("gpib_read: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibwrt (fd,str.c_str (), str.length ()); + if (gperr & ERR) + { + // warning: can not write + if (ThreadIberr () != ENOL) + { + // ENOL is handled by library + error ("gpib: can not write gpib data to device"); + } + } + + return gperr; +} + +int +octave_gpib::write (uint8_t *buf, unsigned int len) +{ + int gperr,fd; + + if (minor < 0) + { + error ("gpib_write: Interface must be opened first..."); + return -1; + } + + fd = ibdev(minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error ("gpib_write: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibwrt (fd, buf, len); + if (gperr & ERR) + { + // warning: can not write + if (ThreadIberr() != ENOL) + { + // ENOL is handled by library + error ("gpib: can not write gpib data to device"); + } + } + + return gperr; +} + +int +octave_gpib::spoll (char *rqs) +{ + int gperr,fd; + + if (minor < 0) + { + error("gpib_spoll: Interface must be opened first..."); + return -1; + } + + fd = ibdev (minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error ("gpib_spoll: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibrsp (fd,rqs); + if (gperr & ERR) + { + error ("gpib_spoll: some error occured: %d", ThreadIberr ()); + return -1; + } + //warning ("aaa: %X - %X",gperr, buf); + + return gperr; +} + +int +octave_gpib::trigger() +{ + int gperr,fd; + + if (this->minor < 0) + { + error ("gpib_trigger: Interface must be opened first..."); + return -1; + } + + fd = ibdev(minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error("gpib_trigger: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibtrg (fd); + if (gperr & ERR) + { + error ("gpib_trigger: some error occured: %d", ThreadIberr ()); + return -1; + } + + return gperr; +} + +int +octave_gpib::cleardevice() +{ + int gperr,fd; + + if (minor < 0) + { + error ("gpib_clear: Interface must be opened first..."); + return -1; + } + + fd = ibdev(minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error("gpib_clear: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibclr(fd); + if (gperr & ERR) + { + error ("gpib_clear: some error occured: %d", ThreadIberr ()); + return -1; + } + + return gperr; +} + +int +octave_gpib::set_timeout (int newtimeout) +{ + if (minor < 0) + { + error ("gpib_timeout: Interface must be opened first..."); + return -1; + } + if (timeout < 0 || timeout > 17) + { + error ("gpib_timeout: timeout must be between 0 and 17"); + return -1; + } + + timeout = newtimeout; + + return 1; +} + +int +octave_gpib::get_timeout() const +{ + return timeout; +} + +int +octave_gpib::close() +{ + int fd,gperr; + + if (minor > -1) + { + fd = ibdev(minor, gpibid, sad, timeout, send_eoi, eos_mode); + if (fd < 0) + { + error("gpib_close: error opening gpib device..."); + return -1; + } + + // set up a frame to close fd + OCTAVE__UNWIND_PROTECT frame; + frame.add_fcn (close_fd, fd); + + gperr = ibloc (fd); + if (gperr & ERR) + { + error ("gpib_close: can not set device to local"); + } + } + + minor = -1; + return -1; +} +#endif diff --git a/src/gpib/gpib_class.h b/src/gpib/gpib_class.h new file mode 100644 index 0000000..8a6e08a --- /dev/null +++ b/src/gpib/gpib_class.h @@ -0,0 +1,78 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef GPIB_CLASS_H +#define GPIB_CLASS_H + +#include +#include + +#include + +class octave_gpib : public octave_base_value +{ +public: + octave_gpib(); + ~octave_gpib(); + + int write(const std::string&); + int write(uint8_t*, unsigned int); + + int read(uint8_t*, unsigned int, bool*); + + int spoll(char*); + int trigger(); + int cleardevice(); + + int open(int, int, int, int, int, int); + int close(); + + int set_timeout(int); + int get_timeout() const; + + //int set_sad(int); + //int set_send_eoi(int); + //int set_eos_mode(int); + + // Overloaded base functions + double gpib_value() const { return (double)this->gpibid; } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)this->gpibid; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool print_as_scalar (void) const { return true;} + +private: + int minor; + int gpibid; + int sad; + int timeout; + int send_eoi; + int eos_mode; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/gpib/gpib_close.cc b/src/gpib/gpib_close.cc new file mode 100644 index 0000000..1cb350b --- /dev/null +++ b/src/gpib/gpib_close.cc @@ -0,0 +1,57 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include "gpib_class.h" +#endif + +// PKG_ADD: autoload ("gpib_close", "gpib.oct"); +DEFUN_DLD (gpib_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gpib_close (@var{gpib})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.\n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + + if (args.length() != 1 || args(0).type_id() != octave_gpib::static_type_id()) + { + print_usage (); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + gpib->close (); + + return octave_value (); +#endif +} diff --git a/src/gpib/gpib_read.cc b/src/gpib/gpib_read.cc new file mode 100644 index 0000000..1cdfe04 --- /dev/null +++ b/src/gpib/gpib_read.cc @@ -0,0 +1,98 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include + +#include + +#include "gpib_class.h" + +#endif + +// PKG_ADD: autoload ("gpib_read", "gpib.oct"); +DEFUN_DLD (gpib_read, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}, @var{eoi}] = } gpib_read (@var{gpib}, @var{n})\n \ +\n\ +Read from gpib interface.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +The gpib_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@var{eoi} indicates read operation complete \n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + if (args.length () < 2 || args.length () > 3 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 0; + + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ())) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("gpib_read: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + // Read data + bool eoi; + int bytes_read = gpib->read (buffer, buffer_len, &eoi); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data(dim_vector (1, bytes_read)); + + for (int i = 0; i < bytes_read; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = bytes_read; + return_list (2) = eoi; + + return return_list; +#endif +} diff --git a/src/gpib/gpib_timeout.cc b/src/gpib/gpib_timeout.cc new file mode 100644 index 0000000..bb3228e --- /dev/null +++ b/src/gpib/gpib_timeout.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB + +#include "gpib_class.h" + +#endif + +// PKG_ADD: autoload ("gpib_timeout", "gpib.oct"); +DEFUN_DLD (gpib_timeout, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gpib_timeout (@var{gpib}, @var{timeout})\n \ +@deftypefnx {Loadable Function} {@var{t} = } gpib_timeout (@var{gpib})\n \ +\n\ +Set new or get existing gpib interface timeout parameter. The timeout value is valid from 0 to 17.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@* \ +@var{timeout} - Value of 0 means never timeout, 11 means one second and 17 means 1000 seconds (see GPIB documentation (ibtmo) for further details)\n \ +\n\ +If @var{timeout} parameter is omitted, the gpib_timeout() shall return current timeout value as the result @var{t}.\n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value(); +#else + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_gpib* gpib = NULL; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + // Setting new timeout + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + gpib->set_timeout (args (1).int_value ()); + + return octave_value (); // Should it return by default? + } + + // Returning current timeout + return octave_value (gpib->get_timeout ()); +#endif +} diff --git a/src/gpib/gpib_write.cc b/src/gpib/gpib_write.cc new file mode 100644 index 0000000..af30244 --- /dev/null +++ b/src/gpib/gpib_write.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_GPIB +#include + +#include "gpib_class.h" +#endif + + +// PKG_ADD: autoload ("gpib_write", "gpib.oct"); +DEFUN_DLD (gpib_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } gpib_write (@var{gpib}, @var{data})\n \ +\n\ +Write data to a gpib interface.\n \ +\n\ +@var{gpib} - instance of @var{octave_gpib} class.@* \ +@var{data} - data to be written to the gpib interface. Can be either of String or uint8 type.\n \ +\n\ +Upon successful completion, gpib_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_GPIB + error ("gpib: Your system doesn't support the GPIB interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_gpib::static_type_id ()) + { + print_usage(); + return octave_value(-1); + } + + octave_gpib* gpib = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + gpib = &((octave_gpib &)rep); + + if (args (1).is_string ()) // String + { + retval = gpib->write (args (1).string_value ()); + } + else if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("gpib_write: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value(-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data (i)); + + retval = gpib->write (buf, data.numel ()); + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/hwinfo/Makefile.in b/src/hwinfo/Makefile.in new file mode 100644 index 0000000..6c68c9c --- /dev/null +++ b/src/hwinfo/Makefile.in @@ -0,0 +1,7 @@ +OCT := ../__instr_hwinfo__.oct +OBJ := __instr_hwinfo__.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk + diff --git a/src/hwinfo/__instr_hwinfo__.cc b/src/hwinfo/__instr_hwinfo__.cc new file mode 100644 index 0000000..1f69511 --- /dev/null +++ b/src/hwinfo/__instr_hwinfo__.cc @@ -0,0 +1,86 @@ +// Copyright (C) 2017-2020 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +DEFUN_DLD (__instr_hwinfo__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{res} = } __instr_hwinfo__()\n \ +\n\ +Internal private function\n \ +\n\ +@end deftypefn") +{ + octave_value_list return_value; + octave_value_list interfaces; + + octave_map inf; + + inf.assign("ToolboxVersion", octave_value(PACKAGE_VERSION)); + inf.assign("ToolboxName", octave_value(PACKAGE_NAME)); + + int int_count = 0; +#ifdef BUILD_GPIB + interfaces (int_count++) = "gpib"; +#endif +#ifdef BUILD_I2C + interfaces (int_count++) = "i2c"; +#endif +#ifdef BUILD_SPI + interfaces (int_count++) = "spi"; +#endif +#ifdef BUILD_PARALLEL + interfaces (int_count++) = "parallel"; +#endif + +#ifdef BUILD_SERIAL + interfaces (int_count++) = "serial"; + interfaces (int_count++) = "serialport"; +#endif + +#ifdef BUILD_TCP + interfaces (int_count++) = "tcp"; + interfaces (int_count++) = "tcpclient"; +#endif + +#ifdef BUILD_UDP + interfaces (int_count++) = "udp"; + interfaces (int_count++) = "udpport"; +#endif + +#ifdef BUILD_USBTMC + interfaces (int_count++) = "usbtmc"; +#endif + +#ifdef BUILD_VXI11 + interfaces (int_count++) = "vxi11"; +#endif + + inf.assign("SupportedInterfaces", octave_value(interfaces.cell_value())); + + return_value (0) = inf; + + return return_value; +} +#if 0 +%!test +%! a = __instr_hwinfo__(); +%! assert (! isempty (a)); +#endif diff --git a/src/i2c/Makefile.in b/src/i2c/Makefile.in new file mode 100644 index 0000000..3edb324 --- /dev/null +++ b/src/i2c/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../i2c.oct +OBJ := i2c.o i2c_close.o i2c_addr.o i2c_write.o i2c_read.o i2c_class.o __i2c_pkg_lock__.o __i2c_properties__.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/i2c/__i2c_pkg_lock__.cc b/src/i2c/__i2c_pkg_lock__.cc new file mode 100644 index 0000000..f437357 --- /dev/null +++ b/src/i2c/__i2c_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__i2c_pkg_lock__", "i2c.oct"); +// PKG_ADD: __i2c_pkg_lock__(1); +// PKG_DEL: __i2c_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__i2c_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__i2c_pkg_lock__")) + interp.munlock("__i2c_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__i2c_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/i2c/__i2c_properties__.cc b/src/i2c/__i2c_properties__.cc new file mode 100644 index 0000000..af82369 --- /dev/null +++ b/src/i2c/__i2c_properties__.cc @@ -0,0 +1,78 @@ +// Copyright (C) 2019 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_I2C +# include "i2c_class.h" +#endif + + +// PKG_ADD: autoload ("__i2c_properties__", "i2c.oct"); +DEFUN_DLD (__i2c_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __i2c_properties__ (@var{octave_i2c}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_I2C + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_i2c::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_i2c* i2c = &((octave_i2c &)rep); + + std::string property = args(1).string_value (); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (i2c->get_name ()); + else if (property == "remoteaddress") + return octave_value (i2c->get_addr ()); + else if (property == "status") + return octave_value (i2c->get_status ()); + else if (property == "port") + return octave_value (i2c->get_port ()); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (i2c->set_name (args(2).string_value ())); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "remoteaddress") + return octave_value (i2c->set_addr (args(2).int_value ())); + else if (property == "port") + (*current_liboctave_error_handler) ("can not set this property"); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#else + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the I2C interface"); +#endif + return octave_value(); +} diff --git a/src/i2c/i2c.cc b/src/i2c/i2c.cc new file mode 100644 index 0000000..a5b1998 --- /dev/null +++ b/src/i2c/i2c.cc @@ -0,0 +1,125 @@ +// Copyright (C) 2017-2020 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include + +#include "i2c_class.h" +#endif + +// PKG_ADD: autoload ("i2c", "i2c.oct"); +DEFUN_DLD (i2c, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{i2c} = } i2c ([@var{port_path}], [@var{address}])\n \ +\n\ +Open i2c interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{port_path} - the interface device port/path of type String. If omitted defaults to \n \ +'/dev/i2c-0'. @*\n \ +@var{address} - the slave device address. If omitted must be set using i2c_addr() call.\n \ +\n\ +@subsubheading Outputs\n \ +@var{i2c} - An instance of @var{octave_i2c} class.\n \ +\n\ +@subsubheading Properties\n \ +The i2c object has the following properties:\n \ +@table @asis\n \ +@item name\n \ +Name of the object\n \ +@item remoteaddress\n \ +the slave device address\n \ +@item port\n \ +The interface driver port (readonly)\n \ +@end table\n \ +@end deftypefn") +{ +#ifndef BUILD_I2C + error ("i2c: Your system doesn't support the I2C interface"); + return octave_value (); +#else + + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + int oflags = O_RDWR; + std::string path ("/dev/i2c-0"); + int addr = -1; + + // Parse the function arguments + if (args.length () > 0) + { + if (args (0).is_string ()) + { + path = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + + } + + // is_float_type() is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + if (args.length () > 1) + { + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + addr = args (1).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + octave_i2c* retval = new octave_i2c (); + + // Open the interface + if (retval->open (path, oflags) < 0) + return octave_value (); + + if (addr > 0) + retval->set_addr (addr); + + return octave_value (retval); +#endif +} + +#if 0 + +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "i2c")) +%! fail ("i2c ()", "Invalid call to i2c"); +%! else +%! fail ("i2c ()", "i2c: Your system doesn't support the I2C interface"); +%! endif + +#endif diff --git a/src/i2c/i2c_addr.cc b/src/i2c/i2c_addr.cc new file mode 100644 index 0000000..e651e67 --- /dev/null +++ b/src/i2c/i2c_addr.cc @@ -0,0 +1,78 @@ +// Copyright (C) 2017-2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include "i2c_class.h" +#endif + +// PKG_ADD: autoload ("i2c_addr", "i2c.oct"); +DEFUN_DLD (i2c_addr, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} i2c_addr (@var{i2c}, @var{address})\n \ +@deftypefnx {Loadable Function} {@var{addr} = } i2c_addr (@var{i2c})\n \ +\n\ +Set new or get existing i2c slave device address.\n \ +\n\ +@subsubheading Inputs\n \ +@var{i2c} - instance of @var{octave_i2c} class.@*\ +@var{address} - i2c slave device address of type Integer. \ +The address is passed in the 7 or 10 lower bits of the argument.\n \ +\n\ +@subsubheading Outputs\n \ +@var{addr} - If @var{address} parameter is omitted, the i2c_addr() shall return \ +current i2c slave device address.\n \ +@end deftypefn") +{ +#ifndef BUILD_I2C + error ("i2c: Your system doesn't support the I2C interface"); + return octave_value (); +#else + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_i2c::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_i2c* i2c = NULL; + + const octave_base_value& rep = args (0).get_rep(); + i2c = &((octave_i2c &)rep); + + + // Setting new slave address + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + i2c->set_addr(args (1).int_value ()); + + return octave_value (); + } + + // Returning current slave address + return octave_value (i2c->get_addr ()); +#endif +} diff --git a/src/i2c/i2c_class.cc b/src/i2c/i2c_class.cc new file mode 100644 index 0000000..3be348f --- /dev/null +++ b/src/i2c/i2c_class.cc @@ -0,0 +1,345 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include +#include +#include + +#include +#include +#include +#include + + +#if defined (__linux__) +#include +#endif + +// Platform specific header files +#if defined (__FreeBSD__) +#include +#endif + +#include "i2c_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_i2c, "octave_i2c", "octave_i2c"); + +octave_i2c::octave_i2c (void) + : fieldnames(4) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + fd = -1; + addr = -1; + + fieldnames[0] = "status"; + fieldnames[1] = "name"; + fieldnames[2] = "remoteaddress"; + fieldnames[3] = "port"; +} + +octave_i2c::~octave_i2c (void) +{ + octave_i2c::close (); +} + +int +octave_i2c::get_fd (void) const +{ + return fd; +} + +void +octave_i2c::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_i2c::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_i2c::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " I2C Object " << this->get_name(); newline(os); + os << " status: " << this->get_status(); newline(os); + if (get_fd() > -1) + { + if (get_addr() > -1) + os << " remoteaddress: " << this->get_addr(); + else + os << " remoteaddress: None set"; + newline(os); + } +} + +int +octave_i2c::open (const std::string &path, int flags) +{ + port = path; + name = "I2C-" + path; + + fd = ::open (path.c_str (), flags, 0); + + if (get_fd () < 0) + { + error ("i2c: Error opening the interface: %s\n", strerror (errno)); + return -1; + } + + return get_fd (); +} + + +int +octave_i2c::set_addr (int addr) +{ + if (get_fd () < 0) + { + error ("i2c: Interface must be open first..."); + return -1; + } + +#if defined (__linux__) + if (::ioctl (get_fd (), I2C_SLAVE, addr) < 0) + { + error ("i2c: Error setting slave address: %s\n", strerror (errno)); + return -1; + } +#endif + + this->addr = addr; + + return 1; +} + +int +octave_i2c::get_addr (void) const +{ + if (get_fd() < 0) + { + error ("i2c: Interface must be open first..."); + return -1; + } + + return addr; +} + +int +octave_i2c::read (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("i2c: Interface must be open first..."); + return -1; + } + + int retval = -1; + +#if defined (__linux__) + retval = ::read (get_fd (), buf, len); +#endif + +#if defined (__FreeBSD__) + // Populate FreeBSD-specific structure + struct iiccmd i2c_slave; + + i2c_slave.slave = static_cast(get_addr ()); + i2c_slave.count = len; + i2c_slave.last = 0; // No additional reads will follow for this transaction + i2c_slave.buf = buf; + + ::ioctl (get_fd (), I2CSTART, &i2c_slave); + retval = ::ioctl (get_fd(), I2CREAD, &i2c_slave); + ::ioctl (get_fd(), I2CSTOP); +#endif + + if (retval < 0) + error ("i2c: Failed to read from the i2c bus: %s\n", strerror (errno)); + + return retval; +} + +int +octave_i2c::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("i2c: Interface must be open first..."); + return -1; + } + + int retval = -1; + +#if defined (__linux__) + retval = ::write (get_fd (), buf, len); +#endif + +#if defined (__FreeBSD__) + // Populate FreeBSD-specific structure + struct iiccmd i2c_slave; + + i2c_slave.slave = static_cast(get_addri ()); + i2c_slave.count = len; + i2c_slave.last = 0; // No additional writes will follow for this transaction + i2c_slave.buf = buf; + + ::ioctl (get_fd (), I2CSTART, &i2c_slave); + retval = ::ioctl (get_fd (), I2CWRITE, &i2c_slave); + ::ioctl(get_fd (), I2CSTOP); +#endif + + if (retval < 0) + error ("i2c: Failed to write to the i2c bus: %s\n", strerror (errno)); + + return retval; +} + +int +octave_i2c::close (void) +{ + int retval = -1; + + if (get_fd () > 0) + { + retval = ::close(get_fd ()); + fd = -1; + } + + return retval; +} + +std::string +octave_i2c::get_port () const +{ + return port; +} + +std::string +octave_i2c::get_name () const +{ + return name; +} + +std::string +octave_i2c::set_name (const std::string &newname) +{ + name = newname; + return name; +} + +std::string +octave_i2c::get_status () const +{ + if (get_fd () > -1) + return "open"; + else + return "closed"; +} + +octave_value_list +octave_i2c::subsref (const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_i2c object cannot be indexed with %c", type[0]); + break; + case '.': + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__i2c_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_i2c::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_i2c object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__i2c_properties__"), ovl, 0); + + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length() > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_i2c invalid index"); + } + + } + return retval; +} + +#endif diff --git a/src/i2c/i2c_class.h b/src/i2c/i2c_class.h new file mode 100644 index 0000000..d47f501 --- /dev/null +++ b/src/i2c/i2c_class.h @@ -0,0 +1,99 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef I2C_CLASS_H +#define I2C_CLASS_H + +#include + +#include + +class octave_i2c : public octave_base_value +{ +public: + octave_i2c (void); + ~octave_i2c (void); + + int open (const std::string& /* path */, int /* open flags */); + int close (void); + int get_fd (void) const; + + int set_addr (int /* slave ddress */); + int get_addr (void) const; + + std::string get_name () const; + std::string set_name (const std::string &newname); + + std::string get_status () const; + + std::string get_port () const; + + // Simple i2c commands + int write (uint8_t* /* buffer */, unsigned int /* buffer size */); + int read (uint8_t* /* buffer */, unsigned int /* buffer size */); + + + // Overloaded base functions + double i2c_value () const + { + return (double)fd; + } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true;} + // 4.4+ + bool isobject (void) const { return true;} + + octave_base_value * unique_clone (void) { count++; return this;} + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); +private: + int fd; + int addr; + std::string name; + std::string port; + string_vector fieldnames; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + + +#endif diff --git a/src/i2c/i2c_close.cc b/src/i2c/i2c_close.cc new file mode 100644 index 0000000..864269a --- /dev/null +++ b/src/i2c/i2c_close.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include "i2c_class.h" +#endif + +// PKG_ADD: autoload ("i2c_close", "i2c.oct"); +DEFUN_DLD (i2c_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} i2c_close (@var{i2c})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{i2c} - instance of @var{octave_i2c} class.@*\ +\n \ +@subsubheading Outputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_I2C + error ("i2c: Your system doesn't support the I2C interface"); + return octave_value (); +#else + + if (args.length () != 1 || args (0).type_id () != octave_i2c::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_i2c* i2c = NULL; + + const octave_base_value& rep = args (0).get_rep (); + i2c = &((octave_i2c &)rep); + + i2c->close (); + + return octave_value (); +#endif +} diff --git a/src/i2c/i2c_read.cc b/src/i2c/i2c_read.cc new file mode 100644 index 0000000..1ee7de3 --- /dev/null +++ b/src/i2c/i2c_read.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2017-2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include + +#include "i2c_class.h" +#endif + +// PKG_ADD: autoload ("i2c_read", "i2c.oct"); +DEFUN_DLD (i2c_read, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } i2c_read (@var{i2c}, @var{n})\n \ +\n\ +Read from i2c slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{i2c} - instance of @var{octave_i2c} class.@*\ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +@subsubheading Outputs\n \ +The i2c_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_I2C + error ("i2c: Your system doesn't support the I2C interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_i2c::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 1; + + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + } + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len +1)); + + if (buffer == NULL) + { + error ("i2c_read: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_i2c* i2c = NULL; + + const octave_base_value& rep = args (0).get_rep(); + i2c = &((octave_i2c &)rep); + + int retval; + + retval = i2c->read (buffer, buffer_len); + + octave_value_list return_list; + uint8NDArray data (dim_vector (1, retval)); + + for (int i = 0; i < retval; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = retval; + + return return_list; +#endif +} diff --git a/src/i2c/i2c_write.cc b/src/i2c/i2c_write.cc new file mode 100644 index 0000000..3e9ecf5 --- /dev/null +++ b/src/i2c/i2c_write.cc @@ -0,0 +1,84 @@ +// Copyright (C) 2018-2020 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_I2C +#include + +#include "i2c_class.h" +#endif + +// PKG_ADD: autoload ("i2c_write", "i2c.oct"); +DEFUN_DLD (i2c_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } i2c_write (@var{i2c}, @var{data})\n \ +\n\ +Write data to a i2c slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{i2c} - instance of @var{octave_i2c} class.@*\ +@var{data} - data, of type uint8, to be written to the slave device.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, i2c_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_I2C + error ("i2c: Your system doesn't support the I2C interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_i2c::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_i2c* i2c = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + i2c = &((octave_i2c &)rep); + + if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("i2c_write: cannot allocate requested memory: %s", strerror (errno)); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data (i)); + + retval = i2c->write (buf, data.numel()); + } + else + { + error ("i2c_write: expected uint8 data"); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/m4/octave-forge.m4 b/src/m4/octave-forge.m4 new file mode 100644 index 0000000..8d04ebf --- /dev/null +++ b/src/m4/octave-forge.m4 @@ -0,0 +1,116 @@ +# Copyright (C) 2017 Olaf Till +# Modifications to print what is searching for by JohnD +# +# 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 . + +# arguments of OF_OCTAVE_ALT_SYMS (see also description of +# OF_OCTAVE_LIST_ALT_SYMS below): +# +# $1: symbol version 1 +# $2: symbol version 2 +# $3: test for symbol version 2 +# $4: macro name to access alternative symbols +# $5: include directives for symbol version 1 +# $6: include directives for symbol version 2 +# (a list of lists of args 1--6 is $1 of OF_OCTAVE_LIST_ALT_SYMS) +# $7: name of generated include file with alternatives of Octave headers +# (arg7 is $2 of OF_OCTAVE_LIST_ALT_SYMS) +AC_DEFUN([OF_OCTAVE_ALT_SYMS], [ +AC_MSG_CHECKING([$1 or $2]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ] + $6], + [$3])], + [AC_DEFINE($4, + [[$2]], + [macro for alternative Octave symbols]) + AC_MSG_RESULT([$2]) + echo '$6' >> $7 + ac_cv_octsym_[$4]=["$2"]], + [AC_DEFINE($4, + [[$1]], + [macro for alternative Octave symbols]) + AC_MSG_RESULT([$1]) + echo '$5' >> $7 + ac_cv_octsym_[$4]=["$1"]], +) +]) + + +# OF_OCTAVE_LIST_ALT_SYMS is called in the following way: +# +# OF_OCTAVE_LIST_ALT_SYMS([ +# [dnl +# [old_octave_symbol], +# [new_octave_symbol], +# [[compilation test] +# [for new_octave_symbol]], +# [NAME_OF_GENERATED_MACRO____WILL_EXPAND_TO_OLD_OR_NEW_SYMBOL], +# [[include directives] +# [except #include ] +# [necessary to compile with old_octave_symbol]], +# [[include directives] +# [except #include ] +# [nessary to compile with new_octave_symbol] +# [and to compile the test]] +# ], +# +# ... further such lists as the above +# +# ], +# +# [name-of-header-file-for-alternative-octave-iclude-directives.h]) +# +# +# This file should be put into src/m4/, and the line +# +# AC_CONFIG_MACRO_DIRS([m4]) +# +# should be put into src/configure.ac. The package should use +# autoheader to generate config.h.in (src/bootstrap should contain the +# lines 'aclocal', 'autoconf', and 'autoheader -f'). Package code +# should include config.h and use the generated macros to access the +# alternative symbols of Octave. An example of a call to +# OF_OCTAVE_LIST_ALT_SYMS in src/configure.ac is available together +# with this file. +AC_DEFUN([OF_OCTAVE_LIST_ALT_SYMS], [ + +echo '/* generated by configure */' > $2 + +m4_foreach([it], [$1], [m4_apply([OF_OCTAVE_ALT_SYMS], [it, $2])]) + +AH_BOTTOM([#include "$2"]) + +]) + +# check whether can compile +# arguments: +# $1: symbol +# $2: test for symbol version 2 +# $3: macro name define if sucessfull +# $4: include directives +AC_DEFUN([OF_OCTAVE_CHECK_SYM], [ +AC_MSG_CHECKING([$1]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ] + $4], + [$2])], + [AC_DEFINE($3, + [1], + [Have $1]) + AC_MSG_RESULT([yes]) + ], + [AC_MSG_RESULT(no)] +) +]) diff --git a/src/oct-alt-includes.h b/src/oct-alt-includes.h new file mode 100644 index 0000000..60c0e95 --- /dev/null +++ b/src/oct-alt-includes.h @@ -0,0 +1,20 @@ +/* generated by configure */ +#include + + + + + + + +#include + #include + + + + #include + #include + + + + diff --git a/src/parallel/Makefile.in b/src/parallel/Makefile.in new file mode 100644 index 0000000..6bd531b --- /dev/null +++ b/src/parallel/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../parallel.oct +OBJ := parallel.o parallel_class.o pp_close.o pp_datadir.o pp_data.o pp_stat.o pp_ctrl.o __parallel_pkg_lock__.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/parallel/__parallel_pkg_lock__.cc b/src/parallel/__parallel_pkg_lock__.cc new file mode 100644 index 0000000..88d6249 --- /dev/null +++ b/src/parallel/__parallel_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__parallel_pkg_lock__", "parallel.oct"); +// PKG_ADD: __parallel_pkg_lock__(1); +// PKG_DEL: __parallel_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__parallel_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__parallel_pkg_lock__")) + interp.munlock("__parallel_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__parallel_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/parallel/parallel.cc b/src/parallel/parallel.cc new file mode 100644 index 0000000..f643e4d --- /dev/null +++ b/src/parallel/parallel.cc @@ -0,0 +1,131 @@ +// Copyright (C) 2017,2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include + +#include +#include +#include + +#ifndef __WIN32__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +using std::string; + +#include "parallel_class.h" + +#endif + +// PKG_ADD: autoload ("parallel", "parallel.oct"); +DEFUN_DLD (parallel, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{parallel} = } parallel ([@var{path}], [@var{direction}])\n \ +\n\ +Open Parallel interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{path} - the interface path of type String. If omitted defaults to '/dev/parport0'.@*\ +@var{direction} - the direction of interface drivers of type Integer, see: PP_DATADIR for more info. \ +If omitted defaults to 1 (Input).\n \ +\n\ +@subsubheading Outputs\n \ +The parallel() shall return instance of @var{octave_parallel} class as the result @var{parallel}.\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + int oflags = O_RDWR; + int dir = 1; // Input + string path ("/dev/parport0"); + + // Parse the function arguments + if (args.length () > 0) + { + if (args (0).is_string ()) + { + path = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + // is_float_type () is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + if (args.length () > 1) + { + if (args (1).OV_ISINTEGER() || args (1).OV_ISFLOAT()) + { + dir = args (1).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + octave_parallel* retval = new octave_parallel (); + + // Open the interface + if (retval->open (path, oflags) < 0) + return octave_value (); + + // Set direction + retval->set_datadir(dir); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("parallel ()", "Invalid call to parallel"); +%! else +%! fail ("parallel ()", "parallel: Your system doesn't support the parallel interface"); +%! endif + +#endif diff --git a/src/parallel/parallel_class.cc b/src/parallel/parallel_class.cc new file mode 100644 index 0000000..0314132 --- /dev/null +++ b/src/parallel/parallel_class.cc @@ -0,0 +1,312 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (__linux__) +#include +#include +#endif + +// Platform specific header files +#if defined (__FreeBSD__) +#include +#include + +// And constants +#define PPWCONTROL PPISCTRL +#define PPRCONTROL PPIGCTRL +#define PPWSTATUS PPISSTATUS +#define PPRSTATUS PPIGSTATUS +#define PPWDATA PPISDATA +#define PPRDATA PPIGDATA +#endif + +using std::string; + +#include "parallel_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_parallel, "octave_parallel", "octave_parallel"); + +octave_parallel::octave_parallel (void) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + this->fd = -1; +} + +octave_parallel::~octave_parallel (void) +{ + this->close (); +} + +int +octave_parallel::open (string path, int flags) +{ + this->fd = ::open (path.c_str (), flags, 0); + + if (this->get_fd () < 0) + { + error("parallel: Error opening the interface: %s\n", strerror (errno)); + return -1; + } + + // Claim control of parallel port + // Not used with FreeBSD +#if !defined(__FreeBSD__) + + if (ioctl (this->get_fd (), PPCLAIM) < 0) + { + error("parallel: Error when claiming the interface: %s\n", strerror(errno)); + + ::close (this->get_fd ()); + this->fd = -1; + + return -1; + } + +#endif + + return this->get_fd (); +} + +int +octave_parallel::get_fd (void) +{ + return this->fd; +} + +void +octave_parallel::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_parallel::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_parallel::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << this->fd; +} + +int +octave_parallel::set_datadir (int dir) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return -1; + } + + if (dir < 0 || 1 < dir) + { + error ("parallel: Unsupported data direction..."); + return -1; + } + + // The ioctl parameter is a pointer to an int. + // If the int is zero, the drivers are turned on (forward/output direction); + // if non-zero, the drivers are turned off (reverse/input direction). + // Not used with FreeBSD +#if !defined(__FreeBSD__) + + if (ioctl (this->get_fd (), PPDATADIR, &dir) < 0) + { + error ("pp_datadir: error setting data direction: %s\n", strerror (errno)); + return false; + } + +#endif + + this->dir = dir; + + return 1; +} + +int +octave_parallel::get_datadir (void) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return false; + } + + return this->dir; +} + +int +octave_parallel::get_stat (void) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return -1; + } + + uint8_t status; + + if (ioctl (this->get_fd (), PPRSTATUS, &status) < 0) + { + error ("parallel: Error while reading from Status register: %s\n", strerror (errno)); + return -1; + } + + return status; +} + +int +octave_parallel::set_data (uint8_t data) +{ + if (this->get_fd () < 0) + { + error("parallel: Open the interface first..."); + return -1; + } + + /* + if (this->get_dir () == 1) + { + error ("parallel: Trying to output data while in Input mode, this can result in hardware damage! \ + Use override if you know what you are doing..."); + return false; + } + */ + + if (ioctl (this->get_fd (), PPWDATA, &data) < 0) + { + error ("parallel: Error while writing to Data register: %s\n", strerror (errno)); + return -1; + } + + return 1; +} + +int +octave_parallel::get_data (void) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return -1; + } + + uint8_t data; + + if (ioctl(this->get_fd (), PPRDATA, &data) < 0) + { + error ("parallel: Error while reading from Data register: %s\n", strerror (errno)); + return -1; + } + + return data; +} + +int +octave_parallel::set_ctrl (uint8_t ctrl) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return -1; + } + + if (ioctl(this->get_fd (), PPWCONTROL, &ctrl) < 0) + { + error ("parallel: Error while writing to Control register: %s\n", strerror (errno)); + return -1; + } + + return 1; +} + +int +octave_parallel::get_ctrl (void) +{ + if (this->get_fd () < 0) + { + error ("parallel: Open the interface first..."); + return -1; + } + + uint8_t ctrl; + + if (ioctl(this->get_fd (), PPRCONTROL, &ctrl) < 0) + { + error ("parallel: Error while reading from Control register: %s\n", strerror (errno)); + return -1; + } + + return ctrl; +} + +int +octave_parallel::close (void) +{ + if (this->get_fd () > 0) + { + // Release parallel port + // Not used with FreeBSD +#if !defined(__FreeBSD__) + + if (ioctl (this->get_fd (), PPRELEASE) < 0) + error ("parallel: error releasing parallel port: %s\n", strerror (errno)); + +#endif + + int retval = ::close (this->get_fd ()); + + this->fd = -1; + + return retval; + } + + return -1; +} +#endif diff --git a/src/parallel/parallel_class.h b/src/parallel/parallel_class.h new file mode 100644 index 0000000..aa28e4c --- /dev/null +++ b/src/parallel/parallel_class.h @@ -0,0 +1,79 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef PARALLEL_CLASS_H +#define PARALLEL_CLASS_H + +#include +#include + +#include + +using std::string; + +class octave_parallel : public octave_base_value +{ +public: + octave_parallel (void); + ~octave_parallel (void); + + int open (string /* path */, int /* open flags */); + int close (void); + int get_fd (); + + int get_datadir (void); + int set_datadir (int /* direction */); + + int get_data (void); + int set_data (uint8_t /* value */); + + int get_stat (void); + //int set_stat (uint8_t); + + int get_ctrl (void); + int set_ctrl (uint8_t /* value */); + + // Overloaded base functions + double parallel_value(void) const + { + return (double)this->fd; + } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)this->fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool print_as_scalar (void) const { return true;} + +private: + int fd; + + // 1 - Input + // 0 - Output + int dir; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + + +#endif diff --git a/src/parallel/pp_close.cc b/src/parallel/pp_close.cc new file mode 100644 index 0000000..79e479c --- /dev/null +++ b/src/parallel/pp_close.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include "parallel_class.h" + +#endif + +// PKG_ADD: autoload ("pp_close", "parallel.oct"); +DEFUN_DLD (pp_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} pp_close (@var{parallel})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{parallel} - instance of @var{octave_serial} class.@*\ +@subsubheading Outputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id() != octave_parallel::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_parallel* parallel = NULL; + + const octave_base_value& rep = args (0).get_rep (); + parallel = &((octave_parallel &)rep); + + parallel->close (); + + return octave_value (); +#endif +} +#if 0 +%!xtest +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! a = parallel (); +%! pp_close (a); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_close(1);", "Invalid call to pp_close"); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_close();", "Invalid call to pp_close"); +%! endif +#endif diff --git a/src/parallel/pp_ctrl.cc b/src/parallel/pp_ctrl.cc new file mode 100644 index 0000000..8a446f0 --- /dev/null +++ b/src/parallel/pp_ctrl.cc @@ -0,0 +1,89 @@ +// Copyright (C) 2017,2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include "parallel_class.h" + +#endif + +// PKG_ADD: autoload ("pp_ctrl", "parallel.oct"); +DEFUN_DLD (pp_ctrl, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} pp_ctrl (@var{parallel}, @var{ctrl})\n \ +@deftypefnx {Loadable Function} {@var{c} = } pp_ctrl (@var{parallel})\n \ +\n\ +Sets or Read the Control lines.\ +\n\ +@subsubheading Inputs\n \ +@var{parallel} - instance of @var{octave_parallel} class.@*\ +@var{ctrl} - control parameter to be set of type Byte.\n \ +\n\ +@subsubheading Outputs\n \ +If @var{ctrl} parameter is omitted, the pp_ctrl() shall return current Control lines state as the result @var{c}.\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value(); +#else + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_parallel::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_parallel* parallel = NULL; + + const octave_base_value& rep = args (0).get_rep (); + parallel = &((octave_parallel &)rep); + + // Set new Control register value + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args(1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + parallel->set_ctrl (args (1).int_value ()); + + return octave_value (); + } + + // Return current Control register value on port + return octave_value (parallel->get_ctrl ()); +#endif +} +#if 0 +%!xtest +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! a = parallel (); +%! v = pp_ctrl(a); +%! pp_close (a); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_ctrl(1);", "Invalid call to pp_ctrl"); +%! endif +#endif diff --git a/src/parallel/pp_data.cc b/src/parallel/pp_data.cc new file mode 100644 index 0000000..4e0349a --- /dev/null +++ b/src/parallel/pp_data.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2017,2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include "parallel_class.h" + +#endif + +// PKG_ADD: autoload ("pp_data", "parallel.oct"); +DEFUN_DLD (pp_data, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} pp_data (@var{parallel}, @var{data})\n \ +@deftypefnx {Loadable Function} {@var{d} = } pp_data (@var{parallel})\n \ +\n\ +Sets or Read the Data lines.\ +\n\ +@subsubheading Inputs\n \ +@var{parallel} - instance of @var{octave_parallel} class.@*\ +@var{data} - data parameter to be set of type Byte.\n \ +\n\ +@subsubheading Outputs\n \ +If @var{data} parameter is omitted, the pp_data() shall return current Data lines state as the result @var{d}.\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_parallel::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_parallel* parallel = NULL; + + const octave_base_value& rep = args (0).get_rep (); + parallel = &((octave_parallel &)rep); + + // Set new Data register value + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args(1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + parallel->set_data (args (1).int_value ()); + + return octave_value (); + } + + // Return current Data register value on port + return octave_value (parallel->get_data ()); +#endif +} + +#if 0 +%!xtest +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! a = parallel (); +%! d = pp_data (a); +%! pp_close (a); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_data(1);", "Invalid call to pp_data"); +%! endif +#endif diff --git a/src/parallel/pp_datadir.cc b/src/parallel/pp_datadir.cc new file mode 100644 index 0000000..6458df5 --- /dev/null +++ b/src/parallel/pp_datadir.cc @@ -0,0 +1,95 @@ +// Copyright (C) 2017,2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include "parallel_class.h" +#endif + +// PKG_ADD: autoload ("pp_datadir", "parallel.oct"); +DEFUN_DLD (pp_datadir, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} pp_datadir (@var{parallel}, @var{direction})\n \ +@deftypefnx {Loadable Function} {@var{dir} = } pp_datadir (@var{parallel})\n \ +\n\ +Controls the Data line drivers.\n \ +\n \ +Normally the computer's parallel port will drive the data lines, \ +but for byte-wide transfers from the peripheral to the host it is useful to turn off those drivers \ +and let the peripheral drive the signals. (If the drivers on the computer's parallel port are left \ +on when this happens, the port might be damaged.)\n \ +\n\ +@subsubheading Inputs\n \ +@var{parallel} - instance of @var{octave_parallel} class.@*\ +@var{direction} - direction parameter of type Integer. Supported values: 0 - the drivers are turned on \ +(Output/Forward direction); 1 - the drivers are turned off (Input/Reverse direction).\n \ +\n\ +@subsubheading Outputs\n \ +If @var{direction} parameter is omitted, the pp_datadir() shall return current Data direction as the result @var{dir}.\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_parallel::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_parallel* parallel = NULL; + + const octave_base_value& rep = args (0).get_rep (); + parallel = &((octave_parallel &)rep); + + // Set new direction + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + parallel->set_datadir (args (1).int_value ()); + + return octave_value (); + } + + // Return current direction + return octave_value (parallel->get_datadir ()); +#endif +} +#if 0 +%!xtest +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! a = parallel (); +%! d = pp_datadir (a); +%! pp_close (a); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_datadir(1);", "Invalid call to pp_datadir"); +%! endif +#endif diff --git a/src/parallel/pp_stat.cc b/src/parallel/pp_stat.cc new file mode 100644 index 0000000..3314c4d --- /dev/null +++ b/src/parallel/pp_stat.cc @@ -0,0 +1,73 @@ +// Copyright (C) 2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_PARALLEL +#include "parallel_class.h" +#endif + +// PKG_ADD: autoload ("pp_stat", "parallel.oct"); +DEFUN_DLD (pp_stat, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{stat} = } pp_stat (@var{parallel})\n \ +\n\ +Reads the Status lines.\n \ +\n\ +@subsubheading Inputs\n \ +@var{parallel} - instance of @var{octave_parallel} class.@*\ +\n\ +@subsubheading Outputs\n \ +The pp_stat() shall return current Status lines state as the result @var{stat}.\n \ +@end deftypefn") +{ +#ifndef BUILD_PARALLEL + error ("parallel: Your system doesn't support the parallel interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id () != octave_parallel::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_parallel* parallel = NULL; + + const octave_base_value& rep = args (0).get_rep (); + parallel = &((octave_parallel &)rep); + + // Return current Status register value on port + return octave_value (parallel->get_stat ()); +#endif +} + +#if 0 +%!xtest +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! a = parallel (); +%! d = pp_stat (a); +%! pp_close (a); +%! endif + +%!test +%! if any (strcmp(instrhwinfo().SupportedInterfaces, "parallel")) +%! fail ("pp_stat(1);", "Invalid call to pp_stat"); +%! endif +#endif diff --git a/src/resolvehost/Makefile.in b/src/resolvehost/Makefile.in new file mode 100644 index 0000000..4ca4bf6 --- /dev/null +++ b/src/resolvehost/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../resolvehost.oct +OBJ := resolvehost.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/resolvehost/resolvehost.cc b/src/resolvehost/resolvehost.cc new file mode 100644 index 0000000..0290aa9 --- /dev/null +++ b/src/resolvehost/resolvehost.cc @@ -0,0 +1,232 @@ +// Copyright (C) 2016-2019 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_TCP +#include +#include + +#ifndef __WIN32__ +# include +# include +# include +# include +# include +# include +#else + // tell old versions of mingw32 to be win2k +# ifdef __MINGW32__ +# if _MINGW32_MAJOR_VERSION < 5 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +# endif +# endif +# include +# include +#endif + +#ifndef __WIN32__ +# define SOCKETERR errno +# define STRSOCKETERR strerror(errno) +#else +# define SOCKETERR WSAGetLastError() +# define STRSOCKETERR "" +#endif + +static bool type_loaded = false; + +#endif + +DEFUN_DLD (resolvehost, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{name} = } resolvehost (@var{host})\n \ +@deftypefnx {Loadable Function} {[@var{name}, @var{address}] = } resolvehost (@var{host})\n \ +@deftypefnx {Loadable Function} {@var{out} = } resolvehost (@var{host}, @var{returntype})\n \ +\n\ +Resolve a network host name or address to network name and address\n \ +\n\ +@subsubheading Inputs\n \ +@var{host} - Host name or IP address string to resolve.@* \ +@var{name} - Resolved IP host name.@* \ +@var{returntype} - 'name' to get host name, 'address' to get IP address.\n \ +\n \ +@subsubheading Outputs\n \ +@var{name} - Resolved IP host name.@* \ +@var{address} - Resolved IP host address.@* \ +@var{out} - host name if @var{returntype} is 'name', ipaddress if @var{returntype} is 'address'@* \ +\n \ +@subsubheading Example\n \ +@example\n \ +%% get resolved ip name and address pf www.gnu.org\n \ +[name, address] = resolvehost ('www.gnu.org');\n \ +\n \ +%% get ip address of www.gnu.org\n \ +ipaddress = resolvehost ('www.gnu.org', 'address');\n \ +\n \ +@end example\n \ +\n \ +@seealso{tcp, udp}\n \ +\n\ +@end deftypefn") +{ +#ifndef BUILD_RESOLVEHOST + error("resolvehost: Your system doesn't support the resolvehost interface"); + return octave_value(); +#else + octave_value_list return_value; + + if (!type_loaded) + { +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD ( 2, 2 ); + err = WSAStartup (wVersionRequested, &wsaData); + + if (err != 0) + { + error ("resolvehost: could not initialize winsock library"); + return return_value; + } +#endif + + type_loaded = true; + } + + // Nothing to do + if (args.length () != 1 && args.length () != 2) + { + print_usage (); + return return_value; + } + + // expects host string + if (! args (0).is_string ()) + { + print_usage (); + return return_value; + } + + std::string host = args (0).string_value (); + + // optional return type + std::string return_type = "both"; + + if (args.length () == 2) + { + if(! args (1).is_string ()) + { + print_usage (); + return return_value; + } + return_type = args (1).string_value (); + + std::transform (return_type.begin (), return_type.end (), + return_type.begin (), ::tolower); + + if (return_type != "name" && return_type != "address") + { + print_usage (); + return return_value; + } + } + + // create addr from ip/looked up ip of value + sockaddr_in in; + + memset (&in, 0, sizeof (in)); + + in.sin_family = AF_INET; + in.sin_addr.s_addr = inet_addr (host.c_str ()); + + if (in.sin_addr.s_addr == INADDR_NONE) + { + struct hostent * hostinfo = gethostbyname (host.c_str ()); + if (hostinfo) + memcpy (&in.sin_addr, hostinfo->h_addr_list[0], hostinfo->h_length); + } + + if (in.sin_addr.s_addr == INADDR_NONE) + { + error ("resolvehost: could not lookup IP address"); + return return_value; + } + + // we want to look up the name (ie: not only address) + if (return_type != "address") + { + char name[1025]; + if( getnameinfo ((struct sockaddr *)&in, sizeof (in), + name, sizeof(name), NULL, 0, 0) != 0) + { + error ("resolvehost: error looking up host name : %d - %s\n", + SOCKETERR, STRSOCKETERR); + + return return_value; + } + return_value (0) = name; + } + + // we want the ip address (both or address) + if (return_type != "name") + { + std::stringstream n; + u_long addr = ntohl (in.sin_addr.s_addr); + int b[4]; + b[0] = (addr>>24)&0xff; + b[1] = (addr>>16)&0xff; + b[2] = (addr>>8)&0xff; + b[3] = (addr>>0)&0xff; + n << b[0] << "." << b[1] << "." << b[2] << "." << b[3]; + + if (return_type == "both") + return_value (1) = n.str (); + else + return_value (0) = n.str (); + } + + return return_value; +#endif +} +#if 0 +%!xtest +%! name = resolvehost ("wiki.octave.org"); +%! assert(! isempty (name)); + +%!xtest +%! [name, addr] = resolvehost ("wiki.octave.org"); +%! assert (! isempty (name)); +%! assert (! isempty (addr)); +%! assert (name, resolvehost ("wiki.octave.org", "name")); +%! assert (addr, resolvehost ("wiki.octave.org", "address")); + +%!error resolvehost (); + +%!error resolvehost (1); + +%!error resolvehost ("wiki.octave.org", 1); + +%!error resolvehost ("wiki.octave.org", "addr"); + +%!error resolvehost ("wiki.octave.org", "name", 1); + +#endif diff --git a/src/serial/Makefile.in b/src/serial/Makefile.in new file mode 100644 index 0000000..2abd421 --- /dev/null +++ b/src/serial/Makefile.in @@ -0,0 +1,11 @@ +OCT := ../serial.oct +OBJ := serial.o srl_write.o srl_read.o __srl_properties__.o __serial_pkg_lock__.o serial_class.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ +ifeq ("@BUILD_FOR_WINDOWS@","1") + OBJ += serial_class_win32.o +else + OBJ += serial_class_lin.o +endif + +include ../common.mk diff --git a/src/serial/__serial_pkg_lock__.cc b/src/serial/__serial_pkg_lock__.cc new file mode 100644 index 0000000..fe224d6 --- /dev/null +++ b/src/serial/__serial_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__serial_pkg_lock__", "serial.oct"); +// PKG_ADD: __serial_pkg_lock__(1); +// PKG_DEL: __serial_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__serial_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__serial_pkg_lock__")) + interp.munlock("__serial_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__serial_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/serial/__srl_properties__.cc b/src/serial/__srl_properties__.cc new file mode 100644 index 0000000..b9f47e3 --- /dev/null +++ b/src/serial/__srl_properties__.cc @@ -0,0 +1,377 @@ +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// Copyright (C) 2014 Stefan Mahr +// +// 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serial_class.h" +#endif + +#ifdef BUILD_SERIAL +octave_value_list srl_close (octave_serial* serial, const octave_value_list& args, int nargout) +{ + serial->close (); + return octave_value (); +} + +octave_value_list srl_flush (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Default arguments + int queue_selector = 2; // Input and Output + + if (args.length () > 0) + { + if (!(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + queue_selector = args (0).int_value (); + } + + serial->flush (queue_selector); + + return octave_value (); +} + +octave_value_list srl_break (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Default arguments + int ms = 2; // Input and Output + + if (args.length () > 0) + { + if (!(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer"); + + ms = args (0).int_value (); + } + + serial->sendbreak (ms); + + return octave_value (); +} + + +octave_value_list srl_timeout (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new timeout + if (args.length () > 0) + { + if ( !(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serial->set_timeout (args (0).int_value ()); + + return octave_value (); // Should it return by default? + } + + // Returning current timeout + return octave_value (serial->get_timeout ()); +} + +octave_value_list srl_bytesavailable (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Returning bytes available + return octave_value (serial->get_bytesavailable ()); +} + +octave_value_list srl_status (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Returning bytes available + return octave_value (serial->get_status ()); +} + +octave_value_list srl_type (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Returning bytes available + return octave_value (serial->get_type ()); +} + +octave_value_list srl_port (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("read only value"); + + // Returning bytes available + return octave_value (serial->get_port ()); +} + +octave_value_list srl_name (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new name + if (args.length () > 0) + { + if (! (args (0).is_string ())) + (*current_liboctave_error_handler) ("argument must be string"); + + serial->set_name (args (0).string_value ()); + + return octave_value (); + } + + // Returning current baud rate + return octave_value (serial->get_name ()); +} + +octave_value_list srl_baudrate (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new baudrate + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serial->set_baudrate (args (0).int_value ()); + + return octave_value (); + } + + // Returning current baud rate + return octave_value (serial->get_baudrate ()); +} + +octave_value_list srl_bytesize (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new byte size + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serial->set_bytesize (args (0).int_value ()); + + return octave_value (); + } + + // Returning current byte size + return octave_value (serial->get_bytesize ()); +} + +octave_value_list srl_stopbits (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new stop bits + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serial->set_stopbits(args (0).int_value ()); + + return octave_value (); + } + + // Returning current stop bits + return octave_value (serial->get_stopbits ()); +} + +octave_value_list srl_parity (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new parity + if (args.length () > 0) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be string"); + + serial->set_parity (args (0).string_value()); + + return octave_value (); + } + + // Returning current parity + return octave_value (serial->get_parity ()); +} + +octave_value_list srl_requesttosend (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + std::string onoff = ""; + + // Setting RTS + if (args.length () > 0) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be string"); + + onoff = args (0).string_value (); + std::transform (onoff.begin (), onoff.end (), onoff.begin (), ::tolower); + if (onoff == "on") + serial->set_control_line ("RTS", true); + else if (onoff == "off") + serial->set_control_line ("RTS", false); + else + (*current_liboctave_error_handler) ("wrong argument"); + } + + // Returning RTS + if (serial->get_control_line ("RTS")) + return octave_value ("on"); + + return octave_value ("off"); +} + +octave_value_list srl_dataterminalready (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + std::string onoff = ""; + + // Setting DTR + if (args.length () > 0) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be string"); + + onoff = args (0).string_value (); + std::transform (onoff.begin (), onoff.end (), onoff.begin (), ::tolower); + if (onoff == "on") + serial->set_control_line ("DTR", true); + else if (onoff == "off") + serial->set_control_line ("DTR", false); + else + (*current_liboctave_error_handler) ("wrong argument"); + } + + // Returning DTR + if (serial->get_control_line ("DTR")) + return octave_value ("on"); + + return octave_value ("off"); +} + +octave_value_list srl_pinstatus (octave_serial* serial, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + octave_scalar_map res; + + res.assign ("CarrierDetect", serial->get_control_line ("CD") ? + octave_value ("on") : + octave_value ("off")); + + res.assign ("ClearToSend", serial->get_control_line ("CTS") ? + octave_value ("on") : + octave_value ("off")); + + res.assign ("DataSetReady", serial->get_control_line ("DSR") ? + octave_value ("on") : + octave_value ("off")); + + res.assign ("RingIndicator", serial->get_control_line ("RI") ? + octave_value ("on") : + octave_value ("off")); + + return octave_value (res); +} +#endif + +// PKG_ADD: autoload ("__srl_properties__", "serial.oct"); +DEFUN_DLD (__srl_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __srl_properties__ (@var{octave_serial}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_SERIAL + + if (args.length () < 2 || args (0).type_id () != octave_serial::static_type_id () || !args (1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args (0).get_rep (); + octave_serial* serial = &((octave_serial &)rep); + + std::string property = args (1).string_value (); + octave_value_list args2 = args.slice (2, args.length ()-2); + + if (property == "baudrate") + return srl_baudrate (serial, args2, nargout); + else if (property == "bytesize") + return srl_bytesize (serial, args2, nargout); + else if (property == "dataterminalready") + return srl_dataterminalready (serial, args2, nargout); + else if (property == "close") + return srl_close (serial, args2, nargout); + else if (property == "flush") + return srl_flush (serial, args2, nargout); + else if (property == "break") + return srl_break (serial, args2, nargout); + else if (property == "parity") + return srl_parity (serial, args2, nargout); + else if (property == "pinstatus") + return srl_pinstatus (serial, args2, nargout); + else if (property == "requesttosend") + return srl_requesttosend (serial, args2, nargout); + else if (property == "stopbits") + return srl_stopbits (serial, args2, nargout); + else if (property == "timeout") + return srl_timeout (serial, args2, nargout); + else if (property == "bytesavailable") + return srl_bytesavailable (serial, args2, nargout); + else if (property == "status") + return srl_status (serial, args2, nargout); + else if (property == "name") + return srl_name (serial, args2, nargout); + else if (property == "type") + return srl_type (serial, args2, nargout); + else if (property == "port") + return srl_port (serial, args2, nargout); + else + (*current_liboctave_error_handler) ("wrong keyword"); +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the SERIAL interface"); +} diff --git a/src/serial/serial.cc b/src/serial/serial.cc new file mode 100644 index 0000000..970f274 --- /dev/null +++ b/src/serial/serial.cc @@ -0,0 +1,163 @@ +// Copyright (C) 2019 John Donoghue +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +// TODO: Implement Flow Control +// TODO: Implement H/W handshaking + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include +#include + +#include "serial_class.h" + +#endif + +// PKG_ADD: autoload ("serial", "serial.oct"); +DEFUN_DLD (serial, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{serial} = } serial ([@var{path}], [@var{baudrate}], [@var{timeout}])\n \ +\n\ +Open serial interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{path} - the interface path of type String. @*\ +@var{baudrate} - the baudrate of interface. If omitted defaults to 115200. @*\ +@var{timeout} - the interface timeout value. If omitted defaults to blocking call.\n \ +\n\ +@subsubheading Outputs\n \ +The serial() shall return an instance of @var{octave_serial} class as the result @var{serial}.\n \ +@subsubheading Properties\n \ +The serial object has the following public properties:\n \ +@table @asis\n \ +@item name\n \ +name assigned to the object\n \ +@item type\n \ +instrument type 'serial' (readonly)\n \ +@item port\n \ +OS specific port name (readonly)\n \ +@item status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item timeout\n \ +timeout value used for waiting for data\n \ +@item bytesavailable\n \ +number of bytes currently available to read (readonly)\n \ +@item stopbits\n \ +number of stopbits to use\n \ +@item requesttosend\n \ +request to send state - 'on' or 'off'\n \ +@item parity\n \ +Parity setting 'none', 'even', 'odd'\n \ +@item bytesize\n \ +Number of bits to a byte (7 or 8)\n \ +@item baudrate\n \ +Baudrate setting\n \ +@item dataterminalready\n \ +state of dataterminal ready - 'on' or 'off'\n \ +@item pinstatus\n \ +current state of pins (readonly)\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error ("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + std::string path; + unsigned int baud_rate = 115200; + short timeout = -1; + + unsigned short bytesize = 8; + std::string parity("N"); + unsigned short stopbits = 1; + // Parse the function arguments + if ((args.length () == 0) || !args(0 ).is_string ()) + { + print_usage (); + return octave_value (); + } + + path = args (0).string_value (); + + // isfloat() is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + if (args.length() > 1) + { + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + baud_rate = args (1).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + if (args.length () > 2) + { + if (args (2).OV_ISINTEGER () || args (2).OV_ISFLOAT ()) + { + timeout = args (2).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + + octave_serial* retval = new octave_serial (); + + // Open the interface + retval->open (path); + + retval->set_baudrate (baud_rate); + retval->set_timeout (timeout); + retval->set_parity (parity); + retval->set_bytesize (bytesize); + retval->set_stopbits (stopbits); + + //retval->flush (2); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "serial")) +%! fail ("serial ()", "Invalid call to serial"); +%! else +%! fail ("serial ()", "serial: Your system doesn't support the serial interface"); +%! endif + +#endif diff --git a/src/serial/serial_class.cc b/src/serial/serial_class.cc new file mode 100644 index 0000000..5c2d59a --- /dev/null +++ b/src/serial/serial_class.cc @@ -0,0 +1,117 @@ +// Copyright (C) 2019-2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serial_class.h" + +octave_serial_common::octave_serial_common () + : fieldnames(13) +{ + fieldnames[0] = "baudrate"; + fieldnames[1] = "bytesize"; + fieldnames[2] = "dataterminalready"; + fieldnames[3] = "parity"; + fieldnames[4] = "pinstatus"; + fieldnames[5] = "requesttosend"; + fieldnames[6] = "stopbits"; + fieldnames[7] = "timeout"; + fieldnames[8] = "bytesavailable"; + fieldnames[9] = "status"; + fieldnames[10] = "name"; + fieldnames[11] = "type"; + fieldnames[12] = "port"; +} + +octave_value_list +octave_serial_common::subsref (const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_serial object cannot be indexed with %c", type[0]); + break; + case '.': + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__srl_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_serial_common::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_serial object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__srl_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + } + count++; + retval = octave_value (this); + } + else + { + error ("octave_serial invalid index"); + } + + } + return retval; +} + +#endif diff --git a/src/serial/serial_class.h b/src/serial/serial_class.h new file mode 100644 index 0000000..de64ccc --- /dev/null +++ b/src/serial/serial_class.h @@ -0,0 +1,188 @@ +// Copyright (C) 2012 Andrius Sutas +// 2018 John Donoghue +// 2019 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 . + +#ifndef SERIAL_CLASS_H +#define SERIAL_CLASS_H + +#include +//#include + +#include + +#define BITMASK_SET(x,y) ((x) |= (y)) +#define BITMASK_CLEAR(x,y) ((x) &= (~(y))) +#define BITMASK_TOGGLE(x,y) ((x) ^= (y)) +#define BITMASK_CHECK(x,y) ((x) & (y)) +#define BITMASK_CHECK_VALUE(x,y,z) (((x) & (y)) == (z)) + +#define CONCAT2X(x,y) x ## y +#define CONCAT2(x,y) CONCAT2X(x,y) + +#define BINOPDECL(name, a1, a2) \ + static octave_value \ + CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2) + +#define CAST_BINOP_ARGS(t1, t2) \ + t1 v1 = dynamic_cast (a1); \ + t2 v2 = dynamic_cast (a2) + + +#define DEFBINOP_CLASS_OP(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \ + return octave_value \ + (&v1 op &v2); \ + } + +#ifdef OCTAVE__NEW_REGISTER_OP +#define INSTALL_BINOP(op, t1, t2, f) \ + {octave::type_info& ti = octave::interpreter::the_interpreter ()->get_type_info (); \ + ti.register_binary_op \ + (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ + CONCAT2(oct_binop_, f));} +#else +#define INSTALL_BINOP(op, t1, t2, f) \ + octave_value_typeinfo::register_binary_op \ + (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ + CONCAT2(oct_binop_, f)); +#endif + +class octave_serial_common : public octave_base_value +{ +protected: + octave_serial_common(); +public: + + // os dependent functions + virtual bool fd_is_valid() const = 0; + virtual int get_timeout() const = 0; + virtual int get_baudrate() const = 0; + virtual int get_bytesize() const = 0; + virtual std::string get_parity() const = 0; + virtual int get_stopbits() const = 0; + virtual int get_bytesavailable() const = 0; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true;} + // 4.4+ + bool isobject (void) const { return true;} + + octave_base_value * unique_clone (void) { count++; return this;} + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + void print (std::ostream& os, bool pr_as_read_syntax = false) + { + print_raw(os, pr_as_read_syntax); + newline(os); + } + + void print (std::ostream& os, bool pr_as_read_syntax = false) const + { + print_raw(os, pr_as_read_syntax); + newline(os); + } + + void print_raw (std::ostream& os, bool pr_as_read_syntax) const + { + os << " Serial Port Object " << this->get_name(); newline(os); + os << " status: " << this->get_status(); newline(os); + if (this->fd_is_valid()) + { + os << " port: " << this->portPath; newline(os); + os << " baudrate: " << this->get_baudrate(); newline(os); + os << " parity: " << this->get_parity(); newline(os); + os << " bytesize: " << this->get_bytesize(); newline(os); + os << " stopbits: " << this->get_stopbits(); newline(os); + os << " timeout: " << this->get_timeout(); newline(os); + //os << "Mode: " << blockmode; newline(os); + } + } + + bool operator==(octave_serial_common& other) const + { + return (this == &other); + } + + bool operator!=(octave_serial_common& other) const + { + return ! (this == &other); + } + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + std::string get_status () const + { + if (fd_is_valid ()) + return "open"; + else + return "closed"; + } + + std::string get_type () const + { + return "serial"; + } + + std::string get_port () const + { + return portPath; + } + + std::string get_name () const + { + return name; + } + + void set_name (const std::string &newname) + { + name = newname; + } +protected: + string_vector fieldnames; + + std::string name; + std::string portPath; +}; + + +#ifdef __WIN32__ + #include "serial_class_win32.h" +#else + #include "serial_class_lin.h" +#endif + +//DEFBINOP_CLASS_OP (eq_serial_serial, serial, serial, ==) +//DEFBINOP_CLASS_OP (ne_serial_serial, serial, serial, !=) + +#endif diff --git a/src/serial/serial_class_lin.cc b/src/serial/serial_class_lin.cc new file mode 100644 index 0000000..21181f7 --- /dev/null +++ b/src/serial/serial_class_lin.cc @@ -0,0 +1,724 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_serial, "octave_serial", "octave_serial"); + +DEFBINOP_CLASS_OP (eq_serial_serial, serial, serial, ==) +DEFBINOP_CLASS_OP (ne_serial_serial, serial, serial, !=) + +octave_serial::octave_serial (void) +: fd (-1) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + INSTALL_BINOP (op_eq, octave_serial, octave_serial, eq_serial_serial); + INSTALL_BINOP (op_ne, octave_serial, octave_serial, ne_serial_serial); + } +} + +void +octave_serial::open (const std::string &path) +{ + int flags = O_RDWR | O_NOCTTY | O_SYNC | O_NDELAY; + // O_SYNC - All writes immediately effective, no buffering + // O_NOCTTY - Do not make serial terminal the controlling terminal for the process + // O_NDELAY - Do not care what state the DCD signal line is in. Used for open only, later disabled. + + fd = ::open (path.c_str (), flags); + portPath = path; + name = "Serial-" + portPath; + + if (fd_is_valid ()) + { + // Check whether fd is an open file descriptor referring to a terminal + if(! isatty (fd)) + { + error("serial: Interface does not refer to a terminal: %s\n", strerror (errno)); + octave_serial::close (); + return; + } + + if (tcgetattr (fd, &config) < 0) + { + error ("serial: Failed to get terminal attributes: %s\n", strerror (errno)); + octave_serial::close (); + return; + } + + // Clear all settings + config.c_iflag = 0; // Input modes + config.c_oflag = 0; // Output modes + config.c_cflag = CS8 | CREAD | CLOCAL; // Control modes, 8n1 + config.c_lflag = 0; // Local modes + config.c_cc[VMIN] = 1; + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serial: Failed to set default terminal attributes: %s\n", strerror (errno)); + octave_serial::close (); + return; + } + + // Disable NDELAY + if (fcntl (fd, F_SETFL, 0) < 0) + { + error ("serial: Failed to disable NDELAY flag: %s\n", strerror (errno)); + octave_serial::close (); + return; + } + + timeout = -1; + blocking_read = true; + } + else + { + error ("serial: Error opening the interface: %s\n", strerror (errno)); + return; + } +} + +octave_serial::~octave_serial (void) +{ + octave_serial::close(); +} + +int +octave_serial::read (uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error ("srl_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + int maxwait = timeout; + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + read_retval = ::read (fd, (void *)(buf + bytes_read), len - bytes_read); + //printf("read_retval: %d\n\r", read_retval); + + if (read_retval < 0) + { + error ("srl_read: Error while reading: %s\n", strerror (errno)); + break; + } + + bytes_read += read_retval; + + // Timeout while in non-blocking mode + if (read_retval == 0 && !blocking_read) + { + maxwait -= config.c_cc[VTIME]; + + // actual timeout + if (maxwait <= 0) + break; + } + } + + return bytes_read; +} + +int +octave_serial::write (const std::string &str) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + return ::write (fd, str.c_str (), str.length ()); +} + +int +octave_serial::write(uint8_t *buf, unsigned int len) +{ + if (!fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + return ::write (fd, buf, len); +} + +int +octave_serial::set_timeout (short newtimeout) +{ + if (! fd_is_valid ()) + { + error("serial: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 || newtimeout > 255) + { + error("srl_timeout: timeout value must be between [-1..255]..."); + return -1; + } + + timeout = newtimeout; + + // Disable custom timeout, enable blocking read + if (newtimeout < 0) + { + blocking_read = true; + newtimeout = 5; + } + // Enable custom timeout, disable blocking read + else + { + blocking_read = false; + if(newtimeout > 10) newtimeout = 5; + } + + + BITMASK_CLEAR (config.c_lflag, ICANON); // Set non-canonical mode + config.c_cc[VMIN] = 0; + config.c_cc[VTIME] = (unsigned) newtimeout; // Set timeout of 'timeout * 10' seconds + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("srl_timeout: error setting timeout..."); + return -1; + } + + return 1; +} + +int +octave_serial::get_timeout (void) const +{ + if (blocking_read) + return -1; + else + return timeout; +} + +int +octave_serial::set_stopbits (unsigned short stopbits) +{ + if (!fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + /* + * CSTOPB Send two stop bits, else one. + */ + + if (stopbits == 1) + { + // Set to one stop bit + BITMASK_CLEAR (config.c_cflag, CSTOPB); + } + else if (stopbits == 2) + { + // Set to two stop bits + BITMASK_SET (config.c_cflag, CSTOPB); + } + else + { + error ("srl_stopbits: Only 1 or 2 stop bits are supported..."); + return false; + } + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("srl_stopbits: error setting stop bits: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serial::get_stopbits (void) const +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + if (BITMASK_CHECK (config.c_cflag, CSTOPB)) + return 2; + else + return 1; +} + +int +octave_serial::set_bytesize (unsigned short bytesize) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + tcflag_t c_bytesize = 0; + + switch (bytesize) + { + case 5: c_bytesize = CS5; break; + case 6: c_bytesize = CS6; break; + case 7: c_bytesize = CS7; break; + case 8: c_bytesize = CS8; break; + + default: + error ("srl_bytesize: expecting value between [5..8]..."); + return false; + } + + // Clear bitmask CSIZE + BITMASK_CLEAR (config.c_cflag, CSIZE); + + // Apply new + BITMASK_SET (config.c_cflag, c_bytesize); + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("srl_bytesize: error setting byte size: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serial::get_bytesize (void) const +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + int retval = -1; + + if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS5)) + retval = 5; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS6)) + retval = 6; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS7)) + retval = 7; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS8)) + retval = 8; + + return retval; +} + +int +octave_serial::set_baudrate (unsigned int baud) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + speed_t baud_rate = 0; + + switch (baud) + { + case 0: + baud_rate = B0; break; + case 50: + baud_rate = B50; break; + case 75: + baud_rate = B75; break; + case 110: + baud_rate = B110; break; + case 134: + baud_rate = B134; break; + case 150: + baud_rate = B150; break; + case 200: + baud_rate = B200; break; + case 300: + baud_rate = B300; break; + case 600: + baud_rate = B600; break; + case 1200: + baud_rate = B1200; break; + case 1800: + baud_rate = B1800; break; + case 2400: + baud_rate = B2400; break; + case 4800: + baud_rate = B4800; break; + case 9600: + baud_rate = B9600; break; + case 19200: + baud_rate = B19200; break; + case 38400: + baud_rate = B38400; break; +#ifdef B57600 + case 57600: + baud_rate = B57600; break; +#endif +#ifdef B115200 + case 115200: + baud_rate = B115200; break; +#endif +#ifdef B230400 + case 230400: + baud_rate = B230400; break; +#endif +#ifdef B460800 + case 460800: + baud_rate = B460800; break; +#endif +#ifdef B500000 + case 500000: + baud_rate = B500000; break; +#endif +#ifdef B576000 + case 576000: + baud_rate = B576000; break; +#endif +#ifdef B921600 + case 921600: + baud_rate = B921600; break; +#endif +#ifdef B1000000 + case 1000000: + baud_rate = B1000000; break; +#endif +#ifdef B1152000 + case 1152000: + baud_rate = B1152000; break; +#endif +#ifdef B2000000 + case 2000000: + baud_rate = B2000000; break; +#endif +#ifdef B3000000 + case 3000000: + baud_rate = B3000000; break; +#endif +#ifdef B3500000 + case 3500000: + baud_rate = B3500000; break; +#endif +#ifdef B4000000 + case 4000000: + baud_rate = B4000000; break; +#endif + default: + error ("serial: baud rate not supported..."); + return false; + } + + cfsetispeed (&config, baud_rate); + cfsetospeed (&config, baud_rate); + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("srl_baudrate: error setting baud rate: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serial::get_baudrate (void) const +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + int retval = -1; + + speed_t baudrate = cfgetispeed (&config); + + if (baudrate == B0) + retval = 0; + else if (baudrate == B50) + retval = 50; + else if (baudrate == B75) + retval = 75; + else if (baudrate == B110) + retval = 110; + else if (baudrate == B134) + retval = 134; + else if (baudrate == B150) + retval = 150; + else if (baudrate == B200) + retval = 200; + else if (baudrate == B300) + retval = 300; + else if (baudrate == B600) + retval = 600; + else if (baudrate == B1200) + retval = 1200; + else if (baudrate == B1800) + retval = 1800; + else if (baudrate == B2400) + retval = 2400; + else if (baudrate == B4800) + retval = 4800; + else if (baudrate == B9600) + retval = 9600; + else if (baudrate == B19200) + retval = 19200; + else if (baudrate == B38400) + retval = 38400; + else if (baudrate == B57600) + retval = 57600; + else if (baudrate == B115200) + retval = 115200; + else if (baudrate == B230400) + retval = 230400; + + return retval; +} + +int +octave_serial::flush (unsigned short queue_selector) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + /* + * TCIOFLUSH Flush both pending input and untransmitted output. + * TCOFLUSH Flush untransmitted output. + * TCIFLUSH Flush pending input. + */ + + int flag; + + switch (queue_selector) + { + case 0: flag = TCOFLUSH; break; + case 1: flag = TCIFLUSH; break; + case 2: flag = TCIOFLUSH; break; + default: + error("srl_flush: only [0..2] values are accepted..."); + return false; + } + + return ::tcflush (fd, flag); +} + +int +octave_serial::sendbreak (unsigned short ms) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + return ::tcsendbreak (fd, ms); +} + +int +octave_serial::set_parity (const std::string &newparity) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string parity = newparity; + std::transform (parity.begin (), parity.end (), parity.begin (), ::tolower); + + /* + * PARENB Enable parity generation on output and parity checking for input. + * PARODD If set, then parity for input and output is odd; otherwise even parity is used. + */ + + if (parity == "n" || parity == "none") + { + // Disable parity generation/checking + BITMASK_CLEAR (config.c_cflag, PARENB); + } + else if (parity == "e" || parity == "even") + { + // Enable parity generation/checking + BITMASK_SET (config.c_cflag, PARENB); + + // Set to Even + BITMASK_CLEAR (config.c_cflag, PARODD); + + } + else if (parity == "o" || parity == "odd") + { + // Enable parity generation/checking + BITMASK_SET (config.c_cflag, PARENB); + + // Set to Odd + BITMASK_SET (config.c_cflag, PARODD); + + } + else + { + error ("srl_parity: Only [N]one, [E]ven or [O]dd parities are supported..."); + return false; + } + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("srl_parity: error setting parity: %s\n", strerror (errno)); + return false; + } + + return true; +} + +std::string +octave_serial::get_parity (void) const +{ + if (!BITMASK_CHECK (config.c_cflag, PARENB)) + return "None"; + else if (BITMASK_CHECK (config.c_cflag, PARODD)) + return "Odd"; + else + return "Even"; +} + +void +octave_serial::get_control_line_status (void) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return; + } + ioctl (fd, TIOCMGET, &status); +} + +bool +octave_serial::get_control_line (const std::string &control_signal) +{ + get_control_line_status (); + + if (control_signal == "DTR") + return (status & TIOCM_DTR); + else if (control_signal == "RTS") + return (status & TIOCM_RTS); + else if (control_signal == "CTS") + return (status & TIOCM_CTS); + else if (control_signal == "DSR") + return (status & TIOCM_DSR); + else if (control_signal == "CD") + return (status & TIOCM_CD); + else if (control_signal == "RI") + return (status & TIOCM_RI); + + error ("serial: Unknown control signal..."); + return false; + +} + +void +octave_serial::set_control_line (const std::string &control_signal, bool set) +{ + + get_control_line_status (); + + int signal; + + if (control_signal == "DTR") + signal = TIOCM_DTR; + else if (control_signal == "RTS") + signal = TIOCM_RTS; + else + { + error ("serial: Unknown control signal..."); + return; + } + + if (set) + status |= signal; + else + status &= ~signal; + + ioctl (fd, TIOCMSET, &status); + +} + +bool +octave_serial::fd_is_valid (void) const +{ + return (fd >= 0); +} + +void +octave_serial::close (void) +{ + if (fd_is_valid ()) + { + ::close (fd); + fd = -1; + } +} + +int +octave_serial::get_bytesavailable (void) const +{ + int available = 0; + if (fd_is_valid ()) + { + ioctl (fd, FIONREAD, &available); + } + return available; +} + +#endif diff --git a/src/serial/serial_class_lin.h b/src/serial/serial_class_lin.h new file mode 100644 index 0000000..003df2a --- /dev/null +++ b/src/serial/serial_class_lin.h @@ -0,0 +1,74 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef SERIAL_CLASS_LIN_H +#define SERIAL_CLASS_LIN_H + +#include +#include + +class octave_serial : public octave_serial_common +{ +public: + octave_serial(void); + ~octave_serial(void); + + int write(const std::string& /* buffer */); + int write(uint8_t* /* buffer */, unsigned int /* buffer size */); + + int read(uint8_t* /* buffer */, unsigned int /* buffer size */); + + void open(const std::string& /* path */); + void close(void); + + int flush(unsigned short /* stream select */); + + int sendbreak(unsigned short /* ms */); + + int set_timeout(short /* timeout */); + int get_timeout(void) const; + + int set_baudrate(unsigned int /* baudrate */); + int get_baudrate(void) const; + + int set_bytesize(unsigned short /* bytesize */); + int get_bytesize(void) const; + + int set_parity(const std::string& /* parity */); + std::string get_parity() const; + + int set_stopbits(unsigned short /* stop bits */); + int get_stopbits(void) const; + + bool get_control_line(const std::string &); + void set_control_line(const std::string &, bool); + + int get_bytesavailable(void) const; +private: + int fd; + int status; + struct termios config; + short timeout; + volatile bool blocking_read; + + void get_control_line_status(void); + + bool fd_is_valid(void) const; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/serial/serial_class_win32.cc b/src/serial/serial_class_win32.cc new file mode 100644 index 0000000..1b0e5d0 --- /dev/null +++ b/src/serial/serial_class_win32.cc @@ -0,0 +1,608 @@ +// Copyright (C) 2014-2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#if HAVE_OCTAVE_LO_SYSDEP_H + #include +#endif + +#include +#include +#include + +using std::string; + +#include "serial_class.h" + +std::string +winerror (int err) +{ + + if (err != 0) + return strerror (err); + else + { + DWORD e; + + e = GetLastError (); + +#if HAVE_OCTAVE_U8_TO_WSTRING + wchar_t errstring[100+1]; + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errstring, + 100, 0) == 0) + { + errstring[0] = '\0'; + } + return octave::sys::u8_from_wstring (errstring); +#else + char errstring[100+1]; + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errstring, + 100, 0) == 0) + { + errstring[0] = '\0'; + } + return errstring; +#endif + } +} + + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_serial, "octave_serial", "octave_serial"); + +DEFBINOP_CLASS_OP (eq_serial_serial, serial, serial, ==) +DEFBINOP_CLASS_OP (ne_serial_serial, serial, serial, !=) + +octave_serial::octave_serial(void) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + INSTALL_BINOP (op_eq, octave_serial, octave_serial, eq_serial_serial); + INSTALL_BINOP (op_ne, octave_serial, octave_serial, ne_serial_serial); + } + + fd = INVALID_HANDLE_VALUE; +} + +void +octave_serial::open (const std::string &path) +{ + portPath = path; + name = "Serial-" + path; + + // use full extended port names if not already specified + std::string fullPath = path; + if (fullPath.length() > 0 && fullPath[0] != '\\') + fullPath = "\\\\.\\" + path; + + fd = CreateFile(fullPath.c_str (), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (! fd_is_valid()) + { + error("serial: Error opening the interface: %s\n", winerror (errno).c_str ()); + return; + } + + // clear any errors that may be on the port + COMSTAT stats; + DWORD err; + ClearCommError (fd, &err, &stats); + + // Clean the configuration struct (DCB) + memset (&config, 0, sizeof (config)); + // set up device settings + config.DCBlength = sizeof (config); + + if(GetCommState (fd, &config) == FALSE) + { + error ("serial: Failed to get terminal attributes: %s\n", winerror (errno).c_str ()); + octave_serial::close (); + return; + } + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + timeout = -1; + + if (SetCommTimeouts(fd, &timeouts) == FALSE) + { + error ("serial: Failed to disable timeouts: %s\n", winerror (errno).c_str ()); + octave_serial::close (); + return; + } + + return; +} + +octave_serial::~octave_serial(void) +{ + octave_serial::close(); +} + +int +octave_serial::read(uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error ("srl_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + int maxwait = timeout; + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + DWORD readsz; + read_retval = -1; + if (ReadFile (fd, (buf + bytes_read), len - bytes_read, &readsz, NULL) == TRUE) + { + read_retval = readsz; + } + + if(read_retval < 0) + { + error ("srl_read: Error while reading: %s\n", winerror (errno).c_str ()); + break; + } + + bytes_read += read_retval; + + if (read_retval == 0 && !blocking_read) + { + maxwait -= timeouts.ReadTotalTimeoutConstant/100; + + // actual timeout + if (maxwait <= 0) + break; + } + } + + return bytes_read; +} + +int +octave_serial::write (const std::string & str) +{ + if (! fd_is_valid ()) + { + error("serial: Interface must be opened first..."); + return -1; + } + int wrote_ret = -1; + DWORD wrote; + if (WriteFile (fd, str.c_str (), str.length (), &wrote, NULL) == TRUE) + { + wrote_ret = wrote; + } + return wrote_ret; +} + +int +octave_serial::write (uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error("serial: Interface must be opened first..."); + return -1; + } + int wrote_ret = -1; + DWORD wrote; + if (WriteFile (fd, buf, len, &wrote, NULL) == TRUE) + { + wrote_ret = wrote; + } + return wrote_ret; +} + +int +octave_serial::set_timeout (short newtimeout) +{ + if (! fd_is_valid()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 || newtimeout > 255) + { + error ("srl_timeout: timeout value must be between [-1..255]..."); + return -1; + } + + timeout = newtimeout; + + // Disable custom timeout, enable blocking read + if (newtimeout < 0) + { + blocking_read = true; + newtimeout = 5; + } + // Enable custom timeout, disable blocking read + else + { + blocking_read = false; + if (newtimeout > 10) + newtimeout = 5; + } + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = newtimeout*100; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + if (SetCommTimeouts (fd, &timeouts) == FALSE) + { + error ("srl_timeout: error setting timeout..."); + return -1; + } + + return 1; +} + +int +octave_serial::get_timeout (void) const +{ + if (blocking_read) + return -1; + else + return timeout; +} + +int +octave_serial::set_stopbits (unsigned short stopbits) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + if (stopbits == 1) + { + // Set to one stop bit + config.StopBits = ONESTOPBIT; + } + else if (stopbits == 2) + { + // Set to two stop bits + config.StopBits = TWOSTOPBITS; + } + else + { + error ("srl_stopbits: Only 1 or 2 stop bits are supported..."); + return false; + } + + if (SetCommState (fd,&config) == FALSE) + { + error ("srl_stopbits: error setting stop bits: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +int +octave_serial::get_stopbits (void) const +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + if (config.StopBits == TWOSTOPBITS) + return 2; + else + return 1; +} + +int +octave_serial::set_bytesize (unsigned short bytesize) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + if(bytesize < 5 || bytesize > 8) + { + error ("srl_bytesize: expecting value between [5..8]..."); + return false; + } + + config.ByteSize = bytesize; + + if (SetCommState (fd, &config) == FALSE) + { + error ("serial: error setting byte size: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +int +octave_serial::get_bytesize (void) const +{ + if (! fd_is_valid ()) + { + error("serial: Interface must be opened first..."); + return -1; + } + + return config.ByteSize; +} + +int +octave_serial::set_baudrate (unsigned int baud) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + DWORD old_baud = config.BaudRate; + + config.BaudRate = baud; + + if (SetCommState (fd, &config) == FALSE) + { + error ("serial: error setting baud rate: %s\n", winerror (errno).c_str ()); + config.BaudRate = old_baud; + return false; + } + + return true; +} + +int +octave_serial::get_baudrate (void) const +{ + if (! fd_is_valid ()) + { + error("serial: Interface must be opened first..."); + return -1; + } + + return config.BaudRate; +} + +int +octave_serial::flush (unsigned short queue_selector) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + int flag; + + switch (queue_selector) + { + case 0: flag = PURGE_TXCLEAR; break; + case 1: flag = PURGE_RXCLEAR; break; + case 2: flag = PURGE_RXCLEAR|PURGE_TXCLEAR; break; + default: + error ("srl_flush: only [0..2] values are accepted..."); + return false; + } + + if (PurgeComm (fd,flag) == FALSE) + return -1; + else + return true; +} + +int +octave_serial::sendbreak (unsigned short ms) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + if (ms > 5000) + ms = 5000; + + if(SetCommBreak(fd) == TRUE) + { + Sleep(ms); + + ClearCommBreak(fd); + + return true; + } + + return false; +} + +int +octave_serial::set_parity (const std::string &newparity) +{ + if (! fd_is_valid ()) + { + error ("serial: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string parity = newparity; + std::transform (parity.begin (), parity.end (), parity.begin (), ::tolower); + + /* + * PARENB Enable parity generation on output and parity checking for input. + * PARODD If set, then parity for input and output is odd; otherwise even parity is used. + */ + + if (parity == "n" || parity == "none") + { + // Disable parity generation/checking + config.Parity = NOPARITY; + } + else if (parity == "e" || parity == "even") + { + // Enable parity generation/checking + config.Parity = EVENPARITY; + } + else if (parity == "o" || parity == "odd") + { + config.Parity = ODDPARITY; + } + else + { + error ("srl_parity: Only [N]one, [E]ven or [O]dd parities are supported..."); + return false; + } + + if (SetCommState (fd, &config) == FALSE) + { + error ("srl_parity: error setting parity: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +std::string +octave_serial::get_parity (void) const +{ + if(config.Parity == NOPARITY) + return "None"; + else if(config.Parity == ODDPARITY) + return "Odd"; + else + return "Even"; +} + +void +octave_serial::get_control_line_status (void) +{ + if (! fd_is_valid()) + { + error ("serial: Interface must be opened first..."); + return; + } + + GetCommState (fd, &config); + GetCommModemStatus (fd, &status); +} + +bool +octave_serial::get_control_line (const std::string &control_signal) +{ + get_control_line_status (); + + if (control_signal == "DTR") + return (config.fDtrControl == DTR_CONTROL_ENABLE); + else if (control_signal == "RTS") + return (config.fRtsControl == RTS_CONTROL_ENABLE); + else if (control_signal == "CTS") + return (status & MS_CTS_ON); + else if (control_signal == "DSR") + return (status & MS_DSR_ON); + else if (control_signal == "CD") + return (status & MS_RLSD_ON); + else if (control_signal == "RI") + return (status & MS_RING_ON); + else + error("serial: Unknown control signal..."); + return false; +} + +void +octave_serial::set_control_line (const std::string &control_signal, bool set) +{ + get_control_line_status (); + + int signal; + + if (control_signal == "DTR") + { + if(set) + config.fDtrControl = DTR_CONTROL_ENABLE; + else + config.fDtrControl = DTR_CONTROL_DISABLE; + } + else if (control_signal == "RTS") + { + if(set) + config.fRtsControl = RTS_CONTROL_ENABLE; + else + config.fRtsControl = RTS_CONTROL_DISABLE; + } + else + { + error("serial: Unknown control signal..."); + return; + } + + SetCommState (fd, &config); +} + +bool +octave_serial::fd_is_valid (void) const +{ + return (fd != INVALID_HANDLE_VALUE); +} + +void +octave_serial::close (void) +{ + if (fd_is_valid ()) + { + CloseHandle(fd); + fd = INVALID_HANDLE_VALUE; + } +} + +int +octave_serial::get_bytesavailable (void) const +{ + int available = 0; + if (fd_is_valid ()) + { + COMSTAT stats; + DWORD err; + if (ClearCommError (fd, &err, &stats)) + available = stats.cbInQue; + } + return available; +} +#endif diff --git a/src/serial/serial_class_win32.h b/src/serial/serial_class_win32.h new file mode 100644 index 0000000..238b869 --- /dev/null +++ b/src/serial/serial_class_win32.h @@ -0,0 +1,76 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef SERIAL_CLASS_WIN32_H +#define SERIAL_CLASS_WIN32_H + +#include +#include + +class octave_serial : public octave_serial_common +{ +public: + octave_serial(void); + ~octave_serial(void); + + int write(const std::string& /* buffer */); + int write(uint8_t* /* buffer */, unsigned int /* buffer size */); + + int read(uint8_t* /* buffer */, unsigned int /* buffer size */); + + void open(const std::string& /* path */); + void close(void); + + int flush(unsigned short /* stream select */); + + int sendbreak(unsigned short /* breaktime */); + + int set_timeout(short /* timeout */); + int get_timeout(void) const; + + int set_baudrate(unsigned int /* baudrate */); + int get_baudrate() const; + + int set_bytesize(unsigned short /* bytesize */); + int get_bytesize(void) const; + + int set_parity(const std::string& /* parity */); + std::string get_parity(void) const; + + int set_stopbits(unsigned short /* stop bits */); + int get_stopbits(void) const; + + bool get_control_line(const std::string &); + void set_control_line(const std::string&, bool); + + int get_bytesavailable(void) const; +private: + HANDLE fd; + DWORD status; + DCB config; + COMMTIMEOUTS timeouts; + + volatile bool blocking_read; + short timeout; + + void get_control_line_status(void); + + bool fd_is_valid(void) const; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/serial/srl_read.cc b/src/serial/srl_read.cc new file mode 100644 index 0000000..a37fafb --- /dev/null +++ b/src/serial/srl_read.cc @@ -0,0 +1,95 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include + +#include + +#include "serial_class.h" + +#endif + +// PKG_ADD: autoload ("srl_read", "serial.oct"); +DEFUN_DLD (srl_read, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } srl_read (@var{serial}, @var{n})\n \ +\n\ +Read from serial interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{serial} - instance of @var{octave_serial} class.@*\ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +@subsubheading Outputs\n \ +The srl_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_serial::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 0; + + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("srl_read: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_serial* serial = NULL; + + const octave_base_value& rep = args (0).get_rep (); + serial = &((octave_serial &)rep); + + // Read data + int bytes_read = serial->read (buffer, buffer_len); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data (dim_vector (1, bytes_read)); + + for (int i = 0; i < bytes_read; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = bytes_read; + + return return_list; +#endif +} diff --git a/src/serial/srl_write.cc b/src/serial/srl_write.cc new file mode 100644 index 0000000..aa511e5 --- /dev/null +++ b/src/serial/srl_write.cc @@ -0,0 +1,86 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serial_class.h" +#endif + +// PKG_ADD: autoload ("srl_write", "serial.oct"); +DEFUN_DLD (srl_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } srl_write (@var{serial}, @var{data})\n \ +\n\ +Write data to a serial interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{serial} - instance of @var{octave_serial} class.@*\ +@var{data} - data to be written to the serial interface. Can be either of String or uint8 type.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, srl_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error ("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_serial::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_serial *serial = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + serial = &((octave_serial &)rep); + + if (args (1).is_string ()) // String + { + retval = serial->write (args (1).string_value ()); + } + else if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("srl_write: cannot allocate requested memory"); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data(i)); + + retval = serial->write (buf, data.numel ()); + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/serialport/Makefile.in b/src/serialport/Makefile.in new file mode 100644 index 0000000..528d782 --- /dev/null +++ b/src/serialport/Makefile.in @@ -0,0 +1,11 @@ +OCT := ../serialport.oct +OBJ := serialport.o __srlp_write__.o __srlp_read__.o __srlp_properties__.o __serialport_pkg_lock__.o serialport_class.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ +ifeq ("@BUILD_FOR_WINDOWS@","1") + OBJ += serialport_class_win32.o +else + OBJ += serialport_class_lin.o +endif + +include ../common.mk diff --git a/src/serialport/__serialport_pkg_lock__.cc b/src/serialport/__serialport_pkg_lock__.cc new file mode 100644 index 0000000..b8d4a4d --- /dev/null +++ b/src/serialport/__serialport_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__serialport_pkg_lock__", "serialport.oct"); +// PKG_ADD: __serialport_pkg_lock__(1); +// PKG_DEL: __serialport_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__serialport_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__serialport_pkg_lock__")) + interp.munlock("__serialport_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__serialport_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/serialport/__srlp_properties__.cc b/src/serialport/__srlp_properties__.cc new file mode 100644 index 0000000..4eae1d8 --- /dev/null +++ b/src/serialport/__srlp_properties__.cc @@ -0,0 +1,441 @@ +// Copyright (C) 2019-2020 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serialport_class.h" +#endif + +#ifdef BUILD_SERIAL + +octave_value_list srlp_flush (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Default arguments + int queue_selector = 2; // Input and Output + + if (args.length () > 0) + { + if (!(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + queue_selector = args (0).int_value (); + } + + serialport->flush (queue_selector); + + return octave_value (); +} + +octave_value_list srlp_break (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Default arguments + int ms = 2; // Input and Output + + if (args.length () > 0) + { + if (!(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer"); + + ms = args (0).int_value (); + } + + serialport->sendbreak (ms); + + return octave_value (); +} + +octave_value_list srlp_timeout (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new timeout + if (args.length () > 0) + { + if ( !(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serialport->set_timeout (args (0).double_value ()); + + return octave_value (); // Should it return by default? + } + + // Returning current timeout + return octave_value (serialport->get_timeout ()); +} + +octave_value_list srlp_userdata (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new timeout + if (args.length () > 0) + { + if ( !(args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serialport->set_userdata (args (0)); + + return octave_value (); // Should it return by default? + } + + // Returning current timeout + return octave_value (serialport->get_userdata ()); +} + +octave_value_list srlp_flowcontrol (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new timeout + if (args.length () > 0) + { + if ( !(args (0).is_string() )) + (*current_liboctave_error_handler) ("argument must be a string"); + + serialport->set_flowcontrol (args (0).string_value()); + + return octave_value (); // Should it return by default? + } + + return octave_value (serialport->get_flowcontrol ()); +} + +octave_value_list srlp_terminator (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + // Setting new timeout + if (args.length () == 1) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + serialport->set_input_terminator (args (0).string_value()); + serialport->set_output_terminator (args (0).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () == 2) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + if ( !(args (1).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + // could be 1 or 2 args here + + serialport->set_input_terminator (args (0).string_value()); + serialport->set_output_terminator (args (1).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () > 2) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // may have a single terminator or a start and stop + std::string in = serialport->get_input_terminator (); + std::string out = serialport->get_output_terminator (); + + if (in == out) + return octave_value (in); + else + { + octave_value_list ret; + ret(0) = octave_value(in); + ret(1) = octave_value(out); + return octave_value (ret); + } +} + +octave_value_list srlp_byteorder (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new timeout + if (args.length () > 0) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + serialport->set_byteorder (args (0).string_value()); + + return octave_value (); // Should it return by default? + } + + return octave_value (serialport->get_byteorder ()); +} + + +octave_value_list srlp_numbytesavailable (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Returning bytes available + return octave_value (serialport->get_numbytesavailable ()); +} + +octave_value_list srlp_numbyteswritten (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Returning bytes available + return octave_value (serialport->get_numbyteswritten ()); +} + +octave_value_list srlp_port (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("read only value"); + + // Returning bytes available + return octave_value (serialport->get_port ()); +} + +octave_value_list srlp_baudrate (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new baudrate + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ())) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serialport->set_baudrate (args (0).int_value ()); + + return octave_value (); + } + + // Returning current baud rate + return octave_value (serialport->get_baudrate ()); +} + +octave_value_list srlp_databits (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new byte size + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serialport->set_databits (args (0).int_value ()); + + return octave_value (); + } + + // Returning current byte size + return octave_value (serialport->get_databits ()); +} + +octave_value_list srlp_stopbits (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length() > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new stop bits + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT ()) ) + (*current_liboctave_error_handler) ("argument must be integer or float"); + + serialport->set_stopbits(args (0).int_value ()); + + return octave_value (); + } + + // Returning current stop bits + return octave_value (serialport->get_stopbits ()); +} + +octave_value_list srlp_parity (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting new parity + if (args.length () > 0) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be string"); + + serialport->set_parity (args (0).string_value()); + + return octave_value (); + } + + // Returning current parity + return octave_value (serialport->get_parity ()); +} + +octave_value_list srlp_requesttosend (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + // Setting RTS + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT () || args(0).OV_ISLOGICAL ()) ) + (*current_liboctave_error_handler) ("argument must be boolean or a number"); + + int onoff = args (0).int_value (); + if (onoff) + serialport->set_control_line ("RTS", true); + else + serialport->set_control_line ("RTS", false); + } + + // Returning RTS + if (serialport->get_control_line ("RTS")) + return octave_value (1); + + return octave_value (0); +} + +octave_value_list srlp_dataterminalready (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 1) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + std::string onoff = ""; + + // Setting DTR + if (args.length () > 0) + { + if (! (args (0).OV_ISINTEGER () || args (0).OV_ISFLOAT () || args(0).OV_ISLOGICAL ()) ) + (*current_liboctave_error_handler) ("argument must be boolean or a number"); + + int onoff = args (0).int_value (); + if (onoff) + serialport->set_control_line ("DTR", true); + else + serialport->set_control_line ("DTR", false); + } + + // Returning DTR + if (serialport->get_control_line ("DTR")) + return octave_value (1); + + return octave_value (0); +} + +octave_value_list srlp_pinstatus (octave_serialport* serialport, const octave_value_list& args, int nargout) +{ + if (args.length () > 0) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + octave_scalar_map res; + + res.assign ("CarrierDetect", serialport->get_control_line ("CD") ? + octave_value (1) : + octave_value (0)); + + res.assign ("ClearToSend", serialport->get_control_line ("CTS") ? + octave_value (1) : + octave_value (0)); + + res.assign ("DataSetReady", serialport->get_control_line ("DSR") ? + octave_value (1) : + octave_value (0)); + + res.assign ("RingIndicator", serialport->get_control_line ("RI") ? + octave_value (0) : + octave_value (1)); + + return octave_value (res); +} +#endif + +// PKG_ADD: autoload ("__srlp_properties__", "serialport.oct"); +DEFUN_DLD (__srlp_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __srlp_properties__ (@var{octave_serialport}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_SERIAL + + if (args.length () < 2 || args (0).type_id () != octave_serialport::static_type_id () || !args (1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args (0).get_rep (); + octave_serialport* serialport = &((octave_serialport &)rep); + + std::string property = args (1).string_value (); + std::transform (property.begin (), property.end (), property.begin (), ::tolower); + + octave_value_list args2 = args.slice (2, args.length ()-2); + + if (property == "port") + return srlp_port (serialport, args2, nargout); + else if (property == "baudrate") + return srlp_baudrate (serialport, args2, nargout); + else if (property == "numbytesavailable") + return srlp_numbytesavailable (serialport, args2, nargout); + else if (property == "numbyteswritten") + return srlp_numbyteswritten (serialport, args2, nargout); + else if (property == "byteorder") + return srlp_byteorder (serialport, args2, nargout); + else if (property == "databits") + return srlp_databits (serialport, args2, nargout); + else if (property == "stopbits") + return srlp_stopbits (serialport, args2, nargout); + else if (property == "parity") + return srlp_parity (serialport, args2, nargout); + else if (property == "flowcontrol") + return srlp_flowcontrol (serialport, args2, nargout); + else if (property == "timeout") + return srlp_timeout (serialport, args2, nargout); + else if (property == "userdata") + return srlp_userdata (serialport, args2, nargout); + else if (property == "terminator") + return srlp_terminator (serialport, args2, nargout); + // internals + else if (property == "__flush__") + return srlp_flush (serialport, args2, nargout); + else if (property == "__break__") + return srlp_break (serialport, args2, nargout); + else if (property == "__pinstatus__") + return srlp_pinstatus (serialport, args2, nargout); + else if (property == "__requesttosend__") + return srlp_requesttosend (serialport, args2, nargout); + else if (property == "__dataterminalready__") + return srlp_dataterminalready (serialport, args2, nargout); + else + (*current_liboctave_error_handler) ("wrong keyword"); +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the SERIAL interface"); +} diff --git a/src/serialport/__srlp_read__.cc b/src/serialport/__srlp_read__.cc new file mode 100644 index 0000000..fad224a --- /dev/null +++ b/src/serialport/__srlp_read__.cc @@ -0,0 +1,95 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include + +#include + +#include "serialport_class.h" + +#endif + +// PKG_ADD: autoload ("__srlp_read__", "serialport.oct"); +DEFUN_DLD (__srlp_read__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } __srlp_read__ (@var{serial}, @var{n})\n \ +\n\ +Read from serialport interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{serial} - instance of @var{octave_serialport} class.@*\ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +@subsubheading Outputs\n \ +The __srlp_read__() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_serialport::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 0; + + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("__srlp_read__: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_serialport* serial = NULL; + + const octave_base_value& rep = args (0).get_rep (); + serial = &((octave_serialport &)rep); + + // Read data + int bytes_read = serial->read (buffer, buffer_len); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data (dim_vector (1, bytes_read)); + + for (int i = 0; i < bytes_read; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = bytes_read; + + return return_list; +#endif +} diff --git a/src/serialport/__srlp_write__.cc b/src/serialport/__srlp_write__.cc new file mode 100644 index 0000000..de40f9a --- /dev/null +++ b/src/serialport/__srlp_write__.cc @@ -0,0 +1,86 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serialport_class.h" +#endif + +// PKG_ADD: autoload ("__srlp_write__", "serialport.oct"); +DEFUN_DLD (__srlp_write__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } __srlp_write__ (@var{serial}, @var{data})\n \ +\n\ +Write data to a serialport interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{serial} - instance of @var{octave_serialport} class.@*\ +@var{data} - data to be written to the serialport interface. Can be either of String or uint8 type.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, __srlp_write__() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error ("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_serialport::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_serialport *serial = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + serial = &((octave_serialport &)rep); + + if (args (1).is_string ()) // String + { + retval = serial->write (args (1).string_value ()); + } + else if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("__srlp_write__: cannot allocate requested memory"); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data(i)); + + retval = serial->write (buf, data.numel ()); + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/serialport/serialport.cc b/src/serialport/serialport.cc new file mode 100644 index 0000000..89c37d9 --- /dev/null +++ b/src/serialport/serialport.cc @@ -0,0 +1,258 @@ +// Copyright (C) 2017-2020 John Donoghue +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include +#include + +#include "serialport_class.h" + +#endif + +// PKG_ADD: autoload ("serialport", "serialport.oct"); +DEFUN_DLD (serialport, args, nargout, + "-*- texinfo -*-\n \ +@deftypefn {Loadable Function} {@var{serial} = } serialport ([@var{path}], [@var{baudrate}])\n \ +@deftypefnx {Loadable Function} {@var{serial} = } serialport ([@var{path}], [@var{propname}, @var{propvalue}])\n \ +\n\ +Open serial port interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{path} - the interface path of type String. @*\n \ +@var{baudrate} - the baudrate of interface.@*\n \ +@var{propname},@var{propvalue} - property name/value pairs.\n \ +\n \ +Known input properties:\n \ +@table @asis\n \ +@item BaudRate\n \ +Numeric baudrate value\n \ +@item Timeout\n \ +Numeric timeout value in seconds or -1 to wait forever\n \ +@item StopBits\n \ +number of stopbits to use\n \ +@item Parity\n \ +Parity setting 'none', 'even', 'odd'\n \ +@item DataBits\n \ +Number of bits to a byte (5 to 8)\n \ +@item FlowControl\n \ +Number of bits to a byte 'none', 'hardware', 'software'\n \ +@end table\n \ +\n\ +@subsubheading Outputs\n \ +The serialport() shall return an instance of @var{octave_serialport} class as the result @var{serial}.\n \ +\n \ +@subsubheading Properties\n \ +The serial object has the following public properties:\n \ +@table @asis\n \ +@item Name\n \ +name assigned to the object\n \ +@item Type\n \ +instrument type 'serial' (readonly)\n \ +@item Port\n \ +OS specific port name (readonly)\n \ +@item Status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item Timeout\n \ +timeout value used for waiting for data\n \ +@item NumBytesAvailable\n \ +number of bytes currently available to read (readonly)\n \ +@item NumBytesWritten\n \ +number of bytes written (readonly)\n \ +@item StopBits\n \ +number of stopbits to use\n \ +@item Parity\n \ +Parity setting 'none', 'even', 'odd'\n \ +@item DataBits\n \ +Number of bits to a byte (5 to 8)\n \ +@item BaudRate\n \ +Baudrate setting\n \ +@item FlowControl\n \ +Number of bits to a byte 'none', 'hardware', 'software'\n \ +@item PinStatus\n \ +current state of pins (readonly)\n \ +@item UserData\n \ +user defined data\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_SERIAL + error ("serial: Your system doesn't support the SERIAL interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + std::string path; + unsigned int baud_rate = 115200; + double timeout = -1; + unsigned short databits = 8; + std::string parity("N"); + std::string flow("none"); + unsigned short stopbits = 1; + // Parse the function arguments + if ((args.length () == 0) || !args (0).is_string ()) + { + print_usage (); + return octave_value (); + } + + path = args (0).string_value (); + + baud_rate = 115200; + + // baudrate + if (args.length() == 2) + { + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + baud_rate = args (1).int_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + else if (args.length() > 2 && (args.length() & 1) == 0) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + else if (args.length() > 2) + { + // go through the properties + for(int i=1;iopen (path); + + retval->set_baudrate (baud_rate); + retval->set_timeout (timeout); + retval->set_parity (parity); + retval->set_flowcontrol (flow); + retval->set_databits (databits); + retval->set_stopbits (stopbits); + + //retval->flush (2); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "serial")) +%! fail ("a = serialport ()", "Invalid call to serial"); +%! fail ("a = serialport ('noport', 'a')", "Invalid call to serial"); +%! fail ("a = serialport ('noport', 9600, 1)", "Expected property name string"); +%! fail ("a = serialport ('noport', 9600, 1, 1)", "Expected property name/value pairs"); +%! else +%! fail ("serialport ()", "serial: Your system doesn't support the serial interface"); +%! endif +#endif diff --git a/src/serialport/serialport_class.cc b/src/serialport/serialport_class.cc new file mode 100644 index 0000000..42c04fe --- /dev/null +++ b/src/serialport/serialport_class.cc @@ -0,0 +1,196 @@ +// Copyright (C) 2019-2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include "serialport_class.h" +#include +#include +#include + +octave_serialport_common::octave_serialport_common () + : fieldnames(13) +{ + byteswritten = 0; + userData = Matrix (); + + interminator = "lf"; + outterminator = "lf"; + byteOrder = "little-endian"; + + fieldnames[0] = "BaudRate"; + fieldnames[1] = "DataBits"; + fieldnames[3] = "Parity"; + fieldnames[4] = "StopBits"; + fieldnames[5] = "Timeout"; + fieldnames[6] = "NumBytesAvailable"; + fieldnames[7] = "NumBytesWritten"; + fieldnames[8] = "Port"; + fieldnames[9] = "FlowControl"; + fieldnames[10] = "UserData"; + fieldnames[11] = "ByteOrder"; + fieldnames[12] = "Terminator"; +} + +bool octave_serialport_common::has_property(const std::string &name) const +{ + for (octave_idx_type i=0; i& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_serialport object cannot be indexed with %c", type[0]); + return retval; + case '.': + { + std::string property = (idx.front ()) (0).string_value (); + if (!has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + else + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__srlp_properties__"), ovl, 1); + } + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_serialport_common::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_serialport object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + std::string property = (idx.front ()) (0).string_value (); + if (! has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + else + { + + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__srlp_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + } + count++; + retval = octave_value (this); + } + else + { + error ("octave_serialport invalid index"); + } + + } + return retval; +} + +int +octave_serialport_common::set_byteorder(const std::string& neworder) +{ + std::string order = neworder; + std::transform (order.begin (), order.end (), order.begin (), ::tolower); + if (order == "big" || order == "big-endian") + byteOrder = "big-endian"; + else if (order == "little" || order == "little-endian") + byteOrder = "little-endian"; + else + error ("octave_serialport invalid byteorder"); + + return 1; +} + +int +octave_serialport_common::set_input_terminator(const std::string& t) +{ + std::string term = t; + std::transform (term.begin (), term.end (), term.begin (), ::tolower); + if (term != "lf" && term != "cr" && term != "cr/lf") + error ("octave_serialport invalid input terminator"); + else + interminator = term; + + return 1; +} + +int +octave_serialport_common::set_output_terminator(const std::string& t) +{ + std::string term = t; + std::transform (term.begin (), term.end (), term.begin (), ::tolower); + if (term != "lf" && term != "cr" && term != "cr/lf") + error ("octave_serialport invalid output terminator"); + else + outterminator = term; + + return 1; +} + + +#endif diff --git a/src/serialport/serialport_class.h b/src/serialport/serialport_class.h new file mode 100644 index 0000000..e5c3d09 --- /dev/null +++ b/src/serialport/serialport_class.h @@ -0,0 +1,207 @@ +// Copyright (C) 2019 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 . + +#ifndef SERIALPORT_CLASS_H +#define SERIALPORT_CLASS_H + +#include + +#include + +#define BITMASK_SET(x,y) ((x) |= (y)) +#define BITMASK_CLEAR(x,y) ((x) &= (~(y))) +#define BITMASK_TOGGLE(x,y) ((x) ^= (y)) +#define BITMASK_CHECK(x,y) ((x) & (y)) +#define BITMASK_CHECK_VALUE(x,y,z) (((x) & (y)) == (z)) + +#define CONCAT2X(x,y) x ## y +#define CONCAT2(x,y) CONCAT2X(x,y) + +#define BINOPDECL(name, a1, a2) \ + static octave_value \ + CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2) + +#define CAST_BINOP_ARGS(t1, t2) \ + t1 v1 = dynamic_cast (a1); \ + t2 v2 = dynamic_cast (a2) + + +#define DEFBINOP_CLASS_OP(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \ + return octave_value \ + (&v1 op &v2); \ + } + +#ifdef OCTAVE__NEW_REGISTER_OP +#define INSTALL_BINOP(op, t1, t2, f) \ + {octave::type_info& ti = octave::interpreter::the_interpreter ()->get_type_info (); \ + ti.register_binary_op \ + (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ + CONCAT2(oct_binop_, f));} +#else +#define INSTALL_BINOP(op, t1, t2, f) \ + octave_value_typeinfo::register_binary_op \ + (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ + CONCAT2(oct_binop_, f)); +#endif + +class octave_serialport_common : public octave_base_value +{ +protected: + octave_serialport_common(); + + bool has_property(const std::string &name) const; +public: + + // os dependent functions + virtual bool fd_is_valid() const = 0; + virtual double get_timeout() const = 0; + virtual int get_baudrate() const = 0; + virtual int get_databits() const = 0; + virtual std::string get_parity() const = 0; + virtual int get_stopbits() const = 0; + virtual int get_numbytesavailable() const = 0; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true;} + // 4.4+ + bool isobject (void) const { return true;} + + octave_base_value * unique_clone (void) { count++; return this;} + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + void print (std::ostream& os, bool pr_as_read_syntax = false) + { + print_raw(os, pr_as_read_syntax); + newline(os); + } + + void print (std::ostream& os, bool pr_as_read_syntax = false) const + { + print_raw(os, pr_as_read_syntax); + newline(os); + } + + void print_raw (std::ostream& os, bool pr_as_read_syntax) const + { + os << " Serial Port Object " << this->get_name(); newline(os); + //os << " status: " << this->get_status(); newline(os); + if (this->fd_is_valid()) + { + os << " Port: " << this->portPath; newline(os); + os << " BaudRate: " << this->get_baudrate(); newline(os); + os << " Parity: " << this->get_parity(); newline(os); + os << " DataBits: " << this->get_databits(); newline(os); + os << " StopBits: " << this->get_stopbits(); newline(os); + os << " Timeout: " << this->get_timeout(); newline(os); + //os << "Mode: " << blockmode; newline(os); + } + } + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + std::string get_type () const + { + return "serialport"; + } + + std::string get_port () const + { + return portPath; + } + + std::string get_name () const + { + return name; + } + + void set_name (const std::string &newname) + { + name = newname; + } + + unsigned long get_numbyteswritten() const + { + return byteswritten; + } + + octave_value get_userdata () const + { + return userData; + } + + void set_userdata (const octave_value &newv) + { + userData = newv; + } + + int set_byteorder(const std::string& /* order */); + + std::string get_byteorder() const + { + return byteOrder; + } + + int set_input_terminator(const std::string& /* term */); + int set_output_terminator(const std::string& /* term */); + + std::string get_input_terminator() const + { + return interminator; + } + + std::string get_output_terminator() const + { + return outterminator; + } + +protected: + string_vector fieldnames; + unsigned long byteswritten; + + std::string name; + std::string portPath; + std::string byteOrder; + std::string interminator; + std::string outterminator; + octave_value userData; +}; + + +#ifdef __WIN32__ + #include "serialport_class_win32.h" +#else + #include "serialport_class_lin.h" +#endif + +#endif diff --git a/src/serialport/serialport_class_lin.cc b/src/serialport/serialport_class_lin.cc new file mode 100644 index 0000000..ce34aa6 --- /dev/null +++ b/src/serialport/serialport_class_lin.cc @@ -0,0 +1,801 @@ +// Copyright (C) 2019 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serialport_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_serialport, "octave_serialport", "octave_serialport"); + +octave_serialport::octave_serialport (void) +: fd (-1) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } +} + +void +octave_serialport::open (const std::string &path) +{ + int flags = O_RDWR | O_NOCTTY | O_SYNC | O_NDELAY; + // O_SYNC - All writes immediately effective, no buffering + // O_NOCTTY - Do not make serialport terminal the controlling terminal for the process + // O_NDELAY - Do not care what state the DCD signal line is in. Used for open only, later disabled. + + fd = ::open (path.c_str (), flags); + portPath = path; + name = "Serial-" + portPath; + + if (fd_is_valid ()) + { + // Check whether fd is an open file descriptor referring to a terminal + if(! isatty (fd)) + { + error("serialport: Interface does not refer to a terminal: %s\n", strerror (errno)); + octave_serialport::close (); + return; + } + + if (tcgetattr (fd, &config) < 0) + { + error ("serialport: Failed to get terminal attributes: %s\n", strerror (errno)); + octave_serialport::close (); + return; + } + + // Clear all settings + config.c_iflag = 0; // Input modes + config.c_oflag = 0; // Output modes + config.c_cflag = CS8 | CREAD | CLOCAL; // Control modes, 8n1 + config.c_lflag = 0; // Local modes + config.c_cc[VMIN] = 0; + config.c_cc[VTIME] = 5; + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport: Failed to set default terminal attributes: %s\n", strerror (errno)); + octave_serialport::close (); + return; + } + + // Disable NDELAY + if (fcntl (fd, F_SETFL, 0) < 0) + { + error ("serialport: Failed to disable NDELAY flag: %s\n", strerror (errno)); + octave_serialport::close (); + return; + } + + timeout = -1; + blocking_read = true; + } + else + { + error ("serialport: Error opening the interface: %s\n", strerror (errno)); + return; + } +} + +octave_serialport::~octave_serialport (void) +{ + octave_serialport::close(); +} + +int +octave_serialport::read (uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + double maxwait = timeout; + + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + read_retval = ::read (fd, (void *)(buf + bytes_read), len - bytes_read); + + if (read_retval < 0) + { + error ("serialport: Error while reading: %s\n", strerror (errno)); + break; + } + + bytes_read += read_retval; + + // Timeout while in non-blocking mode + if (read_retval == 0 && !blocking_read) + { + maxwait -= (double)config.c_cc[VTIME]/10.0; + + // actual timeout + if (maxwait <= 0) + break; + } + } + + return bytes_read; +} + +int +octave_serialport::write (const std::string &str) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + + int ret = ::write (fd, str.c_str (), str.length ()); + if (ret > 0) + byteswritten += ret; + return ret; +} + +int +octave_serialport::write(uint8_t *buf, unsigned int len) +{ + if (!fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + int ret = ::write (fd, buf, len); + if (ret > 0) + byteswritten += ret; + return ret; +} + +int +octave_serialport::set_timeout (double newtimeout) +{ + if (! fd_is_valid ()) + { + error("serialport: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1) + { + error("serialport: timeout value must be between -1 or greater"); + return -1; + } + + timeout = newtimeout; + + // into 10ths of a second + newtimeout *= 10; + + // Disable custom timeout, enable blocking read + if (newtimeout < 0) + { + blocking_read = true; + newtimeout = 5; + } + // Enable custom timeout, disable blocking read + else + { + blocking_read = false; + if(newtimeout > 10) newtimeout = 5; + if(newtimeout < 1) newtimeout = 1; + } + + + 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) + { + error ("serialport: error setting timeout..."); + return -1; + } + + return 1; +} + +double +octave_serialport::get_timeout (void) const +{ + if (blocking_read) + return -1; + else + return timeout; +} + +int +octave_serialport::set_stopbits (unsigned short stopbits) +{ + if (!fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + /* + * CSTOPB Send two stop bits, else one. + */ + + if (stopbits == 1) + { + // Set to one stop bit + BITMASK_CLEAR (config.c_cflag, CSTOPB); + } + else if (stopbits == 2) + { + // Set to two stop bits + BITMASK_SET (config.c_cflag, CSTOPB); + } + else + { + error ("serialport: Only 1 or 2 stop bits are supported..."); + return false; + } + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport: error setting stop bits: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serialport::get_stopbits (void) const +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + if (BITMASK_CHECK (config.c_cflag, CSTOPB)) + return 2; + else + return 1; +} + +int +octave_serialport::set_databits (unsigned short bytesize) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + tcflag_t c_bytesize = 0; + + switch (bytesize) + { + case 5: c_bytesize = CS5; break; + case 6: c_bytesize = CS6; break; + case 7: c_bytesize = CS7; break; + case 8: c_bytesize = CS8; break; + + default: + error ("serialport.databits: expecting value between [5..8]..."); + return false; + } + + // Clear bitmask CSIZE + BITMASK_CLEAR (config.c_cflag, CSIZE); + + // Apply new + BITMASK_SET (config.c_cflag, c_bytesize); + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport.databits: error setting data size: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serialport::get_databits (void) const +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + int retval = -1; + + if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS5)) + retval = 5; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS6)) + retval = 6; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS7)) + retval = 7; + else if (BITMASK_CHECK_VALUE (config.c_cflag, CSIZE, CS8)) + retval = 8; + + return retval; +} + +int +octave_serialport::set_baudrate (unsigned int baud) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + speed_t baud_rate = 0; + + switch (baud) + { + case 0: + baud_rate = B0; break; + case 50: + baud_rate = B50; break; + case 75: + baud_rate = B75; break; + case 110: + baud_rate = B110; break; + case 134: + baud_rate = B134; break; + case 150: + baud_rate = B150; break; + case 200: + baud_rate = B200; break; + case 300: + baud_rate = B300; break; + case 600: + baud_rate = B600; break; + case 1200: + baud_rate = B1200; break; + case 1800: + baud_rate = B1800; break; + case 2400: + baud_rate = B2400; break; + case 4800: + baud_rate = B4800; break; + case 9600: + baud_rate = B9600; break; + case 19200: + baud_rate = B19200; break; + case 38400: + baud_rate = B38400; break; +#ifdef B57600 + case 57600: + baud_rate = B57600; break; +#endif +#ifdef B115200 + case 115200: + baud_rate = B115200; break; +#endif +#ifdef B230400 + case 230400: + baud_rate = B230400; break; +#endif +#ifdef B460800 + case 460800: + baud_rate = B460800; break; +#endif +#ifdef B500000 + case 500000: + baud_rate = B500000; break; +#endif +#ifdef B576000 + case 576000: + baud_rate = B576000; break; +#endif +#ifdef B921600 + case 921600: + baud_rate = B921600; break; +#endif +#ifdef B1000000 + case 1000000: + baud_rate = B1000000; break; +#endif +#ifdef B1152000 + case 1152000: + baud_rate = B1152000; break; +#endif +#ifdef B2000000 + case 2000000: + baud_rate = B2000000; break; +#endif +#ifdef B3000000 + case 3000000: + baud_rate = B3000000; break; +#endif +#ifdef B3500000 + case 3500000: + baud_rate = B3500000; break; +#endif +#ifdef B4000000 + case 4000000: + baud_rate = B4000000; break; +#endif + default: + error ("serialport: baud rate not supported..."); + return false; + } + + cfsetispeed (&config, baud_rate); + cfsetospeed (&config, baud_rate); + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport: error setting baud rate: %s\n", strerror (errno)); + return false; + } + + return true; +} + +int +octave_serialport::get_baudrate (void) const +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + int retval = -1; + + speed_t baudrate = cfgetispeed (&config); + + if (baudrate == B0) + retval = 0; + else if (baudrate == B50) + retval = 50; + else if (baudrate == B75) + retval = 75; + else if (baudrate == B110) + retval = 110; + else if (baudrate == B134) + retval = 134; + else if (baudrate == B150) + retval = 150; + else if (baudrate == B200) + retval = 200; + else if (baudrate == B300) + retval = 300; + else if (baudrate == B600) + retval = 600; + else if (baudrate == B1200) + retval = 1200; + else if (baudrate == B1800) + retval = 1800; + else if (baudrate == B2400) + retval = 2400; + else if (baudrate == B4800) + retval = 4800; + else if (baudrate == B9600) + retval = 9600; + else if (baudrate == B19200) + retval = 19200; + else if (baudrate == B38400) + retval = 38400; + else if (baudrate == B57600) + retval = 57600; + else if (baudrate == B115200) + retval = 115200; + else if (baudrate == B230400) + retval = 230400; + + return retval; +} + +int +octave_serialport::flush (unsigned short queue_selector) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + /* + * TCIOFLUSH Flush both pending input and untransmitted output. + * TCOFLUSH Flush untransmitted output. + * TCIFLUSH Flush pending input. + */ + + int flag; + + switch (queue_selector) + { + case 0: flag = TCOFLUSH; break; + case 1: flag = TCIFLUSH; break; + case 2: flag = TCIOFLUSH; break; + default: + error("serialport: only [0..2] values are accepted..."); + return false; + } + + return ::tcflush (fd, flag); +} + +int +octave_serialport::sendbreak (unsigned short ms) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + return ::tcsendbreak (fd, ms); +} + +int +octave_serialport::set_parity (const std::string &newparity) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string parity = newparity; + std::transform (parity.begin (), parity.end (), parity.begin (), ::tolower); + + /* + * PARENB Enable parity generation on output and parity checking for input. + * PARODD If set, then parity for input and output is odd; otherwise even parity is used. + */ + + if (parity == "n" || parity == "none") + { + // Disable parity generation/checking + BITMASK_CLEAR (config.c_cflag, PARENB); + } + else if (parity == "e" || parity == "even") + { + // Enable parity generation/checking + BITMASK_SET (config.c_cflag, PARENB); + + // Set to Even + BITMASK_CLEAR (config.c_cflag, PARODD); + + } + else if (parity == "o" || parity == "odd") + { + // Enable parity generation/checking + BITMASK_SET (config.c_cflag, PARENB); + + // Set to Odd + BITMASK_SET (config.c_cflag, PARODD); + + } + else + { + error ("serialport: Only [N]one, [E]ven or [O]dd parities are supported..."); + return false; + } + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport: error setting parity: %s\n", strerror (errno)); + return false; + } + + return true; +} + +std::string +octave_serialport::get_parity (void) const +{ + if (!BITMASK_CHECK (config.c_cflag, PARENB)) + return "None"; + else if (BITMASK_CHECK (config.c_cflag, PARODD)) + return "Odd"; + else + return "Even"; +} + +int +octave_serialport::set_flowcontrol (const std::string &newctrl) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string ctrl = newctrl; + std::transform (ctrl.begin (), ctrl.end (), ctrl.begin (), ::tolower); + + if (ctrl == "n" || ctrl == "none") + { + BITMASK_CLEAR (config.c_iflag, IXON | IXOFF | IXANY); +#ifdef CNEW_RTSCTS + BITMASK_CLEAR (config.c_cflag, CNEW_RTSCTS); +#else + BITMASK_CLEAR (config.c_cflag, CRTSCTS); +#endif + } + else if (ctrl == "h" || ctrl == "hardware") + { + BITMASK_CLEAR (config.c_iflag, IXON | IXOFF | IXANY); +#ifdef CNEW_RTSCTS + BITMASK_SET (config.c_cflag, CNEW_RTSCTS); +#else + BITMASK_SET (config.c_cflag, CRTSCTS); +#endif + } + else if (ctrl == "s" || ctrl == "software") + { + BITMASK_CLEAR (config.c_iflag, IXANY); + BITMASK_SET (config.c_iflag, IXON | IXOFF); +#ifdef CNEW_RTSCTS + BITMASK_CLEAR (config.c_cflag, CNEW_RTSCTS); +#else + BITMASK_CLEAR (config.c_cflag, CRTSCTS); +#endif + } + else + { + error ("serialport.flowcontrol: Only [N]one, [s]software or [h]hardware flow contols are supported..."); + return false; + } + + if (tcsetattr (fd, TCSANOW, &config) < 0) + { + error ("serialport.flowcontrol: error setting parity: %s\n", strerror (errno)); + return false; + } + + return true; +} + +std::string +octave_serialport::get_flowcontrol (void) const +{ +#ifdef CNEW_RTSCTS + if (BITMASK_CHECK (config.c_cflag, CNEW_RTSCTS)) +#else + if (BITMASK_CHECK (config.c_cflag, CRTSCTS)) +#endif + return "hardware"; + else if (BITMASK_CHECK (config.c_iflag, IXON | IXOFF | IXANY)) + return "software"; + else + return "none"; +} + +void +octave_serialport::get_control_line_status (void) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return; + } + ioctl (fd, TIOCMGET, &status); +} + +bool +octave_serialport::get_control_line (const std::string &control_signal) +{ + get_control_line_status (); + + if (control_signal == "DTR") + return (status & TIOCM_DTR); + else if (control_signal == "RTS") + return (status & TIOCM_RTS); + else if (control_signal == "CTS") + return (status & TIOCM_CTS); + else if (control_signal == "DSR") + return (status & TIOCM_DSR); + else if (control_signal == "CD") + return (status & TIOCM_CD); + else if (control_signal == "RI") + return (status & TIOCM_RI); + + error ("serialport: Unknown control signal..."); + return false; + +} + +void +octave_serialport::set_control_line (const std::string &control_signal, bool set) +{ + + get_control_line_status (); + + int signal; + + if (control_signal == "DTR") + signal = TIOCM_DTR; + else if (control_signal == "RTS") + signal = TIOCM_RTS; + else + { + error ("serialport: Unknown control signal..."); + return; + } + + if (set) + status |= signal; + else + status &= ~signal; + + ioctl (fd, TIOCMSET, &status); + +} + +bool +octave_serialport::fd_is_valid (void) const +{ + return (fd >= 0); +} + +void +octave_serialport::close (void) +{ + if (fd_is_valid ()) + { + ::close (fd); + fd = -1; + } +} + +int +octave_serialport::get_numbytesavailable (void) const +{ + int available = 0; + if (fd_is_valid ()) + { + ioctl (fd, FIONREAD, &available); + } + return available; +} + +#endif diff --git a/src/serialport/serialport_class_lin.h b/src/serialport/serialport_class_lin.h new file mode 100644 index 0000000..95b15d3 --- /dev/null +++ b/src/serialport/serialport_class_lin.h @@ -0,0 +1,76 @@ +// Copyright (C) 2019 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 . + +#ifndef SERIALPORT_CLASS_LIN_H +#define SERIALPORT_CLASS_LIN_H + +#include +#include + +class octave_serialport : public octave_serialport_common +{ +public: + octave_serialport(void); + ~octave_serialport(void); + + int write(const std::string& /* buffer */); + int write(uint8_t* /* buffer */, unsigned int /* buffer size */); + + int read(uint8_t* /* buffer */, unsigned int /* buffer size */); + + void open(const std::string& /* path */); + void close(void); + + int flush(unsigned short /* stream select */); + + int sendbreak(unsigned short /* ms */); + + int set_timeout(double /* timeout */); + double get_timeout(void) const; + + int set_baudrate(unsigned int /* baudrate */); + int get_baudrate(void) const; + + int set_databits(unsigned short /* size */); + int get_databits(void) const; + + int set_parity(const std::string& /* parity */); + std::string get_parity() const; + + int set_flowcontrol(const std::string& /* flow */); + std::string get_flowcontrol() const; + + int set_stopbits(unsigned short /* stop bits */); + int get_stopbits(void) const; + + bool get_control_line(const std::string &); + void set_control_line(const std::string &, bool); + + int get_numbytesavailable(void) const; +private: + int fd; + int status; + struct termios config; + double timeout; + volatile bool blocking_read; + + void get_control_line_status(void); + + bool fd_is_valid(void) const; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/serialport/serialport_class_win32.cc b/src/serialport/serialport_class_win32.cc new file mode 100644 index 0000000..e501da9 --- /dev/null +++ b/src/serialport/serialport_class_win32.cc @@ -0,0 +1,667 @@ +// Copyright (C) 2019 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SERIAL +#if HAVE_OCTAVE_LO_SYSDEP_H + #include +#endif +#include +#include +#include + +using std::string; + +#include "serialport_class.h" + +std::string +winerror (int err) +{ + + if (err != 0) + return strerror (err); + else + { + DWORD e; + + e = GetLastError (); + +#if HAVE_OCTAVE_U8_TO_WSTRING + wchar_t errstring[100+1]; + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errstring, + 100, 0) == 0) + { + errstring[0] = '\0'; + } + return octave::sys::u8_from_wstring (errstring); +#else + char errstring[100+1]; + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errstring, + 100, 0) == 0) + { + errstring[0] = '\0'; + } + return errstring; +#endif + } +} + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_serialport, "octave_serialport", "octave_serialport"); + +octave_serialport::octave_serialport(void) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + fd = INVALID_HANDLE_VALUE; +} + +void +octave_serialport::open (const std::string &path) +{ + portPath = path; + name = "Serial-" + path; + + // use full extended port names if not already specified + std::string fullPath = path; + if (fullPath.length() > 0 && fullPath[0] != '\\') + fullPath = "\\\\.\\" + path; + + fd = CreateFile(fullPath.c_str (), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (! fd_is_valid()) + { + error("serialport: Error opening the interface: %s\n", winerror (errno).c_str ()); + return; + } + + // clear any errors that may be on the port + COMSTAT stats; + DWORD err; + ClearCommError (fd, &err, &stats); + + // Clean the configuration struct (DCB) + memset (&config, 0, sizeof (config)); + // set up device settings + config.DCBlength = sizeof (config); + + if(GetCommState (fd, &config) == FALSE) + { + error ("serialport: Failed to get terminal attributes: %s\n", winerror (errno).c_str ()); + octave_serialport::close (); + return; + } + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + timeout = -1; + + if (SetCommTimeouts(fd, &timeouts) == FALSE) + { + error ("serialport: Failed to disable timeouts: %s\n", winerror (errno).c_str ()); + octave_serialport::close (); + return; + } + + return; +} + +octave_serialport::~octave_serialport(void) +{ + octave_serialport::close(); +} + +int +octave_serialport::read(uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + double maxwait = timeout; + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + DWORD readsz; + read_retval = -1; + if (ReadFile (fd, (buf + bytes_read), len - bytes_read, &readsz, NULL) == TRUE) + { + read_retval = readsz; + } + + if(read_retval < 0) + { + error ("serialport.read: Error while reading: %s\n", winerror (errno).c_str ()); + break; + } + + bytes_read += read_retval; + + if (read_retval == 0 && !blocking_read) + { + maxwait -= (double)timeouts.ReadTotalTimeoutConstant/1000.0; + + // actual timeout + if (maxwait <= 0) + break; + } + } + + return bytes_read; +} + +int +octave_serialport::write (const std::string & str) +{ + if (! fd_is_valid ()) + { + error("serialport: Interface must be opened first..."); + return -1; + } + int wrote_ret = -1; + DWORD wrote; + if (WriteFile (fd, str.c_str (), str.length (), &wrote, NULL) == TRUE) + { + wrote_ret = wrote; + byteswritten += wrote; + } + return wrote_ret; +} + +int +octave_serialport::write (uint8_t *buf, unsigned int len) +{ + if (! fd_is_valid ()) + { + error("serialport: Interface must be opened first..."); + return -1; + } + int wrote_ret = -1; + DWORD wrote; + if (WriteFile (fd, buf, len, &wrote, NULL) == TRUE) + { + wrote_ret = wrote; + byteswritten += wrote; + } + return wrote_ret; +} + +int +octave_serialport::set_timeout (double newtimeout) +{ + if (! fd_is_valid()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 || newtimeout > 255) + { + error ("serialport: timeout value must be between [-1..255]..."); + return -1; + } + + timeout = newtimeout; + + newtimeout *= 1000; + + // Disable custom timeout, enable blocking read + if (newtimeout < 0) + { + blocking_read = true; + newtimeout = 50; + } + // Enable custom timeout, disable blocking read + else + { + blocking_read = false; + if (newtimeout > 50) + newtimeout = 50; + } + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = newtimeout; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + if (SetCommTimeouts (fd, &timeouts) == FALSE) + { + error ("serialport.timeout: error setting timeout..."); + return -1; + } + + return 1; +} + +double +octave_serialport::get_timeout (void) const +{ + if (blocking_read) + return -1; + else + return timeout; +} + +int +octave_serialport::set_stopbits (unsigned short stopbits) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + if (stopbits == 1) + { + // Set to one stop bit + config.StopBits = ONESTOPBIT; + } + else if (stopbits == 2) + { + // Set to two stop bits + config.StopBits = TWOSTOPBITS; + } + else + { + error ("serialport: Only 1 or 2 stop bits are supported..."); + return false; + } + + if (SetCommState (fd,&config) == FALSE) + { + error ("serialport: error setting stop bits: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +int +octave_serialport::get_stopbits (void) const +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + if (config.StopBits == TWOSTOPBITS) + return 2; + else + return 1; +} + +int +octave_serialport::set_databits (unsigned short bytesize) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + if(bytesize < 5 || bytesize > 8) + { + error ("serialport.databits: expecting value between [5..8]..."); + return false; + } + + config.ByteSize = bytesize; + + if (SetCommState (fd, &config) == FALSE) + { + error ("serialport: error setting data size: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +int +octave_serialport::get_databits (void) const +{ + if (! fd_is_valid ()) + { + error("serialport: Interface must be opened first..."); + return -1; + } + + return config.ByteSize; +} + +int +octave_serialport::set_baudrate (unsigned int baud) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + DWORD old_baud = config.BaudRate; + + config.BaudRate = baud; + + if (SetCommState (fd, &config) == FALSE) + { + error ("serialport: error setting baud rate: %s\n", winerror (errno).c_str ()); + config.BaudRate = old_baud; + return false; + } + + return true; +} + +int +octave_serialport::get_baudrate (void) const +{ + if (! fd_is_valid ()) + { + error("serialport: Interface must be opened first..."); + return -1; + } + + return config.BaudRate; +} + +int +octave_serialport::flush (unsigned short queue_selector) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + int flag; + + switch (queue_selector) + { + case 0: flag = PURGE_TXCLEAR; break; + case 1: flag = PURGE_RXCLEAR; break; + case 2: flag = PURGE_RXCLEAR|PURGE_TXCLEAR; break; + default: + error ("serialport: only [0..2] values are accepted..."); + return false; + } + + if (PurgeComm (fd,flag) == FALSE) + return -1; + else + return true; +} + +int +octave_serialport::sendbreak (unsigned short ms) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + if (ms > 5000) + ms = 5000; + + if(SetCommBreak(fd) == TRUE) + { + Sleep(ms); + + ClearCommBreak(fd); + + return true; + } + + return false; +} + +int +octave_serialport::set_parity (const std::string &newparity) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string parity = newparity; + std::transform (parity.begin (), parity.end (), parity.begin (), ::tolower); + + /* + * PARENB Enable parity generation on output and parity checking for input. + * PARODD If set, then parity for input and output is odd; otherwise even parity is used. + */ + + if (parity == "n" || parity == "none") + { + // Disable parity generation/checking + config.Parity = NOPARITY; + } + else if (parity == "e" || parity == "even") + { + // Enable parity generation/checking + config.Parity = EVENPARITY; + } + else if (parity == "o" || parity == "odd") + { + config.Parity = ODDPARITY; + } + else + { + error ("serialport: Only [N]one, [E]ven or [O]dd parities are supported..."); + return false; + } + + if (SetCommState (fd, &config) == FALSE) + { + error ("serialport: error setting parity: %s\n", winerror (errno).c_str ()); + return false; + } + + return true; +} + +std::string +octave_serialport::get_parity (void) const +{ + if(config.Parity == NOPARITY) + return "None"; + else if(config.Parity == ODDPARITY) + return "Odd"; + else + return "Even"; +} + +int +octave_serialport::set_flowcontrol (const std::string &newctrl) +{ + if (! fd_is_valid ()) + { + error ("serialport: Interface must be opened first..."); + return -1; + } + + // Convert string to lowercase + std::string ctrl = newctrl; + std::transform (ctrl.begin (), ctrl.end (), ctrl.begin (), ::tolower); + + if (ctrl == "n" || ctrl == "none") + { + config.fDtrControl = DTR_CONTROL_ENABLE; + config.fRtsControl = RTS_CONTROL_ENABLE; + config.fOutxCtsFlow = 0; + config.fOutxDsrFlow = 0; + config.fOutX = 0; + config.fInX = 0; + } + else if (ctrl == "h" || ctrl == "hardware") + { + config.fDtrControl = DTR_CONTROL_ENABLE; + config.fRtsControl = RTS_CONTROL_HANDSHAKE; + config.fOutxCtsFlow = 1; + config.fOutxDsrFlow = 0; + config.fOutX = 0; + config.fInX = 0; + } + else if (ctrl == "s" || ctrl == "software") + { + config.fDtrControl = DTR_CONTROL_ENABLE; + config.fRtsControl = RTS_CONTROL_ENABLE; + config.fOutxCtsFlow = 0; + config.fOutxDsrFlow = 0; + config.fOutX = 1; + config.fInX = 1; + } + else + { + error ("serialport.flowcontrol: Only [N]one, [s]software or [h]hardware flow contols are supported..."); + return false; + } + + return true; +} + +std::string +octave_serialport::get_flowcontrol (void) const +{ + if (config.fOutxCtsFlow == 1) + return "hardware"; + else if (config.fOutX == 1) + return "software"; + else + return "none"; +} + + + +void +octave_serialport::get_control_line_status (void) +{ + if (! fd_is_valid()) + { + error ("serialport: Interface must be opened first..."); + return; + } + + GetCommState (fd, &config); + GetCommModemStatus (fd, &status); +} + +bool +octave_serialport::get_control_line (const std::string &control_signal) +{ + get_control_line_status (); + + if (control_signal == "DTR") + return (config.fDtrControl == DTR_CONTROL_ENABLE); + else if (control_signal == "RTS") + return (config.fRtsControl == RTS_CONTROL_ENABLE); + else if (control_signal == "CTS") + return (status & MS_CTS_ON); + else if (control_signal == "DSR") + return (status & MS_DSR_ON); + else if (control_signal == "CD") + return (status & MS_RLSD_ON); + else if (control_signal == "RI") + return (status & MS_RING_ON); + else + error("serialport: Unknown control signal..."); + return false; +} + +void +octave_serialport::set_control_line (const std::string &control_signal, bool set) +{ + get_control_line_status (); + + int signal; + + if (control_signal == "DTR") + { + if(set) + config.fDtrControl = DTR_CONTROL_ENABLE; + else + config.fDtrControl = DTR_CONTROL_DISABLE; + } + else if (control_signal == "RTS") + { + if(set) + config.fRtsControl = RTS_CONTROL_ENABLE; + else + config.fRtsControl = RTS_CONTROL_DISABLE; + } + else + { + error("serialport: Unknown control signal..."); + return; + } + + SetCommState (fd, &config); +} + +bool +octave_serialport::fd_is_valid (void) const +{ + return (fd != INVALID_HANDLE_VALUE); +} + +void +octave_serialport::close (void) +{ + if (fd_is_valid ()) + { + CloseHandle(fd); + fd = INVALID_HANDLE_VALUE; + } +} + +int +octave_serialport::get_numbytesavailable (void) const +{ + int available = 0; + if (fd_is_valid ()) + { + COMSTAT stats; + DWORD err; + if (ClearCommError (fd, &err, &stats)) + available = stats.cbInQue; + } + return available; +} +#endif diff --git a/src/serialport/serialport_class_win32.h b/src/serialport/serialport_class_win32.h new file mode 100644 index 0000000..a079781 --- /dev/null +++ b/src/serialport/serialport_class_win32.h @@ -0,0 +1,78 @@ +// Copyright (C) 2019 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 . + +#ifndef SERIALPORT_CLASS_WIN32_H +#define SERIALPORT_CLASS_WIN32_H + +#include +#include + +class octave_serialport : public octave_serialport_common +{ +public: + octave_serialport(void); + ~octave_serialport(void); + + int write(const std::string& /* buffer */); + int write(uint8_t* /* buffer */, unsigned int /* buffer size */); + + int read(uint8_t* /* buffer */, unsigned int /* buffer size */); + + void open(const std::string& /* path */); + void close(void); + + int flush(unsigned short /* stream select */); + + int sendbreak(unsigned short /* breaktime */); + + int set_timeout(double /* timeout */); + double get_timeout(void) const; + + int set_baudrate(unsigned int /* baudrate */); + int get_baudrate() const; + + int set_databits(unsigned short /* bytesize */); + int get_databits(void) const; + + int set_parity(const std::string& /* parity */); + std::string get_parity(void) const; + + int set_flowcontrol(const std::string& /* flow */); + std::string get_flowcontrol() const; + + int set_stopbits(unsigned short /* stop bits */); + int get_stopbits(void) const; + + bool get_control_line(const std::string &); + void set_control_line(const std::string&, bool); + + int get_numbytesavailable(void) const; +private: + HANDLE fd; + DWORD status; + DCB config; + COMMTIMEOUTS timeouts; + + volatile bool blocking_read; + double timeout; + + void get_control_line_status(void); + + bool fd_is_valid(void) const; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/spi/Makefile.in b/src/spi/Makefile.in new file mode 100644 index 0000000..54662c3 --- /dev/null +++ b/src/spi/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../spi.oct +OBJ := spi.o spi_close.o spi_write.o spi_read.o spi_writeAndRead.o spi_class.o __spi_pkg_lock__.o __spi_properties__.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/spi/__spi_pkg_lock__.cc b/src/spi/__spi_pkg_lock__.cc new file mode 100644 index 0000000..9f07be7 --- /dev/null +++ b/src/spi/__spi_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2020 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__spi_pkg_lock__", "spi.oct"); +// PKG_ADD: __spi_pkg_lock__(1); +// PKG_DEL: __spi_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__spi_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__spi_pkg_lock__")) + interp.munlock("__spi_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__spi_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/spi/__spi_properties__.cc b/src/spi/__spi_properties__.cc new file mode 100644 index 0000000..90294e4 --- /dev/null +++ b/src/spi/__spi_properties__.cc @@ -0,0 +1,86 @@ +// Copyright (C) 2020 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_SPI +# include "spi_class.h" +#endif + + +// PKG_ADD: autoload ("__spi_properties__", "spi.oct"); +DEFUN_DLD (__spi_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __spi_properties__ (@var{octave_spi}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_SPI + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_spi::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_spi* spi = &((octave_spi &)rep); + + std::string property = args(1).string_value (); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (spi->get_name ()); + else if (property == "bitrate") + return octave_value (spi->get_bitrate ()); + else if (property == "clockpolarity") + return octave_value (spi->get_clockpolarity ()); + else if (property == "clockphase") + return octave_value (spi->get_clockphase ()); + else if (property == "status") + return octave_value (spi->get_status ()); + else if (property == "port") + return octave_value (spi->get_port ()); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (spi->set_name (args(2).string_value ())); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "bitrate") + return octave_value (spi->set_bitrate (args(2).int_value ())); + else if (property == "clockpolarity") + return octave_value (spi->set_clockpolarity (args(2).string_value ())); + else if (property == "clockphase") + return octave_value (spi->set_clockphase (args(2).string_value ())); + else if (property == "port") + (*current_liboctave_error_handler) ("can not set this property"); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#else + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the SPI interface"); +#endif + return octave_value(); +} diff --git a/src/spi/spi.cc b/src/spi/spi.cc new file mode 100644 index 0000000..6b4af04 --- /dev/null +++ b/src/spi/spi.cc @@ -0,0 +1,207 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include + +#include "spi_class.h" +#endif + +// PKG_ADD: autoload ("spi", "spi.oct"); +DEFUN_DLD (spi, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{spi} = } spi ([@var{port_path}])\n \ +@deftypefnx {Loadable Function} {@var{spi} = } spi ([@var{port_path}], [@var{propname}, @var{propvalue}])\n \ +\n\ +Open a spi interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{port_path} - the interface device port/path of type String. If omitted defaults to \n \ +'/dev/spi-0'. @*\n \ +@var{propname},@var{propvalue} - property name/value pairs.\n \ +\n\ +Known input properties:\n \ +@table @asis\n \ +@item name\n \ +Name of the object\n \ +@item bitrate\n \ +Numeric bitrate value\n \ +@item clockpolarity\n \ +Clock polarity: idlehigh or idlelow.\n \ +@item clockphase\n \ +Clock phase value: firstedge or secondedge\n \ +@end table\n \ +\n\ +@subsubheading Outputs\n \ +@var{spi} - An instance of @var{octave_spi} class.\n \ +\n\ +@subsubheading Properties\n \ +The spi object has the following properties:\n \ +@table @asis\n \ +@item name\n \ +Name of the object\n \ +@item status\n \ +Open or closed status of object (readonly).\n \ +@item bitrate\n \ +Numeric bitrate value\n \ +@item clockpolarity\n \ +Clock polarity: idlehigh or idlelow.\n \ +@item clockphase\n \ +Clock phase value: firstedge or secondedge\n \ +@item port\n \ +The interface driver port (readonly)\n \ +@end table\n \ +@end deftypefn") +{ +#ifndef BUILD_SPI + error ("spi: Your system doesn't support the SPI interface"); + return octave_value (); +#else + + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + int oflags = O_RDWR; + std::string path ("/dev/spi-0"); + unsigned int bitrate = 0; + std::string polarity = ""; + std::string phase = ""; + std::string objname = ""; + + // Parse the function arguments + if (args.length () > 0) + { + if (args (0).is_string ()) + { + path = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + + } + + if (args.length() > 1 && (args.length() & 1) == 0) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + + for(int i=1;i 0)) + bitrate = val.int_value (); + else + { + error ("bitrate must be a positive integer"); + return octave_value(); + } + } + else if (name == "clockpolarity") + { + if (val.is_string ()) + polarity = val.string_value (); + else + { + error ("polarity must be a string"); + return octave_value(); + } + } + else if (name == "clockphase") + { + if (val.is_string ()) + phase = val.string_value (); + else + { + error ("phase must be a string"); + return octave_value(); + } + } + else if (name == "name") + { + if (val.is_string ()) + objname = val.string_value (); + else + { + error ("name must be a string"); + return octave_value(); + } + } + else + { + error ("unknown property '%s'", name.c_str()); + return octave_value(); + } + } + + octave_spi* retval = new octave_spi (); + + // Open the interface + if (retval->open (path, oflags) < 0) + return octave_value (); + + if (bitrate > 0) + retval->set_bitrate (bitrate); + + if (objname.length() > 0) + retval->set_name (objname); + + if (polarity.length() > 0) + retval->set_clockpolarity (polarity); + + if (phase.length() > 0) + retval->set_clockphase (phase); + + return octave_value (retval); +#endif +} + +#if 0 + +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "spi")) +%! fail ("spi ()", "Invalid call to spi"); +%! else +%! fail ("spi ()", "spi: Your system doesn't support the SPI interface"); +%! endif + +#endif diff --git a/src/spi/spi_class.cc b/src/spi/spi_class.cc new file mode 100644 index 0000000..47de94e --- /dev/null +++ b/src/spi/spi_class.cc @@ -0,0 +1,446 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "spi_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_spi, "octave_spi", "octave_spi"); + +octave_spi::octave_spi (void) + : fieldnames(6) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + fd = -1; + mode = 0; + bitrate = 250000; + + fieldnames[0] = "status"; + fieldnames[1] = "name"; + fieldnames[2] = "port"; + fieldnames[3] = "bitrate"; + fieldnames[4] = "clockpolarity"; + fieldnames[5] = "clockphase"; +} + +octave_spi::~octave_spi (void) +{ + octave_spi::close (); +} + +int +octave_spi::get_fd (void) const +{ + return fd; +} + +void +octave_spi::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_spi::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_spi::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " SPI Object " << this->get_name(); newline(os); + os << " status: " << this->get_status(); newline(os); + if (get_fd() > -1) + { + os << " bitrate: " << this->get_bitrate(); + newline(os); + } +} + +int +octave_spi::open (const std::string &path, int flags) +{ + port = path; + name = "SPI-" + path; + + fd = ::open (path.c_str (), flags, 0); + + if (get_fd () < 0) + { + error ("spi: Error opening the interface: %s\n", strerror (errno)); + return -1; + } + + __u8 dmode, dlsb, dbits; + __u32 dspeed; + + mode = 0; + if (ioctl(get_fd (), SPI_IOC_RD_MODE, &dmode) < 0) + { + warning ("spi: failed to read RD mode: %s\n", strerror (errno)); + } + else + { + mode = dmode; + } + + if (ioctl(get_fd (), SPI_IOC_RD_LSB_FIRST, &dlsb) < 0) + { + warning ("spi: failed to read LSB mode: %s\n", strerror (errno)); + } + if (ioctl(get_fd (), SPI_IOC_RD_BITS_PER_WORD, &dbits) < 0) + { + warning ("spi: failed to read bits per word: %s\n", strerror (errno)); + } + + bitrate = 250000; + if (ioctl(get_fd (), SPI_IOC_RD_MAX_SPEED_HZ, &dspeed) < 0) + { + warning ("spi: failed to read speed: %s\n", strerror (errno)); + } + else + { + if (bitrate > dspeed) + bitrate = dspeed; + } + + return get_fd (); +} + +int +octave_spi::read (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("spi: Interface must be open first..."); + return -1; + } + + int retval = -1; + +// retval = ::read (get_fd (), buf, len); + struct spi_ioc_transfer tr; + memset(&tr, 0, sizeof(tr)); + + tr.rx_buf = (__u64)buf; + //tr.tx_buf = (__u64)tbuf; + tr.len = len; /* Length of command to write*/ + tr.cs_change = 0; /* Keep CS activated */ + tr.delay_usecs = 0; //delay in us + tr.speed_hz = bitrate; //speed + tr.bits_per_word = 8; // bits per word 8 + + retval = ioctl(get_fd (), SPI_IOC_MESSAGE(1), &tr); + + if (retval < 0) + error ("spi: Failed to read from the spi bus: %s\n", strerror (errno)); + + return retval; +} + +int +octave_spi::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("spi: Interface must be open first..."); + return -1; + } + + int retval = -1; + +// retval = ::write (get_fd (), buf, len); + struct spi_ioc_transfer tr; + memset(&tr, 0, sizeof(tr)); + + tr.tx_buf = (__u64)buf; + //tr.rx_buf = (__u64)rbuf; + tr.len = len; /* Length of command to write*/ + tr.cs_change = 0; /* Keep CS activated */ + tr.delay_usecs = 0; //delay in us + tr.speed_hz = bitrate; //speed + tr.bits_per_word = 8; // bits per word 8 + + retval = ioctl(get_fd (), SPI_IOC_MESSAGE(1), &tr); + + + if (retval < 0) + error ("spi: Failed to write to the spi bus: %s\n", strerror (errno)); + + return retval; +} + +int +octave_spi::writeRead (uint8_t *wbuf, unsigned int wlen, uint8_t *rbuf) +{ + if (get_fd () < 0) + { + error ("spi: Interface must be open first..."); + return -1; + } + + int retval = -1; + + struct spi_ioc_transfer tr; + memset(&tr, 0, sizeof(tr)); + + tr.tx_buf = (__u64)wbuf; + tr.rx_buf = (__u64)rbuf; + tr.len = wlen; /* Length of command to write*/ + tr.cs_change = 0; /* Keep CS activated */ + tr.delay_usecs = 0; //delay in us + tr.speed_hz = bitrate; //speed + tr.bits_per_word = 8; // bits per word 8 + + retval = ioctl(get_fd (), SPI_IOC_MESSAGE(1), &tr); + + if (retval < 0) + error ("spi: Failed to writeRead to the spi bus: %s\n", strerror (errno)); + + return retval; +} + + +int +octave_spi::close (void) +{ + int retval = -1; + + if (get_fd () > 0) + { + retval = ::close(get_fd ()); + fd = -1; + } + + return retval; +} + +std::string +octave_spi::get_port () const +{ + return port; +} + +std::string +octave_spi::get_name () const +{ + return name; +} + +std::string +octave_spi::get_clockpolarity () const +{ + if(mode & SPI_CPOL) return "idlehigh"; + else return "idlelow"; +} + +std::string +octave_spi::set_clockpolarity (const std::string &newpolarity) +{ + std::string polarity = newpolarity; + std::transform (polarity.begin (), polarity.end (), polarity.begin (), ::tolower); + + int newmode = mode; + if(polarity == "idlelow") + newmode = mode & ~SPI_CPOL; + else if(polarity == "idlehigh") + newmode = mode | SPI_CPOL; + + __u8 dmode = newmode; + + if(ioctl(fd, SPI_IOC_WR_MODE, &dmode) < 0) + { + error ("spi: failed to mode: %s\n", strerror (errno)); + } + else + { + mode = newmode; + } + + return get_clockpolarity(); +} + +std::string +octave_spi::get_clockphase () const +{ + if(mode & SPI_CPHA) return "secondedge"; + else return "firstedge"; +} + +std::string +octave_spi::set_clockphase (const std::string &newphase) +{ + std::string phase = newphase; + std::transform (phase.begin (), phase.end (), phase.begin (), ::tolower); + + int newmode = mode; + if(phase == "firstedge") + newmode = mode & ~SPI_CPHA; + else if(phase == "secondedge") + newmode = mode | SPI_CPHA; + + __u8 dmode = newmode; + + if(ioctl(fd, SPI_IOC_WR_MODE, &dmode) < 0) + { + error ("spi: failed to mode: %s\n", strerror (errno)); + } + else + { + mode = newmode; + } + return get_clockphase(); +} + +std::string +octave_spi::set_name (const std::string &newname) +{ + name = newname; + return name; +} + +unsigned long +octave_spi::get_bitrate () const +{ + return bitrate; +} + +unsigned long +octave_spi::set_bitrate (unsigned long newbitrate) +{ + __u32 speed = newbitrate; + if (ioctl(get_fd (), SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) + { + error ("spi: failed to set speed: %s\n", strerror (errno)); + } + else + { + bitrate = newbitrate; + } + return bitrate; +} + +std::string +octave_spi::get_status () const +{ + if (get_fd () > -1) + return "open"; + else + return "closed"; +} + +octave_value_list +octave_spi::subsref (const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_spi object cannot be indexed with %c", type[0]); + break; + case '.': + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__spi_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_spi::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_spi object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__spi_properties__"), ovl, 0); + + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length() > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_spi invalid index"); + } + + } + return retval; +} + +#endif diff --git a/src/spi/spi_class.h b/src/spi/spi_class.h new file mode 100644 index 0000000..fe417e0 --- /dev/null +++ b/src/spi/spi_class.h @@ -0,0 +1,110 @@ +// Copyright (C) 2020 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 . + +#ifndef SPI_CLASS_H +#define SPI_CLASS_H + +#include + +#include + +#include + +class octave_spi : public octave_base_value +{ +public: + octave_spi (void); + ~octave_spi (void); + + int open (const std::string& /* path */, int /* open flags */); + int close (void); + int get_fd (void) const; + + std::string get_name () const; + std::string set_name (const std::string &newname); + + unsigned long get_bitrate () const; + unsigned long set_bitrate (unsigned long rate); + + std::string get_status () const; + + std::string get_clockphase () const; + std::string set_clockphase (const std::string &newphase); + + std::string get_clockpolarity () const; + std::string set_clockpolarity (const std::string &newpolarity); + + std::string get_port () const; + + // Simple spi commands + int write (uint8_t* /* buffer */, unsigned int /* buffer size */); + int read (uint8_t* /* buffer */, unsigned int /* buffer size */); + + int writeRead (uint8_t *wbuf, unsigned int wlen, uint8_t *rbuf); + + // Overloaded base functions + double spi_value () const + { + return (double)fd; + } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true;} + // 4.4+ + bool isobject (void) const { return true;} + + octave_base_value * unique_clone (void) { count++; return this;} + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); +private: + int fd; + std::string name; + std::string port; + unsigned int bitrate; + int mode; + + string_vector fieldnames; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + + +#endif diff --git a/src/spi/spi_close.cc b/src/spi/spi_close.cc new file mode 100644 index 0000000..9a36c40 --- /dev/null +++ b/src/spi/spi_close.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include "spi_class.h" +#endif + +// PKG_ADD: autoload ("spi_close", "spi.oct"); +DEFUN_DLD (spi_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} spi_close (@var{spi})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{spi} - instance of @var{octave_spi} class.@*\ +\n \ +@subsubheading Outputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_SPI + error ("spi: Your system doesn't support the SPI interface"); + return octave_value (); +#else + + if (args.length () != 1 || args (0).type_id () != octave_spi::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_spi* spi = NULL; + + const octave_base_value& rep = args (0).get_rep (); + spi = &((octave_spi &)rep); + + spi->close (); + + return octave_value (); +#endif +} diff --git a/src/spi/spi_read.cc b/src/spi/spi_read.cc new file mode 100644 index 0000000..35a3d53 --- /dev/null +++ b/src/spi/spi_read.cc @@ -0,0 +1,96 @@ +// Copyright (C) 2020 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include + +#include "spi_class.h" +#endif + +// PKG_ADD: autoload ("spi_read", "spi.oct"); +DEFUN_DLD (spi_read, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } spi_read (@var{spi}, @var{n})\n \ +\n\ +Read from spi slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{spi} - instance of @var{octave_spi} class.@*\ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +@subsubheading Outputs\n \ +The spi_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_SPI + error ("spi: Your system doesn't support the SPI interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_spi::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 1; + + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + } + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len +1)); + + if (buffer == NULL) + { + error ("spi_read: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_spi* spi = NULL; + + const octave_base_value& rep = args (0).get_rep(); + spi = &((octave_spi &)rep); + + int retval; + + retval = spi->read (buffer, buffer_len); + + octave_value_list return_list; + uint8NDArray data (dim_vector (1, retval)); + + for (int i = 0; i < retval; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = retval; + + return return_list; +#endif +} diff --git a/src/spi/spi_write.cc b/src/spi/spi_write.cc new file mode 100644 index 0000000..1b476d0 --- /dev/null +++ b/src/spi/spi_write.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include + +#include "spi_class.h" +#endif + +// PKG_ADD: autoload ("spi_write", "spi.oct"); +DEFUN_DLD (spi_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } spi_write (@var{spi}, @var{data})\n \ +\n\ +Write data to a spi slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{spi} - instance of @var{octave_spi} class.@*\ +@var{data} - data, of type uint8, to be written to the slave device.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, spi_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_SPI + error ("spi: Your system doesn't support the SPI interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_spi::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_spi* spi = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + spi = &((octave_spi &)rep); + + if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("spi_write: cannot allocate requested memory: %s", strerror (errno)); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data (i)); + + retval = spi->write (buf, data.numel()); + } + else + { + error ("spi_write: expected uint8 data"); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/spi/spi_writeAndRead.cc b/src/spi/spi_writeAndRead.cc new file mode 100644 index 0000000..c02cce7 --- /dev/null +++ b/src/spi/spi_writeAndRead.cc @@ -0,0 +1,105 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_SPI +#include + +#include "spi_class.h" +#endif + +// PKG_ADD: autoload ("spi_writeAndRead", "spi.oct"); +DEFUN_DLD (spi_writeAndRead, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{rddata} = } spi_writeAndRead (@var{spi}, @var{wrdata})\n \ +\n\ +Write data to a spi slave device and then read same number of values.\n \ +\n\ +@subsubheading Inputs\n \ +@var{spi} - instance of @var{octave_spi} class.@*\ +@var{wrdata} - data, of type uint8, to be written to the slave device.@*\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, spi_writeAndRead() shall return the bytes read.\n \ +@end deftypefn") +{ +#ifndef BUILD_SPI + error ("spi: Your system doesn't support the SPI interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_spi::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_spi* spi = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + spi = &((octave_spi &)rep); + + if (args (1).is_uint8_type ()) // uint8_t + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("spi_writeAndRead: cannot allocate requested memory: %s", strerror (errno)); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data (i)); + + OCTAVE_LOCAL_BUFFER (uint8_t, rdbuffer, (data.numel () +1)); + if (rdbuffer == NULL) + { + error ("spi_writeAndRead: cannot allocate requested read memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + retval = spi->writeRead (buf, data.numel(), rdbuffer); + + octave_value_list return_value; + if (retval >= 0) + { + uint8NDArray data (dim_vector (1, retval)); + + for (int i = 0; i < retval; i++) + data (i) = rdbuffer[i]; + + return_value(0) = data; + + return return_value; + } + else + error ("spi_writeAndRead: error reading data"); + } + else + { + error ("spi_writeAndRead: expected uint8 data"); + return octave_value (); + } + + return octave_value (); +#endif +} diff --git a/src/tcp/Makefile.in b/src/tcp/Makefile.in new file mode 100644 index 0000000..ee1edda --- /dev/null +++ b/src/tcp/Makefile.in @@ -0,0 +1,7 @@ +OCT := ../tcp.oct +OBJ := tcp.o tcp_timeout.o tcp_write.o tcp_close.o tcp_read.o tcp_class.o __tcp_properties__.o __tcp_pkg_lock__.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk + diff --git a/src/tcp/__tcp_pkg_lock__.cc b/src/tcp/__tcp_pkg_lock__.cc new file mode 100644 index 0000000..5b9e163 --- /dev/null +++ b/src/tcp/__tcp_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__tcp_pkg_lock__", "tcp.oct"); +// PKG_ADD: __tcp_pkg_lock__(1); +// PKG_DEL: __tcp_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__tcp_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__tcp_pkg_lock__")) + interp.munlock("__tcp_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__tcp_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc new file mode 100644 index 0000000..b701cb2 --- /dev/null +++ b/src/tcp/__tcp_properties__.cc @@ -0,0 +1,140 @@ +// Copyright (C) 2012 Andrius Sutas +// Copyright (C) 2014 Stefan Mahr +// Copyright (C) 2016 John Donoghue +// Copyright (C) 2018-2019 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_TCP +# include "tcp_class.h" +#endif + + +// PKG_ADD: autoload ("__tcp_properties__", "tcp.oct"); +DEFUN_DLD (__tcp_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __tcp_properties__ (@var{octave_tcp}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_TCP + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_tcp::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_tcp* tcp = &((octave_tcp &)rep); + + std::string property = args(1).string_value (); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (tcp->get_name ()); + else if (property == "type") + return octave_value (tcp->get_type ()); + else if (property == "remoteport") + return octave_value (tcp->get_remote_port ()); + else if (property == "remotehost") + return octave_value (tcp->get_remote_addr ()); + else if (property == "localport") + return octave_value (tcp->get_local_port ()); + else if (property == "status") + return octave_value (tcp->get_status ()); + else if (property == "timeout") + return octave_value (tcp->get_timeout ()); + else if (property == "bytesavailable") + return octave_value (tcp->get_bytesavailable ()); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (tcp->set_name (args(2).string_value ())); + else if (property == "type") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "remoteport") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "remotehost") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "localport") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "timeout") + return octave_value (tcp->set_timeout (args(2).double_value ())); + else if (property == "flush") + return octave_value (tcp->flush (args(2).int_value ())); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the TCP interface"); +} +#if 0 +%!shared ip +%! ip = resolvehost("www.octave.org", "address"); + +%!test +%! # test get +%! a = tcp (ip, 80); +%! assert (__tcp_properties__ (a,"type"), "tcp"); +%! assert (__tcp_properties__ (a,"remoteport"), 80); +%! assert (__tcp_properties__ (a,"remotehost"), ip); +%! assert (__tcp_properties__ (a,"timeout"), -1); +%! assert (__tcp_properties__ (a,"status"), "open"); +%! assert (__tcp_properties__ (a,"name"), ["TCP-" ip]); +%! fail ("__tcp_properties__ (a,'invalid')", "invalid property name"); +%! tcp_close (a); +%! assert (__tcp_properties__ (a,"status"), "closed"); + +%!test +%! # test set +%! a = tcp(ip, 80); +%! __tcp_properties__ (a, 'name', "mytest"); +%! assert (__tcp_properties__ (a,"name"), "mytest"); +%! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); +%! tcp_close (a); + +%!test +%! # test flush +%! a = tcp(ip, 80); +%! __tcp_properties__ (a, 'flush', 0); +%! __tcp_properties__ (a, 'flush', 1); +%! __tcp_properties__ (a, 'flush', 2); +%! fail ("__tcp_properties__ (a,'flush')", "invalid property name"); +%! tcp_close (a); + + +%!error __tcp_properties__ () + +%!error __tcp_properties__ (1) + +%!test +%! a = tcp (ip, 80); +%! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); +%! tcp_close (a); + +#endif diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc new file mode 100644 index 0000000..31819f9 --- /dev/null +++ b/src/tcp/tcp.cc @@ -0,0 +1,228 @@ +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_TCP +# include "tcp_class.h" +#endif + +// PKG_ADD: autoload ("tcp", "tcp.oct"); +DEFUN_DLD (tcp, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{tcp} = } tcp ()\n \ +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress})\n \ +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port})\n \ +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port}, @var{timeout})\n \ +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, [@var{propertyname}, @var{propertyvalue}])\n \ +@deftypefnx {Loadable Function} {@var{tcp} = } tcp (@var{ipaddress}, @var{port}, [@var{propertyname}, @var{propertyvalue}])\n \ +\n\ +Open tcp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{ipaddress} - the ip address of type String. If omitted defaults to '127.0.0.1'.@* \ +@var{port} - the port number to connect. If omitted defaults to 23.@* \ +@var{timeout} - the interface timeout value. If omitted defaults to blocking call.@*\n \ +@var{propname},@var{propvalue} - property name/value pairs.\n \ +\n \ +Known input properties:\n \ +@table @asis\n \ +@item name\n \ +name value\n \ +@item timeout\n \ +Numeric timeout value or -1 to wait forever\n \ +@end table\n \ +\n\ +@subsubheading Outputs\n \ +The tcp() shall return instance of @var{octave_tcp} class as the result @var{tcp}.\n \ +@subsubheading Properties\n \ +The tcp object has the following public properties:\n \ +@table @asis\n \ +@item name\n \ +name assigned to the tcp object\n \ +@item type\n \ +instrument type 'tcp' (readonly)\n \ +@item localport\n \ +local port number (readonly)\n \ +@item remoteport\n \ +remote port number\n \ +@item remotehost\n \ +remote host\n \ +@item status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item timeout\n \ +timeout value in seconds used for waiting for data\n \ +@item bytesavailable\n \ +number of bytes currently available to read (readonly)\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error("tcp: Your system doesn't support the TCP interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + std::string address ("127.0.0.1"); + std::string name = ""; + int port = 23; + double timeout = -1; + + + // Parse the function arguments + if (args.length () > 0) + { + if (args (0).is_string ()) + { + address = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + // is_float_type() is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + int property_start = -1; + if (args.length () > 1) + { + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + port = args (1).int_value (); + } + else + { + property_start = 1; + } + } + + if (args.length () > 2 && property_start == -1) + { + if (args (2).OV_ISINTEGER () || args (2).OV_ISFLOAT ()) + { + timeout = args (2).int_value (); + } + else + { + property_start = 2; + } + } + + if (args.length () > 3 && property_start == -1) + { + property_start = 2; + } + + if (property_start != -1) + { + if (((args.length () - property_start) & 1) == 1) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + + // go through the properties + for(int i=property_start;iopen (address, port) < 0) + { + return octave_value (); + } + + retval->set_timeout (timeout); + + //retval->flush (2); + if (name.length() > 0) + retval->set_name (name); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_tcp')); +%! tcp_close (a); + +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_tcp')); +%! assert (get(a, 'name'), 'test'); +%! assert (get(a, 'timeout'), 2.5); +%! tcp_close (a); + +%!error tcp (1) + +%!error tcp (1, 1) + +%!error tcp ('127.0.0.1', '80', 'prop1') + +#endif diff --git a/src/tcp/tcp_class.cc b/src/tcp/tcp_class.cc new file mode 100644 index 0000000..9406ced --- /dev/null +++ b/src/tcp/tcp_class.cc @@ -0,0 +1,492 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include +#include +#include + +#ifndef __WIN32__ +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#ifndef __WIN32__ +#define SOCKETERR errno +#define STRSOCKETERR strerror(errno) +#define IOCTL_TYPE int +#else +#define SOCKETERR WSAGetLastError() +#define STRSOCKETERR "" +#define IOCTL_TYPE u_long +#define ioctl ioctlsocket +#define socklen_t int +#endif + +#include "tcp_class.h" + +static struct timeval +to_timeval(int ms) +{ + struct timeval tv; + if(ms <= 0) + { + tv.tv_usec = 0; + tv.tv_sec = 0; + } + else + { + tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms/1000;; + } + return tv; +} + +static std::string +to_ip_str (const sockaddr_in *in) +{ + u_long addr = ntohl (in->sin_addr.s_addr); + + int b[4]; + b[0] = (addr>>24)&0xff; + b[1] = (addr>>16)&0xff; + b[2] = (addr>>8)&0xff; + b[3] = (addr>>0)&0xff; + + std::stringstream n; + n << b[0] << "." << b[1] << "." << b[2] << "." << b[3]; + + return n.str (); +} + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_tcp, "octave_tcp", "octave_tcp"); + +octave_tcp::octave_tcp (void) +: fieldnames(8), fd (-1), timeout(-1), name("") +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + fieldnames[0] = "type"; + fieldnames[1] = "name"; + fieldnames[2] = "remoteport"; + fieldnames[3] = "remotehost"; + fieldnames[4] = "localport"; + fieldnames[5] = "status"; + fieldnames[6] = "timeout"; + fieldnames[7] = "bytesavailable"; +} + +octave_value_list +octave_tcp::subsref (const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_tcp object cannot be indexed with %c", type[0]); + break; + case '.': + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__tcp_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_tcp::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_tcp object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__tcp_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_tcp invalid index"); + } + + } + return retval; +} + +int +octave_tcp::open (const std::string &address, int port) +{ + int sockerr; + + name = "TCP-" + address; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + err = WSAStartup (wVersionRequested, &wsaData); + if ( err != 0 ) + { + error( "could not initialize winsock library" ); + return -1; + } +#endif + + memset (&remote_addr, 0, sizeof (remote_addr)); + remote_addr.sin_addr.s_addr = inet_addr (address.c_str ()); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons (port); + + fd = socket (AF_INET, SOCK_STREAM,0); + if (fd < 0) + { + error ("tcp: error opening socket : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_tcp::close (); + return -1; + } + + // get local socket info + memset (&local_addr, 0, sizeof (local_addr)); + socklen_t sz = sizeof (local_addr); + getsockname (fd, (struct sockaddr*)&local_addr, &sz); + + sockerr = connect (fd, (struct sockaddr*)&remote_addr, sizeof(struct sockaddr)); + if (sockerr < 0) + { + error ("tcp: error on connect : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_tcp::close (); + return -1; + } + return get_fd(); +} + +octave_tcp::~octave_tcp (void) +{ + octave_tcp::close (); +} + +void +octave_tcp::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_tcp::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_tcp::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " TCP Object " << get_name (); + newline(os); + os << " type: " << get_type (); + newline(os); + os << " status: " << get_status (); + newline(os); + os << " remoteport: " << get_remote_port (); + newline(os); + os << " remotehost: " << get_remote_addr (); + newline(os); + os << " localport: " << get_local_port (); + newline (os); +} + +int +octave_tcp::read (uint8_t *buf, unsigned int len, double readtimeout) +{ + struct timeval tv; + + fd_set readfds; + + if (get_fd () < 0) + { + error ("tcp_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + // While not interrupted in blocking mode + while (bytes_read < len) + { + + OCTAVE_QUIT; + + tv = to_timeval((readtimeout < 0 || readtimeout > 1000) ? 1000 : (int)readtimeout); + + FD_ZERO (&readfds); + FD_SET (get_fd (), &readfds); + + if (::select (get_fd ()+1, &readfds, NULL, NULL, &tv) < 0) + { + error ("tcp_read: Error while reading/select: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + + if (FD_ISSET (get_fd (), &readfds)) + { + read_retval = ::recv(get_fd (), reinterpret_cast((buf + bytes_read)), len - bytes_read, 0); + if (read_retval < 0) + { + error ("tcp_read: Error while reading: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else if (read_retval == 0) + { + error ("tcp_read: Connection lost: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else + { + bytes_read += read_retval; + } + } + else + { + // time out + if (readtimeout >= 0) + { + // real timeout + if (readtimeout <= 1000) + break; + // timed out 1 sec of an actual timeout + else + readtimeout -= 1000; + } + } + + } + + return bytes_read; +} + +int +octave_tcp::write (const std::string &str) +{ + if (get_fd () < 0) + { + error ("tcp: Interface must be opened first..."); + return -1; + } + + return ::send (get_fd (), str.c_str (), str.length (), 0); +} + +int +octave_tcp::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("tcp: Interface must be opened first..."); + return -1; + } + + return ::send (get_fd (), reinterpret_cast(buf), len, 0); +} + +int +octave_tcp::set_timeout (double newtimeout) +{ + if (get_fd () < 0) + { + error ("tcp: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 ) + { + error ("tcp_timeout: timeout value must be -1 or positive"); + return -1; + } + + timeout = newtimeout; + + return 1; +} + +int +octave_tcp::close (void) +{ + int retval = -1; + + if (get_fd() > 0) + { +#ifndef __WIN32__ + retval = ::close (get_fd ()); +#else + retval = ::closesocket (get_fd ()); +#endif + fd = -1; + } + + return retval; +} + +int +octave_tcp::get_bytesavailable () const +{ + IOCTL_TYPE available = 0; + + if (get_fd () <= 0) + { + return 0; + } + ioctl (get_fd (), FIONREAD, &available); + + return available; +} + +int +octave_tcp::get_remote_port (void) const +{ + return ntohs (remote_addr.sin_port); +} + +std::string +octave_tcp::get_remote_addr (void) const +{ + return to_ip_str (&remote_addr); +} + +int +octave_tcp::get_local_port (void) const +{ + return ntohs (local_addr.sin_port); +} + +std::string +octave_tcp::set_name (const std::string &n) +{ + if (n.length() == 0 ) + { + error ("tcp_name: value must be non empty"); + } + else + { + name = n; + } + + return name; +} + +bool +octave_tcp::is_open (void) const +{ + return fd > 0; +} + +std::string +octave_tcp::get_status (void) const +{ + if (! is_open ()) + { + return "closed"; + } + else + { + return "open"; + } +} + +int +octave_tcp::flush (int mode) +{ + int retval = -1; + + if (get_fd() > 0) + { + uint8_t tmpbuffer[1024]; + if (mode == 0 || mode == 2) + { + // we are sending data as we get it, so no outout + // buffers to flush + } + if (mode == 1 || mode == 2) + { + while (read (tmpbuffer, 1024, 0) > 0) {} + } + } + + return retval; +} + +#endif diff --git a/src/tcp/tcp_class.h b/src/tcp/tcp_class.h new file mode 100644 index 0000000..0fb5dd0 --- /dev/null +++ b/src/tcp/tcp_class.h @@ -0,0 +1,118 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef TCP_CLASS_H +#define TCP_CLASS_H + +#include +#include + +#include + +#ifndef __WIN32__ +# include +#else +# include +#endif + +class octave_tcp : public octave_base_value +{ +public: + octave_tcp (void); + ~octave_tcp (void); + + int write (const std::string &); + int write (uint8_t *, unsigned int); + + int read (uint8_t *, unsigned int, double); + + int open (const std::string &, int); + int close (void); + int get_fd (void) const { return fd; } + + int flush (int mode); + + int set_timeout (double); + double get_timeout (void) const { return timeout; } + + // Overloaded base functions + double tcp_value (void) const { return (double)fd; } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true; } + // 4.4+ + bool isobject (void) const { return true; } + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + octave_base_value * unique_clone (void) { count++; return this; } + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + int get_bytesavailable (void) const; + + std::string get_name (void) const { return name; } + std::string set_name (const std::string &); + + std::string get_remote_addr (void) const; + + int get_remote_port (void) const; + + bool is_open(void) const; + + std::string get_type (void) const { return "tcp"; } + + std::string get_status (void) const; + + int get_local_port (void) const; +private: + string_vector fieldnames; + + int fd; + double timeout; + + std::string name; + sockaddr_in remote_addr; + sockaddr_in local_addr; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc new file mode 100644 index 0000000..8acba48 --- /dev/null +++ b/src/tcp/tcp_close.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include "tcp_class.h" +#endif + +// PKG_ADD: autoload ("tcp_close", "tcp.oct"); +DEFUN_DLD (tcp_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} tcp_close (@var{tcp})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcp} - instance of @var{octave_tcp} class.\n \ +\n \ +@subsubheading Outputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error ("tcp: Your system doesn't support the TCP interface"); + return octave_value (); +#else + + if (args.length () != 1 || args (0).type_id () != octave_tcp::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_tcp* tcp = NULL; + + const octave_base_value& rep = args (0).get_rep (); + tcp = &((octave_tcp &)rep); + + tcp->close (); + + return octave_value (); +#endif +} +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80); +%! tcp_close (a); + +%!error tcp_close (1) + +%!error tcp_close () +#endif diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc new file mode 100644 index 0000000..534a50a --- /dev/null +++ b/src/tcp/tcp_read.cc @@ -0,0 +1,141 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include + +#include + +#include "tcp_class.h" + +#endif + +// PKG_ADD: autoload ("tcp_read", "tcp.oct"); +DEFUN_DLD (tcp_read, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } tcp_read (@var{tcp}, @var{n}, @var{timeout})\n \ +\n\ +Read from tcp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcp} - instance of @var{octave_tcp} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer@* \ +@var{timeout} - timeout in ms if different from default of type Integer\n \ +\n\ +@subsubheading Outputs\n \ +@var{count} - number of bytes successfully read as an Integer@*\n \ +@var{data} - data bytes themselves as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error ("tcp: Your system doesn't support the TCP interface"); + return octave_value (); +#else + + if (args.length() < 2 || args.length () > 3 || args (0).type_id () != octave_tcp::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 0; + + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ())) + { + print_usage (); + return octave_value (-1); + } + + if ( args.length () > 2 ) + { + if ( !(args (2).OV_ISINTEGER () || args (2).OV_ISFLOAT ())) + { + print_usage (); + return octave_value (-1); + } + } + + buffer_len = args (1).int_value (); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("tcp_read: cannot allocate requested memory: %s\n", strerror(errno)); + return octave_value (-1); + } + + octave_tcp* tcp = NULL; + + const octave_base_value& rep = args (0).get_rep (); + tcp = &((octave_tcp &)rep); + + double timeout = tcp->get_timeout (); + if (args.length () == 3) + { + timeout = args (2).double_value (); + } + + // Read data + int bytes_read = tcp->read (buffer, buffer_len, timeout); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data (dim_vector (1, bytes_read) ); + + for (int i = 0; i < bytes_read; i++) + data(i) = buffer[i]; + + return_list(0) = data; + return_list(1) = bytes_read; + + return return_list; +#endif +} + +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80); +%! assert (! isnull (a)); +%! # server should be waiting for us to send request +%! fail ("tcp_read (a, 10, 0, 0)", "Invalid call to tcp_read"); +%! +%! [d,c] = tcp_read (a, 1, 0); +%! assert (0, c); +%! assert (isempty (d)); +%! +%! tic; +%! [d,c] = tcp_read (a, 1, 1000); +%! t = toc; +%! assert (c, 0); +%! assert (isempty (d)); +%! assert (t, 1.0, 0.1) +%! +%! tcp_close (a); + +%!error tcp_read (1) + +%!error tcp_read (1, 10, 0) + +#endif diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc new file mode 100644 index 0000000..e40a2fa --- /dev/null +++ b/src/tcp/tcp_timeout.cc @@ -0,0 +1,96 @@ +// Copyright (C) 2017,2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include "tcp_class.h" +#endif + +// PKG_ADD: autoload ("tcp_timeout", "tcp.oct"); +DEFUN_DLD (tcp_timeout, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} tcp_timeout (@var{tcp}, @var{timeout})\n \ +@deftypefnx {Loadable Function} {@var{t} = } tcp_timeout (@var{tcp})\n \ +\n\ +Set new or get existing tcp interface timeout parameter used for tcp_read() requests. The timeout value is specified in milliseconds.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcp} - instance of @var{octave_tcp} class.@* \ +@var{timeout} - tcp_read() timeout value in milliseconds. Value of -1 means a blocking call.\n \ +\n\ +@subsubheading Outputs\n \ +If @var{timeout} parameter is omitted, the tcp_timeout() shall return current timeout value as the result @var{t}.\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error("tcp: Your system doesn't support the TCP interface"); + return octave_value (); +#else + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_tcp::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_tcp* tcp = NULL; + + const octave_base_value& rep = args (0).get_rep (); + tcp = &((octave_tcp &)rep); + + // Setting new timeout + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + if (args (1).double_value() >= 0.0) + tcp->set_timeout (args (1).double_value ()/1000.0); + else + tcp->set_timeout (-1); + + return octave_value (); // Should it return by default? + } + + // Returning current timeout + double timeout = tcp->get_timeout (); + if (timeout < 0) + return octave_value (-1); + else + return octave_value (timeout*1000.0); +#endif +} + +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80); +%! assert(tcp_timeout(a), -1); +%! a.timeout = 2.5; +%! assert(tcp_timeout(a), 2500); +%! a.timeout = 0; +%! assert(tcp_timeout(a), 0); +%! a.timeout = -1; +%! assert(tcp_timeout(a), -1); +%! tcp_close(a); +#endif diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc new file mode 100644 index 0000000..6feeb27 --- /dev/null +++ b/src/tcp/tcp_write.cc @@ -0,0 +1,107 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include "tcp_class.h" +#endif + +// PKG_ADD: autoload ("tcp_write", "tcp.oct"); +DEFUN_DLD (tcp_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } tcp_write (@var{tcp}, @var{data})\n \ +\n\ +Write data to a tcp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcp} - instance of @var{octave_tcp} class.@* \ +@var{data} - data to be written to the tcp interface. Can be either of String or uint8 type.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, tcp_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error("tcp: Your system doesn't support the TCP interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_tcp::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_tcp *tcp = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + tcp = &((octave_tcp &)rep); + + if (args (1).is_string ()) // String + { + retval = tcp->write (args (1).string_value ()); + } + else if (args (1).is_uint8_type ()) + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + // memcpy? + if (buf == NULL) + { + error ("tcp_write: cannot allocate requested memory"); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data(i)); + + retval = tcp->write (buf, data.numel ()); + + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} + +#if 0 +%!error tcp_write(1, uint8([104 101 108 108 111])) + +%!error tcp_write() + +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcp (addr, 80);; +%! # call HTTP HEAD +%! req = "HEAD / HTTP/1.1\r\n\r\n"; +%! assert (length (req), tcp_write (a, req)); +%! [d, c] = tcp_read (a, 12, 5000); +%! tcp_close (a); +%! assert (12, c); +%! assert (c, length (d)); +#endif + diff --git a/src/tcpclient/Makefile.in b/src/tcpclient/Makefile.in new file mode 100644 index 0000000..a780789 --- /dev/null +++ b/src/tcpclient/Makefile.in @@ -0,0 +1,7 @@ +OCT := ../tcpclient.oct +OBJ := tcpclient.o __tcpclient_write__.o __tcpclient_read__.o tcpclient_class.o __tcpclient_properties__.o __tcpclient_pkg_lock__.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk + diff --git a/src/tcpclient/__tcpclient_pkg_lock__.cc b/src/tcpclient/__tcpclient_pkg_lock__.cc new file mode 100644 index 0000000..ac0850e --- /dev/null +++ b/src/tcpclient/__tcpclient_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2021 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__tcpclient_pkg_lock__", "tcpclient.oct"); +// PKG_ADD: __tcpclient_pkg_lock__(1); +// PKG_DEL: __tcpclient_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__tcpclient_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__tcpclient_pkg_lock__")) + interp.munlock("__tcpclient_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__tcpclient_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc new file mode 100644 index 0000000..9b00766 --- /dev/null +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -0,0 +1,193 @@ +// Copyright (C) 2021 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_TCP +# include "tcpclient_class.h" +#endif + +static octave_value_list get_terminator (octave_tcpclient* tcp) +{ + // may have a single terminator or a start and stop + std::string in = tcp->get_input_terminator (); + std::string out = tcp->get_output_terminator (); + + if (in == out) + return octave_value (in); + else + { + octave_value_list ret; + ret(0) = octave_value(in); + ret(1) = octave_value(out); + return octave_value (ret); + } +} + +static octave_value set_terminator(octave_tcpclient* tcp, const octave_value_list& args) +{ + if (args.length () == 1) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + tcp->set_input_terminator (args (0).string_value()); + tcp->set_output_terminator (args (0).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () == 2) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + if ( !(args (1).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + tcp->set_input_terminator (args (0).string_value()); + tcp->set_output_terminator (args (1).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () > 2) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + return octave_value(); +} + +// PKG_ADD: autoload ("__tcpclient_properties__", "tcpclient.oct"); +DEFUN_DLD (__tcpclient_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __tcpclient_properties__ (@var{octave_tcpclient}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_TCP + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_tcpclient::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_tcpclient* tcpclient = &((octave_tcpclient &)rep); + + std::string property = args(1).string_value (); + std::transform (property.begin (), property.end (), property.begin (), ::tolower); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (tcpclient->get_name ()); + else if (property == "type") + return octave_value (tcpclient->get_type ()); + else if (property == "port") + return octave_value (tcpclient->get_port ()); + else if (property == "address") + return octave_value (tcpclient->get_address ()); + else if (property == "status") + return octave_value (tcpclient->get_status ()); + else if (property == "timeout") + return octave_value (tcpclient->get_timeout ()); + else if (property == "numbytesavailable") + return octave_value (tcpclient->get_numbytesavailable ()); + else if (property == "numbyteswritten") + return octave_value (tcpclient->get_numbyteswritten ()); + else if (property == "byteorder") + return octave_value (tcpclient->get_byteorder ()); + else if (property == "userdata") + return octave_value (tcpclient->get_userdata ()); + else if (property == "terminator") + return get_terminator (tcpclient); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (tcpclient->set_name (args(2).string_value ())); + else if (property == "type") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "port") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "address") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "timeout") + return octave_value (tcpclient->set_timeout (args(2).double_value ())); + else if (property == "userdata") + { tcpclient->set_userdata (args(2)); return octave_value (); } + else if (property == "byteorder") + return octave_value (tcpclient->set_byteorder (args(2).string_value ())); + else if (property == "flush") + return octave_value (tcpclient->flush (args(2).int_value ())); + else if (property == "terminator") + return set_terminator (tcpclient, args.slice (2, args.length ()-2)); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the TCP interface"); +} +#if 0 +%!shared ip +%! ip = resolvehost("www.octave.org", "address"); + +%!test +%! # test get +%! a = tcpclient (ip, 80); +%! assert (__tcpclient_properties__ (a,"type"), "tcpclient"); +%! assert (__tcpclient_properties__ (a,"port"), 80); +%! assert (__tcpclient_properties__ (a,"address"), ip); +%! assert (__tcpclient_properties__ (a,"timeout"), -1); +%! assert (__tcpclient_properties__ (a,"status"), "open"); +%! assert (__tcpclient_properties__ (a,"name"), ["TCP-" ip]); +%! fail ("__tcpclient_properties__ (a,'invalid')", "invalid property name"); +%! clear a + +%!test +%! # test set +%! a = tcpclient(ip, 80); +%! __tcpclient_properties__ (a, 'name', "mytest"); +%! assert (__tcpclient_properties__ (a,"name"), "mytest"); +%! fail ("__tcpclient_properties__ (a,'invalid', 1)", "invalid property name"); +%! clear a + +%!test +%! # test flush +%! a = tcpclient(ip, 80); +%! __tcpclient_properties__ (a, 'flush', 0); +%! __tcpclient_properties__ (a, 'flush', 1); +%! __tcpclient_properties__ (a, 'flush', 2); +%! fail ("__tcpclient_properties__ (a,'flush')", "invalid property name"); +%! clear a + + +%!error __tcpclient_properties__ () + +%!error __tcpclient_properties__ (1) + +%!test +%! a = tcpclient (ip, 80); +%! fail ("__tcpclient_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); +%! clear a + +#endif diff --git a/src/tcpclient/__tcpclient_read__.cc b/src/tcpclient/__tcpclient_read__.cc new file mode 100644 index 0000000..f7a868e --- /dev/null +++ b/src/tcpclient/__tcpclient_read__.cc @@ -0,0 +1,139 @@ +// Copyright (C) 2021 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include + +#include + +#include "tcpclient_class.h" + +#endif + +// PKG_ADD: autoload ("__tcpclient_read__", "tcpclient.oct"); +DEFUN_DLD (__tcpclient_read__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } __tcpclient_read__ (@var{tcpclient}, @var{n}, @var{timeout})\n \ +\n\ +Private function t read from tcpclient interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcpclient} - instance of @var{octave_tcpclient} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer@* \ +@var{timeout} - timeout in ms if different from default of type Integer\n \ +\n\ +@subsubheading Outputs\n \ +@var{count} - number of bytes successfully read as an Integer@*\n \ +@var{data} - data bytes themselves as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error ("tcpclient: Your system doesn't support the TCP interface"); + return octave_value (); +#else + + if (args.length() < 2 || args.length () > 3 || args (0).type_id () != octave_tcpclient::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 0; + + if ( !(args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ())) + { + print_usage (); + return octave_value (-1); + } + + if ( args.length () > 2 ) + { + if ( !(args (2).OV_ISINTEGER () || args (2).OV_ISFLOAT ())) + { + print_usage (); + return octave_value (-1); + } + } + + buffer_len = args (1).int_value (); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("tcpclient_read: cannot allocate requested memory: %s\n", strerror(errno)); + return octave_value (-1); + } + + octave_tcpclient* tcpclient = NULL; + + const octave_base_value& rep = args (0).get_rep (); + tcpclient = &((octave_tcpclient &)rep); + + double timeout = tcpclient->get_timeout () * 1000; + if (args.length () == 3) + { + timeout = args (2).double_value (); + } + + // Read data + int bytes_read = tcpclient->read (buffer, buffer_len, timeout); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data (dim_vector (1, bytes_read) ); + + for (int i = 0; i < bytes_read; i++) + data(i) = buffer[i]; + + return_list(0) = data; + return_list(1) = bytes_read; + + return return_list; +#endif +} + +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcpclient (addr, 80); +%! assert (! isnull (a)); +%! # server should be waiting for us to send request +%! fail ("__tcpclient_read__ (a, 10, 0, 0)", "Invalid call to __tcpclient_read__"); +%! +%! [d,c] = __tcpclient_read__ (a, 1, 0); +%! assert (0, c); +%! assert (isempty (d)); +%! +%! tic; +%! [d,c] = __tcpclient_read__ (a, 1, 1000); +%! t = toc; +%! assert (c, 0); +%! assert (isempty (d)); +%! assert (t, 1.0, 0.1) +%! +%! clear a + +%!error __tcpclient_read__ (1) + +%!error __tcpclient_read__ (1, 10, 0) + +#endif diff --git a/src/tcpclient/__tcpclient_write__.cc b/src/tcpclient/__tcpclient_write__.cc new file mode 100644 index 0000000..6f73363 --- /dev/null +++ b/src/tcpclient/__tcpclient_write__.cc @@ -0,0 +1,105 @@ +// Copyright (C) 2021 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include "tcpclient_class.h" +#endif + +// PKG_ADD: autoload ("__tcpclient_write__", "tcpclient.oct"); +DEFUN_DLD (__tcpclient_write__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } __tcpclient_write__ (@var{tcpclient}, @var{data})\n \ +\n\ +Private function to write data to a tcpclient interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{tcpclient} - instance of @var{octave_tcpclient} class.@* \ +@var{data} - data to be written to the tcpclient interface. Can be either of String or uint8 type.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, __tcpclient_write__() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error("tcpclient: Your system doesn't support the TCP interface"); + return octave_value (); +#else + if (args.length () != 2 || args (0).type_id () != octave_tcpclient::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_tcpclient *tcpclient = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + tcpclient = &((octave_tcpclient &)rep); + + if (args (1).is_string ()) // String + { + retval = tcpclient->write (args (1).string_value ()); + } + else if (args (1).is_uint8_type ()) + { + NDArray data = args (1).array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + // memcpy? + if (buf == NULL) + { + error ("tcpclient_write: cannot allocate requested memory"); + return octave_value (-1); + } + + for (int i = 0; i < data.numel (); i++) + buf[i] = static_cast(data(i)); + + retval = tcpclient->write (buf, data.numel ()); + + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} + +#if 0 +%!error __tcpclient_write__(1, uint8([104 101 108 108 111])) + +%!error __tcpclient_write__() + +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcpclient (addr, 80);; +%! # call HTTP HEAD +%! req = "HEAD / HTTP/1.1\r\n\r\n"; +%! assert (length (req), __tcpclient_write__ (a, req)); +%! [d, c] = __tcpclient_read__ (a, 12, 5000); +%! clear a +%! assert (12, c); +%! assert (c, length (d)); +#endif + diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc new file mode 100644 index 0000000..7a6f9f5 --- /dev/null +++ b/src/tcpclient/tcpclient.cc @@ -0,0 +1,218 @@ +// Copyright (C) 2021 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_TCP +# include "tcpclient_class.h" +#endif + +// PKG_ADD: autoload ("tcpclient", "tcpclient.oct"); +DEFUN_DLD (tcpclient, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{tcpclient} = } tcpclient (@var{ipaddress}, @var{port})\n \ +@deftypefnx {Loadable Function} {@var{tcpclient} = } tcpclient (@var{ipaddress}, @var{port}, [@var{propertyname}, @var{propertyvalue}])\n \ +\n\ +Open tcpclient interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{ipaddress} - the ip address of type String.@* \ +@var{port} - the port number to connect.@* \ +@var{propname},@var{propvalue} - property name/value pairs.\n \ +\n \ +Known input properties:\n \ +@table @asis\n \ +@item Name\n \ +name value\n \ +@item Timeout\n \ +Numeric timeout value or -1 to wait forever\n \ +@item UserData\n \ +User data value.\n \ +@end table\n \ +\n\ +@subsubheading Outputs\n \ +The tcpclient() shall return instance of @var{octave_tcpclient} class as the result @var{tcpclient}.\n \ +\n \ +@subsubheading Properties\n \ +The tcpclient object has the following public properties:\n \ +@table @asis\n \ +@item Name\n \ +name assigned to the tcpclient object\n \ +@item Type\n \ +instrument type 'tcpclient' (readonly)\n \ +@item Port\n \ +remote port number (Readonly)\n \ +@item Address\n \ +remote host address (Readonly)\n \ +@item Status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item Timeout\n \ +timeout value in seconds used for waiting for data\n \ +@item NumBytesAvailable\n \ +number of bytes currently available to read (readonly)\n \ +@item NumBytesWritten\n \ +number of bytes currently available to read (readonly)\n \ +@item ByteOrder\n \ +Byte order for data (currently not used)\n \ +@item Terminator\n \ +Terminator value used for string data (currently not used)\n \ +@item UserData\n \ +User data\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_TCP + error("tcpclient: Your system doesn't support the TCP interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + std::string address ("127.0.0.1"); + std::string name = ""; + int port = 23; + double timeout = -1; + octave_value userdata = Matrix(); + + // Parse the function arguments + if (args.length () < 2) + { + print_usage (); + return octave_value (); + } + + if (args (0).is_string ()) + { + address = args (0).string_value (); + } + else + { + error ("Expected address as a string"); + return octave_value (); + } + + if (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) + { + port = args (1).int_value (); + } + else + { + error ("Expected port as a number"); + return octave_value (); + } + + if (args.length () > 2) + { + if ((args.length () & 1) == 1) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + + // go through the properties + for(int i=2;iopen (address, port) < 0) + { + return octave_value (); + } + + retval->set_timeout (timeout); + + //retval->flush (2); + if (name.length() > 0) + retval->set_name (name); + + retval->set_userdata (userdata); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcpclient (addr, 80); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_tcpclient')); +%! clear a + +%!test +%! addr = resolvehost ('gnu.org', 'address'); +%! a = tcpclient (addr, 80, 'name', 'test', 'timeout', 2.5); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_tcpclient')); +%! assert (get(a, 'Name'), 'test'); +%! assert (get(a, 'Timeout'), 2.5); +%! clear a + +%!error tcpclient (1) + +%!error tcpclient (1, 1) + +%!error tcpclient ('127.0.0.1', '80', 'prop1') + +#endif diff --git a/src/tcpclient/tcpclient_class.cc b/src/tcpclient/tcpclient_class.cc new file mode 100644 index 0000000..57706af --- /dev/null +++ b/src/tcpclient/tcpclient_class.cc @@ -0,0 +1,584 @@ +// Copyright (C) 2021 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_TCP +#include +#include +#include + +#ifndef __WIN32__ +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#ifndef __WIN32__ +#define SOCKETERR errno +#define STRSOCKETERR strerror(errno) +#define IOCTL_TYPE int +#else +#define SOCKETERR WSAGetLastError() +#define STRSOCKETERR "" +#define IOCTL_TYPE u_long +#define ioctl ioctlsocket +#define socklen_t int +#endif + +#include "tcpclient_class.h" +#include + +static struct timeval +to_timeval(int ms) +{ + struct timeval tv; + if(ms <= 0) + { + tv.tv_usec = 0; + tv.tv_sec = 0; + } + else + { + tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms/1000;; + } + return tv; +} + +static std::string +to_ip_str (const sockaddr_in *in) +{ + u_long addr = ntohl (in->sin_addr.s_addr); + + int b[4]; + b[0] = (addr>>24)&0xff; + b[1] = (addr>>16)&0xff; + b[2] = (addr>>8)&0xff; + b[3] = (addr>>0)&0xff; + + std::stringstream n; + n << b[0] << "." << b[1] << "." << b[2] << "." << b[3]; + + return n.str (); +} + +static bool +lookup_addr (const std::string &ip, sockaddr_in *in) +{ + in->sin_addr.s_addr = inet_addr (ip.c_str()); + + if (in->sin_addr.s_addr == INADDR_NONE) + { + struct hostent * host = gethostbyname (ip.c_str()); + if (!host) + return false; + + memcpy(&in->sin_addr, host->h_addr_list[0], host->h_length); + } + + return true; +} + + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_tcpclient, "octave_tcpclient", "octave_tcpclient"); + +octave_tcpclient::octave_tcpclient (void) +: fieldnames(11), fd (-1), timeout(-1), name("") +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + + userData = Matrix (); + byteswritten = 0; + byteOrder = "little-endian"; + interminator = "lf"; + outterminator = "lf"; + + fieldnames[0] = "Type"; + fieldnames[1] = "Name"; + fieldnames[2] = "Port"; + fieldnames[3] = "Address"; + fieldnames[4] = "Status"; + fieldnames[5] = "Timeout"; + fieldnames[6] = "NumBytesAvailable"; + fieldnames[7] = "NumBytesWritten"; + fieldnames[8] = "ByteOrder"; + fieldnames[9] = "UserData"; + fieldnames[10] = "Terminator"; +} + +bool +octave_tcpclient::has_property(const std::string &name) const +{ + for (octave_idx_type i=0; i& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_tcpclient object cannot be indexed with %c", type[0]); + return retval; + case '.': + { + std::string property = (idx.front ()) (0).string_value (); + if (!has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__tcpclient_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_tcpclient::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_tcpclient object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + std::string property = (idx.front ()) (0).string_value (); + if (!has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__tcpclient_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_tcpclient invalid index"); + } + + } + return retval; +} + +int +octave_tcpclient::open (const std::string &address, int port) +{ + int sockerr; + + name = "TCP-" + address; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + err = WSAStartup (wVersionRequested, &wsaData); + if ( err != 0 ) + { + error( "could not initialize winsock library" ); + return -1; + } +#endif + + memset (&remote_addr, 0, sizeof (remote_addr)); + + if( !lookup_addr (address, &remote_addr)) + { + error ("tcp: error looking up remote host : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_tcpclient::close (); + return -1; + } + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons (port); + + fd = socket (AF_INET, SOCK_STREAM,0); + if (fd < 0) + { + error ("tcpclient: error opening socket : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_tcpclient::close (); + return -1; + } + + // get local socket info + memset (&local_addr, 0, sizeof (local_addr)); + socklen_t sz = sizeof (local_addr); + getsockname (fd, (struct sockaddr*)&local_addr, &sz); + + sockerr = connect (fd, (struct sockaddr*)&remote_addr, sizeof(struct sockaddr)); + if (sockerr < 0) + { + error ("tcpclient: error on connect : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_tcpclient::close (); + return -1; + } + return get_fd(); +} + +octave_tcpclient::~octave_tcpclient (void) +{ + octave_tcpclient::close (); +} + +void +octave_tcpclient::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_tcpclient::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_tcpclient::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " TCP Client Object " << get_name (); + newline(os); + os << " Address: " << get_address (); + newline(os); + os << " Port: " << get_port (); + newline(os); +} + +int +octave_tcpclient::read (uint8_t *buf, unsigned int len, double readtimeout) +{ + struct timeval tv; + + fd_set readfds; + + if (get_fd () < 0) + { + error ("tcpclient_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + // While not interrupted in blocking mode + while (bytes_read < len) + { + + OCTAVE_QUIT; + + tv = to_timeval((readtimeout < 0 || readtimeout > 1000) ? 1000 : (int)readtimeout); + + FD_ZERO (&readfds); + FD_SET (get_fd (), &readfds); + + if (::select (get_fd ()+1, &readfds, NULL, NULL, &tv) < 0) + { + error ("tcpclient_read: Error while reading/select: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + + if (FD_ISSET (get_fd (), &readfds)) + { + read_retval = ::recv(get_fd (), reinterpret_cast((buf + bytes_read)), len - bytes_read, 0); + if (read_retval < 0) + { + error ("tcpclient_read: Error while reading: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else if (read_retval == 0) + { + error ("tcpclient_read: Connection lost: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else + { + bytes_read += read_retval; + } + } + else + { + // time out + if (readtimeout >= 0) + { + // real timeout + if (readtimeout <= 1000) + break; + // timed out 1 sec of an actual timeout + else + readtimeout -= 1000; + } + } + + } + + return bytes_read; +} + +int +octave_tcpclient::write (const std::string &str) +{ + if (get_fd () < 0) + { + error ("tcpclient: Interface must be opened first..."); + return -1; + } + + int wrote = ::send (get_fd (), str.c_str (), str.length (), 0); + if(wrote > 0) + byteswritten += wrote; + return wrote; +} + +int +octave_tcpclient::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("tcpclient: Interface must be opened first..."); + return -1; + } + + int wrote = ::send (get_fd (), reinterpret_cast(buf), len, 0); + if(wrote > 0) + byteswritten += wrote; + return wrote; +} + +int +octave_tcpclient::set_timeout (double newtimeout) +{ + if (get_fd () < 0) + { + error ("tcpclient: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 ) + { + error ("tcpclient_timeout: timeout value must be -1 or positive"); + return -1; + } + + timeout = newtimeout; + + return 1; +} + +int +octave_tcpclient::close (void) +{ + int retval = -1; + + if (get_fd() > 0) + { +#ifndef __WIN32__ + retval = ::close (get_fd ()); +#else + retval = ::closesocket (get_fd ()); +#endif + fd = -1; + } + + return retval; +} + +int +octave_tcpclient::get_numbytesavailable () const +{ + IOCTL_TYPE available = 0; + + if (get_fd () <= 0) + { + return 0; + } + ioctl (get_fd (), FIONREAD, &available); + + return available; +} + +int +octave_tcpclient::get_port (void) const +{ + return ntohs (remote_addr.sin_port); +} + +std::string +octave_tcpclient::get_address (void) const +{ + return to_ip_str (&remote_addr); +} + +std::string +octave_tcpclient::set_name (const std::string &n) +{ + if (n.length() == 0 ) + { + error ("tcpclient_name: value must be non empty"); + } + else + { + name = n; + } + + return name; +} + +bool +octave_tcpclient::is_open (void) const +{ + return fd > 0; +} + +std::string +octave_tcpclient::get_status (void) const +{ + if (! is_open ()) + { + return "closed"; + } + else + { + return "open"; + } +} + +int +octave_tcpclient::flush (int mode) +{ + int retval = -1; + + if (get_fd() > 0) + { + uint8_t tmpbuffer[1024]; + if (mode == 0 || mode == 2) + { + // we are sending data as we get it, so no outout + // buffers to flush + } + if (mode == 1 || mode == 2) + { + while (read (tmpbuffer, 1024, 0) > 0) {} + } + } + + return retval; +} + + +int +octave_tcpclient::set_byteorder(const std::string& neworder) +{ + std::string order = neworder; + std::transform (order.begin (), order.end (), order.begin (), ::tolower); + if (order == "big" || order == "big-endian") + byteOrder = "big-endian"; + else if (order == "little" || order == "little-endian") + byteOrder = "little-endian"; + else + error ("octave_tcpclient invalid byteorder"); + + return 1; +} + +int +octave_tcpclient::set_input_terminator(const std::string& t) +{ + std::string term = t; + std::transform (term.begin (), term.end (), term.begin (), ::tolower); + if (term != "lf" && term != "cr" && term != "cr/lf") + error ("octave_tcpclient invalid input terminator"); + else + interminator = term; + + return 1; +} + +int +octave_tcpclient::set_output_terminator(const std::string& t) +{ + std::string term = t; + std::transform (term.begin (), term.end (), term.begin (), ::tolower); + if (term != "lf" && term != "cr" && term != "cr/lf") + error ("octave_tcpclient invalid output terminator"); + else + outterminator = term; + + return 1; +} + +#endif diff --git a/src/tcpclient/tcpclient_class.h b/src/tcpclient/tcpclient_class.h new file mode 100644 index 0000000..c3b39ff --- /dev/null +++ b/src/tcpclient/tcpclient_class.h @@ -0,0 +1,154 @@ +// Copyright (C) 2021 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 . + +#ifndef TCP_CLASS_H +#define TCP_CLASS_H + +#include +#include + +#include + +#ifndef __WIN32__ +# include +#else +# include +#endif + +class octave_tcpclient : public octave_base_value +{ +public: + octave_tcpclient (void); + ~octave_tcpclient (void); + + int write (const std::string &); + int write (uint8_t *, unsigned int); + + int read (uint8_t *, unsigned int, double); + + int open (const std::string &, int); + int close (void); + int get_fd (void) const { return fd; } + + int flush (int mode); + + // Overloaded base functions + double tcpclient_value (void) const { return (double)fd; } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_map (void) const { return true; } + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool is_object (void) const { return true; } + // 4.4+ + bool isobject (void) const { return true; } + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + octave_base_value * unique_clone (void) { count++; return this; } + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + int get_numbytesavailable (void) const; + unsigned int get_numbyteswritten (void) const { return byteswritten; } + + std::string get_name (void) const { return name; } + std::string set_name (const std::string &); + + int set_timeout (double); + double get_timeout (void) const { return timeout; } + + std::string get_address (void) const; + int get_port (void) const; + + bool is_open(void) const; + + std::string get_type (void) const { return "tcpclient"; } + + std::string get_status (void) const; + + octave_value get_userdata () const + { + return userData; + } + + void set_userdata (const octave_value &newv) + { + userData = newv; + } + + int set_byteorder(const std::string& /* order */); + + std::string get_byteorder() const + { + return byteOrder; + } + + int set_input_terminator(const std::string& /* term */); + int set_output_terminator(const std::string& /* term */); + + std::string get_input_terminator() const + { + return interminator; + } + + std::string get_output_terminator() const + { + return outterminator; + } + + +private: + bool has_property(const std::string &name) const; + + string_vector fieldnames; + + int fd; + double timeout; + + std::string name; + sockaddr_in remote_addr; + sockaddr_in local_addr; + octave_value userData; + std::string byteOrder; + unsigned int byteswritten; + std::string interminator; + std::string outterminator; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/udp/Makefile.in b/src/udp/Makefile.in new file mode 100644 index 0000000..fa380b2 --- /dev/null +++ b/src/udp/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../udp.oct +OBJ := udp.o udp_timeout.o udp_write.o udp_close.o udp_read.o __udp_properties__.o udp_class.o __udp_pkg_lock__.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/udp/__udp_pkg_lock__.cc b/src/udp/__udp_pkg_lock__.cc new file mode 100644 index 0000000..a0f58ce --- /dev/null +++ b/src/udp/__udp_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__udp_pkg_lock__", "udp.oct"); +// PKG_ADD: __udp_pkg_lock__(1); +// PKG_DEL: __udp_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__udp_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__udp_pkg_lock__")) + interp.munlock("__udp_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__udp_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/udp/__udp_properties__.cc b/src/udp/__udp_properties__.cc new file mode 100644 index 0000000..ea1ec80 --- /dev/null +++ b/src/udp/__udp_properties__.cc @@ -0,0 +1,152 @@ +// Copyright (C) 2012 Andrius Sutas +// Copyright (C) 2014 Stefan Mahr +// Copyright (C) 2016 John Donoghue +// Copyright (C) 2019 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udp_class.h" +#endif + + +// PKG_ADD: autoload ("__udp_properties__", "udp.oct"); +DEFUN_DLD (__udp_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __udp_properties__ (@var{octave_udp}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_UDP + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_udp::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_udp* udp = &((octave_udp &)rep); + + std::string property = args(1).string_value (); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (udp->get_name ()); + else if (property == "type") + return octave_value (udp->get_type ()); + else if (property == "remoteport") + return octave_value (udp->get_remote_port ()); + else if (property == "remotehost") + return octave_value (udp->get_remote_addr ()); + else if (property == "localport") + return octave_value (udp->get_local_port ()); + else if (property == "localhost") + return octave_value (udp->get_local_addr ()); + else if (property == "status") + return octave_value (udp->get_status ()); + else if (property == "timeout") + return octave_value (udp->get_timeout ()); + else if (property == "bytesavailable") + return octave_value (udp->get_bytesavailable ()); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (udp->set_name (args(2).string_value ())); + else if (property == "type") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "remoteport") + return octave_value (udp->set_remote_port (args(2).int_value ())); + else if (property == "remotehost") + return octave_value (udp->set_remote_addr (args(2).string_value ())); + else if (property == "localport") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "localhost") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "timeout") + return octave_value (udp->set_timeout (args(2).double_value ())); + else if (property == "flush") + return octave_value (udp->flush (args(2).int_value ())); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the UDP interface"); +} +#if 0 +%!test +%! # test get +%! a = udp (); +%! assert (__udp_properties__ (a,"type"), "udp"); +%! assert (__udp_properties__ (a,"remoteport"), 23); +%! assert (__udp_properties__ (a,"remotehost"), "127.0.0.1"); +%! assert (__udp_properties__ (a,"timeout"), -1); +%! assert (__udp_properties__ (a,"status"), "open"); +%! assert (__udp_properties__ (a,"name"), "UDP-127.0.0.1"); +%! fail ("__udp_properties__ (a,'invalid')", "invalid property name"); +%! udp_close (a); +%! assert (__udp_properties__ (a,"status"), "closed"); + +%!test +%! # test set +%! a = udp(); +%! __udp_properties__ (a, 'name', "mytest"); +%! assert (__udp_properties__ (a,"name"), "mytest"); +%! fail ("__udp_properties__ (a,'invalid', 1)", "invalid property name"); +%! udp_close (a); + +%!test +%! # test flush +%! a = udp(); +%! __udp_properties__ (a, 'flush', 0); +%! __udp_properties__ (a, 'flush', 1); +%! __udp_properties__ (a, 'flush', 2); +%! fail ("__udp_properties__ (a,'flush')", "invalid property name"); +%! udp_close (a); + +%!test +%! # test subsref and get/set +%! a = udp (); +%! a.name = "test1"; +%! assert (isa(a, "octave_udp")); +%! assert (a.name, "test1"); +%! assert (get(a, 'name'), "test1"); +%! +%! set (a, "name", "test2"); +%! assert (a.name, "test2"); +%! assert (get(a, 'name'), "test2"); + +%!error __udp_properties__ () + +%!error __udp_properties__ (1) + +%!test +%! a = udp (); +%! fail ("__udp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); +%! udp_close (a); + +#endif diff --git a/src/udp/udp.cc b/src/udp/udp.cc new file mode 100644 index 0000000..358b466 --- /dev/null +++ b/src/udp/udp.cc @@ -0,0 +1,220 @@ +// Copyright (C) 2016-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udp_class.h" +#endif + +// PKG_ADD: autoload ("udp", "udp.oct"); +DEFUN_DLD (udp, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{udp} = } udp ()\n \ +@deftypefnx {Loadable Function} {@var{udp} = } udp (@var{remoteipaddress}, @var{remoteport})\n \ +@deftypefnx {Loadable Function} {@var{udp} = } udp (@var{remoteipaddress}, @var{remoteport}, [@var{propertyname}, @var{propertyvalue} ...])\n \ +\n\ +Open udp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{remoteipaddress} - the ip address of type String. If omitted defaults to '127.0.0.1'.@* \n \ +@var{remoteport} - the port number to connect. If omitted defaults to 23.@* \n \ +@var{localport} - the local port number to bind. If omitted defaults to 0@* \n \ +@var{propertyname}, @var{propertyvalue} - property name/value pair\n \ +\n\ +@subsubheading Outputs\n \ +The udp() shall return instance of @var{octave_udp} class as the result @var{udp}.\n \ +\n \ +@subsubheading Properties\n \ +The udp object has the following public properties:\n \ +@table @asis\n \ +@item name\n \ +name assigned to the udp object\n \ +@item type\n \ +instrument type 'udp' (readonly)\n \ +@item localport\n \ +local port number (readonly)\n \ +@item localhost\n \ +local host address (readonly)\n \ +@item remoteport\n \ +remote port number\n \ +@item remotehost\n \ +remote host\n \ +@item status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item timeout\n \ +timeout value in seconds used for waiting for data\n \ +@item bytesavailable\n \ +number of bytes currently available to read (readonly)\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udp: Your system doesn't support the UDP interface"); + return octave_value(); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage(); + return octave_value(); + } + + // Default values + std::string name = ""; + std::string address("127.0.0.1"); + int port = 23; + double timeout = -1; + int localport = 0; + + // Parse the function arguments + if (args.length() > 0) + { + if (args(0).is_string()) + { + address = args(0).string_value(); + } + else + { + print_usage(); + return octave_value(); + } + + } + + // is_float_type() is or'ed to allow expression like ("", 123), without user + // having to use ("", int32(123)), as we still only take "int_value" + if (args.length() > 1) + { + if (args(1).OV_ISINTEGER() || args(1).OV_ISFLOAT()) + { + port = args(1).int_value(); + } + else + { + print_usage(); + return octave_value(); + } + } + + if (args.length() > 2 && ((args.length() & 1) == 1)) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + + if (args.length() > 2) + { + // go through the properties + for(int i=2;iopen(address, port, localport) < 0) + { + return octave_value(); + } + + retval->set_timeout(timeout); + + if(name.length() > 0) + retval->set_name(name); + + return octave_value(retval); +#endif +} +#if 0 +%!test +%! # can create default udp object +%! a = udp (); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_udp')); +%! udp_close (a); + +%!error a = udp (1) + +%!error a = udp ("127.0.0.1", 23, 0) + +%!error a = udp ("127.0.0.1", 23, 0, 0) + +%!test +%! a = udp ('127.0.0.1', 23); +%! assert (! isnull (a)); +%! udp_close (a); + +%!test +%! a = udp ('127.0.0.1', 23, "name", "test", "timeout", 2.5); +%! assert (! isnull (a)); +%! assert (a.name, "test"); +%! assert (a.timeout, 2.5); +%! udp_close (a); + +%!error udp ('127.0.0.1', 23,0,0,0) +#endif diff --git a/src/udp/udp_class.cc b/src/udp/udp_class.cc new file mode 100644 index 0000000..7bce54d --- /dev/null +++ b/src/udp/udp_class.cc @@ -0,0 +1,561 @@ +// Copyright (C) 2016-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_UDP +#include +#include +#include +#include + +#ifndef __WIN32__ +# include +# include +# include +# include +# include +# include +# include +# include +# define IOCTL_TYPE int +#else +# include +# define IOCTL_TYPE u_long +# define ioctl ioctlsocket +#endif + +#include "udp_class.h" + +#ifndef __WIN32__ +# define SOCKETERR errno +# define STRSOCKETERR strerror(errno) +#else +# define SOCKETERR WSAGetLastError() +# define STRSOCKETERR "" +# define socklen_t int +#endif + +static struct timeval +to_timeval(int ms) +{ + struct timeval tv; + if(ms <= 0) + { + tv.tv_usec = 0; + tv.tv_sec = 0; + } + else + { + tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms/1000;; + } + return tv; +} + +static std::string +to_ip_str (const sockaddr_in *in) +{ + u_long addr = ntohl (in->sin_addr.s_addr); + + int b[4]; + b[0] = (addr>>24)&0xff; + b[1] = (addr>>16)&0xff; + b[2] = (addr>>8)&0xff; + b[3] = (addr>>0)&0xff; + + std::stringstream n; + n << b[0] << "." << b[1] << "." << b[2] << "." << b[3]; + + return n.str (); +} + +static bool +lookup_addr (const std::string &ip, sockaddr_in *in) +{ + in->sin_addr.s_addr = inet_addr (ip.c_str()); + + if (in->sin_addr.s_addr == INADDR_NONE) + { + struct hostent * host = gethostbyname (ip.c_str()); + if (!host) + return false; + + memcpy(&in->sin_addr, host->h_addr_list[0], host->h_length); + } + + return true; +} + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_udp, "octave_udp", "octave_udp"); + +octave_udp::octave_udp (void) +: fd(-1), timeout(-1), name(""), fieldnames(9) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + fieldnames[0] = "type"; + fieldnames[1] = "name"; + fieldnames[2] = "remoteport"; + fieldnames[3] = "remotehost"; + fieldnames[4] = "localport"; + fieldnames[5] = "status"; + fieldnames[6] = "timeout"; + fieldnames[7] = "bytesavailable"; + fieldnames[8] = "localhost"; +} + +octave_value_list +octave_udp::subsref (const std::string& type, const std::list& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_udp object cannot be indexed with %c", type[0]); + break; + case '.': + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__udp_properties__"), ovl, 1); + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_udp::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_udp object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__udp_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_udp invalid index"); + } + + } + return retval; +} + +int +octave_udp::open (const std::string &address, int port, int localport) +{ + int sockerr; + + name = "UDP-" + address; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + err = WSAStartup (wVersionRequested, &wsaData ); + if ( err != 0 ) + { + error( "could not initialize winsock library" ); + return -1; + } +#endif + + memset (&remote_addr, 0, sizeof (remote_addr)); + + if( !lookup_addr (address, &remote_addr)) + { + error ("udp: error looking up remote host : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_udp::close (); + return -1; + } + + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(port); + + fd = socket (AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) + { + error ("udp: error opening socket : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_udp::close (); + return -1; + } + + memset (&local_addr, 0, sizeof (local_addr)); + + local_addr.sin_addr.s_addr = htonl (INADDR_ANY); + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons (localport); + + sockerr = bind (fd, (struct sockaddr*)&local_addr, sizeof (local_addr)); + if (sockerr < 0) + { + error ("udp: error on bind : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_udp::close (); + return -1; + } + else if (localport == 0) + { + // if said port, 0, lookup actual port it used + socklen_t sz = sizeof (local_addr); + getsockname (fd, (struct sockaddr*)&local_addr, &sz); + } + + return get_fd(); +} + +octave_udp::~octave_udp (void) +{ + close(); +} + +void +octave_udp::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_udp::print (std::ostream& os, bool pr_as_read_syntax) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_udp::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " UDP Object " << get_name (); + newline(os); + os << " type: " << get_type (); + newline(os); + os << " status: " << get_status (); + newline(os); + os << " remoteport: " << get_remote_port (); + newline(os); + os << " remotehost: " << get_remote_addr (); + newline(os); + os << " localport: " << get_local_port (); + newline (os); +} + +int +octave_udp::get_bytesavailable () const +{ + IOCTL_TYPE available = 0; + + if (get_fd () < 0) + { + return 0; + } + ioctl (get_fd (), FIONREAD, &available); + + return available; +} + +int +octave_udp::read (uint8_t *buf, unsigned int len, double readtimeout) +{ + struct sockaddr_in addr; + socklen_t addrlen = sizeof (addr); + struct timeval tv; + + fd_set readfds; + + if (get_fd () < 0) + { + error ("udp_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + tv = to_timeval((readtimeout < 0 || readtimeout > 1000) ? 1000 : readtimeout); + + FD_ZERO (&readfds); + FD_SET (get_fd (), &readfds); + + if (::select(get_fd ()+1, &readfds, NULL, NULL, &tv) < 0) + { + error("udp_read: Error while reading/select: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + + if (FD_ISSET (get_fd (), &readfds)) + { + addrlen = sizeof (addr); + read_retval = ::recvfrom (get_fd (), reinterpret_cast((buf + bytes_read)), len - bytes_read, + 0, (struct sockaddr*)&addr, &addrlen); + + if (read_retval < 0) + { + error ("udp_read: Error while reading: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else if (read_retval == 0) + { + error ("udp_read: Connection lost: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else + { + bytes_read += read_retval; + } + } + else + { + // Timeout + if (readtimeout >= 0) + { + // real timeout + if (readtimeout <= 1000) + break; + // timed out 1 sec of an actual timeout + else + readtimeout -= 1000; + } + } + + } + + return bytes_read; +} + +int +octave_udp::write (const std::string &str) +{ + return ::sendto (get_fd (), str.c_str(), str.length(), 0, + (struct sockaddr *)&remote_addr, sizeof(remote_addr)); +} + +int +octave_udp::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error("udp: Interface must be opened first..."); + return -1; + } + + return ::sendto (get_fd(), reinterpret_cast(buf), + len, 0, (struct sockaddr *)&remote_addr, sizeof (remote_addr)); +} + +int +octave_udp::set_timeout (double newtimeout) +{ + if (get_fd () < 0) + { + error ("udp: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 ) + { + error ("udp_timeout: timeout value must be -1 or positive"); + return -1; + } + + timeout = newtimeout; + + return 1; +} + +int +octave_udp::get_remote_port (void) const +{ + return ntohs (remote_addr.sin_port); +} + +int +octave_udp::set_remote_port (int port) +{ + if (port < 0 ) + { + error ("udp_remote_port: value must be positive"); + return -1; + } + + remote_addr.sin_port = htons(port); + + return get_remote_port(); +} + +std::string +octave_udp::get_remote_addr (void) const +{ + return to_ip_str (&remote_addr); +} + +std::string +octave_udp::set_remote_addr (const std::string &addr) +{ + if (addr.length() == 0 ) + { + error ("udp_remote_addr: value must be non empty"); + } + else if ( !lookup_addr(addr, &remote_addr)) + { + error ("udp: error looking up remote host : %d - %s\n", SOCKETERR, STRSOCKETERR); + } + + return to_ip_str (&remote_addr); +} + +int +octave_udp::get_local_port (void) const +{ + return ntohs (local_addr.sin_port); +} + +std::string +octave_udp::get_local_addr (void) const +{ + return to_ip_str (&local_addr); +} + + +std::string +octave_udp::set_name (const std::string &n) +{ + if (n.length() == 0 ) + { + error ("udp_name: value must be non empty"); + } + else + { + name = n; + } + + return name; +} + +bool +octave_udp::is_open (void) const +{ + return fd >= 0; +} + +std::string +octave_udp::get_status (void) const +{ + if (! is_open ()) + { + return "closed"; + } + else + { + return "open"; + } +} + +int +octave_udp::close (void) +{ + int retval = -1; + + if (get_fd() > 0) + { +#ifndef __WIN32__ + retval = ::close (get_fd ()); +#else + retval = ::closesocket (get_fd ()); +#endif + fd = -1; + } + + return retval; +} + +int +octave_udp::flush (int mode) +{ + int retval = -1; + + if (get_fd() > 0) + { + uint8_t tmpbuffer[1024]; + if (mode == 0 || mode == 2) + { + // we are sending data as we get it, so no outout + // buffers to flush + } + if (mode == 1 || mode == 2) + { + while (read (tmpbuffer, 1024, 0) > 0) {} + } + } + + return retval; +} +#endif diff --git a/src/udp/udp_class.h b/src/udp/udp_class.h new file mode 100644 index 0000000..c6d5a9b --- /dev/null +++ b/src/udp/udp_class.h @@ -0,0 +1,125 @@ +// Copyright (C) 2016-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef UDP_CLASS_H +#define UDP_CLASS_H + +#include +#include + +#include + +#ifndef __WIN32__ +# include +#else +# include +#endif + +class octave_udp : public octave_base_value +{ +public: + octave_udp (void); + ~octave_udp (void); + + int write (const std::string &str); + int write (uint8_t *buf, unsigned int len); + + int read (uint8_t *buf, unsigned int len, double readtimeout); + + int open (const std::string &address, int port, int localport); + + int close (void); + + int get_fd (void) const { return fd; } + + int get_bytesavailable (void) const; + + // Overloaded base functions + double udp_value (void) const { return (double)fd; } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true; } + bool is_defined (void) const { return true; } + // < 4.4 + bool is_object (void) const { return true; } + // 4.4 + + bool isobject (void) const { return true; } + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + // use single copy of each udp socket + octave_base_value * unique_clone (void) { count++; return this; } + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + std::string get_name (void) const { return name; } + std::string set_name (const std::string &); + + std::string get_remote_addr (void) const; + std::string set_remote_addr (const std::string &); + + int get_remote_port (void) const; + int set_remote_port (int); + + int get_local_port (void) const; + + std::string get_local_addr (void) const; + + bool is_open(void) const; + + std::string get_type (void) const { return "udp"; } + + std::string get_status (void) const; + + int set_timeout (double); + double get_timeout (void) const { return timeout; } + + int flush(int mode); +private: + int fd; + double timeout; + std::string name; + sockaddr_in remote_addr; + sockaddr_in local_addr; + string_vector fieldnames; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/udp/udp_close.cc b/src/udp/udp_close.cc new file mode 100644 index 0000000..eb92526 --- /dev/null +++ b/src/udp/udp_close.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2016-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_UDP +#include "udp_class.h" +#endif + +// PKG_ADD: autoload ("udp_close", "udp.oct"); +DEFUN_DLD (udp_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} udp_close (@var{udp})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udp} - instance of @var{octave_udp} class.\n \ +\n\ +@subsubheading Inputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error ("udp: Your system doesn't support the UDP interface"); + return octave_value (); +#else + if (args.length () != 1 || args (0).type_id () != octave_udp::static_type_id ()) + { + print_usage(); + return octave_value (-1); + } + + octave_udp* udp = NULL; + + const octave_base_value& rep = args(0).get_rep(); + udp = &((octave_udp &)rep); + + udp->close (); + + return octave_value (); +#endif +} + +#if 0 +%!test +%! a = udp(); +%! udp_close(a); + +%!error udp_close(1) + +%!error udp_close() +#endif diff --git a/src/udp/udp_read.cc b/src/udp/udp_read.cc new file mode 100644 index 0000000..b707b4d --- /dev/null +++ b/src/udp/udp_read.cc @@ -0,0 +1,143 @@ +// Copyright (C) 2016-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +#include + +#include + +#include "udp_class.h" + +#endif + +// PKG_ADD: autoload ("udp_read", "udp.oct"); +DEFUN_DLD (udp_read, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } udp_read (@var{udp}, @var{n}, @var{timeout})\n \ +\n\ +Read from udp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udp} - instance of @var{octave_udp} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer@* \ +@var{timeout} - timeout in ms if different from default of type Integer\n \ +\n\ +@subsubheading Outputs\n \ +The udp_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udp: Your system doesn't support the UDP interface"); + return octave_value(); +#else + + if (args.length() < 2 || args.length() > 3 || args(0).type_id() != octave_udp::static_type_id()) + { + print_usage(); + return octave_value(-1); + } + + unsigned int buffer_len = 0; + + if ( !(args(1).OV_ISINTEGER() || args(1).OV_ISFLOAT())) + { + print_usage(); + return octave_value(-1); + } + + if ( args.length() > 2 ) + { + if ( !(args(2).OV_ISINTEGER() || args(2).OV_ISFLOAT())) + { + print_usage(); + return octave_value(-1); + } + } + + buffer_len = args(1).int_value(); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error("udp_read: cannot allocate requested memory: %s\n", strerror(errno)); + return octave_value(-1); + } + + octave_udp* udp = NULL; + + const octave_base_value& rep = args(0).get_rep(); + udp = &((octave_udp &)rep); + + double timeout = udp->get_timeout() * 1000; + if (args.length() == 3) + { + timeout = args(2).double_value(); + } + + // Read data + int bytes_read = udp->read(buffer, buffer_len, timeout); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data( dim_vector(1, bytes_read) ); + + for (int i = 0; i < bytes_read; i++) + data(i) = buffer[i]; + + return_list(0) = data; + return_list(1) = bytes_read; + + return return_list; +#endif +} + +#if 0 +%!test +%! a = udp (); +%! assert (! isnull (a)); +%! [d,c] = udp_read (a, 1, 0); +%! assert (c == 0); +%! assert (isempty (d)); +%! udp_close (a); + +%!error udp_read(1, 10, 0) + +%!test +%! a = udp (); +%! fail ("udp_read (a, 10, 0, 0)", "Invalid call to udp_read"); +%! udp_close (a); + +%!test +%! # does read wait +%! a = udp (); +%! assert (! isnull (a)); +%! tic; +%! [d,c] = udp_read (a, 1, 1000); +%! t = toc; +%! assert (c, 0); +%! assert (isempty (d)); +%! assert (t, 1.0, 0.1) +%! udp_close (a); + +#endif diff --git a/src/udp/udp_timeout.cc b/src/udp/udp_timeout.cc new file mode 100644 index 0000000..d8477db --- /dev/null +++ b/src/udp/udp_timeout.cc @@ -0,0 +1,106 @@ +// Copyright (C) 2017-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udp_class.h" +#endif + +// PKG_ADD: autoload ("udp_timeout", "udp.oct"); +DEFUN_DLD (udp_timeout, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} udp_timeout (@var{udp}, @var{timeout})\n \ +@deftypefnx {Loadable Function} {@var{t} = } udp_timeout (@var{udp})\n \ +\n\ +Set new or get existing udp interface timeout parameter used for udp_read() requests. The timeout value is specified in milliseconds.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udp} - instance of @var{octave_udp} class.@* \ +@var{timeout} - udp_read() timeout value in milliseconds. Value of -1 means a blocking call.\n \ +\n\ +@subsubheading Outputs\n \ +If @var{timeout} parameter is omitted, the udp_timeout() shall return current timeout value as the result @var{t}.\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udp: Your system doesn't support the UDP interface"); + return octave_value(); +#else + if (args.length() < 1 || args.length() > 2 || args(0).type_id() != octave_udp::static_type_id()) + { + print_usage(); + return octave_value(-1); + } + + octave_udp* udp = NULL; + + const octave_base_value& rep = args(0).get_rep(); + udp = &((octave_udp &)rep); + + // Setting new timeout + if (args.length() > 1) + { + if ( !(args(1).OV_ISINTEGER() || args(1).OV_ISFLOAT()) ) + { + print_usage(); + return octave_value(-1); + } + + if(args(1).double_value() >= 0) + udp->set_timeout(args(1).double_value()/1000.0); + else + udp->set_timeout(-1); + + return octave_value(); // Should it return by default? + } + + // Returning current timeout in ms + double timeout = udp->get_timeout(); + if(timeout < 0) + return octave_value(-1); + else + return octave_value(timeout*1000.0); +#endif +} + +#if 0 +%!test +%! a = udp(); +%! assert(udp_timeout(a), -1); +%! udp_timeout(a, 103); +%! assert(udp_timeout(a), 103); +%! udp_close(a); + +%!test +%! a = udp(); +%! assert(udp_timeout(a), -1); +%! a.timeout = 2; +%! assert(udp_timeout(a), 2000); +%! a.timeout = 0; +%! assert(udp_timeout(a), 0); +%! a.timeout = -1; +%! assert(udp_timeout(a), -1); + +%!error udp_timeout() + +%!error udp_timeout(1) +#endif diff --git a/src/udp/udp_write.cc b/src/udp/udp_write.cc new file mode 100644 index 0000000..fce984a --- /dev/null +++ b/src/udp/udp_write.cc @@ -0,0 +1,120 @@ +// Copyright (C) 2018-2019 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udp_class.h" +#endif + +// PKG_ADD: autoload ("udp_write", "udp.oct"); +DEFUN_DLD (udp_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } udp_write (@var{udp}, @var{data})\n \ +\n\ +Write data to a udp interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udp} - instance of @var{octave_udp} class.@* \ +@var{data} - data to be written to the udp interface. Can be either of String or uint8 type.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, udp_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udp: Your system doesn't support the UDP interface"); + return octave_value(); +#else + if (args.length() != 2 || args(0).type_id() != octave_udp::static_type_id()) + { + print_usage(); + return octave_value(-1); + } + + octave_udp *udp = NULL; + int retval; + + const octave_base_value& rep = args(0).get_rep(); + udp = &((octave_udp &)rep); + + if (args(1).is_string()) // String + { + retval = udp->write(args(1).string_value()); + } + else if (args(1).is_uint8_type ()) + { + NDArray data = args(1).array_value(); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + // memcpy? + if (buf == NULL) + { + error("udp_write: cannot allocate requested memory"); + return octave_value(-1); + } + + for (int i = 0; i < data.numel(); i++) + buf[i] = static_cast(data(i)); + + retval = udp->write(buf, data.numel()); + + } + else + { + print_usage(); + return octave_value(-1); + } + + return octave_value(retval); +#endif +} + +#if 0 +%!test +%! a = udp (); +%! b = udp (); +%! p = get (a, 'localport'); +%! set (b, 'remoteport', p); +%! p = get (b, 'localport'); +%! set (a, 'remoteport', p); +%! assert (5, udp_write (a, uint8 ([104 101 108 108 111]))); +%! [d, c] = udp_read (b, 5, 1000); +%! assert (c, 5); +%! assert (d, uint8 ([104 101 108 108 111])); +%! udp_close (a); +%! udp_close (b); + +%!error udp_write (1, uint8([104 101 108 108 111])) + +%!error udp_write () + +%!test +%! a = udp (); +%! fail ("udp_write (a, uint8([104 101 108 108 111]), 0)", "Invalid call to udp_write") +%! udp_close (a); + +%!test +%! a = udp (); +%! fail ("udp_write (a)", "Invalid call to udp_write") +%! udp_close (a); +#endif + diff --git a/src/udpport/Makefile.in b/src/udpport/Makefile.in new file mode 100644 index 0000000..4483076 --- /dev/null +++ b/src/udpport/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../udpport.oct +OBJ := udpport.o __udpport_write__.o __udpport_read__.o __udpport_properties__.o udpport_class.o __udpport_pkg_lock__.o +LFLAGS = $(LIBS) @TCPLIBS@ +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/udpport/__udpport_pkg_lock__.cc b/src/udpport/__udpport_pkg_lock__.cc new file mode 100644 index 0000000..96fea31 --- /dev/null +++ b/src/udpport/__udpport_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2021 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__udpport_pkg_lock__", "udpport.oct"); +// PKG_ADD: __udpport_pkg_lock__(1); +// PKG_DEL: __udpport_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__udpport_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__udpport_pkg_lock__")) + interp.munlock("__udpport_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__udpport_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/udpport/__udpport_properties__.cc b/src/udpport/__udpport_properties__.cc new file mode 100644 index 0000000..e273957 --- /dev/null +++ b/src/udpport/__udpport_properties__.cc @@ -0,0 +1,223 @@ +// Copyright (C) 2021 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 . + +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udpport_class.h" +#endif + +static octave_value_list get_terminator (octave_udpport* udp) +{ + // may have a single terminator or a start and stop + std::string in = udp->get_input_terminator (); + std::string out = udp->get_output_terminator (); + + if (in == out) + return octave_value (in); + else + { + octave_value_list ret; + ret(0) = octave_value(in); + ret(1) = octave_value(out); + return octave_value (ret); + } +} + +static octave_value set_terminator(octave_udpport* udp, const octave_value_list& args) +{ + if (args.length () == 1) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + udp->set_input_terminator (args (0).string_value()); + udp->set_output_terminator (args (0).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () == 2) + { + if ( !(args (0).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + if ( !(args (1).is_string ()) ) + (*current_liboctave_error_handler) ("argument must be a string"); + + udp->set_input_terminator (args (0).string_value()); + udp->set_output_terminator (args (1).string_value()); + + return octave_value (); // Should it return by default? + } + else if (args.length () > 2) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + return octave_value(); +} + +// PKG_ADD: autoload ("__udpport_properties__", "udpport.oct"); +DEFUN_DLD (__udpport_properties__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {varargout =} __udpport_properties__ (@var{octave_udpport}, @var{property}, @var{varargin})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ +#ifdef BUILD_UDP + if (args.length () < 2 || args.length () > 3 || + args(0).type_id () != octave_udpport::static_type_id () || + !args(1).is_string ()) + (*current_liboctave_error_handler) ("wrong number of arguments"); + + const octave_base_value& rep = args(0).get_rep (); + octave_udpport* udpport = &((octave_udpport &)rep); + + std::string property = args(1).string_value (); + std::transform (property.begin (), property.end (), property.begin (), ::tolower); + + if (args.length () == 2) // get + { + if (property == "name") + return octave_value (udpport->get_name ()); + else if (property == "type") + return octave_value (udpport->get_type ()); + else if (property == "remoteport") + return octave_value (udpport->get_remote_port ()); + else if (property == "remotehost") + return octave_value (udpport->get_remote_addr ()); + else if (property == "localport") + return octave_value (udpport->get_local_port ()); + else if (property == "localhost") + return octave_value (udpport->get_local_addr ()); + else if (property == "status") + return octave_value (udpport->get_status ()); + else if (property == "timeout") + return octave_value (udpport->get_timeout ()); + else if (property == "numbytesavailable") + return octave_value (udpport->get_bytesavailable ()); + else if (property == "numbyteswritten") + return octave_value (udpport->get_byteswritten ()); + else if (property == "userdata") + return octave_value (udpport->get_userdata ()); + else if (property == "terminator") + return get_terminator (udpport); + else if (property == "multicastgroup") + return octave_value (udpport->get_multicastgroup ()); + else if (property == "enablemulticast") + return octave_value (udpport->get_multicastgroup ().length () > 0 ? 1 : 0); + else if (property == "enablemulticastloopback") + return octave_value (udpport->get_multicastloopback ()); + else if (property == "enableportsharing") + return octave_value (udpport->get_enableportsharing ()); + else if (property == "enablebroadcast") + return octave_value (udpport->get_enablebroadcast ()); + else if (property == "ipaddressversion") + return octave_value (udpport->get_ipaddressversion ()); + else if (property == "byteorder") + return octave_value (udpport->get_byteorder ()); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + else // set + { + if (property == "name") + return octave_value (udpport->set_name (args(2).string_value ())); + else if (property == "type") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "localport") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "localhost") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "status") + (*current_liboctave_error_handler) ("can not set this property"); + else if (property == "timeout") + return octave_value (udpport->set_timeout (args(2).double_value ())); + else if (property == "flush") + return octave_value (udpport->flush (args(2).int_value ())); + else if (property == "terminator") + return set_terminator (udpport, args.slice (2, args.length ()-2)); + else if (property == "userdata") + { udpport->set_userdata (args(2)); return octave_value(); } + else if (property == "multicastgroup") + return octave_value (udpport->set_multicastgroup (args(2).string_value ())); + else if (property == "byteorder") + return octave_value (udpport->set_byteorder (args(2).string_value ())); + else if (property == "enablemulticastloopback") + return octave_value (udpport->set_multicastloopback (args(2).int_value ())); + else if (property == "enablebroadcast") + return octave_value (udpport->set_enablebroadcast (args(2).int_value ())); + else + (*current_liboctave_error_handler) ("invalid property name"); + } + +#endif + /* never reached in normal operation */ + (*current_liboctave_error_handler) ("Your system doesn't support the UDP interface"); +} +#if 0 +%!test +%! # test get +%! a = udpport (); +%! assert (__udpport_properties__ (a,"type"), "udpport"); +%! assert (__udpport_properties__ (a,"timeout"), -1); +%! assert (__udpport_properties__ (a,"status"), "open"); +%! assert (__udpport_properties__ (a,"name"), "UDP-0.0.0.0"); +%! fail ("__udpport_properties__ (a,'invalid')", "invalid property name"); +%! clear a; + +%!test +%! # test set +%! a = udpport(); +%! __udpport_properties__ (a, 'name', "mytest"); +%! assert (__udpport_properties__ (a,"name"), "mytest"); +%! fail ("__udpport_properties__ (a,'invalid', 1)", "invalid property name"); +%! clear a; + +%!test +%! # test flush +%! a = udpport(); +%! __udpport_properties__ (a, 'flush', 0); +%! __udpport_properties__ (a, 'flush', 1); +%! __udpport_properties__ (a, 'flush', 2); +%! fail ("__udpport_properties__ (a,'flush')", "invalid property name"); +%! clear a; + +%!test +%! # test subsref and get/set +%! a = udpport (); +%! a.Name = "test1"; +%! assert (isa(a, "octave_udpport")); +%! assert (a.Name, "test1"); +%! assert (get(a, 'Name'), "test1"); +%! +%! set (a, "Name", "test2"); +%! assert (a.Name, "test2"); +%! assert (get(a, 'Name'), "test2"); +%! assert (__udpport_properties__ (a,"Name"), "test2"); +%! clear a + +%!error __udpport_properties__ () + +%!error __udpport_properties__ (1) + +%!test +%! a = udpport (); +%! fail ("__udpport_properties__ (a, 'Name', 'test', 0)", "wrong number of arguments"); +%! clear a; + +#endif diff --git a/src/udpport/__udpport_read__.cc b/src/udpport/__udpport_read__.cc new file mode 100644 index 0000000..554b2d8 --- /dev/null +++ b/src/udpport/__udpport_read__.cc @@ -0,0 +1,157 @@ +// Copyright (C) 2021 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +#include + +#include + +#include "udpport_class.h" + +#endif + +// PKG_ADD: autoload ("__udpport_read__", "udpport.oct"); +DEFUN_DLD (__udpport_read__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } __udpport_read__ (@var{udpport}, @var{n}, @var{timeout})\n \ +@deftypefnx {Loadable Function} {[@var{data}, @var{count}. @var{srcip}, @var{srcport}] = } __udpport_read__ (@var{udpport}, @var{n}, @var{timeout})\n \ +\n\ +Provate function to read from udpport interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udpport} - instance of @var{octave_udpport} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer@* \n \ +@var{timeout} - timeout in ms if different from default of type Integer\n \ +\n\ +@subsubheading Outputs\n \ +The __udpport_read__() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +Optional outputs are provided for the source ip address and port of the read data.\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udpport: Your system doesn't support the UDP interface"); + return octave_value(); +#else + + if (args.length() < 2 || args.length() > 3 || args(0).type_id() != octave_udpport::static_type_id()) + { + print_usage(); + return octave_value(-1); + } + + unsigned int buffer_len = 0; + sockaddr_in addr; + + if ( !(args(1).OV_ISINTEGER() || args(1).OV_ISFLOAT())) + { + print_usage(); + return octave_value(-1); + } + + if ( args.length() > 2 ) + { + if ( !(args(2).OV_ISINTEGER() || args(2).OV_ISFLOAT())) + { + print_usage(); + return octave_value(-1); + } + } + + buffer_len = args(1).int_value(); + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error("udpport_read: cannot allocate requested memory: %s\n", strerror(errno)); + return octave_value(-1); + } + + octave_udpport* udpport = NULL; + + const octave_base_value& rep = args(0).get_rep(); + udpport = &((octave_udpport &)rep); + + double timeout = udpport->get_timeout() * 1000; + if (args.length() == 3) + { + timeout = args(2).double_value(); + } + + // Read data + int bytes_read = udpport->read(buffer, buffer_len, timeout, &addr); + + // Convert data to octave type variables + octave_value_list return_list; + uint8NDArray data( dim_vector(1, bytes_read) ); + + for (int i = 0; i < bytes_read; i++) + data(i) = buffer[i]; + + return_list(0) = data; + return_list(1) = bytes_read; + + if (nargout > 2) + { + int port = 0; + std::string ip = ""; + + if (bytes_read > 0) + to_ip_port(&addr, ip, port); + + return_list(2) = ip; + if (nargout > 3) + return_list(3) = port; + } + + return return_list; +#endif +} + +#if 0 +%!test +%! a = udpport (); +%! assert (! isnull (a)); +%! [d,c] = __udpport_read__ (a, 1, 0); +%! assert (c == 0); +%! assert (isempty (d)); +%! clear a; + +%!error __udpport_read__(1, 10, 0) + +%!test +%! a = udpport (); +%! fail ("__udpport_read__ (a, 10, 0, 0)", "Invalid call to __udpport_read__"); +%! clear a; + +%!test +%! # does read wait +%! a = udpport (); +%! assert (! isnull (a)); +%! tic; +%! [d,c] = __udpport_read__ (a, 1, 1000); +%! t = toc; +%! assert (c, 0); +%! assert (isempty (d)); +%! assert (t, 1.0, 0.1) +%! clear a; + +#endif diff --git a/src/udpport/__udpport_write__.cc b/src/udpport/__udpport_write__.cc new file mode 100644 index 0000000..8630b62 --- /dev/null +++ b/src/udpport/__udpport_write__.cc @@ -0,0 +1,141 @@ +// Copyright (C) 2021 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udpport_class.h" +#endif + +// PKG_ADD: autoload ("__udpport_write__", "udpport.oct"); +DEFUN_DLD (__udpport_write__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } __udpport_write__ (@var{udpport}, @var{data})\n \ +@deftypefnx {Loadable Function} {@var{n} = } __udpport_write__ (@var{udpport}, @var{data}, @var{destipaddress}, @var{destport})\n \ +\n\ +Provate function to write data to a udpport interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{udpport} - instance of @var{octave_udpport} class.@* \ +@var{data} - data to be written to the udpport interface. Can be either of String or uint8 type.\n \ +@var{destipaddress} - ip address to write to.@* \ +@var{destport} - port number to write to.\n \ +\n\ +If @var{destipaddress}, @var{destport} is not provided, write will go to the address configure from the udpport\n \ +creation or last used for write.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, __udpport_write__() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udpport: Your system doesn't support the UDP interface"); + return octave_value(); +#else + if ((args.length() != 2 && args.length() != 4) || args(0).type_id() != octave_udpport::static_type_id()) + { + print_usage(); + return octave_value(-1); + } + + octave_udpport *udpport = NULL; + int retval; + + const octave_base_value& rep = args(0).get_rep(); + udpport = &((octave_udpport &)rep); + + std::string destip = ""; + int destport = 0; + + if (args.length() == 4) + { + if (!args(2).is_string()) + { + error("udpport_write: expected destipaddress as a string"); + return octave_value(-1); + } + if ( !(args(3).OV_ISINTEGER() || args(3).OV_ISFLOAT())) + { + error("udpport_write: expected destport as a integer"); + return octave_value(-1); + } + + destip = args(2).string_value(); + destport = args(3).int_value(); + } + + if (args(1).is_string()) // String + { + retval = udpport->write(args(1).string_value(), destip, destport); + } + else if (args(1).is_uint8_type ()) + { + NDArray data = args(1).array_value(); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + // memcpy? + if (buf == NULL) + { + error("udpport_write: cannot allocate requested memory"); + return octave_value(-1); + } + + for (int i = 0; i < data.numel(); i++) + buf[i] = static_cast(data(i)); + + retval = udpport->write(buf, data.numel(), destip, destport); + + } + else + { + print_usage(); + return octave_value(-1); + } + + return octave_value(retval); +#endif +} + +#if 0 +%!test +%! a = udpport (); +%! b = udpport (); +%! port = get (b, 'LocalPort'); +%! assert (5, __udpport_write__ (a, uint8 ([104 101 108 108 111]), "127.0.0.1", port)); +%! [d, c] = __udpport_read__ (b, 5, 1000); +%! assert (c, 5); +%! assert (d, uint8 ([104 101 108 108 111])); +%! clear a; +%! clear b; + +%!error __udpport_write__ (1, uint8([104 101 108 108 111])) + +%!error __udpport_write__ () + +%!test +%! a = udpport (); +%! fail ("__udpport_write__ (a, uint8([104 101 108 108 111]), 0)", "Invalid call to __udpport_write__") +%! clear a; + +%!test +%! a = udpport (); +%! fail ("__udpport_write__ (a)", "Invalid call to __udpport_write__") +%! clear a; +#endif + diff --git a/src/udpport/udpport.cc b/src/udpport/udpport.cc new file mode 100644 index 0000000..a32644a --- /dev/null +++ b/src/udpport/udpport.cc @@ -0,0 +1,214 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef BUILD_UDP +# include "udpport_class.h" +#endif + +// PKG_ADD: autoload ("udpport", "udpport.oct"); +DEFUN_DLD (udpport, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{udp} = } udpport ()\n \ +@deftypefnx {Loadable Function} {@var{udp} = } udpport (@var{propertyname}, @var{propertyvalue} ...)\n \ +\n\ +Open udpport interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{propertyname}, @var{propertyvalue} - property name/value pair\n \ +\n\ +Known input properties:\n \ +@table @asis\n \ +@item Name\n \ +name assigned to the udp object\n \ +@item LocalPort\n \ +local port number\n \ +@item LocalHost\n \ +local host address\n \ +@item Timeout\n \ +timeout value in seconds used for waiting for data\n \ +@item EnablePortSharing\n \ +Boolean if the socket has port sharing enabled (readonly)\n \ +@end table \n \ +\n\ +@subsubheading Outputs\n \ +The udpport() shall return instance of @var{octave_udp} class as the result @var{udp}.\n \ +\n \ +@subsubheading Properties\n \ +The udp object has the following public properties:\n \ +@table @asis\n \ +@item Name\n \ +name assigned to the udp object\n \ +@item Type\n \ +instrument type 'udpport' (readonly)\n \ +@item LocalPort\n \ +local port number (readonly)\n \ +@item LocalHost\n \ +local host address (readonly)\n \ +@item Status\n \ +status of the object 'open' or 'closed' (readonly)\n \ +@item Timeout\n \ +timeout value in seconds used for waiting for data\n \ +@item NumBytesAvailable\n \ +number of bytes currently available to read (readonly)\n \ +@item MulticastGroup\n \ +multicast group socket is subscribed to (readonly)\n \ +@item EnableMultcast\n \ +Boolean if the socket has any multicast group it is subscribed to (readonly)\n \ +@item EnablePortSharing\n \ +Boolean if the socket has port sharing enabled (readonly)\n \ +@item Terminator\n \ +Terminator value used for string data (currently not used)\n \ +@end table \n \ +@end deftypefn") +{ +#ifndef BUILD_UDP + error("udpport: Your system doesn't support the UDPPORT interface"); + return octave_value(); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage(); + return octave_value(); + } + + // Default values + std::string name = ""; + std::string localhost("0.0.0.0"); + int localport = 0; + double timeout = -1; + int portshare = 0; + + if (args.length() > 0 && ((args.length() & 1) == 1)) + { + error ("Expected property name/value pairs"); + return octave_value (); + } + + if (args.length() > 0) + { + // go through the properties + for(int i=0;iopen(localhost, localport, portshare) < 0) + { + return octave_value(); + } + + retval->set_timeout(timeout); + + if(name.length() > 0) + retval->set_name(name); + + return octave_value(retval); +#endif +} + +#if 0 +%!test +%! # can create default udp object +%! a = udpport (); +%! assert (! isnull (a)); +%! assert (isa (a, 'octave_udpport')); +%! clear a; + +%!error a = udpport (1) + +%!test +%! a = udpport ("Name", "test", "Timeout", 2.5); +%! assert (! isnull (a)); +%! assert (a.Name, "test"); +%! assert (a.Timeout, 2.5); +%! clear a; + +#endif diff --git a/src/udpport/udpport_class.cc b/src/udpport/udpport_class.cc new file mode 100644 index 0000000..d7daa14 --- /dev/null +++ b/src/udpport/udpport_class.cc @@ -0,0 +1,847 @@ +// Copyright (C) 2020 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_UDP +#include +#include +#include +#include + +#ifndef __WIN32__ +# include +# include +# include +# include +# include +# include +# include +# include +# define IOCTL_TYPE int +#else +# include +# include +# define IOCTL_TYPE u_long +# define ioctl ioctlsocket +#endif + +#include "udpport_class.h" +#include + +#ifndef __WIN32__ +# define SOCKETERR errno +# define STRSOCKETERR strerror(errno) +#else +# define SOCKETERR WSAGetLastError() +# define STRSOCKETERR "" +# define socklen_t int +#endif + +static struct timeval +to_timeval(int ms) +{ + struct timeval tv; + if(ms <= 0) + { + tv.tv_usec = 0; + tv.tv_sec = 0; + } + else + { + tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms/1000;; + } + return tv; +} + +static std::string +to_ip_str (const sockaddr_in *in) +{ + u_long addr = ntohl (in->sin_addr.s_addr); + + int b[4]; + b[0] = (addr>>24)&0xff; + b[1] = (addr>>16)&0xff; + b[2] = (addr>>8)&0xff; + b[3] = (addr>>0)&0xff; + + std::stringstream n; + n << b[0] << "." << b[1] << "." << b[2] << "." << b[3]; + + return n.str (); +} + +static bool +lookup_addr (const std::string &ip, sockaddr_in *in) +{ + in->sin_addr.s_addr = inet_addr (ip.c_str()); + + if (in->sin_addr.s_addr == INADDR_NONE) + { + struct hostent * host = gethostbyname (ip.c_str()); + if (!host) + return false; + + memcpy(&in->sin_addr, host->h_addr_list[0], host->h_length); + } + + return true; +} + +int to_ip_port (const sockaddr_in *in, std::string &ip, int &port) +{ + port = ntohs (in->sin_port); + ip = to_ip_str(in); + return 1; +} + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_udpport, "octave_udpport", "octave_udpport"); + +octave_udpport::octave_udpport (void) +: fd(-1), timeout(-1), name(""), fieldnames(17) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } + userData = Matrix (); + byteswritten = 0; + byteOrder = "little-endian"; + enableportsharing = 0; + enablemulticastloopback = 0; + enablebroadcast = 0; + interminator = "lf"; + outterminator = "lf"; + + fieldnames[0] = "Type"; + fieldnames[1] = "Name"; + fieldnames[2] = "LocalPort"; + fieldnames[3] = "LocalHost"; + fieldnames[4] = "Status"; + fieldnames[5] = "Timeout"; + fieldnames[6] = "NumBytesAvailable"; + fieldnames[7] = "NumBytesWritten"; + fieldnames[8] = "ByteOrder"; + fieldnames[9] = "UserData"; + fieldnames[10] = "MulticastGroup"; + fieldnames[11] = "EnableMulticast"; + fieldnames[12] = "EnableMulticastLoopback"; + fieldnames[13] = "EnableBroadcast"; + fieldnames[14] = "EnablePortSharing"; + fieldnames[15] = "IPAddressVersion"; + fieldnames[16] = "Terminator"; +} + +bool octave_udpport::has_property(const std::string &name) const +{ + for (octave_idx_type i=0; i& idx, int nargout) +{ + octave_value_list retval; + int skip = 1; + + switch (type[0]) + { + default: + error ("octave_udpport object cannot be indexed with %c", type[0]); + return retval; + case '.': + { + std::string property = (idx.front ()) (0).string_value (); + if (!has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + else + { + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + retval = OCTAVE__FEVAL (std::string ("__udpport_properties__"), ovl, 1); + } + } + break; + } + + if (idx.size () > 1 && type.length () > 1) + retval = retval (0).next_subsref (nargout, type, idx, skip); + + return retval; +} + +octave_value +octave_udpport::subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + default: + error ("octave_udpport object cannot be indexed with %c", type[0]); + break; + case '.': + if (type.length () == 1) + { + std::string property = (idx.front ()) (0).string_value (); + if (! has_property(property)) + { + error ("Unknown property '%s'", property.c_str()); + return retval; + } + + octave_value_list ovl; + // inc ref count as assign this to octave_value + count++; + ovl (0) = octave_value (this); + ovl (1) = (idx.front ()) (0); + ovl (2) = rhs; + OCTAVE__FEVAL (std::string ("__udpport_properties__"), ovl, 0); + count++; + retval = octave_value (this); + } + else if (type.length () > 1 && type[1] == '.') + { + // pass along any further assignments + octave_value_list u = subsref (type.substr (0, 1), idx, 1); + if (u.length () > 0) + { + std::list next_idx (idx); + next_idx.erase (next_idx.begin ()); + u (0).subsasgn(type.substr (1), next_idx, rhs); + count++; + retval = octave_value (this); + } + } + else + { + error ("octave_udpport invalid index"); + } + + } + return retval; +} + +int +octave_udpport::open (const std::string &address, int port, int portshare) +{ + int sockerr; + + name = "UDP-" + address; + +#ifdef __WIN32__ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + err = WSAStartup (wVersionRequested, &wsaData ); + if ( err != 0 ) + { + error( "could not initialize winsock library" ); + return -1; + } +#endif + + memset (&remote_addr, 0, sizeof (remote_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = 0; + remote_addr.sin_addr.s_addr = htonl (INADDR_ANY); + + fd = socket (AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) + { + error ("udpport: error opening socket : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_udpport::close (); + return -1; + } + + // port sharing + enableportsharing = portshare; + if(portshare) + { +#ifdef SO_REUSEPORT + setsockopt(SOL_SOCKET, SO_REUSEPORT, (void*)&portshare, sizeof(portshare)); +#else + setsockopt(SOL_SOCKET, SO_REUSEADDR, (void*)&portshare, sizeof(portshare)); +#endif + } + + memset (&local_addr, 0, sizeof (local_addr)); + if (address == "0.0.0.0") + local_addr.sin_addr.s_addr = htonl (INADDR_ANY); + else + { + lookup_addr(address, &local_addr); + } + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons (port); + + sockerr = bind (fd, (struct sockaddr*)&local_addr, sizeof (local_addr)); + if (sockerr < 0) + { + error ("udpport: error on bind : %d - %s\n", SOCKETERR, STRSOCKETERR); + octave_udpport::close (); + return -1; + } + else if (port == 0) + { + // if said port, 0, lookup actual port it used + socklen_t sz = sizeof (local_addr); + getsockname (fd, (struct sockaddr*)&local_addr, &sz); + } + + return get_fd(); +} + +octave_udpport::~octave_udpport (void) +{ + close(); +} + +void +octave_udpport::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_udpport::print (std::ostream& os, bool pr_as_read_syntax) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_udpport::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << " UDPPort Object " << get_name (); + newline(os); + os << " Type: " << get_type (); + newline(os); + os << " Status: " << get_status (); + newline(os); + os << " LocalHost: " << get_local_addr (); + newline(os); + os << " LocalPort: " << get_local_port (); + newline (os); +} + +int +octave_udpport::get_bytesavailable () const +{ + IOCTL_TYPE available = 0; + + if (get_fd () < 0) + { + return 0; + } + ioctl (get_fd (), FIONREAD, &available); + + return available; +} + +int +octave_udpport::getsockopt (int level, int opt, void *buf, socklen_t *len) +{ +#ifndef __WIN32__ + return ::getsockopt(get_fd(), level, opt, buf, len); +#else + return ::getsockopt(get_fd(), level, opt, (char *)buf, len); +#endif +} + +int +octave_udpport::setsockopt (int level, int opt, const void *buf, socklen_t len) +{ +#ifndef __WIN32__ + return ::setsockopt(get_fd(), level, opt, buf, len); +#else + return ::setsockopt(get_fd(), level, opt, (const char *)buf, len); +#endif +} + +int +octave_udpport::read (uint8_t *buf, unsigned int len, double readtimeout, sockaddr_in *rdinfo) +{ + struct sockaddr_in addr; + socklen_t addrlen = sizeof (addr); + struct timeval tv; + + fd_set readfds; + + if (get_fd () < 0) + { + error ("udpport_read: Interface must be opened first..."); + return 0; + } + + size_t bytes_read = 0; + ssize_t read_retval = -1; + + // While not interrupted in blocking mode + while (bytes_read < len) + { + OCTAVE_QUIT; + + tv = to_timeval((readtimeout < 0 || readtimeout > 1000) ? 1000 : readtimeout); + + FD_ZERO (&readfds); + FD_SET (get_fd (), &readfds); + + if (::select(get_fd ()+1, &readfds, NULL, NULL, &tv) < 0) + { + error("udpport_read: Error while reading/select: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + + if (FD_ISSET (get_fd (), &readfds)) + { + addrlen = sizeof (addr); + read_retval = ::recvfrom (get_fd (), reinterpret_cast((buf + bytes_read)), len - bytes_read, + 0, (struct sockaddr*)&addr, &addrlen); + + if (read_retval < 0) + { + error ("udpport_read: Error while reading: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else if (read_retval == 0) + { + error ("udpport_read: Connection lost: %d - %s\n", SOCKETERR, STRSOCKETERR); + break; + } + else + { + bytes_read += read_retval; + + if (rdinfo) + *rdinfo = addr; + } + } + else + { + // Timeout + if (readtimeout >= 0) + { + // real timeout + if (readtimeout <= 1000) + break; + // timed out 1 sec of an actual timeout + else + readtimeout -= 1000; + } + } + + } + + + return bytes_read; +} + +int +octave_udpport::write (const std::string &str, const std::string &destip, int destport) +{ + if (get_fd () < 0) + { + error("udpport: Interface must be opened first..."); + return -1; + } + + if (destip.length() > 0) + { + sockaddr_in in; + + memset (&in, 0, sizeof (in)); + + in.sin_family = AF_INET; + + lookup_addr (destip, &in); + + in.sin_port = htons(destport); + + remote_addr = in; + } + else + { + if (remote_addr.sin_port == 0) + { + error("udpport: No destination address/port previously set"); + return -1; + } + } + int wrote = ::sendto (get_fd (), str.c_str(), str.length(), 0, + (struct sockaddr *)&remote_addr, sizeof(remote_addr)); + if(wrote > 0) + byteswritten += wrote; + + return wrote; +} + +int +octave_udpport::write (uint8_t *buf, unsigned int len, const std::string &destip, int destport) +{ + if (get_fd () < 0) + { + error("udpport: Interface must be opened first..."); + return -1; + } + + if (destip.length() > 0) + { + sockaddr_in in; + + memset (&in, 0, sizeof (in)); + + in.sin_family = AF_INET; + + lookup_addr (destip, &in); + + in.sin_port = htons(destport); + + remote_addr = in; + } + else + { + if (remote_addr.sin_port == 0) + { + error("udpport: No destination address/port previously set"); + return -1; + } + } + + int wrote = ::sendto (get_fd(), reinterpret_cast(buf), + len, 0, (struct sockaddr *)&remote_addr, sizeof (remote_addr)); + if(wrote > 0) + byteswritten += wrote; + + return wrote; +} + +int +octave_udpport::set_timeout (double newtimeout) +{ + if (get_fd () < 0) + { + error ("udpport: Interface must be opened first..."); + return -1; + } + + if (newtimeout < -1 ) + { + error ("udpport_timeout: timeout value must be -1 or positive"); + return -1; + } + + timeout = newtimeout; + + return 1; +} + +int +octave_udpport::get_remote_port (void) const +{ + return ntohs (remote_addr.sin_port); +} + +int +octave_udpport::set_remote_port (int port) +{ + if (port < 0 ) + { + error ("udpport_remote_port: value must be positive"); + return -1; + } + + remote_addr.sin_port = htons(port); + + return get_remote_port(); +} + +std::string +octave_udpport::get_remote_addr (void) const +{ + return to_ip_str (&remote_addr); +} + +std::string +octave_udpport::set_remote_addr (const std::string &addr) +{ + if (addr.length() == 0 ) + { + error ("udpport_remote_addr: value must be non empty"); + } + else if ( !lookup_addr(addr, &remote_addr)) + { + error ("udpport: error looking up remote host : %d - %s\n", SOCKETERR, STRSOCKETERR); + } + + return to_ip_str (&remote_addr); +} + +int +octave_udpport::get_local_port (void) const +{ + return ntohs (local_addr.sin_port); +} + +std::string +octave_udpport::get_local_addr (void) const +{ + return to_ip_str (&local_addr); +} + + +std::string +octave_udpport::set_name (const std::string &n) +{ + if (n.length() == 0 ) + { + error ("udpport_name: value must be non empty"); + } + else + { + name = n; + } + + return name; +} + +bool +octave_udpport::is_open (void) const +{ + return fd >= 0; +} + +std::string +octave_udpport::get_status (void) const +{ + if (! is_open ()) + { + return "closed"; + } + else + { + return "open"; + } +} + +int +octave_udpport::close (void) +{ + int retval = -1; + + if (get_fd() > 0) + { +#ifndef __WIN32__ + retval = ::close (get_fd ()); +#else + retval = ::closesocket (get_fd ()); +#endif + fd = -1; + } + + return retval; +} + +int +octave_udpport::flush (int mode) +{ + int retval = -1; + + if (get_fd() > 0) + { + uint8_t tmpbuffer[1024]; + if (mode == 0 || mode == 2) + { + // we are sending data as we get it, so no outout + // buffers to flush + } + if (mode == 1 || mode == 2) + { + while (read (tmpbuffer, 1024, 0) > 0) {} + } + } + + return retval; +} + +int +octave_udpport::set_enablebroadcast (int enable) +{ + + if (get_fd () < 0) + { + error ("udpport: Interface must be opened first..."); + return -1; + } + + enablebroadcast = enable; + + return setsockopt(SOL_SOCKET, SO_BROADCAST, (void*)&enable, sizeof(enable)); +} + +int +octave_udpport::set_multicastloopback (int enable) +{ + + if (get_fd () < 0) + { + error ("udpport: Interface must be opened first..."); + return -1; + } + + enablemulticastloopback = enable; + + return setsockopt(IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&enable, sizeof(enable)); +} + +std::string +octave_udpport::get_multicastgroup () const +{ + if (multicastaddr.size() > 0) + { + sockaddr_in in = multicastaddr[0]; + return to_ip_str (&in); + } + else + return ""; +} + +int +octave_udpport::set_multicastgroup (const std::string &addr) +{ + int retval = -1; + + if (get_fd() > 0) + { + if (addr == "off") + { + sockaddr_in in; + + for (int i=0; i +// +// 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 . + +#ifndef UDPPORT_CLASS_H +#define UDPPORT_CLASS_H + +#include +#include + +#include +#include + +#ifndef __WIN32__ +# include +#else +# include +typedef int socklen_t; +#endif + +int to_ip_port (const sockaddr_in *in, std::string &ip, int &port); + +class octave_udpport : public octave_base_value +{ +public: + octave_udpport (void); + ~octave_udpport (void); + + int write (const std::string &str, const std::string &destip="", int destport=0); + int write (uint8_t *buf, unsigned int len, const std::string &destip="", int destport=0); + + int read (uint8_t *buf, unsigned int len, double readtimeout, sockaddr_in *rdinfo=0); + + int getsockopt (int level, int opt, void *buf, socklen_t *len); + int setsockopt (int level, int opt, const void *buf, socklen_t len); + + int open (const std::string &address, int port, int portshare); + + int close (void); + + int get_fd (void) const { return fd; } + + int get_bytesavailable (void) const; + unsigned int get_byteswritten (void) const { return byteswritten; } + + // Overloaded base functions + double udpport_value (void) const { return (double)fd; } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true; } + bool is_defined (void) const { return true; } + // < 4.4 + bool is_object (void) const { return true; } + // 4.4 + + bool isobject (void) const { return true; } + + // required to use subsasn + string_vector map_keys (void) const { return fieldnames; } + dim_vector dims (void) const { static dim_vector dv(1, 1); return dv; } + + // use single copy of each udpport socket + octave_base_value * unique_clone (void) { count++; return this; } + + /** + * overloaded methods to get properties + */ + octave_value_list subsref (const std::string& type, const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); + + std::string get_name (void) const { return name; } + std::string set_name (const std::string &); + + std::string get_remote_addr (void) const; + std::string set_remote_addr (const std::string &); + + int get_remote_port (void) const; + int set_remote_port (int); + + int get_local_port (void) const; + + std::string get_local_addr (void) const; + + bool is_open(void) const; + + std::string get_type (void) const { return "udpport"; } + + std::string get_status (void) const; + + int set_timeout (double); + double get_timeout (void) const { return timeout; } + + int flush(int mode); + + int set_multicastgroup (const std::string &); + std::string get_multicastgroup () const; + + int get_enableportsharing() const { return enableportsharing; } + + int get_enablebroadcast() const { return enablebroadcast; } + int set_enablebroadcast (int enable); + + int get_multicastloopback() const { return enablemulticastloopback; } + int set_multicastloopback (int enable); + + octave_value get_userdata () const + { + return userData; + } + + void set_userdata (const octave_value &newv) + { + userData = newv; + } + + std::string get_ipaddressversion () const { return "IPV4"; } + + int set_byteorder(const std::string& /* order */); + + std::string get_byteorder() const + { + return byteOrder; + } + + int set_input_terminator(const std::string& /* term */); + int set_output_terminator(const std::string& /* term */); + + std::string get_input_terminator() const + { + return interminator; + } + + std::string get_output_terminator() const + { + return outterminator; + } + +private: + bool has_property(const std::string &name) const; + + int fd; + double timeout; + std::string name; + sockaddr_in remote_addr; + sockaddr_in local_addr; + string_vector fieldnames; + std::vector multicastaddr; + octave_value userData; + int enableportsharing; + int enablemulticastloopback; + int enablebroadcast; + std::string byteOrder; + unsigned int byteswritten; + std::string interminator; + std::string outterminator; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif diff --git a/src/undef-ah-octave.h b/src/undef-ah-octave.h new file mode 100644 index 0000000..efad7b5 --- /dev/null +++ b/src/undef-ah-octave.h @@ -0,0 +1,27 @@ +/* To be included at the top of config.h (by autoheader). Avoid + warnings for redefining AH-generated preprocessor symbols of + Octave. */ + +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif + +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif + +#ifdef PACKAGE_URL +#undef PACKAGE_URL +#endif + +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif diff --git a/src/usbtmc/Makefile.in b/src/usbtmc/Makefile.in new file mode 100644 index 0000000..28380fe --- /dev/null +++ b/src/usbtmc/Makefile.in @@ -0,0 +1,6 @@ +OCT := ../usbtmc.oct +OBJ := usbtmc.o usbtmc_close.o usbtmc_write.o usbtmc_read.o usbtmc_class.o __usbtmc_pkg_lock__.o +LFLAGS = $(LIBS) +CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ + +include ../common.mk diff --git a/src/usbtmc/__usbtmc_pkg_lock__.cc b/src/usbtmc/__usbtmc_pkg_lock__.cc new file mode 100644 index 0000000..5b0626f --- /dev/null +++ b/src/usbtmc/__usbtmc_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__usbtmc_pkg_lock__", "usbtmc.oct"); +// PKG_ADD: __usbtmc_pkg_lock__(1); +// PKG_DEL: __usbtmc_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__usbtmc_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__usbtmc_pkg_lock__")) + interp.munlock("__usbtmc_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__usbtmc_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/usbtmc/usbtmc.cc b/src/usbtmc/usbtmc.cc new file mode 100644 index 0000000..1916cb7 --- /dev/null +++ b/src/usbtmc/usbtmc.cc @@ -0,0 +1,92 @@ +// Copyright (C) 2019 John DOnoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_USBTMC +#include + +#include "usbtmc_class.h" +#endif + +// PKG_ADD: autoload ("usbtmc", "usbtmc.oct"); +DEFUN_DLD (usbtmc, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{usbtmc} = } usbtmc (@var{path})\n \ +\n\ +Open usbtmc interface.\n \ +\n\ +@subsubheading Inputs\n \ +@var{path} - the interface path of type String. If omitted defaults to '/dev/usbtmc0'.\n \ +\n\ +@subsubheading Outputs\n \ +The usbtmc() shall return instance of @var{octave_usbtmc} class as the result @var{usbtmc}.\n \ +@end deftypefn") +{ +#ifndef BUILD_USBTMC + error ("usbtmc: Your system doesn't support the USBTMC interface"); + return octave_value (); +#else + + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + int oflags = O_RDWR; + std::string path ("/dev/usbtmc0"); + + // Parse the function arguments + if (args.length () > 0) + { + if (args (0).is_string ()) + { + path = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + octave_usbtmc* retval = new octave_usbtmc (); + + // Open the interface + if (retval->open (path, oflags) < 0) + return octave_value (); + + return octave_value (retval); +#endif +} + +#if 0 +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "usbtmc")) +%! fail ("usbtmc ()", "Invalid call to usbtmc"); +%! else +%! fail ("usbtmc ()", "usbtmc: Your system doesn't support the USBTMC interface"); +%! endif + +#endif diff --git a/src/usbtmc/usbtmc_class.cc b/src/usbtmc/usbtmc_class.cc new file mode 100644 index 0000000..7d57e99 --- /dev/null +++ b/src/usbtmc/usbtmc_class.cc @@ -0,0 +1,138 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_USBTMC +#include +#include +#include + +#include + +#include "usbtmc_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_usbtmc, "octave_usbtmc", "octave_usbtmc"); + +octave_usbtmc::octave_usbtmc (void) +: fd (-1) +{ + static bool type_registered = false; + + if (! type_registered) + { + type_registered = true; + register_type (); + } +} + +octave_usbtmc::~octave_usbtmc (void) +{ + octave_usbtmc::close(); +} + +int +octave_usbtmc::get_fd() const +{ + return fd; +} + +void +octave_usbtmc::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw(os, pr_as_read_syntax); + newline(os); +} + +void +octave_usbtmc::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw(os, pr_as_read_syntax); + newline(os); +} + +void +octave_usbtmc::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << fd; +} + +int +octave_usbtmc::open (const std::string &path, int flags) +{ + fd = ::open (path.c_str (), flags, 0); + + if (get_fd () < 0) + { + error ("usbtmc: Error opening the interface: %s\n", strerror (errno)); + return -1; + } + + return get_fd (); +} + +int +octave_usbtmc::read (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("usbtmc: Interface must be open first..."); + return -1; + } + + int retval = ::read (get_fd (), buf, len); + + if (retval < 0) + error ("usbtmc: Failed to read from the usbtmc bus: %s\n", strerror (errno)); + + return retval; +} + +int +octave_usbtmc::write (uint8_t *buf, unsigned int len) +{ + if (get_fd () < 0) + { + error ("usbtmc: Interface must be open first..."); + return -1; + } + + int retval = ::write (get_fd (), buf, len); + + if (retval < 0) + error("usbtmc: Failed to write to the usbtmc bus: %s\n", strerror(errno)); + + return retval; +} + +int +octave_usbtmc::close (void) +{ + int retval = -1; + + if (get_fd () > 0) + { + retval = ::close(get_fd ()); + fd = -1; + } + + return retval; +} +#endif diff --git a/src/usbtmc/usbtmc_class.h b/src/usbtmc/usbtmc_class.h new file mode 100644 index 0000000..ff3e700 --- /dev/null +++ b/src/usbtmc/usbtmc_class.h @@ -0,0 +1,66 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef USBTMC_CLASS_H +#define USBTMC_CLASS_H + +#include + +#include + +class octave_usbtmc : public octave_base_value +{ +public: + octave_usbtmc (void); + ~octave_usbtmc(void); + + int open(const std::string&, int); + int close(void); + int get_fd(void) const; + + // Simple usbtmc commands + int write(uint8_t*, unsigned int); + int read(uint8_t*, unsigned int); + + + // Overloaded base functions + double usbtmc_value(void) const + { + return (double)fd; + } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)fd; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool print_as_scalar (void) const { return true;} + +private: + int fd; + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + + +#endif diff --git a/src/usbtmc/usbtmc_close.cc b/src/usbtmc/usbtmc_close.cc new file mode 100644 index 0000000..aed6778 --- /dev/null +++ b/src/usbtmc/usbtmc_close.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2019 John DOnoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_USBTMC +#include "usbtmc_class.h" +#endif + +// PKG_ADD: autoload ("usbtmc_close", "usbtmc.oct"); +DEFUN_DLD (usbtmc_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} usbtmc_close (@var{usbtmc})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@subsubheading Inputs\n \ +@var{usbtmc} - instance of @var{octave_usbtmc} class.\n \ +@subsubheading Outputs\n \ +None\n \ +@end deftypefn") +{ +#ifndef BUILD_USBTMC + error ("usbtmc: Your system doesn't support the USBTMC interface"); + return octave_value (); +#else + + if (args.length () != 1 || args (0).type_id () != octave_usbtmc::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_usbtmc* usbtmc = NULL; + + const octave_base_value& rep = args (0).get_rep (); + usbtmc = &((octave_usbtmc &)rep); + + usbtmc->close (); + + return octave_value (); +#endif +} diff --git a/src/usbtmc/usbtmc_read.cc b/src/usbtmc/usbtmc_read.cc new file mode 100644 index 0000000..4f7e60f --- /dev/null +++ b/src/usbtmc/usbtmc_read.cc @@ -0,0 +1,108 @@ +// Copyright (C) 2019 John Donoghue +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2017 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_USBTMC +#include + +#include + +#include "usbtmc_class.h" +#endif + +// PKG_ADD: autoload ("usbtmc_read", "usbtmc.oct"); +DEFUN_DLD (usbtmc_read, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } usbtmc_read (@var{usbtmc}, @var{n})\n \ +\n\ +Read from usbtmc slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{usbtmc} - instance of @var{octave_usbtmc} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +@subsubheading Outputs\n \ +@var{count} - the number of bytes successfully read as an Integer.@*\n \ +@var{data} - the read bytes as a uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_USBTMC + error ("usbtmc: Your system doesn't support the USBTMC interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_usbtmc::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 1; + + if (args.length () > 1) + { + if (! (args (1).OV_ISINTEGER () || args (1).OV_ISFLOAT ()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args(1).int_value(); + } + + OCTAVE_LOCAL_BUFFER (uint8_t, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("usbtmc_read: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + octave_usbtmc* usbtmc = NULL; + + const octave_base_value& rep = args (0).get_rep (); + usbtmc = &((octave_usbtmc &)rep); + + int retval; + + retval = usbtmc->read (buffer, buffer_len); + + if (retval < 0) + { + // read has already displayed a message, so just exit + return octave_value (-1); + } + + octave_value_list return_list; + uint8NDArray data (dim_vector (1, retval)); + + for (int i = 0; i < retval; i++) + data (i) = buffer[i]; + + return_list (0) = data; + return_list (1) = retval; + + return return_list; +#endif +} diff --git a/src/usbtmc/usbtmc_write.cc b/src/usbtmc/usbtmc_write.cc new file mode 100644 index 0000000..55d40e9 --- /dev/null +++ b/src/usbtmc/usbtmc_write.cc @@ -0,0 +1,94 @@ +// Copyright (C) 2019 John Donoghue +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_USBTMC +#include + +#include "usbtmc_class.h" +#endif + +// PKG_ADD: autoload ("usbtmc_write", "usbtmc.oct"); +DEFUN_DLD (usbtmc_write, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } usbtmc_write (@var{usbtmc}, @var{data})\n \ +\n\ +Write data to a usbtmc slave device.\n \ +\n\ +@subsubheading Inputs\n \ +@var{usbtmc} - instance of @var{octave_usbtmc} class.@* \ +@var{data} - data, of type uint8, to be written to the slave device.\n \ +\n\ +@subsubheading Outputs\n \ +Upon successful completion, usbtmc_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_USBTMC + error ("usbtmc: Your system doesn't support the USBTMC interface"); + return octave_value (); +#else + + if (args.length () != 2 || args (0).type_id () != octave_usbtmc::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_usbtmc* usbtmc = NULL; + int retval; + + const octave_base_value& rep = args (0).get_rep (); + usbtmc = &((octave_usbtmc &)rep); + + const octave_base_value& data = args (1).get_rep (); + + if (data.is_string()) + { + std::string buf = data.string_value (); + retval = usbtmc->write ((uint8_t*)buf.c_str (), buf.length ()); + } + else if (data.is_uint8_type ()) + { + NDArray dtmp = data.array_value (); + OCTAVE_LOCAL_BUFFER (uint8_t, buf, (data.numel ())); + + if (buf == NULL) + { + error ("usbtmc_write: cannot allocate requested memory: %s\n", strerror (errno)); + return octave_value (-1); + } + + for (int i = 0; i < dtmp.numel (); i++) + buf[i] = static_cast(dtmp (i)); + + retval = usbtmc->write (buf, dtmp.numel ()); + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/vxi11/Makefile.in b/src/vxi11/Makefile.in new file mode 100644 index 0000000..add0b44 --- /dev/null +++ b/src/vxi11/Makefile.in @@ -0,0 +1,39 @@ +VXI := vxi11_clnt.o vxi11_xdr.o +OBJ := vxi11.o vxi11_write.o vxi11_close.o vxi11_read.o __vxi11_pkg_lock__.o +OCT := ../vxi11.oct +VXCLASS := vxi11_class.o + +RPCGEN ?= @RPCGEN@ +RPCGENOPTS ?= @RPCGENOPTS@ + +LFLAGS = $(LIBS) +CFLAGS = $(CPPFLAGS) @DEFS@ + +BUILD_VXI11 = @BUILD_VXI11@ + +RPC_GENERATED_FILES := vxi11.h vxi11_clnt.c vxi11_xdr.c + +ifneq ($(BUILD_VXI11),1) +VXI = +VXCLASS = +else + +CFLAGS += @RPCINCLUDE@ +LFLAGS += @RPCLIBS@ +endif + +OBJ += $(VXI) $(VXCLASS) + +default: all + +$(RPC_GENERATED_FILES): vxi11.x + $(RPCGEN) $(RPCGENOPTS) vxi11.x + +include ../common.mk + +extraclean: distclean + rm -f $(RPC_GENERATED_FILES) + +prebuild: $(RPC_GENERATED_FILES) + +.PHONY: prebuild extraclean diff --git a/src/vxi11/__vxi11_pkg_lock__.cc b/src/vxi11/__vxi11_pkg_lock__.cc new file mode 100644 index 0000000..0714349 --- /dev/null +++ b/src/vxi11/__vxi11_pkg_lock__.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2019 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 . + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#ifdef HAVE_OCTAVE_INTERPRETER_H +# include +#endif + +// PKG_ADD: autoload ("__vxi11_pkg_lock__", "vxi11.oct"); +// PKG_ADD: __vxi11_pkg_lock__(1); +// PKG_DEL: __vxi11_pkg_lock__(0); +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (__vxi11_pkg_lock__, interp, args, , "internal function") +{ + octave_value retval; + if (args.length () >= 1) + { + if (args(0).int_value () == 1) + interp.mlock(); + else if (args(0).int_value () == 0 && interp.mislocked("__vxi11_pkg_lock__")) + interp.munlock("__vxi11_pkg_lock__"); + } + return retval; +} +#else +DEFUN_DLD(__vxi11_pkg_lock__, args, , "internal function") +{ + octave_value retval; + return retval; +} +#endif + diff --git a/src/vxi11/vxi11.cc b/src/vxi11/vxi11.cc new file mode 100644 index 0000000..eef39f9 --- /dev/null +++ b/src/vxi11/vxi11.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_VXI11 +#include + +using std::string; + +#include "vxi11_class.h" +#endif + +// PKG_ADD: autoload ("vxi11", "vxi11.oct"); +DEFUN_DLD (vxi11, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{vxi11} = } vxi11 (@var{ip})\n \ +\n\ +Open vxi11 interface.\n \ +\n\ +@var{path} - the ip address of type String. If omitted defaults to '127.0.0.1'.\n \ +\n\ +The vxi11() shall return instance of @var{octave_vxi11} class as the result @var{vxi11}.\n \ +@end deftypefn") +{ +#ifndef BUILD_VXI11 + error ("vxi11: Your system doesn't support the VXI11 interface"); + return octave_value (); +#else + // Do not open interface if return value is not assigned + if (nargout != 1) + { + print_usage (); + return octave_value (); + } + + // Default values + string path ("127.0.0.1"); + + // Parse the function arguments + if (args.length () > 0) + { + if (args(0).is_string ()) + { + path = args (0).string_value (); + } + else + { + print_usage (); + return octave_value (); + } + } + + // Open the interface + octave_vxi11* retval = new octave_vxi11; + + if (retval->open (path) < 0) + { + error("vxi11: Error opening the interface: %s\n", strerror (errno)); + return octave_value (); + } + + return octave_value (retval); +#endif +} +#if 0 +%!test +%! if any(strcmp(instrhwinfo().SupportedInterfaces, "vxi11")) +%! fail ("vxi11 ()", "Invalid call to vxi11"); +%! else +%! fail ("vxi11 ()", "vxi11: Your system doesn't support the VXI11 interface"); +%! endif + +#endif diff --git a/src/vxi11/vxi11.h b/src/vxi11/vxi11.h new file mode 100644 index 0000000..d92164a --- /dev/null +++ b/src/vxi11/vxi11.h @@ -0,0 +1,369 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _VXI11_H_RPCGEN +#define _VXI11_H_RPCGEN + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* VXI-11 RPCL definitions. Taken from appendix C of the VXI-11 specfication. + * See http://www.vxi.org + */ +#include +#include + +/* VXI-11 flags */ +#define VXI11_FLAG_WAITLOCK 0x01 +#define VXI11_FLAG_ENDW 0x08 +#define VXI11_FLAG_TERMCHRSET 0x80 + +/* VXI-11 device_docmd 'cmd' values */ +#define VXI11_DOCMD_SEND_COMMAND 0x020000 +#define VXI11_DOCMD_BUS_STATUS 0x020001 +#define VXI11_DOCMD_ATN_CONTROL 0x020002 +#define VXI11_DOCMD_REN_CONTROL 0x020003 +#define VXI11_DOCMD_PASS_CONTROL 0x020004 +#define VXI11_DOCMD_BUS_ADDRESS 0x02000A +#define VXI11_DOCMD_IFC_CONTROL 0x020010 + +/* VXI-11 device_docmd Bus Status values */ +#define VXI11_DOCMD_STAT_REMOTE 1 +#define VXI11_DOCMD_STAT_SRQ 2 +#define VXI11_DOCMD_STAT_NDAC 3 +#define VXI11_DOCMD_STAT_SYS_CTRLR 4 +#define VXI11_DOCMD_STAT_CTRLR_CHRG 5 +#define VXI11_DOCMD_STAT_TALKER 6 +#define VXI11_DOCMD_STAT_LISTENER 7 +#define VXI11_DOCMD_STAT_BUSADDR 8 + +/* VXI-11 device_read 'reason' bits */ +#define VXI11_REASON_REQCNT 1 /* requested number of bytes read */ +#define VXI11_REASON_CHR 2 /* read terminated by eos character */ +#define VXI11_REASON_END 4 /* read terminated by EOI */ + +/* VXI-11 errors */ +#define VXI11_ERR_SUCCESS 0 +#define VXI11_ERR_SYNTAX 1 +#define VXI11_ERR_NODEVICE 3 +#define VXI11_ERR_LINKINVAL 4 +#define VXI11_ERR_PARAMETER 5 +#define VXI11_ERR_NOCHAN 6 +#define VXI11_ERR_NOTSUPP 8 +#define VXI11_ERR_RESOURCES 9 +#define VXI11_ERR_LOCKED 11 +#define VXI11_ERR_NOLOCK 12 +#define VXI11_ERR_IOTIMEOUT 15 +#define VXI11_ERR_IOERROR 17 +#define VXI11_ERR_ADDRINVAL 21 +#define VXI11_ERR_ABORT 23 +#define VXI11_ERR_CHANEST 29 + +typedef long Device_Link; + +enum Device_AddrFamily { + DEVICE_TCP = 0, + DEVICE_UDP = 1, +}; +typedef enum Device_AddrFamily Device_AddrFamily; + +typedef long Device_Flags; + +typedef long Device_ErrorCode; + +struct Device_Error { + Device_ErrorCode error; +}; +typedef struct Device_Error Device_Error; + +struct Create_LinkParms { + long clientId; + bool_t lockDevice; + u_long lock_timeout; + char *device; +}; +typedef struct Create_LinkParms Create_LinkParms; + +struct Create_LinkResp { + Device_ErrorCode error; + Device_Link lid; + u_short abortPort; + u_long maxRecvSize; +}; +typedef struct Create_LinkResp Create_LinkResp; + +struct Device_WriteParms { + Device_Link lid; + u_long io_timeout; + u_long lock_timeout; + Device_Flags flags; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct Device_WriteParms Device_WriteParms; + +struct Device_WriteResp { + Device_ErrorCode error; + u_long size; +}; +typedef struct Device_WriteResp Device_WriteResp; + +struct Device_ReadParms { + Device_Link lid; + u_long requestSize; + u_long io_timeout; + u_long lock_timeout; + Device_Flags flags; + char termChar; +}; +typedef struct Device_ReadParms Device_ReadParms; + +struct Device_ReadResp { + Device_ErrorCode error; + long reason; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct Device_ReadResp Device_ReadResp; + +struct Device_ReadStbResp { + Device_ErrorCode error; + u_char stb; +}; +typedef struct Device_ReadStbResp Device_ReadStbResp; + +struct Device_GenericParms { + Device_Link lid; + Device_Flags flags; + u_long lock_timeout; + u_long io_timeout; +}; +typedef struct Device_GenericParms Device_GenericParms; + +struct Device_RemoteFunc { + u_long hostAddr; + u_short hostPort; + u_long progNum; + u_long progVers; + Device_AddrFamily progFamily; +}; +typedef struct Device_RemoteFunc Device_RemoteFunc; + +struct Device_EnableSrqParms { + Device_Link lid; + bool_t enable; + struct { + u_int handle_len; + char *handle_val; + } handle; +}; +typedef struct Device_EnableSrqParms Device_EnableSrqParms; + +struct Device_LockParms { + Device_Link lid; + Device_Flags flags; + u_long lock_timeout; +}; +typedef struct Device_LockParms Device_LockParms; + +struct Device_DocmdParms { + Device_Link lid; + Device_Flags flags; + u_long io_timeout; + u_long lock_timeout; + long cmd; + bool_t network_order; + long datasize; + struct { + u_int data_in_len; + char *data_in_val; + } data_in; +}; +typedef struct Device_DocmdParms Device_DocmdParms; + +struct Device_DocmdResp { + Device_ErrorCode error; + struct { + u_int data_out_len; + char *data_out_val; + } data_out; +}; +typedef struct Device_DocmdResp Device_DocmdResp; + +#define DEVICE_ASYNC 0x0607B0 +#define DEVICE_ASYNC_VERSION 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define device_abort 1 +extern enum clnt_stat device_abort_1(Device_Link *, Device_Error *, CLIENT *); +extern bool_t device_abort_1_svc(Device_Link *, Device_Error *, struct svc_req *); +extern int device_async_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define device_abort 1 +extern enum clnt_stat device_abort_1(); +extern bool_t device_abort_1_svc(); +extern int device_async_1_freeresult (); +#endif /* K&R C */ + +#define DEVICE_CORE 0x0607AF +#define DEVICE_CORE_VERSION 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define create_link 10 +extern enum clnt_stat create_link_1(Create_LinkParms *, Create_LinkResp *, CLIENT *); +extern bool_t create_link_1_svc(Create_LinkParms *, Create_LinkResp *, struct svc_req *); +#define device_write 11 +extern enum clnt_stat device_write_1(Device_WriteParms *, Device_WriteResp *, CLIENT *); +extern bool_t device_write_1_svc(Device_WriteParms *, Device_WriteResp *, struct svc_req *); +#define device_read 12 +extern enum clnt_stat device_read_1(Device_ReadParms *, Device_ReadResp *, CLIENT *); +extern bool_t device_read_1_svc(Device_ReadParms *, Device_ReadResp *, struct svc_req *); +#define device_readstb 13 +extern enum clnt_stat device_readstb_1(Device_GenericParms *, Device_ReadStbResp *, CLIENT *); +extern bool_t device_readstb_1_svc(Device_GenericParms *, Device_ReadStbResp *, struct svc_req *); +#define device_trigger 14 +extern enum clnt_stat device_trigger_1(Device_GenericParms *, Device_Error *, CLIENT *); +extern bool_t device_trigger_1_svc(Device_GenericParms *, Device_Error *, struct svc_req *); +#define device_clear 15 +extern enum clnt_stat device_clear_1(Device_GenericParms *, Device_Error *, CLIENT *); +extern bool_t device_clear_1_svc(Device_GenericParms *, Device_Error *, struct svc_req *); +#define device_remote 16 +extern enum clnt_stat device_remote_1(Device_GenericParms *, Device_Error *, CLIENT *); +extern bool_t device_remote_1_svc(Device_GenericParms *, Device_Error *, struct svc_req *); +#define device_local 17 +extern enum clnt_stat device_local_1(Device_GenericParms *, Device_Error *, CLIENT *); +extern bool_t device_local_1_svc(Device_GenericParms *, Device_Error *, struct svc_req *); +#define device_lock 18 +extern enum clnt_stat device_lock_1(Device_LockParms *, Device_Error *, CLIENT *); +extern bool_t device_lock_1_svc(Device_LockParms *, Device_Error *, struct svc_req *); +#define device_unlock 19 +extern enum clnt_stat device_unlock_1(Device_Link *, Device_Error *, CLIENT *); +extern bool_t device_unlock_1_svc(Device_Link *, Device_Error *, struct svc_req *); +#define device_enable_srq 20 +extern enum clnt_stat device_enable_srq_1(Device_EnableSrqParms *, Device_Error *, CLIENT *); +extern bool_t device_enable_srq_1_svc(Device_EnableSrqParms *, Device_Error *, struct svc_req *); +#define device_docmd 22 +extern enum clnt_stat device_docmd_1(Device_DocmdParms *, Device_DocmdResp *, CLIENT *); +extern bool_t device_docmd_1_svc(Device_DocmdParms *, Device_DocmdResp *, struct svc_req *); +#define destroy_link 23 +extern enum clnt_stat destroy_link_1(Device_Link *, Device_Error *, CLIENT *); +extern bool_t destroy_link_1_svc(Device_Link *, Device_Error *, struct svc_req *); +#define create_intr_chan 25 +extern enum clnt_stat create_intr_chan_1(Device_RemoteFunc *, Device_Error *, CLIENT *); +extern bool_t create_intr_chan_1_svc(Device_RemoteFunc *, Device_Error *, struct svc_req *); +#define destroy_intr_chan 26 +extern enum clnt_stat destroy_intr_chan_1(void *, Device_Error *, CLIENT *); +extern bool_t destroy_intr_chan_1_svc(void *, Device_Error *, struct svc_req *); +extern int device_core_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define create_link 10 +extern enum clnt_stat create_link_1(); +extern bool_t create_link_1_svc(); +#define device_write 11 +extern enum clnt_stat device_write_1(); +extern bool_t device_write_1_svc(); +#define device_read 12 +extern enum clnt_stat device_read_1(); +extern bool_t device_read_1_svc(); +#define device_readstb 13 +extern enum clnt_stat device_readstb_1(); +extern bool_t device_readstb_1_svc(); +#define device_trigger 14 +extern enum clnt_stat device_trigger_1(); +extern bool_t device_trigger_1_svc(); +#define device_clear 15 +extern enum clnt_stat device_clear_1(); +extern bool_t device_clear_1_svc(); +#define device_remote 16 +extern enum clnt_stat device_remote_1(); +extern bool_t device_remote_1_svc(); +#define device_local 17 +extern enum clnt_stat device_local_1(); +extern bool_t device_local_1_svc(); +#define device_lock 18 +extern enum clnt_stat device_lock_1(); +extern bool_t device_lock_1_svc(); +#define device_unlock 19 +extern enum clnt_stat device_unlock_1(); +extern bool_t device_unlock_1_svc(); +#define device_enable_srq 20 +extern enum clnt_stat device_enable_srq_1(); +extern bool_t device_enable_srq_1_svc(); +#define device_docmd 22 +extern enum clnt_stat device_docmd_1(); +extern bool_t device_docmd_1_svc(); +#define destroy_link 23 +extern enum clnt_stat destroy_link_1(); +extern bool_t destroy_link_1_svc(); +#define create_intr_chan 25 +extern enum clnt_stat create_intr_chan_1(); +extern bool_t create_intr_chan_1_svc(); +#define destroy_intr_chan 26 +extern enum clnt_stat destroy_intr_chan_1(); +extern bool_t destroy_intr_chan_1_svc(); +extern int device_core_1_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_Device_Link (XDR *, Device_Link*); +extern bool_t xdr_Device_AddrFamily (XDR *, Device_AddrFamily*); +extern bool_t xdr_Device_Flags (XDR *, Device_Flags*); +extern bool_t xdr_Device_ErrorCode (XDR *, Device_ErrorCode*); +extern bool_t xdr_Device_Error (XDR *, Device_Error*); +extern bool_t xdr_Create_LinkParms (XDR *, Create_LinkParms*); +extern bool_t xdr_Create_LinkResp (XDR *, Create_LinkResp*); +extern bool_t xdr_Device_WriteParms (XDR *, Device_WriteParms*); +extern bool_t xdr_Device_WriteResp (XDR *, Device_WriteResp*); +extern bool_t xdr_Device_ReadParms (XDR *, Device_ReadParms*); +extern bool_t xdr_Device_ReadResp (XDR *, Device_ReadResp*); +extern bool_t xdr_Device_ReadStbResp (XDR *, Device_ReadStbResp*); +extern bool_t xdr_Device_GenericParms (XDR *, Device_GenericParms*); +extern bool_t xdr_Device_RemoteFunc (XDR *, Device_RemoteFunc*); +extern bool_t xdr_Device_EnableSrqParms (XDR *, Device_EnableSrqParms*); +extern bool_t xdr_Device_LockParms (XDR *, Device_LockParms*); +extern bool_t xdr_Device_DocmdParms (XDR *, Device_DocmdParms*); +extern bool_t xdr_Device_DocmdResp (XDR *, Device_DocmdResp*); + +#else /* K&R C */ +extern bool_t xdr_Device_Link (); +extern bool_t xdr_Device_AddrFamily (); +extern bool_t xdr_Device_Flags (); +extern bool_t xdr_Device_ErrorCode (); +extern bool_t xdr_Device_Error (); +extern bool_t xdr_Create_LinkParms (); +extern bool_t xdr_Create_LinkResp (); +extern bool_t xdr_Device_WriteParms (); +extern bool_t xdr_Device_WriteResp (); +extern bool_t xdr_Device_ReadParms (); +extern bool_t xdr_Device_ReadResp (); +extern bool_t xdr_Device_ReadStbResp (); +extern bool_t xdr_Device_GenericParms (); +extern bool_t xdr_Device_RemoteFunc (); +extern bool_t xdr_Device_EnableSrqParms (); +extern bool_t xdr_Device_LockParms (); +extern bool_t xdr_Device_DocmdParms (); +extern bool_t xdr_Device_DocmdResp (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_VXI11_H_RPCGEN */ diff --git a/src/vxi11/vxi11.x b/src/vxi11/vxi11.x new file mode 100644 index 0000000..d14bb6a --- /dev/null +++ b/src/vxi11/vxi11.x @@ -0,0 +1,183 @@ +% +%/* VXI-11 RPCL definitions. Taken from appendix C of the VXI-11 specfication. +% * See http://www.vxi.org +% */ + +%#include +%#include +% +%/* VXI-11 flags */ +%#define VXI11_FLAG_WAITLOCK 0x01 +%#define VXI11_FLAG_ENDW 0x08 +%#define VXI11_FLAG_TERMCHRSET 0x80 +% +%/* VXI-11 device_docmd 'cmd' values */ +%#define VXI11_DOCMD_SEND_COMMAND 0x020000 +%#define VXI11_DOCMD_BUS_STATUS 0x020001 +%#define VXI11_DOCMD_ATN_CONTROL 0x020002 +%#define VXI11_DOCMD_REN_CONTROL 0x020003 +%#define VXI11_DOCMD_PASS_CONTROL 0x020004 +%#define VXI11_DOCMD_BUS_ADDRESS 0x02000A +%#define VXI11_DOCMD_IFC_CONTROL 0x020010 +% +%/* VXI-11 device_docmd Bus Status values */ +%#define VXI11_DOCMD_STAT_REMOTE 1 +%#define VXI11_DOCMD_STAT_SRQ 2 +%#define VXI11_DOCMD_STAT_NDAC 3 +%#define VXI11_DOCMD_STAT_SYS_CTRLR 4 +%#define VXI11_DOCMD_STAT_CTRLR_CHRG 5 +%#define VXI11_DOCMD_STAT_TALKER 6 +%#define VXI11_DOCMD_STAT_LISTENER 7 +%#define VXI11_DOCMD_STAT_BUSADDR 8 +% +%/* VXI-11 device_read 'reason' bits */ +%#define VXI11_REASON_REQCNT 1 /* requested number of bytes read */ +%#define VXI11_REASON_CHR 2 /* read terminated by eos character */ +%#define VXI11_REASON_END 4 /* read terminated by EOI */ +% +%/* VXI-11 errors */ +%#define VXI11_ERR_SUCCESS 0 +%#define VXI11_ERR_SYNTAX 1 +%#define VXI11_ERR_NODEVICE 3 +%#define VXI11_ERR_LINKINVAL 4 +%#define VXI11_ERR_PARAMETER 5 +%#define VXI11_ERR_NOCHAN 6 +%#define VXI11_ERR_NOTSUPP 8 +%#define VXI11_ERR_RESOURCES 9 +%#define VXI11_ERR_LOCKED 11 +%#define VXI11_ERR_NOLOCK 12 +%#define VXI11_ERR_IOTIMEOUT 15 +%#define VXI11_ERR_IOERROR 17 +%#define VXI11_ERR_ADDRINVAL 21 +%#define VXI11_ERR_ABORT 23 +%#define VXI11_ERR_CHANEST 29 + +/* Types */ +typedef long Device_Link; +enum Device_AddrFamily { /* used by interrupts */ + DEVICE_TCP, + DEVICE_UDP +}; +typedef long Device_Flags; + +/* Error types */ +typedef long Device_ErrorCode; +struct Device_Error { + Device_ErrorCode error; +}; + +struct Create_LinkParms { + long clientId; /* implementation specific value */ + bool lockDevice; /* attempt to lock the device */ + unsigned long lock_timeout; /* time to wait on a lock */ + string device<>; /* name of device */ +}; + +struct Create_LinkResp { + Device_ErrorCode error; + Device_Link lid; + unsigned short abortPort; /* for the abort RPC */ + unsigned long maxRecvSize; /* specifies max data size in bytes device will accept on a write */ +}; + +struct Device_WriteParms { + Device_Link lid; /* link id from create_link */ + unsigned long io_timeout; /* time to wait for I/O */ + unsigned long lock_timeout; /* time to wait for lock */ + Device_Flags flags; opaque data<>; /* the data length and the data itself */ +}; + +struct Device_WriteResp { + Device_ErrorCode error; + unsigned long size; /* Number of bytes written */ +}; + +struct Device_ReadParms { + Device_Link lid; /* link id from create_link */ + unsigned long requestSize; /* Bytes requested */ + unsigned long io_timeout; /* time to wait for I/O */ + unsigned long lock_timeout; /* time to wait for lock */ + Device_Flags flags; + char termChar; /* valid if flags & termchrset */ +}; + +struct Device_ReadResp { + Device_ErrorCode error; + long reason; /* Reason(s) read completed */ + opaque data<>; /* data.len and data.val */ +}; + +struct Device_ReadStbResp { + Device_ErrorCode error; /* error code */ + unsigned char stb; /* the returned status byte */ +}; + +struct Device_GenericParms { + Device_Link lid; /* Device_Link id from connect call */ + Device_Flags flags; /* flags with options */ + unsigned long lock_timeout; /* time to wait for lock */ + unsigned long io_timeout; /* time to wait for I/O */ +}; + +struct Device_RemoteFunc { + unsigned long hostAddr; /* Host servicing Interrupt */ + unsigned short hostPort; /* valid port # on client */ + unsigned long progNum; /* DEVICE_INTR */ + unsigned long progVers; /* DEVICE_INTR_VERSION */ + Device_AddrFamily progFamily; /* DEVICE_UDP | DEVICE_TCP */ +}; + +struct Device_EnableSrqParms { + Device_Link lid; + bool enable; /* Enable or disable interrupts */ + opaque handle<40>; /* Host specific data */ +}; + +struct Device_LockParms { + Device_Link lid; /* link id from create_link */ + Device_Flags flags; /* Contains the waitlock flag */ + unsigned long lock_timeout; /* time to wait to acquire lock */ +}; + +struct Device_DocmdParms { + Device_Link lid; /* link id from create_link */ + Device_Flags flags; /* flags specifying various options */ + unsigned long io_timeout; /* time to wait for I/O to complete */ + unsigned long lock_timeout; /* time to wait on a lock */ + long cmd; /* which command to execute */ + bool network_order; /* client's byte order */ + long datasize; /* size of individual data elements */ + opaque data_in<>; /* docmd data parameters */ +}; + +struct Device_DocmdResp { + Device_ErrorCode error; /* returned status */ + opaque data_out<>; /* returned data parameter */ +}; + +program DEVICE_ASYNC{ + version DEVICE_ASYNC_VERSION { + Device_Error device_abort (Device_Link) = 1; + } = 1; +} = 0x0607B0; + +program DEVICE_CORE { + version DEVICE_CORE_VERSION { + Create_LinkResp create_link (Create_LinkParms) = 10; + Device_WriteResp device_write (Device_WriteParms) = 11; + Device_ReadResp device_read (Device_ReadParms) = 12; + Device_ReadStbResp device_readstb (Device_GenericParms) = 13; + Device_Error device_trigger (Device_GenericParms) = 14; + Device_Error device_clear (Device_GenericParms) = 15; + Device_Error device_remote (Device_GenericParms) = 16; + Device_Error device_local (Device_GenericParms) = 17; + Device_Error device_lock (Device_LockParms) = 18; + Device_Error device_unlock (Device_Link) = 19; + Device_Error device_enable_srq (Device_EnableSrqParms) = 20; + Device_DocmdResp device_docmd (Device_DocmdParms) = 22; + Device_Error destroy_link (Device_Link) = 23; + Device_Error create_intr_chan (Device_RemoteFunc) = 25; + Device_Error destroy_intr_chan (void) = 26; + } = 1; +} = 0x0607AF; + diff --git a/src/vxi11/vxi11_class.cc b/src/vxi11/vxi11_class.cc new file mode 100644 index 0000000..a0bae45 --- /dev/null +++ b/src/vxi11/vxi11_class.cc @@ -0,0 +1,392 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +// +// VXI11 functions are copied from Steve D. Sharples VXI11 library +// see http://optics.eee.nottingham.ac.uk/vxi11/ +// + +#include + +#include +#include + +// open or close vxi11 session only on call of vxi11 or vxi11_close +#define OPENONCE + +using std::string; + +#include "vxi11_class.h" + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_vxi11, "octave_vxi11", "octave_vxi11"); + + +#define VXI11_DEFAULT_TIMEOUT 10000 /* in ms */ +#define VXI11_READ_TIMEOUT 2000 /* in ms */ +#define VXI11_MAX_CLIENTS 256 /* maximum no of unique IP addresses/clients */ +#define VXI11_NULL_READ_RESP 50 /* vxi11_receive() return value if a query + * times out ON THE INSTRUMENT (and so we have + * to resend the query again) */ +#define VXI11_NULL_WRITE_RESP 51 /* vxi11_send() return value if a sent command + * times out ON THE INSTURMENT. */ + + + +octave_vxi11::octave_vxi11 (void) +{ + static bool type_registered = false; + + this->ip = ""; + + if (! type_registered) + { + type_registered = true; + register_type (); + } +} + +octave_vxi11::~octave_vxi11 (void) +{ + this->close (); +} + +void +octave_vxi11::print (std::ostream& os, bool pr_as_read_syntax) +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_vxi11::print (std::ostream& os, bool pr_as_read_syntax ) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +void +octave_vxi11::print_raw (std::ostream& os, bool pr_as_read_syntax) const +{ + os << this->ip; +} + +int +octave_vxi11::open (string ip) +{ + std::string inst="inst0"; + + this->ip=ip; + +#ifdef OPENONCE + if (this->openvxi (this->ip.c_str(),&this->client,&this->link,inst.c_str ())) + { + error ("vxi11: Cannot open VXI11..."); + return -1; + } +#endif + return 0; +} + +int +octave_vxi11::read(char *buf, unsigned int len) +{ + CLIENT *client; + Create_LinkResp *link; + + unsigned long timeout = VXI11_READ_TIMEOUT; + + if (this->ip.empty()) + { + error("vxi11: setup ip first"); + return -1; + } + +#ifdef OPENONCE + client = this->client; + link = this->link; +#else + std::string inst="inst0"; + if (this->openvxi(this->ip.c_str(),&client,&link,inst.c_str())) + { + error("vxi11: Cannot open VXI11..."); + return -1; + } +#endif + + #define RCV_END_BIT 0x04 // An end indicator has been read + #define RCV_CHR_BIT 0x02 // A termchr is set in flags and a character which matches termChar is transferred + #define RCV_REQCNT_BIT 0x01 // requestSize bytes have been transferred. This includes a request size of zero. + + //long vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout) { + Device_ReadParms read_parms; + Device_ReadResp read_resp; + unsigned int curr_pos = 0; + + read_parms.lid = link->lid; + read_parms.requestSize = len; + read_parms.io_timeout = timeout; /* in ms */ + read_parms.lock_timeout = timeout; /* in ms */ + read_parms.flags = 0; + read_parms.termChar = 0; + + do + { + memset(&read_resp, 0, sizeof(read_resp)); + + read_resp.data.data_val = buf + curr_pos; + read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len + + if(device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) + { + error ("vxi11: cannot read"); + return -1; /* there is nothing to read. Usually occurs after sending a query + which times out on the instrument. If we don't check this first, + then the following line causes a seg fault */ + } + if (read_resp.error != 0) + { + /* Read failed for reason specified in error code. + * (From published VXI-11 protocol, section B.5.2) + * 0 no error + * 1 syntax error + * 3 device not accessible + * 4 invalid link identifier + * 5 parameter error + * 6 channel not established + * 8 operation not supported + * 9 out of resources + * 11 device locked by another link + * 12 no lock held by this link + * 15 I/O timeout + * 17 I/O error + * 21 invalid address + * 23 abort + * 29 channel already established + */ + error ("vxi11: cannot read: %d",(int)read_resp.error); + return -1; + } + + if ((curr_pos + read_resp.data.data_len) <= len) + { + curr_pos += read_resp.data.data_len; + } + if( (read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT) ) + { + break; + } + else if( curr_pos == len ) + { + error ("xvi11: read error: buffer too small. Read %d bytes without hitting terminator.", (int)curr_pos ); + return -1; + } + } + while (1); + +#ifndef OPENONCE + // close VXI11 session + if (this->closevxi (this->ip.c_str (),client,link)) + { + error ("vxi11:Cannot close VXI11..."); + return -1; + } +#endif + return curr_pos; +} + +int +octave_vxi11::write (const char *buf, int len) +{ + + CLIENT *client; + Create_LinkResp *link; + + if (this->ip.empty ()) + { + error ("vxi11: setup ip first"); + return -1; + } + +#ifdef OPENONCE + client = this->client; + link = this->link; +#else + std::string inst="inst0"; + if (this->openvxi (this->ip.c_str (),&client,&link,inst.c_str ())) + { + error ("vxi11: Cannot open VXI11..."); + return -1; + } +#endif + + //int vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd, unsigned long len) { + Device_WriteParms write_parms; + unsigned int bytes_left = len; + char *send_cmd; + + send_cmd = new char[len]; + memcpy (send_cmd, buf, len); + + write_parms.lid = link->lid; + write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT; + write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT; + + /* We can only write (link->maxRecvSize) bytes at a time, so we sit in a loop, + * writing a chunk at a time, until we're done. */ + + do + { + Device_WriteResp write_resp; + memset(&write_resp, 0, sizeof(write_resp)); + + if (bytes_left <= link->maxRecvSize) + { + write_parms.flags = 8; + write_parms.data.data_len = bytes_left; + } + else + { + write_parms.flags = 0; + /* We need to check that maxRecvSize is a sane value (ie >0). Believe it + * or not, on some versions of Agilent Infiniium scope firmware the scope + * returned "0", which breaks Rule B.6.3 of the VXI-11 protocol. Nevertheless + * we need to catch this, otherwise the program just hangs. */ + if (link->maxRecvSize > 0) { + write_parms.data.data_len = link->maxRecvSize; + } + else + { + write_parms.data.data_len = 4096; /* pretty much anything should be able to cope with 4kB */ + } + } + write_parms.data.data_val = send_cmd + (len - bytes_left); + + if(device_write_1 (&write_parms, &write_resp, client) != RPC_SUCCESS) + { + delete[] send_cmd; + error ("vxi11: cannot write"); + return -VXI11_NULL_WRITE_RESP; /* The instrument did not acknowledge the write, just completely + dropped it. There was no vxi11 comms error as such, the + instrument is just being rude. Usually occurs when the instrument + is busy. If we don't check this first, then the following + line causes a seg fault */ + } + if (write_resp.error != 0) + { + error("vxi11_user: write error: %d", (int)write_resp.error); + delete[] send_cmd; + return -(write_resp.error); + } + bytes_left -= write_resp.size; + } + while (bytes_left > 0); + + delete[] send_cmd; + +#ifndef OPENONCE + // close VXI11 session + if (this->closevxi (this->ip.c_str (),client,link)) + { + error ("vxi11:Cannot close VXI11..."); + return -1; + } +#endif + + return 0; + +} + +int +octave_vxi11::close (void) +{ + int retval = 0; + +#ifdef OPENONCE + // close VXI11 session + if (!this->ip.empty()) + { + if (this->closevxi (this->ip.c_str (),this->client,this->link)) + { + error ("vxi11:Cannot close VXI11..."); + return -1; + } + } +#endif + this->ip = ""; + + return retval; +} + +int +octave_vxi11::openvxi (const char *ip, CLIENT **client, Create_LinkResp **link, const char *device) +{ +#ifdef CONST_CLNT_SUPPORT + const char * tmpip = ip; +#else + char tmpip[256]; + strncpy(tmpip, ip, 250); + tmpip[250] = '\0'; +#endif + + *client = clnt_create(tmpip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp"); + if (*client == NULL) + { + clnt_pcreateerror (tmpip); + error ("vxi11: Error creating client..."); + return -1; + } + + Create_LinkParms link_parms; + + /* Set link parameters */ + link_parms.clientId = (long) *client; + link_parms.lockDevice = 0; + link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT; + link_parms.device = (char *) device; + + *link = (Create_LinkResp *) calloc (1, sizeof(Create_LinkResp)); + + if (create_link_1 (&link_parms, *link, *client) != RPC_SUCCESS) + { + clnt_perror (*client, tmpip); + error ("vxi11: Error creating client..."); + return -2; + } + return 0; +} + +int +octave_vxi11::closevxi (const char *ip, CLIENT *client, Create_LinkResp *link) +{ + Device_Error dev_error; + memset (&dev_error, 0, sizeof(dev_error)); + + if (destroy_link_1 (&link->lid, &dev_error, client) != RPC_SUCCESS) + { +#ifdef CONST_CLNT_SUPPORT + const char * tmpip = ip; +#else + char tmpip[256]; + strncpy(tmpip, ip, 250); + tmpip[250] = '\0'; +#endif + clnt_perror (client, tmpip); + return -1; + } + + clnt_destroy (client); + return 0; +} diff --git a/src/vxi11/vxi11_class.h b/src/vxi11/vxi11_class.h new file mode 100644 index 0000000..841a014 --- /dev/null +++ b/src/vxi11/vxi11_class.h @@ -0,0 +1,75 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#ifndef VXI11_CLASS_H +#define VXI11_CLASS_H + +#include + +#include +#include "vxi11.h" + +#include + +using std::string; + +class octave_vxi11 : public octave_base_value +{ +public: + octave_vxi11 (void); + ~octave_vxi11 (void); + + int open (string); + int close (void); + + // Simple vxi11 commands + int write (const char*, int); + int read (char*, unsigned int); + + // Overloaded base functions + string vxi11_value () const + { + return (string)this->ip; + } + + virtual double scalar_value (bool frc_str_conv = false) const + { + return (double)0; + } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print_raw (std::ostream& os, bool pr_as_read_syntax) const; + + // Properties + bool is_constant (void) const { return true;} + bool is_defined (void) const { return true;} + bool print_as_scalar (void) const { return true;} + +private: + CLIENT *client; + Create_LinkResp *link; + std::string ip; + std::string device; + + int openvxi (const char *, CLIENT **, Create_LinkResp **, const char *); + int closevxi (const char *, CLIENT *, Create_LinkResp *); + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + + +#endif diff --git a/src/vxi11/vxi11_clnt.c b/src/vxi11/vxi11_clnt.c new file mode 100644 index 0000000..876f0c8 --- /dev/null +++ b/src/vxi11/vxi11_clnt.c @@ -0,0 +1,206 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include /* for memset */ +#include "vxi11.h" + +/* VXI-11 RPCL definitions. Taken from appendix C of the VXI-11 specfication. + * See http://www.vxi.org + */ +#include +#include + +/* VXI-11 flags */ +#define VXI11_FLAG_WAITLOCK 0x01 +#define VXI11_FLAG_ENDW 0x08 +#define VXI11_FLAG_TERMCHRSET 0x80 + +/* VXI-11 device_docmd 'cmd' values */ +#define VXI11_DOCMD_SEND_COMMAND 0x020000 +#define VXI11_DOCMD_BUS_STATUS 0x020001 +#define VXI11_DOCMD_ATN_CONTROL 0x020002 +#define VXI11_DOCMD_REN_CONTROL 0x020003 +#define VXI11_DOCMD_PASS_CONTROL 0x020004 +#define VXI11_DOCMD_BUS_ADDRESS 0x02000A +#define VXI11_DOCMD_IFC_CONTROL 0x020010 + +/* VXI-11 device_docmd Bus Status values */ +#define VXI11_DOCMD_STAT_REMOTE 1 +#define VXI11_DOCMD_STAT_SRQ 2 +#define VXI11_DOCMD_STAT_NDAC 3 +#define VXI11_DOCMD_STAT_SYS_CTRLR 4 +#define VXI11_DOCMD_STAT_CTRLR_CHRG 5 +#define VXI11_DOCMD_STAT_TALKER 6 +#define VXI11_DOCMD_STAT_LISTENER 7 +#define VXI11_DOCMD_STAT_BUSADDR 8 + +/* VXI-11 device_read 'reason' bits */ +#define VXI11_REASON_REQCNT 1 /* requested number of bytes read */ +#define VXI11_REASON_CHR 2 /* read terminated by eos character */ +#define VXI11_REASON_END 4 /* read terminated by EOI */ + +/* VXI-11 errors */ +#define VXI11_ERR_SUCCESS 0 +#define VXI11_ERR_SYNTAX 1 +#define VXI11_ERR_NODEVICE 3 +#define VXI11_ERR_LINKINVAL 4 +#define VXI11_ERR_PARAMETER 5 +#define VXI11_ERR_NOCHAN 6 +#define VXI11_ERR_NOTSUPP 8 +#define VXI11_ERR_RESOURCES 9 +#define VXI11_ERR_LOCKED 11 +#define VXI11_ERR_NOLOCK 12 +#define VXI11_ERR_IOTIMEOUT 15 +#define VXI11_ERR_IOERROR 17 +#define VXI11_ERR_ADDRINVAL 21 +#define VXI11_ERR_ABORT 23 +#define VXI11_ERR_CHANEST 29 + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +enum clnt_stat +device_abort_1(Device_Link *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_abort, + (xdrproc_t) xdr_Device_Link, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +create_link_1(Create_LinkParms *argp, Create_LinkResp *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, create_link, + (xdrproc_t) xdr_Create_LinkParms, (caddr_t) argp, + (xdrproc_t) xdr_Create_LinkResp, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_write_1(Device_WriteParms *argp, Device_WriteResp *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_write, + (xdrproc_t) xdr_Device_WriteParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_WriteResp, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_read_1(Device_ReadParms *argp, Device_ReadResp *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_read, + (xdrproc_t) xdr_Device_ReadParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_ReadResp, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_readstb_1(Device_GenericParms *argp, Device_ReadStbResp *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_readstb, + (xdrproc_t) xdr_Device_GenericParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_ReadStbResp, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_trigger_1(Device_GenericParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_trigger, + (xdrproc_t) xdr_Device_GenericParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_clear_1(Device_GenericParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_clear, + (xdrproc_t) xdr_Device_GenericParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_remote_1(Device_GenericParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_remote, + (xdrproc_t) xdr_Device_GenericParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_local_1(Device_GenericParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_local, + (xdrproc_t) xdr_Device_GenericParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_lock_1(Device_LockParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_lock, + (xdrproc_t) xdr_Device_LockParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_unlock_1(Device_Link *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_unlock, + (xdrproc_t) xdr_Device_Link, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_enable_srq_1(Device_EnableSrqParms *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_enable_srq, + (xdrproc_t) xdr_Device_EnableSrqParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +device_docmd_1(Device_DocmdParms *argp, Device_DocmdResp *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, device_docmd, + (xdrproc_t) xdr_Device_DocmdParms, (caddr_t) argp, + (xdrproc_t) xdr_Device_DocmdResp, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +destroy_link_1(Device_Link *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, destroy_link, + (xdrproc_t) xdr_Device_Link, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +create_intr_chan_1(Device_RemoteFunc *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, create_intr_chan, + (xdrproc_t) xdr_Device_RemoteFunc, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +destroy_intr_chan_1(void *argp, Device_Error *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, destroy_intr_chan, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res, + TIMEOUT)); +} diff --git a/src/vxi11/vxi11_close.cc b/src/vxi11/vxi11_close.cc new file mode 100644 index 0000000..a1f5206 --- /dev/null +++ b/src/vxi11/vxi11_close.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_VXI11 +#include "vxi11_class.h" +#endif + +// PKG_ADD: autoload ("vxi11_close", "vxi11.oct"); +DEFUN_DLD (vxi11_close, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} vxi11_close (@var{vxi11})\n \ +\n\ +Close the interface and release a file descriptor.\n \ +\n\ +@var{vxi11} - instance of @var{octave_vxi11} class.\n \ +@end deftypefn") +{ +#ifndef BUILD_VXI11 + error ("vxi11: Your system doesn't support the VXI11 interface"); + return octave_value(); +#else + if (args.length () != 1 || args (0).type_id () != octave_vxi11::static_type_id()) + { + print_usage (); + return octave_value (-1); + } + + octave_vxi11* vxi11 = NULL; + + const octave_base_value& rep = args (0).get_rep (); + vxi11 = &((octave_vxi11 &)rep); + + vxi11->close (); + + return octave_value (); +#endif +} diff --git a/src/vxi11/vxi11_read.cc b/src/vxi11/vxi11_read.cc new file mode 100644 index 0000000..5bd0479 --- /dev/null +++ b/src/vxi11/vxi11_read.cc @@ -0,0 +1,96 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_VXI11 +#include + +#include "vxi11_class.h" +#endif + +// PKG_ADD: autoload ("vxi11_read", "vxi11.oct"); +DEFUN_DLD (vxi11_read, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{data}, @var{count}] = } vxi11_read (@var{vxi11}, @var{n})\n \ +\n\ +Read from vxi11 slave device.\n \ +\n\ +@var{vxi11} - instance of @var{octave_vxi11} class.@* \ +@var{n} - number of bytes to attempt to read of type Integer.\n \ +\n\ +The vxi11_read() shall return number of bytes successfully read in @var{count} as Integer and the bytes themselves in @var{data} as uint8 array.\n \ +@end deftypefn") +{ +#ifndef BUILD_VXI11 + error ("vxi11: Your system doesn't support the VXI11 interface"); + return octave_value (); +#else + + if (args.length () < 1 || args.length () > 2 || args (0).type_id () != octave_vxi11::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + unsigned int buffer_len = 1; + + if (args.length () > 1) + { + if ( !(args (1).OV_ISINTEGER() || args (1).OV_ISFLOAT()) ) + { + print_usage (); + return octave_value (-1); + } + + buffer_len = args (1).int_value (); + } + + OCTAVE_LOCAL_BUFFER (char, buffer, (buffer_len + 1)); + + if (buffer == NULL) + { + error ("vxi11_read: cannot allocate requested memory..."); + return octave_value (-1); + } + + octave_vxi11* vxi11 = NULL; + + const octave_base_value& rep = args(0).get_rep(); + vxi11 = &((octave_vxi11 &)rep); + + int retval; + + retval = vxi11->read (buffer, buffer_len); + + octave_value_list return_list; + + uint8NDArray data( dim_vector(1, (retval > 0) ? retval : 0) ); + + for (int i = 0; i < retval; i++) + data(i) = static_cast(buffer[i]); + + return_list (0) = data; + return_list (1) = retval; + + return return_list; +#endif +} diff --git a/src/vxi11/vxi11_svc.c b/src/vxi11/vxi11_svc.c new file mode 100644 index 0000000..ca52740 --- /dev/null +++ b/src/vxi11/vxi11_svc.c @@ -0,0 +1,316 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "vxi11.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +/* VXI-11 RPCL definitions. Taken from appendix C of the VXI-11 specfication. + * See http://www.vxi.org + */ +#include +#include + +/* VXI-11 flags */ +#define VXI11_FLAG_WAITLOCK 0x01 +#define VXI11_FLAG_ENDW 0x08 +#define VXI11_FLAG_TERMCHRSET 0x80 + +/* VXI-11 device_docmd 'cmd' values */ +#define VXI11_DOCMD_SEND_COMMAND 0x020000 +#define VXI11_DOCMD_BUS_STATUS 0x020001 +#define VXI11_DOCMD_ATN_CONTROL 0x020002 +#define VXI11_DOCMD_REN_CONTROL 0x020003 +#define VXI11_DOCMD_PASS_CONTROL 0x020004 +#define VXI11_DOCMD_BUS_ADDRESS 0x02000A +#define VXI11_DOCMD_IFC_CONTROL 0x020010 + +/* VXI-11 device_docmd Bus Status values */ +#define VXI11_DOCMD_STAT_REMOTE 1 +#define VXI11_DOCMD_STAT_SRQ 2 +#define VXI11_DOCMD_STAT_NDAC 3 +#define VXI11_DOCMD_STAT_SYS_CTRLR 4 +#define VXI11_DOCMD_STAT_CTRLR_CHRG 5 +#define VXI11_DOCMD_STAT_TALKER 6 +#define VXI11_DOCMD_STAT_LISTENER 7 +#define VXI11_DOCMD_STAT_BUSADDR 8 + +/* VXI-11 device_read 'reason' bits */ +#define VXI11_REASON_REQCNT 1 /* requested number of bytes read */ +#define VXI11_REASON_CHR 2 /* read terminated by eos character */ +#define VXI11_REASON_END 4 /* read terminated by EOI */ + +/* VXI-11 errors */ +#define VXI11_ERR_SUCCESS 0 +#define VXI11_ERR_SYNTAX 1 +#define VXI11_ERR_NODEVICE 3 +#define VXI11_ERR_LINKINVAL 4 +#define VXI11_ERR_PARAMETER 5 +#define VXI11_ERR_NOCHAN 6 +#define VXI11_ERR_NOTSUPP 8 +#define VXI11_ERR_RESOURCES 9 +#define VXI11_ERR_LOCKED 11 +#define VXI11_ERR_NOLOCK 12 +#define VXI11_ERR_IOTIMEOUT 15 +#define VXI11_ERR_IOERROR 17 +#define VXI11_ERR_ADDRINVAL 21 +#define VXI11_ERR_ABORT 23 +#define VXI11_ERR_CHANEST 29 + +static void +device_async_1(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + Device_Link device_abort_1_arg; + } argument; + union { + Device_Error device_abort_1_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case device_abort: + _xdr_argument = (xdrproc_t) xdr_Device_Link; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_abort_1_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!device_async_1_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +static void +device_core_1(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + Create_LinkParms create_link_1_arg; + Device_WriteParms device_write_1_arg; + Device_ReadParms device_read_1_arg; + Device_GenericParms device_readstb_1_arg; + Device_GenericParms device_trigger_1_arg; + Device_GenericParms device_clear_1_arg; + Device_GenericParms device_remote_1_arg; + Device_GenericParms device_local_1_arg; + Device_LockParms device_lock_1_arg; + Device_Link device_unlock_1_arg; + Device_EnableSrqParms device_enable_srq_1_arg; + Device_DocmdParms device_docmd_1_arg; + Device_Link destroy_link_1_arg; + Device_RemoteFunc create_intr_chan_1_arg; + } argument; + union { + Create_LinkResp create_link_1_res; + Device_WriteResp device_write_1_res; + Device_ReadResp device_read_1_res; + Device_ReadStbResp device_readstb_1_res; + Device_Error device_trigger_1_res; + Device_Error device_clear_1_res; + Device_Error device_remote_1_res; + Device_Error device_local_1_res; + Device_Error device_lock_1_res; + Device_Error device_unlock_1_res; + Device_Error device_enable_srq_1_res; + Device_DocmdResp device_docmd_1_res; + Device_Error destroy_link_1_res; + Device_Error create_intr_chan_1_res; + Device_Error destroy_intr_chan_1_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case create_link: + _xdr_argument = (xdrproc_t) xdr_Create_LinkParms; + _xdr_result = (xdrproc_t) xdr_Create_LinkResp; + local = (bool_t (*) (char *, void *, struct svc_req *))create_link_1_svc; + break; + + case device_write: + _xdr_argument = (xdrproc_t) xdr_Device_WriteParms; + _xdr_result = (xdrproc_t) xdr_Device_WriteResp; + local = (bool_t (*) (char *, void *, struct svc_req *))device_write_1_svc; + break; + + case device_read: + _xdr_argument = (xdrproc_t) xdr_Device_ReadParms; + _xdr_result = (xdrproc_t) xdr_Device_ReadResp; + local = (bool_t (*) (char *, void *, struct svc_req *))device_read_1_svc; + break; + + case device_readstb: + _xdr_argument = (xdrproc_t) xdr_Device_GenericParms; + _xdr_result = (xdrproc_t) xdr_Device_ReadStbResp; + local = (bool_t (*) (char *, void *, struct svc_req *))device_readstb_1_svc; + break; + + case device_trigger: + _xdr_argument = (xdrproc_t) xdr_Device_GenericParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_trigger_1_svc; + break; + + case device_clear: + _xdr_argument = (xdrproc_t) xdr_Device_GenericParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_clear_1_svc; + break; + + case device_remote: + _xdr_argument = (xdrproc_t) xdr_Device_GenericParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_remote_1_svc; + break; + + case device_local: + _xdr_argument = (xdrproc_t) xdr_Device_GenericParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_local_1_svc; + break; + + case device_lock: + _xdr_argument = (xdrproc_t) xdr_Device_LockParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_lock_1_svc; + break; + + case device_unlock: + _xdr_argument = (xdrproc_t) xdr_Device_Link; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_unlock_1_svc; + break; + + case device_enable_srq: + _xdr_argument = (xdrproc_t) xdr_Device_EnableSrqParms; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))device_enable_srq_1_svc; + break; + + case device_docmd: + _xdr_argument = (xdrproc_t) xdr_Device_DocmdParms; + _xdr_result = (xdrproc_t) xdr_Device_DocmdResp; + local = (bool_t (*) (char *, void *, struct svc_req *))device_docmd_1_svc; + break; + + case destroy_link: + _xdr_argument = (xdrproc_t) xdr_Device_Link; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))destroy_link_1_svc; + break; + + case create_intr_chan: + _xdr_argument = (xdrproc_t) xdr_Device_RemoteFunc; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))create_intr_chan_1_svc; + break; + + case destroy_intr_chan: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_Device_Error; + local = (bool_t (*) (char *, void *, struct svc_req *))destroy_intr_chan_1_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!device_core_1_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +int +main (int argc, char **argv) +{ + register SVCXPRT *transp; + + pmap_unset (DEVICE_ASYNC, DEVICE_ASYNC_VERSION); + pmap_unset (DEVICE_CORE, DEVICE_CORE_VERSION); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create udp service."); + exit(1); + } + if (!svc_register(transp, DEVICE_ASYNC, DEVICE_ASYNC_VERSION, device_async_1, IPPROTO_UDP)) { + fprintf (stderr, "%s", "unable to register (DEVICE_ASYNC, DEVICE_ASYNC_VERSION, udp)."); + exit(1); + } + if (!svc_register(transp, DEVICE_CORE, DEVICE_CORE_VERSION, device_core_1, IPPROTO_UDP)) { + fprintf (stderr, "%s", "unable to register (DEVICE_CORE, DEVICE_CORE_VERSION, udp)."); + exit(1); + } + + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create tcp service."); + exit(1); + } + if (!svc_register(transp, DEVICE_ASYNC, DEVICE_ASYNC_VERSION, device_async_1, IPPROTO_TCP)) { + fprintf (stderr, "%s", "unable to register (DEVICE_ASYNC, DEVICE_ASYNC_VERSION, tcp)."); + exit(1); + } + if (!svc_register(transp, DEVICE_CORE, DEVICE_CORE_VERSION, device_core_1, IPPROTO_TCP)) { + fprintf (stderr, "%s", "unable to register (DEVICE_CORE, DEVICE_CORE_VERSION, tcp)."); + exit(1); + } + + svc_run (); + fprintf (stderr, "%s", "svc_run returned"); + exit (1); + /* NOTREACHED */ +} diff --git a/src/vxi11/vxi11_write.cc b/src/vxi11/vxi11_write.cc new file mode 100644 index 0000000..b835f49 --- /dev/null +++ b/src/vxi11/vxi11_write.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2018 John Donoghue +// Copyright (C) 2013 Stefan Mahr +// Copyright (C) 2012 Andrius Sutas +// +// 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 . + +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#ifdef BUILD_VXI11 +#include "vxi11_class.h" +#endif + +// PKG_ADD: autoload ("vxi11_write", "vxi11.oct"); +DEFUN_DLD (vxi11_write, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{n} = } vxi11_write (@var{vxi11}, @var{data})\n \ +\n\ +Write data to a vxi11 slave device.\n \ +\n\ +@var{vxi11} - instance of @var{octave_vxi11} class.@* \ +@var{data} - data to be written to the slave device. Can be either of String or uint8 type.\n \ +\n\ +Upon successful completion, vxi11_write() shall return the number of bytes written as the result @var{n}.\n \ +@end deftypefn") +{ +#ifndef BUILD_VXI11 + error ("vxi11: Your system doesn't support the VXI11 interface"); + return octave_value (); +#else + + if (args.length () != 2 || args (0).type_id () != octave_vxi11::static_type_id ()) + { + print_usage (); + return octave_value (-1); + } + + octave_vxi11* vxi11 = NULL; + + const octave_base_value& rep = args (0).get_rep (); + vxi11 = &((octave_vxi11 &)rep); + + const octave_base_value& data = args (1).get_rep (); + int retval; + + if (data.is_string ()) + { + string buf = data.string_value (); + retval = vxi11->write (buf.c_str (), buf.length ()); + } + else if (data.is_uint8_type ()) + { + NDArray dtmp = data.array_value (); + OCTAVE_LOCAL_BUFFER (char, buf, (dtmp.numel ())); + + for (int i = 0; i < dtmp.numel (); i++) + buf[i] = (char)dtmp(i); + + retval = vxi11->write (buf, data.byte_size()); + } + else + { + print_usage (); + return octave_value (-1); + } + + return octave_value (retval); +#endif +} diff --git a/src/vxi11/vxi11_xdr.c b/src/vxi11/vxi11_xdr.c new file mode 100644 index 0000000..25ff39d --- /dev/null +++ b/src/vxi11/vxi11_xdr.c @@ -0,0 +1,504 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "vxi11.h" + +/* VXI-11 RPCL definitions. Taken from appendix C of the VXI-11 specfication. + * See http://www.vxi.org + */ +#include +#include + +/* VXI-11 flags */ +#define VXI11_FLAG_WAITLOCK 0x01 +#define VXI11_FLAG_ENDW 0x08 +#define VXI11_FLAG_TERMCHRSET 0x80 + +/* VXI-11 device_docmd 'cmd' values */ +#define VXI11_DOCMD_SEND_COMMAND 0x020000 +#define VXI11_DOCMD_BUS_STATUS 0x020001 +#define VXI11_DOCMD_ATN_CONTROL 0x020002 +#define VXI11_DOCMD_REN_CONTROL 0x020003 +#define VXI11_DOCMD_PASS_CONTROL 0x020004 +#define VXI11_DOCMD_BUS_ADDRESS 0x02000A +#define VXI11_DOCMD_IFC_CONTROL 0x020010 + +/* VXI-11 device_docmd Bus Status values */ +#define VXI11_DOCMD_STAT_REMOTE 1 +#define VXI11_DOCMD_STAT_SRQ 2 +#define VXI11_DOCMD_STAT_NDAC 3 +#define VXI11_DOCMD_STAT_SYS_CTRLR 4 +#define VXI11_DOCMD_STAT_CTRLR_CHRG 5 +#define VXI11_DOCMD_STAT_TALKER 6 +#define VXI11_DOCMD_STAT_LISTENER 7 +#define VXI11_DOCMD_STAT_BUSADDR 8 + +/* VXI-11 device_read 'reason' bits */ +#define VXI11_REASON_REQCNT 1 /* requested number of bytes read */ +#define VXI11_REASON_CHR 2 /* read terminated by eos character */ +#define VXI11_REASON_END 4 /* read terminated by EOI */ + +/* VXI-11 errors */ +#define VXI11_ERR_SUCCESS 0 +#define VXI11_ERR_SYNTAX 1 +#define VXI11_ERR_NODEVICE 3 +#define VXI11_ERR_LINKINVAL 4 +#define VXI11_ERR_PARAMETER 5 +#define VXI11_ERR_NOCHAN 6 +#define VXI11_ERR_NOTSUPP 8 +#define VXI11_ERR_RESOURCES 9 +#define VXI11_ERR_LOCKED 11 +#define VXI11_ERR_NOLOCK 12 +#define VXI11_ERR_IOTIMEOUT 15 +#define VXI11_ERR_IOERROR 17 +#define VXI11_ERR_ADDRINVAL 21 +#define VXI11_ERR_ABORT 23 +#define VXI11_ERR_CHANEST 29 + +bool_t +xdr_Device_Link (XDR *xdrs, Device_Link *objp) +{ + register int32_t *buf; + + if (!xdr_long (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_AddrFamily (XDR *xdrs, Device_AddrFamily *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_Flags (XDR *xdrs, Device_Flags *objp) +{ + register int32_t *buf; + + if (!xdr_long (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_ErrorCode (XDR *xdrs, Device_ErrorCode *objp) +{ + register int32_t *buf; + + if (!xdr_long (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_Error (XDR *xdrs, Device_Error *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Create_LinkParms (XDR *xdrs, Create_LinkParms *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_long (xdrs, &objp->clientId)) + return FALSE; + if (!xdr_bool (xdrs, &objp->lockDevice)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + + } else { + IXDR_PUT_LONG(buf, objp->clientId); + IXDR_PUT_BOOL(buf, objp->lockDevice); + IXDR_PUT_U_LONG(buf, objp->lock_timeout); + } + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_long (xdrs, &objp->clientId)) + return FALSE; + if (!xdr_bool (xdrs, &objp->lockDevice)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + + } else { + objp->clientId = IXDR_GET_LONG(buf); + objp->lockDevice = IXDR_GET_BOOL(buf); + objp->lock_timeout = IXDR_GET_U_LONG(buf); + } + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; + } + + if (!xdr_long (xdrs, &objp->clientId)) + return FALSE; + if (!xdr_bool (xdrs, &objp->lockDevice)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Create_LinkResp (XDR *xdrs, Create_LinkResp *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_u_short (xdrs, &objp->abortPort)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->maxRecvSize)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_WriteParms (XDR *xdrs, Device_WriteParms *objp) +{ + register int32_t *buf; + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_WriteResp (XDR *xdrs, Device_WriteResp *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->size)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_ReadParms (XDR *xdrs, Device_ReadParms *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->requestSize)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + + } else { + IXDR_PUT_U_LONG(buf, objp->requestSize); + IXDR_PUT_U_LONG(buf, objp->io_timeout); + IXDR_PUT_U_LONG(buf, objp->lock_timeout); + } + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_char (xdrs, &objp->termChar)) + return FALSE; + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->requestSize)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + + } else { + objp->requestSize = IXDR_GET_U_LONG(buf); + objp->io_timeout = IXDR_GET_U_LONG(buf); + objp->lock_timeout = IXDR_GET_U_LONG(buf); + } + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_char (xdrs, &objp->termChar)) + return FALSE; + return TRUE; + } + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->requestSize)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_char (xdrs, &objp->termChar)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_ReadResp (XDR *xdrs, Device_ReadResp *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + if (!xdr_long (xdrs, &objp->reason)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_ReadStbResp (XDR *xdrs, Device_ReadStbResp *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->stb)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_GenericParms (XDR *xdrs, Device_GenericParms *objp) +{ + register int32_t *buf; + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_RemoteFunc (XDR *xdrs, Device_RemoteFunc *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->hostAddr)) + return FALSE; + if (!xdr_u_short (xdrs, &objp->hostPort)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progNum)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progVers)) + return FALSE; + + } else { + IXDR_PUT_U_LONG(buf, objp->hostAddr); + IXDR_PUT_U_SHORT(buf, objp->hostPort); + IXDR_PUT_U_LONG(buf, objp->progNum); + IXDR_PUT_U_LONG(buf, objp->progVers); + } + if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily)) + return FALSE; + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->hostAddr)) + return FALSE; + if (!xdr_u_short (xdrs, &objp->hostPort)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progNum)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progVers)) + return FALSE; + + } else { + objp->hostAddr = IXDR_GET_U_LONG(buf); + objp->hostPort = IXDR_GET_U_SHORT(buf); + objp->progNum = IXDR_GET_U_LONG(buf); + objp->progVers = IXDR_GET_U_LONG(buf); + } + if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily)) + return FALSE; + return TRUE; + } + + if (!xdr_u_long (xdrs, &objp->hostAddr)) + return FALSE; + if (!xdr_u_short (xdrs, &objp->hostPort)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progNum)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->progVers)) + return FALSE; + if (!xdr_Device_AddrFamily (xdrs, &objp->progFamily)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_EnableSrqParms (XDR *xdrs, Device_EnableSrqParms *objp) +{ + register int32_t *buf; + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_bool (xdrs, &objp->enable)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->handle.handle_val, (u_int *) &objp->handle.handle_len, 40)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_LockParms (XDR *xdrs, Device_LockParms *objp) +{ + register int32_t *buf; + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_DocmdParms (XDR *xdrs, Device_DocmdParms *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_long (xdrs, &objp->cmd)) + return FALSE; + if (!xdr_bool (xdrs, &objp->network_order)) + return FALSE; + if (!xdr_long (xdrs, &objp->datasize)) + return FALSE; + + } else { + IXDR_PUT_U_LONG(buf, objp->io_timeout); + IXDR_PUT_U_LONG(buf, objp->lock_timeout); + IXDR_PUT_LONG(buf, objp->cmd); + IXDR_PUT_BOOL(buf, objp->network_order); + IXDR_PUT_LONG(buf, objp->datasize); + } + if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0)) + return FALSE; + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_long (xdrs, &objp->cmd)) + return FALSE; + if (!xdr_bool (xdrs, &objp->network_order)) + return FALSE; + if (!xdr_long (xdrs, &objp->datasize)) + return FALSE; + + } else { + objp->io_timeout = IXDR_GET_U_LONG(buf); + objp->lock_timeout = IXDR_GET_U_LONG(buf); + objp->cmd = IXDR_GET_LONG(buf); + objp->network_order = IXDR_GET_BOOL(buf); + objp->datasize = IXDR_GET_LONG(buf); + } + if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0)) + return FALSE; + return TRUE; + } + + if (!xdr_Device_Link (xdrs, &objp->lid)) + return FALSE; + if (!xdr_Device_Flags (xdrs, &objp->flags)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->io_timeout)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->lock_timeout)) + return FALSE; + if (!xdr_long (xdrs, &objp->cmd)) + return FALSE; + if (!xdr_bool (xdrs, &objp->network_order)) + return FALSE; + if (!xdr_long (xdrs, &objp->datasize)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data_in.data_in_val, (u_int *) &objp->data_in.data_in_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_Device_DocmdResp (XDR *xdrs, Device_DocmdResp *objp) +{ + register int32_t *buf; + + if (!xdr_Device_ErrorCode (xdrs, &objp->error)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data_out.data_out_val, (u_int *) &objp->data_out.data_out_len, ~0)) + return FALSE; + return TRUE; +} -- cgit v1.2.3 From 834ca664b8765f217313b829e820a8a9174ab5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Mon, 16 Aug 2021 13:39:53 -0300 Subject: Import octave-instrument-control_0.7.0-2.debian.tar.xz [dgit import tarball octave-instrument-control 0.7.0-2 octave-instrument-control_0.7.0-2.debian.tar.xz] --- changelog | 108 +++++++++++++++++++++++++++++++ clean | 20 ++++++ control | 23 +++++++ copyright | 70 +++++++++++++++++++++ gbp.conf | 4 ++ patches/series | 1 + patches/xtest-in-unit-tests.patch | 129 ++++++++++++++++++++++++++++++++++++++ rules | 5 ++ source/format | 1 + source/options | 1 + upstream/metadata | 4 ++ watch | 2 + 12 files changed, 368 insertions(+) create mode 100644 changelog create mode 100644 clean create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 patches/series create mode 100644 patches/xtest-in-unit-tests.patch create mode 100755 rules create mode 100644 source/format create mode 100644 source/options create mode 100644 upstream/metadata create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..1670568 --- /dev/null +++ b/changelog @@ -0,0 +1,108 @@ +octave-instrument-control (0.7.0-2) unstable; urgency=medium + + * Upload to unstable + + -- Rafael Laboissière Mon, 16 Aug 2021 13:39:53 -0300 + +octave-instrument-control (0.7.0-1) experimental; urgency=medium + + * New upstream version 0.7.0 + * d/p/xtest-tcpclient.patch: Drop patch (not needed anymore) + * d/copyright: Reflect upstream changes + * d/control: Bump Standards-Version to 4.5.1 (no changes needed) + * d/clean: Clean automatically generated files + * d/u/metadata: Add Repository field + + -- Rafael Laboissière Sat, 27 Feb 2021 06:18:49 -0300 + +octave-instrument-control (0.6.0-2) unstable; urgency=medium + + * d/p/xtest-tcpclient.patch: New patch + * d/watch: Bump to version 4 + + -- Rafael Laboissière Tue, 17 Nov 2020 04:06:55 -0300 + +octave-instrument-control (0.6.0-1) unstable; urgency=medium + + * New upstream version 0.6.0 + * d/copyright: Reflect upstream changes + * d/p/xtest-in-unit-tests.patch: Refresh for new upstream version + * d/s/options: Ignore common.mk for upstream changes + + -- Rafael Laboissière Sat, 31 Oct 2020 04:02:35 -0300 + +octave-instrument-control (0.5.0-3) unstable; urgency=medium + + * d/p/xtest-in-unit-tests.patch: Set Forwarded:not-needed + + -- Rafael Laboissière Sat, 01 Aug 2020 02:57:05 -0300 + +octave-instrument-control (0.5.0-2) unstable; urgency=medium + + * d/control: Bump debhelper compatibitlity level to 13 + * d/u/metadata: Drop Name and Contact fields + * d/p/xtest-in-unit-tests.patch: Switch to xtest for tests involving + remote servers (Closes: #964211) + + -- Rafael Laboissière Mon, 13 Jul 2020 06:15:39 -0300 + +octave-instrument-control (0.5.0-1) unstable; urgency=medium + + * New upstream version 0.5.0 + * d/copyright: Reflect upstream changes + * d/p/xtest-in-unit-tests.patch: Refresh for new upstream version + * d/control: Bump Standards-Version to 4.5.0 (no changes needed) + * d/u/metadata: New file + * d/clean: New file + + -- Rafael Laboissière Wed, 15 Apr 2020 11:53:58 -0300 + +octave-instrument-control (0.4.0-4) unstable; urgency=medium + + * d/control: + + Bump Standards-Version to 4.4.1 (no changes needed) + + Bump dependency on dh-octave to >= 0.7.1 + This allows the injection of the virtual package octave-abi-N into + the package's list of dependencies. + + -- Rafael Laboissiere Tue, 05 Nov 2019 14:15:52 -0300 + +octave-instrument-control (0.4.0-3) unstable; urgency=medium + + [ Rafael Laboissiere ] + * Upload to unstable + * d/control: Bump Standards-Version to 4.4.0 (no changes needed) + + [ Sébastien Villemot ] + * d/copyright: use correct license short name (FSFAP) for Makefile + + -- Rafael Laboissiere Wed, 10 Jul 2019 05:15:53 -0300 + +octave-instrument-control (0.4.0-2) experimental; urgency=medium + + * d/p/xtest-in-unit-tests.patch: Ignore unit tests involding TCP/IP + + -- Rafael Laboissiere Sun, 12 May 2019 04:18:37 -0300 + +octave-instrument-control (0.4.0-1) experimental; urgency=medium + + * New upstream version 0.4.0 + * d/copyright: Reflect upstream changes + + -- Rafael Laboissiere Mon, 06 May 2019 11:08:29 -0300 + +octave-instrument-control (0.3.1-2) unstable; urgency=medium + + * d/control: + + Add Rules-Requires-Root: no + + Bump Standards-Version to 4.3.0 + + Bump to debhelper compat level 12 + * Build-depend on debhelper-compat instead of using d/compat + + -- Rafael Laboissiere Wed, 02 Jan 2019 22:56:05 -0200 + +octave-instrument-control (0.3.1-1) unstable; urgency=medium + + * Initial release (Closes: #899145) + + -- Rafael Laboissiere Sat, 30 Jun 2018 10:17:17 -0300 diff --git a/clean b/clean new file mode 100644 index 0000000..6d06b6a --- /dev/null +++ b/clean @@ -0,0 +1,20 @@ +inst/test/ +src/Makefile +src/config.h +src/config.log +src/config.status +src/gpib/Makefile +src/hwinfo/Makefile +src/i2c/Makefile +src/make-pkg-add-file.cc +src/parallel/Makefile +src/resolvehost/Makefile +src/serial/Makefile +src/serialport/Makefile +src/spi/Makefile +src/tcp/Makefile +src/tcpclient/Makefile +src/udp/Makefile +src/udpport/Makefile +src/usbtmc/Makefile +src/vxi11/Makefile diff --git a/control b/control new file mode 100644 index 0000000..1a59f01 --- /dev/null +++ b/control @@ -0,0 +1,23 @@ +Source: octave-instrument-control +Section: math +Priority: optional +Maintainer: Debian Octave Group +Uploaders: Rafael Laboissière +Build-Depends: debhelper-compat (= 13), + dh-octave (>= 0.7.1) +Standards-Version: 4.5.1 +Homepage: https://octave.sourceforge.io/instrument-control/ +Vcs-Git: https://salsa.debian.org/pkg-octave-team/octave-instrument-control.git +Vcs-Browser: https://salsa.debian.org/pkg-octave-team/octave-instrument-control +Testsuite: autopkgtest-pkg-octave +Rules-Requires-Root: no + +Package: octave-instrument-control +Architecture: any +Depends: ${misc:Depends}, ${octave:Depends}, ${shlibs:Depends} +Description: instrument control for Octave + This package contains Low level input/output functions for serial, + i2c, parallel, tcp, gpib, vxi11 and usbtmc interfaces for use in + Octave, a scientific computation software. + . + This Octave add-on package is part of the Octave-Forge project. diff --git a/copyright b/copyright new file mode 100644 index 0000000..cf02de3 --- /dev/null +++ b/copyright @@ -0,0 +1,70 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Instrument Control for Octave +Upstream-Contact: Stefan Mahr , John Donoghue +Source: https://octave.sourceforge.io/instrument-control/ + +Files: * +Copyright: 2012, 2014 Andrius Sutas + 2013-2019 Stefan Mahr + 2014, 2016-2021 John Donoghue + 2016 Andreas Weber +License: GPL-3+ + +Files: Makefile +Copyright: 2015-2016 Carnë Draug + 2015-2016 Oliver Heimlich + 2017 Julien Bect + 2017 Olaf Till + 2018-2020 John Donoghue +License: FSFAP + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. This file is offered as-is, + without any warranty. + +Files: src/aclocal.m4 +Copyright: 2004 Scott James Remnant + 2012-2015 Dan Nicholson +License: GPL-2+ with Autoconf exception + 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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that + program. + +Files: debian/* +Copyright: 2018-2021 Rafael Laboissiere +License: GPL-3+ + +License: GPL-3+ + 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 . + . + On Debian systems, the complete text of the GNU General Public + License, version 3, can be found in the file + `/usr/share/common-licenses/GPL-3'. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..6b65fe0 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,4 @@ +[DEFAULT] +debian-branch = debian/latest +upstream-branch = upstream/latest +pristine-tar = True diff --git a/patches/series b/patches/series new file mode 100644 index 0000000..ebbfc64 --- /dev/null +++ b/patches/series @@ -0,0 +1 @@ +xtest-in-unit-tests.patch diff --git a/patches/xtest-in-unit-tests.patch b/patches/xtest-in-unit-tests.patch new file mode 100644 index 0000000..23a76be --- /dev/null +++ b/patches/xtest-in-unit-tests.patch @@ -0,0 +1,129 @@ +Description: Allow some problematic unit tests to fail +Author: Rafael Laboissiere +Forwarded: not-needed +Last-Update: 2020-04-15 + +--- octave-instrument-control-0.3.1.orig/inst/instrhwinfo.m ++++ octave-instrument-control-0.3.1/inst/instrhwinfo.m +@@ -151,7 +151,7 @@ endfunction + %! # could fail if no i2c ports or not configured + %! assert(!isempty(instrhwinfo("i2c"))) + +-%!test ++%!xtest + %! p = pkg('describe', 'instrument-control'); + %! hw = instrhwinfo (); + %! assert (hw.ToolboxVersion, p{1}.version) +--- octave-instrument-control-0.3.1.orig/src/tcp/tcp.cc ++++ octave-instrument-control-0.3.1/src/tcp/tcp.cc +@@ -203,7 +203,7 @@ The tcp() shall return instance of @var{ + } + + #if 0 +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80); + %! assert (! isnull (a)); +@@ -210,7 +210,7 @@ number of bytes currently available to r + %! assert (isa (a, 'octave_tcp')); + %! tcp_close (a); + +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); + %! assert (! isnull (a)); +--- octave-instrument-control-0.3.1.orig/src/tcp/tcp_close.cc ++++ octave-instrument-control-0.3.1/src/tcp/tcp_close.cc +@@ -60,7 +60,7 @@ Close the interface and release a file d + #endif + } + #if 0 +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80); + %! tcp_close (a); +--- octave-instrument-control-0.3.1.orig/src/tcp/tcp_read.cc ++++ octave-instrument-control-0.3.1/src/tcp/tcp_read.cc +@@ -114,7 +114,7 @@ The tcp_read() shall return number of by + } + + #if 0 +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80); + %! assert (! isnull (a)); +--- octave-instrument-control-0.3.1.orig/src/tcp/tcp_write.cc ++++ octave-instrument-control-0.3.1/src/tcp/tcp_write.cc +@@ -93,7 +93,7 @@ Upon successful completion, tcp_write() + + %!error tcp_write() + +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80);; + %! # call HTTP HEAD +--- octave-instrument-control-0.4.0.orig/inst/tcpip.m ++++ octave-instrument-control-0.4.0/inst/tcpip.m +@@ -72,7 +72,7 @@ function out = tcpip (varargin) + + endfunction + +-%!test ++%!xtest + %! a = tcpip ("octave.org", 80); + %! assert(isa(a, "octave_tcp")); + %! fclose(a); +--- octave-instrument-control-0.4.0.orig/src/tcp/__tcp_properties__.cc ++++ octave-instrument-control-0.4.0/src/tcp/__tcp_properties__.cc +@@ -97,7 +97,7 @@ Undocumented internal function.\n\ + %!shared ip + %! ip = resolvehost("www.octave.org", "address"); + +-%!test ++%!xtest + %! # test get + %! a = tcp (ip, 80); + %! assert (__tcp_properties__ (a,"type"), "tcp"); +@@ -110,7 +110,7 @@ Undocumented internal function.\n\ + %! tcp_close (a); + %! assert (__tcp_properties__ (a,"status"), "closed"); + +-%!test ++%!xtest + %! # test set + %! a = tcp(ip, 80); + %! __tcp_properties__ (a, 'name', "mytest"); +@@ -118,7 +118,7 @@ Undocumented internal function.\n\ + %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); + %! tcp_close (a); + +-%!test ++%!xtest + %! # test flush + %! a = tcp(ip, 80); + %! __tcp_properties__ (a, 'flush', 0); +@@ -132,7 +132,7 @@ Undocumented internal function.\n\ + + %!error __tcp_properties__ (1) + +-%!test ++%!xtest + %! a = tcp (ip, 80); + %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); + %! tcp_close (a); +--- octave-instrument-control-0.5.0.orig/src/tcp/tcp_timeout.cc ++++ octave-instrument-control-0.5.0/src/tcp/tcp_timeout.cc +@@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, t + } + + #if 0 +-%!test ++%!xtest + %! addr = resolvehost ('gnu.org', 'address'); + %! a = tcp (addr, 80); + %! assert(tcp_timeout(a), -1); diff --git a/rules b/rules new file mode 100755 index 0000000..121f3c8 --- /dev/null +++ b/rules @@ -0,0 +1,5 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +%: + dh $@ --buildsystem=octave --with=octave diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/source/options b/source/options new file mode 100644 index 0000000..6d4594a --- /dev/null +++ b/source/options @@ -0,0 +1 @@ +extend-diff-ignore=src/.*\.oct|src/.*\.o|src/.*/Makefile|src/Makefile|src/config\.h|src/config\.log|src/config\.status|inst/test/.*\.cc-tst|src/make-pkg-add-file\.cc|src/oct-alt-includes\.h|src/common\.mk diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..1ebe9e7 --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,4 @@ +Bug-Database: https://savannah.gnu.org/bugs/?group=octave +Bug-Submit: https://savannah.gnu.org/bugs/?func=additem&group=octave +Repository: http://hg.code.sf.net/p/octave/instrument-control +Repository-Browse: https://octave.sourceforge.io/pkg-repository/instrument-control/ diff --git a/watch b/watch new file mode 100644 index 0000000..f3abaa1 --- /dev/null +++ b/watch @@ -0,0 +1,2 @@ +version=4 +http://sf.net/octave/instrument-control-(.+)\.tar\.gz -- cgit v1.2.3 From 9546c771584b2b02cf271076b49145f1aba384a7 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Mon, 16 Aug 2021 13:39:53 -0300 Subject: Allow some problematic unit tests to fail Forwarded: not-needed Last-Update: 2020-04-15 Gbp-Pq: Name xtest-in-unit-tests.patch --- inst/instrhwinfo.m | 2 +- inst/tcpip.m | 2 +- src/tcp/__tcp_properties__.cc | 8 ++++---- src/tcp/tcp.cc | 4 ++-- src/tcp/tcp_close.cc | 2 +- src/tcp/tcp_read.cc | 2 +- src/tcp/tcp_timeout.cc | 2 +- src/tcp/tcp_write.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m index ac59af4..25e1782 100644 --- a/inst/instrhwinfo.m +++ b/inst/instrhwinfo.m @@ -151,7 +151,7 @@ endfunction %! # could fail if no i2c ports or not configured %! assert(!isempty(instrhwinfo("i2c"))) -%!test +%!xtest %! p = pkg('describe', 'instrument-control'); %! hw = instrhwinfo (); %! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/tcpip.m b/inst/tcpip.m index 2e4bba8..e1228e4 100644 --- a/inst/tcpip.m +++ b/inst/tcpip.m @@ -72,7 +72,7 @@ function out = tcpip (varargin) endfunction -%!test +%!xtest %! a = tcpip ("octave.org", 80); %! assert(isa(a, "octave_tcp")); %! fclose(a); diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index b701cb2..4ca11e7 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -97,7 +97,7 @@ Undocumented internal function.\n\ %!shared ip %! ip = resolvehost("www.octave.org", "address"); -%!test +%!xtest %! # test get %! a = tcp (ip, 80); %! assert (__tcp_properties__ (a,"type"), "tcp"); @@ -110,7 +110,7 @@ Undocumented internal function.\n\ %! tcp_close (a); %! assert (__tcp_properties__ (a,"status"), "closed"); -%!test +%!xtest %! # test set %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'name', "mytest"); @@ -118,7 +118,7 @@ Undocumented internal function.\n\ %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); %! tcp_close (a); -%!test +%!xtest %! # test flush %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'flush', 0); @@ -132,7 +132,7 @@ Undocumented internal function.\n\ %!error __tcp_properties__ (1) -%!test +%!xtest %! a = tcp (ip, 80); %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! tcp_close (a); diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc index 31819f9..925e3ea 100644 --- a/src/tcp/tcp.cc +++ b/src/tcp/tcp.cc @@ -203,14 +203,14 @@ number of bytes currently available to read (readonly)\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcp')); %! tcp_close (a); -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc index 8acba48..785e9a2 100644 --- a/src/tcp/tcp_close.cc +++ b/src/tcp/tcp_close.cc @@ -60,7 +60,7 @@ None\n \ #endif } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! tcp_close (a); diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc index 534a50a..9db8235 100644 --- a/src/tcp/tcp_read.cc +++ b/src/tcp/tcp_read.cc @@ -114,7 +114,7 @@ Read from tcp interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc index e40a2fa..f11902f 100644 --- a/src/tcp/tcp_timeout.cc +++ b/src/tcp/tcp_timeout.cc @@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, the tcp_timeout() shall return current ti } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert(tcp_timeout(a), -1); diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc index 6feeb27..37a314c 100644 --- a/src/tcp/tcp_write.cc +++ b/src/tcp/tcp_write.cc @@ -93,7 +93,7 @@ Upon successful completion, tcp_write() shall return the number of bytes written %!error tcp_write() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80);; %! # call HTTP HEAD -- cgit v1.2.3 From 1b1ec1c082305404baaac051482a4bb3343517b4 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sun, 14 Nov 2021 17:48:49 -0300 Subject: Allow some problematic unit tests to fail Forwarded: not-needed Last-Update: 2020-04-15 Gbp-Pq: Name xtest-in-unit-tests.patch --- inst/instrhwinfo.m | 2 +- inst/tcpip.m | 2 +- src/tcp/__tcp_properties__.cc | 8 ++++---- src/tcp/tcp.cc | 4 ++-- src/tcp/tcp_close.cc | 2 +- src/tcp/tcp_read.cc | 2 +- src/tcp/tcp_timeout.cc | 2 +- src/tcp/tcp_write.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m index ac59af4..25e1782 100644 --- a/inst/instrhwinfo.m +++ b/inst/instrhwinfo.m @@ -151,7 +151,7 @@ endfunction %! # could fail if no i2c ports or not configured %! assert(!isempty(instrhwinfo("i2c"))) -%!test +%!xtest %! p = pkg('describe', 'instrument-control'); %! hw = instrhwinfo (); %! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/tcpip.m b/inst/tcpip.m index 2e4bba8..e1228e4 100644 --- a/inst/tcpip.m +++ b/inst/tcpip.m @@ -72,7 +72,7 @@ function out = tcpip (varargin) endfunction -%!test +%!xtest %! a = tcpip ("octave.org", 80); %! assert(isa(a, "octave_tcp")); %! fclose(a); diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index b701cb2..4ca11e7 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -97,7 +97,7 @@ Undocumented internal function.\n\ %!shared ip %! ip = resolvehost("www.octave.org", "address"); -%!test +%!xtest %! # test get %! a = tcp (ip, 80); %! assert (__tcp_properties__ (a,"type"), "tcp"); @@ -110,7 +110,7 @@ Undocumented internal function.\n\ %! tcp_close (a); %! assert (__tcp_properties__ (a,"status"), "closed"); -%!test +%!xtest %! # test set %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'name', "mytest"); @@ -118,7 +118,7 @@ Undocumented internal function.\n\ %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); %! tcp_close (a); -%!test +%!xtest %! # test flush %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'flush', 0); @@ -132,7 +132,7 @@ Undocumented internal function.\n\ %!error __tcp_properties__ (1) -%!test +%!xtest %! a = tcp (ip, 80); %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! tcp_close (a); diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc index 31819f9..925e3ea 100644 --- a/src/tcp/tcp.cc +++ b/src/tcp/tcp.cc @@ -203,14 +203,14 @@ number of bytes currently available to read (readonly)\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcp')); %! tcp_close (a); -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc index 8acba48..785e9a2 100644 --- a/src/tcp/tcp_close.cc +++ b/src/tcp/tcp_close.cc @@ -60,7 +60,7 @@ None\n \ #endif } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! tcp_close (a); diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc index 534a50a..9db8235 100644 --- a/src/tcp/tcp_read.cc +++ b/src/tcp/tcp_read.cc @@ -114,7 +114,7 @@ Read from tcp interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc index e40a2fa..f11902f 100644 --- a/src/tcp/tcp_timeout.cc +++ b/src/tcp/tcp_timeout.cc @@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, the tcp_timeout() shall return current ti } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert(tcp_timeout(a), -1); diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc index 6feeb27..37a314c 100644 --- a/src/tcp/tcp_write.cc +++ b/src/tcp/tcp_write.cc @@ -93,7 +93,7 @@ Upon successful completion, tcp_write() shall return the number of bytes written %!error tcp_write() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80);; %! # call HTTP HEAD -- cgit v1.2.3 From 1022ab0c3dfd830b3953db28d8c5f5a171c8e7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 14 Nov 2021 17:48:49 -0300 Subject: Honor the environment variable CFLAGS Forwarded: https://savannah.gnu.org/bugs/index.php?61485 Last-Update: 2021-11-14 This is required in Debian, such that hardening flags like -fstack-protector-strong, -Wformat, and -Werror=format-security are used in the compilation of C++ files. Gbp-Pq: Name honor-cflags.patch --- src/vxi11/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vxi11/Makefile.in b/src/vxi11/Makefile.in index add0b44..93bc6a1 100644 --- a/src/vxi11/Makefile.in +++ b/src/vxi11/Makefile.in @@ -7,7 +7,7 @@ RPCGEN ?= @RPCGEN@ RPCGENOPTS ?= @RPCGENOPTS@ LFLAGS = $(LIBS) -CFLAGS = $(CPPFLAGS) @DEFS@ +CFLAGS += $(CPPFLAGS) @DEFS@ BUILD_VXI11 = @BUILD_VXI11@ -- cgit v1.2.3 From 8a3126d5f43e3ec68f63d47626e99c26d755d4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 14 Nov 2021 17:48:49 -0300 Subject: Do not fail when calling resolvehost in standalone system Forwarded: not-needed Last-Update: 2021-11-15 This is necessary when there is no network access at package build time. Gbp-Pq: Name xtest-resolvehost.patch --- src/tcp/__tcp_properties__.cc | 6 +++++- src/tcpclient/__tcpclient_properties__.cc | 14 +++++++++----- src/tcpclient/__tcpclient_read__.cc | 2 +- src/tcpclient/__tcpclient_write__.cc | 2 +- src/tcpclient/tcpclient.cc | 4 ++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index 4ca11e7..e03f229 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -95,7 +95,11 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch %!xtest %! # test get diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc index 9b00766..1ffcdca 100644 --- a/src/tcpclient/__tcpclient_properties__.cc +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -149,9 +149,13 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch -%!test +%!xtest %! # test get %! a = tcpclient (ip, 80); %! assert (__tcpclient_properties__ (a,"type"), "tcpclient"); @@ -163,7 +167,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid')", "invalid property name"); %! clear a -%!test +%!xtest %! # test set %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'name', "mytest"); @@ -171,7 +175,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid', 1)", "invalid property name"); %! clear a -%!test +%!xtest %! # test flush %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'flush', 0); @@ -185,7 +189,7 @@ Undocumented internal function.\n\ %!error __tcpclient_properties__ (1) -%!test +%!xtest %! a = tcpclient (ip, 80); %! fail ("__tcpclient_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! clear a diff --git a/src/tcpclient/__tcpclient_read__.cc b/src/tcpclient/__tcpclient_read__.cc index f7a868e..7e8bdf0 100644 --- a/src/tcpclient/__tcpclient_read__.cc +++ b/src/tcpclient/__tcpclient_read__.cc @@ -112,7 +112,7 @@ Private function t read from tcpclient interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcpclient/__tcpclient_write__.cc b/src/tcpclient/__tcpclient_write__.cc index 6f73363..9a9f7df 100644 --- a/src/tcpclient/__tcpclient_write__.cc +++ b/src/tcpclient/__tcpclient_write__.cc @@ -91,7 +91,7 @@ Upon successful completion, __tcpclient_write__() shall return the number of byt %!error __tcpclient_write__() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80);; %! # call HTTP HEAD diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc index 7a6f9f5..3457b2a 100644 --- a/src/tcpclient/tcpclient.cc +++ b/src/tcpclient/tcpclient.cc @@ -193,14 +193,14 @@ User data\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcpclient')); %! clear a -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); -- cgit v1.2.3 From 670251c9b15f77ae2755a30f997df2feed9c67a4 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sat, 22 Jan 2022 12:50:57 -0300 Subject: Allow some problematic unit tests to fail Forwarded: not-needed Last-Update: 2020-04-15 Gbp-Pq: Name xtest-in-unit-tests.patch --- inst/instrhwinfo.m | 2 +- inst/tcpip.m | 2 +- src/tcp/__tcp_properties__.cc | 8 ++++---- src/tcp/tcp.cc | 4 ++-- src/tcp/tcp_close.cc | 2 +- src/tcp/tcp_read.cc | 2 +- src/tcp/tcp_timeout.cc | 2 +- src/tcp/tcp_write.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m index fc0b28d..19dd62d 100644 --- a/inst/instrhwinfo.m +++ b/inst/instrhwinfo.m @@ -151,7 +151,7 @@ endfunction %! # could fail if no i2c ports or not configured %! assert(!isempty(instrhwinfo("i2c"))) -%!test +%!xtest %! p = pkg('describe', 'instrument-control'); %! hw = instrhwinfo (); %! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/tcpip.m b/inst/tcpip.m index eec4277..1595a00 100644 --- a/inst/tcpip.m +++ b/inst/tcpip.m @@ -72,7 +72,7 @@ function out = tcpip (varargin) endfunction -%!test +%!xtest %! a = tcpip ("octave.org", 80); %! assert(isa(a, "octave_tcp")); %! fclose(a); diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index b701cb2..4ca11e7 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -97,7 +97,7 @@ Undocumented internal function.\n\ %!shared ip %! ip = resolvehost("www.octave.org", "address"); -%!test +%!xtest %! # test get %! a = tcp (ip, 80); %! assert (__tcp_properties__ (a,"type"), "tcp"); @@ -110,7 +110,7 @@ Undocumented internal function.\n\ %! tcp_close (a); %! assert (__tcp_properties__ (a,"status"), "closed"); -%!test +%!xtest %! # test set %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'name', "mytest"); @@ -118,7 +118,7 @@ Undocumented internal function.\n\ %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); %! tcp_close (a); -%!test +%!xtest %! # test flush %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'flush', 0); @@ -132,7 +132,7 @@ Undocumented internal function.\n\ %!error __tcp_properties__ (1) -%!test +%!xtest %! a = tcp (ip, 80); %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! tcp_close (a); diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc index 31819f9..925e3ea 100644 --- a/src/tcp/tcp.cc +++ b/src/tcp/tcp.cc @@ -203,14 +203,14 @@ number of bytes currently available to read (readonly)\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcp')); %! tcp_close (a); -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc index 8acba48..785e9a2 100644 --- a/src/tcp/tcp_close.cc +++ b/src/tcp/tcp_close.cc @@ -60,7 +60,7 @@ None\n \ #endif } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! tcp_close (a); diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc index 534a50a..9db8235 100644 --- a/src/tcp/tcp_read.cc +++ b/src/tcp/tcp_read.cc @@ -114,7 +114,7 @@ Read from tcp interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc index e40a2fa..f11902f 100644 --- a/src/tcp/tcp_timeout.cc +++ b/src/tcp/tcp_timeout.cc @@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, the tcp_timeout() shall return current ti } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert(tcp_timeout(a), -1); diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc index 6feeb27..37a314c 100644 --- a/src/tcp/tcp_write.cc +++ b/src/tcp/tcp_write.cc @@ -93,7 +93,7 @@ Upon successful completion, tcp_write() shall return the number of bytes written %!error tcp_write() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80);; %! # call HTTP HEAD -- cgit v1.2.3 From bb9e8c106f8da5a6ae9a4d42ca33b73a5a0d251f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sat, 22 Jan 2022 12:50:57 -0300 Subject: Do not fail when calling resolvehost in standalone system Forwarded: not-needed Last-Update: 2021-11-15 This is necessary when there is no network access at package build time. Gbp-Pq: Name xtest-resolvehost.patch --- src/tcp/__tcp_properties__.cc | 6 +++++- src/tcpclient/__tcpclient_properties__.cc | 14 +++++++++----- src/tcpclient/__tcpclient_read__.cc | 2 +- src/tcpclient/__tcpclient_write__.cc | 2 +- src/tcpclient/tcpclient.cc | 4 ++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index 4ca11e7..e03f229 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -95,7 +95,11 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch %!xtest %! # test get diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc index 9b00766..1ffcdca 100644 --- a/src/tcpclient/__tcpclient_properties__.cc +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -149,9 +149,13 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch -%!test +%!xtest %! # test get %! a = tcpclient (ip, 80); %! assert (__tcpclient_properties__ (a,"type"), "tcpclient"); @@ -163,7 +167,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid')", "invalid property name"); %! clear a -%!test +%!xtest %! # test set %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'name', "mytest"); @@ -171,7 +175,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid', 1)", "invalid property name"); %! clear a -%!test +%!xtest %! # test flush %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'flush', 0); @@ -185,7 +189,7 @@ Undocumented internal function.\n\ %!error __tcpclient_properties__ (1) -%!test +%!xtest %! a = tcpclient (ip, 80); %! fail ("__tcpclient_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! clear a diff --git a/src/tcpclient/__tcpclient_read__.cc b/src/tcpclient/__tcpclient_read__.cc index f7a868e..7e8bdf0 100644 --- a/src/tcpclient/__tcpclient_read__.cc +++ b/src/tcpclient/__tcpclient_read__.cc @@ -112,7 +112,7 @@ Private function t read from tcpclient interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcpclient/__tcpclient_write__.cc b/src/tcpclient/__tcpclient_write__.cc index 6f73363..9a9f7df 100644 --- a/src/tcpclient/__tcpclient_write__.cc +++ b/src/tcpclient/__tcpclient_write__.cc @@ -91,7 +91,7 @@ Upon successful completion, __tcpclient_write__() shall return the number of byt %!error __tcpclient_write__() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80);; %! # call HTTP HEAD diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc index 7a6f9f5..3457b2a 100644 --- a/src/tcpclient/tcpclient.cc +++ b/src/tcpclient/tcpclient.cc @@ -193,14 +193,14 @@ User data\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcpclient')); %! clear a -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); -- cgit v1.2.3 From fa2db766adfb7cf8cecbcb52203444e27f1025e7 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Mon, 11 Jul 2022 08:54:40 -0300 Subject: Allow some problematic unit tests to fail Forwarded: not-needed Last-Update: 2020-04-15 Gbp-Pq: Name xtest-in-unit-tests.patch --- inst/instrhwinfo.m | 2 +- inst/tcpip.m | 2 +- src/tcp/__tcp_properties__.cc | 8 ++++---- src/tcp/tcp.cc | 4 ++-- src/tcp/tcp_close.cc | 2 +- src/tcp/tcp_read.cc | 2 +- src/tcp/tcp_timeout.cc | 2 +- src/tcp/tcp_write.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m index fc0b28d..19dd62d 100644 --- a/inst/instrhwinfo.m +++ b/inst/instrhwinfo.m @@ -151,7 +151,7 @@ endfunction %! # could fail if no i2c ports or not configured %! assert(!isempty(instrhwinfo("i2c"))) -%!test +%!xtest %! p = pkg('describe', 'instrument-control'); %! hw = instrhwinfo (); %! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/tcpip.m b/inst/tcpip.m index eec4277..1595a00 100644 --- a/inst/tcpip.m +++ b/inst/tcpip.m @@ -72,7 +72,7 @@ function out = tcpip (varargin) endfunction -%!test +%!xtest %! a = tcpip ("octave.org", 80); %! assert(isa(a, "octave_tcp")); %! fclose(a); diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index b701cb2..4ca11e7 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -97,7 +97,7 @@ Undocumented internal function.\n\ %!shared ip %! ip = resolvehost("www.octave.org", "address"); -%!test +%!xtest %! # test get %! a = tcp (ip, 80); %! assert (__tcp_properties__ (a,"type"), "tcp"); @@ -110,7 +110,7 @@ Undocumented internal function.\n\ %! tcp_close (a); %! assert (__tcp_properties__ (a,"status"), "closed"); -%!test +%!xtest %! # test set %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'name', "mytest"); @@ -118,7 +118,7 @@ Undocumented internal function.\n\ %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); %! tcp_close (a); -%!test +%!xtest %! # test flush %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'flush', 0); @@ -132,7 +132,7 @@ Undocumented internal function.\n\ %!error __tcp_properties__ (1) -%!test +%!xtest %! a = tcp (ip, 80); %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! tcp_close (a); diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc index 31819f9..925e3ea 100644 --- a/src/tcp/tcp.cc +++ b/src/tcp/tcp.cc @@ -203,14 +203,14 @@ number of bytes currently available to read (readonly)\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcp')); %! tcp_close (a); -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc index 8acba48..785e9a2 100644 --- a/src/tcp/tcp_close.cc +++ b/src/tcp/tcp_close.cc @@ -60,7 +60,7 @@ None\n \ #endif } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! tcp_close (a); diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc index 534a50a..9db8235 100644 --- a/src/tcp/tcp_read.cc +++ b/src/tcp/tcp_read.cc @@ -114,7 +114,7 @@ Read from tcp interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc index e40a2fa..f11902f 100644 --- a/src/tcp/tcp_timeout.cc +++ b/src/tcp/tcp_timeout.cc @@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, the tcp_timeout() shall return current ti } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert(tcp_timeout(a), -1); diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc index 6feeb27..37a314c 100644 --- a/src/tcp/tcp_write.cc +++ b/src/tcp/tcp_write.cc @@ -93,7 +93,7 @@ Upon successful completion, tcp_write() shall return the number of bytes written %!error tcp_write() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80);; %! # call HTTP HEAD -- cgit v1.2.3 From 397e82fd54093e02f04b7c987873c3982dfe5b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Mon, 11 Jul 2022 08:54:40 -0300 Subject: Do not fail when calling resolvehost in standalone system Forwarded: not-needed Last-Update: 2021-11-15 This is necessary when there is no network access at package build time. Gbp-Pq: Name xtest-resolvehost.patch --- src/tcp/__tcp_properties__.cc | 6 +++++- src/tcpclient/__tcpclient_properties__.cc | 14 +++++++++----- src/tcpclient/__tcpclient_read__.cc | 2 +- src/tcpclient/__tcpclient_write__.cc | 2 +- src/tcpclient/tcpclient.cc | 4 ++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index 4ca11e7..e03f229 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -95,7 +95,11 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch %!xtest %! # test get diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc index 9b00766..1ffcdca 100644 --- a/src/tcpclient/__tcpclient_properties__.cc +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -149,9 +149,13 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch -%!test +%!xtest %! # test get %! a = tcpclient (ip, 80); %! assert (__tcpclient_properties__ (a,"type"), "tcpclient"); @@ -163,7 +167,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid')", "invalid property name"); %! clear a -%!test +%!xtest %! # test set %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'name', "mytest"); @@ -171,7 +175,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid', 1)", "invalid property name"); %! clear a -%!test +%!xtest %! # test flush %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'flush', 0); @@ -185,7 +189,7 @@ Undocumented internal function.\n\ %!error __tcpclient_properties__ (1) -%!test +%!xtest %! a = tcpclient (ip, 80); %! fail ("__tcpclient_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! clear a diff --git a/src/tcpclient/__tcpclient_read__.cc b/src/tcpclient/__tcpclient_read__.cc index f7a868e..7e8bdf0 100644 --- a/src/tcpclient/__tcpclient_read__.cc +++ b/src/tcpclient/__tcpclient_read__.cc @@ -112,7 +112,7 @@ Private function t read from tcpclient interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcpclient/__tcpclient_write__.cc b/src/tcpclient/__tcpclient_write__.cc index 6f73363..9a9f7df 100644 --- a/src/tcpclient/__tcpclient_write__.cc +++ b/src/tcpclient/__tcpclient_write__.cc @@ -91,7 +91,7 @@ Upon successful completion, __tcpclient_write__() shall return the number of byt %!error __tcpclient_write__() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80);; %! # call HTTP HEAD diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc index 7a6f9f5..3457b2a 100644 --- a/src/tcpclient/tcpclient.cc +++ b/src/tcpclient/tcpclient.cc @@ -193,14 +193,14 @@ User data\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcpclient')); %! clear a -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); -- cgit v1.2.3 From e659406b31eb2527ee4c0bc7e8205dd4c0f4c525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Mon, 11 Jul 2022 08:54:40 -0300 Subject: Fix rules in src/Makefile.in Forwarded: https://savannah.gnu.org/bugs/index.php?62743 Last-Update: 2022-07-11 + Drop extraneous colon (:) in command in realclean rule + Remove common.mk in distcelan rule Gbp-Pq: Name fix-realclean-and-distclean-rules.patch --- src/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index fc8eebb..c74d625 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -40,11 +40,11 @@ clean: $(CLEANDIRS) realclean: -rm -f *.oct - -rm -f make-pkg-add-file.cc: + -rm -f make-pkg-add-file.cc distclean: realclean $(DISTCLEANDIRS) -rm -rf autom4te.cache - -rm -f Makefile config.status config.log config.h + -rm -f Makefile config.status config.log config.h common.mk maintainer-clean: distclean -rm -f configure -- cgit v1.2.3 From 8f99f9c6a4b4eab8fe0c62644527c52c5eb79149 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sun, 24 Jul 2022 13:52:59 -0300 Subject: Allow some problematic unit tests to fail Forwarded: not-needed Last-Update: 2020-04-15 Gbp-Pq: Name xtest-in-unit-tests.patch --- inst/instrhwinfo.m | 2 +- inst/tcpip.m | 2 +- src/tcp/__tcp_properties__.cc | 8 ++++---- src/tcp/tcp.cc | 4 ++-- src/tcp/tcp_close.cc | 2 +- src/tcp/tcp_read.cc | 2 +- src/tcp/tcp_timeout.cc | 2 +- src/tcp/tcp_write.cc | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/inst/instrhwinfo.m b/inst/instrhwinfo.m index 70a1cf6..e8d469a 100644 --- a/inst/instrhwinfo.m +++ b/inst/instrhwinfo.m @@ -156,7 +156,7 @@ endfunction %! # could fail if no i2c ports or not configured %! assert(!isempty(instrhwinfo("i2c"))) -%!test +%!xtest %! p = pkg('describe', 'instrument-control'); %! hw = instrhwinfo (); %! assert (hw.ToolboxVersion, p{1}.version) diff --git a/inst/tcpip.m b/inst/tcpip.m index eec4277..1595a00 100644 --- a/inst/tcpip.m +++ b/inst/tcpip.m @@ -72,7 +72,7 @@ function out = tcpip (varargin) endfunction -%!test +%!xtest %! a = tcpip ("octave.org", 80); %! assert(isa(a, "octave_tcp")); %! fclose(a); diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index b701cb2..4ca11e7 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -97,7 +97,7 @@ Undocumented internal function.\n\ %!shared ip %! ip = resolvehost("www.octave.org", "address"); -%!test +%!xtest %! # test get %! a = tcp (ip, 80); %! assert (__tcp_properties__ (a,"type"), "tcp"); @@ -110,7 +110,7 @@ Undocumented internal function.\n\ %! tcp_close (a); %! assert (__tcp_properties__ (a,"status"), "closed"); -%!test +%!xtest %! # test set %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'name', "mytest"); @@ -118,7 +118,7 @@ Undocumented internal function.\n\ %! fail ("__tcp_properties__ (a,'invalid', 1)", "invalid property name"); %! tcp_close (a); -%!test +%!xtest %! # test flush %! a = tcp(ip, 80); %! __tcp_properties__ (a, 'flush', 0); @@ -132,7 +132,7 @@ Undocumented internal function.\n\ %!error __tcp_properties__ (1) -%!test +%!xtest %! a = tcp (ip, 80); %! fail ("__tcp_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! tcp_close (a); diff --git a/src/tcp/tcp.cc b/src/tcp/tcp.cc index 31819f9..925e3ea 100644 --- a/src/tcp/tcp.cc +++ b/src/tcp/tcp.cc @@ -203,14 +203,14 @@ number of bytes currently available to read (readonly)\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcp')); %! tcp_close (a); -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_close.cc b/src/tcp/tcp_close.cc index 8acba48..785e9a2 100644 --- a/src/tcp/tcp_close.cc +++ b/src/tcp/tcp_close.cc @@ -60,7 +60,7 @@ None\n \ #endif } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! tcp_close (a); diff --git a/src/tcp/tcp_read.cc b/src/tcp/tcp_read.cc index 534a50a..9db8235 100644 --- a/src/tcp/tcp_read.cc +++ b/src/tcp/tcp_read.cc @@ -114,7 +114,7 @@ Read from tcp interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcp/tcp_timeout.cc b/src/tcp/tcp_timeout.cc index e40a2fa..f11902f 100644 --- a/src/tcp/tcp_timeout.cc +++ b/src/tcp/tcp_timeout.cc @@ -82,7 +82,7 @@ If @var{timeout} parameter is omitted, the tcp_timeout() shall return current ti } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80); %! assert(tcp_timeout(a), -1); diff --git a/src/tcp/tcp_write.cc b/src/tcp/tcp_write.cc index 6feeb27..37a314c 100644 --- a/src/tcp/tcp_write.cc +++ b/src/tcp/tcp_write.cc @@ -93,7 +93,7 @@ Upon successful completion, tcp_write() shall return the number of bytes written %!error tcp_write() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcp (addr, 80);; %! # call HTTP HEAD -- cgit v1.2.3 From ea86daaad87165e991180e6bd3e4b25f201d6fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 24 Jul 2022 13:52:59 -0300 Subject: Do not fail when calling resolvehost in standalone system Forwarded: not-needed Last-Update: 2021-11-15 This is necessary when there is no network access at package build time. Gbp-Pq: Name xtest-resolvehost.patch --- src/tcp/__tcp_properties__.cc | 6 +++++- src/tcpclient/__tcpclient_properties__.cc | 14 +++++++++----- src/tcpclient/__tcpclient_read__.cc | 2 +- src/tcpclient/__tcpclient_write__.cc | 2 +- src/tcpclient/tcpclient.cc | 4 ++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tcp/__tcp_properties__.cc b/src/tcp/__tcp_properties__.cc index 4ca11e7..e03f229 100644 --- a/src/tcp/__tcp_properties__.cc +++ b/src/tcp/__tcp_properties__.cc @@ -95,7 +95,11 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch %!xtest %! # test get diff --git a/src/tcpclient/__tcpclient_properties__.cc b/src/tcpclient/__tcpclient_properties__.cc index a9e64aa..624e462 100644 --- a/src/tcpclient/__tcpclient_properties__.cc +++ b/src/tcpclient/__tcpclient_properties__.cc @@ -158,9 +158,13 @@ Undocumented internal function.\n\ } #if 0 %!shared ip -%! ip = resolvehost("www.octave.org", "address"); +%! try +%! ip = resolvehost("www.octave.org", "address"); +%! catch +%! warning ("Network access is neede for running the unit tests."); +%! end_try_catch -%!test +%!xtest %! # test get %! a = tcpclient (ip, 80); %! assert (__tcpclient_properties__ (a,"type"), "tcpclient"); @@ -172,7 +176,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid')", "invalid property name"); %! clear a -%!test +%!xtest %! # test set %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'name', "mytest"); @@ -180,7 +184,7 @@ Undocumented internal function.\n\ %! fail ("__tcpclient_properties__ (a,'invalid', 1)", "invalid property name"); %! clear a -%!test +%!xtest %! # test flush %! a = tcpclient(ip, 80); %! __tcpclient_properties__ (a, 'flush', 0); @@ -194,7 +198,7 @@ Undocumented internal function.\n\ %!error __tcpclient_properties__ (1) -%!test +%!xtest %! a = tcpclient (ip, 80); %! fail ("__tcpclient_properties__ (a, 'name', 'test', 0)", "wrong number of arguments"); %! clear a diff --git a/src/tcpclient/__tcpclient_read__.cc b/src/tcpclient/__tcpclient_read__.cc index f7a868e..7e8bdf0 100644 --- a/src/tcpclient/__tcpclient_read__.cc +++ b/src/tcpclient/__tcpclient_read__.cc @@ -112,7 +112,7 @@ Private function t read from tcpclient interface.\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); diff --git a/src/tcpclient/__tcpclient_write__.cc b/src/tcpclient/__tcpclient_write__.cc index 6f73363..9a9f7df 100644 --- a/src/tcpclient/__tcpclient_write__.cc +++ b/src/tcpclient/__tcpclient_write__.cc @@ -91,7 +91,7 @@ Upon successful completion, __tcpclient_write__() shall return the number of byt %!error __tcpclient_write__() -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80);; %! # call HTTP HEAD diff --git a/src/tcpclient/tcpclient.cc b/src/tcpclient/tcpclient.cc index 7a6f9f5..3457b2a 100644 --- a/src/tcpclient/tcpclient.cc +++ b/src/tcpclient/tcpclient.cc @@ -193,14 +193,14 @@ User data\n \ } #if 0 -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80); %! assert (! isnull (a)); %! assert (isa (a, 'octave_tcpclient')); %! clear a -%!test +%!xtest %! addr = resolvehost ('gnu.org', 'address'); %! a = tcpclient (addr, 80, 'name', 'test', 'timeout', 2.5); %! assert (! isnull (a)); -- cgit v1.2.3