instrument-control-0.7.1/0000755000000000000000000000000014170330734013575 5ustar0000000000000000instrument-control-0.7.1/COPYING0000644000000000000000000001037614170330734014637 0ustar0000000000000000devel/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 instrument-control-0.7.1/DESCRIPTION0000644000000000000000000000074114170330734015305 0ustar0000000000000000Name: instrument-control Version: 0.7.1 Date: 2022-01-13 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+ instrument-control-0.7.1/INDEX0000644000000000000000000000640114170330734014370 0ustar0000000000000000instrument-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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 instrument-control-0.7.1/Makefile0000644000000000000000000002403714170330734015243 0ustar0000000000000000## 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 instrument-control-0.7.1/NEWS0000644000000000000000000001613514170330734014302 0ustar0000000000000000Summary of important user-visible changes for instrument-control 0.7.1 ------------------------------------------------------------------- ** General updates to support Octave 7+ ** Updated common functions fread - set correct size of uint16 fprintf - fix else for multiple args 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, deprecated 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 instrument-control-0.7.1/README.md0000644000000000000000000000250614170330734015057 0ustar0000000000000000Introduction ============ 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 instrument-control-0.7.1/doc/0000755000000000000000000000000014170330734014342 5ustar0000000000000000instrument-control-0.7.1/doc/functions.texi0000644000000000000000000030670314170330734017256 0ustar0000000000000000@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 (Deprecated) @section Serial (Deprecated) @cindex Serial (Deprecated) @c Serial (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) @section TCP (Deprecated) @cindex TCP (Deprecated) @c TCP (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 deprecated. 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 (Deprecated) @section UDP (Deprecated) @cindex UDP (Deprecated) @c UDP (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) @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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 (Deprecated) 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 instrument-control-0.7.1/doc/gpl.texi0000644000000000000000000010433014170330734016020 0ustar0000000000000000@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}. instrument-control-0.7.1/doc/instrument-control.info0000644000000000000000000043260214170330734021114 0ustar0000000000000000This is instrument-control.info, produced by makeinfo version 6.8 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.1.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 deprecated 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 deprecated 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 deprecated 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 (Deprecated):: * Serial Port:: * SPI:: * TCP (Deprecated):: * TCP Client:: * UDP (Deprecated):: * 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 (Deprecated), 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 (Deprecated), Next: Serial Port, Prev: Parallel, Up: Function Reference 3.6 Serial (Deprecated) ======================= 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 (Deprecated), 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 (Deprecated), 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 (Deprecated), Next: TCP Client, Prev: SPI, Up: Function Reference 3.9 TCP (Deprecated) ==================== 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 deprecated. 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 (Deprecated), Prev: TCP (Deprecated), 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 (Deprecated), Next: UDP Port, Prev: TCP Client, Up: Function Reference 3.11 UDP (Deprecated) ===================== 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 (Deprecated), 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 (Deprecated). (line 9) * fclose <4>: SPI. (line 9) * fclose <5>: TCP (Deprecated). (line 9) * fclose <6>: UDP (Deprecated). (line 9) * fclose <7>: USBTMC. (line 9) * fclose <8>: VXI11. (line 9) * flush: Serial Port. (line 34) * flush <1>: TCP (Deprecated). (line 15) * flush <2>: TCP Client. (line 34) * flush <3>: UDP (Deprecated). (line 15) * flush <4>: UDP Port. (line 56) * flushinput: Common Functions. (line 9) * flushinput <1>: Serial (Deprecated). (line 15) * flushinput <2>: TCP (Deprecated). (line 38) * flushinput <3>: UDP (Deprecated). (line 38) * flushoutput: Common Functions. (line 27) * flushoutput <1>: Serial (Deprecated). (line 35) * flushoutput <2>: TCP (Deprecated). (line 58) * flushoutput <3>: UDP (Deprecated). (line 58) * fopen: GPIB. (line 15) * fopen <1>: I2C. (line 15) * fopen <2>: Parallel. (line 15) * fopen <3>: Serial (Deprecated). (line 54) * fopen <4>: SPI. (line 15) * fopen <5>: TCP (Deprecated). (line 77) * fopen <6>: UDP (Deprecated). (line 77) * fopen <7>: USBTMC. (line 20) * fopen <8>: VXI11. (line 15) * fprintf: GPIB. (line 22) * fprintf <1>: Serial (Deprecated). (line 63) * fprintf <2>: Serial Port. (line 57) * fprintf <3>: TCP (Deprecated). (line 86) * fprintf <4>: UDP (Deprecated). (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 (Deprecated). (line 81) * fread <4>: Serial Port. (line 75) * fread <5>: SPI. (line 24) * fread <6>: TCP (Deprecated). (line 104) * fread <7>: UDP (Deprecated). (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 (Deprecated). (line 105) * fwrite <4>: Serial Port. (line 99) * fwrite <5>: SPI. (line 48) * fwrite <6>: TCP (Deprecated). (line 128) * fwrite <7>: UDP (Deprecated). (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 (Deprecated). (line 124) * get <2>: Serial Port. (line 118) * get <3>: SPI. (line 67) * get <4>: TCP (Deprecated). (line 147) * get <5>: TCP Client. (line 57) * get <6>: UDP (Deprecated). (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 (Deprecated). (line 168) * read <3>: TCP Client. (line 78) * read <4>: UDP (Deprecated). (line 167) * read <5>: UDP Port. (line 162) * Requirements: Installing and loading. (line 18) * resolvehost: General. (line 78) * serial: Serial (Deprecated). (line 400) * Serial (Deprecated): Serial (Deprecated). (line 5) * Serial Port: Serial Port. (line 5) * serialbreak: Serial (Deprecated). (line 145) * serialbreak <1>: Serial Port. (line 184) * seriallist: Serial (Deprecated). (line 453) * serialport: Serial Port. (line 322) * serialportlist: Serial Port. (line 391) * set: I2C. (line 89) * set <1>: Serial (Deprecated). (line 166) * set <2>: Serial Port. (line 205) * set <3>: SPI. (line 130) * set <4>: TCP (Deprecated). (line 188) * set <5>: TCP Client. (line 98) * set <6>: UDP (Deprecated). (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 (Deprecated). (line 226) * srl_bytesize: Serial (Deprecated). (line 253) * srl_close: Serial (Deprecated). (line 278) * srl_flush: Serial (Deprecated). (line 297) * srl_parity: Serial (Deprecated). (line 324) * srl_read: Serial (Deprecated). (line 472) * srl_stopbits: Serial (Deprecated). (line 351) * srl_timeout: Serial (Deprecated). (line 374) * srl_write: Serial (Deprecated). (line 491) * tcp: TCP (Deprecated). (line 246) * TCP (Deprecated): TCP (Deprecated). (line 5) * TCP Client: TCP Client. (line 5) * tcpclient: TCP Client. (line 153) * tcpip: TCP (Deprecated). (line 383) * tcp_close: TCP (Deprecated). (line 303) * tcp_read: TCP (Deprecated). (line 320) * tcp_timeout: TCP (Deprecated). (line 340) * tcp_write: TCP (Deprecated). (line 363) * trigger: GPIB. (line 168) * udp: UDP (Deprecated). (line 255) * UDP (Deprecated): UDP (Deprecated). (line 5) * UDP Port: UDP Port. (line 5) * udpport: UDP Port. (line 247) * udp_close: UDP (Deprecated). (line 305) * udp_demo: UDP (Deprecated). (line 322) * udp_read: UDP (Deprecated). (line 330) * udp_timeout: UDP (Deprecated). (line 350) * udp_write: UDP (Deprecated). (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 (Deprecated). (line 226) * write <3>: TCP Client. (line 133) * write <4>: UDP (Deprecated). (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 TCP6806 Node: Basic UDP9183 Node: Function Reference11376 Node: Common Functions11817 Node: General12444 Node: GPIB15212 Node: I2C19795 Node: Parallel24552 Node: Serial (Deprecated)28906 Node: Serial Port41041 Node: SPI50759 Node: TCP (Deprecated)57495 Node: TCP Client66295 Node: UDP (Deprecated)71192 Node: UDP Port79796 Node: USBTMC87003 Node: VXI1189953 Node: Copying92616 Node: Index130130  End Tag Table  Local Variables: coding: utf-8 End: instrument-control-0.7.1/doc/instrument-control.pdf0000644000000000000000000116746114170330734020743 0ustar0000000000000000%PDF-1.5 %ĐÔÅØ 1 0 obj << /Length 587 /Filter /FlateDecode >> stream xÚmTM¢@½ó+z&ÎÁ±?tBL$ñ°ăd4›½*´.‰<øï·_•è̀f’W¯_wƠ«îrđăc;̣ê`GæUOÛV×&³£øç¾öƒ¤Ê®[vïÖæ6ïWÛ7ñÑTÙÖvb¯“uYt/N¼.³ó5·½êÿ¢¥=åS‚> stream xÚmTM¢@½ó+z&ÎÁ±?tBL0ñ°ăd4›½*´.‰<̀¿ß~U¢Îf’W¯_u½ªîvđăc;ZäƠÁ̀«Ÿ¶­®MfGñÏ}í I•]/¶́̃­Ím̃¯¶o⣩²­íÄ0^'ë²è^œx]fçkn{ƠÿEK{*ʇuÄpg6;µ̃$4»¢;»µgZ8, ’ü²M[Tå›P¯RJG¤eWxm½ñ­÷E™7·¢â ̉"/²îÑ7»¸¦‘¼ưj;{Y—ÇÊ‹"1₫t‹m×|‘£o¼irÛåI É‘c¶×º>[T̉›ÏEnn#×Ûû₫bÅø¹‘û̉î«¶BS¬ØEVå¶­÷™möåÉz‘”s…«¹gËüŸµ)gÏR©đ133wÄ xAÄbêí;¬̉aGL6K& 0+‡}&ö"?‘á°(̉¦̉a/ ¡ć,•!£½¥‰î-fö3¤Ù*IĂx {aªùđ”sIC%̉đhSô¢¨7å£Å}­HÏ=ŤIYƒ¹(îƒêjŧ ÿZóéàü4{ÖØSOØá5˜‡áZ ä®ekxvKº·Ǭü÷…Ü@2aÂ> stream xÚmSÁnâ0½ç+¼$z Ø¨"¤€ÄaKU¢Ơ^C<ĐHàDN8đ÷ờV{Hôüæç=üúØS`¾Jñ m}u%Œ̉ßE Y]^/`»w¦¶oâĂƠå:1L·ÙÖVƯ‹omy¾èUÿ­àTÙ ÖĂ₫v¹Êó‘DM^ug{¦…Ç‚° ÉpmUÛ7¡^¥”X[“ÖôÚă{=1î+kܽ¨8 …@iaª²»¯è_^|Ó˜¼¿µ\¶öXq,ÆŸ>ØvîF^‚ñÎp•=‰!9̣̀₫Ú4gÀêBË¥0pôù̃̃‹ ˆñs#P~k@hZ+vQÖÚ¦(ÁöA,åRÄÑf€5ÿĦœq8>K¥Â_¸—X NˆHæĐÔ3$¤Ç˜{<Ư0*¢5cƠ~ÿP÷ơʯÂùƯ5WÂ42^!0^#rq‰xƘœE„3xÎü ñ ªz“)c̉gl1B̀î̉°ơ•?ŸXqû!̣NA‡¨W»A*dư1ùÔ)iȧΰÅç“Đó â9ç’†NVf¤¡–kô¯VäaUJü†ố?%Í5Ø»bÿTW£=ј«±®–¾Œ¿É5ëñ2éfè&p2pj³V^ócH£Mc†VYxLS7˜E=›₫1âj· ¾gÈÈ endstream endobj 6 0 obj << /Length 340 /Filter /FlateDecode >> stream xÚ…‘KOĂ0„ïù>:‡,Y¯_{åUQ!(œ‡ª¤PÑÆ"MáïcÇM…EÖ£qæÛ :>(œÎxrb¹-êQí_Dîg|ÚMq₫ÓVM¾ XÿóÑ*¦WÎ2xNÆÓ¦8¹ôJ¨¬ñF4«„gkW{Ñ<‹Gy»%¡üH¯¶¬ÈyU¢́vC¿ß¶]’‡,Ÿ…|êĂ& MÉZ†8£ ›·ơÁVƒ,ŸyqÑïG´lØ€#?­0m÷l}+VÅ]F6F` \3&dåYa¼t.s_‡Ryù#IËMû‘Nmâ"’ë#|‡Å°à£oÛwË$́JèêÉÀVÙ”ˆŒàµŒcÖ́æáhúÎe˜'ÓXd̀Ë$/ÄîQi«̉…J£íă¿Ôl)_œ‡×.7wºđ̣:̃·¿èÔú˜iªï ÷¯“B endstream endobj 13 0 obj << /Length 622 /Filter /FlateDecode >> stream xÚSËnÛ0¼û+t”HE½|í#r* ßÚ‰–ˆH¢AQ.ú÷]r—~¤Fø îp¹;;;fQ?ƠyT7nó&₫kT?¸ƒƯ₫̃?Ge‘æ5´LyNy­ĂŸªâºVÂÓŒC뫼_+1ơ¶-+€\L}V±]’gy¾M8çñ³fw*â/zÖHd•IR•iƯ4Qª”̉ß]‚4“Z¥ƯËŒÇjqß<y[Ù!`5&LâƠ?CT̀ÂZ¬Q/«¥‹“{,Í‹°jB¤ƠG%̀Ö*:¨%”=]1b|ܲØhW䤺3‡AâmKr'~¸ Æâ)+uÙWeÖVµuAºRcî%oTxûÆHÊ4r‘æä§ïđ.ä‹qÄ™i½§v‘¡ÚđEµR¯6|Ă !}8œƠ•$B“öƒt ¬S„2HÖ¸†ÔÉ+ï ¡÷̣¯s'›fGz{s§îm©4,ê  ¨kØ}^íÓ(jîÚ€ Ú!aÁÎmƒ°ø[;¡0ÊP KXG E0®ê²₫¸@›WŒq#Á@®Ơ†LỗLmܺÚô6ưA×ÀLD¼ä ¿S¸ºxOỊ̈cV0Lr±Ó4è¦1éÊ.€¢]¼)®₫œ.j,£8ï®Áñü!7¶pJbWj$`ÖẢ¾G1÷«èåĂ=1ÏvâA×"^Ä$ĂÿŒx8yInôÿÛÀk[{7_÷› {™â endstream endobj 19 0 obj << /Length 1100 /Filter /FlateDecode >> stream xÚ•VKÛ6¾ï¯Đ­2ÑâK"{KÓn¢h‹Â=9h%Ú&j‹†Dí6ÿ¾C¤•¼̃l &9ü4ÏoH̉$‡MJ–”Åˤ>ßåQÚœüơñ8!9‘‚Ăü›°L2qÙBëO»»í½b „‹‚%»}4Ë ’K‘́äsú³í}go]»ù²ûu{/eBs¢sM>O2ª e ợ™Qè‚Ä)@#äăïßRF 0:‚₫¨}µa*} f“qY¦ŸZpe8›vĂÊÔY‘~¯á;wBĐn£xê6Ưé;Âl?ÔK“T1¢ËÙ±}g̀MÏ(Qy1¡z·÷ÁäSø«:C6™¤2½vƒ‚èÅ5¥àE+Ε÷¦Ă¹Û££ó—dL B©‚́rB%EÛCoº₫‡M&r½mÜ"4O»¡ƯĐô,˜Nkw æ¿n”˜D V0ƒ7£¬÷CóŒQỉ{¬‚¢ƒAµUÛ {¾tnY—hü8Ân¤¦(p"gSµ±‘6!0ŒË«P¨\¦w_ĂàZƒ̉˜8÷˜à\Ä€ƒ22BFÑïf —3¼3« ¬?*ű6¯l‹†j×66¿‡h—¯0œkA+ßæx®W8Ë.XN$åë²/ˆ¯"ñ•¼"¾Â¤‰… {œ¶ÎCu¹VéÑÍ ¹.!×qØÙB9Ăä2<œls`¤$p]ëôS4 °,°9­³‡ćMÓ ̣fÔÙ™UáÇа70ׄºÔ1Ó(‰å€ÑúQĐ,¢è3Ka{£Ó·ồ&ÓÛC‹¾åH MÛˆ  R© W°CÓnTơdO§[Q×g¤ư\ơƠyÍ ÷È_˜`ª`2Sù ’g¡Ö OaÍ2Œ^`Cr)÷.©ídñ™Ù7:²®BöO"« .önˆn l‘¿ÙºG7ÈüdZÓU'ÔúçD=°ô›­¡Ff2ƒ†Yíα6=.Ÿ,¤ä1N|ŸKêƠK¼¹êÅØ´¼àD ½æÄºA9¿nP`͹˜¢ ¢SïÆÙå‚©¯"û@bă|÷Ën¾ÔYQN.pỦø€’œä₫(‹Oµdù&˜¾Ï â›à:+k31¾÷“À¢ÑÁ÷8|₫0¶=|y‡^ªp—„]Y\Ge!9§«(^ÇLè7|¾V}&c½„D´ ”ëñå2=x§]<$Û“«”T8̀Wj\…K;Œ·G™ L¼E8I8/_#ăÓ«ºưØ>ßÁîbA0ÇP"Í ù —“©zƒGÛ[ÿ¢ï?©)9ûß<¾Ï °&Ū&Wfđ́ô₫̣ăvë ôG3¨ä¨oÙP½ºÚ́]w0¤5~k§Nôe! ÛưQ2"$TđöUo1kBg ø­n¸Rú̀¬`ú?D,í| endstream endobj 75 0 obj << /Length 2730 /Filter /FlateDecode >> stream xÚíMs7†ï₫́?l¶»Ä@-e[ê 2j/¯â@ê±S5 &c Æ]{~¤$¬ üøÚÑ·Ÿ.¥º˜/Wî^]¿­Ưöv¾èvӫ↘†>ÙUqE+×X'–r¢Œ†‘&“4€`rh@]{„M!Âç±P(̣“».₫©Û.ç“ËbcoY]+Aă4UM4€A3’nL4¨kÚP;A3Ö¸!mË5a–†EÙTS¼Z®³¯ư–WT93ÑÆ̀H¸If@09̀ ®3T#3lÄ̀»~®µÙî‰FZ0çœSœzÊùˆ0> Hy’L¨k?kQ-óxˆÇ±ëWï¦àІ0ZóJÍ+ÓÜ8Y•s `Ü@ơ¦¹ÁäpƒºöyE˜ÖN8a.–àẺH]oæUX¾ñª*æ@¸‰7É &ƒÜuàF+»|Ø0€Í!ß¼Z-]»a¢Ûđ)¯gª̣ÿr˜ÓL9á|Œ L‘D"F’Cæ×MÀ„²K’P“ç_?7™O % åuV«`G¬ z*g%œ±D+“¬ÄHrXÁü†ä!ÿ–0éJ@b']‚Ë IÍG(2NUå̀D4P¼ij@09Ø ®7\Z 7 psÈ2R«÷[΃ù!N?å„D!P¦iB@09„¹~ÔF%EŒ ‹¡¡êu¿ïa½Ø/7ë¡…ê}wÛm»ơ¢›îŸŔĐ sNưSÿÔî;{«€¤·j¤ê­‚ÁdôV»\đ¶!‚ụ́o˜Ô¼ÚÜßÔgÇç×—†{=&{BD£ë0ưµ¶²z‘ÁÀ2´¨Sc0 &c Æ]ûY ×0Å„_*v–ë© ¬µƠ³^özí”Ó `t@‰¦éÁäĐºt(A(t°1›‡} Ÿ®5Ó3«™z¹” `@@U¦Áäºö“&»̣m•Ÿ¶̃tën›è…â„Yû9*Tùµ!¯²rŒ¢ #(æ4F ˜ŒP×!¯pMLÄ(Lºú©ÛƯêăd÷‡¶€ÖÅÆ9ÁdO9á|  Ñ41’80¿ &ˆ’m„ƒà8|æÇr}»™\”h¢¯ˆœă}xƯ”S `X@y$ ˜0P× Jí¯Èđ[8¶Ưn³úÔ“Ñ}Ǿö 2¨Đơ®ÜWÍ^ §›r2¢Œ (Ï4 ˜2P×nYÂZC¸4 Å›wo_Ñ¡æÄ0Q³DE·tæWL0€5̉u›" “AîÚçf$aH…%Ê¿7—W6Ñ,öó>ß IÇGöGpGµ Zóƒ!U…_~kf7ö‡ßÛ?‹ÍDŸG̃ÏlÓưŒm5ûéÅ“iCŒưc"ºû¸üư›ÛÅj³ë„+Q;åŸg»¿ĐåpE\POi¸@09p¡®\Ó\¬ .k†µ§ F4Àµùxˆ¥['Ó×»?OÛC 0w±Ë‹0À ¦̉€`rC]À¤±ï©/L¶vƠDOŒh́ăv9ôÜß&Ú(©fµp₫DĂM¡å.s9ZцTS-LZ¨ë€–DKÑehY3m{²`@YÛn~3É#ºVĐŸë´Đ]çr´¢ -(§4Z ˜´P×-ΈjZ² -kfød±/F 4 µ[̀×ÓùJ̃ÖO{¦l¹ ]ÎV4€±ơ”f “Ăê:°E["üƒBz¶T[ÖŒ2§É[0¢®ÏÛå~º¡ˆªÍvOs Dq.í_oο¦p:r3|j“ä D“Ăê;đÔ(Âỷ§Åj{Ó}Z.&u¬­yƯÖrRl8ᔳ `l@}"l€hrØ@}{6hË •€ ăØèGùÄđ.”ªĂ{­×M"ăơTŒ 0€ 3’mM2¸ï€Lÿ̀´†EdÚ#d¦c–i-ô§±áùpÅÓ1ƠÅ"H̃XbœÓÖvVm§r £ C(DCM†¨ï€¡‚Û2û»¾ Îa¿S(ûªíO}‡ưî=6!UÈcŒ°zûékơâO•nIơü)l_è±›?ăOåíIơü¡¾ư}ỢGóø³çµ\„?Â~yßm¦78‰₫ï¬j&|¾ĂH 3'€r̀¢ 3¨33Mf¨ï€™/¼…EYeö4mNCˆ Yơcv’ÛÔ½SgRq’(Ç.œQtG“M¡ä0‡9È1}¸?™ó-»¡Ïh³J}–º¨ ÔF‹G´8=•ă `¼@Ù"À€hrˆA}dl L@d|«Å~»¼»ë¶“vJÚúákuµÔSH4€E¢Éơív}ôœ4mØơááxË^M®Wø<¼êö ‡XNvå`EXPƯX °Pß>óm íé¢pï‡1„“t§Ăx–llüÚÚ¬ª}÷¹Üe.+pµ”Æ „’AêØCƠSѨÊö|hI~’tÏ*tÇе½ïùµ÷9Í»K] V< ê) %,Ô±KQ¢„`•íơP½±“€ă9€•º‹e§¤-këbí9·ú¹‹]ŒV<A *":¡> stream xÚíƯKs¹à»ÖA0̃œR©Í¦jO‰­Ûz´D;¬ÈCQÙJ~}rôȃ6m2DmƠj­åt·Œ₫4/ †-¨ÿ‡- _+ˆfqûùƯwûiqø·yņÏ]û^ƒO₫éæƠ›Ÿ•Z0Julqóq¡˜#̉ïænñëëơúê·›_^ưù&ER\%EeÚøé¯äf”kíÂ(Gr "‰¼ºf”̉×|¼ºæöơínyå¿ü+ük+ûgJÇŒ$ÆøÚ4%Ló́×ßèâÎÿÏ_”H³ø}ÿÉÏ A¸ÿ]Ü/̃½úÛdEÆKƯ¸¢5¿}óñ÷íz·Ïưæg-à&̉æÿéá³đ•ksø¢GüfÅGüæ™eøVå¾lg&‰2shg¢üÿ#~đ}ñ}_¿3jđaûk`×8;E/âƠÔàBs'\R{:ăRm¸¤!”±YpÁ®O«Ư”,!‰Đ®Ë:ĂrK܆‘oç–`Ü`ƒ!Ü@55ÜĐ܉›DsÀM·qóa¬‡¬(p{*pÄ8ѹ!è·aäÛ¹å7Ø`7PM 74wâÆ •¹™›oôÉ£5Cœe½É»É£Ă¡¹Úưä˜ØĂLư€jjü ¹“jˆà2û±c?/öN̉Á[)åÚ;)A„ÿÖ¨€åƯƯvJ-÷G‚V^†ÚKÿ%S²8ôI»Å³Û±ª©±ˆæµ“Äÿe‹®ÆbØJ̉Y, ¸½|Z0Ê;Æ Æ¥#€`ơ#“%Œ° Œxî„Ñ2B¹ÈE5ªĂy[ØŒ+{œÆĂyÛ¨‚íjy7‰Q́ẉưxöÿùJIáĐ í sL!́CD!¨¦F!;)Ô†XĂBV¥P[ïỜ¢VP¼ à*̃|í¤ïÆÎ›áĐ!í sŒ!lD„!¨¦†!Ûjâ¤OXñ¤0̃@øk¸†¹Ü.ïïW÷S(4'Z÷}S?Ø­¹Ö{¬]Q€)‚­Œ(ƠÔ(Bs§™dD–Ötk „±TÏqk`TÑf üæcñÔ/ü²pưÜ d()´]Q€)‚}ƒ(ƠÔ(Bs'EÜ™÷E„·!̣Q´R³ eC›}9«‡IG–4_AéG‹ßÑaHÛ¥í1D oC¹”BXâ$ˆy5& m‚|Eå,‚@AYPé’‡ö¥—rÉă<¯†³]OÚÓz†©¢\J,q̉C9àe>m“C¡æá+Ê~+ #œ™¾ûùJr†‘l§“`v`Ă x@55zĐÜ‘²–8m3Ÿx5aƒ\I0áZ¡î{A Bbû4 !£.- ƠTÁs'!FË€8ƒp³™º ®tk¿‘&T7÷]y¿á‡‚ùËwưq#µư(́‚ób£´[̀0‹°‹ ‹hîdq œ+™‹~#Gç±óßî¶“{Gfˆd²_•»¼rK0‡®i‡™`0as2]„ ª©‰æN0¥#é ÓÖÀôÅf óß-ư9ßÔ>’.M‡yAôK"‡vi™`"aW""A55"ÑÜI¤ĐDh ̉ƠˆôéY<ẤÁăƯzr&±ÿï“/í¤qhv}9¦ö ¢TS£ÍôqO…)po™bü”ÿˆfû­äq7Á”!Ê™q₫§Ưṛ ³đD‚îö.ù”qh“v‰9&v#3E‰ ‰hîa®”̣ߢ:Mâ×ñ­¶ëåưƠµâơ{ªèO«Ívu»Ü­îüŸØäYsÄ)ѹœo†‚¡EÚä؉PM 4wÜIç5°4{^7Nu’Îø£;;ÇM²QEO{ÈD'¿WsÜơæ<¦àÆÁm ¢F=T«©…çN¢¬ FQmóBçæ+D½§L=?ư}ư°y<´Œ0Ö¿>‰ƯP¿v49†¶ ‚TSƒÍĐJ4ăMÛT§ÆJ3 XÑÍăó®¤F{) áœ́ÜŒ8rí\rŒ l„ ¨¦† ;qñ‡=R³̀¥mjS£Ư,ÔGÅ£6tj­²ÄŸPu+gr«*p»ªSûQª©Q…æNª¤$‚Um °…0JΣ VUm¶ë‡PÂîcáY®~éîôï3Å‘mç”`œ`!œ@55œĐ܉“đç:kj[_-Dn–ç?`ASiîºÿ…Ai$̣l®+†¶]SÚĂú‡Ù¢¥\J %,q’Äü±u™’i£äĂp9ËLöQEÑRq»fGL¯è{ªïvû5j;£s›ª©‘„æN”¨$VJ¶U₫obJ°¢Ra]éb¥́Îóˆoçv\9† ¶‚ TSƒ Íq Lj¡6ărM¸B'ŸF ¸_>ø#¿L^Ăă~KÛüNáÊw¾f3 bfÔ%̀•̀Àj*̀๓ß©Jp–₫oh,%œ›}ă›Ën%áZKJh¦÷H¨æ•cú₫âMî‰ÜÎ*ÀXÁ>BXjjX¡¹+­ˆ¤kcåăh9+XRduxPdœÛç%”Û9rszI_æ₫°|¾Û. /I WvL¿~ø½wtĂø´‹̀0‘° 8-ƠÔˆDs'‘®Àơ@ÆÛDú8̉±YDÂ’ªDŸ;‰„¹?„Ÿùß»ƠÓú?“*ÅáƠO}7ûCV<‹CƠ3ÀpÂ@p‚jjp¢¹NßaŒ*€S´áôq„œÅ&¬¨ÊæÑ©M˜[][‹~‡à”®_Æk‡`Pa PA55PÑÜ ªÿ¸SªlƒÊư¦ÖÍ"–T%ơøÜ‰*̀=LÏêXÏë0tíXs +́ÎXA55XÑÜ + ×%ÀªÚ°2A¨˜+,© ëñ¹V˜{³Ü®wûẴÉ^?öFö̃“87†­j€A…Ư@ƠÔ@EsG¨Ü9¢| F7A qB¼ Jª:Cîuœ{÷¸ù°̃=ÎKë¯{úÖ 0ă05Ă˜£n(Ă„ƠTÀÄs'˜VûŸÂ4m0}#̀,0aIU0Ï`ÂÜ»ơçƠăôsáT¢í₫ ËEqÚYæKØ ¼ø2OXM K4wbiÂ{ÈÀă:,N£9€(¬̀û}ơKÜß•œ MÔî$ÀœÀ^Eœ€jjœ ¹“íw?‰OÇv<9†¶ ‚TSƒÍđhK˜ÔOÛ"S!Œ°l<°¢/đ”.ă™¾(Û©Íư‹Ù®'ÀôÀ~Aô€jjô ¹“%‰s@OÛbRL)ÂÅ> stream xÚµZQ· ~ß_¡Çô¡ZQ¤(10$1\hÀv¶Æ=¸—­kÔ½5Îç"ù÷ư4̉ƯÈÎâôF/;;³ï£(R¤ÈM.8q–EGJÈE ă˜%' ¿©K¹¸È.Kt18 ™±²8 1»:Zăm¼¥\_+¸/i¸7GF́8D4`c(çx`qQ:NUàX9/s…Ü  ©àA!@•â*¤vªDå €×W²àw@Å=(-gW‹N ¯†́ 9F—ȉ€4á§„LMTơ@•Kp ª)–\‚náC JH¯@˜dx!b’̀ºM©˜S@å "¤ĂAC1IM ÅW(Î)^ăđ‚:Å« «“ñ»‚§B*@ª5ăÅ\%2ư)n\†D:É@ràÎÚ0Œ+̉0Π8̀½<4vG‰+U˜[.@•”) ¬eÉX 3@XMX́Ë £À /öT(’°˜,6)up°•U¦Lu0́¨.,ÈdR[…¢ˆêc‚éfXÈFƠPƒÔ_`MÀ«·à¨TóM1é¨"•\QrÅ,eA Å*L™â‚„ Xߨ?T$¨`ó@Â:P¬o•PßHơ}̉Ă“'‡ă˟ߟÜñ‡×oN‡ă÷ç›»ÓÍƯ§đªç‡ăóÓ‡óÇÛëÓ¸Ø̣àϧß¾₫îü“{đ ỴëY„|±«Pnñ:„]FóÍBđ  îÉw|ưåú ¾ÂúỆƒ?ܯ_œîÜ+Èñô™;¾<ưtç®îß¿( T÷™„Pđ">Èu|Ă&y”Œö óÿ!ăñÛ››3à^ƠƯ¬CËêÔƯ¬^>“a|8¾øø»å₫Ooo₫}8~w¾ưñtÛèÂUéS‰ª>cŸS¤nAÙ́kÙ‡Ä÷í¢•îø‡ó˳;>u_}~ÿóÛ›7¿«J¹D|™I$y®;‡©çºIÅäv8 ËưƠg»•ø/ÏÿØ>¾ú×ƯƯû¯ÇóơƯëÿ|Sé?Ï·oN₫ætw|{óáîöă ·ß_cnÏï¿QFxZ*́ {^̀ÑW?ÂÆVïç‹÷Ô½¢nwưÛß—­O Æàn>¾{wơe„¯†tÿa'>ÆzsúÜz3?Êzc³̃Ø­·É›́qq•[—K›7ù¹Ù97_ä†Â … 7n(̉P¤¡HC‘†" E4i(̉P¤¡¤†’Jj(©¡¤†’Jj(©¡¤†’6m(ÚP´¡hCц¢ E6µÇú8R°i!kZƠ‡ÆaÚˆ}œ6=çË(chƯ;{N™ÓTÊ$^°1>P*y3›J »y˜¥_dî,cñ5Ø?Pṛjy*%BDI+cŒ¸êÆn°H.}@¾to°Éz½L÷™$&Hơ0Ë”Ai*eÂîi¥BÏy*£´`ÿÀ(†$`*#̀ƠluÊÄê“ÚTJJ0–Đe§ä(C„®û@¢=ëLJœß@µî‚́Êl.%\‚meDÂdz™QvbTöq5WÉj¾·̉NŒé̃n;eʸΥ„K—•Rjæ)”}¤̃%ÑĂ₫*„{º<˼Ï,Ù¼pơJ¶́q$ŸJ‰œƒá‚(Âe*å’s¬Œ™¼–¹“„Á“LÅ'KYSÁG¸đN¥Œâ5 ”}ät‘²́DIäS(Éđ|*e´â9­;D2º¼ØN”È´deŒ8p±©Œ8Ụ̈ºÄ°’s“zÊëJFÍx^¦R ×ăÎJ™+7¼r/ÊhÈ×̣J”às™CIđÆZë¦VCz ŒÏ7Na'Î¥j4Ø1¦mS9Éh©=p¨vë0»gF|,+'$"y2§Ï«j)×uK™°Ë¾IZOÔsMˆG½8pJ=Rop̉Nœ±VÊÖ X¼å4—³–v÷¤]³̀å pæ¤8•³@µëÙ ç 6•0Gtµ„PỤ̂̀‘Ô­Œµ>¿„ñ©{•å7Ô–‡‚̣Pf®Ư­|£̣́ăÚ7̣Ë₫Đ£Ê˹UZs«´æVi-MỂʨֆXbmˆµb¬5Y+ÆZ+ÆZ›°5k(µ_خԯ±_¹_¥_{»&h¿æ~-ưÚñ¨ăQÇ£G¯w¡è¾ưÓû?D¯wˆ:^́x½@½@½aTíÚñzEzIzMzQzUzYz]zazezizmzqzu₫j§ĂI|ợ¬Ø³Ă†›ÇÜñ «×å„=;•¹œ`êg5ư0™¤äµ‰”Îg½\ú$̃‰3dÏCi'ă¹MeT_ÿkñÀˆH•eƒSvâ,ˆ†cK¢ ÚdNœnJ₫´óB[V»'<#1XÇó­¦Ä^œ\{-2ô^̀çÆơnœ±6[†ơdơâ\Nªí–A·µœ6¼3í”nÎèC=[)àĐ5™³(ÖsÍVëß¶*¯»qfÆzêÊYx³ôº§†Ú>MÁGÙàÔ8»íØiB, çrâ„?é5±7¡¹œ‘zßđ¾ÛTu»qÊÊ;qÖHƃƯR§Nå”ËÊ`C!ãsç)5–± 'ÂzN欱lh=K.>o4€v㬱Œ‡¦“bÏß̣Ͻ8‘å¥2p¦èÅ&sÆâe(Ä cÏ—=¡́ÄI8Đ•5®HÄaƯh.gˆ†â#«ŸËÉÈól(̃±™ß¨ªÓNµØÚ́*C{ Ñ4ódJdyÇnĂ/gq§Ú#ËKCíM…'s"Ëă¡vLj¦që{q"Ë‹CíMi£´w*21²¼0tçB+s9cưÛBÔ¡å…£±·'²¼<œw#¢©–ËQ%îtÆđ ₫WÛ^¶QÂÛ¾}̉÷ÊyĂnw:eGøFH'¢©nÔÖwădd–Cß‹¼ä_cüĐÆ endstream endobj 218 0 obj << /Length 3143 /Filter /FlateDecode >> stream xÚíƯKsܸà»Å¥ƒ`¼9%Ùͦ²§Í®ö´̃ƒK;SeK,gÿ~€ 4vÆĐñŒ„r•̣°»-ôg’ A ?ÄÆÉóyå6Wï_đưWïßnóóß_ˆésñƒà“½|ṇ̃c6‚³ÀƒØ\¾Ùa™6%̃åơæ·³Ưnw₫ûå/₫v™Ci˜Ñª1ïüéÏ$\0ïưÆ™À‚œ’+æ˜Pç‚s~öçÛó éÏ®^ŸÇ_₫“~ÚÎ¥ư;ç3·w–3aeÊöÛï|sỵ̈Ç gÚm₫Ø̣ưF1éTüƯ»Í//₫¹X’×LZ]—ôa{¿{ưîn_ÊíưĂË?îwû2^₫`ÜÚYæ„‹ñ÷›ư)₫#¬{üÅVZübĂGüâñ;$ç*4³ªŒ`êTfâß1âOBî[¶₫JƠ»Óö À"œ:Í~Ä¥GƯ€jZܹ³ûÍYàFOn>騥^ơ–ñøÿĂèƠ'™C1uL?€B“@ªiAAæÎ(”bVBfÅ»Ư‡Eñ³̀ễÿÅ—ăÉ€!˜:¤A @!€(TÓ‚€̀ÿS:¦–é¨Ç̀üà—Ÿ₫±ÔđZ1cÂóØ kdÀ`Mm׫ `Áî&`jZ`‘¹ó̃…;¦¤Î²˜ø²3§ă.LíĂ$s‡œ©8Ï|ünV}¸Û½|sơîöĂâ鉟ä₫hwl:¹×ƹW @á‚íDàƠ´à"sϸlĐ, )¸d®FóUpUíqƯ>?no`Z†́$ÍcƯ  €U-…ƒƠ4£sg`^0.U¦ú€Å0̉øU€ÁöÀî·¯¯‘£Ô`ÇtÅIdÀ„MƒƯ/¬ „Á"„jZ„‘¹³0ë˜w²Ó}Âl<²äna°¢½0túZÇ=.—ăDđ4w_Ó8÷ă*(\Uƒs¨¦™;ă2Q‡¸L®&˜upÁ®·ÛÅ9E¥™ cå÷À·iäû¹•·ªåqn ndî̀M fœ(Ül·Æs» 7XQâ†,J&ƒ̃N"&ĺ~a%%¬êr Ơ´#sga2 ‚ư™ë£XcV J¾> »³X¬Tcă3`ؾßZ̃¢Û—VJiF%Î΄aå₫"Ÿ/ˆ}¡³Åp½3PPr†Ÿ’i&„̉NzGö8Øư¶̣ö”-Øâ¸­RJ‹-*q¶ÅelÑPp…>\1Œ2ëà‚e]¹¹₫9Z œ¹1ïñƠƒa<¦áê÷QP@ª>•¨PM 2÷lÄøÈÂzpƠ˜Ï÷$Ưí–:̉(&¬³Ư#µc™Ûª[@È©»•«iCçÎrœa^@9¢–óÉ̃ÄhæSÉÎ2n»ÜĽ‰« @ï¬)†×'S8uH¿Â€RXIP¨BPM‹B2wVh%³œ@ Ù¤0nø* aؤŸTLk=ΕÜ3¼ơpn~„%…°‚€#Ơ´ $sg„:0#,@¨ÆÍœk „ 3ñ%­wÏ?K…S‡ô+,(…•\!¨¦E!™;+T6êA…ºIaǛ®a¦ÿܼ†‹%›1M¬0DÓ÷#*(DU#ăˆ@5-ˆÈÜỌ́Ô¤ÈËSæ ĂËï~:¿PJ½â†¿½»ß^½~Ø^Ç?‰ÅuZÂ0çʶ;ùr1S›ôC((U7j¨¦™;ïMâ׸Íw¼‡Îå$)Œ «Üñ^UôpuG-'‰;?“¼à;s?®€ÂU58 TÓ‚‹̀=ẳ!în„*¸ú–“èÖ¯r·{UQÂơ óñĂ¿+¿ü¹Üđ₫T¯üÎăƯ  Ơ"ƒƠ4 £sgd^1g²¾%%)Lë ƒd»›»Èỉ˜¼?Ê©ơy(ûư””Ÿª‡q? ?dî́Çqf…,~úŒ¤0^¯rO{Uđsûñw̉y†#:w±_N @É©º—ªi‘CæÎrŒcÚ"§o5H cĂ*·§WíÏèƠÂ~,Ç?ÙåVóX÷+(`U“¨¦™;‹§ J`}ë?R£×+Ú»»ßƯ¤üoo£’AJ3¡ÖT ZđƒÜ=k%3cjü2`öƒÚÏh̃œBTúF£¯*u´"²f>’3§! Ư(Æ ^¯–´@»¾äøO¤ˆ¾ÊË4”ưpJ́¨¦…™;J/—2}€b¯V¹“¼*iró«,¸ñDç#̃ MăÚ¯© 4Áö!4jZ4‘¹gM"½M^CM¶KScư*ª’4¡}œ<êg3?Çó¡y,»„ ªe4ú~(XMƒ :w”^/‰Ö½»8Ư,˜Oqxwé̀½ÓÏ£ xÀ%x€jZx¹§k1"½ê]ç{¼óʤ_¿ÿ²§!KÁo ^SÏA6b,Ñ;¡ËûóÈö{*(O°O Odî́)½r]à©ï*Đ’q¿ 'XQâD=ùØ1§Æë8Ol9̃<Âư¬Jl$‚¨¦…™;³J/Z°ê»´“âVqK®đ‡KfÆÑ£˜†°N @ÁBÀƠ´À!sg8éÍéÂ黤óøÊ—uàÀ’ü)DZgÇnéÛ® ˜‡­K @aƯ¡Ñ—#ÁjZ°¹3–ô&ô –¾Ë7)NZ°X̉₫dˆ|°±û™!åDæØ¦Ñí7UP¦`¦@5-¦Èܳ)˜Ô껆ĂhçÖ Úƒú̀ƒŒ-SfL1ưưĐÓ°vK*Û`ïà@) ŒÈij¢ôRơ¹.E1Œ’«(‚ía7âÎ|¯x9•)ºi\»•í F°ypF ”Fdâ™Qz+º€‘ïbdă¶n•ơ° =#ü)Ň> stream xÚí]Sä6†ïù}Ù\ ôư±W›́n¦’JR“„ÙÚªl.ồv³ ̀̀ÏÏq·-ëD#œĐ€*hŒ}ÎKë}Z¶td‹‡/±prá¼b^¹ÅÙåßnƯ¼[́^üøê@ôûÁGhÏ/O¿2f!8 <ˆÅÉÛ…–9Ø4́ur¾øy¹₫pøËÉ7ÿ:‰‘Œ4̀hU˜vØûr .˜÷~áL`Aö¹‚…Ă#Á9_₫ưúđHúåÙíé!üøĐ}[ ̉₫ó Ï™„ăåLXÙeûù¾8‡?~³àL»ÅÇí— Å¤SđêbñÓÁ“’¼f̉걤»ó÷ÇïV·]âă¯¬ÂûkÁ”̣q»ăß@¶u»vôÛ䯂]¸±eØn¼of¡™U©‘;33c<À7!·®oÙ»?₫˜Dkœfk­³h!5%h‘¹#Zđv¡%øg²e˜ơđy£ăB<Œ­ÀœcM[›Ơéù$\Ú@WÂơç»ơÅ•éo×zœR 'l'¤¦'2wÄI)få'Q‡̣vœ°¦§›é®JyÆ•y]ƠÓE3ÇVßÈơl¥[ØKÚdÙBjJØ"sG¶dçƒÙ’ulA 7ZXR‡ÖÇÍúv5—”¡Áµï§|}‹Ös”Paă!5%‘¹#GÜ1%5æHơ…§̀k!¾iæ}r”ôª§$ (ÁN%(AjJ(!s”Ø ™p#Jô˜’{ @Âáü°;NĂÿ₫̃ÅÈ'ÇÎ.®o&{©á­¶í"è™}ÀdÈÛ́»7¿̃́ñxẾ¨… ³')%f§G³sđ·Èí²ÎíG™yÜ%v?9ôj¹Ú\®¯No¯7“×ö¶çz r.ïßôz›§”ÏqÛjŸ5:RSât2÷`uă= Ö#««*«˜äj«$¬>7Ío@ậ“sÀ™`·Qn†¥¡U«YB–FæÉ³„Ơ°Dç,9Ă¼À,é:–œeǛR>’4béíû®¿X_J·¼};Ũ¢ƠŚÅ(óĐơô¤=Ø.=HM =dîH•̀Z|‰aêè8ÏC–4¦gô¬ºnhzÈqæ¬l£‘!‡Pߘơ¥BØ3BHM BdîˆpjoB¶!ˆăŒ˜!,iŒĐÇÍ bv@¿oǿ>}CÖă“Pø`¿èÅ©)Á‡̀ñQ–)‹ñquø@; +à"L¶S¶ÇÏ£¨oÑzR"l‚"¤¦„"2w¤H‚¿…Aù: 6³`„0Ê•đXصÉ}FèÛ² €[Æđ,@HM @dîlăV#€êÖ‘wqd³„%ʬ̉³|»TªƠÀímGÔ·h=G)Å6ÁRS™{àHË‚PxβnѸ íçX7̉4‰¼Zoô×fÈp34`57(ÁÍÈ'yn°nèÜ‘¯˜³#nDªC‹,1]%A3ê³́WrDôv©'" ˆÀ®4"KRSB™»/ÓÛÏßT'6̀¾ùéË“ï₫1Ég^µëđ¶5º··P=$) vª‘YHHÈܱÛ0i›Ê—Ue‰XdžYÆÏF’în~½½<;~›]¢jSÜ7h÷¯ÚlhÇzzRl‚¤¦„2w¤Gk¦¦§®ä¬‹cô<ô`I=×»ó¿ƠU† SMù´ê5‡¶¬'( –!BjJ"sG‚T· TWÈÖ…Qa–qg¬hà‡qV^µÂµưqî[±œx<² ÁM’R‚ •8R#ºû„M]ÍZGêYJG’n²‹Ñ\ĩ»¾ë‘I(f°OhjÈÜ®™7›xó­a'j˜o'G/yöpM=)6§QY00ÈÜ*æ¸G`Øßq¯éªá¥;2è® €÷Ï˱ˆü-©ºú‚¶æé¨dh\PM @Đ62[6¬¦€6:w¤Íùí=m®”68̉9 mXDö¦8’ƠnCơ|aëMP[ @Á†½FÀ†Ô”ÀFæ°YĂ4ǰùRØàH«ç ‹Èß¡£» xÊ~~åCó×c–P˜a—˜!5%˜‘¹ûÉVe$“&ă Ăÿ₫Ï×BLœIæk=K㵤›êƯUÏO @ñƒMl²wÀjJø!sÇnJ&xª¿Ö•ó°]5Ë€̃HчOk!ˆYXăà¿háû#7GRߨơ$¥IØ;IHM IdîH́ &©nNVÁé˜đ³b$ơ(‘S²æ!·ÿmäüeOt¶§€Â û‡À ©)Á‰̀qê–qpª›¡UpåÅƠ<8aI=N¹ ç§{<\ø̣Î3s$ơmZOR @‘„­C„Ô”DæH’!0k"©n̉¶‹ÓÅ›¤‘¤¤́đD[¦ºçUCkV3„ L“g«)`ˆỊ̂Ưc1CĂ îÖ½™mm³m«êüÛ{¨“€Â[•À©)Á„̀1q)#&ö>&÷ïJm™z{ ñ»ù»ƒ×JŒ5ä§sÍ>/’kÄÎsSêÁ ơÈ¥rØr&ûL/¬¦92wDÎÂÙ9Wˆ¨•9¬˜Ó•¶=èä…<Ók°D=y)EvARSB™;’×=Ü`̣|!yp ôf̣°j‚wŸŸ)̃z»™z»̃ ờ¥sØssHM s÷r{¹èÆü4tÛ;¼-¤°, Kz¿èV–+±\]¯?Á+g–_lá3ËWß¿ÙmxµºZmN/v¿¼¾ûơb}¶{ưíúlu5œ îq"ÅárĐÍ:p÷' ^È C|K>»ÁûăP€‰7ư~]ƒO> stream xÚÅZ]‹\¹}ï_¡Ḉ‹Zª© ̀ÂnŒó’€Yû!‰ñƒă–%ËL°Ç°ù÷9ê®™{'LĂ ‘&ĐMƯ{[÷©T’J:]©¥’*ơTkƒµD\a=±àK’†{<Ó2L©9Ăr²â°’œß"ơP/Uoö h¶ñ•Te|w@ÅïTQ¦ÂïÁ”D4¡"ƒ±q"q>Ô&‰ZÁëMuXk‰ oÔ,¤Í—À†úWCaÔ€¹ p¯h¡0~fỚœ¸)j—Ä½ÂØFU{KRÊ(Ü“œÓ- ¡ơµ{6¸FP©j5‰â®ÁYÂÆI¬Xâ4 k̉2`-)ÚŒ‹”ú(lIÙlT ́%i#<ñáơá?ü¬¦x¾WïåP]œ¯»¦F£ª n<ªê=5U…¯›ªº§Ö†ÿP®uT•JMÍđÁû½T8»pêè°ÁYđîx¢©³" JK]úx½§®>^·Ô{¯{ꆪR-©;ªJµ"2P;ơLE¬ƠUOƨ/¡–'¢ ~êüd.ăB“—ÑçˆÎ&€:·$Î@8”ä¨#’7DƯ¨®w—prë#d˜¸Âň̀f̉ˆç2bF¤æQ̀FÜb|kÑá$…3KÔ@,Ưå@ wG# M«€AÛGÔ:<¥à¨4\5‚¡?Pƈ’á,h•܆+©ä6À/Yá"ËLr?¤W¯̉ñ]:₫éæưM:¾N ₫.}ÿưŸÿ‘³H6Œ«{Ϊ¹ÛRJ ‰ÜiGYϧ”I”Ư²ö{F Ó,Ư×R6ÍR·ÎÄ|„δµœJ™Ú³q®—zS'q²g ƒSK.Ô×r‚ËÛ®?¹!ˆÛZÎJsáÆIŒ(¾ÀÙæpºg̀ùe-ˆb]Ji-+æï;JïYH–2vÎŒ)ûÑ$S¿0ô9Œ­ä±XƯ1öÑ™O`|>Œ¥¢¤Ÿ̉ñ¯û;–ØÔ›g¬ù×ß~ûíă]±77×·'¤7XŚ\ü –Ă~¾F©ăÛ/7Ÿß]¡Jéøöơ›t|ơûmúø°eo?ưru8₫`W×·_11Ÿ^mùzóíË端§5øôè/W?ÿúéÇ›ßÏ V×<²“º¡]o?}¿sé“˾‚{¤l£F#c;ÙFa9¬„Ơ°-lka§Ö“³ ¼x=đzàơÀë)ĂÉZàYàYàYàYàYàYàYàYàYàyàyàyàyàyàyàyàyàyàùo¤bg[ĂRX+a5l ÛĂZØÀ«W¯^=ă}œ0Ø´gÚ"¿YFJôxèÛ¤á-°ºÍ(]%³̉ZN®YË#ó8§OâḌ&}ÇI=;¯¥Dî†Än"ƒ-m)gC̣†-ÓÆ‰äu1'²7̣»t§®åDúVeëΆô­èă+!—IœZ³û¶0µFÙ ¯ådË&;NñÜơgÄ ®qqωô­]Ó8‘¾©lS_Cú&Z—r*̣·q*pωüËNĉÎd›Ô[¦Kq;‹)\ÛO5¤tæ>´‰T$qº›‡´#©“Åœ̉ó8û¸çTøúRÜÎâdäĂ»ñ‰ov©k9ÇRfÛ–N±œ²?¾¥ăI[W-đ-ïâ¶bΗ¶”S\̣é0ï³h.®k9­æÂ§`=uỲÙz6ÛâV°v—µœHó:oq+XOÛ¥ñ9i‹.HóÔvœJY|1'ỸÖ2àùBk9‘ç‘mëPËØÓ¬åDwRî8+çrit2ÀfÙmăd÷ó†v!e×l[o2VÓ΋)‘å“ê{N¬¦jÚñ¤Ö’‡̃sϩȨ­­åD–ç»ÑÉ‚¬Ï.DФ #˳Ưèd†oy-%’¼¶!,¦¶Ø³(É;ZµÍ\ài^̀iØÆïÆ&9ç~)j'íÉhêÖN²’sjÏC7»çl†vóZNoi !R̀÷Lk9‘ăsº{N¡\́qN™´÷$äx…è̃å\×r>]ïEù ½Kê,½Ëó8]Ư/̣́ûbÎg^B//xMă|†à5ó‚×4Îg^Â/.xÍ¢|ºà5‹ñé‚×,Ƨ ^"ÿ%xÿZüŸ¯³ ô@đ: EO¼è¬í¯á…³¢ ‡Ă¡Ä„"F¡ˆ§œm(1Ê„²#''§§§§§§§§§§×¯^(wÊ…rG¡ÜQ(wÊ…rG¡ÜQ(wÊ…rG¡ÜQ(wÊ…r÷¢”È̉+ơÅœH¯ºÖ …tKl-'̉«ö@¢ ÇÀ2ë¯H®öª› ×’Å”ăo×—¬H­t-å3ĨYœÏ£Äæ‰Qc ƯĨ«®¥DvUüå—Fæ,Jơ¼Sm‡e²˜Rv­»fbm~a2đYJĂîT!,£zilúË+QZ^^‰Åù%j§ƠÜv“ĐP¢øÂ©¡N:#Œ L~”¨̉.ô'½¼5óJÔ4Îg(QÓ8Ÿ¡Dmœÿvô endstream endobj 290 0 obj << /Type /ObjStm /N 100 /First 889 /Length 1272 /Filter /FlateDecode >> stream xÚµV]oÛF|ׯ¸Çô¡§»ÛûŒ ‰ İ]ôĂ E>ÙDiR%)»ư÷%[(Å@"À—w³3{;KRÆ¡„ñ$´ö¸ZaÈàêÙˆ«–×|.2. Ÿ—DÔÀ%’.h¡•µ# Àh Á M‰±Nh§́…ö¬`ÔÁ28 Ipë“’ĐIA ˜ähD ̀ ¤Àœ’Bà„Q¨‚dd*Çp©ˆ@ka´W«MBaí4¤k¯G¤‘4Ve, À|62„ rà¹10¡nb ‚„EQ„ Í+°dGDȲÎcYM#>­ĂQÈ"Ëñ-²ñ²œåÆ#ËỹB–‹`vÜzøC¨^¡fGlo±;ém‰8— ́xzÀă57é~Ùtpöă2&‚¸éÑ£Ï8¶‰|.xj"| 8hÎMè¾IL¿LbÑÀVH<)¡®@qĂ¹nÅ sd;¡Cÿ­\º˜°œØ´Ÿ˜B£7”…)A€r5s0Î03×dÀlăÔÈrCyô–6¤Zµ4& àîƒ!J1lÎd1Ĭ–gÈ*^Œ5¼Â6X0/ÂÓa1$đĂ k jSDÀ½ÖØâ±p°Úb¦á´ [Åơp×øÁ±Üê,q¯5FăËÿæYŒßTUƯÆ‹/Ự₫CQư=¿­›ë܈+…ÇS}Ïó´WN[é‰Ïge„Î8é,—g$&¸7âèHŒ/Äø]}Y‹ñ‰xåè'ñúơß§ “d@×đAx`Í¥Ă@?jF/5Ña5½“Vmh#S4‡ƠtFâ™̉tI­‡5í̉$/ù~Ô´~†Ăj’x³>i’…Ÿ₫°ZI64‚Ÿ‡ƠćL&³á§ 2’;¬& ‡ẀZ¯jb<¬f ‰Ù}̉Œè­Ù¡é~¦Wßư'Mdá°x6”ÛĐtV̉®¹ư^M•dÂWÄ@? é¥üÓd9SĂ₫ÇhêH̉Åô¨©1CÎ ¿‡ü3Íqeđ2Qâ\ŒÿăO¯_đI‚£Z”å§5́´®º%Ó)~¦­à§ø¾®SO#̣V¡ÆÇ&ô7ÈŸ5ơô"£X1>;9ăËüo'VÄÏ+{_µƯ¤,‹êæ/eƠ¤ºæKYO®±²¬ù•敽°-RƯgçE“ïrƠµ;A¿ƠuưĐ2_Ñ‹́„~¬P@fä h§Ư‹rf³Ÿ×YßÂ~Øu·“¶˜2Ă¯íäfIơñ>7÷E~è /ím¾Yt·uÓöÙë›mÔư¤('_ÊÜ;Đåf6™æỦà^»§ö‹Ü“²Ï₫zq+Ëô¸]Û´¹}V7ƯƯËă³¯Dyeåà}Üăôă²ÀDíséäkE^ÙÂ÷ïWߨăôá.ªiWÔ#Îó,7¹Z»C¼6¼¿Es\ßƯơ uÂj.†6¶²C•‹ö¶¨æ‹n?¤^tƒ˜w¹ÊÍz:Ö7»˜ø9jns9ßFÄMÄCQÍê˜&·uyŸoëv¨³÷oWÅp´µŸúÍ_êi7¹ÏŸoæÅ—ñlZÖm~!¶çê…ĐySTỨ…à&O®_m§“j€V«!đCSty7xZâSu_L÷@˜gÿîç |†>à3HWÜåzhÊ´̃@í:Ñ ÓÎëÁWơj»k››Ül̃›ă%âxO\ endstream endobj 434 0 obj << /Type /ObjStm /N 100 /First 842 /Length 862 /Filter /FlateDecode >> stream xÚ•TMÓ0½çẀq÷ÔŒíñ‡„HˆWZeÛ,D„&J\üz̃´,» »l­û½ùxóg-µä¬Ç “°Dœ¹–‚Å”t±Ä ŒsÄVWO,»@ÛÆ¹D¦Lc«!¬KƬB& Vzɲ̃'²çɺˆƠơˆçÙˆx^È&à| Çøy`´Èpáb{}&a„„ơ< tĐŒ÷‹-I.2yÍ‹ØưºèÈ{ä‰<~.̣IÏ’ªÀÇØA4‡¥à]ă’PÖ%OAñ)R<âEh*-SD¯̉^W¡ÄŒƠCN8Ṛúœ(EiwÜâPØ`…Ur y„›¨WĐ5d¶™­Bræh°Áœ ’‰Ư˜ØˆÁ¤Œ€e@7ªôcƒ‚Å‚n),’Z:Jg m`^P ;” ¨̃° cêËĂ0YKu‡₫‰]4úC4†Ë^1p{Å &ö˜ŸÀ#́!¨@`j@9`ză ³„đ†è[Ư f8…# Œ# ¼ÂÑMP ’¦V1 'v '˜UàmN:(Â)ê‰W #< 1Ä ¦>:‡É`*ØÀÖ¬IáĂ0µÀÔÊ7Wï̀ëëæÅ Ú| ÍÛéăD›7tÅ|M/_6W¯¦mî¾ơ·ƒÙnî·ă´öÏÄNs¿&té»]j ĐïËûça?ơùyÀµ´' g/o»Ưn) Ü#¢¦ÚHE'ˆJăﻥÇ~<ÿ̉ |<¬Ÿ‡ư|È—Q¦C¾ˆSñM=/Ă>ßđ±Œ¯¸¬‚®y¬ /IR{ZîPΗ 8…ø¦-c—ñö®;́–®ÔÀ9̉ܯĂÏËH'®2Ö¸ˆzÈ?.¢¬yH¦JÊĂ×~*ösÂîíÓûqXó •­øQ±ßă›ÿ~Ẓ¿_ƒăY5́ß ÏÀn¶Ó₫~øtXúựuØwy*|¬Œ«̣k£<è½µç8¹Nó_S ° endstream endobj 588 0 obj << /Type /ObjStm /N 100 /First 848 /Length 849 /Filter /FlateDecode >> stream xÚ•S]o1|ϯØÇö)^́ÚR…@TB¼¡6•PH¯p"äN— ü}fÛ¨j£Fjê={f=»³NYÉQÊ…|¦T˜₫',‘JÁ’ˆCÀªÄɶ3qö$Αw +“y!.ÆwD.Á*\Áª‚b-Ä‘°£3VO‘ç@1Øw¢h|™"î†$̃S2œ‡–h߉’àÜC“åó–|;?ưpZ-_@lùB"En&†Ë¤ œèH­.́eÔ$1Pöàà®m_( êJ9§…ÄBÅ!OrTS’§’́;PđR¢‚î zVĐGÁ;!¸Œ:*¨–E<AÁc1£S"`1R‹€Å°E,¶„ –÷ΪC¹¢`y±^=  æ…dg.BVưчàŸdĐ£³@ Ù#jÁ\pÄ…R@& ³ÁvĐS@l>’^@O¦Đ&$™BüØ|Tô“­±ê@·(¦„íVŒÛ¶bNXaª¢©¬úYa¡ÂV”.p©B”BgL bZ0èÙ<żpFÖpF“Mç ™ "¹؃Uà˜bj¸@¼k¶À#¸ VyC.{‡QÓ äó«˜Ï6PÀy·¸x;læơÏîó¾›úơv¦yùđkêçîrquEË[Z~V-¯é§Kzó¦JùÚÍçâÇ~·Ÿ×óa_!J“8uëû³Oáđ¾ŸÉ«U¤ÿĂ_¯nΥܬn+”ܤ´œ92₫ +˜̣/fÛï+¸ÛOŸ€4³ñ¿èS endstream endobj 742 0 obj << /Type /ObjStm /N 100 /First 847 /Length 850 /Filter /FlateDecode >> stream xÚ•TËnA¼ïWô19yz=B"!HHÄ!Rdœ ¬”x-{ |>Ơ¶’x̀a5³3Uư¨®Ư™•ÈG,‰bÁ’©,B»X‰PI8›q8%â tÊäYº’1ï•|ÆÇ pÙSpk¤<ÖDØ’ QœPtX‹£¨E¦sWPB̀à!W]3%¿Jå•J ¹‹8JZxJZʬç‰rO2åTº"BØ¢±Öœq*bzœƠ¸ë±Ô´«µ́bᩲ{ñŒOđ¸@ ÄEÔ).“ –¸BUÏØQ 8c¦ Ư„Uô$¡'ëAÆ&èIÁ¦p'¬R£ñ˜I=Dg¨*¨”’‰‡́\µĐ=+X° zº‡Üô:‰ƒ+$ ¬zÀĐTèAŒHµCäă/lÁ1ëè±è¦¨ ô ¬Ä±´ÆI³'°†.j„ÉK+;½B©Y³'Đ³f‡IĐ ²gĐu‚ºYç!Yư¥Ă(¬.“ ºÚCP —vz³ -0 ‹F. ‹Ö\À̉cAtl0Ô Á ^¸úÔ lÇ<ƒr¹jd¨æ#Fï]P |í´/ˆîöçx§£Á³‚13Ͼvg¯ÆÅ4ÿÑ_O‹Ơânè—ÓlÓOçƯ‹4ûH³·ăåH³ :‹|N/_¶à?×ĂÔÛ„à1äÓŇ+ƯƠÙE¿Z÷‹ùÔß\ïYí«ă$₫iUÛ›Ớvq7nú±wÛÍ÷ÿ€ËƠ¶%N0đăv:0®úå‰ĐƠzXN·'‚×ưü¦ ¨5Ëö[Ó%  ‘>#ÛÆk­2P@—ùạ́ÚrÈ#ÈM?₫aôU₫ ¦á¾›ă2z9|Æơô䋨˜‰´p¶—·Ă·íº¿½›†Å|ÓâÊ?¸—ưú~XΧq}:Ùú°,¸ih‹`¨_ ¸åß4wrmp» ½ùŸĐFÙ‰ü³júáÓÇ×—ïߌ³ßy₫“Û|îæïÓ‚·ÿZÚĐÊ@[í₫r{ؿưʨ́)È(èó—w|É~{çÙñǯÙÖº6¤nƒ~Ú`Kèz‡j\§Gצ̀{ĐoJxơ₫ endstream endobj 910 0 obj << /Length 1675 /Filter /FlateDecode >> stream xÚ­XYoÜ6~÷¯Đ-`Ñ")êÈcÚ&pôpƯ¦@’íJ»¬•6’6÷×w†CêZùhSøÁâp83œùæàrLJ?îD‰bÉb9›ư…¯©ÍΡ›·ÜđyÀè8_ß^\½QÊá>Kü„;·[G Ÿùq̉˻͜._}ºưéâÇÛ^©@¾P«å>S ‡GLp j¼…™+̉ê©Pº×+îVm—–eQíVŒ”›V}”u!̀›_Äw<3?1Ânïr8"AÈjû¼Z‰Èíˆö} «Øíº$BW¯à´[—÷…aÙ#û±5«µ̃6 ².ÏhIÆÉÀíî@‰&¡™vEÏD 8Ï̃Íæ!ăÆêkÔ*w“¢¤0êX±^ö~HXƯÀư€Å¹ZàÛŸÿXr¸= bËô˦KÑ_VVWèfE“oº̣Tm›zOttTänVwLJ¼mỰ́KŒ’të†xÍ-Ô·ñlo\ô¹ô ö¹öÇ%g*ÁÿŒ+Nï)\™ È—"5¡ ïf5Útª&aH›5h8]&#¬1'DHÙ£$ \­ơ¶eÖáb¸’­Rܨ«¡èdC«<Ư Ü»…ø 3&ÏÅîÅU´yÛuE‹ÂZ7™5¯$@¢áéZr¸ˆC&"9ơøöXm:—–àĐ̣°¥ËÈ4̀ê€É CƉ9È™Nká̃ ḍÏGÀ&£.)\Èc0.Ll̃ "”Ü}ûëơkújriƯtDùè+ÿ]¡³üø•HuU>™_¢±[:ë_½Ư¡XË_\ơÄŧ£=Àùt_)»6…J‹× ½HwÙ e‡­¼XEp!(vx§ êïÓ‚Èw‹–v̉²­ÍÅY…nZ”éº̀‰¼Eá‰SQ!ú#÷ÔaMÑ2\eI©¡FR§¡ª*±O; 2ë”'02ŸÜÇ÷Tܯ€)ËX^»°¶éWWW¸ KFÉ:`̣€Aµ¸º8̀¶œÏ}àG…‰DbùđÉw2Ø;X9'Í·w¤†«ï”Îï¿-ơ8 @BQ¾Ï‚q®Zú!ÿ?”KøIÜëólA­G ỉy¶*ÍSÁ#QÓ+)~Át¨ôà™¸?è îÅYaœù¾€$đ¤i S‰K]³Ë›*ïh ¬̣ µ ä˜xÜ„¸¤©n†_N^Ô Üed¯Ÿ]/wk"µÎ,Ü4¶w‹©Î*̀ó KcÓŒ̃¥‘ytƠÍ-OÈF- S›ˆÍ±ªÆOà£ôYóg0êY¶IÁŸbơ²ĐR” M"Ï_¶³Ç±ÍÏ1~̀úhi~4 ¥ XFß„z2]LD©L|j.Ë™x}x”qoL¶ûû¹ºƯcX†ßé"”B˜ŸøicŒÙ›|—6™iª~L ê[xaŸwwô’ͦă' ͉̉é˜Áç‚@‹géÍh¹¤ßŒZ^gL°ÏĂÖîM™%œé§Ë…÷Äd˜¿̃{Ay¿iÏÀè™&|]đŸ ëüצơC̉ø†¶Ú>ñÓ$ “oƒ?ª0? 0û́ùƠ*8X endstream endobj 913 0 obj << /Length 1639 /Filter /FlateDecode >> stream xÚ­XƯÛ6 ¿¿"è“\t–åÏbĐĂ>pºbËu/m[IÜ:Vf;ÉĂ₫÷‘"íØ9_q{°¤IQ?₫træÂŸœẼ,•ˆU4ËvW®]­73üùÛ•d¹.’·÷W7¿ÁLº"q9»_ÏÏnœôöîóÙ{Ç›¼}ơË}o(đøê™»v̉¶½™Œ„'·Æ(¼P¸8£]A¨œÛ¹t̉¦Èæ λ&Ưh¾=Εtt},ô ${¾P~è¡=w¶đ•P^gNH4è9¯æ éÚ­©RgÔd"¤—Úư¶óbåÜUM[vº{±Ó̉ZfhV›’öi6÷"çó<ë¨]¬ J‹\7´R”:ñDñgÍ&îñ̉`}¨²¶0ë¬MMƒF×EZ^Ă$QNáeBÅăó¿%¾×fËÑưl*³Ùbí&ưˆ ‡Q̣ü(?e‘.´ÖÂÔ›éC•P•ÉEĐcàZx^0%́%" T‡_̃¿s€F(tU2̃U‡ưƠü ²ÅdS1 ëª(‹#ùB ­Á¯ 7Ÿ%4ÂŹli6^jè›k¼‘£ÑÇj ̃î– Ä̃.yg‹1đĂik“Ke±ªÓºĐlđdo|ƯyjqÔ‚k:îz¨$†')ÆN0$Đ5åç¢í ¬i&ÇøÅpq?œ5 äA±#”?é ₫"UëCu¡ưß°›́vŒºÖŒ]$¿³–wC_^N€E”$cÆë-l°6Sơ°éDĂªˆÂ¾ưĐ́T”%jƯj^EËơ.=‹uß¶³̉öÖ¦nũi›)Ø€QZ³j—ß Ë/æ2œ¦ØÁ¼f=3ú+êœàÉ|RDn|»1åÊ<üÅFÄÅù‘>®€+9µëüîôHÁÀ‘y©è¨CKs  Dp”á3R… ÛKHÍÛ]uÎíñ¸Ÿÿcפ>"ÇĐ̀{y-?œẴ?µ!HzcIà{œËuœă «₫X(̀²Á”,æaÚ‘p,lç »Ñ#Á¬,đL¦Åă±8̣¢Éư“Gr|œƒ{!MÜê á‹S³4ÍÊ.FÇL ÿN^ñQ™3,¼1M;¦sˆÖ5 5ºt˜m C¨d»„ÅdFÇÖr7ư†„̀)\G`¿/Kk̀Ns¿ ĐD÷øJh‹…”3.ü is°}ËM›W×µNsFë5RU=ÍGÈ•ÿAG.»&8Ùp̃²Lø-2hQ×á¥ó áÙñp½â«íï₫)?@½ÙH”€Ç>Ä̃tg9ü(àNVr7S‹ŒÊỤ̀ꩇ¢R‘qlM]e r8½?0>Øê÷Ø?@^÷œÛ¥R2°â”J¥º=?0—=4‘ À°%Ó'xÆỈ+w/ÊezƠÇ̀+¡̣‡=VvO9›s>鬥…­=J©ºnfŸN0Uë,¥v s¢ ßT‡“¾S6“î¹ÊlË”˜Jès‘Éç4\XèѾỒ¥å$€!b°‡Ó<¬ëň̃Ç#F1ÙRó…ïö ơC‚èßo+™3k¶æP2E"z:|4r¯è3¨sb§É̃X›lSÎØ†ïdƯC‰Ï‚-ó;´̉ưS¹¬¶[ÈPwÏ{ĂçËû‰» $ÍD/üàî‹x ß´í—wË[ùâ~–p·]~–Oѽ‹N@ÿ܆…øScWÀ ọ̈]B~ß¶S€Ư‹̀CËóS‹Âü£­È¡̣}ü6œ0<vbä@xv`•̣.èPæ?¡hÆƠ endstream endobj 916 0 obj << /Length 1340 /Filter /FlateDecode >> stream xÚíXKoÜ6¾ûWîE xi‘¢^zˆƒ¶h/IăÍ) ®–ÚU¡•¶”l×ÿ¾C)iײ+£v E¦È™á7Ăy|Yêđz ó’4$i˜xù₫,0»jëáâăOgÔÊ-Ap9’¼Z]₫E HdÔ[cS«÷Ù·‡NªÅ2 CŸ½Y,9ü+Ñ–9n}jÅVê%÷ßß.XêKu[ʻŒÅ,ă~¸øºúǻ‡U!b‰x8¯“Å$ˆ8‚~‹Øª²íZSàĐoQ䋲ëjA} ¾•ªJ}ê7ªkñ;5 ­á qJvª”èóoÚ²̃âi·l7ũ•MưF°Çć,%©·¤1IÓÑ#å|]>Tx[à ñÀ‡W¡¾Â«©/º–§I¢PY/À Đ)Dn·p-ưßẽ]èæTƒqª+ekÅSy[¢ jĂ›kÔĂÖ é¬¾…ÙÇ.ÁØÁ–‹ÚÊA"©°¤!¡‘ O‡ÑvamíÛ$öƠÆèGºG1‘ç²mÉ̀§Xèô¿Ç?ø0_‚(8¿Ç/»î₫Óơ=¿ÀcJ#pLPS4µVG¶ÀGm¨µºçkq³Q¢“çFß́}×KZ&êzá„gÜÓ’^xIáBgUTm3Û>ÔVĐ>üÓÀíFÛŒ}0o6Û…1æ‘+Ụ́‘ƠÁ‡öifÔĐJë±8í3Åf´̃́ _ï̃©²ë¤=ơJ »*T³Ç•Íi­Tèó Ô/´y¢ßªÊơÊ?ú¦ á4ô¢$ƒöêö÷ùkàmà¢FxâƯɽ–„°ª¼ë³_§zd˜QÂ#c)ʬÓæF¥ÂàL@hÏfר›ùt’³$%Œ¦ÏBÈĐèŸdKa°¥M1†ÓéDSjn<̣q›À ñJ™±@s/ÆIe¨Åܨg(ó¯¥Â0->,Bª©ÄTØơ&$ùIÈ•̀›ữX©ÁÊÆw/»]c"oùFOk̀Lë¹ÇS\¦´»jn¶;GV́ͨÙëØ[47ˆ470“œôÉ7*ÂƠ±4{0]ÓÚy,{Ü®ÿ†DMB{.³ç06s¤Ï#­/åJÓOưqJÀăÙ¼0[úôßÎ)ôsh˜~u±×̉öÛóHíư5₫mmộR_˜àç4P´INƠ8ÜÀ<~ßô¿Ă¨ơKÿϪ°jú iụ"uøLj}‰ưñU¨µ³üJÔº₫’ÔzÀüM©ơ<*ÑSk“qơÆơaÛRë“Æ0[Đq»£tù_¾W¢’O±Áƒ¨­ûÚƠûR¨·Y20¸£!>nf@u›K™â$ä1ù&˜#S©”û¡)‰üƠ»ST C›f= ă„¢îJwH§4ƒx1nî0‹‘—¸±3íqP“£đ¹‘`kP üÆ d¡¿º ßăGƯX3â`{§ˆ̃(­Z̃ágøiIkmfṽ2GƠŒfÛ©›=Ñn9Ú0ûÍ¡j́î=6zÑèÓ? ₫¦÷3Øë IĂÁÔ°|Ó±»]sSơT_% ,rô.¯J k:g4ưÿ 7ÇCç endstream endobj 919 0 obj << /Length 1402 /Filter /FlateDecode >> stream xÚíXƯoÛ6Ï_!d/2P3"E}ØCuëö²lÓ¢`$ÙÖ`I%;è¿;̣ôaG ¼4Åú0ˆÈ#y¼;₫x÷£¹ăÁw"áD±Ïb?r²êÂ3R½vlă÷Ÿ.8Í[ÂÄådæ›ôâêÇ p¸Ç/áNºªJsç½{³Q»®Đ‹¥ïû®x½XJ¸oT[fVôg«Ö6¥ûëa!b·Đ‡²xX,E(éÊŇô—‹·é`B HÿL{ûÙg-Bæ̉}mmKon­eYS×EÖ•Mm2E{°L¶fg{u‘[Á¾-ëµƠĐmhR—íh¶¦‘lW’hµ¯Í&¯Ñi°1œÚ(b;K0&ÖÊv₫¹ßÛè¹óï’‹ˆyđÇ/_ÙØ9'•Gn/ëLàÅÇ¥n;ÛÙ)­ª¢ƒ!îj+*[ûíú?ßÚ¯Ês]´f4q»Æ )€´¤aܬ-`B~₫^6Đ&…5âf_-Dd$ 1ô0°ä>ă§c­ó₫¤0̀jKGRVE³ḯqAèªí09̉jÛ63ânІC™/¸kÀÆhÊ$΄°ªÑ´Q¥º­º'x5ƠNuåư¶8Æ…í™hÀ …^[sKXº%Eª€ÖăÊœ fP%ú%h3-bü\4–ëzϽ~>eâhÄÎ BP„1Á¯²ŸMÓv5̀±½ÆLâ.†ĂL²5%T8܃§tưƤaw@ZÜŸ< m™đÀ½Îó’@5Eơ£·X_Àk§JƯ>•SFHơIE­†t:$•ÁÊy¬Ñ é¹™¡0M“¢$'m0©¬qKX³R‰0 ÿ îđ+”4Œ0¤»²hiÚêDU^J«ƒ“ƒ „Nk,éh=™©‹N—ÅÍ0nƒ¨Ï¥ h]ŒÓgnyk†'׆îKCQë/ÈÔ<ĐOtI² ÀÁ¾R >5¶ÙæCú™hQSKë/iÎ¥QcDß iỏB{@5ó½1 ³Ê¨Ï½GZÛA+äŒú£x³9N#Í6Ñíç7979! Pa@†ÂdØyĐe×4¢đ’ă\]¨ÜVº©l‹`f…012tW¨¶ ơ¦r÷́äïrøq‘{,÷<'‡Aˆ“‘ó`fVÏDäCkëüqñÛ+ñă„̃ªPŸü˜µCʘù¡ÿvÈ@0?Ií"Ç{6{i–~ÀYËl₫hT!óƯÛëlóÊ~̃¥éígüûRă¿zl]NïÔï,́Ç×̣#†mº÷>{s…̉‘V‹™cVXèË“pk(ëUeªL Ơ.ï ơxÓ˜¨÷¤pEчƒî† «1ÎÄÍŸ=ë6ºÙ¯7'…Ù,C₫kLG Kµëi`êéSôđ«=@™ô壯{±'H0!}AF eÇL؃i€À?â ÜÀÁ7­!ˆUa“r5jp"Ưs3¯•$í^+O›5S*§ïù,›œCĂÈ--s™̉I¬©{ËèÎ`”̉2ÊøiF)¥ÑÿŒ̣`”çƯ«“Ç™´2}­ó´2}!ZÙ³Êô¿c•ç•éU ÔTW,M0h1¬̣$Ăªÿ5‚¨ÔÀÎDË‹S(1O¡fèÓ·Lî‡Û‡̣B顜 nR§?üèI93úF5á®gaÿeg endstream endobj 922 0 obj << /Length 1629 /Filter /FlateDecode >> stream xÚÅXKÛ6¾ï¯0¶ˆ=¨W‚’¾¢@·­sJ‚@±èµZÛrEi·ư÷á iÊ«ơI€bK‘3ĂyóG³₫¢YỊ̈"E’ÏV»«Đ́v·3Zü₫ÓUÄt \x”¯—WÏLÓY2,£Ùrí‹ZÖ³wÁw›êĐ«n¾H’$ˆ_̀R¦ÁëJ7+Úz««[…Küz7‹@uwºŸ/â,.eÎ?,¾úaéTHăT¤2¹P_Kư@é"ER$2‹­̉q&ÂT’̉±Hç‹4‹¢y¼ư₫u!ÖD„`0²†3ĐT2wœ""^Ç0v0D¹È¾j¹Aë£̉›Eû ùƒ?Ơª§M¥iè µ‡Ï8 êys`Ñ©.«^ƠD\íy±«Đ­ÿ̉Ǿ퉹:@Z¨ª£fÏà|úä˜è¦Ưk"l×t̉[Í›½î»aji¿@£•‰ˆ̉ˆ¬\µtص[ {ß[Ú-ÙÔâé?‚²ă ÈSUM„¨Y¬ˆ£Vô©7í°­)qÍ›¤,†Ú˜‚»v<¯ §!„¼àÀ½ât4Q™ ñhÁl¾¾â¥̉-j¯XƯA7û[’à+C‹ơ°7_p^d~^Ä…(X¥‚TC₫ß̉?̣>LĂë(ÎEÑơ3:(BئRmáÉ̀½t‹‹2xF²Óàœ¸ ƒCƠU;eÊÏMÛ½%~sCU]w6é´¦³ºê+ZƯ7Û-Ñ9ávßb\“đx·VàƯú²«½0â§I£a7‡̀ưDùÛĂɾ{³&—S@4 Pwï4 N’¥ÑÄDƠ‚çÉĐ»¦Vú ä#²WµZWöw >ä45^OE,ý(\¤§$ÉHQyVX)’,±ÎÔ8!‡-™ éD~$áù ? süûT°, ÜEWmªư­) d_Ó €gª¸¨€ÍV ôöâNíÚ^mZƯŸÜ ˜w×ö0œ2£ĂdóQ]ß(-(ºüLÑÙ;•¬…¯­ÇçUéËsŒ£½Ç…áË Kù{5-Ù«Æ•©m̀)6f¬ ZW+̃2m05mó8ËÀŸ+=H4cơ‰ÔZƯ5F\r¤¥—)Öwϼ,¸S}×(zJjâ¤ĐO¸æVÙƯQ¡i»aÛ§ŸWÚƠ¨Ó̃¾xXă«äñ—Dÿ\Ë=Ơ¾ƯÖ}³Sí0+…’4ó_3͵c¶¾q„´°RøÀP¬ä#ÂÙz U;©Ä ñăÜœ²àÔ0–\muëîĐ_r.Ÿ ¿ơÄÙ1Á`M ‹c‚ÁÇ}×ô½âj°è4ÀjƯµ;ZÙc6á“jbÔ ?¾ÓŒ6ÿvR†‘)£Bd™DüøîC8«á 'öƯÂƯ,qƯv;ûăê·)d,ĂTÈ,7¢d\’ÑGŸP#+E_E<y.Çzx₫À2£>º@ă‘”̣ƒ(MË ˜̣ÑHç«̉œùÉ}WmOkđ#:É—^xFYe^gÎ*w“`nµmµr’q´³?î9bï‰0Å…y)g‰„AăÆç†).À–$Q0^„1ăhTẻù‹èC ơ3̉Ưøîè³ñĂ>XP„Ùqˆ‰CŒnæId̃ÚKGđ̀$íng̃ê=ø«¶Î¼·a4Ïne´æ½cع­¯ºiâ1đâ/ó–ô Å´…ÿ];ÜnF³đăƠÅh8;G<>H²äÁPđ”V—½V'|¼rA}¼ªë¯¬Ä:<₫ünbn¡Î‡ªéô9«=˜̀¦×Cçl÷°Ÿ‹¹7&=9¡1̃‘;0¥Ü$Bain‘Ë“áô[̃øÈx̣Hp}Q®wÀ&Y.½!?´Ñ¤g~VÓÁœ` ]*€ :D>ơ OÂÉ-(9{äÂÓDúL˜³ü,˜OĂœåW‚9å,ÿG”sÑ{tD9₫ Û¹ŸFåŒu8»‰Ï¾í~.MVéVæ ›†6l‹µ̀¼iNI0,ü >ñ7ü¯•% ßP€=Û™ù]3ÇÑ\ ќƫ›P,¢b̉­ªˆ &–=ßgƠu¿e˜› S)ëyÁ÷<÷VÈ#(æÙƒqw´ø¥]UÛª£h*¿O‘C9–¡Å¥§yC endstream endobj 925 0 obj << /Length 245 /Filter /FlateDecode >> stream xÚMOÄ †ïưạ́5”z\£&^L ŒJ±­YwMÛÔøï¥KkzÜp™yó0yfâé TJTZŬ*Qø*ø%Z”‹—ÇB¬M Ư‘WÜ< ÁYÅ+ÜÇ~”kĐ¾ëü÷B•RX̃ª5àƒû£×Ñ·q)5~‰´8s•FṾî{÷¯hu¥ïF_!- ă ³´ëb¶kâ܇U/øSë$—> stream xÚíVMo›@½çWp\¤²e¿X豉ÚC+¥¾5=`¼NH0X'Ê¿ï,;K€̉4m"ơRY² ̀¾}3ûæ1,ˆáĂÍ »“¸¿Û^îÏùÙ Ă¸£QäÛƠÉëS¥Ó,ÎX°ÚÇ4N³oµ ¾~_}:ù°€WTIñÄ]}ôO[§<`r¦¤ƯÚfÁÛ+»«#•rf’ë¢+›:Œ„VäÜlMkêÂXZóâ ’¦Œ9Ơ•EB-B́¥$űˆ§¤«î]Dn¯nC¥H^VùºÂ…eí~;‡$Iׄפ©nÊÎƯÉ[ŒƯ˜CÑ–kx³q÷đªj,üuœmæ’ ™pÏ™S®³ ̀¦ÎÉ»f·óICr@!sê¥Y6€x˜‹˜©ă᪬÷ÇK–ŒÑL)¿=œPªÜÂm5Mâqy“Î+ƒ%}́E¬bŒ̉cDI¹ä>hcn—XJS>FbKÇiMÓA™2_ SKqv*e}èÚcÈÈ.ŒÁ£=ø#´Ù¸Ó8B5„i)!“XÂvªl&2n"ä,Ă)wÎ(©Ï0r¦®MÑ9uH»´,P=M‹Bl[Đ¢&¨ËfëÅeC‰G¸Ơ„₫—c7â¯áÿ¹©}/éYØĐXö¯‰æƠ¡y³„+AFrt¦½î]ä€Ûp>åm•Ë'ÊuI—´;JNK*3ơRâ¿Ơ.ØÈäó´‹Ùüï¿oo‹¦=h··n/]M›WỌiî}º—Á•©öOPú,vf̉°́AÂVç#‰NP# uư+è_µĐĐöÍ[ç;³§bx°…F²d,NJ¦ổ<›ơơs̃S1¨‡M¾/ûª+î±Ñ¡Çû^ßÙ&×ûú!‰—iéiÅg¨6V³¾̃>̀W8àô=;¥<Ưijv3ĐĐS>î2–U³¶*'×K¤XF¥æ3R~úeƒ¶cyA%Ç>ă© G-¨ F•ÀJ¢+Ơ7à=àqœ+Ñz÷m?³Ư–³y…¥0ïÚă¢ rWVƠbÙ X5‚Î~™ö¶4wî±·ÈΪû¼°™Ư„}~9›_ó ¦Î;„>A5î¤v̉ÿM¾ ü endstream endobj 936 0 obj << /Length 1567 /Filter /FlateDecode >> stream xÚÅXKoÜ6¾ûW,z‰°Xñ¥G€^$­‹"mS£=$9È+®Wˆ,©’ÖvPô¿wÈ¡´¢̀ơn…aèÁáè›o†óXºà®¶JRNR¬6w‘yÛƯ®đæƯÔÊ… Î$¿¿¾øö”+‘,Êèêz;Wu]¬̃¯vy;¨nrÎ₫r !ƒ7ëTûz3”M­WDđNmU§êZ‡,‘q¤ë×?]¼¾¾-™$Rđ3̉OЦlE9‰îˆ–Å$’ÑrÂ[‡2fAY÷C·[s<”ơ¶Ñp–¶r­[Ä«1‹U¼ăøÜ8¼)+ơÑ*ˆW”’LJ¦„£†ÈîE¡8™ Å„%“DUöƒO˜K£IêăZ|‡´dfEÍ­È2GtÜú!’üSŸ½L2’Æ@*0H%=Ç^×”¥½Ç¬á”pp”•:ÏŒ4!ø`f† LLË"s›CĐyôɘˆt®ÏKIHcA²4q9ùm¯ºÏÈE¾fip¿–2ÈË*¿©¾̃å]ñ —̣Ná Ø6ö;÷wªÖËC¸iđ¦k* …T’XÚpûs§4ë™ º½½y(‡]³_Ó`ÀçÜ(øŒeƯîíû6ị̈;ô—p,i4†<#ËV[UYù®1Æ”…ÂĂn¼YXiª}|K‚G½$­¨»ËMpŒđ5Sˆ>¯‹‘&C‚ ó¢Ùâµß·-*ïUŒ FĐw=A¿¸;2‡2å•¶º·̀æÔxs>†ÄLµÏáBI“)‚z@EÈ˲…ópÑƠ‰̣ ^ÿ2É€À2ëMX™‘]\êWñäĸük•X¹›́§AJ; 4܇¼«Ö7HºÍÆèXÍ>r¯6凈 /ÿÄ•¯ö]g9¨tà‰twz{²à8sLiJh&F’¿ñùA’„MnèUWæƠ'>BBå竼ô)øâô|%ÛxÍăX|VMFÏF }H2¡`æø«¦‡="|‘¨ “D§ ¸ÔĂçÖ;WÆŒ$±89W²ˆ“8‘Ny‡c¬¿§&Ôj0CÛÚô=ŸpÍXƒË¦ØZ!1!Véf¦%q´ö ƯƠĐ p÷ÁK> stream xÚíY[oÛ6~ϯđKQˆX^E©Ă€µ][lØ51°‡4,»*¬Ë$9Y÷ëw(J–(Óµăxm‘ ¢‹ÉsưÎáGL0ü‘‰¤é3ä39‰̉3ܼ-—}sñöŒ´ă\èF¾œ={#Ä„`à€Lf‹¡¨Ù|rå¼zu\N]ƘĂO]Î…ófêsgEu’gêî\Ä‹¸Œ³(ºT /p‚éớdz׳nAœhh7zÛÚ`h­ï!"A&ơ\[œ¯k¥{́ Ç(Ho¹Ú¡÷yUk²0ơ»dÑN74IŒ°×Í.ăz]fSê;µú÷±¯}'¶©y„t“JëxªÔ==ת“"œÏ˸ª>¥Ÿ`‰ˆOOgA«ó©’ Cæ¨).ĂĐÀƒ”驯ÿ ÓbƠéđ†:¨ü‰K$„¸Í“'S•Dg×ú”å«Ûx®Ÿ’B_uØƠ]˜µ?m‚¡…¾̃ƯƯ¡e¶Fy¹TúÁ́%‚hmWJι1ÿZ?}kh×ùV/̃aßa"‚Ơ#¼&ßtU “₫tææ‡™;Èø6w¿Ñ1,‡ÜÈan\F%m&/ăëáªÊŸÛ@ẶyЦs=a=/P÷h£Äƒú ´Q&»Jdˆ©ũ₫öĂKÎtŒ}¶ˆđ]ê¨Ơá.·SF4¶UCùsÓ%ˆ¢ A‚QÄ|_ơˆ«k<™Ăr$@Ù]34pĉw«ÉåÙﺓ˜¦ÏG\4¢pĐö¾e‘Ü<[D«¼²ơ%bªH(C\¶>_AodẴÈœ7É*¾Ö<È A:hL57>h+U_\ư0h…¤ï=-X†fyبw›`ÀZéí.ahC‹\=ö×v!Íx¹ïDy¨mC Ï báÚ"–ŸD¬‡$–vÄZÈɦfgï“NưºVƠ,ó«Z_÷S¨/}ÇE ÛY›¤E™«Q·Ó†%´®¥ªƯfr!^Đ̀©YÆEX'7É*©; ›åÎÏ/ œưô⥽yẰ¶*S,€êvu‚ T¢ˆ`Ă,Ê$SÔ‹¡Y]ă"lôuº-­íÖ=ª£uŸÛÄ€[}ÑGéüø€úQ1bd-B‹¼LĂÚ&‰í₫IbÍö†cá6zÖăăĂĤùÜJ̀ång¤…|øÿ£úáIc{¥ˆÓä̀%đ« 0“ö‡ÊY™Ô!­jHÄ̉¶b+Éä¶G£D¸ç×c Ûù ¬ÓvÙ¶©QŒYbµÖÂ.[ĸ¤ă|¨Ơơܹ|Ūµ£µ’ư>nÂ}¹3`°[’BZÁdÈ¢%éMé±:!-éØẸ̀¸´ịa¹—ƒ̉nf̀­û2[ÑQƠÇ,²2JyÛ…CP(P=Û̃% Ä J‡óϲ?˜‡à®¥•1ư‰7½Y§ëfÇÑ•pvŸNưµ‡áaM½J₫~ÈÂÇ%p{8Åø¯DÓ”cFs¿œ¢„W©øÙm ør_jDV'ä$W6«=Då̃́à½!'Ê×Y½æ©íN4À2pvÜħÑĐÄ!dmGQo;" Êq’v Ú8.Ë´ZZ%´̣>é¦ÿFñ?<Ư.ÅáÑ–́©v&ĐhÉÛ˜~ Nߥ:©¹7Éúƒ‘A÷>7ËÜê £J̀l°đ˺9ȺÑ\°ưâ¨>¨(ư·SЮևïN¡bú(ÉX|/Âơª~®ßŒY3̀¤Øà“£̃¼ơ-Dp±=Ô0pJ3ÔS$-Ñn(´aæÆü•²MXLϵÇ6E°‚ ¨¸Q€¦tù„ơ' M;̉’đ2́[HÉK­6«*\Æö³>(êÀ'Û\ZĂ¥ M!Ÿ€K̀¡̣éKWQ˜-¾¾ĂöY_ökÎÉÉô—ĂéNHF_Œ¥lg@ƠGœŒN?¦x>́Äé~ÛƠl₫c\Á endstream endobj 942 0 obj << /Length 2051 /Filter /FlateDecode >> stream xÚíYYoă¶~ϯđ£ T¬¸S t).pogôaL'jm+W’g:ươ=\´P¦c'NE€Ø©ïơ;$^dđ‡’,¤¢HQ¹(·W™}ÚÜ-Ü—·ß^a¿.……édå××WŸ¿æ|3”g9^\¯§P׫ÅûäƠ}ñĐéf™RJúÅ2eŒ'¯—%û]ÙUơÎüÂ’·z­½+ơ2%2y‚³åÍơwWß\Â9áˆ3z¦¦ưêê2ΑbÔ(ằéüô£SưḥºÚ裈Æ(眀”|@Èü»n‘ÓE9¬ht Ố×|v¥¬÷».†C1¢ôËn–ÆÉ—îcƯ–Åní±³©„Bçư[?f<‹iÀat}û³—ŸÏ÷Ạq#Ö|¡˜T,S©Ø#>"˜ NÀ•˜"̀ñ?ÎG§tÓlÛ»(’D‚çỊ̈¶:ÇÛôO÷vJ2Œ2Ž»Ưâ·ºXµ|Utōɸ—6Èg*pܯY7ơÖa~û¿7_»:TíÚ®ÙoơnIT̉Å䤒!‘CÄP1$î­&ÉÏQ™9brP¬̣Û(œ¼^2 tëaœXâwP7Û¢‹ ¥I2µ¹âÖZYí”Y•è²ú1Ă ªsD Ê#°­~ÓñÜ„8"ÉZm¿5ÿo_øëµÛî‡%l±Ǿï̀öál„¶5Y4ơF¸Ï :ÈŸÀ[q „M4V’\F³+DHa:Æ ¹íxû5ÅX}¥nœØ­nÛâÎÛ b9Èa‹¹‚E(’’:d(Æư$ùª ’”äđñaIq¢ûNøÿ¡½a^¢ mÙæö₫&[¬àÇïà8úÑ.ƯB3›ê›Å»«ï] UÂP (‰¤N¡»‡êöóơǦêâ^WÑ\ØM0É/¯ÈSQaÑ`PF\Ú˜/̃°©lPi¬3¡BÀ+pÆOö,Åá/ײ₫Ö aBÆyh µÆ$‘ƯA¦2¥NZÊăâ_sŸ³­Wúh\‹“–æ´VAs₫×ĐçÄuÆơ…^;YR ƯzE˜ ?·óG›1CeÄ(a<0đæ°®~Ÿâ@l,Ưû ù>c—y` +Ăí—%ÓFHăc1›Da^å‡K₫tŒü*ÈÊ‘ĐokKOVúcÊÆˆi?íÊ(O!À0ØÀSØÈS¤ă)å¦YéË'U—ăưÅ8‚“8H›M4đ̃X6Ñ̀¦”`¢9Q2Ưp˜PïôÎÄr£ OËz»-úç}‚¼#6̀ósöǧÉ,(0S˺ª\¢Ÿ?LI|æưÿÔŪ¸ƯhïùI,ÜÄÜ•ö(ÙÈJOÓ0ưBÌ&«g%‡Ơ‘£~µ­|hÛ˜Öͺ(ơ9‘Ø3Œ,D1x&ơyu¯û~3ä~†Ri‡R “ZTƒÔ#; -lSØé±ÂI™#Q–¼ñ¾̃V]§}¹Xéu±ßtmØmn7µƯGi¶ô Âɯ5Åfc÷¶H½vQ¯ïơèøÖ¹öÍö^u?6ºÛ7»±$»~ơ:f73?æCøºÖcÆWøø`₫EÆW¢"\ ¹mk6½B.ôĂ+ED̉px …“<ƒD úÅA˜·q62ÁrS´}Uôç]o F·`÷h§U68²’€n ‹â••ĂĐ¢Äa‡ÍẲ:›ü©²t‰T~ÙÜoKCæ‘3JƯù’}7gçÖóyG?¬ç?M$^|$}¬äŸ7Û¤À7hÎÂđʪw2·}‡7GNĐÚû7»H^Á ‘£|Re`w.á>ù]Λ̀ _ !c œđLP£ç™đuà™đ=~q?ØưKXÏÀ́ËR·íz¿Ù|êѬÉà[µ‹9—HX<­aƯ)ɱ^äÄÜîkùđÅđkĂè0'AÍƯ~¯·­̃¸i‡d(œsˆđ§¿p_Ùh́`0PNlÑ465?™¾ ~˜æLTæƒëÓqR­v«ª,º~}Đ2w=&§×cöäa£»ø¥j›‹XÇçtp ƒ+ù"-Ü`‘\œœ₫₫.n›[ 4́' "S⿤¿=¢•Ÿ#N´9œ «ë¥BQrŒ€7<²‰ç3 û¼y星ȿӶ@=ÔÍ—> stream xÚíYÛnÛF}÷Wđ‘¢ ÷Êe&HĐ¢mâ¶®QĐÔÊa@‘.I9p¿¾³R\y%ù'E‹—á́̀™Ù33%đG)‰RI‘¤iT¬󴽌́Åû7GØÉÍAp>‘<>=zùó'(K2.§ªNÑY|̣1¿êU;›SJcúƯlÎ_Ï$‹×uÑ—M­ß°ø½ZªVƠ…ÍIˆ,Æxv~úîèÇÓqqN8âŒ̃Ñ̉Aú¶¹ÙÔ\)NA'(á̀|yU^èÅ·]# 1IA½‘[—ʺësc·v£Yº½EAXâáĂ\”qÑç3ø¹ÖÔàê?£ư$¡đ93†™iëÏΓh/ßE biôÙH®"Hªª¢G¿…\$I2†ïá#L-ª¼ëPÈ¥9f`‡_0ÇV¼/WªY÷!½,A’`;ÿ1“4Ϋµ²·ü’8±·+•×½¬•Å©µnö%dy:‘oj§²SES/́ûÜ^ÀéÖ$ÆI’L¿è´ÑÜYm´¦ÿ•đ¤SÊÿͯomà.ªë•ªµ©}>ä65Ÿ”ưª l-›Ö~·\·3÷•»_¨>/«ÎHjX2f+O%FR°HH‚@üyê§ä(3áy¢ñ³Đi;ºyUÙËVơ¾Ú̃ë¶uèÛææzÆ…K6}›;oµ&Ö8ËPJR?£[Ơ­«>„9Ơ˜³ó Úˆ°‘.Ü.‚½ú1»ˆIÄ0®bÂ…˜"XŸ̀æ\˜cÆ‘d£(µ̀6ÅœĂè°›±ôA÷-O!n̉èb̀á₫¹-{d‡4¯Sc0nGœưÔä‹ü¢r{âµ̃ÔÛÏ­‘F£Œsbœ¦\BFiX»•ÄTÄù̃÷³9†$0xü=±N$—§(arøFgMhy•‘à&4˜M…´…NêEHOèFb‘L2zøÄ$‚È4… ‘zDó§ÆÑ¸j`5+˜«¾±Tán ®™ÜWí2/Tµ·Øä[*t¢'€  ĐiUŒÊ/Xè6á¾¥ToL¸!r̀EÆXνªưØÖƯ]ÓGäu@£*7ơÄÖTèÛ²¾´×ëÆÖN¥tkê››+« YRtÙ¬!Ö­ß­ˆ®nŒ%1đ(×ÀÂ…¾(T×-ו}U4««Ji"€b„ÜUCX4E#Îtj*!\³Xf4ñŒOØlSCĂC Ñ—º~(my¯}hkûÔà¯/ Bë•₫ë0ní ¬₫½0¨ơª³·c4µÿy·ÑfkŒHÁñ°S‡2Z:÷× Ad ÈP[d:ˆ'´@ X€êö ƒOùS’w´_VjƯ; +Œ­‰ØÍ¸@øĐÀƒi£U>¯BÆP™Ư‹ê›‹O!MX¢ Ơí"hh n™·ư ø̃mƒp2W˜ÜØ“gZ€²ûuw|3–sOĐu*Æü:·˜‚^À÷T÷AOï=ÉGÁP¶U?¨¶̀+ º££ªê¶›r]²Ú±#ïîR› ½)âO!K0ĐT:z^ºå·«̉Q…*zŸod¡*gỹ¶¦6̃8¹åU]¸8Y“|½?ˆ :Z¿c ó¤UùâÆ'À‰Ă¨̉©öº,Tp‘¦º•u!xhv+k̃|±Eaä0f9 ªÛå%PóÓØ₫½ë­ơPZz¢½4‘̉Û§¶oÔ&nm:ƯiÜ…ư0—!Ê„ƒ—"Á Á¢0‰<ÄÖö-9 eXIL‹ƒ0ÂVü‡ÆÔ2ƯsÂÏơŒâPωhJ ñÈ`x…´zÔ%$ëµ*>œy•¤x¹,ª¦ QĐ̉lHHöø Ä+êÔ,?ă`[ ÁŸ1w%̉Ö¸}¢sy¤#où²©keq }H}½1i¯[4‚ ÜÀ³-Ÿ”=D¢„?Ị¥<›$O£{2X½>œ@ü™¨¹¬z¾–lNŸ¨ôguLôŒ0 âëƠÊ–Ô€bÁx*7”ëÀz™ù‹›‹j?;©zq}Hi®ûrfs àÄËUæÖù ë^§–κ€Æ+XÏ•kƒ©#ú‹¥—Ă0Z®´ƠWzøi´°Ôí*0Àå}yQVe?6*›9öçW:çNzũǹœ­ÛƯÆ6»>d·é1œ§OÂƠf¢—S®ÖϳPơäàÀÛjPûèæ4bØj³¾n›Ad1 ÷¾u¶(ăáđq_W₫«v÷$ÂRÄ3ü?œ·á|Ü)́U«²…­₫F &ÓC±Á€lùơ—ôwïÎ{zf]÷‡³ÀỴ̈w&ƒ™̣éĂªù₫d0ø!„‚t”""Ó‘₫ÏBŸó4晃´Sј¿ªmWƯePô \>$ÜäḰưLJ{N mûVCö< ‰P‚`É@àöœÔ/Ûfµ5uøgGC_̣)°̃ï endstream endobj 948 0 obj << /Length 1334 /Filter /FlateDecode >> stream xÚåXÛnÛF}÷Wđ‘ÂÍ̃—4P hZÉC‹Æ̣àø¦V6‰TIÊFúơ%——•V–́ )€%S£Ù3g.gÖ$ÀđCE33dë Ü>­îƒîÍçÄÚE`M,_¼½" %8!Á|9u5_7áû‡tÓèj1ÆBv9‹8áƠ,æá¶È¼,̀'<ü¬—º̉E¦gUX&!¡³Ûù§‹_çĂá‚ $8;io½7¦a^7–ˆ(đI%‚w?›mS›ă!¸d"¢dÖ°¼›EB†ß¬©ĂI.pg™×iíGú¾û»÷ ³ùŒ¬› Ñùªó¿´ïDJUqâoÛơŒÆ!ø‡ß=ÿå²;ÿq‡¦«­¶°²{^étLxø ü‹^¦ÛUsÙ=!ĂCâÇiïp’¦̉Y^›{Đr“Ù£Mœ‹´IíynÚ"ûơˆÅˆ'6¿o›güz)ä(æIªµjñ_¢ăë@ôƯ÷œè³r[˜ 4¾ƒF” ¹jíNÏäiFBè¦ xçÇd˜V®ªu}ïÅ#QLXÇ”°±x̉fHx)«ÇZ×uz¯ư)à>îSd0Ä7%OĂw¦æh˜Çđ̣8c&$Ụ̂}L$xÄĐü’ ̃ ‹onq°€? 8ó©5]à™JWÁơž^'ˆÖéå4{»|ª̣ÆßR±B,`˜`n‹ç¦›N/^å+}Û9* %BĐ. fúŒu^l×wßƯרœÚ 5ñ¤Z0œ‚“x ÂHø0aL¿úpDG£̣îÛX+£ ‰aBö6o|^€,œ¾đ’–@ÄË)NP˜Û,?ŒS…g(I)N¡”@)Mr*÷9uư¸œ÷³3swÂ3l¨c ‚Y®Ê_L~ m̃ñÊ8̀Vå‰eºÉè4‡ơZÈĂ¼¨›j»ÖÓ©¹;R@ cѶ#ăÿ µ~©ÔôRÜÖèéjóïj­x†öJ7Ûª°ŒJ§Z¥SVé¸EÁà)´Ư<°Đè‹đvwsªÁŒxÀ0¨-–œC_Œ'œ$£¾Üëæ‡ˆ‹iŸ¬ñAÎ`ä]ip¹SŒÉ¸ œ¤+¥Ï“; ‚bHQu>AXæzµđÑÀ ,E|vØ ÿL 6U¹ÑUóƯ;Âa«#äè'\!»#üÄÙ˜Ưu—9Èva“÷-×w¢ æÀÔsË¿rl¹£Ø˜ •Y0  i{;´=î%…jÊvq5Í/æ—¯ù×>P -´ît?WCó3¸̃0·ùƯÓ)&ÀxâH)y<Âh¶Jë× Â(L̃¸ƯåecuØ¥¼i‡åÁ‰OvH,̉µvs¼ï î ¯/ºđ.îñ´đ_Ú“±KméÖ¶³ü+&\/̃ô·Z£@NíO®tS4Ÿ§Mßpµ:DO)hY±#Â%x¯̣ÚúÏåιÎU®?8]­ös’÷ô>B»$t“~[ ‚Úá Gơ}­uD]^ t²‹¼;­uAZÂÔ(MØ [g§`í&­',&ºYëæ€đcf¾°'ụ̈5ÂO0̀|–›%lê#í6‚3)¿+d{ÊoF»¹Ú’)è3{®̣…:oƠ8º\¡rEÏ*¯3†,Û^ô( ưàÁ$J’—́ÿ'F]G.t’̉ü ®t|ñ]ï Ü ùñƠC˜esg»>ÓîaZøo-˜e& endstream endobj 952 0 obj << /Length 1724 /Filter /FlateDecode >> stream xÚ¥XÛnœH}÷WđfF í¾7DZi/Ú¬­’ƯØo^+ ¶ÉÎ ³À8Éßoơ hœq,K¦êªÓU§NC" $R4R)C)SQ±=ĂænsÙÁÇ?Έ›—ÀÄd4ó׫³‹7BD£ g$ºº›ºZG×ñoù¾+›U‹ÙëU¹ˆß¬RvEWƠ;ư„ÇË»²)wE¹J¨Â2‹ [Ư\½;ûưª_\Pg'zêg¹›̉ˆ0„Á_ín*Q`“J„·.¿Ưí]«—‡à²qp8JˆB’¹‰ơí*2₫́¦8 qÀÛ™‰¿Úµ]n‚Ô1×wskHHÚ¿Xi\tù .ú_éqù¯–d)J3)œ" n@¨×78ZĂĂw?¢/fæ6bˆB´8ÚD—g»í V§˜¢ŒKœZ*Z̀¨èư,6yÛ¢¹xÂ8bi¦ˆ;}ßÔ{YÙt:¨os+p½ƒdá.ßđ™;ǶRW¢Ä™Hh†°̣Û; »úÅ~À¿ªµîäÖ»¢Üĺ¶¶×íªøĐvö×­5?çJÆ‘¢ÊÛ}\Aå›C9çåà‚ôS_¹,ë¬ mÙ9Ÿº‡̉À˜0ÆÜanåñ6ï đCµ»?†·*[,Qœ„̣"eÔeÊ•_æ.¨í|ă!È‹¢Ü{§0NzïÜ„¼j|N…U uHäµă˜¿Œ%Fœ‹ •K¡°´oœë4:ŸCT@Z{øC˜Ÿǜ6u0Éå}ƒ¸ó!ÆÓsë¦û´Ï»‡9[B"öœx3”Ó‚±WsFbCˆ‹ơ«øÊ™ A—wBŒS™ÛaÈú̀°RPĐ/î&%Zít]‚ºË‹̣baŒ´ä"² 2#?†lhI#˾/» Ñ•Z:GíÊ/\)Ưû'åתíz̃ÎN3}¹¯ơQ'~B±Ég*¶ç4«“?;‘g~vR ÑHD¤zÙg'ˆ€%aú̃w#$'}w¢HÀ‰ ØăïH/"ÇĐ}Û-¦̣ˆÎaÜo1<NÙđÀ´­Ô{©ü;ooß—f̀QúÔDå®{Ϩ5˜PíœÙgLÙû&Ká'Áöêڣ릳¸Ø(n«.ø 4ú(7÷‡mi]=%kO×X‹\½ƒó1ø©\úR±01H›nh6Đơ>o ïÛOÑ`Û W§‡_Áf`́Đç:ÖàœD2}é÷4Å¡e%Agu.øĐ>ØÏr0lÊîĐ́́¸84Û}Ăçh*hn¹5I@¡ ³|´ÿÖDÈ5 endstream endobj 955 0 obj << /Length 1589 /Filter /FlateDecode >> stream xÚƯXmoÛ6₫_¡2³â;5 ÀÚbZtëÖy؇4™n\È’'É-̣ïwGR¶ä2ï0b[:ÇççHdđGÍm81\'åæ$sOÛO‰ỵ̈áḉæ`8Y¾\œ<{-eB3’g9M«±«Å29K_]Û̃¶³9ç<å?̀æBÈôờˆtW—ưº©ñH?Ø•mm]ÚÙœéLå)³óÅÛ“ŸûÉ%“D ~ÇHëoÂ5,¡œdï.S$“‡ˉ ùl.K׬Bøgï—2C”̉n½gÉ^¾M2"ÁûWgºIÔÀ·*ùăä÷ØÜ” B©PVMgq̃ăIJ\©M2‡…Q|„ÖgïbY\TÖç̣ʇ¼'*¡”äR2t2çâÏ%„åÆĂÿͨ²ñŒ Æ 6˜~̀d¬ôØ¥ ̉|đóD 1,y¢±ÎuFŒ€½ƒQVøÊEçV×_Z–u=c&T­2¼+ê¥×ÚÊĂˆÂ|̀¨¨ÂØ¥íÊv½í›–ø¦{’¹ü!¿oêí®ïB°ù8X0¤(.>]’3Ù§pîĂY×]_Ôe¨YÅÜ+F¨¡ĂÀªÂ¤e_຿à?f®FJˆNw\ù…ËÅĐƠ@öÜ羺êmç“Ú7A„ú̃n¶}аf©.Ăè̃̃zÏ̃èMĐ¹O6.Vsæ˜úîN¨ TSÁÔu}':£‰ßœÊ{îät{˜&0t•™Ab±»sQt—EUáW /û][ûÇ.ÇIG#LŒ’îǗỂvƯjWUWƒ7̀´[hCđ$ÑF)Îe=–B ¹Q³S„9GÛä§t;ÁÜe‹êO‘wŒ—K»élåK«Ê4r.¡1‹ûTk£̀8Vt¸[;÷3?mѶ®¤¯Pw®“nhưVcé4–Èï“H,z<̀ÿµ]÷ö 5vªÇ[ÇDoªcµw$wÑ>¬¥~œÜ`2ÈợvÉ uŒ%ï/̀¢[©Kª›aBráçTơHùw.ƒ<“„eú tgP‚ư‡:x#äGyCăÓ}̉âúȘќNñbl„µ̉ÛzœpÔ»oç4Á>LÿôÁă•ÓÙ %PÖé èrWác ±ÙV™ăÍyœư°Ÿ ²gHÎÙcô“ °—ΪưưqÅÈÅÇ.“øp¯¤Úå_;%E Ü@4¸ÀW^đç~_Цƒ7 St»ª£K ×Eß̃e@¨=^G*Êó0ËCÚAåUléuç·‡ĐZX·­®cEL¾—,à:?̣GÄse _ĐO¬Œáx˜AD5 S̉0epÑ7@·!ög«ëo}à€Äsutë3Ö¯ hëÊ^£dxÿ%ö:wûQđ¹?À­®½’’(%ï¥cÍÅçG\ ¨+¹ mÍIÏeS×Ö''P˜ ù!.X¬L?_s¹ă ‰˜(âˆ=G·‚? à‘Ẹ̈G PÆPÿÿ°ÔlmôÈ 17ù½nn€Ÿ iΕ¹<ê ̉đĐí6ßGó:u‡ 8r ̉÷AëP]{q‹2Ó¢Î%~µQäR<ª˜ rƠ€Üă`‚-*ÜĐ7,.×!Œr×¶ÖO^ÁœWá¾¢›\›úœhÿ–§« H-_o0Ü-8i›ă楲è×ëjí»ƒiđË „̃âƯ‹—CÉü ψÊ( endstream endobj 958 0 obj << /Length 1634 /Filter /FlateDecode >> stream xÚíYmoÛ6₫_¡o•€á«H°®]‡ÅÚ¥ö! Ơ¦¶åIrí×ï(R²¨Đ±v+6 lA¦îwÇçyN!†?IIÅb2®Îp{·º‰́ÅåOgÄ­Kaa:XùĂä́ü•Á(Ç9‰&ó¡©É,º_Ü›FWIʋٳ$å\įÅăízÚ,ʵù…Ç—z®+½ê$¥gyLDr=y}öă¤w.¨@‚³##íVß Wш0„!̃.\!,¸ —!X’ŒÆß—§M‘À×]ÂH¬»˜~ï‘ ŒảZa\7W×8Á¯#Œ¸ûÜ.]Eq¢àj½?û% É^@›¢*–K½<ŸWº˜ÿăŒS%˳(¥`‰¸Ç® Ål˜b¿Z,ơµ5Ɉ” A”™ñ BkŸ°eë(®c1Ø­ú.19aexÏaũ­₫€ùæˆB‘Ü¢̣ă§%¢¢CK$œ …€‚CB‰ø/dAäĂ5~†̀@à>₫zñ§Eç‚́VíÍ&—HÀ¥Í&ù?»túvüt¶³©ôtQ›ü¶'2Ä•W‹FØ—+»ơvơñF×! o¨;§+÷XŒ?†ÑÙAY&îcđ£Ô2ÎQÎØ×SË'å´eͽ)e™ø’y7ßZ2P éWèWS “·0Is@NyI÷Ơ°|rŸ¢ë¦Ú9¯ 5뇸hϨˆ–›é±Ǜ¿=7G-í*xÛ¶=‚Z₫ajå!jä¾̉ͶZ»´¶62D¶2D:Â] î‚ö|÷Ihô:áï̀o Ă;ẬN_» …²\Œ̃ ½)‹YñqéH~R{ ÉYÁ>Å÷₫₫ñ•@syÄ~ÀNBœƯ)ÜÍmÈL > stream xÚƯY[ÓF~ß_á7 sŸq«¾@KªZö PeâÉÆ’§¶ĂÏ™‹Oấ."PÈ́̀É™s¾sùÎ́’Ă?’((Íf*Yn®°Ûmo¿xơû rfɧ×WO ‘Œrœ“äz5Uu]&ỏgëb×›v‘1ÆRöÓ"ă\¤Ï§ûí²¯­=áé+³2­Ù.Í"£ Ë<%rñîúåƠo×ăå‚ $8{ ¥ƒô‰¹&„! öZsµDDN*Ü›üb»Û÷½œË§Îá$#9â4ø¶+Ú¢®MD#X(×đ '™yÿ«m×ÎIës³»CRDÀÆđÅđĐé²/đñÁ₫g\₫¥D#)ó€CZRëê›w8)áđe‚WÉ­“Ü$ Qđ'ụúêï¾èvJ)5N•ǘL[³^̉a,c—uÑuÈËÅ0gDB8˜N2¦o8ù¿öưiqŒ´B’…üÙlͼ^îâ—ÙÛd´fq]ÎÍ‘æ#YœápÀ œơ™@\«ïçZ.`»ÓZEƒeưà^¢e#ÚĂ}ßÑ3ë¿#Ụ́³ˆöœưÿ3¢ưƠºá|†ẻ’˜¸ĂZUB|]‚=Û(¢¦ +Ç8ÎR+sÔªÓơ@­|J­ÚSë(sµz.Í­\ĐÓæpâ:Ëé·æÄskN'ÜÊđÀ7p<Ï­ )Ne®Y₫Eä*aæRÊ©’x ¹‚¹‚#¹ÂvL®pèë̉ ¬ ›P}đ¦[£{wÑ)ä–ÄGƯ²œĂæIî¦S˜«(ø æ÷Ó)U Ø“]‚P­*³ÊeƠ~kR¯œ!€ñ*ư*¼ZµÆÿ†jM$€§ïc¢( ºù…Ùu P„mL÷Güza éthªßŒbaçŒG-z2w¾¡ökz Üê_¯¡O·ƠûŒ1­'×¢R ¿2j7`éGÖ¡ºíbÙl ½ö‘½F³ƒ?îÔ?‰¶÷‡·Uüm¾¥OƠ¶Đá]m[e¯¯}ïWn`€Å{G ½É́8[•Á7ûdi‹m·/F'&¹²j› ˜$thOB¥ZÚj·6`z8m¤ÖM×û­jǿüç®v ³²Ëc¾‘ªy‹ óÊzĐfüîˆCÔÛ̉/jÓ̉AvÖRP·úÈÍý‘Å2íª›mQCl3΄ËÍ+2DÆ0 ³¿MÆbP>ÚpŸmöĐÙyßí ÄƯ>ªBèA™·Ö‡~,ÚpImVaËk—éíÚlKªÎ¯ÖÅ.¸»uI@ˆ3bê`¨ŸÉ5Å›êfÈêäÙ^›âÆ”èPH?æ4IŒAÿ L“V•$̣+“11½£â9ä“oœ–"ŒüttäS—æÆ´¶¸J_ïwc ™̉K}XHØzo:÷÷™b¯8:éPQ½À†Or+eoÜ “dÁƒ¨*½å̀•¡PŸ8̃jÚ[«°hĂkhtÔǽÏ~ø+²£÷̉¤û` ŒñÉæ»Đp·Ëñ'¯̀à†™¹öΗùÜ¿<œ²…>3(œäbfĐf˜¥¾{°hĐ·îyjnÖV9"DÙùH ñE£¶¶1fV“ Ñx˜µ­}aÖ¶ËaÖ¶ëhÖ¶§1‹2~,:ïÑĐ3’K”ë8ÉÎ̃ Ăk…Ÿ@ñ°Å“<¹-nŸí, endstream endobj 964 0 obj << /Length 1551 /Filter /FlateDecode >> stream xÚƯX]oÛ6}Ï¯Đ£ Ô,¿I°´k‡Ư†%öƒbÓµ:Ỵô‘ ÿ~—"eK6›Ä‰QC€Ø–¨ËĂËsν‰0ü‘HÑHi†4SÑ|}†»«ƠçÈ}¹øơŒøqS8Œ|=;{ùNˆˆ`”à„D³å0Ôl]ÅoVé¦1Ơdʋ٫ɔs¿›h·Å¼ÉÊẪáñ…YÊs3™R…e5¹}8{;ÛN.¨@‚³G"íGÀƠ4" aÀÛĂ¥aÁ\†"x2’Æ›Máßm\Â8b‰èb\بW×8ZÀÍF¢ßuC×Gœhø–G—g†æ&,Aó1€ºI;í~^i‚‘°0J‘’Ô ¾úX¦‹ô&7.½VÖ§ơÚ‘*"%BPdÊ„FàăƒÉäp#ˆV?ê§É”`!ïxˆNjDỈ?đ F‡¦çˆ̣mÔMZ¥yṇP8!„#¡”L»jb¿ ¹éF_˜tQ»|4+ăØu °[1Ï S#o¼’ ¿¤‹ó¾Ø´MíçM†óÂ8¢d<´1DH¹î2u²̉ØQƯb+—¡9$Ed·%¨BÇó&ÀÇ­ưg©I ́­L"É$áÙ=jrµe&CT±13dzSK2H„ Źzä:Uw§u8Å8”"JØaÏâ?ÚfjqOªg+Ïô 4)A¦‰ÁË#×?–Xó>ÛP“X,³;:v(ê$Äíbe¶*Üåy[•Ù]jÜ…ư¸£Ÿ.ûơ¤₫nÓ/°2u›7!fPÈ §< áñ@‘œơ£›₫Å¥w®€eh¯æ´w@é́ï ¸Ể ‰í*•è„ư‹ÙTfÈ;]êHB¾·–*q!"3Ú>n'Œ„ˆL$Ä‚¬ 6¤äó<œ lÚ†ÂZø”XT₫r9ÏËÚ½V+0y¹çµCwơ~›åæ>k‹—}úa7C6Km­‘›…¢aí¹"Qǘ́vßË›/¡H@M“ưUƒ‘¨±»¾±à</ß^¼?ÿèˆ;/‹Â¸Ô8KEöë•¥Cü%́¬ArïÅdÇ!ú! é)8dCBFú„‰hëUfkEIàă=²ji²_µ—ùxÊg—b·˜P0æ+ôƒD›L€í#¦¼³(÷êđÆvw±)YñÙ]É pXÉ ÷ón•Í­qúï²̃_‰kkH¥»µNÿqup<Ă믩Ïo'@¯4Ëû$ẰUé'¯ûÜWwù¦+¬>¾·+ m ØaR÷[9 ¦øNMîRq u—ég5¤$YJ`~Ü*ïk À×h"Æi~|Ođ{Yô&®‡)́»—KÓ—Ú¼._…ârhøV8u•\…ÛîŸD¶p²g¶ÜnŒîBL{uṿÂ!ơ¿Ê.áÜ)Ù9đJö¯dVÇNâ•6æA¯tËù¾f9œslp V”ˆSºåĂe¶QʶK l¯m¼YµBfªÓØÿm ĐăœÄ¦l(~¬ÿ¿l@GåIlʆŒÜcS]CrœKñ§¸‘¶?$§p)"¡oQăCm,€âÇ;”›ƠØvàÎôqß=ç6̣/8¨‹AH+µ]H«´í¡Ñ®×®³ 9c̉4~¡#ˆÑ£WØÆµhÅÁ¡ĂÑ:ºÆTKpÉtn»C<~ÀvYâûüXĐ;R=ˆÙ*«Çg{˜Öv¤¾́ï¦îĂ¥B¹»,^¸Ñø6[[¼Öß«̉¾´³ór½I›́&˳a·Ú?úÛ¹eǗăùëoœ UÈM> stream xÚíYKoă6¾çWè(—oR (úÈ¢{hÑÔ@iM'Zز+ÉYl}‡Ô#¢LÇvnºEÀvdrføÍ̀734‰0ü‘HÑHi†4SÑ|}ƯÓê.j?\½» Ưº¦£•ßÎ.̃\ Œ2œ‘h¶‹-¢ëø»û|Û˜*Ic1{›¤œ‹ø2Ñ<̃•󦨔ö_™¥©L97IJ–YLtr3{ñĂlP.¨@‚³-íWiDÂ`¯5WKDȤaÁ[“,·»¦¶êápÙøp8J‰B’u 7·I*dü¡[êá@2Ä Ü®,ꀼ=mmª"_µz!f̃ Î´“”‚ƠD´â³̃®̣Æ„s8‰”½b@TTë¼iµ ;ƯuSå]+ÅÇ%íĤ”");µ?ï‘)ªăƯÚ¾̃&TÅŸSÍĤ76m­*í~s ¯}øl–íû­ưʉth~¬¦1ewÀM÷~oö±^˜‡bnPđÀ’!¥¸`†$’Ö=4₫ÆÊ¥ñ¼Éx{H‰M¡ aG@ †IF‘È\Đ]ßàh_¾0 ó£[º8âDçUôëÅ/¡Đ$R#.œ(†ekP{˜7ËÊä‹T+IJÖmLv›®]Œ̉Å—ÅÊÜ´¤A™ÔÁÀlºđ!~9¸U$ÇëALáưubó-™%ñÄÍLgưêß±À!ƯQHXÜçÖ‡$¢‘¦cI$ 7°.gÈ›nk|¾ ‰Q.jºuñ§ Y$IW„“+ˆf̣?œûpúr|8ËÙVf^Ô¿Àñ„D\«c¾!€¬Ê´WvùÔ5×!£%¢ê¨óN8¼'g¾Ù•Íñ(¸i£àX0HØÿèç§‚ ?„P¢̣8¨ô,:úœtPĐ¿¦ªÖơ]Pô B?ÇƯôŸÈư¿ïî”b‚°¾¿¯à$ÁÖÉÖwÆ›p0À zYmÖ] 7´7<.Jhèvkăº¯&Øå…<̣ºœ¿;âÛIbAˆ ¡óÓá‘CÇJóƠÎÔă>‘Ç6ÀJ¸‹¢ïÍ2ß­·í‚±urØÎN¹çä ¡O];‘¸ß³Óú?Ü vÛS&&̣Üü´¸Ưw“Ë»©ASÚ­cGYºŸ¯aDÙà-ß!½#Bzº}ĐøZ$À3¤SxÛÅE₫H¸ eSµêצ®ó»³ñz½ Ôsf&!áÉKŒV&™?ØiÈ|–Ù Ü­oGƒGê®yÑ£N@rÅcăËç§”ov´û|û¬Îg(c/8hœ…©«!ÂQü+´Ç#®yíöXj¶PKưfưca ×c¬©NªÇƒ3ú[‡s«1”:Û'|)Ơ˜œSKÜ*¯ÖºP=¹–¼n-O _™fW•ơp[Ơ^u)×y¨®óàGn«Âvî®#÷.¡ôs Qpª_¢̉XQ²¿̉í*Íi>K™±Y4Î œùi‘́Ü@d‘óÄ.QÂǛr|îƠ™z¹ê°,̀jq|†z1$X ŸÓ}ͧpúfkªæS̉¡Ñ#ä(¥)¡í‘>¬ïL3¹øµº„l>ûú¤|ưÀç4 €æF *&×̃¶^äîÎĐ€høÈăÔ½q­ex{°/6 2˜ªHƒC@ç„ ¸¸€Á8Ă|.đ•Ûk .™•$9ïŒóU^×* 4*4ÓAjè×ÇŸ‹À̃¯ùÚø¾̃— ˆz¤₫xçr endstream endobj 971 0 obj << /Length 1809 /Filter /FlateDecode >> stream xÚƯXƯoÛ6Ï_¡·Ê@ÅđS”̣4lh†ØÖ5ÁöĐöA–™F­-¹¬ûëwü’%YNÜ´À†!@LIÇăƯw¿;’D₫H$i$3†2&£rs†íÛöCäo~>#^.Ád ùăơÙù¥Á(Ç9‰®o†ª®WÑÛø§Ûb«U»Hc1»X$œ‹ør‘ñxW—ºjjó…ÇoÔjU]ªEB%Nó˜ä‹÷ׯÎ^\÷‹ *à́DKƒô¹Ć5æf)"t̉aÁÉ¿íôv§;³₫Ô;%D¢”yÉ?oUíẠ̊¡#(#H[©mÛlÁ­,V­^ÀÏ—9ÍܘK”{#Wt›Î̀–±*«w˜pµzî^·JïÚÚ«o•Ü-„ˆ‹ơÎ?67á{¡Ư¬m» ñÔŒÅÈhIÄÀ— "ÂÙ̉€̣ö¾ê¼Êư²|´lj—ơ&‡u‹ơÚ †TNơî±Óí®å y€äz€•0oƠ•Ra‰®¹8‚hÆó€è]¾Ô…qùÎüS!Â>÷aC$Aâ!M9r1óö=VđíU„—ѽÜD QĂÑ:º:û}.ˆ(%VQos§ÚªXŸwJ{DZ˜̀̀œ„?†(_$"¥ÖF­ đs·`dÖ…4bX™cB2ơAÀÁ ¸̉c‹H!.¬*A'>˜Ÿe«OsØÓ â(O­+,¸̣ö̉Ú íY|Y­Ơ{¯ A¹0 ̀¤-OĂö¬—âë€+¹Âï°À^J•rD9kœSÆ ĂE>PFf]L¥ÁÆe ù¯{høi/6öđùœ&Ø?ÜÛ¦«3 8–`ñR·œ9ÂêJƠ+ŸÁœë®­ñà£›È p×LaŸ= _Ö&Ï`̣Vă}Î!zOU½=ÀuKHOT¥[(ñ FÎï,&Đ>"üZơȬ½1ƒ¥«‹„Äí˜ă7Ơz ,]6ơªÂ8Bö¦i‘©Á<~yă>Öö>y‚ef°9Gê vÏ÷U ú¥SâvZÍSst´W§—Ư_›Z) –güi%Âmê¼½)F˜̉Cj6|7KŒXÊa]†r}7CɳºR!§f•Á ƾ'+Ć@§u” b³¬'¤fùqN+ÉPFf#JF† ô_æ¨M`D yP8O{‰;ÔsU`dúÑ*À <çß³ üŸT‘éĐŦÚÎ*Ö₫g®ÈD¡5´È˜œ‚mRdô¤’øFTÑ}»:,3–ÖSKëè_¬4UƯ鋼¡3+¤‘ALœ̉èR •3Ư"ưÚN7ï.g "™Ó¯ó²\]‡fë&Ñ|R8Ÿp– e´Ø¨ñnêÚŸƒ¼ S¼ ÷>½œß ¿á¬Wu£6¨T¡”v¾ ²u×éq1%çHÂ^†< g²Ù]à`B:ÈEk:t[º;v®́ÆM‡?àñxSè̉8|[Ơf|XS¶$ef{8ư®^‡enF—¦nûeÊRmƒQ'“îd[Tm÷`̉úÚ÷Új2µÚ‘Á|öR“~Ƴe±[µ…VÏæPçSG={ Ó<SƯk‹ üöœ}k‹LKÉâ«Ư¶e2µáyéẦÎ7dÑî6ʶŒ:VĐ|Ôm³¾…DÆǾ´̀c-[nÚŸô¥€Ïtb¹¹†a<¼Ø(#†ƒ\Ú¿#ûÏ$뇔÷¢|ÿ6LËi/Á2+=4Đn“Œ0Å8xس (Ă0×À-® +xÛMq„wƒƯ€'»© Ô®ơóú½IÇ+¸)zÜÓaNN-^™n™»-»óTgă&1U›ÑgV½V]ơ÷©±6,sĂé¾á?¦QZ_8!á© ơ—L̉ç_8«e';`øö †wºiƒù=›̉wÏMGcZʼ¥Û¢­‘œj¯ ‹Ëx?Ù=÷éiP‡¡G]îQ—Ô_¸2]Ÿÿ¶Z›Ó, €]qñk{!Ø₫2U²Ù²0uƒSØ0kævøÉ!ŒÜ­́KOÿ•ïÊ¢óbÀ+ªî*]ùv±sˆ‰²¨CĐ TË%œY[{R½ƒQesÄ«ñÙ´ßxsèlC‘[+mü<¤¨¦^9u_!”¶ËJwOˆB›¬;‹°wjrغ=t‡»̀Dío½‰Ï-zr™k‚f§O­5©wÀ ÜLó0ˆI÷­ª½Œ¯·{v)µˆ4äg® •Jÿaz£½ ·ÂFu7½\û>Ô`øÉ¥1¼.¡a@sûKñWµñ¨áß8P!Ü s@ªP 7sÛ{bÎ 'ăܪϰMZ7æ«ăh?r´iÙùÆ@w}e..¸«Ú]q›–ü§¿7“ endstream endobj 974 0 obj << /Length 1692 /Filter /FlateDecode >> stream xÚÍY[oÛ6~ϯĐ[e bx¿0¬[‡Ă5̃S[ ­$;“änÙ¯ß9$¥ˆ¶â¦©×j<<÷Ë'…e₫±̀đ̀XA¬0Ùâú„úƯæ2 ‹w?Ÿ°HWa1¢üa~rúJ©ŒQâ¨cÙüb̀j¾̀̃ç/¯Ê›®jf…"/f…”*5³2ß®Ưj³Æ™¿«.ª¦Z/ªYÁ Ơ.çtöq₫æä§ù \qE”Ô´§̃W×Ơµ0<¹&TÉ ̣³eÙ• óơj]ÖMU.oŸ¡.»–*CtV0A˜báâYƠ;»«*˜µÇ)œ ₫8?,lÔ«uE‚Ë3àIA )‚.ˆ6Hy»ín¶];¥}€^ˆ@ùëf]E2³OæœîƠ®‚eƯn^Lñ•Xéà§ÿ~A²ù¢+gđó ÿ«ú`ư9D€F¸V+đ¿aèÿ÷i¶„Ă7%̉dyÊëLt4«³³“ߦrE4󜴈J·U³*ëÓ˪›ö£ï$ƒ%aàq¥¹7Bpoü| 6m%BËL J¸u»F(Ú[!‰d6µ"U ­° Âø̃&f´M½/œ I(µGÎ…#² ~^n— äçTÈ™c„ƒăĐB¸páư/›rY×1_ ŒE_Æ#1FœRÜGA(K´S}怙¤B5Mª‘cXOU©̀˜«$\¥w`îÆd*AÙîù'CƠ=Å!ÅD€cSæ&}`BN:Ö™içø¼cSÅw{̃LéĂ,±|(ÛïfP~6ÎM>„”™‚›p\â“‚I¨LÖD;µ4_W…Ŧ ¿—₫ĸ¼ú{Ơv«ơeØjøơj} zïE‰C·£ưÓMÙ”×h0̃®ëÛȦ+×˲YŸfJAgÜVm8-›È Ữ̀X^ =¾£¢æAñß7MW-'›m)VƠëơ¨Ÿ»ư<ÉơÄPƠ”ÙP„,Z­Ñ’EE›‹) f‡8>¨±sj‰äæ1ÄL»/ĺ‰tÎ8‘P 8¬P_få¢.Û–LU0¥‡êH̉éP·“†È»tÿIÊÂÇÅ]âàÓáqÛb” -m~æ3bư í L5ÓçpÀl®ú…QqÁX¿Ư£_ dœö++L¼"jXª=¦ăq)sf‡].‡¥´ƒkñ–ă°r PfÄ™)̃ÓC¹DÆ‚5éKâÅzPơz2ư ¡pͧ;đ^„¨b?/ÈƠ:_amj•o®W¸U42¢08®€ 1ç$ŒxĂä×ànMđEV̉¸Ôl 膠(˯ KʺÊ5U·mÖa½Ø6‚}ă çH9t-Ø€\̉1ùđ±lCpʈq.éB„ ĐnënÊử«"é¼$†©vHuDØ0u²­Éƒr%1J́´´y¬Gª#¨nú–èypÛI8]<«‚ȧQèüÊ' Ü»H^DúƯÍy»©!Ă¾±Èü÷6 ¾́1₫ôƒ\HÈ«ĐA—w @ÿ=Uú7}€ÊP…Ñ̃›P‘—dêáơÂ{€?G«o»ª]ưóAj"ô)Ôû´Œˆ»R¾h1Ü„:2øl¿|pîÿ>w^åöDü¿a `„=áxÀ¾îډ= wn»èbo½ßGÀàgÎFàEûP¼(Ÿ"^äV6/"+EÅŒïë:Üøf“:ḷÛ1&DŒ±@OúÎç@€‡ñèù”Kÿ‚ŸÆÎpvƯ$  ‰IêSsjIœÿA¥‡ .đ¸3ídÇFM×p‹»·À]c¸EăG/<€œQtE"O| Ü̉0vàmY±á[F,04èryu®<ÖB…{¬…Û ÖÂĂÁ® O!|H8‚\ø¸iÁªçS¶=̀0†X‘ö‘{́§đº¸U€w¤`Z—íÎWÄûst¯ ï¡7€cô†h1́>)@D Û{ࣼkp̃Ă²WW$=:Ôï4ră0ưørAn @¸äê(È y±´ûFnÇ̃#·Dø¢̃´ß²$¦(@Ă=É×& …ư,¤°cL:N^zửẪ CaÑ×UÙß(û¿0Y÷Z¨ÚE³ºé6G Ọ“aÍ1 pæÑˆa Đ3/|²¾ íÁf‰̃ù È«₫ endstream endobj 977 0 obj << /Length 1639 /Filter /FlateDecode >> stream xÚƯY[oÛ6~Ï¯Đ£ D ï¤ 6´C‹aǺ) Ùf́Jrºüû^¤ˆ.siĂP ¦©£săwÎù̀ Ă?’))Íf*[]`·Û]d~ñé·ä ,f’¿œ½"#•¸$ÙÉù\ƠÉ:;ͽ¬¶ƒéc,goç"·Đ<ßµ«¡̃´ö Ï?™sÓ™veUX–9%‹³“oO&ă‚ $8{¤§£ô7îj†0økƯƠ:©DXpị̈ÇƯ°Ư ½µ¿Î ¢dẠMk¼X¬µ Ü©-(C /̀Øâ‹BHÿ¼°i¾ª|\/ÉÍï—)¢0b’gR „±´!œál ?d 0úƠ‰^eq¢aƠdǦ%J MèâH‘àRoººjú®ùÖ8eŒêg1NY‰¸P±ñϘˆ]™J3) ¢L»üq°íäOßTëjÙ%À1t”ÈŒT AƯ!0¡‘,8æƒí¿Ï›É¢Äs‹̃ătưŒRj®’# ÂóäËå\ŒD„åƒH¤I!q‰Ó”-†W£Ä—”‰¨$ÎRQE: (’JvAp Á+X04Î;—(—èá̉øƯÚÚ̀M»®Û ¿S· ’C­m\É T-ภ̃·³Ú*ï©­(½‘Ă´@NÇZx/ë¶*×?¬c›ó”IÑÓ!C RíJ>®í‰¤X#N¹XAƒûUY‹€Ái°¸bë”PÄ%T –¼ø® WMƠ÷(SA„@PîOÄx‰T–H̃¢!¤íËÎ́BÎzÓ˜Ơ° ­2èOg~̃ ¾om²sa:dû9ÏwÛ­Ëæ¦̀Ú¿x½"¯éßXg²Â›‡¶‡0$Ê9áu¥ñÔ Ü‹;¯¾«Ú₫ª‚>8R1§Ê"E£’-$¥Åûs V‹;̃§©÷—>áunYµÁǤë,ŸUǾí÷I úå~ñß}˜Ûª«®̀4fë>¤̀;qƠ1ËÓís$φv/éw=†.×Đåa`c@WQ··Ơ5"ïÉeƠ4̃WûIÈ?wùW6ÿ‡c«ÙO÷˜×p^;ĐÀL×£ô@†Úa¢(ü ƒ^fØÓ'{y÷°¿Û-§©|h\S ø‚êúưĂù=ÚÏ×6•T˜WBLtç§H­†1Éơ“Sû”„„B‚iñ—c}c–·æ«]ĐÜ6»q1>1ÿÔưà̀…߸uf\w^YNa· h­ư@ô:§¾ sP –¿ơ4¢=ú¸^¹áÄnG¡ÿ^uAe¿ÛÓT˜çl˜₫9cĐ©(}NeU ­^–Tù>1%ûc¨dl–ANÈü÷}DÂÂØ¡gq‚÷y–>:`ZJ[e¹öœeÍZ–Uˆ²tT‚ ~‹BµÅ¸ªúđ ÎV$·øïí¢†ÅPû·=c !ÍëjUµs~úMµ\v溮&²6lö8 g̃ơƒÚ˜aâ*›¶¹+Ûáº<éÈ‘”"j§w Eú¶Ó̀i’MAï?g4‰ˆà2l§‡¥”HeTĂ¼†̀üI‚‘¯˜tªp©÷ƒ™ñ$ëJàI°́̀°ëZ¿^íºÎøFå7æpc̉¡Ă­BÀSˆqGoáØ éB€_́BÆئ2-5’1Ñê~¸ÂăuĐÉ¥'§,?îÆƯͲß2ËØø°Ù.ë4ƒ1^Ư£?PÔ¼ä5̉=̀̉9–äQ1MâQ¤mLD¥₫£¼²_&‰¥†¹_¦ˆå}¹-á'/&¯L-¹GnÄ·d:pK»p—&†.¥'nyá¿Ä̉®÷ˆ¥{ Aû÷]ènoÎ,EẸ́­k!đ„xQo’ÙË‹¹6é4Ó=|-É₫‹4S8đ³ÜÜ&©ÈË’̀Y£¶,÷gMkç‡ßWv±Ù#Löø/ÀƒMđ°—U½=öûîïäÄ,ímH¸G¢h̀ơ¿t\W endstream endobj 980 0 obj << /Length 1927 /Filter /FlateDecode >> stream xÚÍXYÛ6~ß_¡·•˜á-*@h-̉&Û§Í¢myW­,mtäø÷^2iË{dƒ¢²:8Î ?~ó‰$Áđ$M2ÅbY²̃aó¶»ŃÍÛ_Έ³[‚á2°üñấùK!‚Qs’\lCW›ä2ư馸Ên±dŒ¥́ÅbɹH_.OÇf=Tm£Gxú¶Ü–]Ù¬ËÅ’fXæ)¥‹«‹×g?_L“ *à́‘zë£pMCâƠá*‰H>©DXp̣›q¸‡^ϘN–$C’9ËW[g”‡F„ å`klú¡½]Íùb ™y³Û¢+v¥­”’iƠë«HÛ]5 åæ<åy:Ü”öußƠ¾<¦œ©TH(™dX! sAÆ—W8ÙÀàëCLÉ'c¹K¢4NêäƯÙs«H3$¥Æ§A"ƠĐ¿ÇĂbíozẢÚ>uå0vq½X’t„±vA³tp±ƒk­½ÙwB¤E=ºỗè|!M(:¬ç9Ü0D„§+û±æ*Ër>-Àlơá–ÉÉÙi8F™P0‹@9uk|qcÖĐ»ëß¶«¾­aá†6Oÿ́K;~]Ö h6ö¦·ox ë|ÓĐUêFª¦Êbƒl 1B—„ˆ.)3°2A1¤q»X IÓïÁ£éz(pù¸`$-ÁA2›°đKÈñ&ơèàˆ£#‰d)ÂÀ\¥Ûè}ÙUEư|™Œ#ŒƠ7™œ²q‘Å“Ơ®lÇav¡s‚(S¦~Ä×ị̈×¶Ø«º´ơ>b®œ©÷q.5‹À́©\L˜êê¿¢9%H²Øë ă¬²Đ)GöË·Gó̃ŒሉNÍyÊẲ[Üg(ga\äTŰÙz³‘‡V,é°bĂ\Y EB0ọ”ê¾âæ 1Ê¿º¸±³¸¸§*•€‡E\’wf?K’6å'{ÓvözíGÊÏU?T͵}ra˜ûÊRbÙm Ưôô+Ÿ³yû<}¹±w[?É́Nă”Úe"±'Oéz"ôă ÈØ“n± „Ñ•Ʋzà?Œvá)›™â<¦́}†¡ó5:>ío 3–ëê=&Üd­Ù¶±£ƒn% ƒgß­/<Å®ÛfGq̀ ¯ ÇçwôøhcÆM2R›¾ÜSyatŒ«’"¢&pÚN é.ơŸú¦¦g  ±c½g]£Ù)́:.™qE({\–ëºè{4—4Mh~°Gî fÀ‡Ä*,¡ó &Ú†R‰ê§8{ ¨‰Àˆ{¦PÑYPC{ Æ áuExo ×Âeâ ¸ä,K°ïÀ“ <Ù_téfƯ•EÓGNVµFGZ ₫üc‰~°.êÚI î²ßÏƠN‡6î, Ăiƒ=C…°/tị̂ F gk`SĐ‚œÚR h†=X6³{d3Vj¶‹ )™ÎĐ< đ<΂;ál{Ë̀æÊ$ÊáxFP–³' g¥ƒ£Æ•y”K1 çÚÆ:©fx½­\VF.Ă‹=Á2„"<¬m&œs¤&L'”ç‹ }”ÈdPs¾¨₫Ç2Y2YY™|á¼R1 Q}¹ÍiXƒMç¤B‘đÓ½’ÙËqZî\ÎEª‰«ư¦næÜÀ̃'{%y5+GÁOv FÅi5z2–ÉǪ7]1”s®4[úŸÄs‚y²£µăáÊĐƠI=IyÔa¯|ă”Oă÷S‹ùZ¼S̃¨GÊ› 1‘ øÊ:7–F­Ó 5©W3¢₫2h›/.);ônè ‰Íë7cT’lÄ̀$Q†é©§_!±8nd£^¹1×1́æÜ@½Ë¤µo ăùđ]8P?óGÔ7ĐÎAGwtúÊ•üd̀åÀ$Å>ẂȤ*¸Ơ!́vŸ¹êZC":hƒZc¸6ĂS4ƯÀÂ{€¢uÂơA’aa[Ÿu·'(j†s”1b<1!¿BQ»¤=Ü|ÁNwnȰ8Ûmâ¹80Vơï£Ơe !xü}ô{gNéඪ̣!‡¡Ë́–kƯW¤—k‡Ü›¢°z¡­’°FŸ¬¾£ÛqUWkÇ+&½„&F‚è©u¿uk@‚MÎ3wk«ÙW×ß ₫Ó´&2i# ]J/†ÈKZưÑ»½<›'¹s[€ó½¸ÖmSñưà0~ûó¶3*ÈôÍ»¹oa_À}Âüî™<*‡ba¨jzr¢ £•;7ëA:wîTÿ|]·}¹yD¾—•“;Òܹ¶]¸ó¸ÿ¤‹^TîdÅ`ÈlÀª€}?“úʬÔPöô> stream xÚåXÛnÜ6}÷W,úb-ex¥Úuá¢HÓØE£w¹¶­äJÚî×w†¤®áÚ›KûĐ€Wr8œ9sÎPlAá-4_èDDèÅzwBíÓúvá.̃₫xÂü¸ \F¾¼ ¶Jªºƒ÷Æ´fƯ»Ë=Q´wIÍCÓ %ˆNSs^̃ïÁh`ϱđ…ÿªø{¿́Û‘Áôƒ‡ À29ŸF«iëWÖ¦đÁÉê:ó”4îáøÉ¨\²(ÛAÖ#ó…ÄN’m=ÆÍI:¿/Œé²ÙT/BÛ” `öû„º¬ïp̣r[!¶Ô“°¢ăÛß„́*¨ö>|>K\’T¤OZ̉#´3.x% …gU<§¾â뢓«?{ bBÊTÆP(à0(ĐƠ5]là%P)Q`đƒº[H"î¨X\œüêtjê)©[`³ÓV$ªĐ®x •?ă—Ÿ«l“Ư>ec¶¹qÇJ¨„İ ÍUˆˆ`ÿºÏ2zÈè0£ư¨g!; ¢ªD7d]íË#ǿz‰?ĐZ]ü1Äă)R yI’<ˆªtâàS¥îG1́¸ y4‰ÜA†å0¦Ơœa3_ÀÛºÚ}L£¹Ó:So³µùdz|ŒÍ&1™PÚceƠ9Jk;:ÏXbNØR×'­[ËtïñŸù¸ª8*‚¢…N‚Ï«J꾨YL‹jº:àAAYSR²OÛåºÈ†„6t¡O»¼M`0µ˜B‰éYØJlư°Ll˜D]óÜ7€]Ăèé»̣,Üyß·ÓÖ°îÁ̉Ív­Ó Ÿs˜[S‡éϹé@‡40(ª¾»Dy‘BàH0JÁ¸ ûS³9Uèár­)†…ØQdßÅ87îl÷—µmVܵÁ<́ø'EŒa×>́Ö̀~½6M³ƯŃ·z‹-t„!ÇyB×$iq¤ô%ÇKß•©SÓ–àđC  g9ñïI»[×̉â¡ÓđÿQ9Ô êkH"˜ú‡äA#é,n]–µ»LØÂlM9ÅÁp¬ iù׿KÉèUV̀›l;Â\ŒNiƯ׉뒀̉†‰Îoö‘ÓåcÇƠßü‰¯Ä1R$w¿®v÷…AÆyRfMÀ ¡PdLĂ:R}‰s MF™5¥Ùˆ3¶~:ÆËN€ñÚæ /‚JŒ/0öø;̉1¼í³7Y3³V›f_´pÉIÊ“§Û´"Ôsè(“’sߪCåUq8 'ºS,íäêÂá-ÏqD­¢7KÁđ¬~ˆŒđcRÜ›!^÷¾ClsKđómè€Á‘b¨$,₫Âsg Ô‚Á$ÑzL >·…çëª|G™¼Ư׿r™ÊÈ}Ök¡,Bơ ‡1‘~̉ׯùÉtúơ VßævíÙºSÍaPkz":ÿ¦â§ÎÏWB–OđÙ—¶ÿ|̀°uâ6µ¥ Ü;̃–¥¡CIP1Ôḷôi\C%Ê™Œ]˜îÄ5D̉ ŶS…ï/^[;ï>?ʱËÊü~_d6…¾ÿRÁ6 endstream endobj 986 0 obj << /Length 1581 /Filter /FlateDecode >> stream xÚíXËnÛFƯû+ˆ®( œ̀›ĂuÑ,ZÔ1Đ…ă%l©’”÷ësçA¤F–́¤-̉d¼ºsîcÎ=Caø#QJ£T1¤X-6Ø̃­ï"wqơÓñv &Ëï¯/^_ Œ2œ‘èz5tu½Œnâîóm«ëY‹ٛY¹ˆ/gÇ»rÑUiđøJ¯t­Ë…%4Å2‹)ŸƯ^¿½øñº_\Pgg"í¬à*†0à5p•D$ŸT",¸ƒüs¹ƯµY‚ˆÁá(!)’̀6º.̣µ7efcöÖ.qÑ;ó-D¨âªnƯÍj>K„Œ?èEZ1ñÀL„séÜ…22YÔ% ´i~˜ÁZùz§ƯĂUU»ûs“ö¸jïƯ×ZçKg‘—₫âc]´:ŒĐ-ë·¸qp &—(¥ióÛ3`¶3÷¸µµ³đÈÙê2oó @¿à  çB“ü9ûD¿­.Lj Ç„”vmv}o›=x6ßyé.æ]¼æ‹.Ú{³‹̀uÓÖEy×5¨"'’!ITư›`tĂô/ê› JÏẉ*ä6Ö¾OûX¯ÂN…:Q(í}¼Ç/ơ*ß­[¸$AX•#›üƯÆ|Îí{ưN=&ñôíLi~ÑưØÔ¶cøjåEˆyôè;ṣz¡ë ˜qÂà«…Â8`U₫V%p¢æ 4¿«W°A°ª}Óówđéóô÷ÖgëïIÏ;¤MÓ³O˜íëNĂÇÉ̉ăo?uHL‚O (ô¢˜¾Öü?‡~Æé<íg[ëEјü³r%=U™M35:Ü=]qʧ¥¹ 3ïŒàG~Ơ®lOwÁ­ë‚SÍ`ÅûRbmØ 6G„ ?*OÓ¡HĐgÑÑWV¤£ú₫Ơu½iî‚@@ơ’rÓ¿bï~¹á(HVb\ï+ˆ$¨¡˜Q¥,P¸ Œ«ºÚ ŰÓ<y(‰jùÿdêÖ endstream endobj 990 0 obj << /Length 1335 /Filter /FlateDecode >> stream xÚÅXMoÛ8½çWè(C_RÅ.6Åö°‹m ôæ ØL¢À_+Ñ º¿~‡")‹2;i"€È£™73œ÷†! †’È<‘E•Ély†»§Ímbÿø̣éŒ8» ³åoÓ³ó ΂Q‰K’Lo†®¦óä2ưư®ÚhƠL2JiJßO2Æxz1)Xº]Ít½^™oXúEƯ¨F­fj’å‹2Íùäjúù́iœçqFODê­÷àyB(€×À-"|æaÎ,ä?W›­nMxH®&‡“ŒH$¨3\_O2.̉{gÔ”ˆA-°µ¬[[€ÊfÛª¦®“kºn´}Øyăé½i 9—À'ÜúmëÿT,zNP. ư¯ír’)ø‡Oß‹ơ û0ªÅV9ˆzmŸ7ªÇq8ç±!6Ơ­ig 3­ÍÎ4À1¯tåâ…-ÊÜ눓̉:ù{«Ol’ñ-C+=¨é²pLÚ{€Æ°¯˜­·+Sd‹E1ÊißÎîô–@+&$x$h$cr!†‡C5Ͳ½â¨ Ôăñ)€ĂSé¾?àeƯXKƠ¶Ơ­w‰ƒûbÔ%$âfF̣ô£9Vy:ƒfÀ¯‡ 5)¹ ÿ·["À#†Y1*̀Đ^^ád_~N0âó±3]& 1bJºH¾ưm" ÄxçÀñ±óâÂĂàß<6µOP!-!Ÿ<:.»̃¢C̃¢éE½PWö}!BPÉynbxgwêWÛåơ­ü‰C[.+úăñ:9N‡Øbđ*ë¹å;Ç0”ïŒÖ×÷»c³³!p£·yóUÀÜ[́f)\K°"Ñ’â•”†sóf5Ax¢¤œ#!ø)%¥'”4/ÖT́×4ôÖô¸Ÿ̉3ƠÇ̀.QÎeÀ"ßLLÙ¢dK0­Œä²Ïµ}3¬ÂP7Œ–ZFZX¯ZƯl—jH©c¾5,x7ŸT”o«Üö‘%K‡™ö>Ÿ£ß§‰SgˆswO§_«Îü‰F4Jo›•«q/Œ²Fé„‘9‚A7ñ}´ZÅqÖmvö|;=/Ñ#*açaä5ôˆJ(ËÑ­̉o¡Ef¶f:ÆŒCó±ơ°BRc²Û"N’!7>g:ĂË£Âát—!AưL%njµ˜Ç ÑÁ)^½4Vˆ÷Ăȧđ₫z£ư#Jû°r”ö‰€Û!g|R×´]YÉ¥®ư úÑÜ]i¤Äp$p8'ÓwP½đ€”0¯ưÎ, £&Uw·tˆ#DH±[—º< 9À¯ó!‡Ă@çÆĂ:ÉÉ(\˜hÈ aôœäˆ Ú¹âRØÁ•4ÆƯ%́¶½üÎUÛĐij9–…~á׳”2ªèªZª°ÿû¾`(ŸP ̣RÅøv§VÑM„@áT<3µGcW¹cƯº“>«¿cÂÔü¿¹ æ‚ëï®kCÉ4ßWÚ\Û•'É$̀3)ö¼7uÛßJ}\Ä ®‰>pµX́÷¤ö÷{Ÿ¡Û(¬l›~›£ÚC]1q¨¾*åC´ë÷J:X\>4GÄ•Ă|Q"ÊÄ3ç(ÜƯà˜ ̉y"´£óV鋦æ`‘4‹‚|É¢7M„áó ‹ZJÎC›Â¦£5½m® >«ŸÛ¡Øö…’'%y±VF–†â¸¾q`W฾9¬5sSéüBñ̃’ÿ"ôGđ_ÅA endstream endobj 993 0 obj << /Length 1616 /Filter /FlateDecode >> stream xÚƯXƯoœF÷_Á#HfĂ~C¤JUºJƠ¾·$˜[Ç$\aÏ–û×w–]îX¼öÙMÔVÑIDz ó=¿™Güp$I$sr*£js’»ưçÈ..~;Á.ÂtFùËêäƠ9çÎP‘8Z]ÏY­Öчǿ¦ÜjƠ')¥4¦¯“”1Ÿ'9‹wm¥ë®5OX|¡®U¯ÚJ%)‘™(b"’O«w'¿®öÂ9áˆ3úLM'êêæ$Âe ¯Q7KàIÊ8³*¿ßéíNF>XẀ­Ë¢K$¨£t©w¡çJĂ èGºŒ̣̀¸´—A÷»Jïzeoïj}cV2Ö7n«é>ו]¶åF vÙ]ÛëY£Ê~e\Ø]ªv} »˜ÆoJ]^*}¡Êơ}’ÓØmŸ•}_«₫̉ª̉n¯l×Fç(uZ¦à̀­ªuûùm»®«Rw½³L.\@2zXúK¥llËfè^‡\Á8ÊY1¹bP}]6[3Ôkdßđƒ’ eRÍD%wQ$Q¤\øçD’¸̉e—Û„âXMỤ̀ç>°+¹I€Ÿ²h ßEâ ón$ƯD ÜĂª‰.O₫¥ ¼V9Ê¥\XâÁ’W=x̃Z#Àaœ“ÑB˜wSHH™»w×,ç+1§¥Q́|ơSb̉81Î<ÇBÔ0ˆ?f< ‰gˆ°=ǵº=¤ơƒY{F§!.".&ªÛµ:¤‘¯>h„ƒÁT I2Ï»Æ#>_ưăŒ¶½ªêÁÀbÀ<‰ôÀ½~½¥8‡““{±«kă2[¨qSƒ 'ÅqÙ0S M 6wó5Öéß#Á«· Pﻘ`ÿºï6öIi7En7w@‹c´5È_6ö¥m‚!¢•Q¤†å0.lc̃>j ÿ2 D̀a‡°Æ¿m:]fƒçR‚¡ùÍA¡ªk[ÀTë56³YN63Ă¯®THpêxB´À¤‘q»¶”, ËxÎØ˜Å• io…ÛpÑX5j£,ßÁ>Ñ}r¨£…rN–§Ü"5 /P!ÄL9&Xü~«“1”&̉făÀn]lÍ₫Øø̀N7¶^»9"¸;ª¹ßCISŸíú̃YƠÜ[º¯mg¼pçØ{ G©Sq:~"Cúö®™íjË9·ûIÖêº4n´)¼Sû`";ơ_ĂÂîî”LÀqŒá´u ́ÁÆ3RưùĂË qưdgó~ị́̀ĂhÜïd*{ê“ï ¶ˆrk KZ…†ˆÔ ±£„ü·F q%2J0à̀¾Ï(aXáÇF {®₫ŒP=£n¤pF}87Sßl¨¦ñyƯ¨O¡¦R33á{r&Ïï;Œ*ø‹Úªåœ yq¬‰!Ç¡ĩÂ₫¿.z¾gáñ¯ë )ÑÅ?̃î)‹Úó•9xí̃n«µ[T­3eÜ<4í'°†?·­²€¯ü8PX|6Áñ¡»2–î§–“ç…ƒgR9bâ9Ô˜7üĐxS7M=(è₫ëaîOÏÅĐÙ9ê²ø­›™ÚÎÙ1X»”?s•û!‡ ɸpfïï@¶]¹Ál¬Ô:Œ~ÖP/h~ƒàODí÷®UO¿ ¶_†ÖÆ/€k ê cœüF¸– <œ) /œ=×:ŒÓ`Œ–ß§µ==†P₫q£»úâjÎ6äi|‚¥¤øp(鶪×÷!°ă0)bü$3(ÙSÜÙư‚³ăÂ¥pt,ïÙ~$>}öL• ‡.¡¶ηNQAå²íèEo1–ºS‰®§9{Ẩc@₫Ă&T·ƒ.Ç’Nă€A%Çh‡Á&¸Ü&#>?À&’ÁøGL4sÄ)_b“{h¢ˆHêC“/`èNGV48Á¸@˜í?"TM9 (ØP ̣±e€]8Í7m,¼ï9ĂË₫Zn”ư‡¼ Œ‘;¬Y°`âé` ́r^X/Ô¯¼A©RSÜœ4»Aû7 JÁ${×î—²ø…ÜA¯ÖÓ<¦¯ŒfƒÁàO#eă>¢lJ]ƒoöY殀Ês5Q•„úGûƠ$æÚû(oºSUj;)ơÀÇéblÙ–uoå™Üÿk̀êX endstream endobj 996 0 obj << /Length 1418 /Filter /FlateDecode >> stream xÚíXKÛ6¾ï¯Đ-°ậ)J9m“"Ú¤^£—$(d‹›¨µ%W¢·M}‡/=l-ÖYäE€˜"gF3ß|3-‰0ü#‘¤‘̀Ê™Œ¶û+lw»‘[¬~¸"^.Át"ùíúêæ¥Á¨À‰ÖwSSë*z÷±ˆ̣q·˜¨t`¹•^đPH§Á¤'¨˜È¦r Ê0èü8×ú,îO„½I:àɦ#“€¤‘:v^oHN6&Ç îËx°eÏỒcçpU¿Ă„ÆÛT %¥–7)ÿÉÀ3k]«¾₫çR®AÙ9®A•MƠ‘)E~N&2 G¦çNÈÀd×Ît^XäĐ”û§8̃ë¶ ̃™ëæƒ[sNÂfjTac’̀áÆTNü»Ú>µÏĐ³CÙƠÚâu©¿2¼\Æ£²{ÊÓ KºQ—'¨ ¿¸7Tsóºªn~n§,€¿uïT̃²|‹­c¯—Ê$đq˜uó0=r#׫_i·é̃ÉămÙ{1è+ªék];?ƯæÀ‰mÙ̉ML—›M—óD `×¶ÔH́•tëĆÄC™đ®÷tØ)mâ\ˆ¬mvŸ.M,pé°©uÿÚj=Zˆ}T₫b `Û»ó4óI§ö—!ñÅE/."]ïU{Ô—^6™À,œ¦y˜̉Ơ—ñÅÇ̃=»+ $ƯO¯à©L+•,₫5ÉÙÄDM‰{Ă^•M?Ó̃́Z ÜÖ`ø‡«cØ̃–»ZJ́Oåßỡ£>‡o <©nă¸F¡»™!ÀsÚºƯĂ1¹¸têOH“Ö-đ¼zí™Ă礙Y\èÖ·Æ!ÏîÚTø…¨J •Óíë¦Üuª¬>=æ̃C̃=ü~½Zôn>Ayï(E¬ÈƯ[^ơá¨û%°‹ƒùQËt5/&ÏÅ€ÁmŸîr×·Ï—́rr^âăI¦íḿÛ“'ÿfD" Gœb$̀|øö=*8".£¿¬Ü>bˆ‚vÑíƠ/K3/‘RcíĐ̀#í®Ÿáj½I?(½ŒÁ̀h;ưỒDµÁ0jƒŸûÄ ¦KÁ`Ä2A ÛÅi8^âሓ|ÏÜ%ONØ’0ăæ'ÁûM@½̉@Ÿ‹,"BĐ!"£oBÂEôGù Ïrü$,äÎ0ÏKÉ©U(§A¨R÷c¥Œ2$‡Q?È\/YRá¡?ÂT¬~»N©%·2$:ºE–ˆ—$à÷Hèµ*'—Åpfpl‰#x^_¯IyKåÅNaùL ¢,‘¥₫¾n›æ£pMă3fêí½ÉÛEop]`(΀¡$b¸@™$ŸYp³·Â‡ˆEĂ˜ầ7‰I"Oˆyîî‡31&íá¦ÇáÅ@Ç”™¯̀¯¥íô?W@ă9˜OÀRûë!Rư,G—a„)“ζ$ú”–DI†äyŸԒŒ-₫pGZ%|ßƯ~VWZùÿnWzJSZ™¿Ñ4C!|‘ÆÄ¿âÆDh(dê 4&c ₫ߘoL(¤å_¢à endstream endobj 897 0 obj << /Type /ObjStm /N 100 /First 864 /Length 1236 /Filter /FlateDecode >> stream xÚƠXQk7~ß_1ÉËF3#i Ú‡B[BâBÛ4×^‚ÁÜÇißO纱­¯Ww?œ¥•ggæû¾iw‹' T¼ y$ “ B¹`PâÈ3±fŒNlFÙ)Z¦èơ—…DŒœ#)3•@—‰̀"Iĵ3F¥$u,”2¼Â43‚qơX]ÔˆapVr­ëÈ,ÀIabÆ…3̉`väÄQ„JDîˆ,ZAd܇X¬‚±Ç$!gçÁ£'ßÉ 20ˆáîô’à¯døË˜Ô¼¹²²#J ˆW”"ă &1ÊàH¹d*°Pq’ͤ̉‡Åh5qeI1Q̀•HÀ‹W®đâÈ· €€Z ¦ƒ+ ^©È•Bä"•0Eª¢Àf0Ö €uÅjH«2‚'7 ƠnRđM5µbƒ<{&P©ƒ(‡$Ư`ÇĐÏS@*ÙTCU'0ô$¤V™B,MIQ0XÉT`U3÷?%C d¨6=́ ¸çZˆÎ( ‹©"1‹¸Ă³‰Cdh …êf6̉R‚́Àe)8d²àƠhM!S RC Àâ8ôJ …¸Rtb5m E•$çÁ¡V²Z訂”̉€º©ªå(Ÿ”k){*µ¼ lª\î‘r€ ¢2+̉đZÍđêÈ;K(Ă“¿/N˜ÿ<ŸÏṆ̃ -_®Ö´Ü£'fOéùó+›ÎNÎÇÖèÅúĂç“ƠûKËï₫@¼—?ÿ²ÆƠxvxZ§¯>ưuzrTg?«_qóĂêx¼¸tr9…Ű<øüa¤å«Ă÷ă°|±^«óh±€=áơ°|=~\:;±„̉Û,ư4Ÿ~¿¾ ·ƠÆÜªåEñw<ÁEPPÍ­FÙ£·u×À -ưíw›99î Ơ§ÓÓw4ÛGTáíCëri¾‘óSÈăf–¯ÎÖGoÆsz ˜{û´</Îé_wà—?s'~“đÏ3KÂ÷ÛY*‹ºû̃gǹ,”F{ªÛ̀ö$H­Ú+Ư}á“ë œkˆg#óYîEVæuÍV]zº,†N`‘'µĂ³ƯïÑZụ̈üsƒ_{…‹FÚ3 –^4Ó΀yf)Ë¢à˜ºÏ.ºbŒs«)„¯.đè"WÿÁÂU%î×'T‘> Ú=P´S±-vÊ-ø7ˆùÂÅløíF)¹~™TZ·̀ ¥•uJÉ\¯€;(»Vwó7—3m÷` œ)÷.Sêä&cưí£í~¬½û±ê¤ú¹e&"‹hơss—ùú^4›¦̉̉”D“zCSîße®11₫VJÆÚö±ĐÉ…ñV¹¸{ûØr]XÛ>&½\LkŸ[f1̣¿ƯسijÛÇzÛÇúÛgbËl÷%qË…wr‘ÂvÛgBỲ†¯ ü{áˤ¹ef…9•ÇP2¹å̀ÄY* g雟>sáç¶c’wÂÏawÎ.Û'·í“c/2óÙỡ§̉sѶEîm‹œ¶ûê÷­^ƒKû%"—^.ü›Ÿ*Ûá¢ư2]¸“‹2í“ó-3Ö¼üN˜̉~E)ûR×Àb;+Ÿ~đ¶•JéåÂç»·­äÜÉ…ÇÇù®çmøÜù¶¢†j endstream endobj 1000 0 obj << /Length 1631 /Filter /FlateDecode >> stream xÚíXKsœF¾ëWp[eÆó„ÁU©JäD©<Êv¬­ÊAÖ±# ‚ °Rùß§ç˰ƒ#ûàSÊkaè₫úơu÷Ă?e4Ê$C’eQùp†ÍÓîcdÿxÿëqç8˜̀N^lÏ^^ Œrœ“h{7µƯE×ñëûb?¨n“0Æböj“p.âËäñ¡)‡ªmô¿WwªSM©6 ÍpÇTnn¶¿Ÿư²” *à́™HÇÓ'p%Cđpi°à.C"l“ˆ”Æ?¶€ÆåPlà¿Ç #±Aư3i"F,åF ăBë¹¾ÁÑ^₫a$@ß“9úqĉ„¿êèế¯’ $ ó!ơª«zXHÜvĂ˧® ¥ë©Ä30™2”f¹ưú|Íæ¾fñeU«+ Í"BP.Ơ¦}ÅS€h¾m·ŸƠ;eéü¬H—r<ùĂ&!Xàx†-ÅslB 4ăñp6€# !s‡ÚÛONq>?C$’4½‰ÉĂ“»â@ùA§ ú”¤ˆBpˆä;û’xƯ¥Ođ;uÜøö0̀B ¾‚N ‡®q̃…8Ëøđ £}k|kÛw(<…¦È'/ ª ă"‘Œù™a·MèÈ₫ÔÄ0€• ‰̉ÜfWêD\ÿÙ»â¶Vf„µBSN7IqÊÄ’ø̀ ¡_̀2C˜ËSªëTuBÉ ĂNböÅpăÓĐMˆ©<9/BB<¢ZÅ2±ÈmqØuÅÔ–½ƒ#JÈïÏ×!¢ç…ù˜¿k˜÷]»oRæ‡ù9Ư¯Ư?ơ!œ3^÷[Í™́¿û#̀„RHŸgßÚ¦yS³Ÿ´6ÓÓTwW”*H`ø›Ú,¬b1–q1…5qưä^Y*­ ÷:<±ä5ÁĐ¯³Ñ¾ººªù¸̉‰¬FÏC‹zöQ2L×N_Î 1w†;¯îEºù(t2-‡¶Å Û™§›Æđ¸Qb–vPÈaÆäÂ4ó¥ñeg=k ƠÀ^¥¹XT]ò;0†-D¤'h—4­ñÔŒnl±âœƯL‡Jơ¯Œl¦ẾÇàÚ÷Ƶ2'ñ˜¸ºªtwæuîÛè„<µR¶ƠƒjµV"„ô¥ ă+_ÈA7S•m³s“@ëöÚ„¸̀scâ“6²¨\ƯµzÜØ9!èjh÷ "ä8]H3]Èx\Ç\êáü­9?Wyè}kƯúưÎ ÄE Ø­g3NMĂ%bœ7m£Î_¸|3=h ®Ưî> stream xÚíX[oăD~ﯰx‰#áYÏÍö¬„Äv¡h°¥ â¡Û7™4^9v°V˯ç̀Íñ¤Î¦[ÊUm}™9sÎw¾s3bøÁAJ‚4£(£i0_ŸÄúis˜‹‹ïN°]ÁÂh°̣tṿâŒóÇHijåPÔl\…¯Wù¦“Í4¢”†ôå4bŒ‡gÓŒ…Ûj̃u¥̃°đB.e#«¹œF$1½}̣í¬?œ8£ÔÔ­>¢n– œ‚L’ ˜3£̣OÛơé‡N¶¿N36E×ÉJéđ%A„)›•Ơ”dáv­₫̃€âYh ea½4ߨWJ–¹½·̉ôw1™/êªü×XŸ™CHŒXf¼́êÍiÑ8:“ög¶°₫F¯W§tµyºm¥> ö…Ÿ+99¨¥y°8Ó<^Ö×_üí¶ .>‚ø¡ü3(9…O§¶kúe.Ë̉™Đä¶»V·ĂcĐcá0_«f@>r<ơ£Ak A˜°x_Jéè̃Ö/Ç̀„X̀˜èí¬À´•vjQ-k?)́6©ªŸ$ûYÁ“ËQJzøú’jŒÉT1&©X:ˆ<†(KL̃Ä)C C⥰•ºú™â~y®À~sˆA ¤lÑoAØlúºÖÍÀú øw7¥à.74üÖO8Y1ˆˆ¦æ€«ë8XÀKˆÄá´{½t(•%epỵ³™|]p¾äZM­ í¦x±œ—µăÿ^¹ÉRD…kG¡†7²ËƯd8NåæŸp¨–ŸÇ9,øĂ"ăŸí™úæưh½ÊPFÄÑ’ ²½¤óZ)gĂẹ̈ü‰¨y]Ủà2’#p,PœàJáûñv’PD ›xùG±‡<‰=$…@ Ï ³€7;öÔª«…ă«ă ú̀ª7N)ßëL@w#Ặ₫P>Mø°ï{] ëÅv½6™}D0gÉñ^…r˜ü}f¾5)QV>;é#ØIc:ÎÎưcíZUó˜Ëm³•+hnäû®¹SÚ¼9ïÆ{ræơ¶zÄw†kĂ‚cdH`?£O+ß'ƒÆ!4R](~ !ˆ“OJGÿ2'ÔóW6ͺ½•#ÏâṇWÄ₫ŸwwDbŒâŒï,Ê£_ (Apäˆăörđpz^6ơÚûNĐ÷sz®î?±¸îä́¾†Ë endstream endobj 1006 0 obj << /Length 1331 /Filter /FlateDecode >> stream xÚÅWßoÛ6~Ï_¡7KÀÄ’")J û‘¢}X»ÖÀ̉<(2(³eO¢tư"%‹6ki!@œÈ§»ïî»û$†ˆ$EA¹¾ÀƯÓæ60|~wA¬] †ñẸ̀çùÅ›K΂Qs̀—cWóEp₫rWl•l¢˜R̉·Q̀/£Œ…»ºTƠ¦Öß°đ³\ÊFÖ¥ŒâDà4)®ç.~›ÁyÂgt"̉̃ún–„" x5Ü,ED€Ï$E˜3ù}½Ư©V‡‡ạ̈qr8ˆ‰@)µ†››(æixoM:1¨6–Uk P˜l¿|zo₫ï<đđ^–QLB…|Acë*Ø„mơôEMJDÖGư}·’,„đ»ç`³4"€^¬v̉BSó¼‘ÅiXøsü«\»•zk ψ¦m`ƒ`ÛȲj5˰L3”ö`÷¦̀E¡ Ïe.¶¯ÇÉSăäăNăKí×[A†2–÷ :«”‹›rÈ̃¼çd_nvµ&@ùQŒ:PƠÙM§ hH(uÓ øËɆp0ɦY··^@)Êíé6°¶P¡vÀ˦1@Ö²m‹[é爃û¬çÈö.Œ#bzp’đ'ƯsIXB‘áă!¢:';ö³LRđˆAôgÆô$_]ă`_~0âó±3] 1¢kº ¾\üá›w’Bp®$rÛ í¶z³|l*å©L ư¥N˜í³+P0:V0^V+ym¤" åœ'†­@ûF¯wë›oJöMmyX64ÅÀ/Œ`8—â1¸^eƒÊèyơ!ĐÀ£ÍÍư¾Yö6$•́m~đy2`î †¨.ÁéñÖç(‡It:óƠj «á‰’r̉”O))P̉$?[Óô¸¦®·¦çưˆîAzºâA æ%\¸ ư© ̉uó ,e ®Â“̀±¾l˜¥Cû…ȪnU³E[km“cù<”ØïÆ’³ÿ}sŸÔ`gy“çí~5w=;}ư¼Ụ́å¾åËŸ(#Ơ®©me‡Ơ'ºƠ'́êc…§`ĐM÷P%k?.ºóœéÑÂáÏY84oà—YNö çVªWÙ6zœJåÓEFAƒùá®p¹²Æd8˜´h KŸ'WOnA‘H„sèư2,+¹Zøª ˜g/^zT…ïÛ Ûf³•úæ•t8ærV̉ ĐÍ’₫5s'ÍxéHv UƠÏ\?:›½ü¥Z₫”w±;‚“…y_.W“Á,Ń̃Ewe´=îᜧ'¸_ÔƯIVO?|<è_¾éÏÂ: £³&ĂäS¸íPẉƯĐ &¥ÚIùȯ\í‰k¡ âöI'¨„í›ĂÑU§•'Ÿ”°.Ö̉eøØ̀Ü;€¸°OƯëZVM÷øOà?‹}¦!̀|€9¸n²' —ư½Ă6́¨'[K¯†ư—^'̣Ä…ºó¬7³H‹â¦Rp¿9d̃Gµ/,=ÅFç„ó`́}dV®Æ™:6«ö^ÇÈiÎhP]wvÊ­S8·¿˜x¤îĐ›\ܦ™U‹•¼«nïfÖ°=‡èàưq6™‹ƒôïV¾HÊÚÑ´ơÉĐ^¯K5>AJ_1aM«äâV:Ù²pÖÊrS/ºo&sm‰hÔôÖ[ȇªW½₫ơHŸA»'z&GU»öy¡Í»ƠéÅ£>¬ 0̉ÊŬ—ÛÉuêE endstream endobj 1010 0 obj << /Length 1505 /Filter /FlateDecode >> stream xÚåXKoÛF¾ûWđ& 7û^2@¢É!Ic9$9ĐÔÊb*‘*IÙp}g¹K+­âGƯZ0)r8óÍ́̀7³K" $R4R)C)SQ±9ĂưÓæ:²7~;#N.Ád"ùÓåÙËs!"‚Q†3].§ª.ѧøçU¾ít3Oc1{5O8ñù<åñ®*º²®̀ĐKƯèªĐó„*,³˜‘ù—Ë7g¿^ÆHpö@¤ƒôÜ”F„! x ÜT"¢@'• n!¿ÛuÛ]×û‡̃á(! Iæ$?®tåIJ©#(%)H÷RÛ¦̃‚[i¬›n—»fnà’á“[#—·66­ùZź(?cÂơâ…}Üèn×T6°ƯJÛ››¹q¾̃¹ŸơrxŸwö«m3'ñ!”ÅÈ€‚h)ÄÀ—BD„ÅRƒ̣æ¶lʽY½Yy°›¯×öfƒ̉J±ÑÁÜ₫l»fW€r\€ÔAèü‚üêQ]h=˜hëW'"̣lˆèuo¾èrặù§‡ ûsL¢Rr$3Ióé đ̣M„WÑm/¹‰¢ ‡£utqö{¨ˆH’^ÍR ¢Ư–/[Ư9ÿüLLf惄‚ê4³@ê"9O„¤½ŒöÀåfÎHĐ 1˜åÁ`qÀÏï3t‚ßÇCd¸èaœíñ7:_„ÂMSHL~²ÿ§s“[“Jgñy¹Ö_¬ LP&íÀL¥r9¬Ø"W­!9•ƒâbƠIư07¥ïQÍ%ä1aƒđg,pÈ4,5ÖW_CH 42QDÂACưÿ@ ±íe¼ ¼i$À#ú¶üK‡7,î fB”0ÈMÙèøØ9—"à’@ÜüâƯ‘™—M½± rñ₫µå¢²~^"qg˜r·Ñæ¾2|ÑËV(Dà‘W¶¯«IɾÑ@ê+SÜñ×T’ߌ Rœia:¼̀jñW]ô˜2 ÙMœ¶i(÷«s#9<Æèíncœ¿ŕ=í+ü€÷¡ÏÔCoÊÈôz̃§Û/z™ïÖƯ+û„`³âat¶&¶ă`4Ù=óRĂo–m ˦ÔcY=…9WˆS₫”lT‘Ág×R‰‘}’9$#c§'Sâ³̉Cä!‡Đ́›$·‘éücĂ]ˆF”o*cˆÑQ⦟”äC?Éï Ù£èưÿQ_‘†Vi¸)&³¿„z0€à÷÷ÁPcư”Đ.tçĂ|;Ơd́ܧP:•†CĂ£₫×Ù=±@ʪị́~äplHÚ÷›!#4Ơf ˜éUăqS­gbà èÈ@A!x́"Å:oÛ‰qĤß埰er!¬̣ö—ùX×~»ăTÀ[4̀诃Q··ÿ`GwĐ¿ =́ŒÚÚ^¡Ëªx׺ ví6%ăHQ5–ßĐO4>±'›.ÉÜN¸§=µ{lưí£ÛÆñx“w…qxUV×Á‹«Ùü(ÊL™5¹È^f–̃Ößlàœ™¢ĐÛÔQŒ“ƒ½í6/›ö!ơú¾×dÚ³%páRŒq”>3Y4 E*hŒç1Ư É.ÖÍÁ»‘mZW³Æ©?úíÂ…ÑÛJ€Üv‡)³«²ḳî)ĐÜ—÷¢ÛÏ“÷£’U±ºdW­^çMiî4Z¯c¶z•Ñ« TvƠµ{ñ~;e ̃ÓY¹XëUy½¹çNKÿ¬ƒÛÙSă°Ê[ư¼¾‡₫EơgÍñQÓvzq­g#]̀Z]ÔƠ¢ƒNms¤+«ô±ÇdoëJŸ8̉±”’ïq¤c6“øYté\?öH'}Ê"#(}íèÓ[¨$ư]NtªƯæê®Ø›aa ài:9Đ 0ÇË 8L”đ)§ßïLCŸ,Î4äæÖ )îWÿGRăhø`ƒC%©Çltơѱ†9]nܘc½?Ï0¹ö7© ¼H endstream endobj 1013 0 obj << /Length 1386 /Filter /FlateDecode >> stream xÚíWKoÛF¾ûWđ×ûæ2@¦i]$)’Ô1Đƒc´¸²èJ¤JR6üï;û Å•èÄirè¡ÈÁ 5œÇ7ß7;K" ÿH”Ñ(S )–E‹Í ¶oÛ›È=œÿzB¼] †éẠ̈§‹“Ó3!"‚Qs],§®.Êè2~µ*¶½n“”1³IʹˆÏÅă]½è«¦6¿đø\/u«ë…NRa™ÇŒ&WoN~¹ƒ *à́‰™ÖGé*†0äk̉U‘ |R‰°à.å×ơv×w&<—O‹ĂQJ2$™7l®“TÈøÖ›8qÀ;˪s®Ú^»ÿ["¾Ơ‹$%q悦̃U iáü•E_̀E¥)Q­•Ó7.đ}[ơÚG Hư§)ËÂÄ9x¿ë'PˆÏ@Ñê~×Ö¾Ê:¡*̃mÅצŸ±ë?›¥3¸6½îöYơºÏ‹pÛ!“Ÿ„ül4è(Ê ö4₫ÑTFăT îFb=0çï‘D‚G¨JXZ2\^ᨄßD ˆyoM7Gœ(xZGO~Ÿ£ ‘ qa]%]BƯ¶:µØ¾¬Ës]”³½Qb¹´•0á¾)°©X|V­ơ•s ³ˆ” A-̀P™Ë ½.œÚ1‚˜©÷Cb´g'ñ4»œ!FùđÑ',đ\ QĐè»çë̃†(¤èÈÁçsn<–qßî s*J¡&9‘9\‡ ™{x`ÿ0¸åƠ¥{h€Yq+è<3à+l̀iÙ6çÖKÇU¸³rnái·ÑæÙJ¢Ÿ'8Î=døz‘ăÆ…aÜú ?Í‚Ḯø™>ŸĂàk§á]ơëƯÀ C‰G2ʦ4fǿ¦è~¶~¡̀…—ºWúoMQ×kíU>Ñư#j÷Nđ8bæÄÇÙk ÄN@º{ăPPºGرÈÅ‘ÈGÖ\Î峂-̃6mÿç¶èWs¾„D\r¹U98û¢È)…®ñ₫éi8‚HŸÏ9 &đj›m]lô\0%äéó̃øº3êû¾d_<(7K†„y¿…uDźLBf;;Œn3¥u»,ó# ÿË)íâBWgVœÁø“ˆÁzw°™@¥ĂbẤ),&aL82́\a?D'$ ơ$–#Î)¤—Cå+í Ü«RßUĂóXÍ©uoß™Ơæœq°ï=lƯÚç~úØ·U}ƒ`ơ°_/½ưǼ|åà|Ýà°\˜.“Æư}v qO¡A)~60öჃ逭AáÜp‘j# †™²Ơ€g†Œ'¬ œBŒMÑ4´²_ZºAÛ;ëHf;Ư{s¦EƠv¶>³`$íQ+‘Ê<Ñ̃Öqqï‰[̃9w>Ù±ûJw/¬CSÀe¸ƒY,OÅḯ£=öư.n›n—óqè'pê+é™t]ơmÑ?æ«w°×´Ơ¯óĂOÁá8ñ™,Ö…daªùËóh]ÀJà2ŸĐMØÏWÁW²ĂoưƠ²*×zUƯ¬|‘₫âĩ®„feRàAn«¢Ó‡ù|&knq{ë3ú„ oÇP—7:̀­Ó‹¦.íû¹Ä…7SG|í^ôÈvbLđ![_ÖĂ ́úẪĂ=Iæ6e ĂcTˆ–++Cøă)Gág*"P\¾aÊQ¸_äpÿ2$_®t\ë¢ë¹d+N÷VZæBi¥ơ„[đÅJ)SQÙÀ“@w,^6kOM˜’Oµú¢öz„^÷;3sáux:ü]tºtîûi¬áâKdv 2+uS¯̀ùŒ¾Û81œú‹·Œl endstream endobj 1016 0 obj << /Length 1499 /Filter /FlateDecode >> stream xÚƯXßo£F~Ï_Á#–Âû{©Ô‡¶êUWU­¦êC.ª̃ÄV1¸€Ưß™ƯÅBçÎW]«“. fgg¾ù¾¥đFEÚpb¸ÍYêî6w‘_\üpFƒ]†ÉẠ̀Û˳7o¥ŒhJ²4£ÑåíĐƠå2º¿[åÛÎ6‹„só¯‰2~»0"̃UE·®+üEÄöÖ6¶*́"a:UỲùâụ́dzï/÷›K&‰üÈH{ëÂ5P >™"©>䢬!  øï¯­[×ẽ¬;¼ñă¤&*J('T̉pĐÑS₫¼ ç_/K»Zß­¼U²ƒwÁ Ø=·IvÑ$3r6¶ŨÚ×Äắ]ÂïRÅy¹³!¤÷)Í‚Æí"¡qg—wv\k‹ºZºûO„Ûtđ€ *¾\ë CÜæEØ}Ù¬ïñfŒá³pù>•icóe]•`MqË7o ‹à€)”+—PáJ—0F´2>(5¡t‘HÅâv»î!ô÷”CÁ)” „§QquFKøñÇ(%öxp¦›HA ¬Êè·³_=vÆPđ9_½}|I¦Hc&#”ûxEïƠOu¾̀oÊ)è ̃÷Åup¢"JI&%s‡æ̉•IË=güs°£J‡;*xN°̃s¬ôĐ¥ ÚäàoÎ5İlà‰Î0Ñ)1‚>‚aN×­Bơ‚Çyµô¿5¶´yÿD̃Ă²Gm‹f½íê†̀¡"ăá]µƯum6›:đ*.& MRÓ<éñÜvyƠC¹¾s¯¡fŸûЉ]çöÀŸf¦IÊ#©$àL‘)ô˜œ0ÍÇÀoÎR$TY*A²Œ¿â„E™·-™o7ΈLBd4ä÷—]7H°|&Á?ו}¹ơ Ùm,Œ!™:M£/¥C¸È>/wqv.¾ëKUV½Å2́̀x‘£é̃ê|Î…²É}ƒơ®êæ̀\gU7c èÔy–dœh©#.3¹ze-ÇơaèL8W4¥’ĆwmæĂXåeé—ívMå×>í0]np™×.ó‚)—;´d̃yÚ…mÛÛ]Y~đ†8ZœN1ëh²®æ¬I´PCÂs˜Ë&ă{ÆÉĂÖ‡’án¿é\àă&`. té„C¦øYÙMkKßkí~ ;U3t?Vd-3ŒîÖ.¿äÇømó¦Éư» (ÑSr³¢3ºËĐ]È€˜Sè.ú¢&ĐĂ¼)Ù ïX>¦Â[Í)áX0‡8n¢)Ñ~ܤưix@Ê8"7È—uP€d2Âđ˜FwT—U·ÅˆøÂåŒ6ê¸èÿ¬L@ 2} mDWàóiă³\’Ṃ†Æçû¤ÍkZ `Hs>VÉ›¡6Kg«1rº₫›ÀëÆ©$û‘*ù{ø¼P¹Kiñ×E½Ù–Iăíø<ơ1 >¡À’B~˜2ö™q®ßAL]œ^LqÙ‹)®]q1«ªA²đw¬ ₫h^î ƒy;qÚX÷Ư–Ư<ʤ œÉ#&0ß³â…MAÅ̀Gq„ Q‰ŸŸØIT}©lXŒoªåÅQoæ4bÔ,ŸzËœd\>©H£@'n qôA-₫Mezh̉&™–æEmb Ù́³iÓä»4@àªĂXßæ›ÀMï{o¸_Hé>§¶§ù,Å¿4Í3PæTḄÀ“̉ô3*̃y“y_™z‡ÿú/ endstream endobj 1019 0 obj << /Length 1352 /Filter /FlateDecode >> stream xÚåWÉnÜF½ë+ˆœ8€Ùî}1 ¶1Œ,²r²uà=œ ₫ûT³¹‹²¤± mĂb-¯^¿ª&†/((Íf*H®Npûiơ1đœưxB:» £‰å«ó“ç§B#ƒ ÎwSWçiđ>|}ï"ÆXÈ^l"ÎExºÑ<<I“•…{ÂĂ3»³•-»‰¨Ẩ„Œo.Îßœüp>T ÁÙ3í­o¥«i@¯KWKDø¤aÁ}Ê¿ư¡©]üeu8ˆˆB’u–¿ï!]ú"XX’ÄÖơîûÿ“MDẬjŸÛ¶P>óÅÖû¬/îÏ!cÊ4bĐĂIˆ ù¾¿ÀA ßqÜ´–WCRÆA¼;ùm­”SÄ©n]qêS½©²Æ¾,̉3§°ÀđMº¬/ă<÷‰U¶9Tg×”æ̉z“íªüÜØº7‹Säáqhrĸ¤.0€ƒÛÈäö¡2›HH;<^ÿ N]ßÛ}e“¸±i›Îàq́­1ƒ#D¼«ïJđBä‰7đëzĂHhocJ$xÂ$‚ ÁØS±zP9âDÏAgB$€)ZW´µIöÏwI^Öv,T+訄 8D—₫•÷À}6å> O³Ü^xR„ #„‡“9îr iµïV¶'¥œÓ Œ¾Ư8î‡Ó´$¦%’Rôæ® k±9TÉz£rûiÍÑHS3ñDÖ`ˆ´Aà;,‰èDÁåVûêGR¸S…ơĐxOf¨¦Û.uY9.„ŸÖxª‘×ø‰‘@ô ¨úZ#EÉH ˜ˆC}¹J#Ư+@ ¦1¤¼ÂFƒ€ ä£çYë¸kó(¤öú1$XTB°£2›ÑàŸ/Åñk´™—̣l-58ÑăQûf͉á,²&Éê™UH›¥£y]3Gwăê¤ÍôÇ‹ü_€-Û½Z£@Óc]Èá)6ö´Åª•ªn8rw†»AZ¶Û@â†åî‡m¼Åö39sRg«ú®A7QªŸÉ bÖV¶D|>{`J±A)£™ºÚt‘8øÈ’Vư ÿ¢‹eŸ̀́0 c7°0 ă4ÍœFǹÿ|åÅU|e]}~Ù«¬îV¥ă:KÛÀđ¤Ü›‰Á¤Ù’³²H§ºăpM â‹@Îé8HªƠ|ØÔæÎtô]”ÍE„’‡æÖDlĂ:ÀË"ÿ́Áô¬sè¶Å·Ÿ•àcĐF+ ™OƯíÁq°ßÅo²~ëÛº;́ØÜM#hƠư$}ø¢üsYô+’ZA+D7Û̃ÙnáŒóº|±æ— ˜"ƒ’Ô¶Êâ¼[«­nCéíE€³0)Qæ)çJj}k˜̉z~¦%­‹}̣m§ñ6n—ḳ1÷ 3œVư'!J©%ƒâ:U9~WT ¢îƯ½çl‘fÅGÿIæ.XPFwǺ¹̀Z!¾\²D‹„u{3ó®b/Ö‹¯Ü}çåơ6̀8Ë{„¹“³.xƠ´×¢ñ N0z‰ç DçXÁÁ!co:‰Ïº‰Ûk´KjÚ™{ ·€nhưH{$nÓßh¸MĂ%UƒPIơÈËé,: g$”j] FQb’Çu½~Æ L}AÙ×Èú’>Éăô©;Ñ^˜§Nüu"^”OrÏu®ˆ¢·Ôi6å₫&yÆœ«‚rŒx*}b÷_eÜèùựä2™9  Ÿ¼ÿUY€€ˆO Î&̣ß! ê«d¡º¨Gơ/‰‚j endstream endobj 1022 0 obj << /Length 1394 /Filter /FlateDecode >> stream xÚíYKoÛF¾ûWđHå†ûä2@&i]4h›ÖĐƒë-­l"©R¤ƒô×w–KR\ze=¢ÆiQø@IÜÇ73ß̀®±ÁöbâÅ’"Ico_Dí¯Ơg>\}»u!, G+_Ï.^\rîá%Q‚½Ùr,j¶đ®ư7÷éºVURJ}ú2ă₫e ™ßó:+ ư†ùWj©*ÙU’8‰Oyp3{{ñƯlPÎ GœÑ-íW?2WS½½¹D ˆ3c.E âAÈñ¿)Á4âÏë4€ÇC@±¯z›₫aÂ"ÜJ¡Œk5×7‘·€—o½qP÷¡]{ 1,áÓÊûíâW—1XH",ƒêùúŲ\ƒ) ¾Đú§ˆ#/$ ̃Á~ Ó1ÄÔ¿̀VêÆ±‡1J8'Z@H5DL€ií̃Jm:=b¼ ÅѰèë@Ćƒi½U"[ÅDẻ¯₫#â‘K5C„‘~Qyû̃% KˆßHw‰äÉX$&ˆÅựE“ç‘₫G—` ,…%Ùoˆ)‡pè'›Åï Vƒí́Í/æĂ¼, e@l¹‚A”À[‡u¦ùïƯj»µ!<… fḈ>ë4Λ ê% ±_¯ ¶eÔ¿MÍø›·Ô_ZùP—æ™åAˆư5©J½øA¦zẉuZg·Ù*« ­~ëO¯t–Í~|ơÚ¸`§sˆÂ1m3\ LœR`‚CŒ¡~ÎP`Z” rT`ë*+´₫z¹¿Âä§WXÑä·kw™q˜”Ó2ÓöÆÙY,`붆+´IåŒ í+—€*¡[Q«|½JkåÅ!̣ÉP…!—å JÙ_~‰DqB»ú3‹×ĐW™FĐ$vYåi]«…ùº©­;w DbºĂK1CÄ–ØJ/×:âéÊ|[§U+èp»4FÈ 0§É»Zu׉ ˆ̉¤+”Á(ÖM½q9Á Êö³N€ Œ-v`[{ @\È¥0́ÄŒCp8tm´êx§ßù(VX:1}¼kê,ü X~nZæ¿5DƯ å̉¸>ׯî!tó>rÔÿ U÷Í́@&‹Oa2- =“iQœ’“U*]|–)a‘‚·₫¢?™̣×Ö¬SÇzÀ˜@’}tBd1 v7ÿwĂđ˜Ä·0́dñÁ₫Mö—rYdO{;ád1â ¶˜á4˱ÑÜ/g]©y¶¦HÛ½vBˆ÷…²q"Étóil®]Vëvº7zxoÉ™—MQïOƒ“û²¡è¹¤q6´øín ±Ÿà´Â ưi§ !UUå›;§¤¸·O7ù'ÿÓĂ’£Hr‹/¯ÀçœGơTHq›P0ÄĐ¼¬ÊÜ@Ùx•;PĂI˜ØăÍ3̀Ÿ›à,zĐ1 džÜyr|@yºjúÓ„ᙯ3 é +֦ѷj™6«ú¥ùG‘²ÛĐN¹eè„̉'³¾¬r°¿e§Îä”Íö ¨áØ5);HɬvUkÁÅé·Ùaù­yb”y¶ !B‡(Ù`O(êöY,±µ$1Ư^o¥‹₫$×åCºeZRVF}®6›ôN¹!ç ^N ×'yʉ€è₫Ùg8hQ‘Ä£>רÏr$8êZCIùcă¾km5œ4G JèÏÇ_í„”ë‹D₫cñˆa{,n†V Ù¾ă>ÉƠ‡pe|P‚1¹:¬ C{Ó³Áq·@ôKèÂǶ¾Å¶¹zx/ỹúÔmS¥ê¦êÿĐÆ¸iõơÄw묠đ«¾K¯û>×Ư<¡¾Aü üg“» endstream endobj 1025 0 obj << /Length 1513 /Filter /FlateDecode >> stream xÚíYËnÛFƯû+¸ „“y @Đ´ ’E›&B»H² ©Q¬TU’r~}ïνc’`ø!‰¢‰ÊÊ™JªÍ¶ï6Ÿ÷đöåñë2X˜V₫8¿x̣Bˆ„`Tà‚$óåØÔ|‘¼OŸ_•»N7³Œ1–²§³Œs‘¾˜å<Ưo«nUoÍ'<}«—ºÑÛJÏ2ª°,R&gç¯/~› *à́HûƠGps†0àíáR‰°à.C*f™4}V4V]9ƒ—ë#©î1ư5lD$ĂÄZa\˜m̃ÄÉ>|`$`»/vé&ሓÖÉ»‹ßb`ˆ̀˜uƠîÉ'Ư™§TÓ\!VÈ$£q•»ơï[6æ–¥/VkưÑ*!BPc c†.“ưnÛ5ûªßJWrà…‰~Ư³Œ`Ó—Äc\°˜Ö/₫+c›sD9íÁ)c–HrZŒ,‘(!EU’•Dûó°\éơ"FSHüÁi`G4ˆb¼&¤áq̀ Dđïz§›îk •Àˆr¥á ‘|ÂéK8¨e²»̉.mÍN&cSØn¥[÷f½ô«à4ö¡¾4•~ÖU‡ÜnaÜcÂJù’ñj»Ûwíˆ,XHÀŒOé À“ˆèʆƠ¶íJ[_<ĈyIá̀CLBúÓܦ?¼\›_±ô/r(3$‘¸È§éÏƠư Aœ†ÙîN1E8L¢\²3X­Ë¶E±û  Ræưx{6p9Öר\Øs…$nË}|l ².êä̀[̀QA}µúuß|-nđơWz;!#('ù8̣Ï<Ú³®ô¡Ûúh®V0ázñؽƯènßlƒØgB¤åzïÿ¢₫ª́ú䘑ô= L³p– Ăj°̃|Yµ̃æa_́+í¾“t+×ëcŸø¤dĂ K÷§+ơûF÷a£&Ü3Œ‘Ơ;­û-Úúé Js>Äă³»¥"ï t]"Á|^ê„é ’ÄZ¢ùH8[/8P·™ùBPvŒô|–ö+Œ˜äPSA€“ÿ<í‡#ä Æ–Àêp†F—‹¸úc„{8ơ_”pÚ˜èÄUDZ«ô€ễÚ__~>¥ứVéÏÁăªx8éÿ×I8V~vwáoWë è…¡S¹•LTÈü2§d†fB2o·cXè¾îô}º1èp¥¡g̃aÑ.‰Q•>â„ĐÛ\5粩7λóçoœR˜©Ùo@v¡~wÑ2*”m˜¾­{ë»Âư Wƒ?W½†9`ᡯœ™êœ‘th/§M³6îFÎ Y!POV~Ùòá/½…Ot„¿î›…r̀œËm´₫¤—å~Ư=uă8ưæ—môØÖÁkzT~aö”EpÁWÜ   Vœh̉œ¥´›\zc¬øú₫ÆPĂÁ „MÀqX&ß"Đ4‡₫@hc‹©°Éx }«äÑtn¦/S)OƠÀ°¬ däΣus+ü» Œ}ÊûPèV]ï»oˆÿÍÉ Lß({dºª·‹¹ÿqün₫Ç1½âiF|•Đå6¼’¹\O6$eU®×¨om₫9H#( endstream endobj 1029 0 obj << /Length 1669 /Filter /FlateDecode >> stream xÚíXYoÛF~÷¯ úb 7{’ËM‘´H̉D@?P̉ÚfJ‘*E9đ¿ḯAK/}$AP¤…‹ggg¾¹‡D>$Êh”I†$Ë¢ơö›_ÛËÈ>¼ûơ„8º“åÏË“§/„ˆF9ÎI´¼³Zn¢³øùU±ëT»Hc1{¶H8ñ‹…äñ¡^weSë7<~§.T«êµZ$4Ăi³lq¾|ụËr¸\Pg”´§¾%®¤aƒ¼Z\™"’O",¸ù͡ۺ½¾ª’¡”9Ê×M­Yv›,“¹%{¯”Ơ¿¨öͳ_.ä9œ3ô?5€‚Œ×]±€¯kưGơhü=¨H2‚ÈæÉ4Ơ ăh/_Eñ,úd(·CèpTEïO₫d¥ÄpJ±BtëƯÓKƠ!+®ZB0Ó ¬ij0”#B‰H©Ñ€Q£|]/ k€Ky”¦€i~K—ö*pĉôUđẺ*H /ÅQ‡OmÙ©æTb„x¥(ï•8×dc×dñ‹²Rç–A V&(‚˜v-öf«ÛƠM§zÇIÇ´"E\ỆÇ (p<’-ÅcÙØ#=ù  Àå¬'jVƯÅù˜†H$éàYOBl2Äđ Ä¦›$‚p"G*ˆ1%)¢`,CùƘB̀ÏCÊsÄd₫Hé eŸƒ¨ÏÆ *ǧ»Ù…ư#JÈ}ÖI(æ(ĂÜ7ÏŸÚ:µưQÊăÆ!%d]|»s0Ú`®±V^>k³{Yï»ö°UµNe]0£ˆŒ)\Fqáû²åáü<ܬtÚ‰?†D#À8LZî]&¶‚9 Ù‘ƒNT ̀…B÷&›à ätæ. ·®¾Æµ×Œ̀¯ñ»Ù™ềi<…„ê]鱺^Øû7 ,P [“_^Ø·uÓÙ‡½ÆÀbµ.?`ÂƠ扳§#Ù¨‹âPuûA¯!JG(Đóà?„Ä(£ƒJë&2ÈCUOÎ,\¾¡ˆÈ ¯,}lÙoUwhk§µö°]L+ VkAj +c^ƒƠ;UÏÔUnÚ‘Ûu•Ùº -$ ¨˜”²ß›bS¬*gơqI½ g(ëú… ¯dñ$é‚ÿ6Nº³•#×-K:©ÿJî­宨lZµßSµWµfဨÉxêe€ï ¿úhÜ_wMÛͶ'â>T̘ǿkÁúe=JWnUsèfT̀Ùư‚ †s₫µ˜Gö,tCŒ¥n×6;Ơv7u±U¡a@b${„O8~×EuP!ù$̀ŸùÉy5-ཹNÿ”_”Ÿă:̣+ºN¢s«€>o\±¾™ %„ê}ñèk{ƯĐ©Íltƒ™Åj/µ 6bø3‘©ưưæ\¢£&‰“éJ¹–ÚÉÖŸ÷:ơ@ÿ¾kËú̉ôî|èƯ›­îÙKèë¡ÅÔ›™>Ư|Ÿ! rB¬À¤V†£cN³9 í(¡‡¾Y¾YÆư’°ÖM]DZ‰¦º‹̃¸A&¨pn¶̉Rzjyukb5 £Ÿ5›U¬+¹w—y½€©R{¿'?Ë6WUc[kgư«ÔX\:dª±˜vƒ£¸öuÓybºÊ˜̀ÿ32Îv%é´ ¦s =ÖÔÏÍIkeë̀Î @°§Gn–´(Û½QOï1Jͼ S]îVÊ¿Ơfñ©î£y×£ínÑ3XWª½YµGæ.D  Íyæ5AhnO9b¾À9‰_¶ª-×Gsku&g±§XÚ¹uB&Ó¿Ö¡è'鋦UvÑÛ> Ư3ªæˆSi)—WjH~Ăøeîß_ÙwvíÑÜwE½VĂ đ ’2HơCzжZo[3-ª„„.³Gn«sqËÁ¨aE›üéö‡—ëªèSkáÆñ®².Ä`H])áz»³đ/c¢™µ%óÉÚü­ñY½ 7>û€ơĂØ¦ÎLz{%âjíáªØ{‰J;XUÙ°²á¢å°ªt­X{Á#ƒÁĂîÀ´¼¬ûdÖûw7‘̣¸cÓR†blZäR6]ÎĂS¸ăÔ>j'oU±iêê¦ï¦) r[TÇr)SÊÑ—‹ï½]Ï´fƯy+ë·FÛ¦S^˜Ơ¯D–jîölz»‹³f|º8 endstream endobj 1032 0 obj << /Length 1657 /Filter /FlateDecode >> stream xÚƯXKoÜ6¾ûWèf-1âK¤ ổ )R-íÁ5 Y˵Ơj¥uưï;©efíØÛ^Jg†ß̀|$bøĂ I*‚|o››À ̃ÿp†­\‚ÑḄ»‹³×o9pŒ̉8ÅÁÅn©êb\†on³C§MD) é7›ˆ1¾ƯHöŨu¥¿°đ½Ú©FU¹ÚDDÄIR¹¹ºøñ́û‹iqN8âŒ>Ñ̉Qúse‚°$A1gÆäFíëNƯÖm§M¸@Ia0ÇKẳ$Y¹ÑØ*j»¬ë[đ(árzĐ“êùín•q¿¾̃Dœ‡©¼3/ÎëƒD¨ªs+aCx—u«¶çæé˜ÇʶuŨĂ–Ä®]±Wuz±Lñü¤§ÿ³E³²·¾•ù+q¨̣ºÚZ{{XÑŒv£w°.+º¢ºY}Ùf]æ³ăzCdxß©6Ó³tQf×¥Z‡ÙÈWZ¬ßëÿøoPĦèM Íc̃7€ mVWnpxo„ÇÅ’i±áuW›I:xŸåë·’`R pÑh‰Fà†biNQ0ƒưKHØå‡¶',b*“!Ë)öơ2ygñ¯Óǃ̀TB‘„̉J!O)^#“‰ ˜A]`º«“˜ .Ä *N“Ïp1/³¶ơFv8¡n€é»E„ù‘ÿ\Wʯ— UßQ;¤1B3A!gñỈXë”Û®¥è %ñ¥/-Øăd”«øZ´UOR¯|z0 Où×}Ơù4QŒèŒ×«nÙá·Đz j Ufˆ[¤€2*ŸRdȃ"£A»°Ô)2^g4°ÉƯʧD‡M<]ÇØ€=  `ÖW¿¯µˆÑ”!™ˆS1­*¡ä™ÈƠ91‡Ûx4¦¡b³Ï<$AÔO‚f^“uÚ,Í3/Ù‚́Lt˜}0Đ;‹•XÉç±̉Ái×'¦û3[9µà l"{Kăíºô`ªJö¸Ø–©vY_v.#|à]¸£ImămÖÈ#]æX ègLôøOcD¨ôn*pÔ½\¢ŒÜ²°íó\µí®/Ëû5sͬLV­]öï µÉÙÂE¹w›ä['̣ <,¹¢à@·ö­*m¦B¼Û¥…Đ¢l!’Öà¦2û^·/?Đl‚O§NĐ©‰°&§!ÜŹQÀÿ_”ûHÛàÄ,ü̉~H¿`+#q¤\Aññh¹&=ˆ–/¤.'Y²Œ#N¤QÂ؇§úhcÇÀK…X5öJ¹4 +ugú Íâ8¼¿¨‹ÖÄáÉt}Œ]ß>£9`;dM¶WæíYF»q!o’1™$p@ E!Ÿ×uƯÉÄbĐD$ŸÙ°ø¬ÁœF}́UÛA—F‹[so l¬-ûëÑ[[ŒZÛ'rƯh˜Ú®ÚQQ–Ek.A¾VÆ„%Ÿ‚0iMl ₫I Ós9†·1ph}1LJfúĐb®óªH¼ ]Ss µºnc+¨EŒ±đ7]ôfÉ‘DØÎPYƠ:÷×¥Ưy½åÛK9æYYúk"QœÈç¬ßy¡C‰…·;<Ø1Áñ(¸,@p̣~ë}$vûJ?%ö&^{7–(°p&Ç$… ú¢%’ ¼Đª8s₫boÁ’ö¢k†êúFo'aË{HóbÆH.‹<̀HËŒƠ §À[_8·ëzB\+ëÖç{yÛæƒèaÉO Y)T€T„c*[Ît×Ư ï4S†êó(öƠÍàZàç]¾́fbæï®EĂu œyP6$·ƒºßuWÖ?Ÿ'³¹Ô~âACæ?×°[Ø endstream endobj 1035 0 obj << /Length 1978 /Filter /FlateDecode >> stream xÚƯY[Û6~Ÿ_!ôIbF¼‰R€ÛE ´é6n_̉24ÉàMKTÁIÁU²=̃eæi÷>±?ÿû:¹5®=Éo7wÏ_J™ĐŒ”YI“Í̃‡Ú́’·éưcut·ZsÎS₫bµB¦/W…HÏÍv¨Û߈ôg½×n¶zµf*ËË”—«w›ïï¾ÛL‹K&‰üJMGéOÔ-XB9É@_T·È U€Ér’IaU~ƠœÎC˃q¥o\–¬©"9w‚Ăöä¤Đ’PZ‚°Z[Óë¦*cÛîcđ9#Ôs¶à"ƯƠ ₫|À_ztÉ“´,ÀLˆ`VÔ+߾˒¼ü>ɈPÉ“‘<&œ004KÉ›»ÿ¸È«³Œ©”́ ·‡ªïÌ 5åÆñ‚PiÅw˜e‚bé6#l\6´öɃq‹¶7O]= º±7V$Ư[Ỗ9Ư7Àcv+î«­¹&˜"½¯¶®¨›âe½ººyo¯[—ÔgDWéP¸Eq©'‹ä¼æÜÚYºfŒäµö¾>^ÖɿȺ_,6V“*íÏÛ­îûưù€÷0íñtĐXYϰ–øĂ0oWP"œ¼¸1ma£¤PÔ eÜÅă¢Ëd?ÔêƠ?V‡ƒU¹ÓĂ¹sê›`á{¢ó»0töú%ŒcƯÛÇSèñ]åNhîχ!“ h^.'û›˜ă¡'ätLÈ ¡̀7¡äʲAæ _GKˆc[¹ù’g®Ü̃Bcä~cäéËú ßY€\%”’RJf–²e©æ¾´AMB_CÖCT|µ̣̀W }“ËQ#[[&ø(ôØö£+OPÏœH€£ÀôI··±•8á¢%Nm7Ä`BßÅ”Aơt™0~êÚ“î†?VG[PIÂérÅụ̈#̃¯Ơá,(‘åätBH̀ˆ’”9_8" pàPS‘ä\suÏyX#?TĂ¡z°i‰]¦ꇃhO]u¾¤̉±eưzÙÅÔ;lĂÆ Óâ$…kq?¾̃|÷búªvß=b•{mźû;}êô¶ôÎơó_z§•Y‡è¡ÖvÑyëj«è,¬å«¹€Wa{„nÀåbª9Ÿû•yÔ`ysÜtÏT‡„Æ„n¸0XY¦.©`£†ŸÛhö§ë¶m¡f~nçñWn>¶GlÊ;+¹Óû pïÏÓ"»`–Ơ20 ‹Â)aǪWma§.ñrYß墙ÏŸÿJÏXY@1àD~qȼ>aŸ®Üà=YLe1UúÑÍ5PÙMâ+™§¦¾íUƯs«uCRnè5‹fSß@X¤Lÿ«Ñù±‘DE5µ ÜK…ä•«ơ54ă₫Üu®h9Ó6ă£ß›E\)<¿â2Fºêô<™|™ßœàW1À6eîPu{bX<'¥úK¤’đ\ŒU³‹¡0Je×+ỒÙâ@+“̣zœxa8@üÏ¥‰Să–\#óÂPæ9îv]#ïơ7'üÂæ’”â¦Í Ë‘%Âl(Äÿ´7Q BsE‹̣Ö͉µ«êûK=ï (œÜ²+̀c›eÈ‚̀f–×m°ưƯÿ8 öf¼@q —&J„I΄Z”aOdÆđçBÄöx*3ÉË¥€=_úµ)ˆ EèÈP ¼¤ Ü`ñÜÛåaoØNv<‡.ÿ[FÅûs§7«R@=ë¦`6Å ôô ÙÂơ\6$©K. «ïk³öbƯËP˜j¦PW±Ơ9ivE R°̣zº́åS)$½—øË8Dr1́₫Ùë€oÍN ±$l¢(½Ë́./E@æÀ#ÿá2(€:2ñF;26̀^tóÎuÉ~B+…?­à~øæÍư+Ă ^Ùû̃;G8VM}:*ö/ÈHo9ºÆ¢è^Ú‚ýE9Lz``%].l=íÆ“G÷=X:›ùúW'f£FÉÚ!‚@¹ÅƯî©Jï¶ÈđÂFÅÉŒ§exm³»’¾:-®çFÛ.iÇn jÏb9¡s:^ĘT=́ă |̃pGA ¢”ßpƯ®ST-¡ü}^Ïă>Ṣ̣jƯZ¼1ºă.ưưƠ)ÜÔq>­ÆM8¾Í\ª´ö/“̣ÂY Ä£¸ưđ“»“¶ÑóÁÇRL¨b́ä.ï«Cß¾ˆÖ¹ôO›¡ÿM[è¸̃9PH¹ÅA²Ï¡r•¥â‹P9Ä¢Œ_¤rÀă乌!R "ˆ07¯O¤ƒSˆóºd2Ưf́`‹̉Äùª±Ó¢¬% óDÙ".₫_ĂÿÉ”+XS¨ZÀt¾Àfb̃6×H¢¿å(´+º́W‰' ²úÏwlkzRÔFIXÆ>dz JĐñÅ!ëKă«đ¸Å²35²35cönøwÓm{Às,¨{ÍZwư؈₫82 endstream endobj 1038 0 obj << /Length 1641 /Filter /FlateDecode >> stream xÚíYIoÛF¾ûW=Q@8ál$'@4i$‡´uôä@Q£˜%ª\l¸¿¾oRih9¶ÑE –¨§·|oûf„ƒ₫á %AQ”Ñ4(¶±~Ú| ̀‹Ë·ØÊE M$_-/¿á<À1±ÀÁr3Uµ\ŸÂ×Wù¾“Í"¢”†ôÅ"bŒ‡o û]Ñ•ơN}ÂÂK¹‘Ür‘4NDÈâÅ—åû‹_–£qN8âŒ̃ÓÓAúÄƯŒ˜¢üUîf Â)è$ 93.¿Ûíû®Uæ!81 ."œ¢„ZÁµ¼¶R#B3ÖB‘ ½¨w;Ytrmâí½4,«K©^í$ ;ó Đ^` ˆ¬ÊCPqbƯÜ€\LĂ\A“0_¯Kh^™ç{Đ7ùV+6)©²µŸ6µ²u]®µKđI½±Á$Ó`°à(Éè;€9JI:H” =Ÿ&HƒïƯ¥H ˜ŒÀƠ×:•™uç ¥ïfü¡a‚ïØ3“»+i¯wƠ­YtuđúYm?8i1‘B)½«₫sŒéĐ"7eU™Y鑿 ˆđ¾½‚\i7Ư"†²$%PíZá¯Úbë 言?Ô;iÅ̉S1&„û(¥q.¯Úú…O/ă(cb@ª•M™WªÀ3€¡C>Ÿ£$†D×s@%Ftñ„„/k°I¢ËđçzAq(‡‘đçØç8…/$,àB@X\uù§/q°†ß1â`ôF‹n†VeQ/~÷ÍœB˜j]”Yˆt£‚í¢*!ïđ¢{₫Uṽ¶Ï "JuD”qóơO0êètÔÑđMYÉ/FA¨c$8'ªFKF»¦/&¥{d :¶̉Đà1Ăѯ$vr¨â±?ƒ¤Ï8C„‘A‚Öñzơñ±,›èĂ^4(LÔ$sKư1hlJY­}`P(h=9t µ’ŒÉˆđ(KÇ(`́îeÓƯzÁä°ΘÆÅAö­´[ĂŒ"˜Ê’™ MWÊÖ<¬7Vª0Ưiªú°sê•j¾đl*tIsïMé±çŸ"q–-Îr×v¹&6µFy6"WS08Ô‚Sÿy! VipP“đ“ÁÁ̉qnPDRêÎ ×:!P ¦UA=8à¢ÊÛù⃜Ă8æG‹Ăf8SV&ngLp†0ƯiV0-ˆS]Ш₫Ám5F¶£`ß»r₫PëÓ"Å0{³i›|gh7J.·ũÚ̉/JXœL®Ÿ™Ḉúfç4 … á6[oß-r•wC'“ƒ&48Ä⤦íÍMÙZ»̀±›h»G½™àæÄv0#̀Í[³#úF¢™=N¡¼Ù÷øË{uN1âĐ!,†ù•&ßÙIyµ¬5Å ÏủóVÎp Sơ}3£Ø„S°‡p ™M`Ó=§Pº¨Hg9E#óơyRÁ¿F×9ïÛ¢ÑĂ…- ¨đàƠ£)E½úæÓ„3”ѳ\Ni$OÇ%₫u\á€pC´å_̉ç°€úœ“OÌ₫+`ºj\0ÏëQ(t·{9Ḱđyb—RDƠ‘h™K̀Ë°àø {À“7Û+kuÓÔ[“Ưåëß̀Qôªé·I9ª<Ớêào`”>ç°€í0æ³6œq̀zxठ5¬#˜Ư G2Úô&Ù=¹¢IGX>ô[ưÊ.Û)`GkxA=p‰|ÔuÓåú³Üä}Ơ½0O@ă«ÛN¶?rQVùª’*ñ~×­;ÆơI=iªa9€w]'°¨„S‚ÎWœ@Öê>¨ËgHÑdH÷‘º;/Âîª>Ç¿)́|~Pan¦äRop₫ Ơ%ƒx’¹Ä́oŸ́RÀ¢'—ê §&éÜŒtÇîaH&ÇC’ˆ;§¼L)öŸ[ÎÀÎxó*Sƒm”¸ÖdÛ3']×ïºYÂi–ÿí½K̀uA †SKKôđÇG$`qv~_qu ut(ưøÏ^Dø®́ï:~¾ó̃˜—8|í®Bg¸¶6aÁ¤aßÚèVÎHw\lzç<.Ÿ™éÊŸ^O«ë{h…²n纭»rơûƒ½t̃æ]¡b¾*w_½§P{èUc1Ơ\ẹ‹Är°´q~ÛQ§M OQÈưà× ̀ÑÑI|Ÿ—±§¦ûß–²c endstream endobj 1041 0 obj << /Length 1648 /Filter /FlateDecode >> stream xÚíXKoÛF¾ûW½˜¢5÷Å](P4m$…“&j{p| ¤•Í”"U’²áßÙ).½Jdr*X 9;;Ïo8Jà‰„¤HR­¶g‰yÛÜDöáăogØÑÍp>¢üyqvñó'(K2-6cV‹ut¿ºÍwjfsJiL_ÎæŒñøơL²x_­º¢®ôTƠ¨j¥fs"’4‹]/̃ưº.ç„#Î艒öÔÄ•$Â% ¯W¦ àIR”pfE₫ĐÔ; Ǫé Ơj9@Ël¬eÍI‚ÅöÄùe¾UçĐ3(jCơIuÖ Ư­²ZWp̀¾ÚÔÍä[·Úi[Ä«²PƠ Üᶆ×2^ÍàÏ?úêPHĹ¹z%,ub₫٪旼ˋ:Û`'ï[ëA¯áô÷”xQlU½ïaÛδoïf<órユ“L­êjƯ"•é¨<ƠK4Çöw«̣ªµŸœ –åX³¢º±¯WyY:ư`s 8‘Vî÷ûn·ïÚzcè©‹Ê˺RL<&ËØà3QyÙÖ/C|G’e½á~r*€[áçθ§Ï¼‡tÂ#yÂ3ÈLt2]]'Ñ>¾ Dto(·Eè’¨Œ>ư,8J!›3C8°‘#ûÈ‘qwq3ÉĆ8¡ú¼gEˆÙ¥³9O‰Qˆ£üÜÍt‡JMÄAđ3Ñ‡Ă½B 1,}…|‰´BSĂ‚aÁƠV#xè.S!‡™ „R£!Á`$c$_¥º¶ RŒ2Ή± Ơdžd¨öÛåC7 W:¦å)bRö”?ÎÀ<‰G²¥‰—cଔ÷äŸ6$C„Ѩ^~9d÷̉Z’!́^„ØD“A ƒ4‰×ñ $ÂA›âđųïlR¨=Ç-Ê2DevEÉ ¥Ï1¨ÏÆ”?O÷° ‡K‚ÆßrÔN†DÂüjó·ö¶Z°âRP(ºøngà´Á]m½¼xơ¡Çư¶kö[‡1aˆÎÀ™Ü‡—7Ơ£³¯`t½Ô ‰†±\Z´¥­` áû́——Z©–¡gĂ¯Ú%ó¬g«emï7ѾÆ'’‰-êƒ…í ª±Ö»̉?b•ܸ¶b†c p…ø«¼UƯwS±m.Ôªøœ`¦Ö/œKÉZṃ}Ùµƒ^C¢¬@2@ê!<~6H!̀ö…ơˆ rcĐ`¦§3 —3 ÂRÀCR‘=µ+hT·o*§µv¿Ơ­×̉«ñ[™¥ñ€Î°ÁëªÔYf:ăÇuVØ:k+é+éóÉ—r‰̉ŒOjÛïu¾Î—¥ ‚1,cÇ%«¹µ ¡qJ€>)p“#>jAư?©È»|½nTÛ†Ơq:¢îê¦{~©Ă„ ¢Ú‚ÿM|̀Äâ—Nøđă|®B7QèûYv0=Âàø`f»ÀĐ-RüuÉ!u ”vænÏ÷ÎL(9%´èÙ`½ë´ ̣›ƠƯc? ̃;ÜvÓăƯ¾/́à§Fô•ÆmÄ—ä™%v~Í‘è ß|2;WrƯy¯jÓ§®‘.\íÉÙC˜Më/IÄ1ÉleÓGíV ‡qi`\Æưú¤¯Ö0´V3=Ö€uuîÆi¢̉·œ̣i39éÀĐ@³²ó"çñ( ù¤¤4›(mNZ¥¬Í› oJ̉¼hZ£ú`À3Ư‡Y×Í»ªÖ,î«>öv{gBw‹p+3›Hí.Ị́…N†= - 'ưJs.ăKh$›bå\sØ6°x¢Gíªp¿HèÛ̉{-|^¸C›ºQvünBw÷«¸3a₫럡™œqJẪb,nƠ±œ×8n`ÄhĐ̃æeiIm[̉»¥ír³Ùs­H ¶°̀Ê´“T†n Œ„Ë'î$üІgɉa•zl)qd›’ÈAđU™÷È’»&«ëÍ  jH{)!Gɨôr/†I‹|£·̀2„¡ẹ́̃n>3œOơ¨Âͨb_Üæ­qz[X–6YƯ rt¿, €±•—²̣É) /n*µö“ëñVR£¥¹ĐàfhÔ:`j0û'%"¡Ét œ”;Î[îÜ^­3¨Qùº®Ê‡¾ ë0ÿxî¿¿ endstream endobj 1044 0 obj << /Length 1497 /Filter /FlateDecode >> stream xÚåXÛÛ6}߯ú²41âM$h.Ư"E‘¤‰ƒ>$û µ¸Y¥¶äJr‚ü}‡]W̃[E±ÀÚ’F3g†‡g†&Q$’4’aÅd´Ù$înư)̣_̃₫rB‚] †ñẸ̀Ùúäñ™I°N4‰Ö—cWë<ú€_eûÖÔ«˜1†Ø“Ù¹@g+ÅѡܴEUÚ'½5—¦6寬b*“T#NWçë_O~^÷ÁXpvG¤ơ-pU‰Ÿ4ʼnạ̀›U¨ª[‡L¢Ú́ªÖøö¯ÆPi-»•èÂG>Q>&"yk²¼*·ßà;±¹®˜(œJåĂ<ÍóÚ4Í*&RóI”«ªñÁQÖÙØÛ7:Ỡé»6k`O¹–¨ öåể¶WÆ»®±è³Ù„dN+Ÿ)OƒEXµÓͶjL~: ¨oIm]́Lu¿D…Úîʾ₫eA³í!¤Z”₫³1›ª̀øÑüíËĂW[é¬h‹̣“·éŸäY›-UâƠa÷́[k§>b±]”]l³§`Î0Ä›÷K©ÜRª~)»Â]ØGÖ¡¿Üjà«]ùÖz₫ÖËAÀÔtÑÜí¶̣/ÙºƯPÅ8ÀU²Ë╂׋¶…˜ÿ©,ú×u`–aÛç¡Îjaqûxd Ô6à-«À+Ë™›p¬mM½+ʬ­™u„M{Â.r³ië–·f`~pàïûÆÔ/œ7B@…́å”đÏÇŒ§ÔJY ß­–ÁÚcÎCF}Rô₫Åx_ ́…Ù×f“µïá”ÑzƒƯ˜J1øÁÁÓO– m||Y1‚L'Öơ Ld‚YÊ#jL´²úûá<‰rx{ ÷Ơ™î"9Qđm½;ùƯ«ô ‘+ÂÀ—ååï_:ịø§ÂNU‚f«ĐÓPgvG‡¡³bkνƒTF¤—“ÙÆÁSÀå̃q̉±´’ôF?®lăAcXi2†%NSљۥXÍ1…ÖŒª‹ÏK€+ê‘'²T†XiXÄ)ËŸ[pA<+€ ¿¥ñuñnô$n*Ó’eú¼Dœ˜P%×®̣<ñÓñ'јSñ}ø¾ă>&D«Åơ' s/M4l¾) Á bÎh°|OÖk°Ö÷bAn¾Ü‡K¹Øih̀ƒ?K²ÁfË£%h³a³ư°ä$ÅtàiQîaîXÚµ+=w4ÍkâèxaÁBËÿ[aaœ;RY&0MèC*;.Â9–c½í™+ƠtŒ…]ºpå¦í¶Ú&LØå̀Ôͱ67’©—–0Í’Úézt'C¥§]D©.·8 6Ư\&˜[ÅÆÏ£qxø„5 1^ÚÁ-a(³/&Ô +ĐÙÖßßÛ‰¶ÎvP ‚ü ¬&<­+7˹Xà ‚ư‚DCKRl¾ö“´–TÙT£äæBÜèHă„öåñcØ5€eÔó¹t '™b»ơëŒƯ‰Ñu"X«ÛYúÚEl–ÑôUUvÓ‘¼nÖRïL˜Á³mS=ỴË¡̣^B€Âx±÷§0tQĐ:?{Hç'Zư]?ÑĐÿ´¾ÖøÇ\ndÁ±R44ÆÇߪ,ïE ‡Éó%-Œ™€^÷[ÂIư(äL¦äNzOGëđFC)aif\]’ؽçi™÷§8µi<̣—_¯ '»Ws†gödiá@áü¸Ë¼4Ï"ôơÙ±4,¯[wz6Nï$Á7í˜{Êz_Đ@IöÇƯOM›¹_¬Â){Á} /?t¨6²]רO˜($́’:qÑŸËư ú(›²& í‰t®¸¦÷Hq³Ífy‹ø»·"±»)’z˜"…ứµwUư—? endstream endobj 1048 0 obj << /Length 1507 /Filter /FlateDecode >> stream xÚíXÙÛ6}Ÿ¯Đ£ T wI 4i¢A–6qчÉ^^˜¥EÀ' ¼Ûo.₫đ±!±@ a.¥n½{đÑ5·U×îºVs˜§ ‹(G"Nû+/ŸWÙ:»̃ª>ûu6dưÊ‚ÈâM… $b"A2@Ñ\¿ÙÎö”Ø)5ij_ü lWÅSP(§Ă"ˆÅ‡D(шøBŒ ,åA #‚ô‹Ÿj}xí­ê{I3^H›×d©ơ nƱÉX'=Üo%ÄÚØƯÓéî°ÄH2> dVO‡H¢X^6mfZÛ°Ûøà%\˜Œi‚Æ£‰i`Ư•È£jD˜vƠèƠÎ ®*Ư$2üóÉïúM®ª²T}̉=ĂOœUé$`Ưjá;ß¶Đú,É-os»ÓjâêƠp.`Çvû±ÿeX‘ơLö¡›o7û^ĐUöbWWí±1»¬Í¯óm̃Nàà©óÀQ$6!=¿t»-Ÿ?z|@!‰H'³&Ï™5®ÛÍ/1kKH6™µ]—@»ù&ĂVvÅơÇÖ?qB"$ó‰ÓrnCK¸t?N÷›¹ÙÁ̀ÑqzđÁĈíƠ UÅn›µÊ‡†…¤ăD"„|ÔS”Jz|ÓÅ)sZï/û:×)4™ßTu‘µ­Z÷›̉uăFiK_îÙ¯ƒíhĐ«.y¶í?í²:+˜à¦wfÊàû^¬A¨»Â®TÀ 0–º³rÜ­°“…Çcs›®¬§:R4"|§ŒĐ g§»id¡I<=fZL•¬Ÿ®œ̀f[˜!8»SŸÑø”•+µ˜uF¯u&c'fG—Äd¨Ñu:0æ°7=`ø̀ëÜ|üÍÙ*« }Kđ…kơ>_)¿Ca(¹Ç¡Äç¨&Ă0c”|ƠÔXhÖ*[¹\g­G*»AçR¹§u®9a'˜.“̀Üù¾ÓđyçE“ÿ£|Œ\y0<E₫OçƯtº8n:ắjµÊ›Ñ¼ºá7« ̀Æ©ë?]ù£ ·4—>̉úà>Z¼‚wpVUW¶Ç»àªï‚cÍ`¼û^̀äăÊăr÷H‚̃K¾³"ûWƠuÑÜx‘À2ˆäœrÓ¯1ûŸ_îH?@ÂÉ́ö5DâuMLPæ)ÜLƒ§[6uU8^—[¯ 7ª…6’ʸ&¿å±y$ṽó¹ÿÂñ̃ƯÙtAŸưọ́°SäàÙ€z¶í«8¸CƯeH?A禕¨MÖmÛ‡ư7c]i?O»¹S陪ßyl&¸çpxê&8àÈûËÏtä§5—Yeø@¾DŸ¯Ñ÷×M«¤c̉zî> #ÊÆR1öwËU+Ư1 $ôó±øN5áqÙHc®Ç§pÙz¸É´l²½4JU÷¬ Ơ4ÙBƒơÿï+ endstream endobj 1051 0 obj << /Length 1319 /Filter /FlateDecode >> stream xÚíX[oÛ6~Ï¯Đ£T,¯" @×u)Ö‡uKSô!̓bÓß&É ²_¿C‘ºĐ¦¸É: Ć|x.ß¹|<"†?IIÅb2,Npû´úÙ/çïNˆ“KA0I¾¹8yy&DD0ÊqN¢‹ÙXƠÅ4ºŒ¾)Ö®’”1³Ó$å\Äg‰âñf9iÊỞüÂăs=Ó•^Nt’R‰³<æ<¹ºx̣ËEo\Pgô´“̃qWш0„ÁßÎ]!,¸u—!BJR‘Ñøơ |£ñ¤)øø–0ëΩ?{KDbÄ2̃ªa\;—W8Âï#ŒØ»kEGœ(ø6>ụ̈†Ha¾K›éúǻ®*›Öø6̃Ta„ÄÙÉ́‘K˜fñY9×WVA&#2‚)3ñ üjÏ.7‹ëûF×ÎX6–âJu’¯’”`ă±s;—ÁQN;ù/ ̣€#:­®oå|,CR4ï„^„ÔHÄpÅ´€¬<‚ª ƒxD‚ âåTÈ äƒ ¥{S!P–‰Ç`Ê₫1L}=>¦ëYWzRÖÄPx ùP‚RJ$¢Bº YáÏ&?¶zđr8Â8ʘ ÄâgCÚúd4+›çOo·cª\ÖMµYèeBUÜX~ §"‡DÛL8Ï~]®7MĐ+ HpŒw™2£'¾ ¹F@±́û¤¬­k…ùyȬßê tgÜ ÑÔ©̣Êû "¹‡[kÈbĂă¶PĂfÜQÏ̀Ṿ}[Ǜ́@ØÈfÖ q¡wÇS–#ô6Í{qûJ7›jé`m¼Y$TÆ×†’bKaÜyÁà)´-Ư£ĐèeØ/‘̀/‰–ḥï!A1¢˜= Ѩ„œĐh¾ê懰Œi£I‡œÁèÛÓûåO n`dG D̉äĂ½Ä ’T>1̀J=Ÿ†``P™B=; l†§qºZ­uƠÜG9Ô)!rÂ%"j Ów¨37Úv˜±ä:±)»¶ëºÑD3Œ¿̀Œ¿&Ø‹ø;ó—_‘a8¦ÖCE{•u.ÔgpP —Lµưß̀¿@ÿSL$â*h»û¹́›Ÿ!¨R¿ù}ÛĂËV‘ÈÄNæE]ï¡̃)˜Œ Ù¡ær¦LÎÚy¹wè“- —ÅBû)̃ƠMw€ˆắXø|£—Á ,D ÿÈĐîŒ\á*·vÅ<)¿`Âơô…}lIÈ+}Œ^̀7zL„æ÷¢éz#!ñ>x`‚–[<¼íƠ]Y;ƒ]îÙÍZ»[ƯV̀ç»9q=ÉúƯ=ÁNúMƠßäö̀ÔÖ«Zw&êƠéHGב×ê"Mç0`1…0?¶wüKg½¨dËŸ=oÖºÙĂư˜™»ÜOđqä/%QX©$Äÿ$̣ }­.ÓQébf= ;G₫|́?ºkú¤G¦¢[…¯̀ưư"´ËứAêWG₫|Ôÿ¯ƒ°ËǘñÄ_—é½ ¶xLPdê0·Á lÖ⸠½¹_ë§ÜÆà†Ë(ơësÀ+¼SS“₫¸zV­Á­(lavփ˵l¯Mÿ¹åz”`3¥‡æ7³pªváTq÷δ[{}2öoS̀ȼVåmžƠ³b3oNí“7fCưÉ̃Êyq=×&ñ{¶uëËÎK{p<¤dHFæ½!đøÛ;¤yÿo5Xàå÷Ø79GµVĐxv endstream endobj 1054 0 obj << /Length 1635 /Filter /FlateDecode >> stream xÚíX[ÓF~ß_á7l «=H•è „Z Ûöxp’YÖ4±S_@ûï{Æ3v<Îx7AK[‰ DLr|æ;ß¹øƒƒ”iFQFÓ`½»Húoë÷yxơÓ¶r1ÆÉï./=å<À ’‰ÄÁåƠTƠå&x~ï[UG1¥4¤£˜1>2våº-ªRÿÂÂWêJƠª\«(&i"dÈxôị̂ùÅ—ăáœpÄ=é }7#¦(¼\"P™KÆđ7¹ á“ À‘pƯæ||Œ(Ơ€ê¯ñ(œ¦(%Y¯‡2®zó. 6đăó AüÔ‹î†Îài¼¾øƠXĐçbê6ûGjơÉs¶IJ2ˆ EL«Đ̣o€^:¥—†O‹­zgˆL”œ­ ¦&Tÿ®>Gs¾Mxb^éồV¼Z}điÅʈ„úôÀcJñ ²¯«½ªÛ«LN%y‚Æ·*£ˆ’Qâc¾í”•J¦d¹ĐÁ@́¥” $Qđ æøF]F]E.ô‡Q,pˆ ƒ9|xA0"Üw8"Æœ" ™ë¸âµ¦S; ½V¦thKuƠÁÜB5æËêÊHAj¥s:ü Ö­Åäf^̉çPdæ˜gå¾k›ƒÍX ˆS$(üeôú,À±t¤'6@²ió¾ĐYœ3Ax`]ÖW!øø¨ÿñU! "Y (GÂó*Ä̉±QDRê!÷t’à½×”$x¬Ãd l Ëơ6oä3\˜Á„ëKë¹L{N›uă;‚é:g$–ùN¹>ÖÛc b«"&hµẸ™—xó8Í¡3ñ“tkµƯ/Ê|î"ˆÔ®±A¼2ê}P$ƒ®’)AM̉Đơb’†}œµÔŸÆÉª•ñ^™ưaà07`Y¸ËÛµ6øº(ßÓ If‰Å)Đd1´+j™½¹r:|¾(È×kµ@qè¬@^ÔÍ))û²×¤{´©₫Ü%Đ‘ 1o<ĐaôÀÇ(‡ ø<®8Cô‰U=ûm,8M[mÔŸ}̉¶₫ÔèÏ¡ÀK",®ZíªV]WM»ŒîªhT˜/µ¢ỹ̀‘¥’ä©FŒÊ3$¤©4lh­/ª|“¯¶–‘i£]h¯VI2¿SËä0³ƪÁOïô“ÅÑMêơq6ºưW, g&Ñ)íénƒ»»'Û{›…v)JÅÑ…½^{ÿ~PÑG endstream endobj 1057 0 obj << /Length 1661 /Filter /FlateDecode >> stream xÚ½XmoÛ6₫_¡o‘‰ß©û²bZ m—ä[E7dÉ“¥ư÷;¤^lÚN·bXÑùî¹ăƯ=wÄQ ?8’$’"Ee´̃^¥ĂÛÏ‘ưpûÛvr &3É_î¯ñpáei†£ûÍ\Ơ}=įŸó]§ÛUB)é«UÂ߬‹ûzƯ•Mm̃°øVot«ëµ^%D¦"‹™X=̃¿»úơ~4Î GœÑ"ởà2"‘q€-PÊ™Åüđ{“ùS¥-j@K=ÚGƒêæÆ(ăœ% åjĐ’Úï÷ÅÎq1D8^èçU‚SNÂ"]CS/ü'H†,3DñB­̃6.wyQ´z¿w²¹|Æf#„ŸB*%¢H«r×´]H› H v ŸÖö²GeÊḰÚf§Ûî[ouÈ¢äˆâóø!8‹ !äx©øK^ơAÍ ̉E8B!o2”‰ñLCǶđN ;5‹¤d q’9ˆVøĂR_ź¶Ig̉bøPÖ+ø7”Đ&_k‡J‘¾™‚>£.Ÿ)"©sơm½ë»ÙéOvAK$(;—/ ¤ #BG‹¨{Ö¶hKÑ+}ÙØßŒS2ṿw][ÖŸ‘é,~»q̣Û²ëta% ½ÉûªsªºÆ₫½ÆD¢~đ5 ù•8˜‹w©;uÊß…w\ÀỵS̃Yèæ«Ăăp ưÖü~²'ƠÎQ²xƯÔơ _q¼î.{ ²ÖQ6: ÇôϧKƠ Öyå]4úB^2(äÚ /=̉èùw^?•ÆéÙÆp—.ụ5 zêÀƠ®³m“jÖ 9êG  hé Å_V\ij±ÔA·£qÚ@îËϵ/g_ùƯJjQ ‹2 {beAØ\lû­¶$wÈNl\Û&Å[M]}ó;ZR§#¨ÆT©ÙW”Ó{óx²ƯµZ}nöÆ ĂôÈ }eÜÖ„ói¾đ)û3bƒ:A"D§œ”‡N%‰Ó2 ¤Ơ2`¾lf›+r ¡ăt=8IWăĂ4.̀é ƠY|í³¶¾vîL®×U³×ÅơËCו[ƯôæhT†§'óuhÖ|Ö¬K×+÷æt4P{áđö{_㫉g^v®îfo:f ?Ÿ† ïỗơScº¬†#æyÉÆđíăºo[=œsgæ ÇJ̃­-ÙDït,ZÄHB_°–YZ ›6@|]’´j”±ˆ¦0ñGp°áI‚ ñZÄæ° ¨lĐE%÷ưr"Hfw€]$¾ÈṚ̉Mo¹Â6½O3‹Ë]@À÷¦í́Ü G˜g© rGM#ÜɵB¦H1¼_àÆöùFá:|íFÓVW:÷ßÈ}6`æs¥Đûu[ư¡«È‹¨=9_؉ñ6S¬È÷M/)† ₫RØj ưOÓKÊ‘Hå )ơ½Ó :1%>EÏøÜHñ¾©ơ µ‡«˜_®b,’Œ₫*6ºwuY­„¼¢)œ́䶈܇yÙºB.+}âªÆ\±ÙÇl$\”:£(£|v[Ă ê}ÂvPî <ßưÓ“…I”¬«·½ƒ=ÜßƯûû~ƒÚ6fPÊ'GgD;ù·‡© ¥»‘»Ó¾¼«}ó*¸1rQ6ëIጰ’ĂŒHq9u2`üc2T1Büy‡ư_Ư?xŸ% ;Œéå€óWÁ{,Lç#1¬›¾¦)Å2ƯI i:»[ü4Ed™®°a¥‹«ªËŒS [\-Ùẹ́¥b¼K„°É—ëđ³[øæ4£́"Y*Pªæ¬ÛqÚ´ÍÖÖƠ™›8“Ùÿ˰¦ endstream endobj 1060 0 obj << /Length 1937 /Filter /FlateDecode >> stream xÚƠXmoÜD₫_añŸ„·û¾ëJHˆBQPhSøP*äÜí%wv°} ư÷̀¾ǿ½lri$P•_Ƴ3³ÏÎó́’ Ă?’))Íf*[nO°{Úg₫âÍw'$Ø`X̀,¿>=yöRˆŒ`Tâ’d§ë¹«ÓUö>qQ]¦[Œ±œ=_œ‹üåBó|×,‡ºḿ¿1kÓ™fiUX–9W‹§ßŸ|{º\Pg÷Œt´¾®¦aC¼6\-Qà“J„÷!¿j.wCo‡‡äÊyr8+ˆB’ĂƯê2XE% ^‚±3*|êuÓ•ËϦۮSî%|á…[(…ΗCµ€Ÿ+ûŸḲ×>O  fk$! Ẹ̀ưœ­àå÷F\e×Îr›1D!Qœm²·'¿„™‹F§X ‰•sÅé'd¸ÜT}R „CxfJN„7oRK$KuP²fAU¾ÛÚ̀Ï\-FAơÜï™}ơq0½/êĐúÇƠ0˜íåàoüCw¦ZÅ_îëKïÙ½j́³ÁœĂH©t|”>âcê­iwC*'‘æü ©Ñ̃W7₫á¶ Yûç«úwL˜].ÿrƯµ[µ2ëj·öPJ§Ăfé, ’‡”bü!ȦTÈ0ë¯wĂlˆ;VÀé…ªä#PbpªÅ,“đ"ô'‚3—0(O•”ùÁí”₫†?â£è/ªÍÆ_vfØu ’7₫ÖUÂbI9,)¥2”~çX²vË¥éûơn³ù8:t*Ư¬%À )ơ~Q´»0y‰*2(ú÷*Œ9GŸ{P5aÄáÂ-ư¬`Cñi´WÁ…Ùöfăƈ«dÄ¥@å« Mj©sÀ‡B‡»Ú-Î ¬ư°U×¹Fơq¡Y’P#Œ£R’k¼(àÉ-(â¥Sb‰¦‡ 0Ȉ"8Ñ1∈é̉ù¢äø ¦ ́±tS`÷₫‡¶ZUg›°È^Ú„—}NdI•BP—7Đ›K1Ö’ü#Sâˆ@!‹ÉØâ;X©¹S«Î³/¡¹A•ƠµdˆQ₫°ºÆ¢º̃VŒ‚”’1[¼5¶k̉sí/Z»Ö%ËÏÇ7æïºêæÜßÙÜEC·®œˆ€G•À÷—•ívƠÖvză—ư¼7+µn»Éă5Æ-£k• ¡` éc:5)E¡ĐÖ•ä*Ùª!ŒÎüµ3ưº¡Œ8"ñ Œ̉$ë0tµ"¯6»©:´¤>Pß̉r'wi϶̃lễ,ÛfƠ'»m‰ü5 À &ŸBZW “C>P7¥©A@FLd¼$Đ×Å£À•B­«±y öP½åˆa+C ö;<ÿƠ¶½Ér”l _˜ª (®ü“3XË›0ùvÖÿô ̃,Aá¤éU¸ÖUr¯’h$–`“qcÊÙOô¢j+~Ûm Ê|ơÜ :r´Á·¨GªÁ)Ó0#@Ú˜\ªae(®àÙ¸Í é̀&b$\:Ùøëå®›‰qˆxfàÖ‰$Qs‡l̉eérKí($•”Zú¸ÔâöÎŒ=‰Ô²¾è¸¼îêÁ<¡Đº[;4Ÿ¦fÁÅ|8TÜG9°{(2Z̃_’M¢<ˆ a— ¸íŸăî7[E—©ßJÚ¢r5ơÛ±­MÂăNê¤ÿ_êd ¤«ÔOAÖ•d́_¤Î;·j‡…'x:9›XЦ‰!0\˜»Aàñ^TM¡©áë.>x;t¿˜×»ă\†íctz‘îh!½H¦ƯŸß̃yßö¼‘‹r¶¿÷÷Ëv{¹1¶µ=ñßBI\¹í7Ơ°¥’ÉXÍXWT«YœÉê É^„d¯Ưq¡Ó‡dÖÂßœY<`Û!€xw$Ôx“ªŸœzÂ’ÂmB#ØƯ—±’ç{aIŒ2“Kß½íѵúE¹ƒÛ‘²¨ç«wßü HQ"ÿyÛ…¶nëDv÷!¦¯ñße±M]?€Ÿ+ë$ш‚T$Ï(E,ÊÇ1 p&̀ùb0ÓcC°KÊeđ $¢Ư«œï:ó#”¶^Vư$6‚™såé‘̃hĂ1«…éŒá€ïf]G˜%¹Œ0°̃Ï×Ê\%©ô8›Á¥b{?Ơj êo=aH0ÚA!¨µúÖ~øß(,&™–ôîđ₫à¯]¯os·WŸ¥ªẈ(ưSètXơbÂÜ¾Ç‡ÖØ ăṇ̃U=2íHY:°¨ß³¸Ơ´Ơ<áÖzªvÜ9 d¥h® ÔÑIʵ·à¡iÊ¥8²ÿ±I¤đ{p¢[:µ Ç3‰Ï[{¿(”Î?aÔư¨hùD¯Q1½¾¶> stream xÚåXÛnÜ6}÷WỷĂ«$(Đ6­‹ä¡M“-úäA»Ëµ•îJ[­d#ưú/ºP¦ăµc´H k]FĂĂ™á™C’É2e9C9Ë¢ơ₫ ›§ÍEd/̃ütFœ]†ÉẠ̈ûåÙ³s!"‚‘Ä’DËíÔƠr½‹_\‡V5‹„1³ç‹„sŸ/rwƠº-ëJ¿áñµUªÖj‘Đ §2æùâẶƠÙËapAœˆ´·¾7§ã.MÜÂeˆPD‰Hiüm Øh¼n‹ü»Z0«ÔŸĂH$Ăˆ¥Ü¸a\èq̃}ÀÑ^¾00̃µ1ƯGq’ĂƠ.z{ök ÉÊ ó!u›Ă€¸nÚgëºz ¿èµ\H«f_VE[7Ø<4Ç3ˆe(“ÖÛ;ˆ=›ÆÅçåN}pß§!H Aơ÷ Ó±ă)@6ßÂàÛ̉ =6ÅÓa årØơ ́̀²©w(ä“täÔ†ä(§²7zr“!6•¶A‚b XL‘`¼0C©È¢RBÄÿ!^*6c̀|_#JÈé¾®›²U·%@¤ˆçù] H¨àH’Ôe€Xë·ªµoÇ0̉ØÖW¾{ûâ%G¿´÷Ƕ)« {½/ª̣Đí “?3¦¿æ0ŒÊpf°—Ơ¡kcÏ€_C>d ±́|°„í“z¥9&₫¨Ömh¬Ä¹ñâ0I”?$…$³!]¬v6RW ¬ØuʾÜö\iºëö̉̃êr°Eå.LVĂí°ÄY=y0y2ơ0¿9f»pŸ£¥|„º)€ CƯ€ÓƠ<«Q °D~€CµßVU> hBÖcB%â©#àå¥éqrâYß­‹Ê^¬úéêU¶—ºyêk[ÔÇ‘x& ’q‘ay= Înưur#¡ùÑÓ< ùHkñn»mØÉ$A'9ʲ)anÔ¶èv­&– ,M)öV\ùˆëY8F.™<[í’×g·¬@­ºè³:¤›èrÏăkư£”3Ç®TjûŸ BÆË¥Oe¿tí„ËÄg¸́çºê×x67ËxØ•}±;ÖσKäËH~SÖ ĂNAŸ@ÅYÔr¢ÀØCÏ ‚ÑC€iWDÊ€ơ%ºăe¨&ôƒ₫zª·&́äiF atB6 XăíntíµO.Mzï£6ê*(6<…06âĐT´|ç¿?•ÄÍ(OBNRD³Á¢ÔÍ?ä‡f(—sG₫¼¡÷µA”å3-W[´½¾¸©&ÁY¹VVs8 &JzT[°Ằt!†i\l6¥ÖĂFÖÀs‘¢)ö¶ ™Ư:X•G÷¶©u8®ÊÚØ7u°k)P³Ó›ÿl¹yÛ5.ÄgIèù¤Ë†đ°©ÍƯ=^¤£5NÉ}”„Iês¯«Ư'L[‡:ºf̣æYí>ĐB3›E_‰N—»ƯTÆ»w ruw¹~Å?D"Đ”‚|KE#h_)°=€R×HÚíăË̀È́˜¡êö«O­:†èƠßw÷-Dăë±Í¸>åô”&2Ơ«st³?À.]"8¨±au!„BĐ%’)½»MHç̉6¿ëØëáqØÖí ØÏm¼Ó„§¢{»e óƯ/N‡ÉvÇá|¢> L wCĂ­n6f1k察ÿöĂk{QV§Û±ÀoƒK†@a2&ư5srcêO&B“ °Í†—.\…… _/n9ă@Á ºs7MÅé!4 Æ$ªß¨»/'9 Só“° Ê8ăŸ Ù¿u{ư»2ÇăÂ35–b2Ơ B<7¦¹;R¯·Nt ·c˜á€Áï½MûÿM₫ɸÏú†?ÅCøIÉ£Đ§$(ÏBäiNv₫Ú¼ŸêQ}±êó´Y x¦s¿î0|Yß8–©[üoltYÿ &Üw~ endstream endobj 1067 0 obj << /Length 1402 /Filter /FlateDecode >> stream xÚƯX[oÛ6~Ï¯Đ£ T ¯"`@±u)Ö‡]̉ }Hó ØtªÂ–=InĐưúR”,*t|I†`C€¤•Îùx.ßwhaø!‘¤‘T )&£ẹ́ Û§Ơ}Ô₫ăêưqv &˯ÏÎ/…ˆFÎHt=ººE7ñO_̣u£«I‹ÙÅ$á\Ä—ÅăM9mUi>áñ•ëJ—S=I¨Äiólr{ưá́çë>¸  ÎDÚYïË…@§;EXđó àcC|,¾,úÖ :¿LeDÊ„ ÆAÂŒđ€Ûwgy“·v"Ú1‚˜¢Ơ0W:Ÿ9¯Øƒ•uÖYƇbsDá„Îhu÷ƠÅ͆6D!E{OoBn$b¸Ç_ëH'ÙZí÷³®ô´¨M₫Ç)âJG\H¯62+3%„!"È!µñs>®ÍMu¨Ü[½Nïù™®6e³¿ nÛ6Ø× )¼¿-ôSƯ@́›?„P(*‘ˆ¦Ù¾"QB‘ ̀éX£ú₫ƠUµ¬ïƒ$J…:¥ÚôߘưçW;¡˜ ¬„?“Wp’z `kÎ(‚Âù-Ä¡úĐójµl‘₫ùî÷V²nªÍ„Äđ‰u9¡*v•ƒ: ®,XÓ%°'&£‹èăÙí>çC"RØc_;H›Ù Áa2ÏçUÑ„GKa„®PƠ½ûœ]°Ü,ï¾7ºIƒ]Ô`$0ñÜ©ª@_x#ÜΑÈ×ÛûÎPÆØ1KÜ &Ơ íΜÂâ5¶́7½ö– ¤̉/¤ÇêŸL}LÚ²ÎeåA²̃£ŸG¢¾|RÍAÍ®aƠ\ư'Ơü4)ê”ÚvîájôºZ,(F¥›MUº<÷J(­J§„Ü¡`đ ́Œ÷YhtÆE€ç%ó7>+Ạ ¢ MûD•‚¡• º×Í~ưÉO•fÀ¦Á+g@Êb¬>=®Ñ—OrÜơÓ× NØÛ ôNÙà ¥”q­|:óB/fû¯h/– ̀„Oö~&!ûƠZWÍ÷ ×Ă.HÈ^®'’"Ôø½v ×|ÑíÄ™Hn2›¢Ăn:ÛV~ÄŒ"₫ª§†›à â/e^´­Ñá7eI ÈhKn¿LtÀqRj¯®Û†%àÏ7ó+Àî? ²L2†'c–à²' ÷$æ“„‡Œ+£ø'œuºÈëW8Â)”™»ôíăVưǼN• £t–ùRû=đØLæÂANO_t\AL%Ôp2<Úƒ±Ë]k×®Û§ÅgL¸½é.ÊFµ¼Ù\‡Êi>Ï›nx`CØ•(‘0Ób$Ü+đ^=µîn~]\îÅ\·¥È‹Ç5)ºKdwB·X´°©ú¥BrÏ´±“Zw!êƠÅ”ö—· ‘ ¡cÇοÅЦÄ8ÂY`‚ÎkƯR‘‰ÿ­̣— endstream endobj 1070 0 obj << /Length 1575 /Filter /FlateDecode >> stream xÚíXßoÛ6~Ï_¡·J@Åđ7¥Ú®ë°>d]ën]›iƯÚ–'É)²¿~G‘’E™í,è€v(P;2uüøƯƯwÇ#†$R4RCSÑty†Û§Ơ‡È~yưóqëRX˜V>›œ¿""å8'Ñäzhj2‹̃Å?~,Ö®’”1³‹$å\Ä/’ŒÇ›Ơ´™—+ó _ëk]éƠT')UXæ±ÀÉûÉ˳Ÿ&ưæ‚ $8;i·znF#¼\*ÜÂeˆP”%©4~R6O›"›„‘Xw ₫êw" #&yk†qaöy÷G3øñe„‘€ư¾´K—Gœdđm½9û-„†(2Â|H›Ùz @H\VÍy¥‹™Á0¦faÇ¥I÷â; ™ ifñ‹ùB¿·ïK‚r!¨y?e†&.]ûSÛ}äp#ˆf·ê‡ÄđoAI<ÅM8[ü'¶>oÍå½Ạ̊êSÈÉÀ‡C$̀DTåQ Œñ p ̣áƒÇ!+ 1Ü£¯çë È ‚ÅA.P!3Ç%ùŸ̀LߌOæa;†…ævtŒÀˆrÈ1)Q 1J}ϼÂê-ÀírFÈkÀ ¾·9¸*ëV]Wå̉z÷íóWV竺©6 ‰áPÁUB³¸±–|K…BÊYn ₫²Zo 7ÑŒLáămÈ>××ÅfÑ\Ø'Ïn]?…WE\̀ÅƠBχq;,î6¢ ¦Ûµ:‡̉$s/½W¼c̀ÀͰƯë,Av#œ9÷₫ºiù—> É2ÂÁr„M q´µ;¿Oíæy„”R»-ªd v׺y˜̉í+èXiÍ6­îÓG_r·)ÇIó;• ¾*Ö Öº*׺jnC2éK[Đ˜µ~ÅÉ¢FúĐ÷/&QŸR»¾'F}C>ôÇI*I btûê"@?\¬ È¡ùö\ñÆĐÙ äGm%ÇœÔ4₫ ©ÍÜÊ'wzÄ\NAE¾ ªvå';¶üđSËOj˜²X´—8°‡¤mÁb£=‰‘%ø¸I:ÁÉR¡’ƒ,aq¬Æ²ÄU¯J ¤†ùªäïN1H"k-)I‡¢ä U è²>P§‹¢®÷ÔQ‘#iây×ù̉”G[d‚[˜Ë±¹*–Úwư®-Èá T"k"e á¤k4‚°_‡Yu"¾Q³1Ơ‹…}P—öojW^!ö ä)ªú¤́†=5Ql%è± ¸ÆBEª½b±m!¶ƯGÇaaẠ́xY4SsàóƠ‡]z!í±¦)ÊÚÔ ̉]ă'Ư6×̃µ½XtÓ©^w v8N{tnA1¯ê;s×yôUkÉTo« á$5"ƯÀáÑ%„Ñ££Đö|îjP}pIJưæ2FuÄ[ÏĂßSăøÏmïé5ÛMS!A:€ok]=‡g?Èá vé¦î:Ïm§Ô5o}8́jäa`“ùR—›æä5öÍ>eïkswpÉ¢§åjV#;úƯŒ€¶‹ºhM‰Ë(]¬\p'¼Z8í4lîcx ñöƯD¤L~£*åªKJ5^';t—cuy±GGí“ăÔ_$@ƠIÆ¡·=Uưư¢©,Á¢igD@ưÏ?èpM fæM¾¶¿&ø´[–d‘©ó×`Ă)ÀØÊPNX Á₫RÍ›°–*¤¹¶<ĐtlµY^™{[¨Íñ, 44ñÚèÖ’☑;b¤q ¿Ü™ÉɃ=6‘àч¶}c”ÆḌ;ºnæ«ÂĐøt6«t]љ뮺{ú”R¸!›•?4ØÚƠ7>‰Đ©îEÁ₫ÛV²L=ܨđ¤P0ײ½‘Àóa'ûç…wÂW .ÿ£<ưœṣưü̃/d|Äoe÷Êøđ•æHe#ó˜€2¡¡ê2uÚº)A›ăRõ¶ endstream endobj 1073 0 obj << /Length 1486 /Filter /FlateDecode >> stream xÚÍWKoÜ6¾ûWèf-1¢HR€’6IÓ¦IlON²ÄơªƠJ[=løßwHơXkmÀ°½Z gæûæIê…đC=y2a$ảË¡ù¶½ñ́‡¯/(Ê ̀$_l/¾£!IĂ”zÛƯ\Ơ¶đ®ü÷Ù±Wí&`Œù́Ù&à\ø¯6 ÷‡:ï˦Öo¸ÿQíT«ê\m‚H†qê ºù²ưåâåv4."AgôÔI?p7‰<ÊH₫jw“˜P :£˜„‚[—ßÔÇ¡ï´y—ÎÁ…^@%‰ 6×›@Ä₫Ÿ(ºà¦„¡•,;K@fÑ₫ñÓ‡›(ñ›¶·ß;M*ïÉáƠà:Vg‘ơÙ刓„§Î²‘26úÆ¿kË^­[Á£Ö ôÚÙû#Ä&ñƠM/l.X;ë@±¡>H› ovömƯ @ơơA髼üR® <¨vÙPơƯó‡²Ö¶údº¶Ä¤º¾¬3~Ï‹¢U]·*…œ t á1CÑ€3a¬sđÉx«êÂ>ơ  ’<5¨´˜Aeä ‡è |‡₫Đ)Ô·ÇÇVƯ–ÍĐU÷ö$Py«Moè÷ômè9—¸ëøÇ<\!@J"sXcÊ:ú;9đœóÓ"xNM–!R@é O¬¡Âh̃ă¬e4hóƒ4ü̉ƠÆ Â$]¦â÷ cÍ:'Ÿ ¢mªíïë́ ¦¢›„%À¥̉I?YÓ' Å©¾Û¬V&0̉äØe !k@R’ÆÑ Çj(‚(¦D¹h ï±EƠØWMVÎK­jwY®Vs=\fù£'©†n·vp̀8]8Ç„Gâ„Ó¥ê˜Äq<çt¡øvsvFđR{Jd<Æ7À®sªÂ–¼öđé¤Ífekû3åI`¡(4êsư×ºÑ îjG'°c•¡ ƯgúRuÏŒ’ĐŒưFöô;M ÈˆÈØ¶³®+oj; §Œ”›ê˜ aŒ…nốmcæY5í%©Œüª1^Á÷è§yÄ„àS›LL›Ô­y>iÿ¹éàh²¢yõ˜iȧ¶åA53*$¢{̉§ b‰²vÓ)oê¢' µkp#½Ó¾g%LĂ+3¾qëƠ)U/kƯ­MŸöY«ÏjA ½ln/,đ¦R™‹ùî$Br£ơư¥ÿ(´ÏºUÎ;´h„”qAé¦Ơª¬hêê~*ü“adœéăGäÖ æyk;¾å{ŸUQ3Pa¼ă†_Ö]Ÿ™wÁ•̉¥°'S‡Cj đïvă–O})ø{ÜôY㕦đ_‘$zÏ¿úz¼„ØÁÖ́ƯɃÇH$uqW̃§‹ßñî²0ÏÂb'Œ*ænÓ€Y3ßÓ–WYçV| Ûl‹é`i]ƒ›hsÑĂI¶¼H€P2 ­oLĐX,ăúÁôF±§|-¾üa|qƯ™µeVđvMUÙ¶6ÖĐ¢>\We₫}4·íÉU$d¡ÉÆv8(;Ñ̉('}4q‰™nêï̉~·Vfç;̃¿î§gKû¿é²ßV,~‚;ỰO¥ßáĂt­›ÅåẢ\ºZ#…®Ç^æU=ụ̀ñ ¿‡ đn8¼Đ«ÿsk±¬ô}Vo°ëCàLPÏÜ%˜Ÿm«óRú½ÖŒëö@½n”•Û—ùX·¯°ˆmÎäoĐ”Ê<ëú×m3O}·2Æi'g ̃iË́¹ÑU"ÛƯpƯåm‰¨OÊø±~Úy«½5Nüƒ6«Çơ}zy©ôU±ŒÍR=Ă₫ơq endstream endobj 1076 0 obj << /Length 1430 /Filter /FlateDecode >> stream xÚíYYoÛF~÷¯à#”›½I(Đ8‹MÓ&*úàú–)›©Hª<¸¿¾³UÖ•¬¨iSBJùvæ›c×$Àđ1 â„¡„ÅÁª<ĂúÛæ60/¯¿9#V.Áh&y¾<{r!D@0JqJ‚åz®jy\†Ïï²m—7‹ˆ1²§‹ˆs^,öƠª+êJưÂĂ×ù:ọj•/"c™†‚.®–ß½XÆHpv ̉AzÜD"ƒN*Ü@~Qe×›üÇMºé̃ÜeMQƯ*4ˆ‘ "ÂÄÈ×ä6yV™=kó́îr³µÖˆ¬”¾ßÔyg$î²ÖHlƠ¦•-»ÀZÔB¹sc>üṇ́¦®6÷đN4¨È¢Å©Aµ\$°²)‹*ëêæè;BÚÀ»…a¶é-ô¾,¯‰¶°ñđ&ë² Øªo ‚jƒƯæ̃|]ƠƯ¤hüä"¡áˆqIU¢˜ bA Rxjp€“-"!iøó›óåËçÓB†pªö¹†8G䔥ÓD̀¢¯À猆+Àw FÂ|àÓï#IHŒ“<4E)%"—W8¸¿ 0`î½-8Iàm¼9ûÉÉCb´.ɬ‹ûöº+WOÖ«MƯæf .ưh‚fjïÉÔîựBEf–,¼(6ù•Q 〔 aœÇ½¹hzm“·Öœ‹Ÿ…¾\¨ôç°$ĂI)q\Ÿm($˜ª¯ßú4‘%4i">7D 8-véù\kÍö-4•VuUåÆ5FSêØc©éˆJñ!|ë£O4È*ç§©5ûmµí»Ö§ë“ŒûT»û!)âP-ˆÂî"rA‘Â|5( !/FÆä@>Ë D!º đ< Ï•*LR—ç5T2… ÚÏuú‰¹^oT.A9p I¡:=€ềazĤ˜©TtT Äoú²T•ó̃§hJ¹7‡p 7‰^muïÉ+  årL$ơ¾/‘$'€¨â¶'HÑ…Ë»ÂÛiê«á§̀<¦mëë‘êSWÛ5å¶©•Ô;Ư<đå6ëëbSt h÷¦¨\Tî4:¥Hëå3ŵå÷ÏÎưå€ëQÀ©:ƠØ1©Æ<©8I®)]x¨;C®©9à“´Ưå=yÆdƯͳ Ö±yv–¢Ư€™Ë„ÏÛ ;ơĂqĂ>51bS!l‹?¼½̃-—º“ÇHÀ«qçÿ̃œ¼éêq½¹_϶ÉWE;Öà1L"ÄûBCÀ³q<†é®ÏwcséC-÷Fï€Ư;zVu_uûipeh° Ösv\+ÿk6hÿ!„¼åÎ]r9‚v/(ûéAE#ó¦)Û[¯&˜«ErL¸éß‘üîˆb‚p"œzù6â=Y0À¢'n;%â?Z^7ui€Nç œÏû̉N]̃1GÄ0MR;æĐǡǵYMN®̀ îNbÅFêüĐëỵÚL½öÊ¢^ ă内fæB*‚!u1Å5‹¾Î×Y¿éoÆ*È~ Öø<È;ƯËƠ”§ö;0Uüư‡A»Ü9 ¾ê»}±cáỞ\[1í•íîß,u¥ÊÅŒ}®-†ec´Ü€ đ²ëCN9q­H=6ÇÄ̀^bƠö4ÔdSÁ-æj‹‡ẽ¶Ùmî÷=Œài2øÎNü˜Ód =Éé@éâ|çÆé}StŸæÆ©êËëûÎ×L2›æäW8wlI§'ç¦ä8j:Æ)JÙ rªî’úôcị̂NåÓ|F¶Cß±SªQñQnó7e¥3>¨)Án²êĂ®wHk†¾§f†Ï¥5?¦¯L+Ú®f́á}å„UƠä?ÉrÀ endstream endobj 1079 0 obj << /Length 1396 /Filter /FlateDecode >> stream xÚƯXKoă6¾çWè¶21|? ổ¢[dQ´h6EÙ`¡Èrb@–]IÎbÿ}‡"%‹µ“´("‹£á<¿ùH’`ø#‰¢‰̉ i¦’bu†û·Í}â®~>#^.Ál"ùĂơÙÅ{!‚‘Á†$׋©ªëyr“₫øoº²™eŒ±”}7Ë8éû™æé¶.ºåº¶+<½*eSÖE9˨Ẩ¤‚Ín¯?œưt=n.¨@‚³#-¤Ÿ˜«iBÂ`¯5WKDè¤aÁÉ¿m»Í¶kí₫û̃á$# Iæ%›²Û6u뜫gT§ÛƠŒªôÎz‘:¯yº^8;+đµ+[÷úK³́º²FnŸĐ¬Œđ̃® ¼`ZºƯ 1Ë„¤é¶½ëVÈD&4’FôŸbí³póË:ŸçwUé,ø³!₫·N‰T !ÈAûư-Ø}l'§’œ!ĂF¹ïgẠ́OÍ“đ)§ƒü'íÏƯ ṃî!¦ $XNT‘X<2B ä ¢Gñ9̃@tZÖ. ̃̃₫yYÛBÍ.̣¢Œf‡y¹¬'åb)—#¡‰ Œ‹1†™3£{(],ûẬö¸µ^Qÿäj‹§]_[̃)·ô±k–ơ=²ÇÓK/·^Ù¢›;‰y¹È·Uçë·[;‘wó±JHúClHßÁïx½z‚¸ßG×å4¶*útöö´yU¹e×oCÚ.¯‹ŕ±Hü‰¦È¨!°ë>:E—ÛX=ÎúHyŒùk†1¢6Pÿ”jÜÜâdkŒ¸J¾ô‚«„! “*ùxö»GÂ`s†mË^•*̉Ha߆˜¶Ũú¼ä/º!HMÙBÖb₫j N£MîÅ‘ÜuN<£̀@gcíSª&$÷!(Œ ‘)nÁ@T> ¡€}†rĉcZAFÄè^×0QjƯ–Ñ6’ H÷‰ÈâYù>O6 AHc¤9ÏX,/¡2=!ô· kpÔxDós¶7đ›È‘×s·Ö”U™_äîß'Lxå¿—mÑ,7Ưºy=Ä©>­₫³ă›\R}~R“S¢£2áêÆ₫+ºœR˜¤½*F̀Q^ ËEløKơ×u]F,Ôq]ÍR)æỏƠLC‡6p©|₫¯uơM¬I%äzÅy%Ñ’ó˜B¡¨Æn/ÖÛº‹ib20Öíí̀RÖ=ơy”(@i¥N¢QAQÀ ;æYŸb;¯ë(±›Fï tÙvP>S躲Nöy\4ë•kơ)!k«i3{tz\¾19ûo!“¥!úuüc@&«J ùrd Ơîiʧë˜J-§öâÖ“k{J̉ư)I§ĂÙđÀ)ɱRQ@[W›.¤ªÍX9Ă×Ox0P_?ïËø(Ëœ™ÏísecÛ»×)pI¦ûñÀøL(Ô èƒmQ”m»ØVƠ× æ~œçYốø̉bvNïeÑ›$q‚y!s¤¹9äÆ. {©ṃÜ̃ÓíW›¦ï„¯ö.àE˜̉Ȭ̉ÇÍ*”˜y“YEq ÷,ÆƯß’‚>ø®cÓ#2{ccb_̉jưÅ\524ôñCcW\/;Å+à†…û§ eï«;ÏÚ-€ÈŸïûi¢&Ó„ưÿ§ 6T¼Å4±ª¤!ÿ́49 ˆ¬đyxÓ¹ Ñç<œ+wS!%ÖĐxî>‡d̃Øø?œơî~TN°ßư.Ö«MUZ9w/a!v¼™DÚKˆS+`ÛàÀ„ƠdÛ{ÄÁémÜƯÖÈÉm‚( =és'Ă!"§)‘~¢8m੘B0 Âê9|?C¾«"¤±X’àfÄÆóo;ë6 endstream endobj 1082 0 obj << /Length 1398 /Filter /FlateDecode >> stream xÚíXmoÛ6₫_¡0±|U`ÀÚmZ´+–Ư€,‡NTØ’'Ëé²_¿#)É¢ËÄëeƯ0pd™<>w÷ÜI„áD2ÅbY4]œ`û¶¹ÜĂÙ'¤[—ÂÂt´̣åääÙ©Á(Ç9‰&³±¨ÉUt{S,[Ư$)c,fÏ“”sŸ&ÇëjÚ–ue~áñ™éFWS¤4Ă2O.&¯O¾Ÿ ‡ *àlO¤ưêOà*—´‡K%‚;¸ ¤B̉ø}’’ø×W„nCÔ4Ûp”Â.•ç›]ˆ¸}ßÔ §m‘À¿Û„‘X÷ªü>à#FḶHæ9â\tç8º‚_G 8î£]ºˆ8âDÁÓ<úùä§0$Hfeđ†…tûGIȳÙt^¯´ÓÀ÷Uaö¡ Iåöœƒ_ØØ/,>-çúÂí—YDÊ…°†K™±+ Çno£WƯ1r¼ ¼@đ°èëÄø%£’xŒJ$¥è—ÿ†ÍÏv‹êË!ID!Eó‘$²Bªr²S°&¤c¬·rê¿·° ÖU¥eœ Ü;R°F¾øCˆ;pX†0¥Öôy6¦=ˆBL!ÉD!ŸO¡z hAµ›Fä‰yT/{T¾óy˜Ê÷¡ƯƒF̀cQʤ‰44؈$ñ¬_~µ^,ªâ»`±ªäN~& 9ù}±º2$Íè@RxÜERH|’x$•=IưƒIÙmÄÉMÙ5]7¦Víüνr?±¸p_7ZÛ¯³ à[[w{˦6«n͇v¦ơbY´åe9/ÛÁn :Gœ  +hơö…aÚäÍ‹—áHƒ¬œ9ræjǵ8’C®àG‰3# ˆïÅY£‹«§ÈÔWè1FƯ± ªCĆ8™ÚZ3?₫ƯfØJ¾ ‰ÉÛäÀUùg°„ú™̣^ṣ xƠÿÖüToÍƯr––«!ÿnu7q•ír Ëf®ÁtßæÛ¾9¡–ˆf;½·‡öœi½®ÚƯ4¸p4ØÅ û9;¬?̀k?„P0eˆÊƯé*½ ́?́¤{ ÖM³X]%eH uˆ»éßüŸïî”b‚°^¾<EV¡>‹Q'ü¶•‚Ç쩨mǛQV«¶Y'$^h3º¾+Øéˆ ÚIêu:¯ªåº âƒéÔ–ŒïỢlpJÙE…ƒ7 eĂÀ£§h‹BǦ°± Gyw+¾€iƒ~\Û–̣̉ơ½ƯeB=ëP$¾˜¯û™Íơ†<6woÆÆ×aœƯá^lo%v-7w àá4<@AçuÛ¡ F¤ë ß­Û=½·½&7Ú¡±Ñ·g[·ƠÓßdưü³F” ̣̃̉;"tP·oL/©ø‡HÛ:s¢Ó́ÛCM±I» ¥nÜé ½Z×:lyâ•oy; đCª`¦cä(Uø7|lÊV?É ^­—wmx·=Œ5tb+ƒ;4«Ó#·t›À8¨AÆ9Ê;Zƒü(›Ú:y¯I?ç’́X&ưÇ»dH̉P¹ÅÖƯƯ/ÆAÆnẠ<ËöªËƒ7ú›†`U6µN?T•¡à™¦a|Ñ÷…—ẹ˜ªbWyE×’vª̣Uñ€íƯ®›ª3«u°é@2Ûd]Â; ̃Ûª¶¯wÆ­®Đ£®¤„«8·ÆOÖ¡ (’¹đo‚̃ÔÅUq9ïÊû8CƯ“—:!xT\v÷đ}¢-$%ù¨¤T.ƒ 9 V‚î ÿ\@]‘÷\Œn…,ƒµAj»è"wVLí3ê«ù_ ÈdÔ endstream endobj 1086 0 obj << /Length 1357 /Filter /FlateDecode >> stream xÚƠXKoÛF¾ûWđ ·û~è¥AS4襉‚£ ¥•%€¢\rêßÙ%.½ ”Ø-©åhvæ›Ç7\R`øBÑBi†4SÅb{…ưjwW„›÷¿^‘(W`5’üy~ơĂ[! ‚‘Á†óƠXƠ|Y\—oÖơ}o»YÅ+Ù³sQ¾i^ÚE¿Ùµî /ßÛ•íl»°³*,M)Ä́f₫îê—ùqsAœ]hé ưÔ\36WKDè¤aÁƒÉ÷u¿v›O]Vpª‚KưÚ6÷a¡^.;»ß‡»UxØÏ¨.A.6<úĐw›ö9@xùÛ*Êo7}o—áOK»ªMUơ»p}E¨B>ärVU´«"à 3Áºù:nóđφOX`ø’ w¿®›&<ílèÚp¿i÷}í#-$pVH3`°ó-úÚ¹÷0óÎŨư} 5°Ơ…=D¸8\ßàb Ï̃qU|ö‚Û‚! ¡ÀES|¸ú#,jÂF d@•·Á;˜ ÉÁ̉ES1©÷1&D.€9ç®Ö`1tœß)I D4-s±q"“I ‰IØN‚(C„#9«„¤_EÊa‡A"(bà·„l ¦ ØjÀ#Ntaj iν.Œù€Îno³)´VËÁêëßwơ²¾m"|P̀l(曨D„ # ¾ ¤ ö”8é àĂIØ¥n”Rc¥QN3‘Iu1‚˜¦#]ÙøUW†K¨ æă—·oRă­Ëqhg«z¨“ºƠÚÙÆÖĂ?êpù„ óPÍûE·¹ïwÊ¥Në÷²¬®V.?S¹’"rBâ²Â…2c’1Ę~Vå².1*‚ÙWWn¾¦ˆ‚đ*©)uyM“\³—©)ĐE vt¶^₫o%u+hêă²†`g4Aï"ø(ơ:§‡P$;Æcwhûœ¦´Önf‚ËŸ PÁ±æO˜¤ej ’—<˵bs̃ˆ¬; ±“ĂmΜ¸³MĂ•‡qw÷ÎCĂU·Û†‚ ÆúÅ}3®¸Ø6 û½ơ!$T¾DOpª¨!ßÚR¥•«EE•6§rΨ jĐßUyØ:çoðÖ9«nëí0CÄ¡¬†©m{ß'5:@̣ï'c L~‘Rîlǹ`WfặϤ™1©(aDçÙ×ÎX *„id óª0&§^6!Áa†„Ûă ÷yüàG®cüœĂbáz4 ̀«CÓ<=pp·isA¦2Ø8êHÄ\”öEë¸ï u·{´1P9Ü8¾÷¡`@ÄLJ|k»ƯÛ&̀~(¾œÙ~ÊÈôă4Ï9PIj/(Œ3å{á 0˜S…a@₫́‹íÂLâxâ§ÛñɃËî̃¶i¤oĂ_QüQÅ›:Ù8j±P0áÊpÂ׺ wˆ¯P:CˆĂqFp)IœAÄq̀=mÊp¿0Àö¾±®¼†JÏñ$…¶f´5¬Ñ́9> stream xÚ]Û¸ñ=¿Âo§Ö(Q¾>åÚKp‡  mEÓ­DÛDlÉ¥¤Ư,Đßù"%{•ö`5$‡äp¾gµIàŸÚ”馬²¸ÊÊMs~“Ь;løë‡7J𶀸]`₫ôđæíû<ߨ$̃%;µyØor¥ă"ÓἇvóÏ(/î₫ơđ뛟ÂIyǹÎ~çµûƠƯUºQeœª\ăƯøŒ´ˆáµï.—»m¦"Óµö@e½»ÛæE}øóßxüÁtÆƠ'|O¶aø£mL7¤ûö‰ªØÅ»Jo¶@EWưư®Ê"ăÛw°?Ë¢́¿é¿:úuêŒ̀$I‰Çn¶J«XáAªˆ³$å“₫Ø_î̉*zqöpD`$Ü\Ç)Ä¡ơs¿‘ˆç»´Œjg8ưÔµơˆïUÑ=¿ñ—®‰oé4.“Ư¦¨4•’ ăÖb˜Lb•’įg–¢÷û·‹Xíåsn¯¡WÇṇ̃ăÛ·ûa÷îđö–4Vq¡Ê+̉¾¯ƒû5!×|M’¸Úy{₫ü„4î?=ḱÀ¼ ¥Ơ³GỌ́ÜØó·AU(£Ơ,·v}œFÇ"÷̉8‡ÖÈư/p%ªRú–Å*gêN¢ç|rOÔ4ÓÙt¤{"X¸KÆÙcƯlwà;^¿§ëµ>ú :¦Y Ñ`}ºHI]§üƯÅ*+˜OÎÔç;0ÚÇÓªñ!ơ€VŒ₫p̉ÓbÇM€·hx‹FØ[4 \üÖüÙƒÆßăÛSf:ØßÉ€êÓâi¹qß;†Ù4*6 :…„@?`~µ]+ס0đK›z÷uˆƒH.€U–₫fÜ\Vr5LŸûadh…@d"`ÙàÅƠÍhb ²ĂÉ­́¡3²‘¾ơW̉aAo$N1ΠʹŸä:dhÛŸW”{WEĂ‘ưÉNèÍv»Y½da< °à×¶ĐIôÓ Ï7=ë©«ÔU­´ß#H³‡AđñÀ)0l³|"Ä 2G¤¢¿z†âw¦ÚƠ‚‹G$»ˆ-Y€#ÏĐ«áë_ˆªdI…¯.Ă«qátâ1l */‘1'Èx^\pơù?₫ôsƯ5ù«ÈHáë̀¹¶Ư°öœ=ûü\¯èÎ’̣!ÀÔ`ÇiA0yRF¿ƯU:BSỆˆ0AFŸW/¸*rÂ4Èj8¥@* Pª‡l³¢pAʺHøºPbC8…<¥ï$K· ø<-ƠÄDÄ«/—yWœ†w½̀tbt& ®{ægN¦PĂhu8<áâ@dúôêi<ö$­uôf¥¸́ºct¿,öhfÛ¥ÄZ5ÜÏHHúª«úí‘́NXĐ(cQ"€éÎûÁOñu,=på½Mµê «œÉ­´x'@* å[“‹®Ø]Đ·ăMyæ ñ´¸mah»R]_Ëæ+r¿v’PÑy~iå‘ḅœÏqîg|i`w¸I;dÛ¹ @?¤¦A*À-âº._˜ƯÅl°ˆƠ™=OÀ& Xp†#Z˜÷ắ…K˜mr »(Óœ©àÑ=¼Ô ơđỠî]aX)4^‡AŸd›zP‹ă1ÄU;̀ÎÀơ䯲]¶ĐzÀ¾¶p<¨1n¬Y 'üÑí£=Ù‘ótX" ¯̉¥ÈƠuªăØWäÖsA³ê–KïJå€8y+eÁ|LÅ,í>1¤äđ̣–pT. "ám¬7Y6Ó2§B™RB’_*œ ¥%TƠßêóåDôWBw™-è.o*¢rQÿ”RÿÀw˜Øßñ¨æX œư|4¯q æGëϹ½h;˜rĐv9áª3¦a\ñĂ—z ä ¤ˆ‘súå^ïÿiá]Píy”µ> °6 çÈƠB+s|1b[ iîœ#Àú—R… FWq¹8œèxÁDï₫{…\À œ¦×q@'˜‰_̣R³×IÎÏĂ*͇ Œçy½C/‰ ×8¼¦ƒ†£÷”¸ÆáL Jñ./:‡¼ăK̉ CÁá®Û™SZzˆe₫“áןz_ë·ü”4w!}Isøô‘å0{ä9«p¢*Kăg;å¼P‹z £¹ hÓàL0PÈy T\ĂÍ«&”WÖ•‚Kp½–ÏÍƠ(¬ă})߇Ă₫K¢2®‘Âĵ*úˆ ! “  Ó>‘_µíd\÷ëEWeà–Ûó×?-à^Ễe¢(@ó[ĐÓ¹¯¸ÈÿăÂTÅù½a¸• Èê@ơƯ¼ÂñÎæeZ/EQªDI`…u€ GÉ= ̀·Ë‰ª<•^Ɉăd#ù5øv=Eb¾å¦ÓkIKï# Ê|öYdKéS̃~ˆ}~Âï{dÏ€Ú‰C*`X´$[}gúi !R¹!"s‹'×3‚ ¤]¶†fa%¨@£ƒVUùs¦ÎOµ̃i>q±vI$í;H œ¹‘$¦_Ÿ×ñˆäÏ»êèa‰œCæ<ŒÔmÀIî}A"2aJÈđk╌ *¥R²zœø…Üm±:ÑiBñƒ™Æ¦&°{Ÿè8×ô¬i_7ăD‰.3˜9΀Ù8Ä¥ô¶„jå̀—ø«(¡ÀÈ™ù„ÏŒ®éÏHI°/J3äå¿—j °¥°·“̉;$ơRE'Á₫ô²[… \^'Wư8÷Gßrc3pø8XÄ 3PÛÈÍ ĐÆu< r¨?Ŧ´ÚĐx䘈q‚{̉ÍÄjsEUø*­ Ư«y‰’½‚*+V©á²À7°x;&ÖO¶ê“ÉæD‰6]‚…­PG vđCZ66Ă3F'DP½‡Ç &5˜^+ÖÔ¡ª_Æäˆ.²T×äÚ¡̉Ü1(çzB/8bOœé+߯KÄ ís ->“fz₫—̀7xô 5Y7P®Ư¯‡C0Ë»êçø4đ6¿́ymN¾^¾Gµ³|jÄ#˜<!˺(püúv6€ ªăcI.¿1ÈU#‡A-Z9‚|ʃ#vv×_ÂQ‘̀„8+¼ƒ /?A¡€VđöÓÈé2À×(Åϼ!¹g¨”¬d»¸tÎü–{÷ägÈѬ7Ú}%íÙµÅvÄd΃tª#~« -}y„ƒ‚}T‚1ø \¤æ%ơrº ´“l -KêûÜ₫†ˆ³<"ÔỜç¦Ù^öỘYÜƠƒÉù¥µ(7Ÿ‡Y’çö¼)².„¬‘Ú9/÷î–8KIË•´ƯÓäö)’ÔÁé |ÜcÜ^&'ạ̊ è½!;RÙÂ=Ɖ‘׬́fíZƠMŸÖ´=eBỤ̆”M ’Qq›F³×èmËS!u Uºål\ zxw›A]q”¥Æw»¼)ăĐ̉Et§#%dóoHu _k¬¡”lJÎüâ¬kGªJMn5w«Cd:K)WÄ́BŒæ>|®dꉔƒ‘kÙv£HT§r’đœ¤¥,ZÙ-tHéµe{°̉ѯç[TÊ…9ÿ7A>€"ô^ •¯W?ƒ=¶v¯“ùÀçN³„øóKrøo r¹Z ¦WMí‘đDo‰áç₫ÿ& E endstream endobj 1093 0 obj << /Length 3225 /Filter /FlateDecode >> stream xÚÙrܸñƯ_¡̉K¨*Í„÷‘7ÇönœZÛ[kå)ΆÄ̀`ÅcÂĂ²öë·/€äˆvmé@7Đh4ú7>ü7Yx“åÑ>²›²yå´?Ưđà·Ÿ_²n w‹•ÿ|xơ÷Ÿ’ä&đ÷…_7Ç%©‡êæ¿̃ëËånæn+óínE‘÷úüưùăp{?ëV÷ªfè¯Ó¡6%1¥n ‚"ó½$»ûßĂ¿_½{p %a²Oâè/roW¿¸B̃ñ>ÓĐ^!L÷~ó̃ưöá30”%̃ëoyđæÓÇ·ï̃úøYºB²/‚äfû ̀™ˆ¿¿Û¥©ï½Ơ_ü nÍhºvØăæ› Ù§9.O÷™Û— ÎfXÉá–ÅƠë£î3vüưzf@*"₫tG̃3ơJèÑRè1 ư.đJÊỳ/œå3goºË¼ésoNgŒÀYœ„ª‡GVíÀC x×vµyÄæ5µÂÉ“́Ïj‚—Kư,@¡ÜÁUz>¶’-xOü>!®îa‡̃0•9 ¹ÁƯ(ÚĂ Ñ…Ư˜²k«©»eÓ¨áqXß~ơ.(Ë ô~í»S¯[¹g ~€©–®Í“̣ZêP %Ë6Ïjų©­đÂ8Y#à|!”k 6àkG™÷NÙ /(éƠµ¾U.UU½ø8x{%`¼é3±5Ư"í8!¨†new[Íë{Mm.À•Ñ-êäh6Ê9€Igæ ¼¢ùj*Ø31̀¾DןTk₫P s¹z‘‡»–áûÄCÓíÊŸoªøó„́Œă$EN•Èñ£¡gʼgû®áQ×óNU©Ë(”ëz‰+¼‹êÅ Y°áÉñ¹=¾€;¯x;ªáŒ¦»ñL½₫ÿdzÓĐ/•ˆÁâdûÆ è@ûĂ"°¶‚ À¦Z;̣̉b4Øc²=é†öµb}ˆœÁ^f´L9ÓØ0Y:†cª ƒ+5¸•›èoºœØÆĐ £äđ‹O‹_ÅŸ²k.ÓH‘‘̣uVu|vdĂ¥7_ï’Ôƒ÷µÄï±g¹ÚB`́a¦-ë©̉Ăb\ HßoÖÊ co“l|ø¬1Ä0b¾îáqÉÊ”t4́ PJ‘ï\n#ññLÍ̉%ổ—/P¼PB)(\!ÚKC×lêOÙMü½Ñ6&ÍÆ ÎBÖ(¨H‚¦¢®ëÚWA„EËWÀ=¬¡ø³°h V́2ßJp’Œ “_„ïeùbà\ GºE! {Ü1ËXø(ü9ÓâƠưvd*µùj—¡k—Lƒ?å ±÷|!¯0,SH<ËÑ¥ª¬ w6¹¤Æùƾ›NËEÑBáqÖꑬIÄvM¹íÄöÊ¥LGP°y;i„§9 FP·­íÆåư— ʺ2Ẹ̀µ<8‡gÄ4°)/–U)H0¬ {g²DN| ̉êIø½›.¼_ô S|Üô±!uĂl gd%ø= Mưm”„Í"”Œ̀¦W=A˜Q 3|{y¸Hkœ¤%(÷ÇÀhcZA£ÛEàW3²b¤tÔjœzÍæGè@ô¼j-9…¿(”‡aö w¾já›c?Å'a¡ÏcñÅÓC>§#ú C# äƯ¤F‡́mKŸ¿¤¯ªï•H3dÄPàY‘^$Â Æ T9¼«=«›wmÆ’q~çBv8™Gq°gĂ>Q̃ =¯©t%N_a&bË ÙèR~œ¼4Ë‚vؼfRơđ #¥ø¸ßº"àÙÏ{‚E!ÏZ j]Œ1Œ‚ƲÀ¢˜ªª÷¯ype•º@2lkÅQHe×ǰ–à¼X£¨8"¾TÍîBÅ8*h3,;ÎI5ü¸ÓưÊS®¬MJ®Q7Î#¯ÓOá+6­ÇÁæ.}ïao ±_Û­̉"¤×ñ¹›úR<ÿ‰ëúû=®* LGo6È̃0 Du8'¦dÖ}à@ñÉĐAnSê'á Ơ蔘ă Ñ0‚ÊŸ$˜W.•qq˜+™`íF¦²Ơ^°3.ªèOP'‰÷».G^æë] sàm×Xù ËNZ›=¬X̉”8ù<*̀Ñv̉Ä{¿Të[^eY!zWü^k?́”<®¨IÙß!Öń@Vii¨íÓauxÅ­1ª]y°×ƃ·\6¤î§ÖüAëA˜–ØÀÓ½ˆƠ…mĐÊ®§§€¸’U¥dÄéT²¾¨¤6)ç̣  ˜LP­$œĂ%œX•S­|áÚk·å½R+|¸Zµ§Iô½-Lµ5P5.óH6©gB€J@M®̣SMg)VrƯ]¸í̉ë²Ñm\¹hϲÜl'´,8®??Û¼}Kâƒ=ô óç[^ÆRơYàK¬Su™)_%J‚UîØDĂít%å½<•Íd}éqDÖ47}hûÀhµơOç®&©û.¤ ÅY%L)®ª́Œ¿́>`Đ‚Y¢’ăX¼LÁZ…ß‹"₫HµËIªă„ëëÄû_@üN>æo Ñe]nís³V¯¡w˜„Ơ§³‘ØđöKÙ%«8àVUg̀–KùpD,$Ầ,hwvHv]ñ ÓAÄSˆoäåÔ®¥,OO<”«†Mƒ fN°pĂ8ăö́&V_º„¥è¢<³|gÂwF|ǾïÙäœákK­›9Dæ\ˆFü#ç®åû`ÍÑ’ăàî+LI¯©ÛÚ áĂf"#um2×µQPH&# Å(´u-ÉpáëBàKq…jHÈ'÷pѰ’À^¾ô-ªYº#$ DßFYĂ¡bóNàq)!œOKQ=9EBBNeƯ†£‚=̣Î j<6ƒ̀Ê`—ô¥ …ç|!3É ₫4_n(ÈøÈ_*.Z9÷RVÙn”¢6̀ÆOt Z!÷8 uS ë®Ä.е¼h¡(¿áK¯G,#/V½6ßë'JĂ‚*r>1(5Skr Âă1s'e˜î$̉Ë“ó¹;¾™[»v£Ä‡n¾Dë ÍvơÅN éreúŸF)ÈáNs~ô½'™üîÉÛ`MºâVà8Ѥv¿­œªx¾́û§̉xÏÖW@ÀÂ\„JĂ÷SVjûư™íê§đ:”*ÙƯІ$[­%jØ~iàè—¸‘cB&S×̣̉d‹YĐ+ÎC iÓé r€ Xµ)ǽƠÆ­€ÅL‡²ª P̀f`9¿!u|Û+Vm΋-ăóÖY2P29±˜xÅi,1“  PJ\°ÀÀ Ơ­đ]T‰cßƠ‚Boص•ăß0Œ¥‘÷ÙÚyÍÉ UÁ[$Àù5ëƯeêEQ)º¥¬̣H¯jW;(B¦ÑV_ÁÇ^ËḤH¡2»’-¿K·0°†‡£öåO-¦̃6­·CàÔ0 ́àpƠü„9% 8X†?\gçR¦œGäxC›¨…Á¢^¡ơơJûí†ÂxbÏ}ov ¹s !T ¶ö ÓlÙ«¢Ù*€#¨Zü(ÏÛq^ÛjXd%6“*J2#Wª.ö½Ô%N"ßVÚ₫ºYØ_R æBoÍaê¨ g%?4ùPº‹J̣Ô¬[Ơ˜’UŒ¶¶½Ëy Ô<ƯÚ4mª 2ûjÙêwkSbß« *ç¢â¶0êډ뼌ØG$ÿĐI^0?Ü#wXëjẦµ`LC >ÄVjTŒĂ¶ uBZĂ•ù¢å1à0Éëä"€ñÄ¥ø›ßÈ6™! Ñ®q†A½™Ăl›T‹ÛÇ?  ßùçŒUÑÿç̣'¶Mz endstream endobj 997 0 obj << /Type /ObjStm /N 100 /First 943 /Length 1246 /Filter /FlateDecode >> stream xÚƠ™ßk7Çßï¯Đcûr»’æ— 4 †B ÁN¡­ñƒë\̉Đà ö̉ÿ¾ßÑÅÅ9Ëîùt6]ƒ÷f¥ÙÑè33̉.J c(…B.ø(!„”ÆÄï-äÑBÇ(3:b`( X‹wÄzƒ’ÎRJÁ8y+U¨zn5‡ˆ?¿ƒÍÈ.Eh$5tRˆÙ²7¡R•8Dfø’ ó MP“Ẫ Û)Iˆí".0yŸBªZp8Eø”’â4¹A©…”   ́cÜÄnqô6aÜ&Œ¡́܆—2*đ*儲¨’V 0£¹ír²åœ ́ç i­¥!SÅœB–ÑIeD.Œ)"\ßÔḉÙ§‰Îh$x€(’#Ơ¯Â¿Ă¿ùûÓgï³á¸²¸X]yå₫ül8Z\-¯/ÏWu‘©M?/̃~8{¹üN\‡ Ï“ ¦1µS wv ¡XÀÍ0Fé†qkj¸Ùî0̣&Œº vѨkơáhéåç„´›7ip£Çpƒ~Ü~‹j6;#ˆcơ#(O·®<-F)ÅØÍ#¦gO‰ư”Hl”H́/‘¸‡Ùb{¹Mmw¥@ûØvË놔4Ï<‰åu=Ê×à̉Ø îÆÇgܦwGÀ ùq’ÜE@}SIZJÚÏĂú—“Çn1{ÉÜ(‘}7 ï®̃Í——ï‡oËW‘Ụ̀í̉ö°[Rˆt'‚»Ç©± –تåámđôÄ€¼ endstream endobj 1098 0 obj << /Length 3152 /Filter /FlateDecode >> stream xÚÙ’ă¶ñ}¿b*/Ë©ÚQx“²Ÿ́M¼•ÔÆÙrÆv¥â<`(HB-…‡gçïÓJÜIJ@ƯèJîbø%wUzWƠٮΪ»¦{t<Ưqă§o™÷‚™ß?¾ùăEq—Ä»}¼Oî!ªÇĂƯ¿¢ï.—û‡´t0_î²,‹¾û†¿~üyôA÷zT-C?-O­i¸ưÑ4ºŸ4 HöUơư¿ÿúæÏî@EŹ<û?OogÿöÙ®:Ê]\äLÄăÎUô~G=!EU4Eư‰áÿ–±¡9eÔk}`h?̀Ü0ư}MIÔ.Đ:6Ơßg^æ³Ă3ŸỜX–I˜G°QŸ4"AlÔa65 Û2Í2 ~H²]R$LA£Úö…™z‡ù>̀g=2đ¢ÆyâæpäQDMtCÛÓ]3Ư0vâ!&}ç6-veR†l”7ËO wl<ÇA¢øóŒ¼ÆÏƯƯ?”e}¯&+Ÿîá̃ơØ™i2C?ñâƠZ+ơ-JsG£9q+dnºßG§/.eK ;€¹ 2ËÉ=‚Ơ( ^[óZËp₫|–)3At‹i† ™;ƒ‡̃î©y₫§qüƯ»-áQ=n˜§rh¸Ï߉…tzjeä‚—0 ‰¿›ƒ–uóYÄÚÓ¬f oPfdå₫NÏÀưt₫‘˜‚0Ïèè/°f&¡Æ•¿ÅI9vÓêø|ú:ç¬ÊA0–¾5¡`WŒ“½RÎÇÅKyVÀj±„¯¢ƒ}s‹Lx'¯̣¥ÁĂ2_–™Û¬|‚¼'EÀÚÔÙONlfm·jÛ%i !y’‘Äă7\5̉ÉøD2Àm3Dà8à¡oe‚9̣0SCDÀ;bÎÉf,[j¢á"+L9Îs0ä#§+{„D9¹x̀1;ï.1EQÛ0/q5K¥wx¬.“E$Ç{VíñC8úºĐ¡,¤̀¨›™}5tÉÊaƒø \£ø£EJÓÈβ‹PA»æÉ̀2‘ †ÄṢ̀•·³”¶¼=q›4¾î°›ưỆ3ëóP2r·“9hwgä 0bĐ-©÷}ÂÁ,üÂc¬›7̣÷r]g.…&G§/Üq$ÆŒÍ̉ÁÖ7́_9àÀ¯¡f&¨ÎÈ̀µ/7ØYëløá| 7x&r̉âÁN@ÎA9"è­ˆ¶÷Y½0‹he Y¿Ă·"¨Vt°“Ä–ûlR…‡ £ØIàỢè•L!“Lâ¿7°úö3æpoÛG}²÷ûSÀĐˆ̃%eß±Y0ï‰å₫¾Χ„a¼°•ƒüˆQlUp̃y±†ăGèMg2oØc§„ôJwvf‰ eGU ¼ĐWƒ÷ÉÈöư¿;ê¦Å$bÈĐ'Ó¨–QtZMË(ÓDHnÚÖÀ© ưœk¤`æ%dâÎqiѶ-±!ĂS‹r²>a²6ÓXTI"kü弿₫åÓß±•²öV«¸f¬ B{.œƯ±ưÙé4Æ)‰₫̣E, ǃq”́÷%Ås™qœ9AÎ̉*²'B†ö‹É†a»2îy4h®K N¨híQö[(¬>3TnjÚ´)¿9¨‚à:+;½0\á§üP¸ơB”?Ôkœ4¦$ tÎC§eæ”hpæó½đá”ÚÁ¼Û“‘-›¯+%‚Đ̀¡•P§UÜ£Ư*›IU¾}™%à>ñ™́­R­X(mC$¤kÄAÎcæ¼ sc=6f’à1 SŸ B¬FÔ®-_x«ñ-vE°r²d°K57nB —îmfRÇ>´ÀÎÁLM«LÇ=w±Ø1R3 ¥5Øœ2ú {1Xפ„‰)k~]ä́Ăf™p䯓I˜fXM U‚F+ ·ƒ…¬WG CàúŶ)¦_Ÿ̀¼Z{μ$”„rªO>₫Ưë‘ơ0t1ăÁWó 2y˽ֺ|ct1¸`Ôç4¯ù 'X æ0„é2L̀eç+T¹G6˜ăkEĐQí4l»3í“ty‰<ºjÇdkTÄQÔs©|C¸Ư>¹’/%̣Å.eFl%•¬*.Ya¯ái@Hgz1Gߌºó”§[™™ÉÊàp ̃Ć»'ioó(_ÇƠ¿%Y₫™¢>̣̉Y¶ö̉¡ çÿà i\í×WƯÈU{S—æáCÏ?‘¤¹¥&„ ¬ĐÓ kZ„)Y†neâ™?Ïç¡Ơ2äøœÛ …ÖÇƠ>ƒ,–^ùµĂÄ ÖçNâG̃¡ÈœŸÛ²â0MZ^fHv"çÿàû1á”ÈjtđfîÍ8 ߌñ¡€x“™5Là˜ Ö#ÅyIñʼnwà"Ï|xhWH%J₫‘̣_ÀŸb„ endstream endobj 1102 0 obj << /Length 3188 /Filter /FlateDecode >> stream xÚƯZO¯ă¶¿ï§xÈ¥2đ́J–dIé)  EÉæP4=đI´Í¬,¹¤”Ư÷í;ÿHQ~Ú4çb09$‡œ™g†£—=¥đ/{ªOUê¼zjoïR¢ÚË7~üö]&óö0qÍüëûw₫¦,Ÿ²ôФMöô₫³zß=ư+ùê~ßíu¢‡Î|ÚíóK4Øj6DöỶ¿̣Ơ­vÂs:Œû́t8₫đ7«O,*ătJ“¿£m‹“@‹ú°wUˆ¢Ùˆ àê„3fª¤–!Ă”³j5aé”'QP£́8å†íÙMÜ댻÷J́‚¸Ñv¼[C¢!á;@bÏÍïÇ ̀í₫B"‰Ûyp̣É2Q›Åc”%é÷˜W"f~J~°ăŪSYÊ<a%%̀XËæy‘¸C˜"¬„Ë…˽p—ID}€;<[îEèFèi6v±€đ¦>À(ïm-AhT³Ă ömÇ£øS¼ưủ·»é•8% ĐơođbÈø‚J‹Û#1B ö̀t•µtÓ¨é·,<2d¥:W¢B?®e8RçEHáb_MÀr°Â EßĐâ‹¿đ)9Dc¹9¨i&mưi‚:y‰/ÊZŲ"ÑËJÇIˆ¾œ»Êï¦!n„ÿ3V¤(l‘o­#_=Àå–³E¬AĐ:öÆ-Å?½²R7´ï pÄM®‰¨£ŒĂj!I8öóMËđy5́¦Ñ‚ _³€OÖ€s4ÙMwf;:&¶k%ÈnØpº¿dy¡. :“₫‚ă“y dkPbó¡,D0«ƯÜOf¸øw€5—+Ư] ­V8̣E…8°Nv™̉››‘ÁpƠ¶äV8&f¨… Ëố¯rp˜a_Ç}ÂVáă4b‘²äO2 Ư©4_8PpH x Đă¬Á 2¿™nFo$›‡«ƒƯ8BHØU“ü}hû™ÂφtÔ]øüÔ¼½đ8æwàGY¼ ̣ëíÉâ€yªåB@£U³“)“¤uœÔê›DƯïè©ö?øœFỲÆF ¯¼üb8 ‘åáT—ëy’ùơ8, x%€!‹ïÇaÿøåVbó7;@=ÜHÇ,Wåÿ¤)3û¦BF‚NƠïQ%ú5R½¥₫f•ä,ê2|ü H °¶S`úïDá7°5ƒËµê¤dSø $Gu¼wám-P(Ÿ·@₫‡Îm:¨| –MiÜQ½¹Ơ®´B.`ƒq+8ϽƠªS/½Œ|=Z¸ûŒq¸'́€îƒm”¡…5 ú9üZ“`kÁäsÈóèwM¼œqºJØÂîKÚ¤<4ÙÔ&€AÓˆ=1j™üªÉMĂÖ¬ØĐ5«È r̀¸@s”a}°á ᆢ­LV¼ø~å#–\̀@»Ñ™÷«“_̉25è/Xµ9§47^½}¤Íuœ(̉Jâ°Íđ0GHÎ[B+8D5̃'û0m̉ 6¶Ltorlÿ’fÅ'-\üÖºÙ~¶p»ÖX—Ëfm!yoÊŸvsôÀiç]Æ&€¶ÏSHG9È‹%‰d$«á¢·2tÇËÿ8â¤}Ç*[ƒă¯0ˆ¼ Î"8[1é£5¤rLẠ́9g₫°<<Çxæ™ÓIÜá·×̃#fVk¦’‡̉Ê:™ ¾îmT‰XçEά±¡(́“~$•Jü¼ƒa9'¸;ĂÄxŒ2́ÂÜùÎóh§‡­Ă›„­­ün>ôÏŸK,sH„.áí“CẠ̀Ogºkg|¼ÊT¹ƒÎiüÏ X8X¡³ÎWè„®6ºa.)C³sWñÏâx>ùYŸbcĂlˆ¢ô1Me —@Ầ ±qiJÎ>k–iZ¥!̉8Nvüû6f1&0ot̉ ”.«ù¦axfä|¨ FŒÇ-‰"„æ…O0·“¤ÇăÙV”<âơ@yăĂ1µ ÉÜÉ—x\ e/Q.›VÍ:˜´[ÁƠ' ¥7h„'4hĂ/ŸµöXR$¬.9©}¹äĐ•7®„²rĐØ¿àËi4øÈLê~hư%µôY ¼.HÂ䲉 Q-†:‹’pϤ(Y¢[́j©₫ ‘kô¾ÊTq™­Dë*aû…¶Uj·Lö‰2Œă¡l¿…"đí­¡%àæ’Uµ$ز&úgNÁ—8ćÊß©‰FÁ6hÁí×€ØÓü¥ö½å–p‡â§FCQÙv‡·.ÊÍ/¡¸€=½üzäc¶STâî±áß75$DP+¢̀€æ̣±95„¾¿ÉØæ‹GT₫é´3°:¥‹Đ¿÷ªè.!kÑQI÷˜Ëg’ËƯ”„¦̀¥tQ4Q€ưŸÙHB¡)X =œ[jÿôK i²í<& ¸á|du™†‹Ö§n2½U¶kûvœ/Xuó²[¢,åj(—ï±­;*H3³å9LK¨”yô¥L$YÔ‰Ö€rs7¢Ç&ÙÆ»*_låcnˆ²é•³È+£—’´ ]Qp]ŸóvÅr›P¨¼¦‚:² +D=A6<àà½% ØJ.Ë–U;0/ăàá%|`B\ù÷o¹ưˆÂ  XÎOç2ªS`GjR̀€Röåa<ø®·ç>^§‹KR|ç˜ơ®r<}ĂƠÇZ*“T6²71m&½y” Óă”Ù1iëÂá"2$¬ œUkz3₫¦Ñ¤¥*̣ÇÈø¦$‰Âß­Œ–'ÀÛ—V°?èO·¸éï[]¬}"7]Çf’ú'`î^óÂ1—M#¾›(z„‚,9lÉñcô™°ÈOÉ‹¼’%RbăăẸ̀;™̀n(¯6ă3̉ư₫äÂđ]z:.jFV“¢i2(˶ñàøqfÜ@$Ú\ûÏ}5*₫¬gœOÆÂW<ÓKrû7V.9X'~"¢ ¾v¡;ÿṇŸ]0‚œ_—:‘¸f₫tG~îæÛV'aRÿNW”R¯.ÊÇPY®C%tgÇ.ưNk»ŸÆ}è?«w3tZÇ•j´>üV—ù,Ö¸ÊHg Ÿ[W™> stream xÚÉnäÆơ>_!øD£wv;'9‰Ø“ÁXFÄ9”È¢º"6Ù)’#)_Ÿ·réæ †ÍzơjyûRnBø‹nø¦Ø'»}RÜ”§w!AưÓ |ùđ.¼;@¼[`₫đđî?fÙMîá!ºy¨—[=T7ÿ îÏçÛ»xضr¯·wI’÷ßóï‡O¿âG|°­ơ¦aèçñ±q%ÿäJÛö6ˆEäáí¿₫úî/Ó…²8Ûeị;o¯Øÿ‡„C²Ë|f)QÙ̃=µ¶‚[qĐyü‚¾kR3(\[v .Ë ®k~ <:₫©^h›ÆµO»Û»,;¿²ƒơ'× ^v8Z9XÖŸ}G¬­Ærà ×ëÀ' ù.JvQ1e×öă‰ö8¬¿¿½KĂ<¨ºñq¨Ç†JÓÛ?û£i,L†{ ,øJDT q-ÿÖ¡4ƠÉ]-ûvÓưÉåy?̃î“ ×đagăWñ+z˜œ5ơñá×)­›®ƒG¼ñ·áŸÅ4{ë₫èÿ-J̉¶ó' öm¬¾ÓÍkë{₫F9.¶蔳+Q…ĐÉ̃ew:¡ÈV2Yo g8¤" ƒ²1}ϟȲ8„ÔBegx'ă«Æ®QCØÇ̣~0ø=®™cd‚ úơÑÓ̉U£ü1^`­>ÎglĐ·<1I29¿ Ø:œ3̃‚^ă“$Çé₫=v‚g_Å‘”CÏ!­LÆ(ĂâO“Ơñ‘²%… ¥¦YÜ_ϬO1º¸0­0™×I¼€Ká˜̀~gĂc¹Ør‹iưÑôŒÓ [đ'E08b# ²Y_:Ó:@@ƠØ[Aæ¥Q´]{7_!ÂûYỌ̈…Ü*fEâ/oÏà,;8øÑµ(Đ4JôŸî·0JK¹:ƒOB¦â×ÓîkÀpJ·k%BEÈvÅçѨ?¶À±¦QœÅàgk4t|‡D\xƾ~~e…™Ï ëcÈɶl¢æ'¥Ü†´7+¦ë•¶½U¨Ñ»ÿ»M_@׌ó$x&gö†Ëâ¢`ằÁ•²Æ †› a€·ÿ'n± àrX„MŒà\]0[h58P¡¼¬lñéơr‹Zö៕_‡U„½pºÆMJ•†¦ùº·‚Đ¥çOvh”^3°œS´H8˜,7UM'__k3Bê(ù&ØWs:7˜R§E6¯Ÿ%Èyă9Î;)̉ ƒ™mĐö·ûÛϨÁ›Ât¼ß_ ”÷À/fa¨º®́ U"È2‘@ÅÔ£Rà”? ÄoFƯÇüĂÁnî64q ̣œ¾˜̀Éÿt[Nù¥‰̉ùA Öu¥•LŸk3ïOJå´LwR]Œ¼Ie+µD­SF‘E‚O‰Y¬ÅÇ·mËđŒÚ#‚\H;.¢¹2/´Æ„•óÅœwϹE\„|Ơ6k*~­5!TœëâÁ2Môđ5X-ư:ó-¢@(ØmÑw_–́·‹ƒôyܧ9€Ï ‘,˜ À“Ö̉8˜»*0¨,ûAü†ê°•=¹âµ›¹L@–k›Z@ï/I^†BhRi.騵bØ5‘*;~'Pw§:Û+¤kZ5áɯ®kDù–küØ(Œ/ 0°A’®é&%ZD¥.ÙNë„ú­p[úy¢üéåơ6]ÊvdÜcdxJéCÉ&‹9b׉‚l"T„—n†! 7ƒÁŒ½@cŸk¶(œ¬ÂøèeOI¨áë*Ä S"u÷uÓ|¡h8E• æ»1ˆ­¡Ñr¦Î,UôÿX§E5€%8é„5|[9ÊaÔĐ5×̉Ó\‰2 `Æ5污́¬tm¯éZ!Wb çiÔ# )_gñ0…ôi2TU &á"ñæ<ƠÊ‘s²N <ÛôưË-uzeN÷Z¶oɦÖZilφ\Ó3(Ø{ÖNo¨[’LEU v‡‚ĸ#*k¾ÏÖJ[`5ƒûªrÈSí¦?`€$³çµ[K±C²Z^WMưä( ï¿c°!®Àæ­½|r”ا¦ejµ×̣t½‚œÍ9L}₫dŸM¡'NÙ³¡ öµ´ç›Øù®Ñ4©C€»%GNúSçRK§œÜJ4qÚˆZđùƒ¨ơ¬`¨PÍxƯ³EđG¨¬[MÔ£X+8 $¢rß Ù“7'ÆÔ®{œ-â  &\zĂ fÚ¶Ÿ‚p¤ê /̉á‘d.•ÛÉ"TÆXlwۢǾs¶Sh²À_V;±A`ÉÚ6®â¡Ö øRqÁM|#PCÆÿ‚ =•›–}?›ú¶Å`êÍ0!¤º8¦ ¼ôl„ÎÉïê*‹Ä”Ц*’Qï4úZFÚ(‹ÈIÎIG†xö̉*̉‰Sv Ô&Ki=–Å2'Hø”D¾f=Á mHZ^®~[5s22æbk¬uV Gß(ĐJ#MƠ'Çó<ªïÎ@Î`×ù÷̣8Đ'éR™P&=·«7m₫SÇI8x|Éâ”'Î–Ê }äÈå;7i¶æ_é7¯œ¼eϱ¾Ê#’ „GwèȪ’:đÏ•#Aà,k˜yä ­J¸kBí#|<”‡vÀù¬ó«d¾Íá6=AÓ«h­‹̀ g2‘¬è¹ÊÇ–‡h>–äß|‘₫f<Ç;|OK³Ư!ºÈ*$¤v}Ùwâ¼Vs’ËfͰB§AØĂ„ß8í‰MˆècU©(í鱋7¤x »ÈƒÑ2åRcy>Á$‹k¥¢L²ª¶Z§Ë³œ£\̉óùqŦ?Né;'ëù.>Dk̃< o¾»œđôê¹ê™{êÜs/¸)ôµ€-€B.؃_¢ä ±ˆĐ OµƯ7’^~'¬€̉Åï Å`ú¥Odë¯₫A™C>—”M_Ÿcy¥Ÿ²JƠ3ܯǜüÄ7ĹOzC„W®?7b7ú%ñÂBâÉŸ?‹ ơµ̀èÿɺÿüo'̣¿Bÿ¥ï% endstream endobj 1111 0 obj << /Length 2970 /Filter /FlateDecode >> stream xÚÙăÆñ}¿b' X)lRöir­8†aL‚lz¨ÖNĂ)7Éïß§®>(qcaWuơUw•V=dđO=4ùCs(ö‡¢yh/2º¯<øéó%t; Ü%”|úđû¿VƠƒÊöḈ¨ÎéVO§‡o¯×í.?lL²¿nwEQlÿÀßÏ?üåæ³éÓcœŸ;Ụ̂ø{Û~4°:6Ù¦VÛÿ<ưưĂ_Â…ª¼ÚWeñoï©ÿÏT–íU\©÷YỤ;ÚưvW×ÙæG7¼Øg;Ù₫+Ü1S›‹¹:3~ ïœôd‡§†3§#g¿Ú»I=ÉNz2Îêî#‚ 3Ú™_fëÂy ư@œ=Ù/™*Í yó ª}ÖvªØ«JñƠ_ñ^Æp¯V6ŸƯ”›qnqî…±₫|{f±1pÑîçm̃là‚éđuFC¯Ÿ;Ă[¼ávÿ|“£ôÈ”tËÂ8áOƯpáif^ÍÙ­Ú—àø L̃r÷”O¬;À%$Û©zŸƒøvªÙÊSŸDfßÛ‹,?|æQgd5®¤{v¢x”cF32 ¹‡ß^_nQ)́à± ư{âăĂS½Œ“§yêŸMÛÙßZe› U¤~:íùhPĂG†ç₫dSNNŸ ‰›f:æ̀' á#̃Úđ= ¾ăp mĂÄÄ&Đé¼nâS×đJ²ưѸWà&K™–|â‰À†b_Ơå’ gaĂOÑfrRW8µ';iÅ>s1œîè¸©Ë ftb̉(AẠ̀ºJL1'ûđ¦ƒøg¯?¸°g5¨7Œ{{xY;ô;æƒË­ª“Ø #èKVè°&ºx…x¿’áó/j6˜±¬W<~³Ó àR¤N·Ó́̉ă8_®“ߣ {tV?ÛΛLj±â}H™¨ûưYk¯VüêÅñ(T]Ľ–ó~£́xwcÚ)½1"NNºo¼Æ^Ь4kFÀk·!ԻĶQ%I5/ª±g­̀Ơ¾†¿9‰yTP\¸²ăa‚—¸è €Œ–¥Í“út²xo-ë@à—Q¦œĐÀ“G F˹Ø|QEy]<̉älKïÿ£PÄ́¸Ù ̃»×‹Ñâ;GñS0ÄmB̀*·»²È6 ñdG ài. è‘¿¬û3“:2´ÖȃOL‚*˪pŸyL4€«voÀ·‚%̃ _Û^ÔLÙÚơPG ̉O^£¨ÄÄ;2üuÀ%äôÄi˜ơÆÀÏ‘±!SA´î¿»˜Œ´,ã<&$àfƒ*•ăǵ·DîkpÁzjXyIÀ8o>ƯƒÄ˜³aRó§ IØ©´ó%n¤¹aº_\Å»ó ÂƯñŒC¶ˆêQhåaÎđEXPuξr¶øÇ0-1 ‡"‰X0£‚ü1đ §¯““¥ƒ üY‰ ¡yC4`„ä}‚CHtf·b\^‡T 8fÏ®ª`æJ̣3å ‚P¸ ¾O•8>ĂévƒpLÔ.J¶6r°¡U!6—U,É¢¸‡l"»Ư>́A\JÔDz¬¢¸ •eéÙ„8ÍñçNXˆ¤Œ”„…º?ZѶƒód¢´5é âÀç±ÅíJp–‹‹\˜Ç‰¡k§[CdyØüÖ·F…6¯Ûª&ÏÖ ”¤9Ắ0ûÀ1Fír¥“F!ge¢ơ! Ơ¿$S¤ƒ&„GD£e•¾^1ørđ“ƯîÏF•¹µ‡ˆc%ÉBfe[ïMAÂo Z2E¦TđÎ>VJS̉e`!…ÜxUÓhXÖL‰ Yæz-¥vâwâ¬,.–ÄzÖÓO‚Œ/t,ñm©H‚8¾ÅûÁÀ&µ̉pÄi|¨í ä+{sˆ öD1®‘´´Æ„̣N¼̉< ¥ÀܺuÍœD””[*ïîCi­X4gá̀¡CíṾ—&O’ FQibû¶›ÓR:®zJzÊ[ÄȬà%9ÁRiÔ;¹+Èʉé ÂW G\ª”̃©3R)¬}–GÈï®yÙ(¯edÁă¹=ó²€™RI£éípëøÇ¯vèBOè mŸƒÏQ`”ä(¬[(1Đ&¸u‚‡ñSdÛΖíp%n¯¥"A¦¨æ¶‡NT^ÔªÂDR;ï*®4µ”‹0R‘\sGŸP— *$² «# 0óc‰Úwd?VÉM‘¡^Ù¾X³¸˜.ơfÖU˜Î)ó’£ ]À*ªöÈÓ"5ÇPôÂeÙø=*zë3¿©Bѽhlx..C… £ÄÖq́™Ÿ0Ñ₫=¸ëYÛn”•Ă{a–Œ¾H2ç›@ªXQǼ# ud8*hîm ưúÀ[RÉ7Ù8ëÇîrSg ŸbOCÉỵ±#Ü¡‘'Áà&ˆÿcp&ơع MT¼Ns\P"i Ö§âƠR¿ërÅHTǼ"Ë¥.ăVkåg^ñN ·*V•ˆ5#©Q÷ed8æ9÷|ɉ É!è%‡´,9ĦMV„Id¤|¾ÔAz;̃́·păj₫>YêÓ²´8Ï6¨À¢”Œ<}Y­gÔ&“A®ÈoÉ›c@ó ó´FÆi´1黦],™%³"&¸»<”Í8º—ƽ§cÑ|”„ɧ¡Ñw£æÎ!cơÙé V £ØS¦†QDĂ(SƠ&ă&RVÄ£`;œP¯Æ¢›L+Íÿƒ3Cî0"ƠKĐÄ¡(J•„A’zA­¬ˆYo ƒ¨̣w!ó4ă¨ÛYÁLtÚ(¸˜èVA­¼«¥à(©àñ&X\ĂQ%nñ3„cèËÀ(fjµj¨²LÖùư1…‘¸#Ëî,‘R!˜₫æP/%đ5>Ñm̃ó:0ưEĐÔƯĂ,h±Ñ/³î82`ü•BñxÜ*åˆ9K ư®×)ú8êKè»Çns8LƯù6l¾[3¥fxl1×½¯ çÀjîƠû²ḉ-í;æ?¦Ë¾¸ü)Ço¨6rß*Í©×:ñÀ…ƒ¢¾4̉µ\&äô+”d³$"¿ƒă_J’ <ç©₫b™˜e‘æ÷Wé₫ç(Hót¿&Ǿ…t^;zV…ZA²Jie5ç‚I'¤ñƠQ–vB’.¿iÁùùŸ¡~:ÓÉT1e}3jøÀ>ĂâKNœG‹NCv7n7 »µ‡Év!Í©0ç”8Xø:_8¥j­ˆ—ø‰¼D¨³?É›…lÑÇXlû ºMëü®A9©'zˆ5p0ÍÿÉ _c÷Núûe†¤{?"¿  ú„èđƒœLÆ4!+—mÁo4Èd¬qá '.êDD„˜@;DgÆ­1@z…XƠ¸'₫y¥P90ÇÿÉuF…‘©e漉Îü~ ̣cđYäẠ́p,[å‰Ç.‹¯á ø#ÜÓ<}̣­@Ộ·Ä`/¾!©}?̣¶‹PD¶|\I½-xuP›–±e]ºözáể„Ư7ÿ±̣É)NƒÏÙ÷₫ÿ9ü÷ÅQ endstream endobj 1115 0 obj << /Length 3365 /Filter /FlateDecode >> stream xÚËr#·ñ¾_¡̉%£*Q™†Cæ¶Il—WÊå(‡TœD‚$²ó ™ƠÊ_Ÿ~ƒá—ª4@£Ñư‹»₫»¦¼kvƠÓ®jîƯ‡œ î|ÇŸ¾ûP̃7 æŸ?ü₫Ûº¾+̣§}¾/îO)©çăƯ¿²×ëæÜe¦?Ú/›ªª²àïwû6TöéÓ-Cœ^Z{àöö`zo€@±ọl[>üûù/¾yªËú©VƠoÜ}À₫¿GxR[ø¿}Êkŧ€Ñ‡Ív›g§qèô¸Ü íÏ|áÄà?pä×̃ÎèÇ~2{µ¦Ç‘Ñ?áIîÊâ©Pw›¢yÊ÷[^é}@Œ LÚm³Ñv†[o&î"óÿ™7†é048sdà+MvŸ¡»ßgăEˆºtOB&P·-Q® đ‹̀>H¸ÉŒO–¬³6ÜÂNnèèl9œ«z*j>-Yî+Ø…=Û/»Ü—2upw–Ù80–›zt‰ÏÑ̃xîŒsuĂUŸơ(„Ç‹ă÷(§ ~zyØÔuösuS¬ç)"hpɪ*²>́*äuzŒ‚Ï¡á+ïƠ+‚ ¼´†¡§Á1é¡y ©àzºkku¼dưÁvÜ‘›WíFKlœW;^"†_hÆSÜc"B{8†Úe?•’»µ£¬£\¿Ó=\¥Ç;Ơ‡ÑØ»ç1¤s5Ơ Î 8çèDYƯĐ2•€HÈ”ÁuoƠH®D5x9<W³Yă²µ́›¥P …:Ó̃›Ñ3ÖÂoo4((‘Ư: Îg{äÍ"‘^đoö”ĹŒ;GütvÓÀ¦¿?­ÈwFbTUVl à‹:R–¤–ÍB-a,¨%÷@¦†R#& ooaÉơ °—uffóQ²¥èƒ|IU˜\=ĐX½…xï[°e—{2–ÏáyHóÀa¸ÛlÅÔxVƒ₫‹<|Kv+‚j ĂǴŒŒ23]¡ +0xåL‘#¿CF9\œ9ÂÚ̃“Âæ =Xæ7Ü–rÑGF!T†©ĐÙ²eä̃Ôà°­,ôÙSXV;}vúzÁ{+TvmĂˆft0“6Ë+ÆïÎÈu}đøB‚ø‚€? .±Q¬ ÿû092Cr]áZ¼D:¡wBI!™ ·J;îáM2Hä/qq65üˆ'`Ok÷Ă”Ñ.îTñ¢ÅôÙ‘¿aà@€³SŒÔp‚öC¯Å<ƒ2ưœƠà‚¾1 Á₫oÊz—uZĺ¬÷lơj»À|Ă6X‚và¸Îâ¸2ä,©“gt¼-ü²_óÅ€›Ôđ>*Ă»Yd₫m8\舶„f8Ùœlë:¯p7Êe\ ´Rß×dß̉ÙÉ|Ñà® Éh‚ÀPd vØBcÁh₫̀!tN&Ptºñ³p',€pçHd°‹‘Ác|øŒÍÄYD Ă" Û[đ_£́¢…Nđ8ús^ç¶?´ÓqƠö²–‚ đ²Ô|shµíǸÁa †*%lv<»ÉZÚ૟́ë2Ö¶æ×Ÿ€+ö|Ô¹Âbxư¸ÆB^ë„ÑÀºÄÍñ xVưÉb¨q~ä₫„ó#+¤7m;÷TOăb\£)¯Yơg‘C†ŒỒ ¶tÜt—Nª’3¢©a‘u⼫*Æñvdû°Y Ô‹BR‚I|ÇÿÙÄeÊb̀d_ Üv÷<Â"GWŸàPgO@àËĐ˜6́•iÊ4^ ²₫Ơ‰‰…¿A™–—æl£h7IvÖ’F,4ß¾Ö³A”D³$Ï~‚´­çïëņH‘„l5_v‚’½hoh€`Â3c–‰?gHṃA›hëÇ%̀Y,.xĂkđû+bºr),́Ơº×ûơ`}]½² )gïhbDËC ÍB ¨Y₫;[I3JQïûèŒ-Ù&…•0Ä~¸N#ó6Œ½¹‡ö;!̉ÍQĐ̣)H!/FüƤ-8Ô#¼bêĂ/“¥˜{ƒ ®Ñ§‘g̀HD­É °ôP…]Ú Ó˜-‹Œ‰•…¶º5Đé¾7,D™±]0®³#Ùx„Íö(ºÀªHŒ<â°öl¯ÎœU)V¤F‹;vbÄ¿†øªD© Á¿—`6ƒăkwp¤ µg²+G®Â04Ü=¶CÚ»ää¾N8IÓgNÂØĐ·o< …ŒÊ ˜_&Cù)aï4…p€1'‡ưƒ¥Vök+ç V6!`„Æb₫[Eƒ„;`jĐæ9áëäbdá4Ó¶9bX§Đí2‹÷ÅR±‡ö…›TÆÈçÍ%––+£†¨“Z6¡ï©z%i ¹Ưæ. h¨ỗúåü4×Cç_P\@‰:êơ!–IViơ? s©¤Ô4Ê+_ă1=÷ćWrN‹°~è7æ p̉KæFÊ­‚án¯ö`+‘̃æäŒaJ©qĂ~ qµ–•åo´Xd|sÎ$o /€–2-Ö&9%EÎ1êÿD–_À“-ÔyÉÙ$Já ¢@#„(…£a7̣…Ø öCÔ•ăHñ ¥%-~qÜ Dsñ‹e£ÁDŸë˜ ¿t ¬}™›½$u^“%̣è¬æư˜w>Î_{!KWîÓ8´ÄÀÆ Óùª#ƒ€S|A/3ä£Ö|T8!¸`¤7£˜³&T˜Á5ÇR!é`UrƯ'„"K‰µX}´q‰áäaú¤Rï”îP4T“ Đé8o¹’$Æ‚ËØ%פ§P6 efªfµ‰đ(1Jt¾s /À‘³.·b e;å¼íÀpgÂkÁº¹:[ÍÁ’ƒXáÄA¾¬Ûe¶ÖSÄ:¦HÅŒ´piX„8ˆ&‹OɯF‡©Ơ2’>ûIj†`•©ªc/ÔŸùáœë„ÔÀß)5å œid½ôÉ®bµ¦ 7Ñ­ââ•R™D•`:¨(ÅÀùY{¿)‰úk[‘0("̃–ñ5´4™­–IôçÔDƠi¤̉»Å.­JƯüÚfạ̊ØÏ™ăRƒ¹*Lêúª´´¨ Ü aµøíÁ\WP,´¨0/5„~ñ&‚¿Âú/}QA" endstream endobj 1119 0 obj << /Length 3229 /Filter /FlateDecode >> stream xÚZƯsÛ6Ï_áéKéÛå7©{sZ%ơăxlởÎå( ²8¡HHÆöươ·_A‰i2™±°‹åØ],~ $8óá_p–…gY]åQvVîßøÄƠOgÜxxÿ&¹K¼t$ß®̃ụ̈.IÎÿjá/‚³ƠÖUµÚœưÛ»>Î/ĂÜSͦz9¿Œ¢È»₫ÿ¾¿û±÷^5J5sï‡u]•ܾ­JƠt ‹̀÷̉èü?«¾Y®́„’0¹Jâègo¤¿³„Et•Â:̉+?‰e08đE¯sXL´ïƠfzØYuüû9ˆâMƠ•ºÚWMÑ·ú<đ^™­ü‚M˶‘Om{iÊz؈îçªß#É~'ü®lѺ™'tkôƒp/JËgüơ¥tñ¤.І`Ë º ’€xĐí®ZWüïÑhÛêEé²ê„j·2”fF%Ÿ”-8‡­ÚFmD¸1êđëhá5msy¬ÏˆˆÑ»oµ+=²jßÓƠÓ¼ĐM–Â+éwZ0H¼‚©×I–Ơg?ˆË¢®_YâÍN ¼ 3‡f£47û­TH ^_ÆQîưuG^;p×¾@¢±!÷̀!f‡_™W° :$“­dÔgäµú S'đÅ+ Á@3£ƠÅđQ?)Ħîe"Èí[fĂYJĂZŸỖÆ/2)¬XL¾ÚUz3¯̀-tr'ÍÆt*₫h=tU£:éFÇ!vC¯«ơĐWÍÓÜRºvKC=ăXDX„Ö‹Ô{̃AF;&YˆØ_È”He0mô¸NAcĐïN¤dÈsÖ‰äºè”ôPôº_©—~¢–sœ‰Æ¢́«¯•5dÎÑŒ¿ÓAË›M 2#ÁØi6̀«ÄÙµ ’öSăEhº^̉|'j)L ƒÙGSD…s¹tV”²̣æĐJƒP£ṇ̃ÀÓªÄ=¥ª¯Æ9 Ă–̀ƒ™-`5Đj«Û= ¿̉Ö ́0ơ,bÚG 1I²¯̀›dh Ç Äg?ñ ø̀­r+ ~iT‰Y éTö÷xÙÚØË+¢ÎÑ›¸pÍ ”³ ªǃLÅ)„”È®qÁ¯ÜCx¸ÊG³ÙÉ×@ˆáh[¶ J₫ M}ιILú×d "`ƯBW”-ܲX±ˆ²üNl´Ø D;9$ơ2ân†’`™”í₫PƠªê˜C‰gÆ_b¾ ID±9dâ‰+8¸€él'$‡¦¦4…íÑÄ@HôŒV̀hÍ tº4q*˜ú‚¹´G.F$Đ&"g–ÄùOf5MÑ î`ơ‘N˜3ư¡Đ% ï˜ }?»²#¤Wpfñw-äL5¸Èpy`N9àܺ»¥ÛÁAÉ͵Å@€á!f×̣­zA¼"ÊĐÜW½̉¦¨+%ùÍ‚¡áÓ…£™ờX –AI"g£¶8g⪺Ÿ™x‡ˆE+µi÷¬ÙU,Áqƒi?ÈÉÉD‘F£Ă(Z:"‘ƒEF3œ¥wJ\Œµ9[à‹ÎÉÙ­†9_0¢*`r³¨[Æ0̃áÄ„]ßË ºØT%¨ ‚•±á. i´S¸ëV².¢ơ•… ¨Ă/á;„p:ÑlW§ßY6̃̀2°Ää–0Q€(‹Æ DÚó$#´ÆG̉u” ‘9FHu-ÿâVÆ/{¡;ÈĂƯöUˆj u_4ªºúu2-ÍTK¡^=I?x‹®}‹®'ワ.À“peÇcSĐ<€fÜ< ß®íÀ¿«F”ṿË¢˜ĂÔƠ”2¨ÁD8ˆ=₫íPñ=0ªê2æiÈŸàĂm?J‰Đ­^ È|ÀŒÏP?Ëd²X ¥úŒ¤}',>\€)KÑñ ËäÄfÙÖµ*Í̀˜§[^ 7µàĂ™5̉.ro {–̀Ä p%‰û\`7iÛdˆ¥Ó.Ù¤*È_Ë·÷¡Z8÷h)?{Ú¦a>1%•£Æ©zL¾•†¢ ï(Ë$é·„[2¦†Ï$4‘Ç¡ ¬1t³|‚­N%ÅZm5c`JüVZÈÊŒ±oÆÎ<ô,v¸×dª™cC²;ó±ñÍÎAi#t²72‘w p-²@¶ư±kÓ“eaaƠw0`éƒQB˜&ăÓØlqä8B¿VaJdQ̉Lc1=rœ\åNz„®]áÂk̉ÈFï«à…èeÄ€u… ơ‹ &ó8:Öiæ;› ’x¦¤Ibơ(0°˜+˜“nA†̣©I”Đ¥àëÄ‹˜O'}bÜ v°ûfÛú ñÛ·¬ưö"Uđ÷Oµ8¦Ù0Ç\a`i†¦bM¬’ăCúv¢N«)ƒkˆÙâ•“͈MXừ" ˜u•/ĐË#đé§Ư ¿ˆÛ^]–?­TK³6*¼nçró—Ọ́vZàGN²ˆ¼ơĐ}5^S¯N£Mɀ$*ưär,0—cÀàȶ1]vïBûöxăÁ­è@*ˆˆ¡ùJ¥NGĐQ™z©`éY—èvx’̉¤àT̉˜̣x¼øá}@y‰|RÅÄØ!Q,EO4f+ Á C°™âÿv»èo2b,ñAA¢áz/̣₫…G5o6ÑÄ€ÚdÉw®aœ ́6k%fê=̉uWf¯»¬(́hØơ²äY ‚ÄÖí˜ĐfʨvÚ/”± £QÏÜp’FÇÊ ±ÜÖaƒB˜à˜;Wl¨¤.L³× x‡Tí…GÂ_,}ö´d¹1}́ư|A“DÁé$±KœdNÑ  O(¿4tz̉½n¥+¹oµCïä̉÷Ejó™Íä ,7\)ĂFÎ̃T¼‘́usUá´§[˜¶ ¼LªÜ¨©½°M/[©›VêBËÂd˜8ó§'@œ.(å`Ǔܯ »`.^¸Â \8£B×Tq₫ă$.ˆ³mq!˜ EpÁÜém:̃©Á¤(\̀Ư8Z'Đ.̉¹)’¡k2ÉP®XĂ…Å~©Ä́bŒY"îäq "9>ï1 dSoQpÖ¬^^GpÜŸ˜C¼-Ïè<ó¹÷ÇƠ/pwň˜Ăf„F{à­Mí-ÿnrxfO¹̣æ°ó¥(ÂÆ¤8 l‚ÀÛ \›¨·ø₫7¬>³¼)Ú°/=¡}\abDl|(‹_ƒ‚ñZÓ}Á2L=½8265bFIs ̉‰&¤§Ñç¼²aY 5|f/'Ñn%Ôa©" ₫q¢ÂFnvdC–ä0MM˜Ô1L3›L±=¢×ȧu˘ö©ˆÁ4À+º*³.ø®ûđFS8’Ÿ¹¶‰Î©Ÿàởè¼ ’‹f·ĂzfæÊñf{ôb“ rO“ ?Ị̈ÄRÈ«×/̣HS ó7đ!½‘¾m‡~Đ̉å8²sŸǹqạJÄ»œ³« §<Dh; 3‘iå±Sø1t|ƒ;®+ÇưÜ Ă*˜Ưær^°rúđ[”¥:@ UÊ–Ï?®óç^n$h÷…¹9©å+¨xuơ?uz'YàÅæmÍàñøIämíuµ‰¬I•z(·’I’ÀyµI÷M…TL’Đ9¥Aêi|hJœ9”ăc™’&A’̉’Àí‚€Å̃Đa-å"F &pàï­nf[¡k“”ŸîÍx8`5Ef!¾ºŒ÷UÈ BczÑ®Vù/; §‰€f₫‡´}#çî][o”ˆ̉5_JwaHrå%SÚ2ϹÔKƒ£tüˆ;èa9Ï0]0&b¶9&8L̀fü›KîD°ùoUWÖ L=ăŸ.Ó ¯’¬¬õn¯~_>,ùÑóæïî#ӟ΃ đ®®ïV1ëjưøÀ|ÊÜ?ûưĂơy?]}œˆ¤̣̃ÏỢn%âˇ7«Ù8X-™8ö̃â€1T́÷÷·7¿^¿½]2ÿö&ơé»—âÈ¿.ïWÜưé÷å÷|Ä…±́Í£|ü¸ÂÔ|öïæN¾|)á£ù? •ƒ endstream endobj 1124 0 obj << /Length 2820 /Filter /FlateDecode >> stream xÚµY[oêH~?¿"'#%¾p;óDÀI¼C€±!Ùhgh‚µÆF¶ 'ÿ~êÖÆŸƯY­V‘âêêêêªêª¯ËƺjĂŸuƠ³¯z}Ḉ;½«Ơî[›¸ùûÁĂ7Kän@đ¦&y·øv{ßé\YmsĐXW‹M]Ơb}ơc¸ß·ń¾¡̉uü£uă81üÎχé ×xP©Ê£„¹óĂ[¯˜Ä+• Xƒ^Û躭.₫öÍ[TúÙq¿h½–₫. ³ ~tÍvÇe'üéÔî‹G‰Ñl₫ø >Î&c¯eAÈăát|; ˜Á"!ç­¾k ƒVß1¾'²ó ñ™á¿ǵ]l$³7è9xqc9¦Ơ±Ø¬‡`øR}ÛøĂrÜ!êÍ~ø 3_üÅăl¹`îK˲lØ;N¯̀Ư³Üp*Œßüéøy/V#ư÷yà…¡7æ!øU·E"ô4Ÿø­îô ^£Ér Q“ñYÄt&ÄẠ̈¤‹™È±×¨€ƠñM·ÄtZ§‹Æ7DäÉ£pA£<¼ó'>úkwÛx(LÜû‹)8$o "ø°ÎÏi´œ ez¾ æ³Đ3yDÖ"á]×dOà‡¿µnÜ6X̣s1“gëÆ2P~_ÙL’D3‘˜{÷4œDÖóZW'çÎø²ĂI½Î–bÙ1_ø‚êzZfèô™±wï₫³wÍcP)á Ăå“w¦Ñ‚R ̀j>³ádÂƠ>ơFp*öWf…pxøÏ₫H² ˜7§³ơS¡ŒŒfA€vͦ&í¨aZ.lÖ5mqÈÖML™Ä»¸ŒÊ8KYG¶a“8z‹¡“¸Ä8|b"°¶¯Êü)ºÛ‡¤ÆgÏđ!˜µœN(Áx¿/!=Æq¨½đ¹„ñ đ¼© '"ÎÁ oäW X.à3áµ€)Ñ0„ˆ(è´¿XẦ!`ˆÜ?®ÁpÄ=?åpe(_;S?„|Á-Û`ÑBĂѤÀởî´kA‚tœ#HGNé'˜³É, ëÀe‹“”H$æRƒÔÙ,8ßpwáö¡´¦Á´'ŒÀcÿÑ2` óI7<ÑŒ*̉á2ä ü©^N• OÊ’úºÅ£Œ›Æ0 ¾˜Ü¶%X́^/tyù“eà‰À=ÏH¸­Ëp[<ÀKÈư“'0ANS”¤j´É¸“ÖÎÏ¢b±¤˜̣1…p ,G̀a@`«µ]u/ë̀ƯWYÁUjÁ¡°Z°lLơé‡X¡ă†ó£ÔuäC̀c€=w˜«r_®‹ èPvôj̉óâ¼Ơœ÷S”-U¾ÏŨ‡j…̀‚¹V‡ŸQºæi¼/~₫ ÀîuŒr‹íi¯k¬ăb•DñNå<‘m˜D¢<Øü÷É3´ &µË¨¾4ÁË(Đèˈf÷y†J>âµZ‹¢7| }àœbÉU”¦YÉ2,"¶¾Ç,&û%µè+hÁ¿W¢̃±5·{°ú¶å@Àx­VY¾Ów–`g&äVŹ*ßtÅô\}ÄêX-Xe‡¼,˜.¶Q’ˆ3û}̣ÉÜ]<Đê£̃$×v˜7Y!£U’ 44”¨æØưˆwQ©pï>ø‘Êó­È’C©ØX>6‰SÎt.(I¶±?b!ù¬âê|AE,WYrñø—[¦8y€˜çÙ{í0Pƒ®qHU ¸û³œ‚™,çgT‡Ư^ïééîW3]:ÇƯ>Jcˆ«7YeûºbRàh“]m2bÙ́ ½©lá•¥¨˜nïûö•åÛµñu ë· ÿ¦mËû–‡-°™IÏ4!“C=èØÇn/Ô‘r,s0H=f-ÇÂ\AÑ2“µœ[¤q«đÅ’ÈÖÀ50OÏ…_‘ 9Ê£©]âwÁ®œ¿9âi LËîŸ0Qäă˜x°VX§*đ#âGJ±¯rÁq:'(:S §OrqÉ3d=<ßø­›íèđxÏ€¬Ư3|Eü–ˆÀ‚ăt*}Ở=½Ÿ_7e'ɸö@oúqÈÖ „!•â3Zá̀6VµhrĂI¸NÛ gM|ư«&‹öM®ËÙ¦d„ ̣¹ă6æmXHöÊ9©­Èy™Ço„d$œÀWXd•Qú®–₫­)$Z@‡Ь4tM§«û-¼O1¼–c¬éé‚ xî˜_–‘6'8₫ ¹É’$„›vE@EÀúx…EḶÙÅ:I+£½RÉÓ±ˆцÓ$ởvuåVËË(k ©¡Nộ¯$pp§¸:ët²í²B̉Y_9±ͧ(€ëR]$¦ú±J…Üđ§œoÂÊ_¥̣tm‘u=m]Ư¢b›‘ÚB¬£úK:Ê&w±ÎÉ>üF£15ß·dÎ/,”Ä©:³ÉaXp ₫z–ꥍăVåêlHC’¤PB07–g“̉µàp·wƠ7Ư®‹Øe÷Í>9Ñí‰T»#Ö!…ûâÍÙ !ùÁë̀I£̀‘SDđă-Ơ†Ièb„™ çH;ÍÉs©BLv¬Éô¶évå…*ÛS\e¾³Œ°ñmđµÛȶa=-üTQ~i±6&:”[¸Ç¾î}#:nl€Û–&èªECü&#RˆTG@¨ï<üD\G‚`‰sªby›‰½»lo +OƯ†CO/€óVùÅa•|ƯƠ=­æè³,ú³,ôgY¤«Ï²dö­’“~û™YƠ>÷U4B‰†đ1C©¾f†‚~I{đ¡r.q8?ñ@́“å:X˜XÁå™U’tÏ“45M”7îO)‚¨¼0¢ơÿ"N§*qÓ ă·Ù¾*­ËB8ƉÇ›ÈÀ= ơ.‚Ú¦ˆWßQ†^‘x‘oÁ¿jƠèÙG}¨K³âƯ>‰µÑGÂỌ́³ÿ׈>y}…­¾ÀÖ¢úK|Ơ$Ó$Ó†AơÑ•ÆƠGW ÑØTCÂ6¸ư×̉wsª%€kxSŒ“¢ñx_u¥ê‹,̉h˜«•h\£QXkæ†I‘ÉŽ–~!N›³|W}w€®D¾?lu wj{|Q¤[>ZIïđ‰Ư÷ü *¿!­°÷Ă/D¬Ê<Ăö“6«ơûH~|“¶ayƯØ̉›+‰ /f'đBî:“~çđ̣ˆSú½Î%ăÎ$Z f;n½U'™’WÀ́%ó"~@å2[µ+.¶§ơ]ÉjäCĂ“2/=Ôz6¾,Ç©₫£Ï£f驇ƒ°°k¸ÿJ_¤cóµ)pzf·Ó×}Åÿ¹!ÁøÜ›p endstream endobj 1131 0 obj << /Length 1322 /Filter /FlateDecode >> stream xÚ•VmoÛ8 ₫̃_́K v,Ụ̂Ëö©¶b‡b-z)Åơ€¹’³-CVåßÇy9Üb‘")>_Ä&!üØ$‹&YyœMªæ*´\½Đâù₫99ư‘äƯüjö…ó ƒ",Ød¾›/&{·]7ơ£ÜíB₫œúq{·é{ÿí‰w/Z¡Ë¸O›÷ZV´~•h{X‘…^ʧÿ̀ÿ¸ú<âxÿ¦÷{é31›äA‘¦ "`aä€# BˆùZöST÷:­Vºlˆ¨T#+ÍV·w>>¼̀??¼ư푾Ư>?ß~›¿~"r©4-”²vf̀®´ú̃O™·V[g₫:@èÇX');ơkÿ]já ôji¶¥7D–í‚;µqí$·¢F$ÎE_-²7Z¾oŒÛ‘æẸ̀`Ó.„R HÚ}hà¾TmÿéÙ«º¾ ö4³ ‹à^|–l¸0™$‰·B†í0Ñ2O™µ0²ÂtÂ-@Öö©Øûî §cĂ,áA–ç€̀Z%÷0ư¶—܈£ ‚$wÂ×d×F»x@1‹ÏíW¿i?A äC½HD¼%ÊPÀ‹̉³Ó²4Ñ•Úô$¤–ÄBa¼F?Jâ M84w 5Tb—ñ'ºbD̉c0ơ3–{h/ÂøntI–$pè0hËƠÊuOú£›€ÍF®àÖ2ÏùNM‚ˆ…| Y,´hI‚yDIÆ(OP¢¤ÏưÔg̃Ë×!/ <{FèeY¡wØfœwû»µFÉ v*[b¼±8)É+µ1Äs$j₫üp(ÈCB¾Nó˜N(¢ñ!YÖ½¢ƠJZÂ…”hºÚÚ̃!ja¹̀{ y(—G̣DlQ âÁ¼î€̃}éă¢ß &ñ”;ª¯Đ$‘ÅSăí…©·?¦lÉ ÀâvŒó¼—«vÈỳ1d•ꬲ¶×›{.r ~öx[U]Jđẹ́#ºP\ØÆ…sû†ô¬KÀmE%ú¾ÔÖ©€2úË4O¼½~ƒ¶m4„ÓlÁvSb "‰ư×@ϼ¡¥­ZÊÉ ¨#l®2 ¶êIjKUăe«gb<Ù’^ˆÓá%EẠ̀h’FaÁ98¼{AXÀ‹́;æŒÇÙ^ß ‰|Ô}N±pÖÆtg³ív¬ÚM ôjVS}÷³S?“°€±™ùùïCv/}îƠQ›;5j½¢‚xedâ´×Ç,s±eéèƠÜáƠëL¶ ‚(¼ \Çq"­2ÄwƯHC;²­”v“DCú´+âj¨á€6\¯QĂ´`˜c¬ç5âaÂùRù+æwVŒ­u°‡v²#³¤O¿y×Đd+h»–ïÚÖE‚ÅăĐ%`»)©–­. å^Úym â6 ¸‚&¸ÜÔ´ká /£](‹Z¶?(F¼8‚nX40í;8iè̃I¸GÅ’¸°CqóÈÆJI§i¿ÀÙ®KC+Û'-Pd#Nê\†,ØY( Lº;öhØÂ\ºêzÏGYÆGYĂÛ H×ß µ À³ µ$‡„g£AÊãÙél˜y‰îu†g-J²Á[ Œe\ì'> stream xÚí]ßsä¶‘~÷_¡G©ê„#~’̀[́œ]NåʾỡSœY]OVRF#û’¿₫À!60́f 3{±wY©J6»@Íß4º”ÿ¼hƠEÛiÑéöâöĂÍáowï/Æ?¼ùæ Ú]û†× å—o¿ø÷¯­½è›^^¼}wa¥N›dïíƯÅ_/»úÛÛ?ño“%«¬°F3acë#́N]ÈV(iÍ€=<†r¢₫ßûíĂƯæ䱡Ú854¼n„q̃®n…vcÛ/Çvꢽss¡‘ïgdZƯ=a±g¤­>ô¤₫xä#Ó¢b˜üàhG¤ĐX¡L˜¡n~l¤yÿ²ÛüçËư~{{ó¼?–AkEëúÏQá'(« “<.Àq1¸€/-È^ ¶÷™•RGbx{Ơ9Ÿ||Ø>Ǘw3A‰^ÿ.CI£ơªÏú⃿zHCÿk`àxH 1«ĐǾôÂÙ>ó…̉Đz97y@₫·#`çEÑ×s0v§É!~è₫ÈŸ!ÙÆq­iàÂ$Â@øÑUSÙ¤+ÈøËî°_6“„øË¦‡_¶¯jú¾¿́§+Ơ_₫c·}ÿóPV̀ÄxƯ‰®“kêX™:Fºë…4À…ÇÔ:THÀ äÙ2Åúæbéư5§Lyw{ÿø$Ä₫´+Ș#gHª÷],—„Đz97‰ ­°½«'!ô§])@Æ4ñøç`Œè¤â’ZÓÈ…I„„˜È×’ªÊ•dLZ-đHHƠ‰œ›¤«…Zbµ@9’CŒùB«©Z € “ ƠB-)É£\)@F äñHHIÅéà(́øâ©1‰œW{è ̀¢Ùá ¸Â‰€$pnr!Ör" åJ‚•†1\ñHHDÎM̉°–ƒ)Grl"ŒáÇ@€par!ÖR" åJ‚M1̣HH@"`3¬~,>¾́çC`+ZƠ}ÚçpbX ´ÔǾÉû ÷x́®pb œ›\ˆ}µ¤ØG¹R€,Å> )ö‘ȹI:öƠrcåH±ûx ¤ØG&b_-)öQ® ćÓh́ă‘b́cŸéµhaçñéêZơ—›‡ÙM©s{8Áûê-œ©?ºƒ B7p€Œư 57Hï̃Ô>}ܼ!ưÈ ¶nxwn(ØÜ ½oSûøqÛ†̣#‡XØ´a=~Ú³!` ƒôMåă§ ̉ ba»†÷øq·†‚Í ̉{5µè(?rˆ…̃ăÇƠ963H¯ÍƠ>~\£üÈ!Æ9Ùb©ïñcfFÁæ鼬öñcZFù‘C`³qÈ xs263HfdµO2Ê‹ `a[†÷́1£Psƒt.Vûđ1£üÈ!6dxó0vHĂ:í½gAß=í¶Ăñ­ư»™D̀ùçï~ îh*ñ#' ¯Û±û5è?3¹dóù\€#œ9ÄÍM.̀jµ ¤ir¥Áæơ8ñHH3‰œ›\˜ÛjIH“åJ‚m¾ÅÙˆGBß(äÂä WKBâ(W ls„4ˑȹIz«å Nt”#96ÍÇ™‰Ç@ë(àÂäÂlWKAî(W …}'& iÆ#‡)¯U¤¥‡Ưæænf²“¢Ơêl“]YHG$Z›CéL8…üîùöæanñÉçSÿÊmÀOñÄq¸ ̣_}ơ0€̃= r ¸Â<ËJ¡”/v.^?1̃€ófón³Û<̀]n̉ö‡w ?ÛË("sơ’˜ à’€Ăƒ^B]áH‚$áKSÛ‡S^ï~Ưm÷›ÙXăĂrưàûR8×&́×ûcÿk``¦ØÏA+_Ri|áTûrar¡Ú¯%!Uû¤+9ÈH‚ª}±Ú§psƒ Ơ~-©Ú§<)@–ª}©Ú§ “ Ơ~- ©Ú']ÉA–ª} ©Ú§ “ Ơ~- ©Ú§\)@ÆB×¢Ơ>‹„©Ú'K“ Ơ~% SµOº’ƒŒ…nƒVû<RµO!&ªưZRµO¹R€,Uû<RµO"ç&ªưZRµO¹R€Œ….¾ùÆ#!Uûrar¡Ú¯%!Uû”+ÈHú̉“„Tí“ȹIºÚ¯å Vû”#9ÄRµÏc Uûpar¡Ú¯¥ Uû”+ÈRµÏ#!eạ̀́/¦i…̉Ưư ëî̉o6›ƯÍừuBZôj½‰̣Ø%{aÛu?Ûm º^´“\´p4 Ñ_8¢%Ñáû> ͋ǣÜ'j"+E^³Y+đS5;]/ÙÔW,K‰YpôĂrỠëÆ1ôêÊñàÓ‰z…ˆó+F^¯[ć©z D× v2€+&!Yà G³̣ Z/Ư)†hĂl}ºh!"V¨+áL¿ª¶̣Ă‘âz¹Np¹Âq$ä |áÈ•@äÚt¢¢ßª¯f^+¤\·r>âîdƒzuMpuÁÆWƒ /uÈ^]²ï‹Ö£º†÷÷Û‡÷ăgÉoîÆ×Aïo=₫q'ºOôƠcd'V½€   8Ù¨ J€®0”@Jđ“•m⢌WÂîçÍưÓ́j›ơmóúô*Œp`»^F“\FpHѳäĐŒàAF­]g¡Œ†K3Ư>¼{œùpƒưzđêơA(\¯É®8’èơsĐz àÙUdi¬oV‘ÿÂùÊñ_° Jû6v-ÏóŒô…U¯»d7ÀeÚ,̀}À́ àYÙơ>°µø;ê¾ûÑÏ„×>_ÚŒỉöáJ^R¨™3¦̃“v u”¼|Ù-í êú£â Mhm?̉"PưtØ*/­°ˆüƯC”:̀Œó:±Â­«Wœ*P[-—©?*8z¨\€ ¹¨y öX[}á|Yåú€ûư|$:"'S#ŸcỨ¼¢6óoj¹îçW¦́V:¡UwáZ#ׇ§ØưzꤷY_:|2̉hè.¸Ø˜‚Ơ¯û ç¼>â.Ÿp [N«ˆNʤ̉@ÊëÅ4ÀƠÇơø¢›$'à GOr”U¢ËúOOÇ ́zØ£ií¡aw̉¶VJ˜Îæø‘w½FÁS£` º^¹“\¹p4 å_8Ê%£ŕÊơ •”çP.„¼Ưïf"¯®ĐZsÂ3…̃Àw½€'¸€á J‡ øÂ0¬¥ĐZ2́ZeÎ!`yw³¿™?B²¦§F̃Às½p'¸pá`¾p„K GáúÙÙÅïl’Ẫ\Óí9„ !á̃mǵ —G6kÚđh­×éd×);B§ÀN ä¨Ó¦}Ü¥%u*ưÚsÈ"¯°ÏÄ×ánÏơˆ̃™„Àw½~'¸~á í+éøÂÑo<»ºd[+T’ë7œƠ%äœ]çÍ|*+ÚÿfÈ´|‘kîơÇbÿk`àH %ÈxåÁQ,®möÁ'ó×BlM#&ç¯1Ö‰̃Ôs0v_p$ƒïÊ9Zi5ÎùPj¹ „Ö4paa •¢íÚz BÚ•¹0ÈtR4â’ZÓÈ…I„„Î §OĐAè¿àJ‚\dúáƠ´KBhM#&çI°ô“±¬&!ö'])A;ƒ¬Ï,\ï˜$ÄÖ4ra!!L^Ơ$Ä’v%oàl°’IBœ!)äáYă'Ñ6œ{x³ùûËv·ù°?ưú<»a×÷ëÁ]ª€UĂæ»KľZ6¡ÿ50p,›d~Ï.©¸ÂQ U£{¡ºt•Åóăư/ƒb6??>ïgÏ=™ơV ₫4ºåz Mp Á¡́P W8*€çSóÆÇ¾xåNj₫¼Ùmç.₫ơµ£îW5Œ…‰Éô>_s'¬oè́ÛŒ5ÂD}aˆBq́Æêđ‡Q]‡ĂM?6¶ùÓæi·¹½’—7ûÍÿ 9ûy áOŸ°đ0Yâêe1ÀeG_6€¾pdA GY´ĂÚU,‹ĂÉ“ÇƯÜçój·&Fü…§Èq½‚&¸‚à@**øÂQd{Ñ6 N[?í67ÿ3##¬ưÜß0@êÏÈbuư  ơg6T²ÇêOè £₫$‘ “tưYMBú¡®ä Ȫ\ú¡đHH?9₫P|±ÑH (÷Û¹"BÑÊơ’”·U#Ươb àb‚cJD]à GLr“î1=]]cS¶¯Qäz=É«_BN£È®—̉d—Q…–§Đ”ä(%Ơ gä¼”äå|ŒîÖY:Xq(Đ[/É.8†ÇŸvOâ¾pÄC Gñxz›-æö°•/åïé3F‹,Ó³½zc$ô¿·' ä3f¸èqø¼'đ…Ø ­iäÂ$²;äÇ^WOBè¿àJ‚$¦F»Ă;ZLBk¹0‰vr«IˆÛŤ+ÈÂv1“„¸]L"&ÉíâjÂv1íH±°]̀d n“À…Iz»¸‚¸]LºR€,l3IˆÛÅ$ra’̃.®&!nÓ®ä ÛÅLâv1‰\˜¤·‹kI˜Êu•d$Á¢å:‹„©\§ “ åz- )³!]ÉA¶‹™$¤̀†@™Mă„rmÊl₫ôöÍüw×C¤'—êêz!Mp!ÁñTø;đ…#$9IûÈbS¥¾sƠ¹Ë·?̀¾‡7|%dỞ9{̉«5ơGÇ×p„!'6ª©3¢‹/ÿ=?mçïX^¿zơ1-D„¡¨ÙdWonC_8:#£ĐZ#Tc3¡'âƠá$üĐPŸơ¨>¯…u9"qi­Z_9:qÂL×+w2€+§Fׯ¡/åÈQ¹N^›XV®oØø²ç¨\ˆˆß^«×]óS…ˆ®îd.MB¸Àp ä(Üáµùø’)\«EsâK£p!"qƒ­Z/¬Ư<×Kv2€K#!Yà G²r”¬QBÆ÷ơHÉú†úÄ×;GÉBădÿøp÷f6æÚ^ôŸÅ‡»0éªê¥7À¥ǃđ…#=9JOKaâ«v?|ÿíüÊíº:ó1Æ ^a“\ap ñÍMè GarTØđƯû¸öÄçîvSR(½~Œíć‡!¨×WêË Œ²Dß,pÄ…ĂFmÉá¨qg¼¦|á¼NÛCKƠºß8oŒÍ1ºy¹ÛỪ%|ºơÖđqÔ­—çd×'5…î€@_8 %ƒDUß Ư;†D‡–¶ëÏ Ñ ó§á ú?ö›çí?7óŸeUëz9²ÜV«@Ơ ®Vè C­rTk׉6^N«Ơ·́uµBLüv:»”;qƯ']/ƯÉ.]8„t/éÈQºm'%9̉ơ-•4ç.Äü±‘öåùçyñ¶«zOUoàº^½“\½p@ÇB_8ê%£z]+t¼M™V¯oiU{ơB̀§›ƯvHf?y,×½ĐÚµËHs½p'¸páX¾p„K GáZ'œi9Âơ-»³D]‰nµưºhujÈ D×+w2€+&₫öô…£\9*×XÁ+̀̀p¾UŸC¹rÿøôÓvî̉”¡&3k¼}EM6̉Z/ÓÔW)9"¼Np4ĂF‰êá6:ÎúÖĐ̉¸s¬oe˜ûí‡ÍăËÜËpÊÇ̣ơơÊWh4ĐZ/̉É®R8vøÅĐN ä(Te|Î ¦¾eÛe• bbÛîĂƠºëI§Só€Àt½v'¸vápyđ…£Ưyöf!ÙKáâÅ!o97 íog>₫èÈơNÿ‡3£²mEsÊ{ÀªÇØfÜ’G&C_z¤C,•n¸çÊfB+OƒÈC,ZZwÚ¡Q{ˆ¥&¶+=ŸkZZ» )®íd-G¾ÿ}ሖ@¢>ͯ…£Eë[v<‡h!&~ óºpêü‰®—îd—.MBºÀt ä(]õ¾X“½9‡lZ\éĂ}Q«j—•iN ¨f!˜å@jøAÔĐTû´Tj}KÛ¸s(bâÔzEIư¤®×èd×)FB«À^ ä¨Y¥…S±núêụ̂.̀›+y‰ß…é„ü,JsL¼ziLpiÀ̉èG3¡/iÈQR‰^÷…4¾ºß†»Âg.6́ơi–'½Àm½r&¸ràjô¼0ô…£9*§QBY5M„Éá[B8ºfư(tưø®WÓdWTƒîŸ@_8j"ƒz)¬›̣ûíÓ́«Y²Yơó1"U`¿ZZSTYp€ñ0aè€ ²êÑÅ«è÷»íû÷›™ă©^¨~ÖyWKiêJ *₫päHJÿ®‚1 endstream endobj 1095 0 obj << /Type /ObjStm /N 100 /First 999 /Length 2228 /Filter /FlateDecode >> stream xÚ½ZMoǽóWôÑ9¸·»ºª? Á@CA€0$H,è È QĂ%H ²₫}ªó†L¸́Xœ¦.dqwæ½úzƠµ³Œ¡E\ ­¸̀ö»¹˜›ÙQP#†è(“É¥\̀C7Äqf'Ỳ`—ƒœDµ\–ª¯Dr%'{«¹̀ˆ́ªd3²k9¡/‡Đ-½%ˆ:ÉpňFe~ẺëHHáI/NÅđIi¥_Lê¤tw’₫Èbx¤÷–f‘^Ü’Ư‘’#‹A-rDbđÔỔè­ÁQ*Y9»Tíµ˜4Î-);îPÊ¿V§kj¹˜÷¬)’j>st\‚y s5Ç#'Ç-³“ †Ââ$fCá́„jGÑ´r÷”«}Û¬¦©Nv‡'…Í? UjO²BIëy‘¤•hI94™BMœ̃ÚïÍZîÔïƠÂK÷@Cȹ{ iÏ¥¦3×{-T Ѽ̉f(=ÅQ) ±•[{§¤^KmuÊ<ÍÙi†¬]SJ÷@áK¥̉\il(%hcô†(ÑƠX́ưQ©%¹ÊÁâ(Ö7½8 ×üS¢ZØü+ÅƠÚ{PĂ¯­väæ5²¶Up¢ùW£k‰úkä÷ j¨M¤*‡¦½å^Á*®•f(UÛ´…~G±>í ¬Ö¨±÷“•9˜;v}H¦Ÿ¨ºR5ô2Z‚4»¶Y§—ÈJƠLn•úµb‚cs¾{z&{ëY\jöNo B`S&ơÎuñdí55{₫,ŸÔåV <{v²{~8¿vϹƯsmƒª¢¡¦æ tóûïOv?]̃½Ü_»×n÷ÓÏƯîƠ₫·k÷æDß²û_}¾ØëoßïOvR¬ưùơ•¹Ư¡Nv/öW‡—ïöW7³£¿ö·ư¯̃₫pøÍ½ú‚4ñdăèk{£|o/IJúơ ÑîuŸGƯĂ¿ÿăí1!MïqçÏÎV‡ôØ(´~÷¢°±1 ›_5|$ ₫¢(4ŒûQÈW"Æ#Q´ÍQÄđu£ûQÄ´= ₫ºQ´#Q”íQÔ¯ñư(ˆÅîçç}íúbnư{¿àd÷Ăạ́×ưå jxcÜïÔk*Íç>̉Éë±À1z®6µ£×íA/{ùñŸ×æ¯Îÿ¥`=/Ưîç¹ùñÍéơơÅw»Ư§OŸüûó₫pù~wöáƯ₫üjµûƒåèn¢)=&ÑwÎ…Ưs=¼ơÀ\₫H}©ÊÛÊ‘œÚörÜxÜW½#¥//7o›AÅWEÔ“Ö ÛƠÿZ¡ßá'í]?%“'ûM¢î$]üúßuçâôĂÙáêpqúy÷éôó·êÀ·gï/Îüéơ¿Ï¾ĐCí*ÑœƯtH¬Zº‹Jÿû©ë Âăün#ëúa‡65u ÷›Ú—5uÂY}§©£—F†~Ok¿·Åà#  È d2™,@ Èd²Y€,@ g g g g g g g g g g           W W W W W W W W W W 7 7 7 7 7 7 7 7 7 ·™B€aŒƒaŒ £À¨0€L@&  Èd2'ád rrrr24HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ 4HĐ Aƒ´hđøÖđ_'ÚƒKDe_´¤YOiÑÆRHŸ́L éuëIøçĂ«ƒÓ£́zđÜư”ÁÛ‰){ÖÁ°R&̣…âQʶr.aFñÆ•R—ÙÖÊQÊ2)ʼèØZ)m.é(%oå-­\4ʪ[®dö„,_¹/fÚÈ™uEh·”…5Ü<¤LmNjWN¤vÀÉugƠmVn›VZđ:ÏrJ̃Æ©«ƒo:–$±ïÏjKđŔA+i™snL­®̃Ë•²g=®F”1nälÑưàÔcÿf7q̣ÆrM­ªråÔ¹`ơ‡œ[ƠIÁÛà•“–W†œ´U*I?„骵r2ûiÈ™x̉ç2…FœLs¦(—)4¢”IÇØÊ‰‰0âäI-DI']»m¡¤ŸÏ8¬yRô0å´%h@ÙæôÑ?3̣¬ö%Úg@¹ơ c¬úyIḅöÑc-¥=̉ḳ$[J J”r@¹yÎ.µ%j9 Üܱ(&8Q̀çæB5ùlß|£Ñ¶„ø¤Ơ%ª9 œUMP¢ÊiƠ'ª9àä4g×c]†=u_v=n:á¹<å®·R.»̃ˆrÖ®ŃzCÎI»̃ʹ́zCÎI»̃ʹÔ#ÎY»̃ʹ „g’9aå\&ˆ“ç|â\)—‰0¢œµë­œËDrnm[›6ªŒ;ƠÚµFMé)ÂÚ´ DÓ(7 M N4퀓&í—+'vÀ¹Y(KÓ‚M; Ü¬4-8Ñ´#Î+fLz¦±ÿ#óÅ₫ùL—”Z•³TŸ[}’cŒ³ê„o)E|3n>Ųf4Ç[JÖ#N™tZƒ§ơˆ³N:­Îơ´p̉¬Óœ˜{#ÎYƒœ|Î̓œ|Î̓œ|#Î:gđƒo@9í´'߈“ç|ÁÀ:*ßÙrơ¡<ɳڕR¢·ïWJ)ŸäÓ|LÑ笉MƠ÷ÿ‹Æt×\)?É77ëxç2̃G”4i¼ƒă}Ä9k¼ƒă}Ä9k¼/œëxp’LïàÄxp¦0i¼ƒă}Ä9k¼ƒă}ÀɳöZpb¼8ç<8])1̃”ÓÆ;81÷Fœ“Æ{²¯ăíÓÚ¤Ăÿ¶ÿ¦  endstream endobj 1327 0 obj << /Length 1603 /Filter /FlateDecode >> stream xÚí›Ko7Çï₫{´€áûÑ[Ó4EH¥)æàZjaÀTVêôÛ—Ü%µ³¡¨µ.­9ÄÚÎ<ó3ßbơÿXexe¬ V˜ệæŒÖO·VÍo8¤æË¶}M,rO¢.¡TĂ@JÀ@p “qN6üIPF4°‚æ_{OÖJemh©~>~¢ƠÚ¿{íYauơP[̃Tœ­üO×Ơ»³Ÿ‡jÉdWṇ̃úî~3³#VÚæC 0Rc§£Ú:ÀY…u”…ÄRBkFÙăª=DL¨Ă¸CÁíăqí(®77wCZ¹ LͰ¢JSf'S  ”vʇS c) 4§(ơâZÙJ½¡Ú”BÅíæb=Ú§R=c:µOMNkë§–1C+ˆ¥„ÖŒr ƠxqË hơ†ÂÈĐ wW7›»/»!°‚2:»ˆ±ó9ÍÖÎ&,4(› –63ÊM刡ÓÓ`hƯ ¦§ŇíƠndzÊưzqNñcn§sÚ:À9…̀p b)á4£8•p®ă*₫Å›ÅRHq₫UôÅæóvs¹`ç»ÍÚ?`CœŒơK÷ÿ5N1kÓyhà<À̉Ḥb)á!£x–éz<¼Ypw~·ë”'gÇ÷(1ÏÓ jàÁbfzK Aå@·„›vVöyá›Ă#¤·”3<… 0”b§£Ô:ÀQ‚UmÆ‚Q”@,%(e”J̀ẳæñưﻛˈü¯h̀ Ñq 0–bƧ³Ô:ÀY‚eUe ÄRÂRF9°D ̀ôYêÎÉYØ+6¶6~Ôî£pk»ªÈ1g~¹Èg€sXÆ4NDzu€c k•ÁÄR‚eFÙc©œ&V¸2,•3„ ~.;²È¶[Ó5ÏX€S2'Ó  tv*†Ó c) 3§è´ˆpê[D§7VJ‚N(‹mexÑyá‘í5S§sÙ:À¹„µÊp b)á2£¸4XG̃¿{¾úéûÑ¥)×sv<61¹Ó±iàØÀ *tsÆR‚MO¹{qEø¡ØˆîÅ•_Æ/®TK¦ˆ1±»ưûëc㻩l^yœrHULק߆Q?û8ÁÔ~  ́‹4 Jộˆ¥ạ̈TFYPK˜«´s„§{¸º£ªđëZ!lm+u}EAŒ´]Ul-BưP>¯E/˜C)©“APP;•S ÆRjN9jm¸!RÄ©7Rœ‚S :¾4ñ”R;°Ai“̉éîÛăŒ‚ªem)!—M€¿"¶¦ŒPoû¨‹U{@¡(¾<Ñ|^hLêtF[8¤°rJA,%˜f”§ÚÏ9ys₫újt:é“óØû¸́}¥c§ăÔ:Àq‚UÅ'0–œzÊ£‹Í%±*.»?”,bÂîÅv{q»àö|>ư3rbˆ›oă}ÙnOu„ÇL[8vѦÁN£ØXJ°Ë(Ç^L9Kh<üpu»¾ =Ü7w®nïw××C¤<ÎN=Ù~mPJœĐ)•Gs›/ÛöCLºuÖ ˆ£€‘ŒjBÄújK{pëö¿¿1×Khø.ubŸ€c+›Ú/ƒA’û"u¹Ä¢ñơèÄ‚W7Yç•{.kåo†Âáíô4Í̉‘¨ă¼¥ït˜R¥ˆÖyáK$†cÍôÄöùPz"M÷{¤e„R^„hWî¹D’à߆ï%NNBl ”®HsÉiH‚SÄJW„hWî¹O‚¢ŒøtMNBjŸ ¥/‚|O1J´ŸÖ•%!Yç•{.‘$Ä)Ëä$¤yQ>”®H3/¢èW–„ư˜—QNƒ<̀¨½ïn×oG·®”#’?ơ3 ’‰O-$™ƒ§¾HÓgr’ÜÁÓ¿ø_Y endstream endobj 1305 0 obj << /Type /ObjStm /N 100 /First 999 /Length 2153 /Filter /FlateDecode >> stream xÚµK‹¹Ç÷ư)´L6º:/=À ̀Ä8›̀Ø‹$Æ ÇÓ„!Cw°Û0ùöùƯ«ª¸uIrUà‡ºZ¥ŸttR' )' DÙ9°°7J­̃¨A³z£«̃™RÈÍ;…¿hph\¼!’̣Zx…̀ ŒÍÅGp‚´>:[o¡K¦æ-üSÄû1ºTó~ŒÑ[vsÀTÆĐ·€ÁÉ:’Ù+û(Œ˜ú 0!Îæ³â¸”₫¬®ƠŸI ’’3„‚P U00!ÑÜûY+>ÉAróñRª©¿Qƒ4öÙK ÔßÀ?JæËW ÊÅg©©ô¨… ÀP…ˆ» Ô‚e 9hƠ₫¬m}°–úàF} &̣¹,Üçb̀Ôß0 –sĂ4Xé³Ç„¬6Ÿ‹åSêÏJÈÄưY Ù—V Yú.`ùY³?Ẹ̈Y 2‡œ[&!C ÀÀ$!K껀Í+g=È%”³äÊYr Åú J %³¿1•"₫¶¬Tó7„̉¯@àư •S#‡*Ôß(¡j—_©¡ZŸ}i¡æ.?L¼–>{(R­}öª›ºW ½Á¨ u—}µĐ¤ÏȦ¥¿[B³>ƒZ&å3¨-´ ơfŒÙt«%oô₫ ¥£!qÙ åëđå'Íñ½HV}6®T©$ŸNsSªn(Ü0ÔÄUÔçŒ÷úk FÛŸ¢W_(Œ ƯÄåJ†yơêáô₫ßÿz §ïŸ_Nï¾ưư¥ÿü§ŸŸ₫ùpúáùËO_‡_>>œ~|üü>PÉÑ­ Ê“Œ ‡öÆVư¾¯^…Ó»púăóûçpz~GüûđƯwøó2ÅLN)ºBÜdÖû˜p~±a&Y$ª7™lw29Å‚]\˜ÜbËv“)éN¦X4(ÍÂT•ø63ßÉ4°à覵˜­Ưdê½ë̀y#Ú¢Ñ]̀M¤̃‰‹Î±à̀¬-Émf›Ä̀-VuƒYJ´rŒÖ$v‘½d.‘ö¬3MbjŲêÊ´Më±LÁöÁû/L…§`=–É%ÊF´0ÚƒK9Oû‘5æ’¯3é^¦ÂíÁÍ¥µ•IAóUæ$3Aêki é~̃Ñ™Ä4¼Ñ¤YQ+ËÔóª?È#cƯq4Éë!—i£AÈ#réc™r·…ɰ“=ÑÎb¦‹­5N¬Uµ$ùQ6Z›4ÊmN"Ë+y5Mj‹ØUd™„D¢YëY Øơ½¬“È·¨mđô”íHÁú¢l_₫_=X8¬Î§@y34DAᙑi¡^0˜¢©…)¢9Ä$$¼zöbx0‘ ¡’¾Î´ILä´ åï´Û»›ÅT¯ƒle"bƯQŸ<‰ ±ºÙO؈Y=–I%Êß…Ép …e­ûqƠÂDư·çñèN—§Ê•|0×Ô˜(`#Ơià¯ë-ß¹NE¦ÜtEå‡R·r§GĐB±Ô²2+Êz”Ø7™÷.³f$>›u6‹~€v‹yo©i‰<¡[˜FH¾PbßdNr} ó¢¶·˜vï:.O°.w;²§Aµ(ñ!Ae µæÆ j0#="9’ƠíÍ«CІ2pÇ6yѹÊêßµ¢:ItˆZ™ˆÏu4,ÓơxÍ2ÇPÔ¼¢n‹¡höz'^·Ië̀±ÎLST[L´ÙO3Äk>F¶ƒ‰²ËO‘¦*âơơ8ƳL¬ÚÊʉ5_ÏøÎưTb”BͯT¯Fꇰ­̀×|Èq´r‰ư&æ‚„„5Ómd›“! ä%A¸…œ” â%?¸Eœ• ä%=¸‰œ” ä%;¸…œ•\‹Ï»…œT/ ä0ËÈ»sƒL9úßẤæz=Pó¤&ØE[s…ÀK*Ç"½ßTœ̉<àÎNÊ¥¼n*Î~Ͱg'“¢‰ ².›Ó¯ÊNÅ9 g—6¹˜gEt,•µn*N¿gr0Sàl5¿g°ƒD” !#á¼2QY·V9¼\™ û)+ÓŸ§̀k’b$ëÙ6¶’,fæc™µÂï¬>›¢v±c™¨̉ÆÅû©ï܇ñ¤ưô›Ukf‘h;gÓ˜HN²®¶Â™c-zh&í7ă₫‰̉Â4T˱ëD́²Ú +E;´ædF}PWà×8•äPÉR±(›C ªØÍë›)“6eEâ·*-!˜æ̉Z&•Ed‚Œz=A Ó¶sh1©yTÈ^£pÜâGeG{¦!Q̣ɦÂ%h¬́-s̉1!m²úvB¥|ư”D&ÅjJ)Ú&PªQËÎqâ$ÿSư+’ƠJE-ë¡«,¤¬6Rư¤ÿ¿ÉG^‡ØxóÇpúË_ÿü3Aÿ¦…§o¿ụ̈ñí÷æùé¥#ß ê­çîo*ú^́zÆă¹ÿ ư¼~zûåùó»G,*œ̃¾~Nï} +›·Ÿ₫ñøpú(O/_ƯnúÈ.¯Ïß¾|~́ḮǘÏ?ưüé‡ç_ÏB³æA!‡`Đvß~ú‚A|zîßÿü₫E¡O«OxiđhÈhèhØhäÑ(£q–Aÿ~đ̉(£±üª]”FƒFƒGCFCGĂFcŒLcd#Ó™ÇÈ> stream xÚ·T”k6,̉)´ÈP̉1 Ử-= 300̀CƒtIw‡4¢’RR̉!’̣̉zÎ{̃ó₫ÿZß·f­™g_;î×¾×3, Úzܲ6Hkˆậđ‰ä5ä€|>>>>~} ù &`1„¸¸Â±ÿ2w€PhL„BÛi 578( ‰…Åøøü||¢"]Ä w˜ @ƒ †D@\ Xä‘N^.0[;ú˜¿l`vPTT˜ë·;@Ö⃠Êâˆ> ‚ô`åơ¯lv(”“/¯‡‡ÈÑ•éb+ÅÎđ€¡́ºWˆ‹;Äđ«`€&Ẹ̀§2€¾̀ơ®‡„¢<@.€ĂÀ„+ÚĂ aq 詪´œ ˆ?Æê ¸ơä₫'Ü_̃¿Á¿A`0̉Ñ „đ‚!lPĐRRçAy¢¸ „Í/C܉ö¹ƒ`p5Úàwæ €’¬„.đ¯̣\Á.0'”++ ₫«D̃_aĐ]VDØÈ#!”+Á¯ü`.0ºí^¼&ë€@z |₫ 0„ ôW6nN¼˜³DUá/4Dđf Aùøø„…€ˆ3â ¶ăư^ßË ̣[ùFWàçă„t@ÑE@ü`Pú‡ÀÇä \Ü ~>ÿ­ø·Dl``Àb Cü C dôđ]`S>4÷€¾_Ÿÿ<™£éeƒDÀ½₫1ÿ=_̃'ZÆÊœ*₫NNé đáâpó ̣€|èă…Ñ~ÿ£ ‚ư•Æùª" H€èŸlÑmú;c÷¿Àö×r°₫K‰f-ÀöÉÍøùÀè/àÿ3Ơ»üÿ1üW”ÿÉÿ7!%78ü·í·₫ÿ£9Âà^ Ië†B/€½ˆÿ55‚üYZ9$Üæuª(z d¶đÿ4æªó„ØhĂP`»?\ùƒüÚ18 ÑFºÂ~]*n ßÿèĐ‹v@_®hB₫VAĐ{óï#`¤Í¯ă€\\@^è£%A€½‰6Ïßđ̣ (´ ]œt!ø5O¯̃/è·$* àư#¼Ö. °}/BQÿàÿÁÿ̀öo… €Œ„£kùAs À ù/mÿGD‘ù_¢ €×ơ·ø¯Án..è%ÿÍAt₫–ß(ˆ'L0=‹‡Ø¿ i>«’¥ơà^’cY5Jgçö™viq» ÁMa“´èr"›̉×A:·¬Èv,3Cí³ƠX‹₫>I§é̉÷Ê2Awdµ‰`j˜¢ûsÑ–lÍG:üÜú2ß}¯} 01ZƠX̣ƯDH´ ÈÎ<º”=k>¾œ›XƠù₫Fè áƠËQîƒh³À̉q–Ö9_¨qPÜtx÷ö<ŒƯËû|C¯–ÀIà·#Ṕc̣•?öü‹÷ü+}~×6jfj*:̀ă{#|äÖSƠ('}ÊJ¢%'s…#ăzgBº¿<1¤f|¦MåRÎ-™ ̃JÆÜ–çÎr‚?k±̉×àù„²”)C“*™úÊ,sÀüϯ™èô1l8[Ú¶mï´ṛ̃9W’Ö;$z÷ˆ4eÜD? ]¡xN"7z1Os)r=Á*>€5‚Ë#ÓR°·¢ï®çÇûZ^uÓh%êY2~Æ:P}œ­î¶³Eúß7,›d‰±o#×(ÀJ‡µ¹jEÙ±óÜt±øá¾ù3a‰ÉDXĂ]Ñóy‹rÆT ~eU o1ü̃•É7Gƒ̃đ£₫ îTÁ$G°Ïäưzº̉ø‹Y¤.܉‰®£µfKFŬ¸!Ưç4A.ˆ›D̉ çwÎx&Æ—ơË̀,&|³í"Ñ+-á*-$Êh¦l•› D½û*ᇕÖÉèËsvë‚–+r3wđ«ÍdàÍÓ@?Æ¥… g̣;¬£ˆr‘Ûy»n^Ư„×/˜́„ ú”Ăiö/ûƠË‚WM¸̃k›LÔ$ ©Ü}áÎW®µ—vgÅRºÁöyhæÁä̃×7¤hÄ“áYNbÆ3o8‚2C¯m‹²™öÊƠà±Û Çé>Ñ0‘t•†P‚'æ†Il¿ăF̀( ¬₫)‘GßÙưmàÉ%B›ơ%¿Ç•%M°8pfrU Găáll̃Vn"ö‹£-­Æz‚£‚Bü´ƯqRCaơ3ß&1;̣¬Ø°å”wyãÑÎN·aΟå,PµñÉ TjÅ₫gœ¶evO«¾W©ª„äẸ́?‹Üx¤3ö$‚æ+k.#ü€ÅÈg×Z¥jBîñ¾ö‹óÚ́̃»Qđy<„!KWOàgsnø®Ât»dxÎf’ÿ¾'–Đ–‡9€ä‘Jé¡–F·°?§Ûđ°¬ăăûŸ“=W‰ËƠÊgÜ*ºzgứơ,eÄ0¤ß1Ef¨ƯÄ+ñ±ä¹ O¼sH o»,;T3{‹“ÛÉ—QĐB-Œ 4Gí±`̣¦Mœ)<èe¾Ô®́Đ*xü³X £+ÛM„ôkÚ÷rÿ»|·½³ÆçAO¿Q^’EnED¼wØQl)êq)´2;̉qw¥_W̃ú"E“Î=Æ U|±zàÏ}â;¨ßÿüy{pS#ñ3‚ZLÉtv11ê΄ơ"b́á‰6] /76ù>}"IÉf¦Xúöà»RÂF¡aªĐ[\ #v–Y¾'‡ô¢aH®ĂoÓåºơ¸́Æ(ɤ§á.=ßspûæ£,Z‰UŸ8̀I-7Ÿ.Ơ¡ô}‹G\ïEƯÖ©ídɪ€»ËëZE\gJQ¤F́·jÛ\”~©^vSÇ̀xµ·Úç,qdGº›Cj¡,¼†ïYYit׿|Fk!Éz(£¶£N¤“™¼O*¤àS¯´²^UƯ·Ärî<̃‡ÚB^bKÓD½e¿¾Uë\2›HF]Yg Œ)ÔÆühdß>Ü@ưđ‡œ”ưåè¾p:vÔJ—dÙÿn61ûƠ×@¯ùç v¤°Đ˜<—TÉv«ÍƒLIT̉ÆË1­˜u×½øBu8–mèVÖ?’XơÉù@ű }»‘hŸk©ö³~RîꡆÙ6‚#Í=9[_äxÊöª¶€×^€đôXæJ–qîÆu™8<ƠÎñz³á̀é±U¬à́Ơ>ÆOF9.µ‹QczF|`S@i¢D Ÿ`fRwơƒèSøMƒ@•nÓêỹ0wû=€ư¨ư‚Aé÷O$&ƒk}øÑṛG‰̀“3ߘ$̀IeLŒ„ üÜœ ácĂ\Oªƒ[¿í 2LYLUê~•¯’â:Z"ápñܾ(…Ỵ̈àarä•©È$Ô¦X3ß8Đ¾ơ)³ 8Ç#t÷ä:Z³eµñïKï×?aTK)&ô–SW»;”pçvÄ0€Ă6  é٩܉­Ÿ)¸'m¨2=´"í6–ywó#ư8#j́ˆ÷ vđû¢°®ô§á₫Zm‰"»HkM W~¹N¹zÇZ21„¸IFđÜe<xß”oåå:Çơí“‚ÇŸŸyP·§©̉mœ ˜¥:jµS­’q¯it)ÂT¡êÆ1'¦ï{Ú̃‘h,b¥¥4qG 6ï—–(`iĂ- ¹…ü;ÖHiđBÇL=î;}O-Én3Æ=$đäÅÇ´`k<«Ê\º‘YV?¦_¤ÚôËÇ‚̉8ÍnQ>E’wv‚b̀¬Í€8ÊŒ•*¹¾»[0IâPÑ—_©ưB.y<¹ù_Xô¼Kûß|ŒëE_I‹OáíƠÏB|đ1a{Ó½‘æƠZúF½B¡\'|)‡ èâ”ë`>ˆ]}ƒ7ñMO Çü¼vH€¡zkÇÊ4È—ó"è™Â}ƒækóÈcç©ó×¶0©¯8L¦éT ¯\sÓ3¹¯ư¦Ăw?è¤ăØ›}ë€çCB<«³. ô™e—4gDÚptÄ m·,}^»₫,pâDU‡ERµ’ÚÁN öµ “ÈĐñ–|Í…$~̀ü¨>^W­÷‡×S‚ËlĂ^¢~Çfoï7.́ñ†=:¨-/ÎÄåÖË ±Đr̃ñTIù¶Îxn;‹µK!SÑ:£Â'b0E/fä=Ø6ñº¸´;éÊXA(đ{đ9•èđ«Ñ"đë~î=§½Cư@"Ưlk~ÏN»È˜)ÉÛúÛ¤)O燲‚ÑodüWĂ“Ó&>4síB·±•ă^¸€Í½ë&d¹€Đ[Èë)̀½4Ë®‡É|¦Êû¸KÙ7$@ %Ø6ÎÀ5adÆ|k|“*>¤ºë̉Ú;•‘×á‰ÈÜéøÉF¸jk‚rî́y5“=kI‘v'yÑi§Å)P̃ÁĂt*dàá´µ©h¥øÀ̉ëƒ1 > |j_Ù]Ú¥JTÜçÈËĂÀ@=¶Hʘ™‹‹Ơs&¯IH¤̃½ís@²Ù{a l[OƠ;̃ÚcP® 8#ÚW5—̣H Ê¢™QNô-ÔH(®ơ¤³Tȇ=">ï¾_‘>—h.¼ư®û´÷S†@̀‡±rå"̣íÔĐ6jIƠ.ªKÍpC†‰Èeq‡îM2´‰XÄ•ëƯøĂRÆ"=ïKE_Đ‘@‚èo»P2hBc~rîÉ ¥¼Ç«"°Ăî0T,nùFá_+ên¤”øÅâMÇbîMÓ̃wSđ`ƯRFI¯d¿B>1ÛƯ1Hdy+–ËDJ!z^ªû̉†î­‘Ô,₫ˆ€É³ŸÚÆ™̉â_S^°l v {µ ̃VÓ gS¹›ø G?¡ó‚zU_H´_´̀“4ă>-âÖÙA¼æĂmAßX)Ûé¡ d+§)úNw–Lglଛ@ 31Ư¨ñF·£íå] BÙm©K2—C¡E×´Đbñ̃¢DA_W}äÂ'\ÇÙê†\°‹B}ëPÿùÖÛ đYäûÙ@Ơ{"3²»tøLñL­ơ,»4tg’W½ ½É Dƒ̣ëÔPcSbÿ†úƠ0jÔ#Ÿ{ƒÏ™º¸;'©K ß•ơß,Y‡oQwºÆÖ³É©ºñ‰î…ŸcW9‘¬™‡+’wơ–Il0o¬½̃ïs -b̃‘_KMĂØ1—²Ä=NN,/W:¼5|~YÔ0¸&qï#'aŒĐè@oöV¬bJ%·2“ûz,3T“îÈî<âB}ô®û̀³bu©ö3Í*ÖÈJ]«YØ7₫Z&¬‚¬M×÷é…TöơÜé}~*âOceÎÚÎx¢́RL0¿ÀΟÍÂÆœ₫̃Ų€yó¤UƒWú“£¯¿%EE~˶-ľ¦Z ³D <$H:ï!ĂË<¤ÿ¤¹X›È|gS'åi=i›̉"ïñOöë́0W†éPÜ=]©$×̀Ạ̀5f¾1b́Đ4¿1¦!Fn™XMîÿÖi‡K§¦zDđⓦ,ø¹:{°·lØf’„O Áfö₫é ÿñ1¨è“W¿8?NÎóȃ”Ëg8ÀW{áơk­Û¢;¦Ëï2Y«̉ÙŸJMóÊƯ°2„`̀§*NÏ6Ÿ‡Ôˆˆ/ZƠu[I½đûR8ÜTÜưÆCxơÔ9—ëÍÓ—¤¦.ÂƠăr߃¸©!jJáơ&ư¼Dû´¼È6äÖÏ0ʨ …#öÎÎömø¥\Ô{“­Én"eƠ´xđ5úáhÊÑ|ƯLéº̉‚ ¢O÷kÂÆ„Úû—úî ¼|²1¸đËƠÇÔköøè}v¾ô•ựHûn/r¡4CzÅ,j§±•èj’¡ ÓîE×<ßù®#R‡îK-‡[¶8×lRDñ*?¡p7@‚x|ô4ºSÁ₫{Ü•ÆăåäwňưÉ–™!g Rơs½°¬éбf7\.Ù·ËY¦êăÁĐEÀZĂ’GÓ¬̀?F¾¤µ¦JËèTÖGkOfö́âuÈ"^_ÑD`Œ>UØ0mx:çNë̉¸‘©g¬Ñ¨¸Đ̣! >Î+:m=”éIq_̃)ÂXÍh7B|ïrl-\]îüY,÷_Å ñd£ÚñI3Î₫ÂÓù> d?^c¡ü•¡Hñ™jïæhññđHK+F»±ïÇ;ϯoQ|xó-ÖˆÄMÉ$́¥ ùîíÑ‘çåÄ#” tÊ̓>Ö Gù(Ú¹³V¾­Hê…ºYVVơW²¾sn’Ge½\kßwªÂ ß– g ptƠ˜£°0Kˆ€éZw«Æ7G¥̀Ûû´ù̉Ÿê”Ôă\œÜ<5un_q̃>€`$*ÉO_ V_okWb¹Găgû¶_Đä#4±ty(³sÁ1N Ô…›r”e&Sk„Ç̉ạ́$:¤[¶©ñ?é&đ\IÙX†ØƯQÖvḉÈ^X3X>˜Å)k[ÈØ –wèE®!å#Ăk"U|k²[¬è29 evD’ ơă¨å°K»yÜ[SZÛL#5¸b%O§åQRb[¶̃) ÉÖƠ~n<{Ÿí ]TCäx„™̣>Ư)f‘ó‡@~Øà[)éç•ADRÎûëP©û•&Ÿ´Å o©"²ị̈„¯,)~”h™t™ËF¼rO’[ª“1‘ /\^ïnBµ]Vb‹_öÚ*‰ơJ:ư¨‰¶4#vz?•x\đpđ'QÑçoña¯h®¥̣Ä„»RñÆ•qÎe9Æ5'y°>¨;:!áx!Ç©¦[¨ÿø‹‘ŒÈ¶ÛWÔDy á—åzÅ­ ~f“>;%9\©éùM̉s"Ơă×ÊUÈ•ç´6’Ÿ*®¡JÁH?öëzŸ˜+ĂK˜.•Ñ«•l¥¹ë̉å²û§™¢"ÙD°Ă Æj¹‹é“m¤F̃‚Đç$€˜™Lhê÷lM@£jµ)ñ?-}fêä2ă÷1R°¨iđ½ %öl®_¢h'xV]ÏhY›̣5ÑGnuß¾tñ©°µmÉkBá0Û5Œôª'Xü•5¨g‘çd¯rn…q0Í€ê*ü¨ă»£̣NDÀİp.q¿x ÷èƒ=¹­iă›8SKXèđØ{N]́vÿ+¼u¿º­“…h„̀Đz=Y v¸¸{¢…%̃VF¶ó̉áÖîdåmÛ·.u]§8̀Mz»§5ç´–îßw̉ÆÊÈÀºÀó>I¦èƠ†ûͲ¦¡Ët¹/&¨0z^Đ₫¤@ɾE<äœsø)%[·\z *́₫L’̣’H¹Ư|& Æ‹#—ÑiAÔMĐø̣ÊăVl¡9»‚b3CïS=pOÓºê{lå±0ÿÇÅx¢¥8÷ÂY™mö>ö+÷A _ ¡ưÖx©¯©wŔT ‰8“.H“™_ĂÎ:aÂÙ¦íƯ)³+¢÷øb–—©÷: 2tΫhdA‡O>0ë&Ơà ơIl! Â~ÏßæÂ¾,ẹ́p¼å]Z°€xÅ̃7~Ó´ ï`t¯$:›.dÀö€™~¹ñvæ°|n¶huä}Đ'§ åc+]nU庻Ạ´Í·YpT&GëoÖߺÀî—:°̉Ơ‡v¢ X­µúæc̣ˆ‹SßF7j‹̃·*Ü9ø5X—¼æ²ïD|9Iª¬™^ăe5¶2¼ĂÍ¢g\<|N•&đ9m”ÿ~!†m'8@œ"Ô‡ÛùÎ7ăîå×9’Ÿ""µ“ï§8™Ç`ă‘5º¡Âˆ̀™ ư÷ăƠµpvéĂô¹LZu1l\ ½WH­„öëw< >^öc:•̉ tÙƠÆà}`?† |e›5ïä 9¬Ơ`3W^Xij<ïvG̣rï˰—nt)En·jѵÅv)üÜ;P¶-ôº/ÇOôÁ9*ÛH†ƒq+J&üGn½}kTÿƠmy‘[ ·§Y,pÎUnTÊÛú‰ơ´É­3ÖëNºđ2Ù½sV*<êĂjÏB–‰Sâ=†íù¶_  Á›¹HÂVfằ€²qW—â1ÇRë+d·WÓªÍxmˆẾ”²ØV™EˆÈ ‡£­úÎ8ăÁz]†5\˜¢äˆQµơv‚†­X·daơ¦û‚²J[‹åă(̉ ¹n*%¸÷êIqLˆ-?Ï;̃¨nĺOᇓÉḳÚL8Úáw3E™̃¬Úí™â?Ë£ëơ¾Ôaß‹D±j₫Ä7 ÿN¯oIßdÜÂæ/§Xâ₫¥Z§ÿ¾ÛƯhºƯ'Ụ̀Sê¹F¨g­–|Mád<€]hÔ¦)¿©‚!%Iæ‚ö´ƯÏh&ç÷₫âßeUAD¥X̃ÉTĐ)å"‰ºOu¨¢Sl–‚ ›+m|@±Œô³‹‘́>£ “…¶Û]]å´=W3ȲÔŒmÛ¡Û%=ïÄ4Đ‹ªÇDQæ]́º6âr ̃ª`Féá±–Sߤ$—ª„/h®Ccxv øX^…ÎOO5û)ô÷E`½Pèq¹M±X{>c„̉Ư@”ê K %y9Ï”—y½=ëY…Y¡WwvïrÑ/ÖhVă¯î+eà0íí,’8e†)~¿]ê÷£<§¶,ÔSfµ•'  &¸ó‹¸ÊƠ¨KkŸu~ |9¦ÓŸŒÑ{×J4éM–‰2Cfvœ¡ÇƒñCđÙ3Ó°fǼ …:7óiܯËU’½†n6à±@¿5Ÿ†!¤Û_}ăạ̊€w—Ù>àÜSVcliÜ|.HÿoäèIkp»â™”ÅûD*ád¶[TƠÍ‚pÙD¼ùss’`[¢r³­O¸I†ç³ 0°’vçPd£i[ăV!œ•·̀Æ\Û6K±ư›‰7’[¥'ü¶F½›çsˆ*«Xæ©Å=ùV¯4X—ÆüoŒºĂ°«n“¥Ư Ư¢ #NhêE@̀,ÖO95‚ơ Ó5œsؘ¾ôL¹ ̣âÊÅÔz·Esª‡LvḰ:ư8µ¡‰ĂKH S̃5³ÏÇu˜R{ÛÚkm² †½IùÑ0r{̣áûäÙMµ‘×Mî” :RĂÂlF{¬½½,ÜùiD×=y†«7±s܃́Ư¼óº}̀•"ÁS3Ơ0ê ä·w.æ±7|u•äƠª¤¹Ê3jÂ"Ơ½}¬ø«eƯå‹#©o_wÎzi%û™{á¨\‡¦> stream xÚŒöPZÖ€‹"Á5¸Ó¸»{pw M»»[€·àÁƯ‚»kp—Áƒ_Μ™É™ÿ½ª{‹*èoùZ{íƯP‘©¨3‰Ù›‚¤́í\˜Ø˜Yùâb:ĺVVfVVvD** °‹ è?rD*-“3Ø̃ÿâN —7™„‰Ë›¡¢½@ÎƠÀÆ`ăægăáge°³²̣ưÇĐ̃‰ aâ6(2ä́í@ΈTâöN` K—·<ÿù ̉Øøøxÿåµ9&vEKí[F ‰ @Ư¹x₫OZAK~wwwf[gf{' a:F€;ØÅ r9¹̀µ P2±ư»5fD*€†%Øùo…º½¹‹»‰đ&°AvÎo.®vf 'À[v€º¬@Ùd÷·±Âߌ€ÀÆ̀ößpÿö₫+Øî_Î&@ ½­ƒ‰'ØÎ`¶”¥˜]<\&vfØ8Û¿ù›¸™€mLLß ₫Uº @JT`̣Öá¿ûs:\œ™Á6ơẸ̀W˜·1KÚ™‰ÛÛÚ‚́\œÿªÓ¾ÍƯ“å߇kmgïnçư2Û™™ÿƠ†™«‹¦ØÑ$+ño›7â™ÈÀÅÊÊÊĂÍ9@@K–¿hx:€₫¥dûKüÖƒ¯·ƒ½Àü­ /ØôöÑÛÙÄ pqrùzÿSñ¿„ÈÆ0]¦ °âŸèobùßüv₫N`€ëÛú±Xÿúùï'ƒ· 3³·³ñüc₫¯#fÑUUÖĐbøwËÿU‰Ù{¼™¸8Ĺ\l66>+À÷ă¨˜€ÿ]ë_Y;s{ßßå¾Íé?%»ư{hÿ}AèÿKÉ₫msAÚ?‹®ÏÊÅ |ûÅöÿyƯÿạ̊ÿoËỵ̈ÿºèÿ·")W›éiÿ6øÿћ؂m<ÿmñ¶¹®.o·@Ñ₫í.Øư_SmĐßWẀ̃Ǽÿêd]L̃…ÍÇv–{€̀TÀ.@Ë¿×åo¹æ_ÍlR±wÿơ´˜ØXYÿîív­ßç·ü— ôvy₫7¥¤Đ̃́¯[ÆÎÅ 0qr2ñDd}[%v..€7ÛÛu4yük‹,̀vö.o.€·æ|æöNˆ(7€Eô/ÑßÄ `ûC<ñ?Ä `‘øC|Éÿ+€Eê±X¤ÿ;€EæqXdÿ'€Eî½eWøCoÙÿĐ[v¥?ô–]ù¿Äû–]å½åSûCoùÔÿĐ[>?ôÖ»æzË®ơ‡̃²kÿ¡·́:è-ûÇÿß›¥ÉŸ¹¼e0qù£|s4ưCoÀÿ̉_ÇÍbö|è¿øv,oÚƒ·Î̀ÿà›¹ù?đ/%ø;Ç_èö'Û_›?ú¿̀í]₫ưÍÀâøÖˆå‘ómT––o_,̃dààÛ¬ÿoÛüßZ·ưGío­ÿ Åơæj÷¶îÿĐ¿5gÿ'û›³ưÿ¨ßªwø£~ æđöEfg2ÿ3.N¶K₫gœosux{ẃÿ1ù¿făø|kưƒa{ëÓùO­Èíƒàz3w~{­ÿ›á­ggË„xKú§„·WÅÅ̉ ôĂ~ëÀÅƯ₫o1\ÿoĂtû¾ÍĂư'ÿæíñ| ïù|›•ןẫ"yœ₫Nơ?/ ĐƠémX.ÿzëß™ÿđ¿¾¼A qyÁ(bỦ₫»Z”ĐioBh–jO;•É{Ù©Ăơ.‰®*3hĂéV4iø;úê$í͇̉gï“–z¸đÖƠ¶GŸ'£ÏjÓ{mˆKS8“'¢uưÄDLö}}´­¡[ »ä¨r]yQỤ0»÷I{Ôơ—₫ [ØSƯ¯â–Gz*aú¤£X4G•k5GëÂD OñËmîæv#{̣•Tî3¢ïÏO…̃º›́±÷ó^kǻÎƯø”øºxÄĐ7cÓỖb‡Ér¸‹̃Åßâ䢿™.4 w ™8rÖu- –Nnâ—¢íL‡ÅU·©Ä†lÔ³;ñ0rêxfÙŒ̣U;q¼¢+æ2‚E¬]NUØĂÓz¿Ø„ÜĐÀv†&/r/áç ôóùÍĐÔyơÿđy‰Ư4×E¯ÇÛÄå´ç÷…ï䤴üW½k§ÂSDĂ&#l–dٰƧ_µ‡*1^­…! K>MCÉ[ƠlÈuy¡¾ö*}=‹¬ îß@†Ú\tÔØs Y2+ƠMǦ[ñËơؽ•Œ¢`WÏ«ÖK<éÏ3Å+W„ ²©å©*61)H̀£!h·¸.ºS!柨Ÿ.™‰@:2«3ûâ3-[:u*c衈VY6 ¢8gË*ăĐNÈïd›ºê’cÆá^¬œ#LƠÀW₫Ĩ â„G‹_®4ˆư5y;˜"C¸IתçÖ2o¸!UóŽêơbñ©2~·wj[K[‰Y¼VkFÿ\iŸ(§ă{3Ç{T˜9Q‘K#tçÅ0•¦»R¤ÎXOsuÏâ­….ÓÍ÷ă½Æ|®Ä±·*ÛCñƠJ®N t B®–%±óA3C˹­=*sцE¾xMͤ0ƯƯsˆ»LÅ^ôă?H8Êünwd Ưqƒ½öTù¡æ‡áÚHQ¶Æ™§±­¥8ùnx)¥´éA‚º‚QÜKé\̣?æ̉ë g¼̃Kwä²B̉uû;},Oˆâ_¬ÂæA∡”ạ̈ÈjÍ>Ă,́åh¿¶d¨ 4ḍơÁèêfÛúqíCÂk⇃dơmĂ” Âǘ̉÷N‘osđYơñŸÍ3œ̃--¼KjTî{ơƒ_Y?ͨèFƒ„€ ¡¡YÙ' Lé1¯ Fyb)j§K¤>ăóB<¨ Đ꣇´N`æ½ë[éJ¢tø…™@6EN¼zÅW£âѽô-É\7`8ñ…âiÁé¥ ÀÚ60ủótor~Ă¢\NÔ’ĐeªJî©L›Ó^‘Ovh¨B>ËkǹơÓp½+üµ |Rdžư¹œ́>ÈÏ$ƒ‡³ ø&æhu¦«Q¨•a´TK ¸ÏÑÏQ=?ÈkƯdùÓæÖ¦ û@Ô>~Ă$}¯!¨éV©{e®‹ÿWn‘^åx¶ÿˆ½fơ,₫¨È¾k<ÆåT©wÅŸ·[W0ô°YÑ9î·ù̀ÁXT4F(̃ŒÄ$3ç3V9®̣…—*(¹­†YÚOÅLjL…ÛƒçLh'æơAiÂ3ÈáÂÜă[¿ÇGf”ñ«4,‚Ô®̣{±îG÷7Y:› Ë(„ar.6…ưw{¼m:xÿ~"‹ ©&©äçu¿°nÙÙØºÈd́8ï¶.¤ía<,…-HBåz:½8‚»•đsâ=ß77!KÉn#ÚÏø0¥ß©p´|E¸f\ ‚yë:œ¥0m\˜dq¿uÄ3`«%IäncË:›Đơ—æ tr±đZ“Iê+3–mè›çÆù?50 9 óÜ&5+´>Ö.é~÷«´¹¹¿)Âh3Kc+çg |X1b "v¬ú~ÊEU`øÇÇ¡å èLRưd³p"]ÙиÂA&@ ééȰµ_v2#WŸä/z‹°ïvgÅâ45¿’¬K¬‚NÇYm¾À ́ cáâàJÖ‹SÓ¥´̀_wOí ½xäTÅLt·4ị́—¹çKú†5è¡Ú₫ôºKRĂ₫MI<û­'™ĂéÚçà¥Æ¢}„Ê„ĐXlb$ ³ß`k™P 2¿¤io8Đs̀h*‚gÎZgu%̉̀»#₫ÙA]º÷ƒQtÁ‰œ³r½Px¦¥ Uˆ¢ôA^ª]2²ÊåÑ0“\Gâ ’)ñD~x₫•®YܯËđäøÚè¸>a¥Ó’¼u‡8gèoY-̉ ËÊ…–ÂWÙ³öŸ®gOr³º!Vä~É1èÛ"NÉá?ră|·ÆÇŒ]° ä#‡UBK̀ôèuüZr»{‹¢…Ö+Ư|3ÆĐT Ä 7àgè£|œES~Ë0\W°‘V|*JP·»/èßñ£øäoô>̀€økƒ>øö½Ü88sÄq4ƠV _0ïȉđ¤W¿‡Dơ½Kkq»›4AânQÚÖ†¹ ¢{éª*̀°*«9¦ß’ư çvUPnŸ2ơ÷;{2Z“Cx’äº(„Ả@ör.ª?ơuU0NV\ (í$çù*ß9‹}vwĐv¹¶Æë© ˆö¾¼Œ/đÉq3¦#ùÎ,FDÄ‘»¼Ÿ$O™„•ˆÖ`äđ¯MOYsîÍ’ÀmÛœU{L(ü®̉0¬+cÿù9˜*đÉSB_±₫½:Ÿ̀̉/ƠOíóYNæ×̉E†Oú\\áI;ËnØz¡'ëé°päwƠ ‰êứZ̉* ty©óyLP̀(_RÖ’ ]X´1—<'»ü»úđà¯Ê9›Uå½é–…Æ!Bµ%ÚÍ„Û́ @Ç+ºËIà&Ú•/ ¯¦q>å·0äÜ]̣ŸPHUtF7¼LQ¿eë†gî|_Oé¨p–äÍ•ÙÑÖ*·7´JsơñULơ ×'ÿ́˜KWdµ²Ï káVÍZ™ÓYäu¾é ¦Dºû®G×ÄnW,›z³›]Ά£f¯ ‚sxÎo 9X=~˜r· ‚§ĐưíH¥ßÑØô­(ƠJ0àó3ó+s©9–"¤|ˆ±D{ô‰1#“q²œU”m±cƒ¯ ưÜ ˜̣ơD5–4'΂“ĂŇâdœyˆŒE)wÿ¡sM¬Á¥½n·Ê8‰Ăd́âbă7§*‘!•x“a´ …&hÂ~ÄI öû̉èƠ;ißB Hüô•Ü8»n!Ca¨¸™œ¦Œæwë«R¿;Ư•5â«$œåRGU [ëz‚½á;4Ö;›®Ù+µđ?W*9òÄ>^¢ùwR‰¯XÆ\₫ $ZdܺÎ̃'¸²?’OY!—ɬBCË4—±Oˆ¡kóĐÈƠĐ6·fL_VÙTd×â·î˜mrTç ­†¥¨¬²‹UêÙÎÚ¼LÙ‡+k´Ölå›BZÍÉWY8ụ̈ûªo“ỵXxz*„Fí™Ô¨¢ö7í’‰äĉ>ØíC¾r‹²}·́ÆR“â«ÎÖX@ö§Í£NưE¹ïÏ?zmÙEp÷z§øjƠ}Wœ¼Dø“*^ W+äu%Bz{È­)VÄXó„_ä 60Ö8ŒöÛ›/£ ">MđăƯPJcÅơà:T́ <Ö́fçÖB0ï1åC9~Jc̃‰øÂ|Ư<$79.&{©£$¨YÅP²¯èf’R©-dE0ï¹ø5‚ÜJ¦MÇúYщ`éX²ª₫gÖ¼Âù!ÙOzs<† 2HMÑÈÏ“#PÈŒ"Ư;<ÉÜ„]¯&dWQB;C˜ÏHĂIĂ®…¸Ñ¦yÍ, ̉]u«•;ư}cÓ­yÊ['¡Nºq‘x–ow|±‚ö˜bèÇ'Ë<•̀9\%;xb;j²€´ºB>r<-2̀jb÷lûE'å©ÖIBÉa?c˜ºlíaŸªÚ×dôÎ+Ów¥L [ƠƯ>̀äƒƯf<)Í̉_¡¾‡¡S9løeèCƒî#ÏĐÆ¯ ̣ï]°·ˆLc®®z‡ǽíHg/|…ÿPË?kS₫Đïl²Ï{¸Ü)Ư:£ẽv-÷¾=wµó¤pLRиå,–Iä́Æ@€éêVÚW’ÄÄùnËy±ÑÚ•æÜ=ư¹*Å3Bê85dƯ¡·«%¡ÏW–~½WL|RØS$]Ùh¦3ă‰;©ÆṬ GË „­qFë×½)c0y¸¼½«™i¼ AëOü×±́usNiñrë/´̃½ăü«ˆđi /ëL ¹¦%S‚¤Q`à¼vMöÓ˜åđ3ÆDÔĂ€QƒsÆ×ơZܬCbF—bO0dÍÅô˜ÓK Uư¥₫“zaváz4u¢ï̉â!l ë!KăOúÙN®fÂwàQB£Î³HlD{)£é4 ơRÆ\ôoR;ă¼·Éy:öô¤i_v))NQ¸ï§½_ÎáŸÊ¶+ơ¥Ün4j#uØœ!RyÀèYÔÏ¡Ÿ†Zqûbˆ#Ía¯’ùbhm#^{î‰ÖºJEôBJ7Eeר=/•©̀¥ˆæYá?Œ5wàw¥ëØqZ²B –Í ¤ü–->ª‘Aï\ÚođXzLwM Ά„táÔÍHÖ‚˜3°Ư‹ Ô…ø¼¢ü˜PyÓNg~iA¼¤b‚’ÓÈÑ3¯ÖĐá™ca&†ăDÂk¾‹`¼³ä9çÙăœ<&Bđ:äă߫۲z±ur»ÉP¹¥@₫’oàqÙ¶ct×ömT¡·¹/ɳ,¬4!¸úz’ mZí‹·ù‰ªø…o™ÙH7üĐâ­ß̉SƯY4gÛsötüM[Œ¹J¾}Ói@—â,ƒ! c*ê·ËmoË¥ñáóa–Èéôă1«ƒ:uß™—S¹p/¤iç°¨ùÆƯ¨­+\„âơ:?¯ oGQ}µKJºh~/%u9…5O"+Ă¯}‰ƒ_ˆ ăˆHèf4¦ü¦äu¡E±TXaâ‚`åTpüh…ưø¶©{ ×Ưz¶ _Éáƒa:é:Âu¸…,¡•f‚L”Đ—jK¨>±Ál/¸Á²­Z¸‰pr×ñÊÜ~Æ9!{¹jPº~î±ÊÛVæ$.îÀZî4]{Ư+hùé’+uéy¹_·wsA}î}宪Ǡ%÷%ϱ‘¡eë̉ù­㆕¢¤¹,²-R±4q•æ»ú¨U¼ßÓ+…âç¿fÉ£Gñôˆ‘•öă*‰ÈaGĐ,2ßZw{ ª }OÙ£d1ÍÛ¡ªƠ†mÙµ“½£̃¹LÏåĂÂâ"]UBs5̉È:NgkD&¥>£‡(R¹ÊúÜ܇0¼.°–4#ñ#AÆ›áªĂưª(ûÎ]©é~£L.¹øèO<ơẹ̈DH*®Wp€4mZ<Ôƒ âưÎ3RÚ®·wЧ̃ëuRæ<äS̃ÑAF]„úq#* 3¿6ÿxÓCyí¹²Í¯°KÈۼ襬°¼[FYÀè Œpe#ÜøtP±ÜÉë†a`±Ë™öĂ‚ö ½cÚÏAêT‚ÉÔÆÆÔ¶9ÅMa…FâÆˆø×b4 €Ô§øVîB¤¡ÖM…¥ÈÛ#ñÓ¿yJ!Ûù£w¤D='̉ï` o“}+&J»Bt³‘lñqyIäd‡„=d“Y’ÛU#ñ÷¸l f¨¨O#O&’’¨«œä]ßơ‡Ë}axx¨–ZÓ¬YØe­#i*Ü¡MÇÄ’0n}>nFª́²é–̣^*eľÍÜ/äCĤa¶9!Ê×utüPmŒ‰‡%]}ƈʿâs©‰X«Ç>Xâư»yloßûÚ¨(êm¹m²ÚơºioRW%ËwBă3©ëåɘY]èÊ ăÑÍỪÏ]ñ$ÁÆÚLÛ¥+ºïéf"ù £tưÎm₫µîÇNÑ6Âï3:Ơν»È)s_]8gítá'![h{=w‘îVYeÊø]/Ư£4(pkưc臦ÔM'"ܦnRQ~ăBQñ8?£ưÔN5 é]Q­>ƒ(‰u3”Îz2„Ö€mú@× ˜^צ»¸ƠA©Ơ„'eN§O¿Ơ*EUg7R]Mă[ÀC\hêP[GpÇ/)w\=lÎiO°×®àư‡Dơ’®:}€•rf&ÊŸ=Í;ŒÔ_É—…™-Œo ĸ¥Ÿ‡NÄ’H†̀tÎâ°nb[t$}!j2OCC÷AÚmF‡Ù66ª%˜Üϰ`ûâÀ/R‚uñsiOºĐ/kÛJT8몰†îxkÁѽ̃Ô’1üyÖB´È#‹t"±â&YŸÂ$Äl¿ù•Œ*sù°µG! î̀«Ç¶¡€4Ëñ°\çg{j¨–ÏTèß´ăÔ&Ss✼¹̣¤[´W^ÊüÎà¥Ç7O¬Û’n Đë“a®'ƒ]j³Æñ#pDo#ÜkµŸ[tüñ¹¨-™ñĐl:\ÿª‹Û₫SêiƠÜR÷a äw^éy=ôLTóú"Ï<:z9ÈèÑpGfÚ4Ümr¢Å̉7r,çH”~âıdơÛ¾9(;ïåëD›tùosđ;{P>¶÷Å«”RÍ]çVÁIhR±T‡Ă™Ø_qkyN×̀×Ạ–á­œ×s̃%₫’ëm/OvE ¥OẂÙ¸Ün$?çg†>ñ›Hû O]ñ¶Ü ¡@¨ÄW'í'Ä`2Ña’Ẹ̈°ÖF[øØ=2ûêÄWjÙ<9´O¼o×1C…$ï'¸:ꑺíêi¢Dq¡ Äå²»§LÖ3úô½¢ơÅ=,RS¯GÑ́àôDµ3íeƯ¼>nªÁmb•ÚàP±U ƒ¾‰ûóÍÓ¶¡â÷ÏGi³–¢"n²Z*ùu‡ÍÏŒé;v=8$ ~Ú >Î#fÚ̉Ü•µlp¦eXp:œ0̣̉…µ}g<ÓóLN8èèŸ9ÉíP&D“å®–1a“¶H±˜ư ă$äç!GWíƒt¿M ä»›z\µŸà“=…|×f±Mú>̉5@˜"¹ÙÎærƒ%ëf€È­8ÿ‹ÁûnịỊ̂k'Y½º¿́¦‚Fó7Ü vÏ &KxL¸̉¹*æºw¦•nN[\‘×5Û­^qñ„­GÊ»™ -¶èíS'Ù´ ÊÄ́HÅ×1!i‹×t'X‘Î(ÉÑ\©ï ÑèLmÓ ơl°›Æ¿„ö́ât¾#…ÍïóeÙÿ¡ƒ 7́~o³ĂB.Yé ƒD›Ø¨î沟tÙo¨%j[zh²GUynPƠÂÄd :„µp̃¢Íç`Ñk`«Cư\^ Q8plœo˜Í£I“%é.èwwoéÏÁv<º5û‹ZÍ•Z çußgô¢È•´Ï+N·‚RT)°hÆ ßI;₫„êzùUW Ê`5º0(—”R'‡*Y1Ú bÈe*²iêË5Ë̀pĂ<̃+‹gwØ"Ñ#ÇʳZ4¨J­]™9[¿p²ÂbVˆ¡]W/.ÚÍǘ₫¬`8L{†¤<µlR5hq%·§z%ë¬gs}á)Aêơ4¹îÑ·¬R®¬‹³£$ù×ỡ Vô 6fÓ%Å€h₫åñG~N÷”«E˜°Ôw;!¶ôÙ"˜|Jé!áP]R”\“ó̀\̉vkikt¿_{~·ơṾeZPø„¤‹vïo~ÉàFZ$ơ‰º½Mç3oăX¯×7Ăư| ×̉*¶"âîŸ%=Æ"¯U^rZ8, oÊÏlÛ90È ® ,BÑ1lRW ĐöQ­Wètˆ lM#Mlâ¦E½¸mùíPÄă5¯‹®>’ơ±J-Êû u€f‚&d¬[yådG6đ#:RÆïĐ:¹Sbf±̃8®¥đöó®‹í“üëj+Fá1µߦ½§‡¾:SJn‘–ˆ\Ÿ@O!½#Ûƒümʨ\Eđ°}uw̃®q=̀vê—BÓ0sÜ`( Áik£fZ(¿ ½̃“YלP?ăd³H¬55sTÚ!”gP 1ô1S©́µ³èü>ÿ«¥Öa¡’Q{a›zÅ*U°âÏ{¤§ó,Ø]@wQ_ÀnÓOÉÉÙÅk"£àÀ¯É-CV£ư¨‘£7ơhÛ[,TöéAqB¢ăAæsêéˆ ¬ñM×ϦrŸ3l¿…~2a(ZÈ-‰m *¾¹ ÅM“¶\w¢fƒ¾b1N—cùÄe:K¼x ÷ˆñˇ*Ÿ|6âeü×5(Ú 0—ÙP‰æç’ÅăÙgDÖŒ am1aVóIŒï~⬋ ¸ÚüyI§ôzÙî+Cå›×JLcrHƯB˜w¥́¶̃Ơ:ZAüA¸uqDâ‹1jP#îÆ6A˜¤8́aiAåëÙ³¬½-ƒvé‚ OGXî>Cå%?*Hí¶‡mâé¸ï÷JI]YƠñÖ†*¶Ÿ^º†mx»s…;A^í₫¤ä¾V[,¡|!?c wT'â%î6°\¯„U(JÊùÔ½ÜF_†ơ³"Ńs«A汋‹,i¶S¾ÓVÍÖ‹%cq€ O? ‚6BqLÀ§Ăd¢êœ‹2ÙƠV)‚Lºf't([™ú¨áJ?© ´jk°=¢¼¥²‘UU#}uFt¡ºx …oo­>©®÷ ¥ơ™+éÏ@P?¤DʺG~LÀÁ9߆½4·ú¾®Ö»º̃p¦-joÎŒ)~3ĂQ¤ó ÜRa(HZúĐ7Ô† D*•ˆéû¤(ơa…̣œæ;œ«f˱V§0p̀̀ï%ˆ¼—R[ÎF²:ñ®_Ú`“¿Î¨Ë2@¯z¢b~-@¬]Ç›£©øæ½¾`Êåñ#a£dƯĐeùƠuúC\hhZúèC»Îà³3Å:ë»Ä¢™đäçḉ̃fDú°^oz³®••Føû¹üNW%ú̀Z•×HVÈRRé±ß?I:lûT090cá.èN†béB)ر(cki‡~ÚÙ{¸¾*›|#W_KnƯƯÂr-*écLZaŸ)<.ÑSM/¥ §°öBó™q‘Ñêhí\­ô4ÄtŸñ»Ưªª3&‹¡wÍŸÚ…Êwfé߆+/34Đ=‹‹nä·G”đ’ÓËaE+¶†‹½¿)ц₫<—ü‚v¸Lç´\z‘^[ˆ7—Æ çJ½>Œ‚’đY½`§&ÀµÈa:ư6é=· Ă)r_ Τà¶6çØ-¢ơ ”+G|D&¶ÆX|ËØ¨…­Qƒï5_ÿ̀€÷quLœ5øñA4̉ßQj¨9đ@’ƠRé'÷üöQ)²c̣(zî»ùmă¬Â›íÀl®¨_Æ”ûH„dëZ*K"Æ|“'Q{à”NhqgNÚ+ë…-–~₫x2$_|́?lPY©Ô dU=†›Láç¬ƠHN:̃ºYâváP+ưÛªVÎñ 28p›IäZ̃çÀ߯ïĐ-¹j™Ü¶³uÈZNiß¼Çë/Q‘P‚œê¨[Ô½Ươ&z1êEĐFsÖ}¿ü#Å̃é´Ï«ÿº$s7<cÙ ôBÉ́²ä¸t1Ë–¨Eû2ƯB8Èô†­©NÑ}Oc̉I´ü¨Æ¹´â­N]Ú?YY„J̣HVjŒŸ¿C¥zΖ)±,J•UăñRäÇxư®4¯ÄŸʧåqề̃¼*7…vEÏ/htûy¹HÁó=h}ÿ½V î+ cz`D́q-örë§ùjŒ`0¢RÅïü¶bX[TĂMµ½Ơ)í*-«Áù NÔd`<À¶Q†ë+¬tù;« 0&Äñ¿] ,]6Ï”ÊW4]eüZ,•7«) ¤(gMœ ª`q¥1ÓU!ö¢@ç̉*›ÔÀ¿ßØ"¿” _3°09Ù‰¥?P¦¾6Eûnư²E•$a¿ÖuÓúkZơÛX¹#kÄÔP½úµ́a2Sù^çùAđ–Ç¢1Ư£²—$|2Oñ‹½’Nq^[b‚=ǺĐˆYu¦âد†¸µ2›@9¾–bM ôpZƠí̃ù\Ơå"t/„u1ÈÙÆkçbê3Ï&PóªT<4Ư–"ê­p¾̀ÔI,}è̃º2Úû;Tñà°¹æiç¾æ˜VÔo² ƠÓ»Ê,1Ø=&2F•j6‚käü0_Z=™(SÏJE`KĐ®ÉZmn9ÊTN‚Ḉs÷ÔØư>=H¨Û@öI>GùR‰Ï”z₫’ÈaÍE8!é`âfô ±­á®º4°Ó¶oÎi‚ªñïÁ·b½)ă½Ï̉Ä©¥ˆ—7³ùd*i¼æ¸$Y8„’ʹ̉0åztÚ¡÷1äqƯưmS¸ñ› ×'2ƒƒKwK¹öî±NđU¦ælp´Ú]Wa–ơºñO0¶3~yåÄ×W‡Éä¨Ûd—ˆ0Ú}₫¶÷צ D•ËíÓ09¯;¢ùÑôÆAÓ›ç €™Eh ÂúXÉ],¦~(_Ù`́‘±±®Æ×.E%æ ©ë*¼Ùæ|&̃¶Ï1̉éqÀ¹ NZ¿~™—°<ñ}•̀x**/6îj»„Á^=àóĐËfñuí}…;¹œ¿L¥V¶¢("Ájƒ„RÇZ%á Z0_@Ø&+W\6»À•teço Ç€ $Œ©ó9÷¶Y…Ư­́ÿØ`RhOÀ¤wë.)†X¯üˆ4l2&‹?b­Óz ¨nÉö˜.9>µB}íG…hÎ"é•iˆÁ2s41*JAªñÊ’À¤Öüä₫²‚PVÿr} }/ôm±"́¡B8́á~qXQ¤̀°í¶æ ÁÔëÙÓG–M©˜¹ư,öàë‰á8̀dư+Ÿ–™`V<¤È·byL7ơžC×8]dm¬|3ƒ;¹¸,‰§ă{Ⱥvj'̀„a¯æư™ê6½̃ñUXÚ̉ôñ9DC™ Y•_Éw™L›–hgä¾'-Z½Ç-f¬ïư&K̀Â:^Ø;‚!FO9ªË‘»£hƯ!¡$´ .îá?̃ßH˜ÀEô~Çḳ¿¦àvjăi âs¡DPơo '|l>±©¼M¢¥B°W¦6ç—R‹À4ÙÀ‰ó#äG~Æçj¦@w[ïj#ÿâ‡ëh !-øƒm´°.sơ&BVܼ.Ùx!àÑå}JàÀ€<æ'9­/}PÜ_ಠă)4—³ô»D¬̣&Ù5Xíßç0¨—6lV£0FÓß~’Hxeß!”UÍööAC¥[} ₫å¢9¶†ØÔ”;3§î\#*"§ÈâưÏÏ4œ×[̣è÷Ø.Uôå5y/Í0n+NÙw9™zK{5ÀÈ$áyºWú›—¤u6>Œ&ơåKăR¥ 7•ï‰6M_%5´Gé[s´ß†™ä:[₫7\¢RÈiäæL•*ΡQ!䈃½‚$H‰&£xNKçÀˆ0‚^” É‹Gû€Í̉Ù]±óó"ñtH™hYiwQÁÉ!£èC[Êí_3¼́)¡Zé̃ÚéÍÈÏña®Uk­0´W6:æé»6²!çÏg?ÑÅùs\p©îyY[́t‡#·4DØ̉|›Ç§É‡÷«ă<×hٔąÊe“2Ø_¿kÖE= O|YÎ'Ql8ÿEßâp„`e#§—ºÏ8±»NdËüè²ÍT:t?DC‹`.̉>å oçxämPÓ5^Ù‚™Y`¸ ‘#KŸ'ñá ba,UëJ—y€Ó!:ŒôGQF!c̃ÖŒ̉F‡oHÄ(U¥zÇûÅöHDùö́Ÿ\‚²sŒ’léŸÇ1k0¼í8KS¢å?¾+Ô~đNp`‰Î¥$g¬ỵë9–A?¢ºMÚj 2J˜ŸyƒhQT|y.VVŤt_ál #L]Đh > ¤† _äEÿN%-|ửª“ä«!½ü=…—H÷t‘ è)l>$>p|éºÅ“ÆcÓM"Qÿ'ñ™SiÔ`×ù7| ́ezF•C Œëº{uv ¼©].›Iº½Ơ.YÔ:…¸Ăw̃°Xø`Xơ E›UdW³”¦½³hÇÎdůºm„øÇ!Ñ‚ÓnU³"Æ6œ‰ËåGÛ]³ºC;½í´ g&8.rïx¯óƯóh?ñ ‘º̣BŒÖy7`ë§qøa·â¥º÷>=Í@b󙢳c±-nCßô {+civOm̀-ĂM½öd ÜÜèxr²°k?D¬¾¹äpÈ8Ï™Ă®ôf÷4œJÿ+z¿‚tyÚ$ä—MŸ5ri,åÁÙ²BCk¿TP÷G¾U*0ù™{­ â*Ÿä· ÛJégL¨46‰»&Ơ3®Ñ]t³ơ§ü¬Œ26̀±¹¤Àbÿ~lËÎG o+YxætJokC/È“OI›ºÆ ær ‹̀Ï…>Æ̃͹2B’<6baûq5|+È֗Ɖø”–́4¬w½¤˜ œg•´3ô˜† ¼’¢• ¥! ¥E>²¾dB{:?Ô° Wÿ¯w²áĂ¾›¢ßyµÆ_ï¹yGLĐ´¤̃«zl3•Ù|ÛÇïb72e"12đ&9çøæ«Á³'¹ó†;n=Çlz¤+½|\Œ®èºÅ%÷$fÄ`k‚±ª‹éëóÔÀ«äºH çw¶´Œ‚3®‰}¦·wÜyf£Ÿ¶—Hi–PĤËÑøønœ×-Æ×ªw )O–am̀:iF[jaÇ6«è¶:®³ö̉—¹œm<ÿábdu͇2Ë&Kˬ#x:έ‘søjetßñª;)Ơ©©íÛÀªÜ³ß×wcêë)–‰ô|ÇđKÄ·SËbæ̉‰cëe:·Å·ƯË‚e ơ7+¶ư|ôà\ ¸•Ê_Dơ®¼]̉3ă“ªL+ÏoxBw'”ọ̈³¿1‡.gü¤–Mî ×r¸f€©+´ÍÜ–ÊâU˜ƠTV¸ íWÎgïnjx™r“u¬¢ø‡̣.fÏÊ³Đ¼ºUëb ¥v„]“ÅË*-I©Å¹¶\³er¿I—6Ñ·y’͵ÉZđxV]`C‚#ÀYßÁO>‚-%Dá ]SÅ™&±FQ‹m—–“Ú•èë|iÈÈY»gÖƒ©äîư•œóÈAÖZ¡®z4‡Ü Ë/¤¿~ôÛZˆ³:-ÔQLªêQR_¯r>¦w÷éƠG†¹»-̣°çs/OÄÚôÚ¥@s ¥ÉT¶“ßDs„÷Đ,×”Ld*Í<¸âÛW]V´„½ö0x79V*f5›=¡¯î§Ë˜qqÍĂèB{̀ÜJ=ЉçRD¤ö¤(êô-^(‹î<¿•™×ôÓ¸N,'T6Á‚7–Y&rœ,cSzB‰Áø€rˆ=V-³P¡£ù.å uZṛ[O¶A¾KKú=?ñ½0.LơrÀDEV5<[>ü‰ Rä#¥I~w§Óe_‚…¤Ơy`Ö½ïJ.´nûrùÆ̣$•§_÷{I ‘Rbª₫ù¿Ü±ä³ÀÛEFhïgÈä'*Ö¥üñ¤]ó¸ ́©M̉đÂ5od}ËåΆ̣Ë;µ»\ƠË.7!"uP'F׳ ‚Åy~ Æj„Sœ6[É4ú¥̃ø»ÅB1|ûm·¾r¦¦s—Ƒᣔ^=ûhI``\ª ½%À¨ü¹ Å̀Z`‹Ư1*c5Y©L–Ó É½åËçOZ6 §Ja[Ú0(q@&Ơs¿CoøÄ̃V“o…2|`zÄĂ:́ĂQ´j_ŒÎ Jßêϼ§0|¾kŒI¯ªRfv́×$ ™ØXKP¯HzîèÊứ|cv/.]¯¼ €“Âèôu27W1åæcùREQ”4vÿûºD₫"ƾŒRª˜P$LY¯r6~ÁƒÜ­lo;âVr¥Å&œ«\½;­º æN¬̀&‚ i½w=†%tö¨¿7¯_Æơ—3^́¶ßÉ^/\Ú245¨„I| ·ÅÿPi´¨‹ĐGŸ:Ë£Y¢GRxSÅS#÷µÔ!µÛÅ/ŸœîĐlPöe„;Ñ*NøKñOùIư Q9¿T5ôXXL½H5¾ù°³`jí'Yă;̀îµCn²n ÚÁĐåÁ‹ ê§Ø˜ûîͽö+ÍÁÛ VAWDZ²“ç½ÆByw‚”v VàéÉ…ß»êüoO)áV•ü‡jƠϺÚyHQ¯Y®,{œä˜ êi=sm ˆpÂgơ’ăÚÛmM1Ç×A Ơjÿ² ñ° „ØăÚE³¡f?ö‰o‘TÇ%àf\1Ä X§ºÓ;d̃RëƯ)́ŒHebÛ̃Z¿1̃s0EeËâ%•§/ÉôưǛ’túÅE‹²ñêÜ ó/PVØ1€¢&̣ û|É¢±ªÛu¢o´ÇĨ₫_yμÄí [lú_ &—h ¦ƒ»¸gkSJØM³\[ÑÅ"±²·!-äH==W•Ù\ï#LX.½eá‘ü–Rƒ–xM–ɬ0;C~N¼c\$ƒ©ƒÉ9€qå~|ú̃˜•₫pIo¦>7&Ü–ÔŒŒ> l¶»R1Z&o.<¥OWÏIC]4Ô‘öÑ.¾·ó¤hØZ1§–ïßÑ’+Đ.øc>…mJ5QW‚îèÀHÑ·¼u/‹ßZŒrºÚ¨9›â%0Ï“J½jiŸ@§…̉BL*…Pª¤sSóG.RÂj̀}t©£é¦ ,ŸƯLƒh2³QÈ!4:Ô¤¯f[ä9 óט»”-#EULêH9ê·§ô[ûÀêX+-g–¸o•Úó†Ù'q¿ˆ‡I…û´ŸQâqùOú¿º}J* ¢ ™ụ̂!²}§½§˜u{“»*}.xlÅ2¶ó:ô{Ÿç¥Ïa`]ÛÜ&íÙc§̣ă>Ưôñ=6(*Ù„{Dæ—J›6„$àµ0T[·Woiè½F(•›r¡«»¤¯ÍrñÏpFĐÖñé¦/<ÅÙàúá/Lù.©ÂÜ2ûí>1¡2}‰́À¼ưc:Íö*„ƒ̃"Y ªà1ø¤Ø¢¦F²dŒ!ñ¶-½O‘ÜÑ rÄÁ'V]ÅÀÑs#°ó-\ÙÀ̉,>̉ÎLŒ%ú€˜äèPظøVrj·˜¦EtâÓÈ\N8k-ʘö“đÈOx̀bÔ%;̀¬J®s÷dE™˜É4c6mŒ¿fhn*b_”ĂhtƠÊ«BASû{ôcßF©31̃x¸´#—₫a>˜YE!Ÿ̀Óó ¨Jl j’Öá©ᡇXú¡41’˜®>Ff(;½<(,øĐ3ë‚ä'ôJ·éô«M-aÈdh X\è)GçàƠ‘\GÔÄBÈ(RFe Vg}¦µ«x ùW`™é#t°ư¿cóÚB¯p–½̉““p“*ÖÄzđưØÜ¹‰+¼s|' <ÛÀî7ùÅïy£¢Ù9Ö9ÔơŒíÈñ‘íð J̃öD_₫å„Z¶SQ₫0±Í4Ön̉o–Ô¬-vM®̀;¸«ö ‡ÂêWé-X©>[îcAF -DjÎé’<Đ́@<ÄiÑ#n/s’ΑÓwêà!e M ̃ÀNÆ"OÚÉæÔ‹1æÓOt,f£àÅöê`đ¶)«Q#²Á„ I%6pçT!o©SÍÈ cñĐÆtYÀo>hc?¡RÓbÓc&₫ÅÄMútÈ .*# ºÎ07P ‰?yX”)¿«á£Ôkßö…åj?ˆ&#F#Âw© /;ü»jăW̃àç4->¾!Ç<ñsPc7kW¥½¾„đWå6ï8µh -"”Ø!ÅvüEÄ¥AhÄgú5*VJ›fw6œ~# ‘ è«»ïMßzʼâúBxø ÷d*WØÍƠÄ"Œf«,)Bø&^C¸GÛU,Ề2L2΄¢:äh?+¿—úÚg…&,ơ XI¬ív"x›çÆ+#b{ļ́¬JŸû‚/9ÛÎ^Ød:bó&9I—m»hèDÚ{¨~&_iøNhÉd… »—§Âop¢ˆîË >°$00£óÑô°©ët€àE*€G®ÙYuMăöÄMư;9² Ï©÷¾Øṇ̃¦Í/ùf©´G 9ä «Ă•Ê„fæZlú³ 1©•¨ZBô°ˆx´s!¯-kG1;VÁ²[j…|T¿¬ `đ¦–(npÓ(MH:ÛzögÂpd›rĐY„H|́åC°)bÇ3—¼€‹­*½îæí`Mï(îùî ˆê!> Oz6`(χÀGŸPÊzÍ,_₫¤Đ§÷;B\6Ôđ¿mưüZhyÍľ[\Ä‘l€²\܈ö-6o¶¯Fî#í₫å0/A¸G² †q™̀¼ẹlă ÈåtÛU”6¶đïÜƠ)å4—Ø'mH>§9\SPtË b̃øÏÔă¤Ưå̃₫b ₫ ¾ư€t­€QJl_P{U…Đ4± qb+¦rÉ[ùq-Ă¹Ç!LeS ¹g»ªæLî=Ó]dû®ĂPf¾ÑÖ, ?<0y ­7"9> .Ăë¡.íd̃'¸ñé¡‹@Í üÙ”ùqG­ê^Íá5yûA,pwĂ8mŒèÛñư—ÇO Pże§™₫Vv£úîªj*èÜĂôZ6¯$<Ë™d³IÖû½¨ƒÑæ<] Ʀí@BpC!mǜ»=}¡©g™^ÊøCÑZX_¨Äææ0=^^ơ‘¡»³‹‚ÏÀÑ¢µ‘ˆú>«Øê0 ̉¢¯‹íZk.;´G×6…cf̣„°ÆÖܱ­t{Ú³êq-bª–W°?_'ç(­ öFƒĐ[-²eÓvÊoø&†FÊÙÈw?¬wR¸¡†Óñ1Ø9JˆcÂ5PÀŸ,ṣ_ưnđyxWè"u¡Ú(®!Es€:íl$œ˜è=£Çº=Ăv¢6¸ăNÛ­°Ơej^Á(7Ö_‡Ô•jFÏ¥ÎtΡ7sSW"„ăb(覃´a—ML¯Éü[è§TGfœÙ!ư©¶Së / o’´æˆS¢ûKî&¹m…w¬™º-ªbb3T;káÉÎTPdæ»Åvê`9/Ç­º­RÏ$¿Á”q‘´&6åư«Ë]dCx àœ6Räơx¢u˜¦}î\s₫ûÀÜ0AJîïjU×TmÏAß«ÇKˆ2ú̃¼¬¶ëÚtœ=*@á:NsF=á@Ëh˜á́æ¨̉¾ÿ(¯ ¤Ó×ÈE'5ߢ0©™•xL• Æ8ñs‚Îu½, Ê¿ÿÎ0™â Rjd–XIí Ạ.åmrÊæ>û2ç[öƯ?H$ƒYNl¾_´ö¦»ï§^̀fC°¦îÀ\QqÁ4½?¥é>Ơ Ú(¸âB‡M2Rr¡µÄÿlYň÷è…Gé;$UØN’)IHñ¶?Ư´™‰;P;zµôàÙHSaq˜4êF³„bd™}ú½EkGÙơÔqÀÍù†ƒæ#Øiƒ/¨1ƠÂx¦–­ZD2Ùzw Ñ…Wó:f¬Ư;Æ®£¯“Ư³ùPËM8 ¤Î/J™å`Ú„ ~>Œë³Zƒé̃K°Ót¦»:“gÀ^p' I r³ {w°¦rưVÇè÷†B¾yBÛ»:§®i³ÚÓ¸ÿ?o ơÏ"s‘€Û;s{×e4uYœĂrQG'΄âH¹‹j1È1<¶+Ô¡ÓGđ«˜Øh”f¯J)†µ{osR‘zĂ,D¡2'9ÿÔ4 M‚½ócÄ,ûÆRhË‚HH$‡±”ÙƯ A˜æØúNÆï̉í ±e.x/+˜₫̀Ơ¾.É:ưƯ \›áM|•B]'Ù¦̃G$̀x¯³4Y986 ‘Æ}S̉ăVÇS(¯û ¶C‡5Œ:ªˆÑBLà±ô „j~r# •ÅáûS´ÔK˜ëlâ·ƒäZß̉ ¦+LQ:I@Am³—úC6l!½e(ÙåLÈ’5'pP®5ưgnïF^̀w¼Î¦Ưß–Œ/ &Ưe¼c!Kb˜‡tˆ_÷@‹²÷RÜ^ÑƠOѰ₫N‰f‡ŸG¶Yæô%Ë0›́ƠŒQ«È¢đƠ¼GC›|F÷G~éô]=¬«ép;HRê| RáĂÊfW©>¶´(™v\:x^R $6üÖ4ê´„S±ăh¬ Ô`·¢;Ă¯3ääá¼Â„îGÀ…ƠV0 xß-.Mîß(}{Ê<÷ßư«=Pê¿’I¶̃ïàíJù ¢u ¡‘q­»đß3KöS«Ten)ûÎÇTÛ2ÈưÚ†>p°G̣å~è¥h3“@ø-₫çmVÇ+Ăèßa!ĂVœ]È¿8£fwôY IuØ™Ädˆt® ă€Ù]~§—ùö8K¶;8Ú‘*l¿Ư—Dx†₫$NẢJ¶Ào±RV³ đb?çÑÍËT-ç9Bº]"æXĐ=n;̃%é6sS­|WÈŸa³¬ư”5¡O ư¿‰C(—~đ[ѺóNSuA¡¤Å½DAæ—g ·©`Y“ ~}›ØŒçzŒ³¸“Yf̀²ñs w²r¾ ¨P_øb4p$º@“µG¥MÖL¿©´zàzgÙJ‡¿^2•€0ü;ASŸlµOcWg 1, “S†ÇºD̃×#%14îù‹QƯ/[#@×5]rD<ˬEçr[VîÄb1«—Ơû¸ãü h¨̃L›—WZư™¼f?—˜œ qñ̃’|i€£ûj¸ÜưÎơ< (ä1©ü°4Aªv'T$ëơ ̣î—áÆµ—m£ăγ(x§₫̀ØH,‘2‚FèG0æ…nÑú~öăüïüñ7¾·lAt¼>åĂ+Jsz’Ïụ́¶ệçFn*Ă¥´Í-G ú( ü/³'©uĐeU¶æA¹GĂ‚C°¨úƒiFÓ_h*Áÿu{c8w‘T̃t qWßëzĂmTđ Wuôµy›Óªs¤‡QàÍîqn+ ±æ:Đúoô2Fˆë?‚¥Y€¹"[ª*:¦Ê~pÑ :î-]-²p…±YèÇíI±úJ‹8(r€Jpz˜·´ÑAƯH”ô˜Ú~¶m_œ¢es\L’;pñÅNûfßjX_-lÈGä¨ûNÄu¿Nmƒi™²a(³_/p!t«›/̀Ú?# îÂ'ÉPñ†EÁhêZ₫’¤s$²ÀL¨­4]kÄ]îrk O-8Iñsu°Ya×ʹ~jÓ¥0I°>̃Dü-n™“¼î9«ˆñ{³\Å/9"¬÷€$'îGN|æ¯\˜à.ô° 8F)p¾ºdu8µ÷%æ ü/°¡=Ûèơ7H ÑÈ·́¤TwnñóâáƠ‘+¾G ?@bhJ§¥“*;N7[,'îÁy’ÅT8‘+fÈ!Àѧ'KØ·¥đçj̣æ¨ƠqZn‰ªÇíĐ`¸^ccẸ̈Qze:×"ÑCÁѤp=³Û&ÛªL~¯đĐ·`&x†[#,/(¤|¾:ª̀́÷B/™ǸhơFP#÷|÷ù½¼¼ORĂ!ớNSX™Ñ¢QÈl>ÜœZO¤§÷B#º<ˆ.yƠ>nó)W-Gx‚Í+>á­ÏÄáñ6â¶J!3•.è¨æReV\½Em̃Ú‚15n’"ù‡ m€÷ß°û.R½c¦;̃è́#’#ØĐ(̀3±9ñ4åP̀V鬱Àq;u>EëZ’ø bï!KÆ”„d¼ªZQ‰ué‹©…³öFÅæC¥ªx¨i¯öó½‘lré·2œ2Wló —fÜA×­÷-· FÚ½‹Ă$èxU´îøôV̉SU7©(`È₫[dlÁdVÉĂGJE²b(jgNŸÆỌ̈r5ª×—Ójhÿ;åä9$aómyäô¹Ó5‡<éz>L0¯¾ y³g R¡Ư,¥O£›ó¢Äêɨ!}Ăb¶À·©Sè¯,¨dDáøé¬Ơ7"²̣D¬@S­FÑ_Úc…‹đ¤ “ÖELL×?•ơ–3Á[›ZM¼Î>7sz¬>¯YvKjµXŒa•3_E'¤OƠûb¾·Î•ÿ1sHW]ôƒí&‡–Ül/èĐ‘Ÿw<3¦3bạ̊Ù…ˆ¤Eo8“‹É2mˆ~¢^ 溛& ß5ÀÙ?ml|5Uh́4ƠÖÅ‘§º†E?ÿeCŸÙ}Ù@A†úøÚlÿæŒĂ,„̣¬¥èá>Ec Q¤̣6ÇF,`_¼áa–&H7Ê:_—« .«OêƒÛ{n*·ùBŸr(‡đͬ6ư™%È’1hÚÑhü¡G©˜B×o<ƒ̀ù6¢ç΢^ o£x T±ưó†\¾ç2±{ÔÉÙyM#'•H„4₫©-Ak§¶ê‰Tå]¾%„a¨?<ƒ¦Â]xÊ}/…?Bá‚,kƠ¹kû;;¦¤ÚxåÂøÄM ­ß»ă­i“Ûà…O8˜ùÚ] Ô €aÙŒ%*i7·£¨o…Óó‡®WD„Ójy¼ÖgBP„œàÑ,é'å6½IcÆ”ạ̈å”p| ^£­à~˜nëËñ¦g(§0ê›°á«ßR½fÀ́nßü߯:ƒŒ#ØKÿ`Zœ•¶đđ»7˜Nz‹ Næµx½̉Ù4LN$8Ö{µË—ˆ1&ÉX‡ÔZuÔÓ«ƯeÉ´%x̀•˜N¦ÿ¿×ª·t0oG}¯×4£‹ƯöN ü©±|–c÷tđD ë´—38j‘¢V\ß[§¡ỵ̈s‘Ë%HgÁ.[GXv endstream endobj 1349 0 obj << /Length1 2697 /Length2 23728 /Length3 0 /Length 25240 /Filter /FlateDecode >> stream xÚŒ¶P\ ´- Á-¸[ăî.ÁƯ .Áw—à$hpww‚»4¸»;$¸¼Î̀ÜIæ₫_ơ^QƠôÚº¶Ó$J* Â&vF@ ;[gFf^€¨ü{f33#33+<…ª…³5đ1<…:ĐÑÉÂΖ÷QG ¡3H&fè ²“·³ȸXXØ,œ¼,\¼̀̀Vffÿ1´s䈺Z˜ä2v¶@'x Q;{G 3sgPÿù  6¦°đđpÑÿå¶:ZÚä Í6 ŒÆ†Ö;c  ³ÇBPó›;;Ûó21¹¹¹1Ú81Ú9 ĐĐÜ,œÍïN@GW  àWÁCàß•1ÂSTÍ-œ₫–«Ø™:»: µ…1ĐÖ äábkt€’T¤åö@Û¿å₫6 üÓ #Ë¿á₫ñ₫ÈÂö/gCcc;{C[ [3€©…5 (!Çè́îL0´5ùehhíḍ7t5´°64üÅÜ !¬ 0øOyNÆöÎNŒNÖ¿JdúÔeq[Q; ­³ü/~b@cPÛ=˜₫¬•­›­×?ÀÔÂÖÄôW&.öLj¶.@i±L@"øß23 3€ƒ™™™‹‡ tƯÍ™~…Wơ°₫¥dù%Uàíeog0ô¶0‚₫Á{9ºÎ.@o¯?ÿEđ,, cg€Đ̀Â₫wthú7 ßÑ à Ú=󯿿}­—‰­µÇoó¿æË$¯,,§ M÷wÅÿêDD́Ü^ ́̀Vf˯%ă}ñ₫o%C‹hüá+mkjàù›-¨MÿĂØơŸ ₫ç8hÿ¥`ÚZ €ú÷’ë2s0ƒ>X₫ŸWư/—ÿ¿ ÿåÿ¶äÿ›„‹µơ_jê¿ôÿµ¡…µÇ? ¥uq€¼è lÿ·©đX¸Øüo­´³!è„mͬÿm£…“„…;ĐDÉÂÙØüïmù[®öëʬ-lJvN¿+Đh₫—tZÆV G‡h%ÿRA—óß”â¶Æv&¿NŒ•ƒ`èèhè2q¼X@·htÿk‰LŒ¶vÎ ¨‰b+đ̉̃`ư|?ë¹Z®ÊêÔ…K«Cñmt̉Kä Q{̃«¸`e`Á½™¿€8 ‰>i……ñ€5­Êâ}„mcoëèbËNö@₫úN|MI#†¾#©"fU«~ºs ›đ ĂTdµíF½ÛÔ2‰`‰ç{Ư+`IËüد©Ûë±̃auxd€á6$©ån¸qd»Û[£H°_À̀…VÜ\'|e™70 ªÔýM—P…~Éơ ÷”a0¿WÀ¥ÈËV>3³67T/ø(ÁGöÇËÏ̃  3¨óÖnh_9^:“..̣qÍÙÄ ̉C¨s̉Ä»?å¬ES)óƠfK™.6*°ÅJ<ˆåâ¶8.É Ø¥%{wç+‡Ău<,ïỵÏÔ+ÔZc8̣”IvN"Æü‡DƒûxnL¶nÊÊDô0íÔï/*ÜÂD†?oªrå|êxï—Ơ夘")ñ¦đv{¶Έ́TUĕĦ1YCơƯĂöXWá“}©´UÁ¢|¿́!èÇÅ b½¸Ơ~BXŸ~6ú±Ö¶+̃Qƒ!¦£¬~¦Hß[† ÓonT¿|ÁÁWQ½Ë%óÜëÿ>¶Ṃmj›Ü˺B·ˆ½¯ ÀÇ™aKI2¿í—z½₫:2üÅ4¼iMÍM¸~‰ &mf¸~24 )BÓÎÆŒ!0~"È/¡J_“+ Ăx‹Ï´Ụ̈̀z nzWé¤[»†ñ“?¸́n—8ùº˜`˜ÚÜä̃ç—¬ïî’9ʶƒeø©á¸;Us ™$óSđr¬`Ø5:™©¨?¶ |iH"Mƒ5`P#`Á¶ùg©0†j£/ߣ+±‰ç1đÖ R¡n¼L ¿•A®b„Ź«•“q.£́ơâ‚á¬'óWŸ́́:“Å¿`*y+1oæF*Á‘ív©F₫±êƠßN™|< aÊÀç+ sÉGØ”W₫ÖC›óúÆû…ôµaó‹µ́ ơC?؆†êê4Áa\Ák®Äc,ưÑl(/×ÜîJǘ,³„×ïœ'î¤À–‘ø8S›¼e]XÙSƠDÁ ,R±ê¥œ+j§¦½oÜG©?.Q`§Ỗ·5…èK^ÓN:ÅÆÖv«Ä3Ïs¢åÄ Ne°]A„t⸤qÏ«Pp2ä4ưs0¡‘XÚ41]Pc5˜’•Ư ­ÄÚa|†Uă½Öm5xàD‘Çè5o—T±0 }dL£—VíĂ*S¡Gi¤r \Øp‚®̣—| Ú̉ U¬Ë¨=À‰~¼A`~ˆ …jB‹,Wt,Ưû”¹Ç‚´§!­Ÿưè§Z@ï¶Ä‚ˆÛ­P¥‡đăàjâ¹'×/‘Ó²]³ÈR‘Tµ àÚÊBăÈ̉‹Îy;¯‰é]:Å4\}”OÙæă¶ˆ5¸‡ZT3ˆ=_U{/©4}gÖS˜lơm¿@ÈÈå`!ÀR' Á×îg›L…¯hP ô’•hX_¾Đ³J3Zë±=̣Á:5«Êû»l˜¯–̃Üïơ†æºu.·¾̉²—Ëÿƒ%™ÜƯÑFøờé FÏÀơ•­ö:mJë»’Û§ŸviFB^±s°$¢¢Ä^ØÆ°Œ¾Ú_OΉö˜±m6Œ́ƒÍœ”’MȦtoªÆg̉(åøí;!Ñ­Ñ?6û¤Ơs<0÷%~¥3ôô(v $̃Ô¯ñ¬ Í ùÁ*è:Ó ưæèºíç|h¯&¸a 7îl¾ |âr(™Û" <́×®œ–‡ÊŸËà¬7)÷Öv"s‡åñpĉ®$̀÷á ˆ«ëg%âë†:a¦wJî́~RÁÙ˜`4êù–%‰æ0P´ĐIÙD~p,^?íƯmJé’N—é@ß±$§œs(Üñ”Ú °rÉ´<_781Aœ…5£₫Qâ©LÿÖY@§r‹{,^̉©¿ÉŸ—ø=9ÏN ʰJ‹Üp×áCËâ¹¾÷"z„ïE ­;Ưëô³çµ2xk9䋪 ×÷Ζ1ÎĂaĐ?·V 7àû?2Yæoô/æx¯$œ‹Qjø •î̀)k6“CK­í#:KçW´ÁùÍ2.j\ -Øb–9&¢èÿ8±]ñïEêP|ÚvV€bC²MŒH„̉_ẲÓ^6ĂˆkđÉĈæ‹2 ª<-– ]»àö}í^!®m‚H8°îT¶ Á+Ëơ¦é ùqßPpÅÅ£‚K…¨×ü“wÇR¦ÆRèĂ½¬.PœYr„o¼sYÙáÍç’Á+Uªæ‹L¾L₫|Û…gk9Q–xÍ>Ç^¼Ć|ŸĂ÷ÁˆIOQº.‚<%–^"àđÖ1¶2™Dù¥‘ /ÖÔ—Ó ä°D-Àaå]&{Y.pg`øG̃å…5Ăp©Ä íæé*v—(5ïÎ₫¾ữÅĐj€)’o‰Z_NÀîIfÀ¥ag´v‹§³pe)Œ Ä«NˆÓ̃‰,JÀ÷Sf¹]O· ¿ƠQ‘3/ƠbØ đQq|ñ0äÈ+iI–̀Ṇñ@F|€,™ÂÖĂâđ‹[]Ÿ¢Æƒ¿K@Èè l“² ÍEÙvÂtÄ p_I„ßćXœ«ªÊ™°Jª\²îă£L¬"ăß_J­¾ÆĐ˜NíHx¦46 ænKƒ ©HQ&̣¿BµÅA]mÁ¸Ñư3$t·ƠkJÙú¯ +„I<<Ú¶y/§é02ỊÜ/ Œ&ä_æ>m2™z³­'¦+Ü&•,ID­Ø§2•w‚™!ÖÔP{ö~ºihl̉êkˆ̉Cđ›™§°$‘ê8P”z…ûL¬ÿ5‚ï ´vüÊ7vK¦É5çm­ÿ‡2x̣E˜Räe*QsA₫ œgÂÖÓoƠƯ—Bñ8p©†åơ~ )¾Æá!‡ÖvàợÔWÑĐ`EdËó“¶Z^–Ël­ß¸V´PI[g?ûnỐÖ?åüœVê9ñJÈ…¯J>7nox ‡à¿`~¬haÑx–¶m÷€XÁíâ±Bîx•¸zưÅ̃ÔÛØ¡—£ÛÇäyơĂlÆ₫]×É[5ú đçl= ^©«́Åà¾eêJ} ¢ÿ!¡„zÇ‹Ă$4–@¹ËÁFƒ$oØæeŸg`fp”¶.E´Ú©ëB̉¤ç¶ÎÆ7‘( ?Ơ­¦¯lïp*57Ûl0dâî°¦Ù‚n -¶ç¥„VbüM'Ÿ­̃3§ư|v¥̣´aD£SÙîk]´öx"ÆáÇÊEÔú9'ZWÑosØ ÷µJ̉…C_2 æ®a‘¥đÙ™)ráe#jtë~ƒưS K…m˜₫£˜€·=4Ưi©99áCq?ø¡sù{ƒ½ïÍ’²7|eĐùnƒÇ­;̉çÂÅl¦ÂëZ¨.å~=«;½WíSç'ßÑ´Q Å~̃đFG-™Á¼/€XÄ ;£"3”ÆĐcĐlµ–æ·˜oMđè̀¹¼Âª́ăđÈÆá¡ö©Ê–j’︙ ÇU ÔÙzăï0˜ç)MøÚf‰Â!WT*ƯeÜàưÑœ¨‹<ÖSl ]m¢'Æ­U+®ư¹\›wü|¿o"¿?¥óªÁÚwØ…?nàr'ôï#dù 1æÜJØA}ê€̃'₫S¦ÇÔ£áEZáR¸NƠx8Á÷Qñ̀¼7¼n¨C"|ÄÏ=‹+9Ă l4oË‘êưa¡Ç¼đ]ï~_wä½s¯P0)»¶¡NŸ“™mißz½­²Ô.ñ¼ø2‚!Đ´Ï}JlÏ 7E9”÷q.k 0¨/¦è1H̀=[ív*lqưÖ: §ûô‰6sîYyd³XÁÈ4˜n¹­c-(Ó.j±H ®ÍsêÚ́Èl̀pçsŒK½DöT /ºæƒÇjSiùä›Ú¶7Cf7¯́‚¬zbØ‹¥RÇrÓæ¯Rơº'ä€vµéÉj§×>ˆ·qq“\'4ù×)R¶1™oZ+„¹H½ÄB̃ó3±:?Ë÷₫¸wÚ-ô{´â‘ÖügW’>±ơ:ñüH‡¾X¨)~R”ˆ2Äx´Ỉ5ÙKJ+³¬Âơ¶kI‹¨ –àêÜr‰̣û¢đ "]Ù^Xgs+,ÚÚ»Ÿ‰ 9»äœ®µ*xªZ¨ŸÈ–q*å’^ÙÇ‹ÎöÓÀ&¨nNn{ï}%°MÔ%åæèéö±œ0Ë%_̣7ô˜Jê{!‡oÀÍ#û‘Ëï﵉Ê=ƒÄJœ…Ùnh©iỴ B–4üæ;̣ma¯ó¹Ă¯>›ÀSu1™ÙI--È̃SE¢áCتCÂC¦8Ïo’ó┼ù ÂI§Ûdo¦ÉÆcU³ßJÜ>èîă=ßêÍÄCâA đ¥Àu}}yÑÚä0ˆÆ–đÑOsï „PËüA¥×0$)„¬6‡Â) Kœ´¿r#đÄ;¬®ÿøfX`¶‡VÙkºA—ÔköœMmÉsàrØeG"Ưbt1?ø§̉zñxL7rÀ“ZAúƒMå…zø7L‡̃ K²‚æª̀0s‡A„‚ô6';$†f¡8xYI®èm̉Ê“¡oöJvÚWNƒ¼óúäfëUĐĂ xưLKgmÚz„ÙΣç.TXû̃áÆÎéÔ™4.Ä?ɤë®ÔaU\aŸ,áø=Ư#„₫æÜaÉ25&¼ïøYÙ5Uù‚;*ăÚC/Küîª>xâ‹úZLL:|̣SrP½ÎÊ¿Z·&/dÀ̉² 1Ư ÅF Ü©Bëˆ OÈ]`wxTi&iï\_zÙêaÛêQ‰F?,ô2u--9 ̉ ºüî€3<2~;XCı¢W˳€¿ „Û1‰OØDZ߀)̀ßÁÎé©ûÍú yô9<]–v̀_–w~U£@eW)b¬R¸T’*°«oå»ṇû¨ø9뤔W7vÑ©ÖÆ0C­Ä0¸|́ü‡Ô!‘O[Yäh`.Y)ø•›÷¶|ö ̀ơ6‰¶GOª}óÉ–½L íƯ¦‚Á,,ˆí`yăÇÔ¼l=¿ysª|¸~§¤¿}åÿ©AЦ¬j¯\ đ^§(üVÑ.ÿYC‘³”Ñd`³Oˆd>é@X¯{_¡rE´‘Âyet.¸• jO…®I£I§ =€tŒh5.%Bf4Í Ó#y Î÷¹”h(R!é»Df×»»{ó~±pÑF)6eÛ­]øQ¿úÑ·æ:X¢”Hp_û³À,²>¾¼\ë×?‘±3DU†mU…m•ΉD韥˴Æû‹&F’HYç^œ5̀NƯ O/ơB'âG¨n Y6å3X+G*qktB ºF6&¿Ñ®£moo(dMª>C¯ØỢ@Nágh·¾ü _Ôh tC¥hôŒm[{+ÓøÓ£CH6×–ƒ¾3#›rÅs ;Ú’…t{sU2¶³*"bá%pܬÇC†ø é‹êDFçhb¦®ḲÜ<*Æ”á&k¾ß›FpïA· Ä©"¤ÔØ´ÑG¬́%Æ·7ƒŕä—¬Ë5ĐeÇnü [Å\4oËËô{™³1¤'¯Ï´[­M›“«V9:Î7tNÏ|Ôß!´Q®àGç½`lƠ²©§½bÎi½‰Øvßă1>är_ư²=ß÷ˆCYG¬đÎ́k¶G¶÷ÚSέØ^<4ÛÙ½ZöOïƒó𴦦³Q o"Ú-̣8içr̀D;Ơ_-¹Y g‘{$+†uªcqÖ•QƠó[Tø>u\‚\+²­€l€[àXgØ®‹‰“u¡› Ö"¿HBÛˆÔ„‹Ñ́\zk₫–ÁF‰va~Dôn<0ØM1²â*D â²°ÜÚ'†í(é–cz¦)Ê´O²¦àS‚ƠFyX'Æ7±”N1 G¢V,,ïưÔ¯Ç$6:H#¥aözo6Iè©´âÅơ5tµ4Út­păœÂDzéO¥•‘jǵOX¤7V”©đŚT3ëÙƒ ÑÚ à&7£NÔn$àø­¯o}ͤ¾̣!Ú¨p¤R£AqqḾ½dc­½‘ế̀Ѫö™UÙ…wŸ˜üÀªµÆu»û¡[ap;²«)ŒÖ,™Ă,MN¢èe¤—èLE@{Lc”ë€%ë(å@vJxÁJ8ôCtˆ‚Q¡MúÜóư _<Ö“ ÙK¸†¨T DÄ₫%E=́.;ÿ×ưf>'9‚BA#Yđ®(Èï$¡²̀äæ5ḉ`S·ï>A¥ĂÔP—ûÅ!J´æBßv&ªW²—ï 3ü –£Rr¥ü–½Ô…@#¹CMy„DT ơ³¨ö"\/âZ¦đYCÇ„²˜ …ĐW/R‹K}*O'Ÿ́ê *Íä`Îë}´ƠÇöRç=º2Jó_ ¸ üzbg® v“™–>f>­Øµ½¬I¿KƠđä{Ö±Œhɼ¾M~.(ÇüØ₫ŕi±²iy뱬+ë}J¾…ú«vÇçƯĐû°f¾¯/3'ë/ºYÓăMFƒÙ°4FFØ7?^×å›— Ö}qT²Ztw [T¬¸¯T‹d_¯Æ¡ŸŒç“E¬ÔAÏ—z l#°C«à×2¼ü­“2–I¸'¿ïo¦NđƯ³̉Yq4ªZ{ñŸKW¶pgˆ˜ª:–hó®;}‘ô%ª‹/S’§á^ 8WJ° Èđ½FdYßi³´“™­‘·VaÂØơ¼à́Ÿ ê5& ¼ggB"<*S­C¥ß<ƠKïP©₫djvâåđW|Ic&]Ää•đ®m|ºØ´!ÖŸR¨C6¶@Ăd?ƒâ•êG”!7b̀°ïôØa~0 _Ôưx¦\«Æ4]đae_í*?¨¾ÔÀ!·QJ̀¯á@Èb»µ“†ë‡ tM!©ĐRù×ư«†mÑ—Ó—•J“^±³B \§täÛË´•kăB÷jŸ×s` >6üQƠOÈnrú–½É́äUE₫Ö·—ê¾É̉ƒ`*Ó³jÍ}ØCpÄÈÏ¢’ ¹Ï0*6'v£,¿tÂÍøÀ›'̃Û¨È',XÔj­Æg¡¢³¸mÂln¬x̉ù?BN‘E¹wV ¿­@0ơđANb>ïj–“Ñ4@Z7²¸€ÂRÈ¥ù à‡AÄ›ˆ'øÊÄT ơ"¥¥•înñµ¨fºE`DÀäŒ2}C$ &É/jĐ 9]ëè`&«ëÖoy<̉6Ê–Hjs¡£É¢+"îḰJ65÷å‚j™₫O+p²=A›ƯT¾˜3ËiOæĐÇ™¢gCycTđ¡»̣”uª₫•°́I@•ë§Rđ3˜u٨Ħͬo0œH R.me Ư³Á.‹—¸\„0a^_l)®ÆóßY+À̃.§vúÜö+r/¬¬YpÙ6…G;½JqµSâLuH%ÑÏôEâx´#Á•5^­÷¦R9„|]½iÉLäÇ¿o;&+á₫I×D‰¡ +ºIøø­ç-™¤}ER?ơ’r›¦Ëa„’¥Ó£ÛxfPÍ₫oVúPtơ‡PBÑü¥VÅ• yOĂ)tŸjÈV®¤ơ[Dä iËH^øZdˆù¦¤ZƯëI¾‰&HT±±\ï5YƠœÎÆ,­{˜ 5•Ïà/†vÔrpb›“ä#:F n Ưdåq[­‡ ỹ\ø¸[l}1G¬PÉÜrWxqÉ2Đ¡Ñw œDỳ²Iø´Ö#䫳̣¢¾ªC•—>m¤Q3Ưă4R<>cd“ơî,)*}§ûcnL´ËÍ ƒ)Ç< tđ”æ.§đg ‚ºº‚ê’ô×ꛂ–Ăl²O0Q-E½È`é#h¢Pu‚y‘¬R’VÁ…j%Ú‘0BÛs}…³ Ư ơ#ö´~!! zt~A¶…B·U ©×µá04R¯ ̉ˆ¸ü1U»TX>W3Q<†'鉧\™+{Z×AD÷~ö ¤"‚’ï½·ˆHY¡À#ƒ|?Ư•.U®Ÿ=ëúómÛ-æZcđ$‰‚ùÇ”̃ŸvXB·í+S°æpƯ!Á~^ä†eïĂÜƠu¬¸XMLÙ¨ưïq¾SåùJJ6A 3ÅuaP—Ç(KCơÚär0aR´E‡¥!›ßT# ‘±ªßåb+×Đ©­b²¶äd)Ơ­'ôºrÑ.Pa8!zízƒ1 }Ưøx¯¢;×2)ä,ƠaW…Wå™Yp¯Ë¿b˜68 fé«Êu®NS¹Ú=ÈÛ+N¼ë}ús-„Ưy™P̃mʧ”£Ưû\[uRÉñ§oë]ɹk:ù₫àÀ2ăXn"i˜Ơ]ÍÆ’ÖKª“w²Ê7ôÑâñưA÷{¦:?"™»xÜ›jíË«ŸáÏ¡CVKs_"ƒtkˆˆ’ßFÓâ|7GNđ9[sŸN|̉G(oAí(ôæª ˆ7¸~!¾´™„ˆÉM•c₫ä`JR™b%ä)f:º|N˜₫2sˆ#ÖCË¿›LÛ‡ÏÀ¯‚Ùơ-ÿ}ñzL̃T›nM0J¬]Í€̉®uÙ甼¦#8øŒ´Bb«ÔÓnvDp>8ŒL¨'ËÊ„CÂôưYé·%z’ômI–zX-ÑïlÂ:©³³Üq£aéq÷6Î(|ñ‚E±+T@¼ïC}ơÚ+s~àà'Ä¡m]k „¬m$Fµ©NZ×Uñê™U+Q÷‡lYg¶aG…Wµzn²üµK N5j!]ªÑ5ăÍ`³‹ É́T¹æ<‰!ô¤ 7Îö\Nï'åŒƠ ­ư ÄĂÛ%k¶N*!lezUÿ–„‰E9©OÑó=ß¿ <î̉¨ùÀ(=1YÛ³çYăçZº=ùd•!VçÑ–ïỦêî\v“~B;‰j:±ơ$ïÑÎ5¶:ö'9Y₫n½w¼1¹XÖy¡CeYÓ|;muWø†D蟽 Ï©/n8±ưÉ£̉Öe)PP@¡§³^ç)ù«;‰g()ƠF²ù ›‰PÙđeº…đN39Bà£a, Kíä^‡¡JùDe·•/ÊÔkrYL:́¥̉AÓp‡:¤1%s±ÛT ̣'Àæín‰™´K^»¨?J™‡"†³$ÑÛ‡îØùCv÷̉Ô™ÏfA_ë*”ÆíDIƯpüB Ѿ<‡µt¾-̃Tj—OKlÈ ‹ëÇ[‹yè.Mñ̉³CaÜÔ]T{ÄÓƒ<œ…i“>3Ó¿,Exs™=öçGu èh'i#'K§™èŸ?)1kX¥«f k;|<ñØÊ`²đwn™Vu§NH÷ÚPééX KđdùUÄđ½tAêå6̀V3ÉẤSÁ³Y®2X-¬Öos¸#v™×väïùḲÈrđ1¿=AuMÉ)ô¾ou+Dđm¶±éø zï|5ÙL«uÁŒ̃óÉĂîÉOáĂUq“4­ÔÅBƒê§èƯ‡}\@å=ñ;²ẨIyÚ“ˆØIÎ9ÍaµÂ@̃÷0Ÿfơà–¦ÇZܳZH)|µä%wCNđÆP}‰hs™Â:®gƒ#œ—°êŒJ zß—C|~«SZLÄ5¦¹“–í|$·|³ŸD™>Âp¨CÓ„keÁæó.-›ÎhNÍO¯ü…®¤”—m¤¯‰à\L8Ü3{ü0Nû~Kns)²¿ñ™s+{¶)†6-2 úiû ªZÊCP &=‚£†éѤ9‘¡¨’Fâ:²°æĂµJ+tº dWJA©G¸.¦Ø÷ÑLøL¼›[R̀>è]xïZÜü¾Ḳ[5̣wMå\¨’€ßéè`Ÿ5Z"/q¼M®ÀàBŸ́xb‹|åŸê7¥ï>âë:nÚ̉‡çö¾_̃ÔHCÉ»ƒù₫́­ùFï+Md³g7Së<Æm.}rË-ß§TƯfF„S¸X‘₫”78Wn¥̀%0*÷Ù¯âß̣F¿ÈPôÂó8µ̀+“oz®b—/»CrOªHÏV[¼‘×’Kö£ÀBX$32ơâ Ú”́Lz±Sm<²êäå?ο’vÁĐ̀̀@ñ“ɽôÛ¹ëƪ[_Ÿa:D¿u-¾ê‰1tN/@?Z₫@Ø÷1ºÓt´æw[«ŒæUÇCwY놥»L¨Y³ßå{kF*uˆå+éâ÷p˜¸i`E-V‡_aêøđW¹á^ Pö®Ơ=Å(—˜lÛó褿oF +ñ1¼$_Ç*“.®‡¨̣BÅƯ÷®{û:©Á¼Ưo¶ª¨¶U Ôøç¹a-¦ y– \c?„Ŕ4°˜ê§$˜ÏáÂ,ÇôWª ̣ăOÖ­"X{‚/$UscMÈÚñϨÎö¿›fĐ˦§̣ÁÇäÍ×T¡Àëzpظ°™{_„ØñÆ1dMÀn*ÛÎnÚ}½>óhYÁ,΅i…÷œ¤ơ·l¬ [¦•cP×üD,=}·3Fơ)s¬Ë|b­–ó“à¬Ü. Á°óásûeWáøÅ•;¸8Ă i²yƠ¥Q:YAô!̀ÀBf4©óRĂăQæeè º̣˜ 9àK3’ø©Ñ̃ZJ§̃ZJ©¬²%AQ_®ZOO/ñ®¢ˆ[”îë|_Øå öQlÏb£₫PIÙ₫Œ¿fo—ÖhhD`ư«©Ç#6@ø­ŕw¿-¾»ÁêzܾơI4ơ_ƯPu ¿JK§uI©°I\åöü O¤aäÅ32×"Cv3E¢ï´4ÊĂ~I3úYób«̉é¸c¿EÅz­l;ĐÎ́\`4Í,×ÛJæÎBwgàáTL¥µjKO`j¯sHÏ™#Đz¿4#edJä™z¼œct/ÜÔƒoù¿ËóơÀ¾sæ !³p¥Ù`œ$6ƠGªÍ}DöY±)!4•‹ßÑư&,jYÚ[:ËFêw:rdzÁŸ5Ơ89G¡w\ë©ø™P{[¨5¬o‹nt>8ƠĂí6¢ëâ‡Ă7*ijsÚ2×^0˜ï K‚œ÷óâÚs™Xvẵ¿›Oi±„\Uq‰\-Ë1T1È€y—[Vỏđ‰̀ñËk˜µ—P´S†Ï@^;>–̉"·Qe`Ç¥'‰ylZƯq»»¸Ó`‘nê Ù^IU†êd&BÎéΜà†ÄQͬcjFÍkQÉeˆPó`?ÿÊp¢¨~D‰âNcØm……ÆA3%®̀Æuă<>Â×Ă…>½À>îN‰́Ïx™µgÖW„ªù̉ço„pDMÜ‹è§#.QƯ\’cXæră.åØ>‚‰Nj„ê:?q–8‰ËóœÊnÔ+Ö«"’¨W¥Đi|9ƯοsÆ›Rvñ©EúÒʲ¦™¤³¸VSí1L ǻ¡6ë, ©à†Ç[–’NŸ¢EÙ:t¢Ç(ĐÅ lÜ`—×åixÔ3PSc=Øä²G¬́£iî¸Á3É?…̃s³xđ¸ß‰8Ç7b”èă{ÄO!•Ú [öw´đñ \ÖG¡I+üÈ(œf:J%]]€»_rơƒa¸ÛJ*ÙđfÎRÅ_À¯·2ΘX¤ïjA¨çÆÉÎH¯"jáÛêï]ñøB®Fwu ƠC¶ó– QÀåóÔy»“Ơª7FW³nj?Ạ̀6XÏ )Y¡b‡È`(ÈkË̉Ë‹Û|è0ª¬[ØøxX*ùØ¥ {OÎ÷̉ê›YŒéXÏ6udîƠLU/XË'¦¥&°̉¶P¬ù©¬ü<’®rÔ&è²xÓxg̣dÀE´*=Đ€r‰~ví>ÊÊÈq««ü·!—¶e:,p(d,ăúgÊ$̣—øa¶^9“½!ÔIü]2.!‘ùx6dAî–Ød•¯æƠز/₫sT‘Ô÷à”1/ˆçŸäDÀ·ÙÝ̃›=Ÿ…b"•ăD)ĐÛI«6íÅ «’D9wNʺë¬ÉÙOG' CµĐN*uf&ü$\̉q´Å×Ơ.‘#ÜR?¶ca…ê(n,8[ZØ[)/J(=™µÚỎµLû܃DwĂ6÷ö=¸¶_ 2™ælÜçäụ̈hSVÙœÁ*dÈ̉'•·mĂßUS̃x†C±&ä‘)¤²‡®$.Ÿ$æ̃YCz Ư¥D½Ù,ư2lT§|.4_Ûó™ot0‘aé]}ưỉ[æ$™pÎx‘4¤àQ˜oŸv‰à‰N‚Á“F+zƠ_j…!Íܵè̀k®̀»¾Ëđ >Ĭ*ơt¦lY8¦A?ô¬±M×è}×˓ʤ'Eÿ‚g${Ê¡ ̣6m Jö¤}9BŒ4,\éc^{N4·7#vIü&¯u¯DË=»ÙÛïkÁƒæ{®\PUΪV;-L·4Èß́ư|Mnư¾'ø̉¾2îÔƠƯ$ÀÔ¡9\F‘¢DÄŒíS<Ù,'ªb¹‚7ñÚ1Ơ‰?P`XÈÑæ'úº1e®ûµ¦Dyh’ JøRs¥q®üAvaqăưàm¤`jÔµ[r‘ï5 ơ‰Íbà‡ùè-?₫§T²ºeƯú´̣ (ăóÊ+Ve rÀ0ưWq‘©Yêè2_KÙ*ÛÑt‚PCSEjÖ`Ư°FËÖ².÷e^¤c”oº`,“ù́¨Ïr>œ"ưûÈ_ßQgr0¸j&™@­fGøYCoj?ßiÄW®mû9¬Ḉlâ™ %@B¸/×N áHk“(¹£"ƠPà+ß–PVu¼ë̉ĐùÑBđµ}ö¸’†Ê‡î2Â(x×cg‡„+åÄàL]—}K¾“M̉É)nâ-”–Ă8\g2êÏx̃»U'=OàŸØ©9(Σ¦>Û{QEMN¥f$”%Íg³kªXq3?ȵ̣ ‘g̣¸v~,ºh n¾Î?6i’aÁË›1êÇ<­²~tæn̉e·ª đι„È4mÅêß•ñT.*uˆC­l9ơ¢H §W‰ ±(›Á}ôץǘg¤˜ôÉà¥6Ä'ŒĂùa]Ä?̃àƒd«…×óƠ…%Ú?o´ÿ¾rËÑEî¤=7Íô‘Å¢H‹¡‘(¹…i^´ù3qE9„ËB{'Â₫Ơ5!†O€ƵΔ…ÓÄp}÷v°â¬›ëi^¶µûŒt»O₫µLM„•Bá Ø2DÜ´fÔ¢ácÜ=̉ü}́‘5y•îi¾ô¨…^ÎâV±́C*sªí¶*äđŒ~aK+;NªĂô}ro­”¸diƠg™Ÿ)o«ơø˜Öscet‘bG,bM đWÚi;$°Iï2ÉíUV"9p´÷)”Ñ w·ÆIkÓ.¸ĂÉƠư‘ûó}BúP§MÔ«¤<¢B‰{½yÎ́¸ßî9UÏt|4 ÎoC̣BWÍ:c÷̉ÄÚ̃§óHlV1·ưoơaë6¤–¹×±<`-³FL˜I–×”0 €*ÆÊrx.® ªoMJ½ơ·Dè%O¨Ôld6]•>$nnl´غ–Ôg -í̀¢¿¾\ö‡fˆV‹¿½wë 9KïZKO”ưO—`—‡ÚP ;:1öÔK¤­)G<̃ˆ.Ă©¹ưó¦UH,/KÎf¸ŒR©†ÚœÆÿ,Ü›˜÷zÙ½.PíSÂ7·ÀôÍåŒ&É騵mª îd(æç²a«;Â|ßë\À,hç^c¾U:½˜8]g!Î é´µ̉úÊö|Ï3´@ëú±ú¡lm@+Ÿ=f†È®Ø\W¼GR”Í9áứéMÏñq¦¥é›U¯dâéÏŒ¤@êµb½”Œă*iÂyƠ§ TÛ!4f‹£FJ<­ø4ÈËA¶S}ưÓ¥ÉÖ§H₫‰à„KÿŒóXœ¸O…¸°ṭKü/Å*$â¶ßÅ=Œ b(q€bÆLÛ>J›S à€ÁEÈắN¯äçª(ˆƠ®©TËÂtâ­êoB¥ø#ù̉·œG¤k*oĂÍCÛ1fc"…¨Jr'‘ä́˜µ‰.i/¦ÏíXÊqóßH„ßh™^V;1¸ô½Mơu€°Äfƒ.üöyÔĂôf‹~Ú>rù!cßúîcèωĐÖBU\@_„pûUZîH‡ÉN|X¾sX#ÆḶÀ¾! ;óM×ëø¼‚™Ç~›Â[Ă)s±ø+5Ÿ!‡s#!!UÄƠˆEVyi[Úíç4°â½I¯Â}1úU½7»&¤Q¦Ûo"zƠ±…‰3éÄÇ¿È5àx*›b¼Ầ °<½ç­VV¦xÂ?u¢Ó…ÎtøÈªyߦC8± ¦áR”Ơ³óƇ;q‹£0ä¤R¸p₫ ¯¯«Ñ®³æW²Ă°ù{(›¥­yŒyÔÏh½HR Ûv«'Ö̉Ë¿;œĂö/Œ'Ú|hR"HÁ#¦À¨¿ü̉?¶ßöìÏÊd…¤5¤dO²Œl8·Wb¦›Â pë8EÁo¼fê•QÅ¿ªb>đb‰đơ3°‹¦Sẹ̈ÄPÂ#Ç  p7*&ûÊ\Zä››äúI¾=i[ר_ˆr¯“q©êy!zS?B́AÔö¸ßPoî@“áæl+&î›|ỦO=ÛĂ Aœ•ZÆ"—«„¬©:MY?™,̣”+ú6ëQökÑíÂͪ¤)& >Y9y™• 6GâRY¢È…ÚûΘñ¼W!´td2¯:à́Ç¡{•9¼!5CÚzÅL5”ăú9©J!ß́„üæ0¸Ä&Ơ^53ó¡ơë}€¦]¤½€klóIB†Ä¢ra'QÙ÷ă’íÏ%„oOF±nï]¨œxøämxDQçƯÑiåoG&ăæñÔ l•BZv¶v uƯ¡Ơn RÙUíđX}½ ]é>Ø„!Ă”ÆBt7ĂoĐ˜\Æày)-̉x#*x?`««P~"lå'Ya®ËĂàăÚ\úÀ$•N a¬›Äv¬¡Sd#à÷4ÇXȤè₫ñÆA›pq ü²†È¡¥d0>1÷mNlÓ©ü-«^Zˆ¿‰ÈréÍ=)Ëâ›ä\³ÿÀ ?ßĂ ‘•$¥íïtë wB ]ØŒÍøæ‡.TùbƯEÖfZp-Æt>?&Oö˜¼´'dÎP¹ZtÏ̃efÛ|K×a+^\ăAyÿÇ$k¦9-{hè¨le¾lQA$²QG~Đ>n•(/…™½º‹4đÉ<áˆl5&ÇêdC…J[—>€Rß³ Ôw¹Y›kë¸ €Ûjpj­`t»Qàæ…vÆ̉;‹¬Æ¢äa!xưJƯÎÑÅ–ưlËî!pư'ÆÚE-EÏíàœó„ơ´Æ~¤4j>ø„?=Ù³X›5Zf-_“á'Ñü˜gÓN0AïäK÷v|÷óc?*’p1À•©5, †¨¥«j‰Å0¸íœJ"„œ̀4®̀h”\“jûDå£Í¹%›‚¢Ni‰h›ÑƒVæbMg'ÚtĂ+B¼e¯¿b­˜6¥Êk¨c®X)S̃”­æµ~wùkT¾­¬kK×­©]v›ŒmŒ–û—Ú-‹tx½'ˆ<ĂÔ⣨%û¶º K 2ư%^÷y 0̀ÍîQlyä’¾½lJ“NûûKä Á´đQà `·²G€rÓÙŒ|g{N%]ºơ₫Â^­‰¡×µ»đÚ Íâæ¥̉lMäa4ÓSH—!À†›}’opÂ> TÊ/[Öm:‚Gw;ù<áøS̉´êr*¥¬0ÅD¢ËÜ(›¹èöZ0!ÛY{œ× µéaˆ©—æ>ÇoSª̃dOË/!–ư÷ …¢́ ˆƒLÛ‡œ6ø°M̃âêq£¦ÖkƯĂ=—©Ú̀”5_…S}™›‚[5;\Ä("‘ë½ưd·{ ḱ±g7´Á$ <"I¢đ+FơlÏ §mÛÅ®Tª ¾%Ÿ"Éơ“}"e=`‰‚ɯ•0 8ñé—XlØ&ü&_ï&0ϧ¹=®]&“½º•!;Ϩáo› SeÆânÈתÇCöÍùÏ\°ñ%[%÷äQh÷¯º×‰µP•ZoèÆÍ¥ƠpÏ5a›=⪖NÿÉ vÔVt;I¼N”¥È}bàă§Â™Ư…î„·)µ"U¬”xJ¼êHê„ỲT%¿ ä¢|K‚.Pọ́ÿ ¯Û: $s·ïơn‘{:ÎSơå ,aÇÏn 2À&x¼ú£8†B¤0&ÈêC5 YÑëe²4ä55ƨÿNBïDÚ̃)܆ѕqXyóèÈäUê»O!~/´Å¿ëÖtF¨̉<€Ç~½–ơ·i[/5R¨”,63!ÚÀ¶r¨>=l”‹g!̉ÄŸ~¢I.wÉ8w\ʹ«³ ÂxØ€´ ̣ÈPøˆhbçƠfmC§&Oå¨!Wù…:œN”®ùHD¡Úb6Pñu»(êq“å’—à-®7Êt{Ô.³ØéVQ1ñEüôZ²Á›Å_Êô"Á¬c̣™æ;DR£b#<Á0[mAÿ\›Ù*P¾„NHü₫¼ù‰øˆ€;b-zxÆ‹h8F€&>âĂ‚‡Á x́¶Ÿ¨øº‡A¹2¸›̃ͽ]¨LÎ=ñLpw”ñk₫ƒ0α]1fG0ªDđ/ï{fƒ EÇƠNÿÖjơZ·ó2:ÍIŸ̀¡å‡ï˜¶‡ g`2o¸¥ZeĂ:Vs¶ºfëc/¤hL†×ô °ÜXÙ* á“÷§îưeŒhT ­\ J#C…́ùü‚›tL6™DmÀŒü! ¼K¿*_ÍæĐÅuư‚” aªÂ»…’H6?×'yív@ß®_¢×Î8Y™€å?̃8Ëϔ֤/¡}óFº¨ez –t¼¦¹Ü‰́¸ ç÷>–} ‹6iÇr}mÅâºQ¬—Í ÏéÑ>Í­ˆ¾ø³÷Ư~¡̉Obûª?­3Ú2@îÅ"ùË¡¶"N§j€Üxµo7ƠTë”¶¥xÅîvÅ´ú#‰spáăÄÏ?QxáÖb-çứ(¦íÑ3=cf̣.!Ï;3Ú0“έnù|ˆ°ó±æ×Èé¤Ç?eÖ&tB^ è» Y_úø¦÷¶ ß2’3ăyhÿ·–È~»Äó‰OS·Ê @01|€(Y=SàÏîÅ9éi()|IúA6.©&¼gz̉ÿđîSÿö:iàgÄ8Ñ[/­íư®á£ĐÎxS [ŒU¾b<²©v‡o,VV¡;—å%&…ÛÊ=Ø̃jfê¿[ÿ^¿T6gÿ1{Eb0»C1žk‰G 4ÄÚ7¢¡8jê²ïjwñk»Æ°èÙ kqæ‘ TT/WÅÔ=®'0h!½ª”:¶“ë)ăăüv ¼7µRˆzq™!~½̉­}$ç-œpN9UÛ„©]¶ç•è9̉©ñ G;êü €úÚâQTu–ÂM€¿qXÿX­Đÿ¹½Â÷¿˜ßÀ­ soâé¥çvƒ̉-FÇófø508á˜ÇOYÚé$7À/×üA(¢0#±™o&Œ’´iÍàÜ[ñp$è²]¤pT¤Ô Q™^Ơ9·ÿ²Ÿæ¥E'«/Ư°+1{“JÆT1â9̉)ú8Æ®/°..w²ÂçS4£8ƠY‰`>)‚p‘$ÀMƠl[ÊÈÏlZµ«µ3¬˜%=cĐܧ†°¡ÑaÂï*ÀUqóñ^¯a‡í³$́º÷?¾­Ơa =¿Ză–Bs²•w8AéÂml1ÓWsñO6Évïp?{U¶ ~sÈa­ưß ¿4)¦€̉¦ṣ­I₫zÊœơ•²j•8¬µ|«Íq×[ă1‘ÊœØßéש‹_¹î̉Î̉,ñ)kệXFÄÚGHI•ÿ¤P,e¯“zb³¨!f4‰.Î&¤c è)Ÿs!©Vÿü̉Ÿv2 •ÛÖ›×¢€‰FóµƯ–å³"ÑÚmÚE>+#ưYvY*L¨ÎnÁ•û„ÆW)q;v‡d6xŸÎ°{“å…Tʼnô›2ûQ5 ƠÖ³`¹àÿa®ñZC )o¾®.BÆÜ·ưw©©mTø¡…ˆă{JT₫ÎßTlT=î°_7y()J½sMơ퀧¯–ö7́7úM&ôètt+vΗ$F “\êz°7 ơ°%8^đͲiuñaL’¥@Ùa¿ưïZ„ÿÄv«?BŸ‰PÏ₫Tà)‚„û9oá¬0&óú̉¾8 ¿˜#/©Ë:×/hßd1€!±ư0œ , ồ‡QTḱLăÓ’ZâíÇß>˽²Y¢)êÂ$Éѽ' ơªóª†!Ö†RF¤A Zî:穆½è·Ró¹`°äƯ¾P ,'7cé[èfl•ñ1~{·ÛI?UËäjÀÄ׌Wٷً=ÜÖNªSLÄß?j—¿µo9›vE5Ö·éa ä]C˯G]4•lçD‘-9¶FBÈ™ œ*p˜§\Rzîu„~"*tJasmXdª_OMÏ }i¶²*¡‡bª7oŸîƯ©xyƠÑEá5z}µœ60£!¡¹W“l,†‡~,T™¸¶¹gp@ơumjÛÑ;¨Ûv́L¨£‰¼æ‚µ;#U:Ṭªˆ, \ÇË‘sÇï&û‚ê™R÷QrOlzI%×Ü$ȤiÉgÜĂÄ̉•@₫Ô4‘â_Z$Ñ:Zœ0Ơ‚ç»ĐFđ»©Í¼ ̉+Ï7y“J¸Ă Ă5!eÍHqrHk‘á);Âzœ̉E„ (=$È0SÈfßø:dr­y˜]ôÜs¸Ó¹£Üơ±&‡âis"Ñ̃u’+ÙRœĐ­N¤àÿƠêJí²S`VÖÆáê/K®B¥UœJ₫j 3U>·+ôû÷´Aư/kôxœr?@‰Nàv‘l~̣MÍ·çÍí~,û#XUçZ>z|_ë°·B.ED>+>N1àåàidO/È3€ªtǸ(æÆîˆ½ƒrzÔ ¦?Ûû®& ¶w]Ḻ…5ó¡@N;æäJM/;Ó×/C2†¬_÷RcXµÉ12áƒ]Î;0DºÕ¤ơ0!S¸ÄÔù¾j×­tĐúó)5.¨·Â‘‹~̃ª¼,T(—¬Ó@…́Æöe5W–±ÓOzĂyf” °‘ ´C¡©e»)…v¤ 7¨p„3Óñîr‘Œ´ĂÁË‹₫«›P`ˆÛD34lD„lḶưÑäéíˆ×œh‘ƯyùØ–_ Ç6£1+ƠËZ+·@Ä»₫½-x1…LO d‰:=Çßˉ–Ïr|.ôE¼ …Y’ç¥r ƯM-UÜ6]iYE“ól¶R¹ËæÅj˜“¡_gÁ„…×ó} Ê  ÏÈí†Öü†„‹V†<p³u.Xï½@l7PqE¦Ó:÷ÿ‰>î€1Ë8ÁâÙ(³ÑÖ̃tôÚ¦뵉ë›G—籃ª'«ÎúöJÉœmhø É:ǹûœÙX|„œcD 0PT4w;eá]ÂøƒñFêđ LJ Æ,)ô(VX–©ÔÖñ)md#đ‹ÈDm¾\[¥œ ̉Å.éê±|TJÇa–¡M‚8!£_XƠy¯0ñDu× PoÉæörén8ŒM˜Í¨nêyÁ̃¡­y† ̣Éqtà°kúcJmU¡XG₫±¨·ôơ{»´«Aƒö ÷;è›·ë(Đ9PÇ€H­éà@2‚;ư¼Æ”“ϸA#ûʰ2„‰̣(î¾±¥XÛ8W {NJ²œ7/·÷̀|É¿£Ü" +™ +Yưë*hÊ{°$ỰÖB`jÀë ÿđ~Zÿ…«ËPYª¹4 †˜„&˜d½ ú¶"i 2Oeü³W­pHí)F©fáÏÛÈ„P4sâxToâ-+=ä%³@#ÿ_~€@ÅA> ư+5r„¦èO(4=%©·†ç½ˆ¶Ơ%¡Á—)Ké°4´#ÄFÇêÚwXY ÷tA5v-É=RăVk¨–_Çx¤-—2K¿ÎÚ¨6â#è´¯&ÚcY‘=ö_g0œ™¢¬ëzßÔÈMØç2¥-Û{ê~ư›Œ[ê–ÙÁ>[Hù;¦h{iØ^t¼âÆeâ\ũ3֜Ԅªûi"}Kxpç=!l¤ !‰7ç:‹ª†©5Ú d}¤áđÆ5Zâq,•pÊÓ׬C+́Ë°Ê”à „ƒ¤]‰–_‚^3G¶ơóoh̉§FKt•@hUœđ-æœtb®Ü ù‹‡ ¹è¾"PđlîºÜ=́zwêâ+32†ú.ñצ^äàƒ£̃Ñ$Wg̃?Rb³V¿.Đïß¶¬K+“U¡¬ØLW~Œµ!epAÙ6Á£n;cбñV…ĘWI,ôµ§ ϳôvÓTœË₫ÓIáⲹܥƠ ̃åê€[dR‰éHZ9:Ă#…<˜r—‹ÁͲ£±¡ óˆ S²C“9 RV#¸Ÿ4½€‹>CÍ©PZK®¸ƠLG Á¢ê^ÀÆ8ÖçÎ`«ÜoR ÙÅ\€F?åíáàs×'†`iBÚs=̀³ZQ́¾„í(b̀­ó,SÜ—ô†Đª V®Êƒ­&94æ¼Ög̀]æJgă9,ùH›Á=ÂÚ?Úö˜Åó2W™IƠV½˜—驼Ơr^Íá˜Ú3†ÔA[h€Q²–Ä,úH¸©ÄA;ÛoĐœ…ó] ÷eäcp÷µ‰ÀF₫„=µ­…\é@±µ«ç|öÍzÚ£÷Ù§«êÚê¬×ïÄ™¿@"‡ œ)|0b49Rÿ^¡5­zTVA:ø¹¯C u |^$G|b vwZ~M·Qr™¨±3E'6Àß/g‘ˆÍ…‡­̉U ŒˆEN&íâÛÍyüvB¶|b5¤“ĐuẾĂxE± ÿƒMw·›¥ư8ÖûöŸ ÔR7%̀M̉$YQçÀpö]u2.y¯KÓ)ø«û^;ÇÏ{Ï#œ£“hˆc‘÷^øJ‹  Pó`º’6,¿êÖÓ^ÉdÚŒ°wÉmü?·I–¿:ùÖĂ ±vÛ§´S¤¡^'.ơ‘^Xé8¦₫J“ù`øØMđ–·ă|Î<Đrwe¸å•ó›>›–@đ$¼™?³‰&ÍhÑÇîwˆevwXéjg\«2ÖâHû9·Ç.V–—DˆËö¬—ÏVÚ̃ á'¾}•ÓºÁ®aßÄ=ÏM ®&§/("¢Û $×og°kD´t6É^ óÈ–3 ¡ýB¥“µRÉg·*­¯¡°L»GÀ ÿÂx>‡¾z©ù̃/ ¸ˆu[V½ÍQ;ưÅoÓ{§_â¸5Ó']ù1Ôy÷ȘKÖ•œCoQPr@sox¶9€Ü àÈt?̣~é<Đ¯dÉ(Ÿ{›¶J¾B3#œ yÖÎ=˰₫ù„Ê9Â;&ªă¤éèh Ơ2V́f€K A¸ ‰ph›…;ơçж”đih¹#äƠ×%33ê‡ơå,©UŒ ä£\&w Pƒu5I~ˆ>©Ú‡¤Xˆ®æâ„ISÀ&úS̉“ÛÊP¸À%Çîè–Üo÷:(Á¹½BK¹Nª¹;ë…xäåêă½¿´¡?}î Éw¦i°nº°˜ă¨Œga¼ơeG"âÉ» Ÿøê­§è!8R½‚Ϥ¢59·£'ơäD#'k^=AĐ«Z_Ạ̊ >^­Wăñäˆ6]D¶Ö¦]ƯÚyÓ‰ˆ„,IÑ›2ñSºç2¶Ö¥[đDµGçôD­³m>çû3 ~!U₫ëúh^H&x/°µ ¡²Qµ%E×0ưgAÓ[‹×B«M½ ¬­ q5[‡i  †’ ¯Ä'BÏkv§ "Zƒ•¬Vüi`ËlÎæ-©ƒéñ­oº!ë+dÂÎaơp¡³Âˆ›Ọ́:KL~-Ơ Îăwn&–‡·ùU–U'@ÑôE»“@^ÎPƠ׿bềí/GxY}W¤8ÁÔÂ~R/GKh[¼úÜßbXáöŸ¿¡Æ£È.™Q-xD&*9EƯ5OR°'3Uk„¾Ă>7ë}ễ‰R¢BW}né­•¦9Ÿ#@)ÿX€†¯¨¼Í09kYQ)×ơÚ >-¡i¤eL­½Ä×#€îä:€~^SƯHy1:3i½ 7€ƠœŒl­™b©2½n\¸ÓăpIÈ›=ÚtI?`éY{Đäœ&Ö*MC ¨ö˜À²ÿ#Ïù b{₫CjfBđ;uôÁ·±w¯êz²[4Ù~o™- ëiå%zôơh ?}‰ơ§màu—ưrg=(Œư` Æ@M{ICζÈë…¹# pGA Ú¨V-Ơ?4üs±l5boV:|Ôo¨›ưVe¹äÇfȧÂÛÆX?Å7À'}¨ßS›EcƠJ(›¡ŒÑÊŸèuw̉ Î9ú·9ƒ•5d̃=H ~úÉSDâ@”ë£({b́|¡u a<³4Ë…-¿ÿ†/̉àº2zZ_>àÅrMÜa&…Uñ_U(¹Vzë0—‹S óˆKœË—J_Uf$F´5BçE&yµ¶ø¡1 ¼G˜B.ÉÔ¥–åƒÓh!̉=6jû<ÄÎÄC»%a‘W·-sWÎ1î₫Ü×ƠJD¾́ÑE@qÏj§ö.mN6EĐ5‰&køN‚g’~ÄgSø!ÓF‹â7nKmÑ“o˜†₫a§1Œ¥¸€X¨GĂE%[˜ó¸SB:{Nüf̣JÅ›  oÂưB¶¯₫rßî LÀöl×$ǹ¿Â^ „è¯Kǜû±éàBƒ×BâU'öZÓ¥N¸:Aà¿qưô£¿tpúÅ,Û/`Đsµ8YzqœœÖuÜ^Ÿ¯[«8 1k>ØtF’óăU œ¦flpœµ,‡¿–Ø̣½X'«Øns•=ÿú¯¥ »¡H”•ÿŒdll{ÑÛ`hp©<ĂÉ4á'’rxƯs±z“¥à‘ëÀÉDŸ­Kó¬[ƒNB}́ï̉Ïœ•êIyÖ¬ÁéÇâJÙh`)ÜT!†±5Ë¥S̉́̉hj1²gjl ²3Ơ°@CèAzĸV–=é᛽Ek!ÙÊw*9Ú ´7ñ@RE— &*T—×~ƠVt·+̀ÍẲùlTØїΨFi1Iª4Z]Ô6bưƒP]^ƒ8âá$°ï“âÿå1q®XV^ÄvºŒrÆU‡„=_TBŸé‚À:¡`¾»>¢±H”Wb7S:Ë’]Ơ±[nÊ @•H‰³™¦mÁ¯¸̣ǵù I¶Gó† ̀½—3j]F¦»[™j‰\E´ ^€*¡wyÅÏêÆÆø±É§)ôû2‚t²6¾́¿®½Ÿ/O¤ÀƯM₫ÏüWÖ|¶£„ PZéî†ö…›z'†¾æÖA9TatÀ⦑ o2œóR,Œ“1ËH™ƒÄ}fL[́«mîP;ûB!/ÜpwYѱăª-\*ÖƒjF;/³Ÿ0 $΀oM¹¬×eîŸdÜjW†.J‰äĐ#~ÈăZ¥ù¸-T“NS-Ê3ŒQ‰+v'„+ ˆ˜N:‹‰Zè]Ö›dåăPc¼t¾”„Ïàj×Çت ¹\jh&:₫léØ+©ä;9cr^¼qñd «C% ăíÜâS”kùÆlƒXmæßZvù°=¹‹ÆÎÓ4ó>{7=Bv–ơ¨vÊo“ñn ~.!HÊOb©œF} endstream endobj 1351 0 obj << /Length1 2262 /Length2 18413 /Length3 0 /Length 19745 /Filter /FlateDecode >> stream xÚŒµPk¶-»»³pwwwww°pw –àîNp÷à!¸»;w ¸́Ư}:»Ï{U÷Uđ)cú™ª“˜¥“9PÚÉщ™• ¡¤Î`eå`feeG ¢̉¹Ûÿ%E ̉ººœùÿ¡—p¹¿Ë$ÍÜßÍ”œ̣ö67??++€••ï \ù’f K€3@̃Éè†@%áä́ă ²¶q̣?ŸZ :ăßî1 +ÈẦ dæntxhafĐp²Ư}₫‹‚VĐÆƯƯ™Ÿ…ÅËË‹Ù̀ÁÙÉƠZ˜àr·¨Ư€®@KÀ_å”̀ƌ@Đ´¹ưK¬ádåîeæ ¼ ́A@G·wGK +à=6@CN â tü—±â¿ ÿn €™í?tÿö₫‹äø·³™……“ƒ³™£ÈÑ`²T¤™Ư½Ưf–Ù»9½û›ýÍ̀ß ₫NÜ -¦0{¯ïßƠ¹Y¸‚œƯƯ˜Ư@öUẸ̀Í{“¥-%œ€înå' rZ¼wƯ‡åï±Ú9:y9úưëÛ ähiơW –Î,Z  œä¿-̃EdÖ@w+++;èz[ذüE®éă ü[Éö—ø=ÿ?g'g€Ơ{ Àđư‚Ÿ›™'àîê đû§â¿Àdá0Zƒ₫°¿‹VÿÂï“wy Xß Àú×ϾŒ̃wË̉ÉÑ̃çùßĂeÑ“‘Ơ“•aø»àÿ¨Äż~L|&v.V+7€çư#à¿YTÍ@ÿ΂ơ¯œ£•€ï_ɾwéöü÷ôiÿ}t€ÿæRvzßX €öÏ‚²r±Z¼ÿbû^ó¿]₫ÿ¶û/–ÿË‚ÿï|¤=́íÿÖ̉₫¥₫ÿhÍ@ö>ÿֿ難ûûî+9½_€ăÿ6Ơ₫ë\•€– ‡ÿ­•s7{¿1Gkûÿ4ä& ̣Zª‚Ü-l₫µ*ÿ’kưu`ö G ª“è¯ÀÄÆÊú¿tïWea÷₫h¸½ïăß*àûÑüwH)G 'Ë¿®‹‹`æêjæƒđ>âwÄđc{?CK ÷ß `avtrw¼—°rrEøkÜ\±¿DÿBÜñ?ˆÀ"ññX$ÿƒxX,̉€Eæâ°ÈưAïœĐ;§̉Ä`Qùâ}çTưƒØ,êĐ;§ÆÄ `Ñüƒ̃kĐúƒ̃ăiÿAïñt₫ ÷tÿƒø̃ufĐ»ÎüzÏ̀â?ˆó=̃ûCæđÇú¯Y±X₫¾wøø> –-ʃ÷r¬₫Àws«À¿” ?îAÏ?|l ́ÿèÿ2ẉpưû»ơ?à{¾6²ï³Íû₫Çâ]ú|o…Ư?à{/́ÿß›áđÜßKÿCÅơîêø¾«ÿĐ¿çô'ú»³Ó©ß³w₫£~'s~ÿïăh´úÓ.N¶K]ÿ»‹5Âåđ½Îtí½(·?‰ư…€ÿ¨ëƯÜíưMưăđ>§?́ïo‹»+đs|OÎƯËéïÅzü¾÷Éóđ½T¯ ơƯûÁØßé}₫ßÛàû§àw&_ ë¿Bư×…[x¸¾÷ÁưïøưüÿÿưÏôZ ¬.9Y„Ù6†u=Ö‹z1L ÍSèdĐ1ù­ºv{üBM¥«Ë Ùvư)–:Ú‡¶±'E{/ºFúÛ﬽öSG²Zç³ÿ‹I¢ú́A'ÂÊ ÎĐtñ™XÓ 1<“¦è¡ÿoí`;Èvđyª^ƠϘ^2̃Mƒ•ë—Ôë¸_*ç˜bµb ƒË¨ ÍsñÈaÜ™ˆáè1®½QîÎcäO¿‘Ê'2 œÇr”øéï°Ç=-únVk²»}çÄ×Ç#†¼Ç˜˜¥ö?N“Ç]ö+/ÙZñn,!ÍGfLß`Bc>fÏ®©G;¶ö7xN¬~eÛ/H„Ñaî'7T´b™¸’«`×uDcº7p؉¿Z‰ovưÔîµ²M'Ză›kz,̣%7 çEzMnệCâ(̀/–÷º,¾H̀SÀ±Ư}¶Â×yÁư-GpÎlç)1>¡c²ÉƠ[f½®£Ÿ®óSå%pĂˆLÜ{¤x%rÖƠă\~¡$FDzrû́I>×%L²øFܸhÖ …Fưk¢yâ~‘F Œ/N.”0K»Ưö¡Y÷÷ѯª5ä¶7}ÁIxî;kØé·‰&¨&ˆ°7Ÿ1EOô`/V±~’¶?»Í O‘zn,C±Dđ*I%Øü—¼ñP)é›ÏưK7>ÚÑå¶ÖK₫:E☋J‰̉JëÆ$‚‘ôº>IfIèOJª.âôHÑ`»ó́Üœ >G Œ8ôqÿ9®`I>v`E¦Ÿ;.Â|úex¸ärâ^Ó¡å³øoûCÙ»œ‚q)-ƒ0}éÆ Sµ;:Ó­YÜGkK ¾´\z‰«Ó|àa´÷½ơçGƯËäx¿̃Ơ ê¦‡ä¬Tä°CÊ׿ƒ› Q¥çÊ"ẮqZBE¬H¨ïqYp¾TùP‹ Ệ/ɦUÅsK:ÜmŸ đÄàbU Ѹ•Ob²É£xL;»6’=•4.uEĐƒæ_½åÖsèUXÈÓ¾!¶"¸³ PÚ‡ŒL¼Q!â —) Å>,¯}è|~Ħjh,U×0.(Á™WoÉ4û$}RKû50·¯ù' Jû·°°M¬êơ°ÊqÚY9"jXÑ>ôüĂ½É}̉€H¦Ư ~¿10Ê6₫G¨H±€̉ù2L[cĂÓ·á=·ßGÀ´ëÁ]_h2Æ–M–ëV"&p¾/I%ÀÄ9èiçù/n”Äq–GÄ#ËÊj,3ó|Ơ‚Dù(s¦W½È&¦a™kœ fxP̃®5d=›pâHߺ<ÈQ>¡ă)HÆ©¢9¥ÍvY<ù ÚiÚ÷Äàḉ‘=of.¯ ·¶oí½“Ä®| ³K)·&bkJ‘sàûEfú¬O]¨Uˆ­¡—£6îD?i„_î9Fb•)ünÈá?g¾9,œ([¥a÷uv!)z;‹’îùº1L~¸ÿ} w §½a¢<˜[ùØC_ÿ‹H.ª¢º³ÚÅ®"›ÇÚ`Â1[ƒ3‹;# íFËd8₫A-ü3ù&~¸Y'ƒäD¥̉ïUcê5Gkị́Í¢GH!·|úºbnĂÆ Ï§à¡uyD0·VÏÛ™i]½£;¸ê†^̣đÓêÎ?ëoh?^́ø #bµPOÍ­ơßù·&w“ ÓÍw¤V.°XÑkÀÅ,,u_Ás«²1­Lî¾\\®ü“g· ¸́ó!_s¨ưFfB±Væm>÷à̀¥lđJ¯îă–ByÆoÎrÑ$ ĐËSø…égU¾º˜ÁS;Oúÿ·+œC×[A»>„‡¥6ù͘›¸]F|ú UÎ}ä7ë6¡™¢°˜ßMAƠ%ĂΘRágq_:âÓœ¨@ ×ÔnM^"¸>OF*j?îr9rUa-{¤¹RḈ€«¼“üïĂ{•E§°Ë§pǶЅ>y¨²ÆÆ!yÙ "ÈcyÅú?‚ÇÅ|ƯRxŰ1i®×YØp9œ́Û Ơ©8e·pæC»Å›l}Í­"¯f95gÜ›ƯÀ©„Ù;öÍÊ;;8üª̉g]dß̣ˆ¿Îk̉-Snk;í-!­Y=P¤C̃ÅæI”K¬+ Λ¢SVö¹cÔ½Ï ÎÚúæakÖm~SØ81ÀÛà~˜ŒY_ÂzS,ÿi½tậNÏsD’vÖ̉†o‘$ÚIa–sæƒH.Đk!(‡d@êê›pdÊÚ<̃¸pâ[yN6ÉËBäèm9”?í d:»đ!}lp0! AƠqT¡r0.ÊÄÂggatä:®˜=l°Ư£`ˆÊ~«ü ơÂư¿Kn û'Ó̉îÛøµâÆẨÙü,Ût_[ „(±eCRË«eâÈL-"ƯĐDÀ̉đ`2ƒ¢¿Æ0ơcl ¢Ơ₫2ÓyT@º]ʸæÙÜÓFJư°¤oTzG{A®ëø ÔGUR¦7|«,$éÓÎaªˆëÅA°Ü>₫²ÖyuTg±ÂÏ2ª ₫¾xIMÛ‡8A«Ç̀‚{¯ß£íÍÀ#6ÀY ûåÂóöI;̉N½OW;æúÇ5ƯÊ× ¹–s–ÿ¨CS¡|ă{úgj)ë–‚|ÆÓđF-Ø¿7`·p·xæ.Oß ª»]Û<Ô¢̣çbV]Yl§oºb˜Äê·jDDæ²\¦îëµ»iÒîÁ(ªx}v´ 9eé´ˆûå~%ñ~±k˜T¾÷¸›̣…aÍ*1 4ÈØÅ'xü !M23óƒ“XŸf™˜•bW=ár1–(F̉¦'4”̀±qJ•Ÿ”*ïç'̀ª»Ÿ—¾£B?Am—̃ª‰îB~yyÂđTe5” ̃êrÄ ,¼d½Ïlä¤9œÛü&ÓöÍ ¬ó7ˆ¯ªZׯ©ª;‹`Su¾ÑwAŸmfU÷roêÎú¡qÔ«~¸_9V¤ƒb|Á¼W¶f‚QùĐå,œÍ£/*Ü­±!d•Ystkx—„­Ú}÷#>"ÍîÈơµ(4~˜=Ÿ₫»,Yµj*aŒ1 ±¼·û†̀Ĥâc̀‘ƒŸ¯b́$ƠÚ‹ú\¡†f¼æÍsÏ̉-bÄ&6Ó•Ík>V́R+°÷Û₫ă₫ÏaRíˆOQûñ¿›Ëw‘±“&¯¸l°æç¡ (ơĐÖÎ.4v‚e–!BnÏ’˜%µ,¡̣­1Jƒ̃9 ƒÔ»D•–˜ mr‡ấ} 6½Ú ¦RPø`½¸2;¿ û‡(k´SkW¼ưl'‘?g.-ÿL’uZƯ•t₫E;₫y³´ÖÁk®L&”»—G]/éD–Ï:2 ö³đÓ*ÛˆdT§.½_Nd(=l°i¤”đc_êµ€Ï|ˆµÎÓjYGĂs'„m$è¨Í¨¤FçY­¶ÏǤ‡_¡€mÈD[ÖÏÔ;ø-̃û¶ÁĺÑÚpP®Ơ=̣’4»!.:‚Ëa€*HôàÏzñ%ˆCäëuºí0–V¢|øTöºÓô G$'”y@¢‰Ó•€€E™â-9s1Y| ªŒx¥g̉:Đ  <Êđ7×_öZ0›óHA¯†CÔ|­Á̉øA+U¼8)8#„¢nî ojîÔBQŸÚß*ƒ~Fœî$NטƒM–¤zºP:ơºmê„$Ë÷TYfăw$kÇ' ÈVûpVăăD«†'“Hɹ\oÄQCq Á¨"_Êë¸{Is5}Ù¾8ܯ̉èdM;Đé}ü]bÛú"¥†3@•ˆˆJídß…Ç4ö@ó ¹•*HOø×”v§²ÓyđđJtØưĐ& œm€÷Ùë@Í]öXề*™̀­{c畼~8-Üư»ßÈ•-–—%Í2GopDM̀ZPëi9eÂæDë5ànÏµí ¤1“’CÔÔ&˜ù^“s ưz¢3JOŸf7\¼è]qU? FÙW4K>øÅF<3dĂ 7 !~©È+̃Od5 oÂĂ.í²¡nµËA4}Ă ‰Iăyê‡Êî´ Â¨ä•(Hc*¨o¦béÑNè̃æ£WRÈwsYÙ*´̣q›mw2©aĂ6fæL Û3p¯f ¾é/FY´"­ƯĐg“Ơ×`<“ë1%m)rÀÓÚv«G—Ïu…Öà‰ÆX$ÇÖ†O!&s¸ïG“đdÓH¨O#5̣t&1¤½u•Ñnƒk±á˜ -«CeK5 ]Å+|Dø´Ø3v7¢éfîÙ‰àN1Ûß5@)́s)tÆôƯÿ(ªZ²‡tCV¼êµc‚¤uœ…¥oó ÚzÖaé JDcWúI…Mª×‘g~pë\k;.J+ùÔjuóór— êŒ÷Î₫¯×L2?B—I«›-?n;â÷NÑ/ =B@|¯óÜNƯfÿt>|¼s_º́~J©G <ºŒ¹Añ}o~'³ƯÓp«c¸ºhIêtBÁWZdû·lå4Eªy¶çMÈƯZn>Hg騶Â;h׆Û4̃ÊtsƒWÚ‡Đñ[)÷MW$*¬›äÏơ…Yw‘óøbĂÔÁkÔ ‘¯¬×ÉŸ{_eräĐÄB3½+9rrxƒÈ ­¯^œ2}ËŸ̉h§vwóVêđî9!,uº¡@ÍÎÆĐ¹^€6.Ï(̃¸Lí^HƠufw×wÂ0®kß0+×ÊIͲĐG `©c1XcôJ-₫®]æPĐØu+6ûº@wñè/·ï“SÔE(‹đ9áMŒ*6‹ƠÑ÷é‹`‡$¡j% a´±ÂơB¥~8è€ÂçÁJú̀n×céÔ-èƠzEz“@Ê€T× C`®÷—¦´̃vđTh/«#"®b¬fúÖxÜyÜq?™=·3ä4íc‚º<5gä\ÙÁÔ'_IÚ^ Î}ÂIªT› æ¢Ö\V™ïâ´Clê.–ƯeT)>ø©_éù2G TKº~æb»¥b¥“ÛÂ}€ööÛ8É·&5‡“:øǸæ̀nĐ6×MpÇ$Rºµ¼« Hô•æoMS_ϼXRüN;o‹_v°#ä8¦9ă¬wïÜf"ñr{3{×/,ƠÜ»́"ˆÏĂM4B}¢Á“êKĂo„ưV¯I%K°8 ™ˆ|1i$Â."ÍɈ*Pd­ôÅf»„-á²^¬3[eű;̃[81F×ZorƠ¹R|lûéæPÇʵ;~0ç$ç< s#ÑÜêäá‡xAŒQüªÊ€³£ÖD¶ëưLvm§́sE±>}¸å 7sp BY±Ïj'‹Feßi¾~M$,ÓËÆÈ étƒ H¯—ÅQ”¬“™Ö §Uæä¢“Zg̀Æóºl™Ëâê^à&ẈuË3Z“§3RLÎq ¡—sL«Ë—0>R#“ëÆ(ĂÅQÓNÊ©¿ÎŒ:ˆÑo|Á°ˆb_[LĐBûX¼(0'“̃ƒ"m~#½X—È{„ 娛ߒ.Gœ%¦0¹O¤ï Ésb>I3ü¥q¹û“à`*^OÎăÜO×­F‘d‚-ø[ÏíL<± t­eƯ‘ xù2¥¼u%ô/GE·}?q½1#[üÔ«W=ñ5׳¸¨‹°û ¯xă·\Î10U½M.ü!||̃@ #ơy?_‰ÈO">*K̀‡ ;¦/̣ôÍ!ôåµ*®“ËüˆlL]2fhä̉ºæ]°́ƒ*̉ ‚€=bƠxg¬aM:=0Z³í7°’†Nư¤Ù‰ØgшˆÍ¯*ü¹û® Æq‡üJ¥|n•H¯áù³.¢aô’I¿ô2LĐ‚æÁä̀…%n€—qí¢3eFT!Ä¥#)x¢IsN¨Û&æØ±‹e P…7nă«ûÎ Y¡G¤Ñ=ZÛm&Óx2Wµ¬Û+1‹cœ'Cí/ô\Éàµpj^_Y9D’x¯ïˆÔ;¦ÈŸăZáH˜k.™‹Va÷ö¼0́ÇPÎNŸEÑŕ-èܸñÅK=̉¶®”{øjb&Óô˜ÔȔěÉD²’2&ÿ{um%WnxKJtÛØ‡*¯Z A~GḾ-³)óÏÈîß’LñnF‚"̣6Ç;²ØP}g×ê¹;(Ÿö±¶Tê!^W?âyơy©xĐ+?¢Øy[Dåf¾i-ộUËö¹đÖ³O£sÜ|úñc9h1ûîs(s°F Ă®(5jwT¢áÀ¬Ñ·\síB²ÏÊ[%ΫØfư—¬IVñ]öñ›óR’±HÍΰÇ®ü7ơ·Äè çjhPBEû`‰ÇXß'ruZ!qxưH$´VZZƠÜ_ ÷r j£ô·+1Đm‡²ươ Ơ8IG%±ơÓ+—¸Nû¿$ƒE 0]à85ºT6! –Ú«µ!³NÈÛT7Áæz¦­Å‘ºƒ§%<áàÛ¹ }̃"ƯJdY«ấ-¥Gè—pđ/94?ׇÁtö1ÙE‡̣©¯pđë¾₫€Í; ¬ñÑ'â8ḍ¥è#µh¶¤†« '`ÛX”8ÊoñÆ‚Ïbb.ÜÉÜ>áÆ£/E¹¦6J́¹Œ̣}Ac²öî… OVƠØ lQ2"/µ­đÉœBë㫬Ÿl°năƯâ6̃Z­ñ­E¡Í1#åg¤P €ç¥”ëÚ î›ṇW˜HdY6Ugó@L×ö´Zï»% ØÆkñ/:áœeĐjo9Q6S<8¤.¯jçRT;̉÷u¶üóƤ[b_fôK?’đƠ/%°]ôlÛăR~~óu«Ï_ü6s„_L’<\ç>Ûn,Ñ6´G˜|ÍR}x—+™RÁ¼zÑx+ˆÔưK¾ C&˜p€M)ß‘r×u3‡cÆ.0®ç<CúUegcḷ©¥ Í#fÁÇFîc¾“Ç{J¨g²¾½̉áí³`r7©t4Å–ëMơ:Ă-B7Éb;ÈD[4ï5¯¢ªꇳR²5aké0Ô«ÈÚ¨„UPộºđ¹¾¿Ô¯v1”´K‘áëysyưä¼]ØÔÛbio0[#ÏOw>(c?gµe}³ ™Œ#_óơ •yü€3ßkˆtG-Ă¯‡í½&èù>÷lcĐó(w¾¤Nó”®ÑtÙ&Ú\ºø)ó†6e€»VoVÎưhD”–öçK³4)œƯ·(‚&µ’F“́Ă˜ÆA+?¤¹¹YDÑFµƯ¨O{₫Ư}bV́ ‹ó˹q/U\ñRONBĂ—eKUk ›²,[?ùfÓvđ­,̉—!Ó@V"M}®}°©?đfr·~ZB#f-nÁÑ?Ơcv#Ü}†ÙíØr{QÊÈ·̀ÂL?øÖ@c«ÜA‘‰~‚OD»•dŸ/Đ¯8’ơ˜è¡4w8¼[´?¹cÈ>¶3ä2ư®WZ¨ïÜ=v2é,&̃¨ọ́øûåP>4â`€ÓƒSÏߨSy’wV’¬û~)¥¨½å¬/ˆLà¡NÀ©¹8Ïs½Ñ(v=₫VV‡ZPyRå‚́zkê“´˜₫yôX̃æ̀bȧ‚ÿf•;o“è~ I-in¢´Wr½´?;6<Ú²µ ƯƠóé“LNăêµåăÁ¯c{¹Ô¬Ñ}ˆàéñíºHlb$ˆjû̃ótó;­¬v\%†M:›±ÜHIÙ.k„ˆ<æ‚°ĐÓ$\–¥A…Ÿa„; xĐvYÂrQŒ:Y0“Ü ₫¿ƯöŒU^)²B#„€l¿…¶ê»ôº‰i>«\>=æ#ÑήS1ơ|e‹•±K ås› ÁD(2‡æ[Ù;aÀ„©ƒYR¦‹¨XnĂp)Wß!A¿æàđ¹¤?+%``ĂmÇ\*äéMQ*'¬ụ̈|i$Ç¥·3ÔˆHeç娔F—œ‡K¬ù^»éYg¦+´q…?¶bÆsh¿ÆđñQ »á ÄÉEŸo‡{ƒz+QL₫¶tĐ¥è0éY"¨¾8u:LL¬5™è]V? Ø’½¢FWO 4JiÉ_8c¦¤d„sT.J˜å-úÍy…¥©]“5#t‰Å^moqÙdí:âƠ]°‡|unÉä·cîT'°%t^T»–T!)úUÜÔåÔ‰$Î埘¾‰FæQ¡¶ºÊ4XDk‡đl¶‹Êbp‹FV#-*̃̃xä“KƯ‹áà¦+_fZKaÂ2¶ưEÿuG°öa‹@ú\²ÄêÎmâú8PgđƠxr§@7äÙÉD¿²Ù[8ç~„ÊOpQ)}måMû‡¸ø¢O—×4 ÉƠœ{üO_`åH¢~§@®™zKUHÁ¶vÊ¢ơZ»¼ §ưÖđ{¼VA€êÂÆ¼˜ß^wgnMK ÊxÖÇ µÛw†ë_8Ï3^»Đ嘳á9§¬ĂûJL€}.ă«`à ×X. UÚªĂ °[Ü¡†Pj “ïàĂÙqnÆä'ö/[X‹€CrË&´. Kó ”Bû dÖ‰LL¡³Ñ€‹]Ïf̉ôêøÏ€®?sö xw# F¯8÷èCÎKa™2°4!eĐË^­qL^=ÀÓ„B2äÄîÛöß;\µ3Ñ‚‚¢4Ău×óDă¼fÆ‚ñ˧ñ=ù ¹´é±Ø{û¹~RL^½eY‰aéÜWêí–ÆgE_2¼’đuÂQ…k¢ ›æŸÏ6ơnsø X jI¶è‚_0O¨M Ó{n²¶H¬Çw×]Ơë7ƠL ¦·V˜gºóCÔ€ö­p”¼™àÜ">?]_Í©ƒ¾_rØ4)k*ûÂ0Ơ»¤E!Ằ9†ÀĂ´•˜,и—º?³>”9i«HUª´…ˆÔÎ;q+ï"§ä4̣h½Û£h[À9ïÄu4ÖñípÊEíi&VGÛæáú@£«5ˆ¡p}óÛOơOë.¼/"ê+CM–‚6#ś(h°¦H¨àv½“åtiؽ{ù¿ç-oÜbHUwa²úáuºÑp»˜P[BÉÍZ%W×\Ơ•½ơs¬:û—'å tü93 ̀ÂâƠÙ¹Hd徸YWÆédpâƯ9KMÏøæŸíol(êˆóEƯHVh|r¯˜Ư~VX/;lZ{Së“?â‡o{ªT)ᢛ  Đí’å¨P4¼ç÷Ø_¹KË”0ĂBH¾́«ḾüXʳeCÏÿ !Óöƒƒüèg7)ùëü ÖÍ~M—ÜmkY©—’ܽ*Çu‹i»KSëŸ̉·åܳԘÑ•]+Ư¤+NFƯ/ŸÈ5°tgÔi–FÀ´F×>–¬»îO÷”=ßR•œÄrw_ÙeT‹ÚÛUóË‚CeL›Ư/ßÁâ]À”÷\Zƒ7KốȡѥáŒỤ̈P^¤w₫"Ô0àÛ®gñĂçÚ[Ôƒâ*U(ørúAÿ̉öÆ®[÷Y?Á‚aQôV úEvû’Èp+Ư›í˜HØB\”£Ñ̉p8$dơ’gv‘Ê9ˆ™G®xA·?î¯á<¾×¥*dHäƒuÉL§B®7̣¹·=ƯD¡/†ç'é8+è'v—‰ØË]/uá‡ZṬë}ú€p^Ù§÷ɺàK= º7[ƒX£ê$ïY ’€ˆ¾á}~|?G‹“=_+I¤t…Ñ“ưo‰OĂ#JAf¦êơ/W±îâBu+›ó\ĂkơùSW½ó—ó4¤\—:›ĂBÙ¾/¿ÙŒR;X 2#-T¯ª´P9<pF–:ñ?³¢?ØHæåKsĐå*Ÿí}ά¾£Áb—é₫}̃=bt< y#»‘8&ơÅ$2›¼Âv½øs| NPơ₫û†ưFK«sÉD•‹ ª₫̃íÏ  <·S”œ¯U¨)?4ä—¾×äd ƠƒÂNlMo I¼Ÿå‰°?/Y9̃₫¨0=˜³H[ËÎAô›1ɂ駦‰ưüd,U¦06œ÷ơĂZDÉÓïŸƯ8Ík­l…ÇlØ)Îă—kŸă³üºùù·± ¹ÊöÓ¨ ÎÜHåRƠïœf~%ßêùÉæ.#)ÜåF²“IÓæÜn6æ¶ËâGËW±,#@TcÇgB;ñF‹\ ¦Äq<ŸZ>0¢0jMÊÅ=ä»pœ÷à(4;ß’¹¡~|ÈËÆ›hQ”,̀¡ơ“Y~`ø„Iª=%P”¨̉Ëu8ûú½˜q~đƯeÀçëjâú*°ï›¸7Ù”"–G¸ÑÄgªí@÷Í€bÚû¼›á₫Áï§£B‡ç“ø Ô‘D›À [â®¶¤öu‚íÊ¡ûËH‘qvŸ_Prº—v.}‹#|©™¹0Á­ óÍ®ó’ óÓă¦) 鮇,ÉP©„jmÉöIh¯Ó±ƒTSרX À¾?Ôa›/ö7OuFỔ–üür7+²Ùè/-QưÅ̃øl¨Û¸ô+¶/g%!Y¤ ́´†‰»„ †åÛxa•O„œe=Åfô¥ñw[={LÇ…Ï›́TAôUû Ïh'è¯wưMÑ2¿đ !\NÑ÷̉T÷#²_zj"ö*z£÷ñ‘Ô]>¤Ă<}Ê”3êäïàŸvŒé‹ÍFêù₫­âêĂáwJ`ÙeÇNẒ  ɘM•üRd ơ-S¢°0 ë°í̉”J>SÚ„â3éß‘oœw¼x^¡%ÖüĂ›]ASù¼VÅkRw¸Râ„e8ï¶ à3”^K‘>{4ñ —7Û„r3Bÿé ³L̀÷}ºFM²̃ÔÆÁf ™ “́!\ !ÕOQo¯–NK#·ÓƠÓƯl#h»Rö2 cƠ¢:#Íè·P½â‡,̃º2ĂđJÿns=R ÙåÔ™lWVJ́ñו́)cEô» :w?ɰ7*˜ïE» u Ưz¹Q( r£¡a{<¹à́ M5£[íCw2“–vv¥¶e×Ô ¦ĂCƯÊ!ˆ43Tœ·Ÿk‡3g¹½Â¾óë`VACøơ”›YŵHÁ3£›Rœ-Â|µG ‡ö:đ¨_ƒ4ÙƠđ`‰m|äË„›IjOfî{ÈHị́Á¡éơ¦¢¸—i9ßIYGU8–í:e1đ­n¢Ú‚m₫µCĂO¶¼F‘†(wf»•=“h Ạ̀S@¶—çMUƠ@w g_¨ăVÆÙw_èè]¬¥ö¤gÚD Ị̈D©0XÁÚñu(…(™ éHJºÂ5)f é¦x ºĂæ)Û„;±†ơË9H–”<­Á–°ó(I†FÆB;º;ŒúdN n6%3—pƠÁ·¸úñNçúóV$4}E60y!ksŸDûøÏPŸĂ¢º>/v”i£§;ĐE¸ø3ïCưX²§ûB¾÷Q)#PKÍÏ?Yæ¯êu¶Ç^̣•¡«›̉7lϾî3YThWÎ1U¡Î@ÅÿQ%6Y—˜Cá]•m_ḾÛaÛÈÇ.T¾qaÁ<×¾‡oÁđ|²ËŒÔăS•Ư8˜œ4Uaöçü=\B"­|9)$U¡•§£¢§ön½|̀©»üRÑM¼te\-ú•EW7ITÅ:VY„‹S¯ĐT±*/Ç—8èç;¬Ú̃Oƒ‚ñ˜i©ÚjwX>²Ö5]Ảđͭ߯b^_̉̀p–̉ÔC¶¼×¼Àé Gd°á´QÚ[iJá3~¿Đ•jS¾ÏÖ¢-tËämzm„oƯüđ·‡:ñy¨‚ü®(BĐÉn[ß§1Gm급z»k0u¯ăXÂPûoä‡È›Í ˜L®!j–̃ŹæđiQ¼åæm‚-!å~¨fÍ´/OçƯ&¬̉—s/¥D~9tº|'âă‹9TÈ™~S³rà KÊ ¡¹ËÛá|Q×ơn·*cи—0ÊM„¦{¼©œåíj²ï³̣Ïb¿Ë£ñ¦¯K›Áå.}À¾‹1J ôXưÂÊg¨ˆ©B̉›­y÷KßKôjËëùĂkù÷I¿F«œ›ƯO>†y‘|ă·̉87 ¿'“Óm ¯ƯFU'µKîÿvïK-]öÈE¾‡Ơ—ÛÇjÛÂ:\w4œk’zÄ¡1_ü¥r“Ô¢Ơq]s©HL¤ÜÀWL?L˜Ưê_Àœ´öp|‹d//É=tfÿÔ=¢«đaKk‡wqoÔ3Ọ̈˜31t˜†Ç›M´¼CưeO÷Âp,‡\ `9±ØZh]ª[^äù ×à7Íb…q)l{se’̀ḿĂÈ>˜½´R¡á[|kåú£ù¾×=¦‡÷`wL1ńb¯Üjw°¹KD¯Eƒ^m‚Îé̀§f'₫ÍñkUν₫46öÓ¸ơtlÚhE eÑÂÂC¯¼)LŒl7U \Gº°Eh39c§EÔ¿«ơÙ|`++K”²·t&‹«Ï˜ZÛ0̃ixm§ÑÈôơ'ÂwÜgØ;Jon¯G5ƒó¨2„\·PMUY¿P–Ü ’÷‘¿}°(W̉ùjêå.Ø•c̀‰ÿ²îQÀe¹³–x4|3>íµËèĐ½Jءɛ¿€ÛN !غͼgŒŒ. Aùô Ó é¨¯ˆƠ[xEß3 Ạ́OpœXø$‰„B@—K™RúUđdÜÙå•áïư’ÖÁr±;¼½NªÅ" ï¦zùM–¤NKú•;Ñ́ÇŒ¬Y% KĐ…¯¬"72ŒÓ¶ }]ö]|\ t÷A~´`øHUE#̉fÑâêÇr6Åø5*vÖtm…Đ{ˆÀßÇ(ÅÉ8ÆSI樂Cï©}´`˜µ &öaBÀUµWÿ*Ê©±“Ơ‚fŒăi`̀üĂácFÛq̉›‘‹̣đ ,Øç£%Yༀ3ÑÆ-ø¤·Å¨ƒS" Q«i Ûơ˜p•; çĂ“åˆ}Á¬ÎÈêóP8Î`!5ñm³.ZK™ ÷¥×V­¢ÿBwH‚rWD›¢êüéÙ­ÏŸÎhÿÇIÉäv½SÀúø<„™` à¤ïÇKÜ 7töWùƒơ₫–vªiëlÇhÓs‚“tF^Ü;jÚr&*ƒüFÖµFcíÅă«Á¥—ï̃0¿\x5 ÖgI£º ô–?>_³¢æ7K%^ưŒÚÉ zYeƒ9Äö ‘7\‹JDÅ̉z+« êö­ƒ„³jñÅoỄù¿uœEî586bÿ»1ùwy*[u$½ ï¶Vÿyo[+’ÑíĐ à5½psˆ(€›û^Vº“0/H0²•OôDbûί•²;ÀIl—±Đï⌂S嬩Í0a½pâ¬Öƒö†xJøÀmæ₫Y½GÁ¾._2]åS}́¨D-%K…Ák_ükæ×N«Ô}v|3xI™8¼4ư‚ṆUê½Mduoy« y¦Qpæ A”6„ạ́Às¹èº$ñx1%Ë=8Y¹N4Í3§>¿¦ØY57wÉ@Ûë'óΡoˆöÅ9Û$U¨ó`¡6Ak¯V}×­_ÍbËă¸áË8¡nÖ|H¸Êít¨q»†órù÷ĂGM«ûÓ1+ƠHƯÓàÄb¶cĂ‹Q÷£ ưCuÔc Âñsçæ§-‡üăñP‹BçX́…*‡`#[Ḯ35ÂJY»1đN‘`r¦ë3>6n )C;¶ƒ…;ƠŸJˆåSrß,µ63™¤”[bM³¯ÔA„¼äñ%ø*ZwAQ& ølA¨9» ˜8oâIÚŒ–yHüÉ.RY¦m^Ëj»Ic¶Ÿc_¢Øm/d̉é±íŒê§<öa µûÑ™ô8n4ØÊ/̀É]k‡"R2E_8³äöM^ÿÚ&vó ˆÖă²Qư»™´C̉¶7(… ¨Đé&q¹Í±úûêÆª"÷‰ÜŒ™ưÈ@FÏÅÀ§&óyΏ¹çTÖ4k‘kÀÀk×’‡]̃ËÑ“¢6yƯ@§ Ä2W¥+o^ù:Œêô憮lØ2ÛÆÚ9›ÚÓ¶|3%¼ Z‘È7†áY<R>€ºª±a¸ë®Ơ¾ßŸ+n¶̣`«2'tÉ&?ị|hO Œv€•¸xÄHË,Ioë¼›‘ă>Cøå¡•(ƒ9X[.́̉-ײ)âNÙ´Ô¥Á~prw:Ơ¸‰¼¦a`W/ÛƒVFïÛ A ?6Œ_zXQ>kÓû‹}Êúƒơă-ÄuÊYæ5SB¡MóÈA‘0²E[,èCuyâ”Í×§Đ!_¢q”́” ¡Ơä åÅàÂ7„KhGMÄ́&ô¬‰kÉji/Á¾´åÄè¸h4SµÚSXͯ7 %wBÚ™n~.1»#ѱº+Sqîö»Á”¦I1”´€ÛÎBé%/ÎEߟ¼ZÄÅmUß̃<ÈæÀ†­•ÅÀíơ»ÿ€Ö¬Aº<ÅÇè3 $B•u|D:&¯•= [ jÏÀɾƒz#¡ƒ”ÑÈç8­Ós¨èÓđCyM|ÆÚ#/2M‚ÖæŸÉƠ,ÿ8­z¢ˆ‘›Ó­·gk–„ßD#Îf{‘ßúëeÄ—6ưû•ŸÔó́…̣¼ àin>}+́/µ¹$QÂ6L)W#™X–'1¾¯×yæu9Xa:iô3Ư 2­Áó½^ú í×_ "Kê£o”~’dåŸÄú;ú[³r÷oÔÙeü"¹Áje…ëÜ¿¥’'ÑØX&~̉ q’Ï‘¶à̉ïÿ8${SÛ Ú³1Üßp‡ ĐêưKª^Yd¹W~Ïúë创§ªœ) Rîyó .¼ªh8«J íCK~::ks(ª“i¢ôú5Üñ«ăëi 2æ– ‚ºơL+’U”Ïî¸i¢M QËZÜ̉{ uxˆ¡¿2’½—¤˜Éâx€1" ¨s†‚6»µE₫đÆ%,1kYF€gÀ&Í«%Åx̣9Ù‰ øˆ_ùÄƠ HĂŒ]Ơ´6¯̀fÚåíK¿XÍr•ƯoNwŽgR褘Á!ÿqaEyœ&]Ö†Ơ{cƒZáĂ`vá¥ÓÖR"è…3P'[ íç“ ¾LÔđo^†|½Ư3P¶¿,CçL™NĂ…‹í¾đGđ§ ¹È´ÁÉ}+ó»€ƯjT›©:Q~éç—( PrÏ4œµl¸Nê¾W‘æRï½qæE¨ư©%G¼j‚¬+1%ˆxÿhÑÜç¦ÑåøÛhÿă·Yàa¯“¾ĂëAíg¾¯Ú¸VwáăK‘‹‰£ú¾ú¢ù-Ÿ­ º¿eˆ™Uo€.‚̀Gqđ®%EƠ[¶êRܯÖùÍS6C 1À’º×óœuÈ;Ü̃ÙÈÿÂ9¶ƒơôôvD‡ÎDĐ^'₫©CÅ®*ÍPa#&ÙûƒE&‹$¯Â¦Ï7±Ä%ߥ”6ôt)|̣¡Æ É6ơh.×êÈbóGu°@¼±‹ƠIß®°Ëæ~u’°cÁo[~Ü÷)ưŸ oôh4ô‰h!= 7™­Vfcøï•;’§¹}}7®è"Ă¼Uɶ¾ÁÁ'§º©C&æ#=ZÅơ¦÷j8Œñ7́àÇâKâ®à‘e([É„µL{̀c~ÓQọ̈FưÙDĐF¾₫Q­Ï¼ïMVT.f̀ÜâÄDvÿ7Mt̀ `©•óWÁ‡ÏÀ,Á¶‹¹ø¶Y¾cÂâŸ̉é=©–S¼̃9|…NE7ó±=jöÊ4¥sNJÑ`}äÚÔăZöHƠ/ÂSû8#æä‚ Đ,¶)#ª“×$±Lk 4¹–4v-´j‚7ùíO¼5‘¥C"ăá¸u5¡ÈNäơîçü9¨ ‹cŸIfç=£óP½Aó+̀ÿă#ÙêCι°đ|Hiö₫]́ỦI]Í‚­!uÁŒǛŒđ™U$w`†h°ls˜*­®m•ûÜÍáE ̉ d8*7ùyWijÔđo+wï!­eD¦¬Í&ƒ»”¾`¿¦O5÷fUJØ•H3„ǃŸ½Ư .ÑIjVQ¦T1¡XØKîCC Øb°,i颯n 4ë7U³œ…‘Vè$Û’Œ3 @͆ƠV=î ˆ —ÆƯÍød.̀­P:׀ʨ'cK©Ú– ÿ }˜ÍÈG¶0%ÆIP>V—ưÄL;2¶êK ªà:˜đç‚!¯A(l#h¼Ül!̣QRợÖ‘f±C‚¥Ư¾úơƯ2‚^₫d’ÛÜíB4>V.O~´Œø÷@»ÍW%}rU¤5đ}àhµ;éú/¦§¼#az₫0äKp₫Ÿ[w˜¤hNª:½” ̃†·„>:î­â*ÁùóS¢L²J—B”˜ẹ̀V,ùlj±!J£p›_@qJÍ 7g¨à‘nS³₫á`,!. vă95“1Z¸ùÉs,₫>­ ă%)åÏPÉ̃‰ă™ƯßjÇỏ}UbÓ°yÊ«cÓ¦Ô;ØGà‡Øé‘»%v_ ¼Ko ­̀qÙBû^ª3µÍµ³âû–M$ʬç¦À´Ê¦úæùbÉ0Ï®á÷¼öQ̣=¶–yË* hal>Ï÷;ͦˆíEÊB©eŒá-d~Lv¯ ê1M‚S₫4 ̉ÙTWVƒ2w¹‘í±ß^·*8ÀYu*à>"«Æ —©<ÍϸP² F Uj<²„qÑƯ î{Ÿđ èµ:EÉU)¹¾ƒ~£$²À|:>́c÷à\–Œb±-AºÀαJA>K×O|gơYKÙ™T¨2|Á x^K_ºD_@a×hCưđ˜é\åư÷­²0ÿ0úmΪÑAÙ4 WÀ»åO¹’nÿà4ç+¨Ó½RÁỵ̈÷Ú//T¿í ÚH™­d©ÉÍeÔ»*Œˆ,J…ͶNï¼¾q’Ëeh”ÖÁâ Ü<¾„ÀVÓwL}¶¢ôw¨¥”„ƯÇ÷’I;^Xgö?’‚D¼qTÖèb¢óaM¤V]*!xbüÑ®ÙoNsNµGüëfă%s©đ ơ!Ÿ³gG»<&w/‡?¡Xƒ»;e7“ßW[¥<Ï8G´-¢®"/Óªe—û¶º‡røÎo˜Bp·ÿ6‹o(8¨¶¯µDcµÉvk;nª]ë…˜`û¶‚&æ‘ñBôî’ ¥Œ4! ¬1[ƯwÆŸ%Q8óÜüà/±?²₫ÿËb₫·KÜbdáu†=Ö¾Z«îx½4ˆÅ]ˆºG?̉ẮQæu ¼'^Ôé)—ä62Álˆ8OX$öw#×D3ƯV±Ö¯æÿg1™ŸY"$!‚₫ æ¹Jª_PÙ}c]|#Că®)[9ÂMbû.];s¸ع&B*N.ØCèjÚå¹axôH‹Ă±úÖØˆQ\-kñ¼jCbu6V_¼45i†Ăß—tÿÍ}-k%éÎx°ÛúÀM~úoVô²µ)k* ¤J:^÷Ơ‰Ç´Ê‚»»…ù¼ªù ´ H¥â¶;»P…ÅÊ€æĂq&ëû‡‹¸̃øÂà?§ơ#"n„¯“ËJ|±¸Tđ₫K'(x­/+áH8å@̣y Q¡˜1ưƒö'×X‘üœVè¹µHóœüơ§đ$èë. ’ƠÏ æ‹ø̉Íè¿WÅvÀñ[…p ƯX?#Un.dË"Đ@m°è˜Ë‘½‹–‡Ư[&å%¡ư¯̉ÿ#Ç$dQ-7_°­ĐʻűÄwé÷¾Ü¢?Đ<8#°$uå@qĂL4 >Å¢¿D´M%å‘v+ùWẼ”áªÑ˺d¶çt›N¥f(_5„;Jè$́Ѽ…ŸW´úü~ưïK%‰4²cc>˜`¹6ÀÂE`U=É÷;€§æơ^+ îd;*ụ°Ư \@ZÖU‚W– ˜º—WË÷¿\ê'®^Åî¾>RM²ªv~så>}ÉoM†¯çÁ­u=Oâ¦f&©å¯éQjûpÅĂ5ÅzOvYöN­=ªK&uö¶f[±ø_Ë%SLbî&ö¬µÈ?xÛ/qăa‹€Æỷ›„˜P|dth­s©$5guƯÇ6 èM 0^đ–q¢¶$³ƒº‡&A?Y‚@ ÎúñĂ›»àâæ£GÜÖ [¥PÎâưžñס̀N®×+ÓȰÆƠæØ¼0Ycü…£xq¹]GMUüm†èhN3ëA"LÁ]‘牉å]Z2»ª ¡Ç–e^zÇbw†)̀¸Ä¡â€T•!„ ¡{<̃ P(Ïs"®àº %mÿ(!Ï4·ë‹C@ásî*;aÀ" -PßyP•Ø•œ•|ưoƒ›9¡Øy4Ơ+Q¤rxeú̀ºÍP;•·‚¡Çùj“‘QC^̀4ˆúN@đTÏ5iï½Îqk…ưKơUĐO`÷ZÖ€̃ 2StÀHp)d¶ưhÔN^3̃Yµ"È®úÀü_°sŸ[ơP½]¦Vxư¼ǃĂ%j:'IwoOKn†ÖΠ´5z3Cç¬"̃¿p§‹F èÑLăÜ…À::2‚ùÑ…à$äè~Ư¡Ü"Ê5LÊ^ÀúÚ‡ bà«GúQœ‘"U1ñ>6¯®®Ö6z+7]̀Æù¾«pyûê¼cÎ"ŒÙ% ‘®´ư¨”̃á¦V'̣RÜo•äT׋ tÓxåÅrÅÚ1ú5kçä+U³ª¡s†"XéQ‚‹ïm*ǜχưú¢QÚxH<%Çk¹ÖrG‘h5)µ.ûfª¦çlÂcQp¦ù¢V\I{—™eUU¤À‰ ̉2UNè,²W|T.Ỵ̈ÊI©,#v.1Ă-'Ñ0øp&P1ƯÏ}ưns ¡Ô¨·Ô @ătÆƯô_\ 5súg[àˆµR₫Ad"¯¬Ù3ư“`e¬VD¥<¶±X¤rFç}™¬"ä¦èZtÿŒ(’pc¬ÊµPˆ™ ÛeüNÀ;Ơ§¦|NỵB1PM­₫mty×qf··‹X:Og ®óƠÏNѱ36¸…Ë.̃r‰« endstream endobj 1353 0 obj << /Length1 1952 /Length2 13819 /Length3 0 /Length 15022 /Filter /FlateDecode >> stream xÚûeTÜẸ̈€ ,hp‡0¸»»»»;ƒ»; îîînÁ‚»Kpw ~ÙrÎ̃çÿ¾kƯ»f­™ßSU]]Ơ]Ơ=óaHä•hŒm ¢¶6N4 ´ôœ!%iz==-==# ‰²¹“đ?rU ƒ£¹­ ç¿,„€N2a§C[€¤³€ ÀÀÊÉÀÆIO`¤§çø¡­'@ØÀÅÜ C ´µ:ÂÙÚ¹;˜›9}̀óŸG¹€ƒƒúÏák ƒ¹‘ @ÆÀÉ hư1£‘@ÉÖÈèä₫?.ȹ͜œ́8éè\]]i ¬imLy)¨®æNfE #ĐÁh ø#e€¬5đïÔhaHÊfæ)”lMœ\ €€•¹ĐÆñcˆ³1Đđ1;@IB g´ùËXú/jÀß‹` eø¯»¿GÿáÈÜæÏÁFF¶Öv6îæ6¦s+ @NTÖÉ͉``cü‡¡•£íÇxs+Ăƒ?C7ˆ ( >2ü;?G#s;'GZGs«?r¤ûĂÍÇ2‹Ø ÙZ[mœa₫ˆOØÜhô±îîto®¥­«çÈÄÜÆØä4ŒíèTl̀íÂÛ|ˆ`₫‘™,ôôôĺ =èfdF÷ÇÊîvÀ?• ˆ?rđö´³µ˜|¤ô67~|Àx:¸NÎ@oÏ+₫—`ÆæFNC ©¹ ̀?̃?Ä@“¿øcÿ̀ƯZôåÇ ÿăơß' 3¶µ±rÿÇüÏ-¦SĐÔ— ú;åÿ*mƯ4¬ŒFz#€íăÁûưȘÿÇ¿ÆJؘØ8₫ ÷c₫²Ëß5@₫wƒP₫×—¬íGåäÿº6= ½ÑÇĂÿçrÿsÈÿ¿*ÿĂËÿk¡ÿ߈D­¬₫Ô“ÿeđÿ£7°6·rÿÛâ£r>º@Æö£l₫¯©đ¯Ö•›;[ÿ_­„“ÁG7ؘ~T4 -3ë_bsGQs7 ±¼¹“‘Ù_Eó—\åv³2·ÊÛ:ÿqÀhèéÿî£ÇŒ,?ÇÊüSüh¡ÿVÄÆÈÖø^cda88¸Ă|lơ±<>̉èög-èhml>†>Rô˜Ø:Àü±¯¬,:?D+€NđbĐ ÿ—Ø>Hö¿ÄN “ÿ‡˜tÊÿЇO•èçꉃ @gđ}ø4ü‡8tFÿ%æŸG‰ơ?Ö¬ñ¿@ü2èL₫…L:Óá‡;³áGŒæÿ -₫…QZ₫ ?´ú~Äiư~´Í¿đ#*Û²ø°ư¸₫¥₫ˆ̉îơǼv½`û¯´>î:ûÿ"Ó‡{gÛªü³ø₫±úÈÇá_ø‘ă¿đĂï?ÆÅCçäjû/ơG~ÎÿÂü\₫…Sº₫ƒŒ£Ư₫…ù¹ÿ ?̣ñøÿ§.œ>Îè?Ï¢ưÿy!n@#˜å[#®@‹ºÀöß58®4{Œ̀đƒ×a·Pj»"X. ₫BÜ7LùáKƯsûá›È'Œ%ïÍ–êèô–º¿¼RĂ9Ñ—Ú!L w¨½¦yN¥÷¥ºº4ơ™lŒMÑ/~(₫t½åŸ¥À ¶¿Ú›Ï8ă&ưQơPivñ™¬é”t"2ü3&;;h`‡@FG•`­À́\§±ă5ÿÄY<èÑcêÀ(#ËöàJơ'ó­Tœăcx;©ÛŒc̃”Ă^Vl)ư)À,Én¯æs ¹ÿm{à7rCÇ1%>"®L‰Ư©kñëóLơÄ÷éèGijDØ2]›…6u9)Ôn¦]™XËđ‹´!qækEưyp(¹{Ö₫uN‹£ï7N:Í`^Lð­ư|*Ơ dj₫M3«̣32•%æÉat tØ`đAÅ KÜ•Ă¥Ú'-6C¶1U÷î€ZböK<=¼÷«P9$(_xó&́<øÔbÙ¦Ä`x$&Pb£ÑÁ[ ñ ‚Qe-àüâ{S½NͯlSDà´viC+>$áw7xä₫AŸ6½æi‡…g[{+ºA~ó:ĂÖOy›«ï½Ç%;ƒ@5*mÎW gŸ̃{,ÅfS·(çßçk£Å;£7ªs¦g@\“½Á̃Œ\¹‡²Nv™i¶°4Eỳo­VL'á 冾̀ü3­vđ,ߨ́ ¿q2+YZ5:Îdyûrr¿:̀\`SHŒ₫.ă¯´¬KKC €ÊÛß&hÎêxá]»£~3À0€1óV¾ăƯ«?$ø|Èô}~dmuî@ỴÁÉ%Ư³̣`€̣ó ^$ç¬ÇúYåû×WăzÏj÷ôYшm¾ôŒ;`€̃²ÛM,Â÷ă¸&Ö:E/u5Iz4l:ƯḷaÔ«¢ÙñAg©,@“<Ô0È혙¢¨®°üCïºËizñ+ûí¥’Øá!²˜4[¡<Œ/̀º˜Y²’ƒü0ÊßuY_•rØs¾E¢G+‡—OÁñ:ÚE@«•ÑÄŸLŰßd ^8¢‡Ư/̣ aDô‹èD»Ê¾Z :6Ói µ€Ï¿Á>ẤÚTƒ ǹ™ÔW ƒ›eB‘ÏÚ’Œ<^Œ|¯$`MEjäû¹®™: cN•ê0¯œ¹d<Ÿ8”*y.Vp̣½Dtơܦ) SG8n.²Ç@Aü¨}{ nƒå\„đø{*~os×Î\D@£1s!p%°(Dc™È¶G"ä<4m?6'¿ ôk—ó_6́Få̀bßä&¾Ÿ -§Ú¦¿Tzçă[½ QêE:W)lÙôúVK+ÛÁöǛv —ÚœơrÀéo«o„íwĂKYe4 `*́Kó3Â₫%!ăKç/ˆ›Ü)Ù”í,Ѷ²$¨ÜЧ¶óß`»¥VÔ¿D´ú̉ g±ëeékB`¾é Đ?év=bÀ†ØX÷i$a›F%.$n¯5¿A³øÆœª¥MvoÇû mܯ¤+¼₫úRfÛ]Ák ø„đ‚‡êpî(:§³Plœ˜ñ ö›‡êR;̉‹Ă.>©VA¦ÏÍƯhtïdo°d×ÑÄ¿”.¬ïœĂùØ¡ÀeZ“ˆ¯È¥Ù ́èĂhtjmD¢¶Y`ßo'W8:B:NJgˆP Iªs$ḉgï¥ÅL‚:ΩbOđ̣ÛpgëQ®ŒªPz^*lØä¬₫ßK0Q¤já»)+–FÅ|-È1ç¶E§!\†Z•½$uÚëƠfYăƯÆØ5wÜê!8pZH¼Y¥\ëc“Ÿ "„±¡Ÿa/eÄ"ÜÈm!/>[µ¦(×/t€*V6ù¡¨.Q÷‹¿Çsw¥ƒ;Úl§) ̉^]½Z3DkDékâßP°¢÷.Ûè=ÎLªv¾̉MûÖÅ{pLY2§=Ok?Oc1iä•ĂLÁK‚ñ¨}yur<°…vÀ sßX¥Œi×%|4Ăà½l$½Ó<[˜ÖWœáLÜ;gv]Î0»ª¢ÑÏX¤™>÷P;Ó«̉̉A•·úÚ¼ÆưæS‹Z‰oP+”`1Qù-̀µ›¿•Æö‚áËJ…a-™ÑĂcÂ⹫[Œúå=ớƠ€'7äbÙôŒ P¿Û7£ N~Ô¿‚*_±©üD,Œ2NƯL£Dà`+"ü.çå“®¹å¼À¤ú›Qa†hGÇÖ₫I²,Íá©T$bû Aîd̃ÏODU”XöÜÇÀỲ2×·@jO稯h?ÍÁiàQaZ,51¥4á5J5̃YÙ£¦|BÅYân•k°›ŒQ‰„ŸO 5Ü)~å₫4†çªßîÛBưVn¬k–’Ø‹ǹÎÇJ¶ê‘ –̣xưñµ}ăeBפx1€³zæ¬:è(­Û₫—áˆÑK VSñZ #N~—{™̃!NpêK½ü²ïˆËMÁ¦7V9V{¿<'°7jSÇơæ(®|Ô-L¡ư Ø©D(Ém7„É9®l‘ơ€åº9D¯ø>ăôÊ ÿ¤³<•[ècX Ü¿L< [¿B×đ’t†“B…³wÇ ßuöl×ø|j¸ir•¾¤°4u4=ª…É„?'Á3}f|;I#ˆ¼ºá f£–ÇÎß³̉‘]Æ=‡̀ÓÜŒs XÔÑ.¼ƠÊYpđ¸` ñDç&ƒ§ä_ñ:ÀØ7}ïí>Gÿa<ƠoLoXK‡»Á·ñ ÜimÈu~~À£ª¾Ú4Ö‚BÄÑ̀Åjó±U¼5X¨ÊÙ6ÜËínËdr:1 §<Á Øß qÔ™´†=ªôCö¥ë‹Ù,«w¦¦›%h_ Î)ÔgQÿT3]1‘\¬Bá@ü,åÍTù_¤uƯ₫UéüĐăïKÆö#PÇVØ_EØ€$c¼¨éĐisa´…<Ơe-ªµ‰æ¥rN ­M»4Ù3(- ₫`?ÎB×îưB,r̀ü¾ˆ²æ̣/y‘™á Í¥d<ªSÑ8•™™t¢Ü´SáÆù©ÏaÑA—ån˜¹¼î{G§ÄcÓÖå¬}ê?=ô´̉°¨vB×Ñ q|³å*M0:ߢ¨IA‰Ø«p×&l’¸×zÓI0FaÜÚ]ŒV=iHzœ$lö|å[Eå:`úêˆÊ*°́œÂ«g ẁ¢Xíåµ<‡ëÜtàÏ×~~6_j૾̣ ’Úï¼çúÏæ=°“N¬Å|47/u6“wưj!Öœàjé*§*Ạ̈@9‹Påï{ỜœûIZ"PÔºƠ!9₫vPçgº„¯¥»ÇRû¦ ”>ûAYn<êÉ$ñ YĂqtó™âôsœĂ%JJM"Ïy[19Oˆ ±™êA=µÈĂ)%±¹ÙŸp4>á ²ƠF̣Í&4^ cêï‚ư%ă‚y2S_R0È÷‡:' Â=̣1#Ö=p–¥@G¿u~«ë`ÁÍnê—ÑRâç^ V%&Æ&ơAÆg‘À‹“¿{Œ™¤æ9ßôÍeN »Ưb—uà_ú8=ÙïS·o‹H÷‡„Nß&!?ưä ˜‡Ăoeqê²tÀn5VÖƠËPñΤc5\•ó…å*²ÊœL&­CK}xwEB¥̣t/£•3°Fªîr»˜j…ÄZ´ÑZB)EXR§†ư.÷Àú²€ù~’r@¶KÊ/ư+àr¤ª‡CÎÙ­0?Ø‚öƯû¦ÊÓÖr%këæ”ËeèÊ¥ñ37Vj¹%F̀kúH†SC!ăáL‘_Í”]]₫ÄxáÈưµ¸Ëưî/"’A&-G¹eT¢˜ÏÄât\äœ;êné0t"Éde;>tp6ŒÓßsúøÔª¢ —£- ë́ñ-§AL]aZœ_bóàâÂ^/ưG0ÇG¹x|u¦/púÖ¬ù%4^Æ3s¼z²NA[3¥Ï_i2t®Àó¥)bvÎÎ$ˆ0 yfn#Öx®#«—mRGOÆJPŸå(…Vlâê°99æË®=ú ßN¦FR™½Ñ®b%>oM&gZ™ĂAøâQiNsåA”YÑ„Úî{'Y¿'ß&0ùÛÖæû~Nv(GcµÜp |¯^íØt÷0”¹\tGÛ›í˸µaù’)¡ûéû+b jr ºªvbµÀ ÅŒqœ¥)ơªu÷ˆ*~&Ú¶•›¹Nơ#yá>da“oöWëvû*Æ\8 ‚ªeÇ̃A ä‰Úq̀´̃±öƒøy©(¯B p%È3Ê:ªYoVϧx₫Ë·{“ ù!í™Ç“¸ªA/[ sä…srPKX­5 DHg5·?Ù^FWr¸zÍ)®\ºAè1í~çØê‚Z¨fÅΧʛÛhÙÿ0Ă®×^Đ¾YA₫CÁ_SN'+¶Rhc#­g₫üaWµ€‹ 9s$´”Óï3₫'w6/¦Oê°¿ g³Ï—»¾Óôo₫ qgƒöpåU¡̣h’: úÊl„Ï|Đ³rªïX̀3Ç»hs.Z,6838®°Å·ơT~T‹ÜµB8:nqÊ5Nz$Rơ₫I…aOÇÚd*ç£îYv‹‡Rcx7>Ă­Cà70óÛôáM&>§Á'̃/ï‰ íơ'Ql´I—PƠO™ÄXçYúüe’‘Må«×·“[„f²á1ƒÏ³W0v@벩\ ¿X’Kqu¹]ùË7›&™ă@µơOË»«µc #ï¢^ư¯ é>µ¢?í‘ ă‘Ö%1â%‚|û¹8+¿:%·`f9NÅzMóö¶Ó¥¶r;å7×—¯räYÔ%H°M₫†GÚó\råê”±D{áÜ£®Ú–)/ôY1™ÂD>&l¦ ¹~í•ÅÚb+Œ¨oWÁëO¹ †¯iJµëv‡{χc˜̉g&a­5[ TcÂ#°ØÆóÍÚάÏ¿8B•\¥ÔߘÆXIB–›̃S©]RUƠñØKe½Ä”»±N­ÔGơ¸á́ÂT¾ÑĂ3ÍÑƯµQdbăoÜs'@BË[4±º Ä+É‚@tp”Á&ÇF¨zîD`;ßÜœf WGüª£„Ë9d́¨íäÆưmEĆñTO_g(&' ;ƒˆ†+µ ©[Ñlhyz‘΅đ̃"\„Åđ„Ñ/SgÄ üÓ9o"icïn ß:ă¡¤Æ¼åi\tüWỜAñêœb NI₫%Á”À6}‘uÁo>Y†̉ï₫ÓpLß*üÎ[o[Ư”æ¾1Æ)^Χ¬¡=eT•ṕßLNYÍđüXFÓ6–-]¡ehặz#@#/«gcÚM–ä‡óÔ ô¸ç£äè¸Đ’© –Nk9UsÓ—g=W¤—WÜ! È›ÜX¤}ú YHS¡êP9s}.º5ăÄœß_IÈ™ºúhäQ`Ô§VĐ[íQx—x!7Ú©0 ÏIFuĂ fmióc\Úâ‡QQ¦½cÏÖJ±Qª%¤Ă_#f÷¯GaM9¾̃Œ³bX;ÖC‰ô䣾p¾ï·O{• ¨ ¨‰ú.ZßĐ#©çYoµ¤Ü1-₫f‡:ÖuH’•ù>& ¢¯¸Üux]€/zF¢îÃt>mv&Atؘ0f[)ÅLNă< ¶."©JP$P÷”z®O-¼éfY×¼|=;6©\À̀懷b²aÆĂG C¶0KiƒŒ­®Ô••¨.£Ê¬Ü†ß(ôÈñ.÷7JPÁfĐÙrÅl,‘ÅÑç1C´Î¸Ç9&̃d>ï­TÅ'ÉdϾv„])¹ñ#—́@¯)ï@K~ê®» i)’Ạ½ ¯w}FüÎbñû˜Ç¿ơf›e}*ä3aS gAÄ^«đè:(¹US«Ăj´×ă]4¬ü*hC”µ—ÓØtÜA/Ø%Ă)ˆu>J‡c5ĂđL‡Q÷Óm¬'doÑ"Dƒä!’9áÉÜê;„n1dn'†<¼«ƠưRĆô{±L.đ¨Ê5^:è9N˜É®ÿ'z&,ƒyb·—DZ²Jغø ;’‰–Ú%ÏΤ³Œ…ù F¢hä’1đ7†¦j•™Ü"=ü÷’•çÇ€s&îW…Ơ.ZĐƯFñv9+v̉₫ïƯè²5BÚÄè?XHa¦¿Ïi´?jÑD¿œÆ¨ $oMÉGeCçé·©rnú %µØAÉå<¤£ñƠMµĽU"R‰₫ÎcB»O×ơL±ÅĂ¥}Í[(«éœZÈ”kE–«™áĂ4÷wbT$Ûëøj¸ÿs7‹Ú₫ÇVJÄ3h8¤£r¢¥‡d` ÆŒ‘ư ̃‰>C§ûLÜè0³xEÊq E– “œçk!́üĐÂ;ùhE•b¬nÆ>Ñ~4Oχ|ƒÎ€2¦uÀOŒ/§¼+÷Ö“7~Öă8²æ¶ù#):í÷í¿oÙ·‘p2áK÷cE £ý›§ù]j4ƒFaƠ©Ër‰Ä~´¦)ºï(/‘ܸȰ̀ăŸ‰Á!¿|ÏÜÉmaUÛ§³P,°Ûµ’2!å7†‰ÔÍ-ỔëÏ̉MÓø‰¡˜çfd̉¬¾S¿¨‰€ûôf—,r+w¼*P?e>³qÜôÓu°¿RÖµĂs"ϽVƠ8Em£Îcô£™€âÄqÖh˜åd»ñ5lèêËçj3å›P­ø¯í•RA"Ç$‘B½€x¤ L¾ƒÎ- É7Íå[̉¯"ƠÍăơ[ú3‹¦8—ă²́ Ù«k­Ú©9M"“K‰¥ÛCGnÉßB:bSd¨‰««%f“„Xđ2s])²ØL½híc©ÓN ’\ṃă[T*ƯI!7Kå§>f°§pêÜrJÊËu¾Çÿ‚Ëf₫Ù•Vỵ»«»¤ü3€Ö‡à§­Ä¥%÷éÉeüÙÈæ „Å"2åd»Z‘èówYD[6ÿá;²´,/Ó´O;ñ¾GUgô7Ă%ç¤Ä*¬Ö‹sê xNa0Ø¢hT—!É !RaẸ́+yhµY“½ ë,¼ß›ƒû²ñi!,q›œÆâr¥|µ”²‘4Rù! ¼UưÜœœ›ùÚ§`.á}Ưº¨KƯáP?n|Ç3åëÇ[F—³Få9’ê.åo—’Ư0 ŸĂ5ÏJ;3RƯâÍæXd¹4§Œư¦…áSµÇ˧›@Ÿ èÑ)in—ÖaÖ´.¾Á×̉¨¤QZPÓzhWnºaëè_2‘ăù6mœÜkº!Ñ `T™ßßÁ"Ë/.̀qJBW×Gï¶Ääé˜h3q‹Ê@½d–tÍ—!è#Êvµ[}ƯmV/ ‚^NºƠÄ ₫9•ùëvA½voaçù‰’gñçû4͵U€äö— ăèH́”3á!1±]ă¸ß¸@G©ñ³ƠxI[ ²“# )Êj$||ñ/¼¼—HH]y×XB fˆÁB¯=~ß§U4<í˱k ,Z¬…Z»jí àBÔí¯c:¢îKÚHBI~ÆUŒ± §¡À €Ă­|3Đ.żÏ͹êköŸ–©üŒ‹†OÓÊ©ơ*È—¶ñ¹q¾ö̀§d8ùtZ“—ëI)… d5¨’h8y:Zæ”|gΪ¤–6ôâ}hV€”!Ù×Â{ñóđd\}Ä!ÈƠrUøë=Û ¾eYEa>²Enô)w ¶ó­Ÿpj¸nIHƠ­„x L]´öÁ­ ÏṢ§¾K«æ”«8E›D“=¾r§£ôv}„Wÿ=y1.â—&Ṽ<Đ÷¸¾́°´„où±h yÁàđåߤі^NA÷3IªÑ<î°̣JM­'Œ86Ạ̀CPjƠ&8G‹¤1M$¬¬vĩ@uÈ"×g…íßO}³ë6Ù–øÎ_-á«ÿ̃3…wL™̣4_ÛQ½¦b~ô"›ñfÚu4h́4¦< €ºI°~èîßê„H€¨»>F˜,S„¦øÈpơe7ƠQ4`Áf̃œ±œ¯¬Ôz27Al±wŒđkú»iÿÈƠÚyt5­ê¹¹ç=³¼upƒ/+TỘˆƒôngf)¥‰ĂÅîDëíØŒâɶS?éíëgÿø}®üÎZí7ù½Z{kơætÿ…´Ü…˜ÄĂ~}{3öBøu–²/Áú¯Zv:W¡Wh›eÈ«˜M7|vμHf̃ZJç“>)Œ§8¢Èl;»^fNooLx0/E“ÙxVÂà*h,îÔŸ,½¬iÂÙÚGäR¥'I~0-$¤V`ˆi©*è‡íRx§%ŒrÄzĐ—Q5ûº´VóÚfج®\Ü—‚N‹7<¿+3ÚËMom¸‰ Q}Eøb&ri[(Â,F@ܫڣü̉óæäF÷*×0ƒ%‚AjKˆ5o]…œÑ“ Î4k&J#*î ÊY¸_Ÿ}KéÈ|( ó<%å,ÎÏ<:+6†«À/₫¦¨~NÖ ßcxgG±è?±J]=­qYôĐèl—.ôI÷̀s#—)Ăz.êÛNoÊ%ù<Öxç¥é ¾._Đzk›ưçñ<"¡ú Hÿ̉ËìƠT¡¹{gáÁkodüä§!^Mûï´² ßMæÂj…p_óˬ៉¼”$]å÷dÛ0ÓA-£ˆúU¾L(j%3'Xâ³p>{öØ-LN›x ¯’Ü₫ R«°öóÍtơf? .¤áÔ Ù²ñó§´dƒM¼5v5O£`«'¦đ„À$°Î¬·½gnyde•€Ñÿô¶Ø*}X YË*oEJ|ÿ°«½Äa;§¶S+I\ơt2Ír,­2¾?8ÕЮ_‚ü²•¢0¼«_Fû£º¸A¨#z±J¿T<Ó¯ƯF«ùWÓÿù`”E'…Ø]÷ù¶ ¸©Î$¶%‚ïB0„ºëJí¯ÏÅ ›=r‡ôúxTx¾>âJ‡ª„ưÏ¢M[£ÏÛºâ¬à’i*3;ºÙEáâϲ§I…}qèkó=z\}óÉ7$5V‘Ÿf¡E=¡°¢RÅD[ưŒ~°°RzÁÀ” khºḰ¥’‚¦Øj'b|Áµ¬´‰đØLÆÛ$ Ù®ënâp®öôR<©Égƒ»ú”†‡Ä²Àæ¿¥‰ª‹¤¦ëÈi-6˜wØäu&(}¤œVñj€¬"'b©Gø`añ0xMÀ éé[0Mú®êCy“f…•¯>kˆˆ˜ÏƠ‡©ëJ0—fƠÎMđˆ®ëÆ uµl¯MQº+°́TúÜù›hņ5wCWƒ.P±—%'Ö‡6>̃TnNbçíă6›¥Yå <–Œ;¾ô±ÿ1ùûÄ6uæÑÚ8˜ëíÆô¶°$k ,#¢vD?ŒÁö®\r #æçj?Ơ¬‹¡ØÎTLĂSMÎ₫I€"ÓûëëR鹃ŸX@087¥h¢,ưëà°ºƠF̀èûVTêy1‚ ªô´Dyћ毇"äƯḶ/yá:·è5.œđF´¶•xâbçÜŸỮtưYϘvÜÚ__è¢*Dû‰i‘c(R÷*ĂÇư’|O°=2ø T‰¶DëÖÙ‹&ö'͸½\YTÔåj‘´'“ÑÍ¥ĂmlµÏJ"UZïP ßà´UÄ¡uêí|¬<XƯ1¶ƒ ËîHq[ô•i}ˆA‚ÄÁ/ăÈH‹ØeµE§4 ”~ ë´oóÖx»æ#í©Ú[œ¢ë2+̃bÊÁƯ/øƯH́e¯Ñƒ́CBï¼ /Á!A«82.9-¬PiÖ/Zóê[Qæ¦ü†œ̉_„̣;½¾‡|39ö7¸|ñÉ m?zcºT³TµÑÓ£$iN¶Àï!´ˆO eá)j8oQº9ĐæC ƒ%‚Ù/zđ DjzD¯êDÔC¿Ç; ưôjùwx[mÇÔ£Î;Jb 7¼ŒN#á ùï8°%ACfùÀ¯M³¨Ï™ñe7ß“˜zM‘0doë}á¾d‰¸đ°¦ô$ÑŒ @ ’yl\˜Y½¨@ơŒỏ<»çÜUƯ*Œ 9ŒäÅbêï»j†{s qo:;‰+¬úŒ³k*¾Ü̃á°_«øÁP”’Q´óÿºŒµ6¡̉ø _½*²̀ïÔG0Lª¶₫r>£j!Ÿ\¦zg}GeĂDƠ™„baĐQy8ûêZ1p¹xVqă1W“rAʶ%ºö { ]Ä4gAiöƠükܘ¿³€vHƒZéÏçRÛ]íIס¼‡»jE¯Ù ±®B QG(:rRé..V+•~äl?°1Kú̀ºZ³•tREô°¹X«PµÜ\磨/DyBe¾•ªè~c-"áư’‡J”wB»–êäRbg4˜Ç¯ŸŒ™käQ#{—5U+±Ú/¯Y¢É9ü‡ «àÀ4…”δYµ n¥»-T0¨s§,²rTù¬p^²n7€ ¢ô“ê–ÅsèƯVŹÆă#®Û íË—=Ï‘̃+Ñ]]º*Í)×Èiáø-zÉÆù+`]BÛ!Iê eµ³yË1KÖ/±éÁkS%°^Ư7$l˜¯Ó Q{Zź¹r nê½øÓÖ‘ôéIÖ9jÈ’0E~2̣ ¼uhÚ̀ĐES8áå˜w‚{uÙ,›Z'æĂS[Á;à/>Hy¶r̀Cë8I¤p‚æ_^G Cø™ ß`ˆ=²­6yUÿĐ/‡ g?"›lúkÄĂŒÓħd·ÄûăÇ2C›¡™,$á)˜‘=9Eé.XRlVVµª§Ê¦FèñÆæÉñ'«ªœ Á]Đªiâ&(x§"z—ås–$c5™ôèÎÍ Î3ËKªî½v(~® ñcCcø™`Üv|OĂÏ£ƒ^¨«¶Á}ÉÚ|²°Ï?:ÊV®§óæË¶ÆfÚ6 ×<Î’¢\~³¸Ô¬XK#I—b4Œ;N8—1Iî̉5¼ ^®r¥æƯ‡Ç ¬bX!)‚ˆyU&¶ØÔ“wE] ·0cưi2tmÏ‘ù ̀%Ác‰ ÷„f:/•áơ%â>,gîràú'€ ºQúŒè]”Ã٦ܷ"=5'tçˆƠ‘V¨Åiºl:̣aÙù·újTÖ& µ—Lă%÷ụ˜ ?a ưû•Ö{ ×O§ï¹øGSB>%C^5`  `̀ö~¹¡qoÚd DÿíưW†(¢ä¤€;> đ 3û´­Ê·Ë6Ơ^6üao[iơa8qµmåJiÀ…Ó®–ÿ€₫ C{ôB®í*£3̉×ăå@–đ·́ë$¥ûơX•n' ?T #÷ÖûÁˆ<Ó–åè÷Ư‘³\»uǼ³₫°×ÖÇ¢·F¯¦€Oç%TÊ₫è!}P°±²—¸ ü Iáx_k´D© ¦ÊNØÊ¶ªXPZ7èƒB[ÖE]¨b°‹@9Ù ØÛ`È­ŸíBÄ‘^~…¡=h(+Áḷ₫Ö¤ơ&%T³1-@Pt$ÏE36è¡Â`FEfâmK][KbI±H¤æ5j¤ÖXĂè|î'%“å¬ÇQ:]đ)úW{uơgƒ•¼&¶»wÙ± ©‘¬E>¿ˆi76lê+ÉXÄÖ×{'¦o-I–ö ü½ˆO~̃•àé»ÁÔ”oß®Yß«œ+CĂ‚–ÖDiù&­cơ¯ĂbÎăwüḮ6á§)|¶T^æ ›m«ă£=d̃UØôë œäk›đă<|9đ@IR7UË¡ë1ơ*.¬eU.…³½J†¶+»Ѻ² ²ÎN(}û„Ù\‚k«1Ê[x'²E êí†#t@Äkr¿À̀eÖç”4ßë)¨°µ­̃SwPMºë²|†pÛp8ëM̀̉\=^@ÉmO•+lú6^̃±›”¦íE«@ ê¨+(Ïym€ ,ßNŸîNQ?cñztºÙEÅou»~~ÙW;>ÙPÀÙÑà×]o—h́̃<„ ̀p¢ÎÂăPüzcIT\³œy³u{ÖV¨æ"’ƒ#¸FaúX|ëú×#êœçµe[2Ä?â‰âk(™Đ0»}­‚¥äYîÚùÛöƯ[Ú÷VjÙC̉¦aú Öш_Cq$XÜ,’rÇAh,Q;sJ]ơKêÏæ]̉ØVrÆ#u‘<̀Ø)»Ëyif˜–™ * Èv­Oà]ư*â[}·̀ ß2@#(Iaîö]¯ÍS£¾¤±èĂI‹T+¾+Ôï¤3ü*̣º5đ•ͼ¼»oLIƠ,Eơfz$8ø¾(hStÙæ/§ƠPëxvoO¦³·n„ü©}¹wĂ¼¾Ô¯Ú8U²ß‰C!vEn­”¿T¥MlCZo7Ï’860¹€»9C©}Ř:R-?ưöSsX‘ưƠZ‰JËûipL [â æVgß’N CJÛëđîeEûsJcÀçƠLˆr Ù́OĂ²_ô‡«Ơ ̃°+A? 1¼ÍE Oî¿ óÁAƯ ÿ ¬ñ%ٗٗiH°)¶9¿œ| â!_j›ï«¢‚Îw&$“Q’è—™q=*PçAî¶ä ëñ©í;¶By&U›„PXº-êå0̀³¶Eg̣ä}ƒSđơyVơµÜ‘¿¯¨ÊF·|~g¿z=Qækrâ6ĐË?½U]bÜÙ̃­s.¼0³Èù—ø,t%³¡;÷¢~u¼ßÈD¬£Ù½oÜ ÁöÆDæ¦ö\6F Ä{ía ~“V¯©pk‹N,3 lèPF¦4đaơé€₫‘ ÷^5]»ầqSÚeH÷Eé­åg¼ –rT¯dđ@öl̉nÀ^óW;)’(pqĐ à.€BU,a « d ơÔ“NQ2aÚ¤äƠå=µ³\!›1«`Z.ÂÓ"hS7†¢̃_Z?_`糺¹Ú­Ă}́ rä¶q @XhQ B{Üm‹{GƠg¢‰pZrV_.Ù*¹l–tjí˜]̃Hh'À÷lµ¦Ư×8ri­°ráÅ-6[>?åÁ8Ëáx“pơ¨³̣yS,Ùïë)ç¡áå¾Qé‰Paµ”¬Ï—½Ă)D«Ù>3hôï EéÂʽ¤qa—¿xaÖPv–™÷AåNû₫d‘đ9*†‹t!)ó«×¤íØZ¿ªöèŒÉö›̉·‘nÑ\¥[6²/¯Ăµ•WörÙî7 â÷Ë¢]&bîœ0b>Ç”Ẹ̀B±̉]¿Ñ k> ‚04ÚO•©noO>@2̉1GáÍ%øö¼}rÂ`oQ$¤ó…¢ÚÉ@mˆ&̉‡Åsh¬*6åÍ/n–a¡ rIE’Ø!ÍỵlD¤̣h.$n¼Áÿ!ă%½?¹>q2oTg±/vP‘yªLbx&ÀÜ?ƯGAƯjµËEÑôZ- ^–=ØDN0S7àØ¸ mųđŸ4>ïïÇRbØê|-dQí¾üMûH®₫|;Z_ØẸ̀Ơ‹ŸJO—’3F­ÚEüU5ăû¤JƯ-₫gk0Ô‘0öø}đ}6~K¥w`ÈƯºµ‘ËđOĐ̃W­œÍ ^È( °ƠÇ/( r\@éɨéÎ^*”TiÄâ±}slwüPZ§™-̣,*EÍß…€·G̣n3 —Àé2­{»..Ç-ă@}¥J:"ÿP%®ïíéíˆV)‘Üq¬Qw†øQf×Ç₫­‰î(8ơ4|ÄdKü:P3ImĂ₫ŒJ®Œ‰n¼^úü¨›¿»H#G¯ª²²膻:Z6‹Ô‚y÷Äë†Ư¡S*Ơà%ùBúbV¡ê¡tĐ’~+ô‚F‘÷ưæî…àdât,³¢¯Ë˜˜…á¾¼#CÙ•/Ï™pĐÓ$Œú/wÜH+@uu;@ư„Ë’ä¹=‘Ér¢l^#)~)F¼†₫ôÂ@§Ê…•ny‰¾D/~üè™R±ciÚàS®/§8·‹ü d(#û´°Woß½ÁKå„Â0½†!$•áÖ“[¸'ăÁJÑÍJ̃Đ^Hl]ûEÇi´Áj¸ûĂqZúá¶yatK |@-¢ „¸'»y7ñ¥ÿ~Dax7%Áú¾4›¸ß¦4yñ8[â!¨'ºOÆ©‰–VÍÙ¸Û ‡ă5lÄ2…¿B”:À„@ÑÀ¿¿ÿüÿ·†à endstream endobj 1355 0 obj << /Length1 1915 /Length2 11152 /Length3 0 /Length 12332 /Filter /FlateDecode >> stream xÚveTœK-<wi ¸4®Á%@p ® 4Ö¸»'Hp î® ÁƯ%¸»»yäÎ̀½™yïÇ[½V÷·ëH]µÏé\Q…IÄb’„Ø82±2³đÄäTdUUYY,,́̀,,lÈTTª`G+Đ?d*u½bĂ÷‡˜=ÈĐñeMÜĐñÅUbq²°²X¹øX¹ùXXl,,¼ÿq„ØóÄ Á&9f€ Ää€L%±u³›™;¾́ôŸG­1€•——›ñ¯p€ˆ5Èllh3t4Y¿́hlhPƒAnÿ•‚ö¹££-èââÂlhíÀ ±7¤c¸€ÍÊ ½3Èđ›6@̃Đô79fd*€ª9Øá_&ˆ©£‹¡=đ²`6Ù8¼9Ù˜€́/ûT¤e ¶ ›9Ë₫Ëđïă°2³₫îßÑ¿m₫ 646†XÛÚ¸m̀¦`+@AR–ÙÑƠ‘`hc̣ÛÑĐỆoèl¶24zqø«xC€¤ˆÀđ…ă¿:Ûƒm˜ÀV¿Y§y9h 1ˆµ5ÈÆÑùw}â`{ñËÉ»ÿ¾bKˆ‹Ç?Ølcbú›‰“-PÍlç’ÿ·×Ẹ̈?kf G' ÏËÅ‚́ WcsàïMTƯlAY/¿đđ̣°…ØL_¨€¼À¦ —dCgÀÑ̃ äåñ§á¿2++Àĺ0™mÿÉ₫² 2ư~Q=Ø Ị́"BVËïÏßOº/:3ØX¹ưă₫×EEƠ5Ô•ä₫&ư·YTâ đ`bc0±±³¸X¹\¼\¯ÿN¤h₫w!„JÛ˜B¼ÿª÷å ₫S³ó¿…@ûï>¡üw.yÈ‹€AÚô®ĂÂÉbụ̈Åúÿ­ú¿B₫_bÿåÿCïÿ[“¤“•Ơ_´ÿqù¿< ­ÁVnÿöy‘°“ăK;ÈA^Âæ]5@ÿêb9 ØÉú­̉†/m!bcö"m&^f®-ƒ$Á® E°£±ù_2ùײÚï¶³Û€!àߣÀÄÊẬ?¶—^3¶|'/êüËzi¥ÿ̃UÂÆḅ»çØ8¹†öö†nÈ,/¢băäx°¾4§ Èơ/=€̀6Ç—À C/€)Äù÷Ơrq€"¿—₫…¸^ơ7âæåÿF<, â?èÅSưoÄË ₫ƒ^âŒ₫A¼ ñßè7G ÉưÙ@Ó? ;höäÍÿ€/µƒÿ€/%Yü_ª°ú¾”aư|é Íđ¥ ÈßăÅ÷eÿa~)ËöóËF¶/†üÁăå¯h÷üœ đ_røÇí…ưđ…Ăđ%±ăßđåÊ.?̀/§́ôϹ¾Ä₫5»Œ!önñÂÛùøÂÅåø2€®À̃nÀîÁÿ™±“½ưËàưk¼(đ?ø¯)¹‚Œ‘çf ÆüƠÍ·•"D.L[#́\j×ÏNdÈ‘VĐ̀0̣ø–EDYW<ñéâƒæ‚åÚ°r°ĐŸ¢‰$"¹],yE[˜0±‚0a¤B ™k̃Éó¡"̉±tÆDà'~Ưsë‘:!/¹Ö¤ÆTùÁñ!¹ƠÚÙµS€'"-É)CRØ¡ăŽ÷?V²̣V⃟êog±đND‘i«¿£‘ÑB©?¼Á*kÁ4˜é}Íé3ơé=²cơ©‘f7_ëpÛ½yËáVèŒya™4;Œyư7s²°±̃”ó¹•p¿‡œ:¾ä‹KÎ ³5]IG*èÚºNṆ̃Í &Y ™ºøä™KG¹gpôûrMJÑ|ÅœhO PnÁ}•‡û)Kúm°Ø¬FبÙTHcĂ!Áơ³Ù–$WŒ~-’æĂô—^ÇU4ä>_Uơ’Œ##Ê+{XñöIƒ†Ú9ÄG c´)ƒ»Öf°½%$UµyY ]¿lĐ̀åLówM8ëj¶—n—»}ª•geˆ)úè~8^ëCê<Ê®ë/RFđôư­@,ºˆîØ,ôÁT6éưÙ¤ ¨¬ ¼R·̃©Êzpt‚Ú=)íƠ¨Ơơ\,2DëÖ 'XbœX̀ ´}7g²@Cm<«­Ch²ôº‡₫1 ‘Ç`d”å#QÑ<Ë4Æuḍœ‹ƯÊ3%®'M̀Ñtd́IÖ(n)âk´:füWÛX¯ƯöU=É+K]u{jÉZ˜èóÈëhˆB@ßwÇóiiѨ̃+éɱ¡ezÀ§%æÁ)¤¦qÛ‚³¢‹i›Đà-¿‰’̉É1£é̃¶×(kêMR[¬¸–c̃è&ü’»Áq̃hîÑu(ẹ̀ÿÙÙÀØĐsBÉ^zf@vLÄIR=đçêôœăwƹܙE¦c¤ Mª #C5đ[œ«I>Äô@ê%×Y9y©µàÛO»2^%Œ‚'I“®GX¤đî Ö…üWb¢­!5J½­_˜ÁŸ P’UüN¶ë- /ä[›‰Ó„êŸÛ9óC"(“́€YĐ:¦-ÖCæáhöÚĂ“&K?m̃ …`]T×Ôª²Ḍ2̉‘É(Úø $Îg#âĂ8P}d„7Ư‹ó=¸V <¿†Î'„4ø·1ŸíX®)f ¸ngK̃gơ>ּܬ«•WzóHQúu±k"Íú&j7ẦE VNQD©QE$YPƯ´e/¹¬7̣V’;²`ÅPú­˜›@đ›öz¸s­/h¼ÆïeY5.)ô² à®Y)÷ũ¡ăE€Hi[m—[Ïç?vđ>­ÜöÔ®%),~O.p%HN{Ë”3ÏA‡88®ysÀ́.BO8 “ăƯs?ëlüq÷ó"¦ºZÔ(3©³ªöí“âÈUiǺ³ÚœHE32¡ùÇÂơ%sIĂêZu8;/ÔƒD¥+ŒtyѾԟ¿\IÇIŸ~Ơm¹sÀ?̃đʉfÛéa ¾ë‡_tKx\cĐ½æàLwåѦ9ªè(Y¾öùWÅâ€zÑq́ieÛJ‹ï&ï¿àƯâßâ,ö4hl!IF¬¾[LF”|ĐÖö§ÑñÛµÓ«¦eŤ2ÊÖO¨Ú£pV¼JqëÓÏ¿^L¢&gđm#œQ×!(c(¹‰•Jm¹Ä¯Pñ²Uµ÷Œ¡ÑMbT#Lư£|ƒI¿º3—ddK KĂéW·ê/t¬#ä¨zßÂæ@Öü° û$ö¦”7nÿ€ƒù¨ ́x×8W¤ư-ïøWåç°˜%‰–vÄ>EL¿€fܯ9 Íhæ“\ïH¼ ×݆-ôƒêï`º=qmEØÂ¨ul’•>Ỉ́hpDs~W4¦ÁÁ¿„úJzO˜&:¼³Ç¼PáíÁU6§Yp‚ÛDÜv¶ĐEÄíß{âÿ–…döɯüáH^,”v̉:ẉn ª#¥ÅưÜï$wÜ:!l¼][\ơ€¬Ë\ưí;~Đn¤KêT+Ù„\wÄ·‹ ªÚ“éQ«mæÄöi†V¸aj¬Óçç&¶Óïëˆ(4 Og,B¾î5¼–í—Çó̉•Hôü²Ÿ;ä™”"ñШª8¨Ç6CŸc¸5-=êBâË”¸@9[Û®¯㬄ùÚ…xå3=b̃ÅƯX¬†æiº¾|Ÿsr‡¦÷™Ú,+ ÀOU¡sûkơo²Đ?bú’fÇ™.…ÖÀ¤…íQÎfEhp¥²OêFfÉuàlF‚"ñÑuñU(vc‹ÑÛàG™Ùki`.ˆ–á×̃œ{6`¬ đ×6ˆ N&›œµ/GOTƒóQ¼u>>¶¾¼ÓH6­=Ø£ÈÀR(=—Ê8k$6„ºÍö¬† q Ơ$—®óO/k¼_W.B˜zw 6uUMZg£7Ä¢S)úœè̀.ẀW½246d2öHrùUFÙï:ëuh|Mbƒ½&KuD7q§N?ïx ØđlR™¸û±y2Â’¾?l§[o•t-ÚQCùÁÁ\ç©ÅùVÛ̀ûH&dÅŒƒ²̣jÂ+]jº-^íåd.̣Đ{Œ)ư ÙÚÇ: is!VJŸc¸¤¶·Ñ|ŸhĐUÂ÷9\Û\O_ÇÆ¨$·-¡Q̣ËåQôfÿ(G4† Â{̣×óöE›%ÉFEÊlW₫üé%íß̉8È2æ²Â¦—´1X?ñ-nJm̃0ä¬ßÒ*}4–sDÌ„1#băfçFÖ`Ib1ÛØ)8|}{j2) ¡_’,Êúer„ËO«„²'̉4‡Ÿc¸Û*Ế~"^O që`ô“™sù=™ÿwÍÉ=.:5¦Ø›±V`BƒV†<}¡Œ•*Ö•À«OX!ºỒ~ÆưOF×$a(¨]Ơ†A–¢ùq%÷‰c¡7y-ü„#̃é„¥ĐÁqƠ­äÿ’¯̃N¨ŸámOú=^ ½tớ$-ÿm$‚⛄Ẹ́'(b+zDcƒ‰JƯ¨Û!˜*”=̣ÅäÄl¯)©^ñï%R¤Áq„áØñŒü…^½À•EwŒăH)g $YTÛ,Z[MÎă9Ăeúm“fî³Uö$Àk$gÖüôMñ`ohJ×́œµ@¸1£Bľ%‰ä;§ăm¤AwœĐøy\ö—¶Ukøgª©9¨Æêe{…ă'\%²C’'ùÑ´_{»«“mMDItĘ9JFŒ̉¨p̀ŸØ=mÓ96„TKï?Ơ ös<ơG̀Âz,©‘\•Ûè¨ơ™gÅ{»>Æ aœÆi£ư$tûđê‹ơkåd¿´Ô1*7|—(î:Åp̀Æd¢Ù&÷‰ZÔT¾'ǘÇưäv×é-”/càI¯ï‰ÍlđỤ̈ê€rgŸÚơÚÎădÍo?~lx•áî1ÚüuSP¦—:42|¡nö|&ˆÔTñZN@«§Å å½//X#CmúPëê— ¼êe†¼7=†—v>ñ·3Ûå±®[s(]HöóÎưZù[‹*hAÍoE{ø¸æ£g ¨Đ¿rŸ- _ …ùpỜÏÆI₫́ÚỴSé;OAµM– xö¥”(iøQë:`VØ=Ç Í¤µÑt0;ñ¬ˆ­O½eƠëXÁm6R…ÏÇ~˸hµ@Hêù;˜ k ($ ư&ŸÅF¢á#œ¦ÈÑVN.@Ô€4SƯÉOrÖt¦<n2́3PµÆxƯnö‰]̀½G¬ûG3~ÎŒ™ú‚ÔteĐMử& ä€0ŒôƯ₫ sxé¢!'ö‚º̉tëƯ­hÀæfO]i)™æ Ó<®‡̃eg¿êjùDZK¼j®7ŒƒÔÉÆµômùˈ́̀Œ¦ñ]óe “›ÉÚÙäzK̉*2¼S̀|Ó¶²₫S=7ëLÆEơvS̀ůŒu<ëồb?¾´+ÿ$Ś|³Æ¾oNóéPæÛĂ§Ï‚Æ¯ÉÑœ'̃©>eâMƠZ=ˆíư`¡oP:— l¤¨wå ̀̉~f_ªQÖ0°ÑØ"˜wz|#ætEq°A6?‡üvµX¢Đơç …ùJ¼&h//ªßiuË[9*á›0t£̉áÙ„û§ơEóLäŒ6v¥ Öo‘Ú=ç'Ô6úF¦‡ưÇ3^»‹`E†n—}J;‘Ÿ$:i³nĂ8ÖÏô3ºYíê@ÑW  &A"NCwúâ5;¾2©đ~H Ynv.äÓ„÷[ÍçwÂZk¯ĂÚ4#öª·Ÿ¸úRØ[‚Æd¢aip5x˜›íü¾c̃¶œcä$ÆTáwƯuÊUAaÙs‡{Èf•: 5n3ÎåKktªÁ+8àùJÆÛ`¸6r̃¹YÄWđ¥é{‚.b8 s')¯ wú†Mœ~wƒPÍR2ưÉ*^ưER|4!jèÀëÛ°–«ĂGJœ~VVâÉRêÎK¢d<Ö•÷ƒ di[AÖ.sÆÓÓ)y¡Ç>Ö‡5z‘N™·̣̣¾-—(„;Ê‹¶?çká ‹k¦­¯¸Yå (`à‘×ó Å$>X§¼O m•́̉ »~ú…8ằsÀ_åj‰́¹»j>FW•Û$ ĂTiÄ/E_L U›¿ĂƠ6>‚³È\¸ÎñèưÄ“4=Ỉ̃ƠÁ°,ÓP ^ â{ÖM·œc2‘ÇưÊÔ2âa."-P1˜Í/'uJ¥ÍË$hu&Câ<)U÷µ2OHdHµ §Ø«1­Í‚à™aˆùX_‰ÆĂæKvÖÇ›£ñ)Ë{NSÉD^³5e™÷Ù(eÎ1ÄÑû I É̀r¸ßW‡üaêg<ö‡uÆ̣ÆVÎú#ùÆ,¸‰ỴoÅq+û„6•ă§[3·Đ8{Ơ"-D’Ô ñÏgßâ–b+¤ [Îå5'×@Öh½µö,É OÈd¸ÏUDkWN£üeÏD¿8(>ø®đ–ÀĐ•¦”v́Íﺇˆ*7,¡́(Ç̉m<„f‹*>@£6Ä@ ̀0† Cxàà„¾"“%Q0IÄ1Xˆ’K_r ÿ éÙÉí×̣̃à12̣gºđ\ -T„•¬¾]4SP î“%¹±)Ö¬oN4ú1<t̀\¸K’»Ü·FßC¤ư$«FôèGc™Q8ægúÔ—·CߨY©Æ‹‘»L}†àâKUoUîµ»/wód°&„&À$’Ë–=uÂéæ¶w2,4øøxí5îÀ‘:Zô›Jd̃çđC9Ưv‹•-ú@(£̃é0¡ÇtÁÎt×.*|he oÄŸ»7<¢µSPVs”£¦Wç™°n Q#åÇß̃ỊËê¾÷)cUÔ%»?ŸzmaMun‰ô K3Çhb(KŒ]A,÷eÏ«i®¬J‚á{JËÄëé‚W Œn¬UÂG<­ïẮœ ́ QqăIÁ—­n•Ú¶¢» ß0¢vWX8å,7ZwflCÄ ƒZZ®f†ñ­¦•KíIµYl”dgû´ht¦Ư†©×Öi#&̀¹h¨<•ªy[¾?çyÛ<Dc°ÁzÛ3”Ÿưip¸CÊrĂírF€í°ăæCï'VĂÄ ƯCZE¹[É2Q%EÊÊà³.aṇÈ·æùm\V?²<.¹ÄKÊÂĐ2™(]³1¦ÚÈ6aáĂ·†+¶Ú"ØBƯW½ L× ªO´Äp7]t}|ˆ[ºgÂ5¥Œr`ß Gø(úèF[0êä¼ViØ9 N‘¤Øjî¤=t₫úA–7¶ñ´ +EŒÎZ™¶áQi¥ÛüƠß_ÿœ!yo¸Ø—üáÜ1›“ ¹WĽ?ï̉ĂÁé¥×*›È<±¡0' ́5J±ĂfFU0ŸKTfÎEzÆîƠ‘P‰Ư”ΟÁÂÊß-ˆoóơªỡH.ËÏ—?Øî[s•IV»?Ñ=íûVÑ‘ÍqàöeÏzŒÿm”·tófj.d¬zä •—¿PYÜü¨æTÅuhÖ8¦!­ôI üdlPLíîäUö]ç)@º[ßíC¼ăọ _é’9ø#)}DßLª¤â×SºzPªp›À\Sꈳ+¼ưNf#< C£3Ew÷lͶ(F1/,`$+äñ®E ,|ù8d9+,,| ơ²ZƠ/A.JqƠ6²Ưï‡-Ÿ.¸ƯđYL“„^^să†ÖÛS?ßNŸHm/t“ÚĐS¹,>^x0ÏÁMBÙ ̉2ɘoè–‚ËÚ̀đ8ê‹ÀÖ²TË`Œ t‰ =@·ÚÏÊê5WYĐưYùöÏÙàÖB!yÉ{Ϫ 1-zçMª³ëü·§q,³ü¸[/°¡KßQ4ÄÍ¥zѹ|.Slr`wÈ—Û‡,ÜÑç[ßđí3úz]èVááC8Ü.táM4x-Z ¾w$.¬ˆ}̃e¼.ÔơíX…Jè·¶êÉ”̃Å‘ nK!n“ü$y£ˆY₫å$Æ+½ê©©¼û çVxHæZ­(̉Ü;ê~ưW:ôTÔØ“µBËÑ^ôèø)¨îG~”[XŒZŸ®Đ×̀Óđ#2<̀èï:—Nà¾N¥!—»í µ›^¶Ä@ĐF~Z|H²‹Á4v±½„ °×Û«5!Ù́å >´¡mđ=ë< Æóú¾SÀ’ṃƠ¥ÖªU™̃ÄLF©*Àµcu×»yV°ñ[* D 5–oÉ̀téÄă3zSâ9KpÖ…8eơ™á£iˆÓƯ¯v̀#º¹%oÖB:^}S>ĂK´Àƒ…à8g3ú‚“[§j¨1îEJ'XªVGÂĸS7^ëg¸LpÚoÈ_Û9‰=MÊ.JËK:̣îeáÁ“Ó̃ZD>H‰ÊÚb}Oiùø¶²ăF]Ù·óû/J&¶…WÂîà<¼6„̀¢®X!àÀA2®ÓÄ\÷ƠĐb3í¸…Dzè#fpîâ;̃Ï#µÇË ßÓŸ5WáÍT\“®úăå—È×oµw¢âWÔ<°TB­̉ÏxÔ|CùÆŒÈÜ uW3ăfm ÙWôdSySé‹ezY ?Ú‚@Ñ7Ä&aë>è°Â£¡ơB×Ỹ}¶̣‚na-•¸Jw¡¸4¼Y…zY‰ueá‚ŲǴ9̉“u7UÏxÁ2Cˆ’í ZUkëØí0»[A¾ >mµ¿(2>ôU¶a&v¯ÂoJbbʸ…²âÄ?«iŸc4©êĂ ü8”³T|đœ2¹*QŸb”ÁEö­Ñ`_ft àêŸÆ̃&ä51üªÉ©) 2¿•ŒAËmx,M“#Êb¨§ïßËÛ7âEĂ:͇åîh? ½×¥$‘Îv‡¤Í¤£—HỖ»QñÀ¯×̃+<·â¢â&sЧU“½Æơ)B+,o•²ṇ̃¹O—4Ñ̃´îHÏ #₫A–4›D6(síêăÊx¸@xL/Œ–#‹ Oœ±>́¯Đjn‘äKk…óQ`å[‹³©̉ç²ÄØÄ7„ˆq™4›‰]HÅVăQÙIt1î{obÊcN ù¯5§#ëc sIó³Œu:nÊ*‹ädu 4†üÜTÚ± X-âá•Ô¸Ô™·mÙ ÔóbeE4KDóáBMäzô6ÁozQ÷Ÿ2Oz’0V¸j‰ksÜb‡A8qo5% "]?¯̃ôî© î̃©ư Ê÷K ñ̉ïG>Èq3fá>aÖù̃´ö„‹„ÀYpz=’>=OÆÂ­»₫D¾ïă„•LX́±ÿ‘oÈ”º·*ÿ)Ư8ÊE¶̀˜Jó<.¥ÀÈæUÉÈ´åQ(†z%ÛE‡è9L̃€¶²®o“«ư)º/Ö%íƯ„a:̃µÅj3öC̉é)'O>µd2­d j¢®½S2†;Ïtíªß)w#£¸Áç¾îka‘óëu«9ßđ'1¦nE”:âjNe C™ÁaQ©ă$|ûƒâ1qåȰإ´.cuÆZ̃Ïá¡w¾Â‚ë8”ϦËl2B¢0¿4úÈÚ91º©L°”:ư‹ơBBi‚Àªe'F̀ÚM¨etT:`Ѹ*¯îáÎ.ñrûBfưăè­đ29‰­ºˆ%Rñœ€ó7~ṣ.—‘È$Œ‡(Töí1A±́Z– ¬ñ–QÅÏ=éEæt³ †gµ"äƒåÖ^ưÔÜÔH;r>†µ.Ç“{kíÍ›ep*zT3Æ)•ñµºêĆ™P7â÷̉ü Óó>ơÛL¢̉íê42sÔ×m̃Xúp®ç”‘ñXđØ•w«7Ó%‰^¥¡m¥kÄåÉ·®]Œù₫¹Ơå'S™WSØÂSÿW;Eg®Ïo®*n’í>êä; ÿ́­© çèêånvû”é‹‹ù®•m„¿•æÍ÷̀¤ø‰7xLÍâÆë"kçªüía}5¨ÿµ¨±dFF¶ÆÇBj\§Ùâj‘6îù¢mL%Qu/aäFfçÁÔ&.x̃%(SMH @Z“’½Œïiä\s˜ÿê6ÛÇ -—µzÑSÛÔîƠ=ấ}åB ˆRH´¼®«3"l261LœEy‰ÿI뜿qn”w̉?VOå¬~a*b¤O`!³#Æ®íT¡©Vq.bư{p6ËÊ–€ư Ïq®L KŒỌ́ó—ÜJˆÑàÆÓ4[Û“Ä÷ÅQS¨¤_FTV\b1ÉZd…Öj*0íưP/¬­á“«6œ ǽ¤>™¼—^–“¦Ó3…„Mß´…ŸÇ­ü”½.«†»  ùÆFá™ïÙiÀ;\Jg̉>: ;̀ÿ³²È[Í(l[H˜—5â‚2fto˜f:Á¦Q˜-¦Æ¡÷@vÛÆp(].zÓ±|$Ñ$bqQ‹Fđ´$‚~Ơû|*,à̉¤i{Ï`)ä ¹;=Uj‹_‰&ïª-m8R̀Æ=tti×ƠÎĐ{w™S-v[mÿ¾É$đ.@á̀Ę Pn]ùu3ëñY€́ệ–đ{rXÙ¢­&¹À1T&)´Ư­¾÷N(‹A?̃†`VAφt5‹gÜËÚ6W7Èç#™}ÎâÑÙtu¿ËYâ9 œpÏá·Wµ{¦É¢¾±‚h©z“ꣴvĐ–Â-ơ›n9ØøFŸTù‹̃ÔÙ(»cGØ™Iµ¥µj„F2_ï­G´mà{{QăƯ ¯fI¢¶́£–‡Ûû!ÆïTà¬j %¨ă’1ªŸSeê^%´¿Wjájë*”Êï¿ËŒ¢ é—­ë‘I9ÑV̀₫`;2e¾5ˆÖVÿăủ!Ó«AÔÚ‘ñ¶Ñcg£Cg~ê¥7ÂË2¸ ̀8:tZ£’/ñ8HYk…xÊÓt ”ÆVrY?q$f JVåË…{™Úæj躷h£3ä ̉#r¦îh‘&r6àÛʄʾΉ[µzvfçß°ô¾×àw sÆø Vư­¯[̣<₫üC4|µ›V¦8O3öÔÁRS8b˜àâđz©’*lÁgƠ˜$̃ñ–hǿwp?A[́L¡̉7V´}öº ̉ô+À¶êQØëƒF¥ḈÍ_#ÈU&Yןèđ稵̣[³£Ü{ÍW<¢§s‘̀B²ø0a)~jàÊâZ—è’ˆ̀·?‡J™†>¢¼êlå{·PNû@藍³Q…#®̉‚1Œ£˜¹dmxƒƯ ÊKÚ½̉S_"Q‡)¿Ê‘MNOÁUao¸–âZ#ØƠë"¨Ø~¶Ê%ù6@D*MTwi‹jZëT^¨üÓễMFÑ_Ró(-”POʰ¿\?zÎ́œ1Á3iưá}›] ”ç×úø̃Aû³ºw#k³ä¹A± [ƒi!́₫å_}2ªÆ‡°nËË ZîëµYăæá[{qưbôE!̉qo·Á°̣zü¯¹­<©%0µí‹‚±RÉ“¸‡á{.‡ï·‹s-î4]l æªp®4#ŒÊ¡¦²pïü‚%`í÷e¦À}’k|Ê3i9h¿î,îüsQ{̣~Xy¾ï@ö²R"*rÀ¤Ÿî#Ôu äFüJñÓûDÍÀè *;́«jØ’pèâ³ă’J±qà‡¼u ^)IÀWu,ÅËíơzêOkT¯¢oa-sM¾ëm̀ä}›Ú¯¢Ót5ïZ0.™0cdÁl&zŒ–›¤ccHèăy}Ó†¸j3Æ›oÙÚ„ k_ïø]µ{jc¾îÛ?¦³b½è ƒƠ7™,S×FG>Ç ơ,JG|@†ï₫A⇷¸13®zc_™”ËpÚè‰ó8KÖŒ!Jl},'Í;ñjÈz¶¡^0‡˜Ùkó}°+ëL C˜9Vèâ€ç‘™E9“D&̉f†¿S`hJ®ÓMĂ‚ZLU:$‘[”/ă¿¡s̀»’fÎ̉ÈTÖvŒ´¡ó¬ŸẬ„Ä:ü‰Ùj¿A8l.¸²̣±g£s2µŸ:­»ä¤åH‰̣‹w ¡øi/B¬£k)Ó·FÜ}}²"k'ÉZúêÎ3ïøƯ¥h;#gÑP ̀†Ø&UOªrJăZ>u}Ú¶A€[D¾=̉[àÇ₫[Mj̣ œ¯q†JÔ± ¤Ú¯°—˜°LV9&Jụ́Àụ̂½h“§l10đ‘…ŒKÚïiÜÏX×’#h•m%5F§¥ßƒ WrV«œ»ÅĂk ¯n”lÔüÔÎ6ơ†ؾFßuåâR3Ö¶^ôœ‰F°#ÉËñ¥Z̃³²rV÷Đưê%½rís°r1œB‘Kaâ ÷´½=©½“÷î7Đ*øeåûư2'z…ƯbJĐé¼p°˜ơMÑÆ€Ç¸ưhúø·Å Ê2KI ºÀAXÛ#èæùå 6ÍỬ|G%¬,¶~3'\‚í>åæ~†ñ̉a½'ª…Êdeµ æ_1’O»<(Àˆ T#Ø₫«®’´±U BÖzù\³0ºi)_× ;3¶œ)â¢hå)n₫¤ƒiÖʬ©³R§: C¥¦ È›„y₫x:µ©–2kØNbZ±éwà[?ŸKû7À4̣`²µđDj›”v¤ÍëJÍåÜ×çAèáE­ăª}®Ûº́iÔ[;wó>‡Á(óÊø–UŒ{«ÇǛK:Đ7TCVµ‡ÁƠ›Q₫†+b(kØ;®­™0S)‹g•ø¾ßx|ƠïOËx*NS¡Ÿ ©Bq.́ÖC±ˆÏÓßÊ[Lô6u&R90oqKaMä¾9¸è)ô•ϪƒÓI\̣Ôèä1興k¾,L÷ 1,.đ•à ïí¸Ë²¾ÛNX¼Çë–©4¸MÆ«NÉÓTÿh HwŒëùJ—é/Nö4s'u†n'A(}2~ˆ;8eæ>n@Wèêj œ̉÷ỹYæP‰ôê"„I‘¿×vS]¢„Oed‰nVü¼Ø/©(TNÜØ9ú[;¨4¥O=Ưâçg.̀¬Ô€jf^¹qm5°½¸qÍĐ,r¦îƒ›$z!Éúuó‡¦<È„½Kưñ³ñÏb”‡‡§ÆBúfË vZIå(Xl«–ÖÅFd÷½Ø!{T7„ÊQ‚r^•ù´¬³9[²çÇu×|±–đ©¿87%–0ߢÁ£ƒ2ï3#ˆcx2ªZñS^đ ª~c?ne²5Tʤ• ¡·%À«m=®bcvFkÇ ƒ„'¥G"c¿ï‹¶á.îFb^iNö4O(¶¶zơ¤2B W6Ă£ ;M̃]$ =€­²ó=Íç ÉƠâZ¨9ạ̀ênÈ₫0ß[›W ?víØ·T9qPëíú̃<;¢¢½raY† åưx¡-u@=W|̃fjVhF_MH‘­|´BóêpMäLé\óÙP3S¾³JñCb(¾ôLͯ̉è _ÜÔ•ÉƠE Zï¼`̣ïX„9iTz‹.eÖ" Kü2H. G@ˆ' åßƠ$L}7‹Àä9ñ(GØ‘!ØÙafé_5ùƯ¹àÏZ³ßÏÀ'çåÚ(˜~y­°èØ±ÜÆ£iÁµŸqªé$›>qp€Œœ̃Ñû¬»NE;qO-`XŒ²*@ÜËôr6;¢(…M«@¡m’g¢qḰ`̣»÷¾ ïFYO‚“6‹Ơem r(²l§×KM,ô †~Q³ïäŸßå¾ă £Ø2§(v“ơ:´*Pä¯B¤.ö‰Ä¹²KroGvjô)™4‡D¦p ×ç(Çàq´‰‡IÙñj7B¼Vâ[œüd¡„å&×l3¿é­_ié"‚˜±Ç´¸ƯƒïV( ç›1ô•2ÅÈă$\¾N•Ù†‹q¨B¾ë pnŒă@S{¢Åk”₫~Åü úŒâ‡đñÖ}s. Ñ4m 'sN/œŸ&ú2è•øîI¡j— ß[º.¬@|‡̃cmKƠ‹ê*.XIDcxGỊ̈•"k©ëCRû¸¿́ü$<.:¬ ÛÊ߀A¸$À*Ôđm|7FÔƯc£3p›ŸGçw‰pvw˜Æ˜ñf`÷J endstream endobj 1357 0 obj << /Length1 1401 /Length2 6058 /Length3 0 /Length 7007 /Filter /FlateDecode >> stream xÚwT”[Û6R"ÀC7 ‚¤tw0À3À ]̉ ¡̉©H(%]̉ " %!̉Ư)~cœs̃ó₫ÿZß·f­g}ß×]{_×^ëaaĐÖ㑵ƒÛ@”à0$?/H×ĐÓă /$€Ç¢Eº@₫²ă±B<P8Lâ?̣0eS#Q@ 8 Pơtø~ ~Q ÄÿÂ=$°ÔĐàTá0EîæëupD¢êüơ °Ûrüââ¢Ü¿ÂYWˆÔ 4ÀHGˆ+ª¢-ØĐƒÛB!Hߥ`—rD"Ư$øø¼½½yÁ®^¸‡ƒ47à E:ºÄĂ büĐ»B₫ŒÆ‹Çè;B¿zp{¤7Ø  .P[ ñ„ÙA<Tu@OEĐrƒÀ~ƒƠ¸?›đọ́ÿîOôÏDPد`°­-ÜƠ ó…Â{¨ ĐRRçEú ¹0̀î'́‚€£âÁ^`¨ ØøƠ:P’ƠÀ¨ ÿ̀‡°ơ€º!¼¨ËÏù~¦Am³"̀Nîê !x?ûS€z@lQûîË÷çpapo˜ÿ_+{(̀Î₫çvn|0¨»'DEáeÂûÇæA H $@܈­#ßÏú¾n_N₫ŸfÔ ₫np7À5$jAưáù#À^éá ôÿOÇ¿Wxüü€Ô Ø@ 0¼²£̀ûßkÔù{@}3~üèçïï7 Ắà0ß࿘OIÉDÍXëÏÈ;åäà>€??À# ÄÅÅQaq đßi´ÁĐ?müG¨ ̀ˆÿîµMúơ‡́ôÁü;—&E\À₫ÏÍA [Ôƒÿÿ̀ö_!ÿ?’ỵ̈̀¿̣ü¿;Ṛtqùågÿ øü`W¨‹ï¸H”4à()À₫jù­\ ˆÔÓơ¿½*H0J ²0—¿7P‚ú@́´¡H[Çß|ùm7ø©4( ¢ G@̃-?ô_>”¼lQ÷EÊ_.J=ÿ.©³…Ûư”™€°öđûâP\üùQz´ƒøü¢1ÀÇ ƒ#Q!j¼@Àî÷óL…@Ÿê€¹@́‘?]¿­ü¬¿Ïï§ù_Um==PNä/f ZúkưKéˆÄojn+îT̃rV)Kăͳü{~±5æ‰IO´0’ơs¿£úÍŒ£îrÖve”©Ú“%‘#4œ;gC>æY!s)ʹH4Å%¹=ü₫óĂœÚá£hj̀̉íƯDZ"k3L3¶$£‰«ÑNÁỢ•‚ï­ˆUSñMÀ(:e1wˆbå¾5bsc¶E·|–1Xx n î9½0cäjkçX/®¬b9YX£ÅïàFÍi±}xñªˆp2ú ZíHTE-Ç͵8ó×̀où1ơ!Ï G¹0g¯§ûº¶<-NxåÏç}:„lIÖ EcºíÈ&s°Xs…ôA$ù½‰ŒqV]6í“ß6ÛΪ3ô‹«okb.„YÑăØnCZƯS÷hÍåƠßơ9iMưèæXùàè{Ó#”+»Å=ÿ O£"”p¥RªñMêÀú„ÓG¥Ù4®s·AĂIÎƯêë·z̉ ¶[&ä›^Đ-ñpµz^ó¬&ë±3c\ÑíŸ'%m=ño‘D+¬Ek{Uí¤Z\³æ¼ưó¥]ˆ„³K-b4'0X·°ư—zÿ#”ÆëưŒëºá¬‰­S:Q¯Ÿ·̀qË‹ Pàngđ́ ’"eS?)<ä%C2ƠM@GÖH-Ü]ôD„´Æ)×jZF!ë&g¥ˆßăNHƯ‘kÆN¸4dRydÚ2Mº“Êæ‰…}YçíkËâ ¢1tÖmbé#M½p ôGƠ£æ9L Ó¸^ä‰Ă˜iº€fñÔ‡G¾¿đÇÈz%æ`læ¼G³L{?Ñïu·ÊŒ~ëdúÙ·–Ü›Z*£ C½ù}¯C˜åe0±#¡Áü–Ò\é¶²–LGùnKRÛMáz~9ei#åæ¶¡hÏŸ|sa£ë>Æ9Ư¡ƒưƠ¦°ºFÇ–«Ö´ûêËơ` ×r6el:&có³Đ’ùeÇS …Ơ×öóˆù‡@Ù%µư…†Ó±ÉĐiGÉæH­C b̉Àø†Ø/×V½¹ÇD»~"‘ÆJ]“ƒVMªÁ¡ë¥$Q& ¤Xs»Wc ?J#íO¹ơYj1Û¯ÅûÁM©:¾¨éƠ'½Œ©u+¼EÆw"&¦¥ơLB¦°–sÓÜ 0Ư°>$–Ï+jÀôDkÖ¡·)Ù)O*É®đ©øZ¯‡b19Èä+C‘ôôº¬¢îƠëoDXïÜîF̀½GsVíß°¥  Ú}¦G¶ôüùĐù«jÙd«"̉L^÷äWÎÚW¸í/.ZiØđ¬!M£9̃ÛÎ…îŸäMd[Ö®@©»Ë&sb}AäpP9ÛßM,IῈSs§KJ;wØù!\#-Óư)%tiépüFTÀ'Ưƒ@f & %̀^¿nơ×›Wµ.ï›rŸ̉Îv>K]7µ›$e%: :”…fàÓSnÚô“̀T§¥¿¬ƒQ}´˜i—Ö L˱k«¥z]#7 êœñ™û{AÓ"º¬ éÙlû‚ố8û1`î÷Ú—Ûä†̃Ó >&đØ~ôæÊ„Û¡ÔÛei*Pƒ’ƒZ̀qƠ *E€y” úF(ÖÖÔA>ï+¡„ufÈjƯ\µôi¡{[—¼ï ,—ÑŒk¿œêÍ;GS'»AGçÁ‘)] ¾ê'̉¶W2Ôª́'(lºă- {w“f4Ë Ç$1_N ÷aèŒå*å®`ÂÆßXwíMaÔ4!†d8d“GZỊ̂ 'Åmu&ÈâG‘% 9N‹pµ6~jơR§Ñ•\Îå‰Â˜J›h^å£S›ˆpäÓ̃é&Sˆ•*ă>_#ñ¼̉%Ó¼ă‚¿¼ĐJM¼­é[ñ₫@(“̉ÈL¤3îÎMhæÖ̃ÆcăÓ;?’#&¾$óèO3üyäjí!ựXŒÆPođᡘ¿èƯ×C†[<ƒy¸–§g^!ùiŸlå3‹%́Pù>Fèiß7Ǘ ~®bæÊ©»³°–>ogNwăëv§Œq<Öîj|ô©‚É+‚O²•ë̀=Uï v&c'ÚçêÅ€{œ]Kg<‘¯9’¬4×̃ơ-h±9)>i³'̉̀ÚÀN/4₫5)Pp°üeßXQ—~Gb¹wØ”µỨ1•g•?Z©G…Qê'K~.YNöab>#|XñˆÍ¤ºôá²o7ñ9W……ª©bq× ØGĂV¸Év$uW?¶s‡qY₫ö›|uR™È‘ŸOơqø!‰›ïˆ̉»kÑ܈x‡~Ç?<ÖÙO+ê¯^„3íß¾́¾ÁÉ-¢FÜăæđDæ“æ DB6I}±dNé«ỏ‰§ñáfm[62Êơ—D°˜¡¹fÿ2K—T‡zBLe/<Ɔc{̣å Ù)!EaèÖaÿ:ƠÛ7Í[xVÏaXƒ{™ Ơ[U,¯'Đ ư"´Ÿ’M̉*¼hI^v7e2uPgÛd!́¾Uî•#«y×)ó¼ƒQz¹U6Ú7÷¤’â9¥‹/ñ¼^̃Ç(K88ưÔç-¨sûƠAÉYav‚¾̃^5ơ`QnW†ƒ-eA·Úh»?ñG%.È]¡—SÈƠ _â‹À9s½nß' À?=s(˜o¼@Ó⡲ôG¯e›¬iˆcK4“ª8H«!eg3‰ Æ»n.‹¨¾ÄÓiês»°ñÉ5Á2¹¸×{Ö±ơó¾]æ­Á—µS_•6«³ûSờâƠ¹ צ—\ÊøEùÏåÍ̀«X„g#|_s¬-ïÜ2¥1g Qºf^äë&O•¡»—>Oí¬6ÍBß2ß×µüîê÷úȺ̀í¢¦ŸXpÖÆ<Æ»Q»jØ$]’ÚøY$k'?âßÉtWtymшÀPî4=±=v|8́Zgq1~¿Îy¢.5ñËƯm/ p´”îUơÛxl³á: Y•¸E²êè»d ›´äª†¶1ă÷ÉΑkr0Føđ ÀmưUÏ¢J̃đÙ»ä>Å•8œ0AC¨Ía,ˆ*›à}lÿU0ư¾€SX&\•”ĂTss#œ̣-=µ{ûª,^cR2̉ËÁ‚â©àÇè2í…yø;} 7t¿¬o¤Q¥„%æÙ€]Ú¶0†TÅœ‹ U†™­ûx1)êvCF ÆMǘNñ2H'È»d«¥È™·K2‹N™NºS‚ŒªóM¥ÊI-gˆqˆ ®·óù"8hwàÁTgeù ¥”äO–¯Zí 7 ̉!•ªy¨·ÑB¨C´&‡¬æ™̀¸,l°Ç—†¥ÛwW"ă•mJ7éáuY*_„2 ×V#ïḤ›%–#Ô- ’®¿µu~¥Ù1Ó_érb*s roûFæ@cËU\Ê?‘ ÷„§*ÇËÅ0<¥N#à­»#¾zŸ+úË„ƒ&Å1ê‚?PI‰ñó‰×̀”Do³;ïMƒ7z°ña₫OƯ(Ă= Ÿ¼×iërwÙ°Ÿ²wz ̉À1Ax÷‹Ï·øÛ ÷̃¾˜Q™äN½¼=h{ÆkSx‘ă·ííFÚŒ̃¸ÜÀŸC;ßơØ“J±H_¹µ§¸†§µ“‡a 4 äôŒå&ï»qºöÄùđ*̃éÊ;µĐº̀öÖ‘åü†£j³Ơt“#ùcέĐYYsg©Íâ£2I/¨ˆZưeDñY„ˆ3/—̃¼¼­¿QôíAók‰§d4ØäuK’|{•údp¤:4­º&–ç¸h.[²§”×áM̃²@FâîQ´4Ùø=®3PK¿–ß0z/̉$‡ús’̣8&¯E 5ưbAC—J³gZÈÉ9Óáœt«h³Á¤~‹ó³Ïµ¡¡…¤G¦.V₫́”F•ûaĐ|£Á[2‹ wMM–Óú¥åÆ-dú7Å3CæÔªS­Hî,ºD²÷‹QÆoKÓǪçÇ»Ế˜Ji¯u®¾K÷'Ff…nỉ̃Sđï‚ƠJÊß1%OI×<‘-/âkzbåk{ư¾û®2œë g›ï=¬«·ÅéPLAÊ–ÁNA ¢ÀÑc!ß7Üà;Hsê3t^9-'!±ªÀë Ø9)¨èX÷:³;×;,ƯúI}\̣Ơ¦ù¤ÓÔ¶Et‰öáÔiß v*µÍ•ô>7¦N̉¶C,fß[Å•„Ç ½!Ü+E]”Ä׿èŦ³@mX¡Fu¤­±vOG˜>ć§bÄÛ«á\æ[Ä-aê#ÉƯ¶G.¹g̀æx;Ç›¥7SK³²U¸ŸÅ)Ơóq†|†\ÓK:™¢Í/Ëcñ‘:Q‘˜$ơºÆÑHI®Ú{œËîwêÙ?„d«zjµÚl™toîc~=pt>p)UDç,ç~óăÅQg4&H'÷xPnkù1ï~₫ơƒäµDÂ!t:j8ç²tśΪ¹‰J;Ăt徯Aœ¦cP Æ´=}<‡6ÏO ³¿ßÜŒ~wÊÇÍ%Ëd1¦wª{„òÆ®ÿÆM÷f̀¤´¥F¸îyÊÄ̉ûUXÈ+ƒZyánüÜ|³È2ù¨Î·Ä±̃4ç<«¹V9"®ĂV^ÙéYÏ Ơ^©ë½­'‰räz>©ÔδÔö¢Aº%¬–̃‘óÓ1óÓÍ‚!Q_ÊDH½^äKë$]—ÀÙ’œ]̃÷> ZWöÀWÍ Å¼è^ Óú,!°”c–å(<ê₫`‰¼÷“ 5 ©¼“¦¢ûÀGñnEÎŒ:×ö˜S7CíS™éR%<¥äܵÓü«••ÉK.{˲0÷ z¾Í̀x̃» "ià"h{˜ë¾ưf̃£-h©TŒ Áí£ ¥I>–o²ƒÈ̃9jͤ€úÓSÇŧ—dcX~­Uk²?of¬-½Ávˆ»Â£Ă1~9³0?YÂ.yÖ$­àQ̀Ÿ¸B⪥ÁtˆzÇ~1¢ĐĂ³Æ?Lj£ÛÚ¬Ö;Y¿ụ̀Ư¸2›ºª¤ y†@6ăg‘Ûă`»¡6¹BóoĂß `geØbÓl¾ÊơÑơ₫K Ơ·jvL [̀¤8Årܼ˜eáÙ œO V¥‰3‘꺣‹˜bóÁs5Jwú²ñdóùvc2B7*đ6ψ HjÍ{ă—Ă€)¬ÜÆÜ;zÈƯByt…̃^_ôƒ^N°A9H¤ˆ~ÙơøCỵ̄QXe.¡øKΕº!÷¾oÓñgíaAf+¬ï^œû²³‡»¯*hÑ(>Ñ;í º˜ú›XÊ2 i?»ă9ÂRϺc;`¬v™0Aç¹|{§{¨PŒà ±̣Ỡ£×‘‰–}ß@,Té_‡Œ« R¥ơZÅ ÍZ•±[ó—fŒrr®*RG {¦˜‹5ª; ”‚&_Đô&È;Û?.`³âÆà‚OĐ^„jêă »Yàâ3|0ÂVø‚]Md[¥SŒ>‘]ÛƯk$ÖàiíQ4/.́[Ôµ[Ÿrkù¢¶bßW¾¢eÔ=©·¨¶%̉Ùî-‘YƠf×PŒ…0ơ”Ôó`?ê¼ÇÚỀœ̃©c—å~YƠÊDH]5™·ó ̃TYœÈ‘¤Êª3ÉB©o#ô¡ŸN—QyÂä–ÙH]ô„^‰È÷iËøçûỌ̈[[\ñdÙ”>q…]̣PÈ>¤¼ûăÍ÷>U—tDñ‹0%₫FM™4€¢KÍ' Ça幃̃`ø¡t«´û|ÁóưIÍ3_wåó^ăx:|»,°=¨s°ô²Çêîæ^³̃µE…è]ӱɵ ËVÂ3¢Ù'âơhgç¡ĂG‹̀6LtÈvbơigo¢Uăn¤ œ*ỗ¤;†ĂȾF¯zâGùç=h­"I×c2±©’…QØ–ÍÂôÈœÇ ŒÙđ÷úă5îÇàÍçă6£NÛ[L–Å—:‰—̃ÛÇGoö çkarj.Ÿt"·Ô´M̃œc·qéTZ7†u»|ç³bï2KëêĐ—;mËC^’ñúI|Ç>HăU•xÆ̉Œ}ĂQÏ%̣󈔗ӾÇʨ-zc%•ß₫æËÛ\+”KÍÛKa5í†Å2ư&É·¸Nå#̀Ÿ­E<U®B}·­1T÷*/û©—5 >6#†pv›wªĂ5ĂLŸËsúo˜}‹PŸ˜Æêp¶±;Wà5T?ox|ÿưÇâ8…‡» _ºâ#`£³#‡ăï§,ơŒÄÂC¶'«GlGüa®Ô]%ô£Đ·²aûñä^ƯøÍ…̣ä—:Là#& f₫é—ûúRcR[– c¾ƯƯÜGLÏ\üu+¬'êÅaø§¦₫N„z¦oEk#̀øz-ên„Ö;ØX ¢€H‰¸µDmú@¾ƒKºÍ¿cŒđÙó3‘¹ú‰(‘Rưç˜"̉γqööÅKéƠXW$E˯öˈqœ̀‚¡>vÉqr¿ŸöçTX5zṢ†FZ}²®ưÚƠ™ø endstream endobj 1359 0 obj << /Length1 2534 /Length2 17420 /Length3 0 /Length 18892 /Filter /FlateDecode >> stream xÚŒ·T%ê7œm»]“m[“k¤ÉílsâdÛlÛ¶krM®ÉæÛÁ=sîư¾µ̃wµVíßß~vä$ÊôÂF6@ kGzf&€¨œ 3€‰‰•‰‰œ\Å̀Ñø:ùg ½ƒ™5Ï¿$Díúï41}ÇwA9k€´“%€™À̀ÁẰÉĂÄ`abâ₫ =@LßÙ̀ Ƕ±:À‘‹Úغٛ™˜:¾ûùÏG•!5€™››“îOu€°Đ̃̀Pß §ïh ´z÷h¨o P¶14:ºư— *>SGG[FF}+{j:€‹™£)@ è´w₫H ¯oü;58r€©™Ă_ ecG}{ à`if´vxWq²6Ú̃½”¥d ¶@ë¿„eÿ ü]3ó?æ₫Ö₫Ă™ơŸÊú††6V¶úÖnfÖ&c3K @AB–ÁÑƠ‘ omô‡ ¾¥ƒÍ»¾¾³¾™¥¾Á»ÀŸ¡ë$„?ôß3ü;?C{3[G3Ë?rdüẰ{™Å­Dm¬¬€ÖpÄ'ff4|¯»ăß͵°¶q±öø26³62₫# #'[FUk3;' ”Øß2ï$¸ß4 #€‰‰‰‹•´] Mÿp âf ü“Éüù=/[[€ñ{@/3càû8}g ÀÑ̃ èåñoÆ#8ff€‘™¡#Àhbf ÷Ûú;hü~�™+@‹é}ü˜LüüóIû}ÂŒl¬-Ư~‹ÿÙbFM)eE%qÚ¿S₫‡)"bă đ gĐ³°²ØY9ܯÿ¶¢¨oöwÿ̉”²6¶pÿ́{•₫°óß@ơ÷zP₫Û–¼ÍûÜT¿Çü ;“áû/æÿçaÿSåÿoÆÿ°̣óÿHÂẸ́̉O>Ơ_ÿ¾¾•™¥Ûßïsëäø¾r6ï›`ư¿¢jÀ¿Whdædơ¿\)Gư÷]¶6±ü§ff®@#E3GCÓ?gă/²ê{fif T´q0ûă²è™™˜₫‡÷¾\†ï×Ăá}$ÿdßwç¿=[Úư±d,́}{{}78¦÷Ibagx0¿o£ĐơÏ!02XÛ8¾«̃³óÛØĂưÑRv£đ¤¿€Qä7â0ưFÜFñ' €Q̣7b0JưFïVd#N£ÜoônS₫ÄÅ`Tü̃m*ưFï6•#6£Êoôµêoôîïó?ˆûƯŸ₫oôîÏà7z÷` ohá`©ï`ú•™åƯ•½¾!Đh́ø/2ûß俆ø#̀‘-€ÿ%ÏÍúữ+gøbÈĐÆ̣½áÿ¡°±ưA±²úơ“Àhô/øîøÛÂ{¾Àỵ̈ÀñßÎé}}~«¼§jü[å=6c3çÙøƒmădÿ/…w“ßßù&b¬́0ơœœb¸/T†X®’™·J·¼ƠY¥P[ơÁ[ô j̀=±’èĂ[;+%̀¨KêÄ_Of–ù*…øSK…SxUîIA)”7r-:\r„Ö,P½:“׫&ö>cϼ_CưF|Ñ©”¸-}°Ơv%ZDª­`+'T€ơ\œÍiû©=‚ÉT2eníÜIëÑE£½715s7ƒ¥MËqjfx$q9/¼.]Đô:%´É }ë•æ!™œÑÀw½P2€â7„oi!<¾(¤~ÙÅԑŪÓgÅÇáÆØP¥èbơù÷(sFI=…Ùüeié́ăWm̃´ø ù§æœƯäÇfBoIXÛèC¨Ô¸ ÓÁ£*Œ SvÁxª«S‡ƠwÑÍ̀ñâ“~3k¹BˆÓ¹>Ø̀¸½y5:J‚‰ô —=vXĐ:é$Oá`4̀&.wû,]9lŒÙYM¬B¥Û_ª8ƯWôƯ¦™ ©C6Sί|ĂÄ]ư4([†JîØƒ% ½ù­Í;X¶Ûç¡ 1¢]˜"ïÇX} ²¤´ƒ̉C»Ưjx"ÇvrWÂâv. ŒMNÈ;msø̀.ˆˆ¨(=£ækF‘\J_•÷”i”\bo£ÓøÛµ,“]{^Dwå>"óE6³-1¿Đu ü»“N5 ² à¼Q&D—"*xLK$‡ôêo¥© ù>ƯỌ²¯¥ç+Z Ï Ñf^q_É‹M3Ä"ÂÑcƠQA‚ËRt†£À«ªúÙ}T£}§¤”V"ú]B§’ư…ûõđ¯-ZÁA‘c²ưƠAê#¡ØB*5Ê=:đ W‘₫%¸ôö±c*9 óXf>È"tàEû(̃¥â¤iN­?46‹ơÎP§uôˆ@ê¨Êg)¡¬R áe(‘e¶g)²PÓÅ7åéxä₫îz{$¯̃åú4ăFûªđÑĐÔ R¦v1‹¯ÁD4LàÙv§>-Ơ>•ụ̂˜ƒª°ư¬ÄCQ›œÈ}>Ü Z¬ḉöLàWͶK¯OK\Đ jÉvb²ưím‘«¿ôj0↌\âñ=?J¿¹36¦HRvh’„üIY’›ÈçÈߌŒĐD ͇áăÜ𨔵]Gí½ûLM¶u`1²Êêp’¢b“ÿ,jíÅ&Шùf?TåÑjƯ­ªùÆ-^’µ0÷±bË)†{Y`SÏ×®cœÑ/ëë!’ëvb”̣7ÏtcnâÅ2Á.ơ §!WăâÏ .j¼OßRlèº`±¿‹ÈZXÈÔ{@sĂ˜˜<ÓZz–R´áû̀à É éÓäÍ‘Ư†v:Xm8áT=1<ôïm€.¡lĂ²n’GJ™`OƯ/P[(}….úñöy¡8Ỹ –ûm™5̀í#2ƠtÏëÆb‘/bOW(i¹ûÈ6’Bn¼g™¡æ+»H₫¿P£¦0ñZÇæ~Đ5qß@0z_€t3ômZ£ëÛÙiúvÈ¡J‰H%únƠ‰#éJAR4-[íøeÈÛ Óđ¥î́‰®Ø¢‹@U0.ŸÉù8÷œươÙ@ÁZŸG°8́g"™0̃›Çµ7̣1ơø€²¥ lƒanÛŸu:F©"D ̉JT Zô*4¿ØH̉#¦Ư4@ô(åê_¨ÀáËa*È¡—* 0ñQ!5&'…̃%½ªRÄ*uô‰Ăk±Èúöp@ \RsQŒa2è£ûß&Æ‘`·0ן;¢4Êñơ‡«3º·3oqa6z=ùªñm0›ïmsŕ¿u°UA«êjûŲ»tÎ9*NŸlyÖ.ù/¼ëÅëF‹¨~*Œ31ÄuVF2¯SĂ=a…ù¸‘‚çmơQÔÆFk®¿hÆRí|Mx>Hh‘§‹'Lˈó½ưi ’591ô¼È幺̣q2s}í́ o‹$œơÀ”!KđF¥+±úF63‰ Ï&æjsâ. –ă¢̃M,Ạæé»“€PåN –{jpä›`dĂ”:éQ́Üœ₫ñL@߉B‡ó»S~´?lX?¬™káÀư …}×>"’ÔÉZnÔr³®*Œ/"³̣‘²ä5ήÙé7=êụ̈›é>œEÈP¬ÓÎTmø{%4í) ©  ×ó4sƒLÉ8#*¸îí³̉t†đ)°$̣|[»Î’k,ï2CwWºeØqCmû´m›ÆÀú曜¡ơ2GÉ8•UÑ—ÉE@‚ï”Ư¶¯6׆[S£H°¬=¢¿qWC%@â¾ß‹æÆŸü& í±äÑÑÈ!+MT̃Ư°¡5µđÉưă×q復L àˆ%ŒpΨ” 4ô§¶ƒ;eçÏp]I-Ü X»Ó¿4‘Êåcyœd0&(W‘ÆV#–uúÔ¤Çs5½/rÛư#L¦ăÛŒ—âóI¼cfn¡´km×âЬÁÊö=§µ7-̀`|âúÂḳĂfÖîà¨çoœ=_æí­ư奉ë^Ă&/S^²%Ê-Êjàk!/;̀;“Úñ*6–÷hë Ơ€xóSÅr󟓨Kº7¡K¤/4>_Œ¦qƠt1w¿@}–eÆD—«D'íO3(ûÔDpÖÑllØ85›e_×^ Ïgbù5â,)†]£Rf’ßWy÷BûØN(8ßG}^̉aÓïéfsàˆñr»%l̀â3ÁÓÉwüKNØÂ)%›eÂTü®ĐCe§®‚ÔF3'nÚ$£G´„»½‘ư8+¢1~Nûñ#§ôÆôÂÅ}Àâl×]rFñOÊ,<|wÜæcƒúﳆ0_|A–à˜rª{zï ÆƯñJÍ–“ ªø7…)•Í̉}'̣+:à>É?Ùö¥O†âê®M|–ƒuQ½K?aKZZî£Kß4+̉ĐÛh¦.ikĐFØ]ËÅäÓ4f|mÁïr_má[wóUƯ L̉È ÄÏÓnƯ°rÊœàx̣R8ÄgP1¨×Do₫ªËú9·î7ªŸMé4+¿fª₫è| ±Ø&P:)R­›¢³ÙSM“ê!àhJRvXh/h‚ÓH¡7oo$ÀN-,P?æ·rµ;“Ǜڙˆ†To (ÙípqÛœ[^ê ḍ{„éü2ư—¸Đ‡Y"ƒ9̀nºJkJ.̀áç¡’̣ l<ñ¹@J^Â×òX€ Ÿé#̃”¸WúË}‚¢Ù²[Î̉œ •¡D̉Oøñ.¶æi˜qó¦ềwµ¼”7ESu:vÈ|“TgW̃Ứ»à€\(ºÑú:đøÄº°FI´–¥*¤DfUºÎöŸV°ra@£¡÷³üJLư7LS\[sªä§ ̀ª²^ˆb|̣-Åø` ç¥!-£å÷ĐL×1{'œ|¦¤8F ­haÆw§¦º—¸y¬́8¡«8j9u«âAó…I~œˆ|Hdy7[>¡F’)>É÷í׫́y]¼z]5ậúƒX¼¾<Ô®€¾/}ÛbܼîƒQGIRwü¾s%;F-ØQK:;³ÒX‰¶Ñ_Ñ ́Í¡tE=†‹đ5unÊÊ*̀'u…W¼¼Rö¨O;]̉³\9®§ª:¨đáf¨º³đü~”°®pw¿ª«u¹Äré¦ÿ!å'`è®è2@™ ë!tï˜ÚƯI ê#¢¡b‚’ µ Uí…¥’£¢Ÿ<́œU: fŒ™6g’UĐ:÷z®^ KëÏœĂB-¼€ä±QtöÓб*;¦´È]‘æÓhq’̣¢̉® ñ¾¥ü/́¥(tóá b 0—v'Ư₫Bp¦ ÖïºV½üàŒ̃Ÿ.®kŒ¯·sá.(¥`å!r[·‡Ñí̀K.R¨áF"Sgkh3r„ѧ §́s·[‹9($§âE¹¬́!={9íkĐ®>>ó]JÛ¿6đ­S•|Ôéé««ưZéªx¥ă#³½>‡‹Ư½©ñ¨ñMl4ô¾) Cи‘“(i9uĂ µ9V}tÇæ xŸơ9r›VåĐ“óæk–ë=·DǴÔH Ă ń,9̃́'Œ)·¼#*.á7n¿V'3Ă=‡ñi8CMφn H2Ñ!­i"³ĐEà¹?ü éÈSÍfÇ/«§pŒ»Ä–Û­ô’2äH²ôVaæ!ơ×7 ̣ôB­NTÁ̃‹~^̀,%— æAñrö§À±ÿĈB ¦ÇC<9wÑV×YSDÔyÁe.Jvó‘.ámLNÏÍëăQA:öˆ µá*äúUbêç– < —ÈH{¤%è0Ă*˜Í Ñ$Vư¼S°3œLc€²à8“&_ aÛ¥œN¦8ØÖÂY<"Ÿz°‘>PQçëàf£-, RÇ&ŸƠÇfç7&nÂ:R"æĂ‚__ÊeR ʨĂ"R*áósΗh?€ơ9İJ­Ζdåfw'Lv¶çípŸ\A¦ím~J>~ ®Mqv¿ØOë÷?ÿ¸`‹̉+Ü%·–~¦¬Ôw=Ç$Bè¡ÙÇ‚̀mư&·+*zRĂ4CjŸï6¡,Z±Æß3ă6‚đ¤5÷4§ĂGB_ÀLVÅ.¿.‡*E/đ5/u Âdô!Mû”"E* üÛ‡jÀd¿IäFƒ!M«*(mQ9檄µQ œ×¤’†S"x£_¹s꾡 ®‰œ»¦MŸÍÆAQV­ÿŒqv øẂ_{æ—êǃé²P²Ë’X kƒ‰s¡7 ‚'g-ééË3êÙB"ïOl²°˜=:ÂR1jơ ưôä-ØÑÖ·çø9¯~ƒ ÖDÖ& ¢€ụé$DC¯h_OZW¤r“È´pÎîâ „w˜árr¿“¦¯SVî®lđl?Í 3¾@N7IßĂÀF&MjÏzZ5À¦ ßẽ„đ’5¶{>Â3F©ĂPơ¼”̣±yTùqÁFjáó—>èm³“¡°-Ư ÍzƯó@‚¼×xöüÊ"Jy.d¹`rhZqçp¸Đ̉đ¦Ù’³bï­8ưW,̃I „H½Z+„»ê‰`ÄåÙY1©Ă¦™]¦ơaoQë^O8pjŒê{µÉÀ’ÍSf€Ÿ́Dé¡ñ-«₫uµ́²2‹|[ÇĐ¼„µÀϘN>¶‡UT4WeÄ™”Ïk¨VX›¿s.H?vgÈăñQn´5´á–ÂKvÏÚ)£Àç;ÛJÖg­±MZ†\ƯoGEd·¥Ñ̀G ^Ă ƒ³Ư†ÓÏ•;¥||iÎ'w«MXcî ×A|đă ‰CSyk ÜcöPë8ơ¾¤é~ )#Édn‡S% 9ŸOÚj‰8= 3syk?™À3Qo¼‰óEbƠh5E‡̉B2”}}`™j}æơ£°[ü&ºZ v•ªÙ'îè½8Cü`æ°~Đw§Ñ`7I‰VDy05 ‡&ohö×î@WàÚ+ÄP}„dzNFăøIŒÑ•Ëmö“}ĂÚE₫®†˜ˆ̉E¶t—­Æœ4áD͹ÖMnÂÀØ9­9ÿ€‚n>Pº"Đeº¡í£–Ÿñ·_}˜qÅ]®MuRh8©)oÇùQfüTÈ£IÙî<~Z^€T²£Gˆiíºœ})Kç 7ÅëÏFá³ZDà~¨-îÓ.;¼Ó¦ †ß¹+Ơ”¹NĐ<2bæ34ʤÙ,0Ï)É́iÓS_‚ö8©¨7¬(ÂdƠÆ>Í!₫”匣.¯5¹ơiô \¼i eîj{3£ˆ§½ĐlĂ!WaËÜúñpT̃˜ăY¥%ƒ#”ÔS@tb°6»bôáóiÙNwJ!NC²q­£×tRZ†y²t’ätcN`Eé´Q¸Âú|_±Œ«Ac'¼T³û %zÀ‹µx8¾NôØz0N}̉1Ùh9₫̉&9̣aáXh•f|ă›rYBÈ ­âÙÂRªcúK¨÷Ç¡ .ư¹.gO˜‡°s:‚GSæÍ~‹2(äï̉̃:iî „’“¹k]0ŸM,0åôàæF—¤‡•Íz‹§^”îñu[Úжm!’n",ÄîöĐvÎε›í§3M¸¥OŒ8 kÛ§×Ô›Îêʶn'7e² Ôch…¦$¸¢Ơ­øOkÀçî“DhQĐç̉"`ÀƠŸ£…H0Èăâè2'›ÏTC¬˜ ̉ơ¸Ën‡nW4 ñªËÁw°T#ÚnT”sǻâ]DG<#;EÉO4÷ă'ÅĐé]‡Y~f8´¹·b̉éíÀº#?ȃéÊ1éºá'ÊÎṆ!Ă» xÚ_ƯúÚoN¡¿$íZ¬“r`–¡'È6™z?ă z®µ,"3&pY†ñ­Â“Ö°×ưnÙª!hü1ú—Á:²ÄĂ!Q‚å[i·×ÊvƯ¢S´­¨?"Ø´1CƠƒ1\$%ÛliB[Ó°‡>.£Ù4âùÉ9boµó/g\}äxE;9³:”Ë•-$c­,Đ&‰fÚ1ÄÍi­×ù®ĂW„ƒ B®ÊÓṔS‹lؘ”;_¥©m÷EÂÑ(¶xxWä܈ư²W7hl/‰{:¦ Z[™¾“Qû·s€ 5Ǥ}.b™¤Wë62ẹ́=ơh/Ë–ä•MÏÏßÄ•̃µq«̃4ëÈñͶ°iw¶@äƠs3đ³¥ çka|̃À5Ơă·ÊøâR7-×*ƒú'i3¬]Mă°W–+q×â ×BÈ„Ùq˜°fÛ4|́Ïy*-ü‚×Çđz´^̀øC´zj»Pœb=ñ†—hÿë;Ăuº¤Ô’2‡Íaz "áO#½ND\'Mø­-nư2`Ï 3Ä/³OA„I—Ö¢é`qz•è”Gq ʦ!ÎÓUFàŸ±A溸ø̣Ơƒ ÙLÙ!ơ MÁđHÀ6¤™{qu½NÉ(ûJ́UW ï`軣ùĐºù(N;k0=©üêË=Ó+pë²°²G¾PNµ1°¢§Đ W‚j¬'aËŒö?ôĂuoe•új`”N—è ú½ êSª̃ZT\̣P°] A瘼3ILùzˆ#Ǽüđ·ÉaD̉±‹[^[́‚}è¡́´MÁå|»¾ĂÙm6E2̃ ymŒR2sĐ¢bœÊhræ#n6pW†öSÑê3?ÆJ‹ä+nîÖ™¯Å§ă×Ă¿ñ3{"ĂM đ.yĐÖäÆMŒ‹NÇ,%ZYµ¼a;½¡àƯt=.h5!Ưđ æ€âë7!œ3}̀ô@}¥å ˆN…PÇCÓŒÈ0±¡%™̀)ḾéH@Í™ 3BlíÚC;Ô}̃qtÛ9@)ömlÜ– Èơ¡Ă(̀1nCB`†![R—o\&Ëdm̀aA”ÂùÖaΖïºèÿ|曑̃dÏȇªßỊ̈ư dăQ¼Q-gSµí5ɹdgÑ•Wçà»ă‰ßY•(.¿Tï:­s¤"˜đ}­ ,z1ƒœ#N¥yŒVfWd„ ¡́’ëÎdÈ™#gcV€Súy7‚å|Ư|·*ÏĂξộH‹f"áq&C4A)ïe†Úƒ@ä¯$KY9ÎÔh‹‘å¹v¶a>§â ̉lâä‹¿}Ú}Í„®î¢ïSæwlwbăÚé›^ÑÊ?W¤¾¿åÛµŸkcey³gy,ù9­#× ;ƠEŒÜ'ÑU¶¨LíỜo“) ĂÀ…nK×ôÎe¢ZØViŒĐƠK\¸ºs₫\0Ăå³Rßië BD¢è«‰À÷~Ë®4ƒ_8Ѿµ̀dḤè„Hj2/d.Hl› Ÿ`߸6;IÊ·ĂƠ¹³ —0K´ñƒơKm=V‰4ÔÅTŸ ơ½Ï¤‘øHVé§t˜0–¬Eg¥pw=lÖb0 a"ÀÜ÷"Œ1Ä "-ïϤe„GÆWîQ^Ï7£óƒæÓÅáy‡ù*-§—xÉJÉ¢µ́è1°%Ô±é-„fŸ_â¡p/¥G{ÔïF„ypoéRdn 3ÔFĂeeZLk9·]X×Ùmnæ¾J̃̀Í'›>s[·7›èÊÖߨ*$Ó‹^%xóWR?8]a®YBÿt¨[é­øJ`º×tơqdVîÊù‡-Ùnđ϶“j˜Œk¿R™~¥E` ’nÎîÊTÏMÓó*ç8– ƠflU=̉ît:/¡brAbµË ßXœp12d¥o¸̉À +v´W&đP¦¡w§̉r›ØnĂ[ü2†¸§·è‚0~¾ỗA……›,gÁÖ ]™-óĸӽP_©\K™s±TG$M«¥ˆwH=,{=„®3ÙæÂÙ.öª°9\£ë”°W»/‡ø+GÂZ` cçIq£!Æ“G{âXzö8 =†~U<ˆŒa¤»¬Æƒ<ûKØÓ̀a*¢N §₫&´*ăƒ^a€†'k ¤ưđ₫³HƠëô«'^Mơ•3Âûرló¥·ÖmWndKsm©«̉hÆÄº³®Ơ4́€ Ùd7ZOùç₫‚§ i„!}¾˜hf¦ F‚0ïíÅx»^+˜]™AqẤ˜ô1»1´™\¤™‚L"pqÁ–:( lúƒ>¶đE´°Q\8<đQ­ ­–m©°¶üÑ’Mô ­K¼_—èF1̃‹!‘¥ăé´;*pÉíwaÚRp¦•(‘ozåk¿rE×9„˜WɇvcWô¿ÙmÛé,Ånlk˜^_ÙôSß°T?A‚úîXï9$bs"AG£ăưÍrö.ơg®ô8 äîª3ŒfU”̃o‹q‡ođ ¼É•âM¨ Ü÷8̃4èÝƯ'œÀFCÓØ9sbÜf†6’3’G_(´)Ơ0‚WCNwÇ ¤.AÏĐ¯í ߟºâ ÚlƠĐŸb'¾±ƠXÈñÈĂëQ @3_·†x8ÅŒ /n[»î^Ö(¢Ø'¶ËnÙúÙ7kÂ'GÛ± ́˜²ÓU(œN¾½x6"ËXR,€í÷J'¸ơYÂæŸÙ3td œÖªzrÚo`×ù¨UÏĺ;Ç}ÿˆ°ođJbÖ|dÉW7o–̃H_oz¼d•¹† îídw1›‰täƒ5Ë.|8L*±XjÙÀ1₫¯sæÀ (ëểÀ¸bzh ß́'*ö̃₫a u“Èhë^û+Í‚„FÑÆgeÚ üG±uƒ­ ₫£d‘äyÑ¡\¤ ;ü:đN…óGt„ 5æÖ₫³‹ÖhN2M¯̃˜)ªʧôđˆtæÛ‡…sk°ÑĐŸc[q H†=Ëe¯pÛ4ú·4/ÀÖÄ Û¯r¸Ô…ó* es‰±+T—¼>`XŸéƒØ¬ó­«bú?HưRôră±7”ÂJèL;ô$§ÿÀÎv= ƯëU²‡…Ó-•Öuº;LZŒ7»fƯÍŒ¶åHhuÆÈÀ×G11ô«Ơsô|0ízh³}p¾eÀ ̀\À›ÓƯs›¯y„·¶Ơ"%è ‘¹j™Î¼ªÑ¢o/Øú³ñ/qÇQ#æyÄ©ïÊsJP¨X•aj­F̀%#O¹Ïz·’…s¼Gă kȃ]rKŸ2Đ́Ñ_“¦\F&Ô|>N˦ ư²₫¹Y* ̉Ö"ÙA¿SA®R!tZ¬«7‹¸R4ơ¼ëm*oBáA~G†½T¦„SÑÜ@J´J†H—Iî2-Ûú¬ë<ÓVôST| ¾Đœ‘'h‰>_ÔV&r%è—ơB| Ÿ oVUaxPçæD/º˜9BèÚ,û!Èga"1™^»(Ÿ‹5J¹¸%j ¹…Û°„t5b°ºĐ “ÖØ» ~C6–Lœé®ŒĂ´²6¬%¤±qb~tæo÷æ;đ^?:D¤ăƯ_nÖ¸¦“ô¦ .ß߈¢ØÜesßæ£Û÷Ÿ¾v% ÈÂƯ|‚¤*’¸cí «ùÉqœ~Hs.–‹s Ö¨.k{$)ÁÓ»Ø(ä!q ₫½&¬€ œ-)ÛAñ½=?p©.ö•Àbë́îÜơq́̀FYF8•ñS„elyG]°$ŸvÄÚ› Zwp,XmYĂmª`I £~½åYS³ơª÷­Œ#{ë)ă§3ĂÙ6é;€K´<¼ÉÏ$j̉‚zùX~ÂB$ƒ̃/ÏCÜR —qú’óCg}5ˆw\Çܵư¾ÎI\Iœ—?“‘¶ è>vÅ&w'|ôö¥6¬̣ú*CT¡Ă,É ásx}ĐŒ0xÀ24øåC:“ù~3){9ÚsÉ {¡eÄ7Y!r¿cBè ^l%CZ¨à(퉌;;ơ™̀ư8WÏ œD%‡ 0$ÙúAeñǿS_ÇèeO›„éjg‰œËQ¹æ9^—OU:ƯúL|ÉoƒĐƠrOk<38ßÛ?  4M_J–·ÎưÄù¸FhễŒ¤₫Q(.]bKû±HÂÇ^S5mv’tƠ₫zê áGFM›ë¢$‰¦Ötp¯)ñm ;ÛƠ:ˆËQÈÛåEÎ)‰f,»;˜ÔÏÄ”nap¤´á·.–“ü&f»çBN¶nl,¦K”¬plï‘bï¾Zfl̉îêL²;SºÓî²á½mØz|g`lî0pLZÅY¿E$?º,N…L"Nç²?öC 9jë»È®så,«U6^ÁăPăÙuwơ—²ơû ô!bơ*sí´ !+\]·,MÉưüø“đ™Ÿ0¬QüóàIe”Fc@*H’}11«¦¾‹6 =£ü~}₫“̉zûy(©«„VÙ‚¯y¤¯;1¤K₫ƒ¹ƒư†SxĂêvÀ/NÄ"̣Ưzôt7ơµN¿‘:́ư`ßi‡$•ăŒ^ ̉̃Ơæ)‘‚v6b ]́ÚI!s` 4ñµîuuká×MÓ°M² Ï~”đ›óÄøM¾ƯÇëú§†ÖT¥¦C÷´̃FÍ"¡ bdö¢dßf/ưˆ³1a‘M]uô'\‚”…‰o»(âÆP™́úÖ—(Øm(BS_Ÿ¨I§@÷jgYŒ–ƒmLè eøyFdƠ©%ôÏm-;qŒ x|pÖ ­RökĐFâøÇF¡ l~œ¶”%¢^^Å`Dÿ"“WkVlr=_i!g„̃Øp9ü­_₫q/ơ9mÅ 7«¿2´"7T>›ÔhÂSpc»À°$ddºéÓ.LuÇ“ê퇉ÑWøKđ©g'V•ăxNg;ÓXO…ÙÍXèhdBƯor © EŸZª•W£­³đj°Àï–«³^é÷ â,§ªg¹ñiă ·œ‘¢ 1QéüaNø±ÜÖ¢÷*è05uư’3¹Ât)Ëưn ][uógG’₫¦ƯR|´ơ– '“…Ê{ËRløz"á‰'Đ2›B¤nƯ70‹ ơgtM,¬˜²=Çë5¨B!₫é/LW‹Q·xnrAˆ‹Ú ]ˆ’¶Í%‡¬Èk‰S̉ªv{Bh®·Ah‰\ ˜,•yƒ«ÿj̃Q£ô‚Ü) S 9XZȬ¾"¤ÛP‘BÜ;vsº•y"rh÷q±„÷̉·ñ9̃[¯‰¿úhù³Ö>úÚg7ư‹“á×Êñ–ü-/|ñú¦=3đúï>Ïcy(º?pMÀ›ÁơpM¨²¾¶̉È}IMö«S rÈ )-Œ}u(ê,ª‹ü*kđo=đåƯæ„XÍxˆwÖÈ}K¦Q(F^(̃/>øQù*U)‚ơy©rbº5p<~ĐÆ%˜Xˆ“¥$<Ó]•œöÚΗ'†è[Ëư¨10hJơûh•ăÂỪÉB?Ḯ³6»Dơ‹–ç₫$.̀Z1ö¤%đFqèHȼ&85”ÉLdÑÂßMxäÙ\ñ™˜.&³\MÎü]sª"Dî¥c>³Ôvzfù‹Âë$Öo‰!ç¹̀´ǻs¡¬ {_Å2…È 0÷oĂÆÈœâ6€ ư”mƠüOm;’v·=4×HŒ₫UI/Æb6Mâo›Ø@b:˜LëyÙưm³´Ó[ư–o®7té₫÷¸*1§ÛÙfÎVCQ'V·̀ùî Å—¹¥¸ƠP _’ Ÿ³]œicq¾Ư¶Ă9D\Ưƒ~Ÿœ®„u5!ût¨øaaWåCz>.΀ ¨ûÅ\JR…ăƯº=+N÷|³ñ˜¶ÛEEÚRäK©„¹ÖfÿwäÚIÍ0 Ƴsr½ø+ŸRcŒ°¤%û-ꂇxhj ‰Û‰óúfo£º$;ßÏW´Ç˃èyÓ.¼₫sL>L ›DêÊnV|![=¹È>P%k̀v½R@HƒRTÆBwâPaú+™V3 ‰̀·Å¯…k€¼Ï}mرç t•̣¿ÄÚN´p~Fp4́€Uk‹æâ‘(Ç7‚ø¤™ÅĐ¿@~Â'hHưjHjœ|’6IÚyEXÅ¢¨ÿÓ¾}̃½Mé _WÔɘ·Æ’À̀‹Ps‰B1 ÑS,eTÊ1Z©c›YTŸ]¶‹̀!£I¦¬çOñ3U`ΡÈÚ#ÍÊÁ–e$¬ÁèºÙ*‚„Ñđº`Ó´gÀ*¦Ăñ€ª»í^^LáMFâ>¼Í»2â¤GÏ,ÿ4¤Z>ƯDoS²2Ñ¡́«FÚ{ʇLr¥"üQư ÙĂơmFVªâÈfUĐzría#0_d‡ Ñ2Oë]g4È+¥Å϶j–’O¤pN9B×ZOaăV)‘a®̃ÉÛÏO8¿°ÆUk„œl"T–dr-¥&Îû ¹›c‚ùB—̣ ©­¦)My“#=È|I­i&îx(JW†›&ºù{èÍË·z<¢L)j4ÈŒ&ûÊf7ä*f«ˆ-ơ&P}]–Él°Ç,Ëkg hQmneæ¦ăyïFÇïͼ&‰9µ&#\»²x÷E’yˆÅ<íT̉É´GSZ<5èÉ5Ghº̀‡Ưü0#ê +‰_Gù‹ï3›ù[p¤$ÿ:ï^k1Ừ2hä¥4À‡nĐÊëÎY™ïmƠ_;M%¤¸ca¬o.ÁgK‡Ó̉ÀŒ¹ak¿¸z§‡/~¶SwW®ß=PpÖÿÎK-Àü3ÄwăU•Û\©yN‚åÖ?µ«–)Z-|#’ôTV@¼jbŒ˜â5c̀ăéMEdûK½E?µƯ/Öđ¯x,H])’\×Ó|®,f‚̉Fơ¹ Rpz‹º¬¥.9“n,êµê0êo† ~ºG{ä叨¾üæn;ëBÈ/ú%¤ghX&̀|vv?˜ÍHùùLàôûVBúú2AÚ)oµt ”apuŒ/”âjå…7–¥¦ßR$ˆy2 ¨Æƒb$² ùbŒÅ̃‘9u7у 3Cí8%xôƒ÷+ÓP~Yv؇2'¥<]¹¬u'íl¼2?ø×iH-­Ê>¾tl³˜¾‡dÂÁ”à7Ë@?èø̣Ïx|.±ä‚x›ªÖRPEè̃xôG9wU¾ZsÀñ0ĂHñ˜lû̉(§•‘Ô,Àôœa@Jb×c*V”•qÿ)Ót°̉)ö(U÷`½L!±¿¢/óæ×P¸Yººq;ùkJ@BÚ—̣kE±H•Ä&b¶àp!7N‡ø¥ÖƠe†yY<ÇDˆ¢$/Fb6lÏÜÜdƠ"d5₫ƒg@ïô2Ö[k¢˜üC¯f—tA­bgÏɳB W µ85ÏH¿Z²Üë¸gÜø¥½¦₫ûÿvÁD_œ’XªJÈÓ5 Å)Å%.ôë<:ơ‚t] Kz¸!¸É¼Xç6² 3ĂăÇ5aQ1±Ïß¶Dý_Ơmk!Ă|讨B,̣yF)£Rct±́̉÷Ư? ÛÔŒ”-•´w&ơĐ€ÓˆEÆú}bU—)s¢rI?áÓ§N ¼D$]¹ihê‹ÓèóY*ëlƒ}Ή·ê ·5Ư6|¤Y5'êÓî.BpiËø_ÍÈe`îJ,̀—(Hµ©€j 5xzu ?LåQ²Ùâî5ÚUp#Ơ°5́Qø›:y.h|_§Ü§Đ4D¿ñ4¦%ÑQ1]{đuϪ‚^(x`®ª̉O^HJ¥YÂn>|feɽÂx\X/S«K$«hô“Ó‚ă€¥'êçØ ÿájSƠhSæ«[¶}EPq]ẉl“é$z…‹ä¹.oâơCF1l£˜å̉êăª₫­¨¬ñ¾µ-(sÇüAếAF™1­Â4¬±É&öqcÓ Ú¯Ê Ï—|‚Jñ^…H#^eN†c,EâTçùOĐ#«¤·fBöœF§Úƒ„ơNª‘•¼O×íBz§ 4嘴%T (ÛŸÊhy¿!âĐ%½ù&R[ª&Ö×R, pU âb® ¸–¹kp£S&Z~SDúDcr5üɺÆÂ /j¶đ–ưÎ2Zê‰[é‘_¢‰b=‹bC£F‘]Ñ ˜©ZÀ±7êß6Gαs̀RoÄ„ @]•üqø¡]:àëîäWÉne VJjªû©råi µp-—T₫_m'üRáˆÆ®¥OĐ”fU^ëN_đĐ¼°^ÖBC¬±äªáÔ²wΡy›Ó½¸nÏ5}Ônµàt>æX (´*{›”j/Êzͽy)U˜x‡WµP×QôÜÔYl’œ!B’;UEă‘HÑÚi|]FƠÏĂGbú<ë†Ù‰èï©[œK˜—QŸê Û‹OÛ/Ưª›|9ÂLtRRß × ÈU2¸§Æ‡óÍÑTS²ü!Dœ™Ö.¤ơl̃$À‡¶ë^Q;9¤áªƠ5·Ë& ,î¼áâax¼Èˆ[Nï…p@Gà´1zl9'ºáÁ}É-¿qb‡’6ë¶jS)ặ&5ù¡vÅ­K₫%Å~â,YÇX”¢_gEOÜR¨ŒfÇŒv•‹z’ÎôĂ0¤Ù̀ ø\¿Ú#ƒi €pÑ@ơ§xí)\wÚx¤ină—u´2éT§DùP{ơÔ=Đ€i[xÈ]#¢äHºdÁ8bf̃VƯÉ5%>Ơ,ÑF±Ăv˜¹*Á–ä¯̀ÎËä3‘øÛzd̃́ç×’Hèl÷-̉‰L¿à:n°œâ¡V·4¥đéâYñ¼/e²#́V| <(&¥Ö₫1›34œü̃i;¡jI*]Gƒ‡¢™ˆ©O®̣×;#ơYUH½>Zn~Xyw'¦Iú0GP‡uOVÉ­.“Ỵ̈P<œ¼Lơ †°vIàMù|½7>ÔƠù†‹-^ö¬([™»%ÜẠ́˜tÑ$ÑLXÂH¨OMœ6ñr|>+pÿqe>â}ZúyÁZ̃ÎÄ  1-ÿ@™{̃[DêÀp$ˆÀĐà#Û²d¤uÑnÈÓY}é•#ÀH” ûe5-/+Hc}¯ À2ï°Áé¤ _…!N|%)–lmOôÿ ö÷ó6Œ³ŒÍ(ßåC\/ku[瘭‚ ±L屦åƯẻMƠ¯E‰¾:ÆVj{f6£!ĐckØtGp±c…× ÅÄè ×₫ \¹²×£… ,̃K„ÿ'¯ªj­-'ÈpHù•ÚÍ₫†8»áơ}T—ZS đK‰D­Ywó¯kÀ̉¶“³º´'̃[ V4đ·>lm(â ¢ëÛ=L^íLØ€ôôöJÊöQë_×tặVÓ"h:2ö;¾ĂuÔ¢²©C6ă£µOôB‡,¼†wBÁÔµỖÀ(@W:iêăÄv~#Œ€Ô ¢™n†ÿÛK ÜD@đ D<ó¥4rí¨ƯüO葃,=^ăn­̉Ó¿ ú"+(XL}ư/}_³ÂNuÁB©Đ¥ïHh4Ç­höEÛ“l¡M¼W À“€UưáäoJÑăªœ¸gL»'Ï(ô¹@¼‚/zÂÚÇy*ó¯}ÖØ¾ AWå| hdI4©ÿÑỪ̃¿ûH~¦n_Ä̀Ê]<ß¿Í×đÆËÚâyhÿó’Y‡Å_ÔÇ_œ–?̉ÀUY­ÂcKL~˜ VÎÉúÚÖæS'aè.m{³‰$ï­úm蜫Ñ%ÎèH ß—ăa‚œnf!騾ùâØÂ»)¦¿a4ÆE 3.O¶Cá?À­VŸ¬¸˜rjѬ3¢§‚’%ÄÅĂ₫`:“1̃‰ Ỷ\Sp”ÄQÏ?Ư<¶x»„Y@Pư5<° å’† G¦±1¦[Că„í" ₫§pÈ8l@ éq¨)_³Êă₫ïqâYé©C5̣c䓸aÊ‘€©×¤ ơ~c‰ƒ•"¬9@z÷ç‚ZámF̉R}«ac=Å âFfKÛ”·’d!ocSˆm₫k!¢ Ñ;dËz̃tï“NvI0æX4 %ÿ&cœ´ülcZ ÁLY l4k÷Q-¥g:C}˜q“x2¨™£̉c^$ Û@‡k›{©ÂGçÊ×*ÚûD#ËØKĐĂΧ7Öƒr̀̓œÔG„ Nq¦¬d 6R©n HRÇ^¶§"'®6n…º‰\}á87;wÅUÔ¯m7„:ô\¤ÆC̣$rà`]e–‚ùi&’jElƠY¬……ÓưEFr ×â^+Ê.è$¹#&ùœd¡Ø0’TŒ;̀·w%¨‹OÀz§U‚@¼uCøTโ o¼^5 åy©éP–UY!{x…s™"8 ]Ly¿p¯AzễRh?Ñ‘x¡:£G³û h>yuĂƒp¶• ­—‹ ;ø/•1[yû!P!ØÎSê%˜đí×î¤E9̀Ä}»w±y?—Ưmíª¥€đï₫¦w{)>÷‡Çª߆ÿ¢ÊÖ¯L`ºyg0^Î?g•ƒäÔQ‡‹8̀ç âVẲ1^ØƯÄi'?—y>Ñß*óÛ‹¢`ÍÍVï9ŸΜºdüëGÄtÔDC´̀V˰ieđÈS£̃ß/Dt]†Eƒ5FiÊ&<óơL.a‡ÉNéÉÇïă:’ÓDà&Ç›ÊË× ƠèܽڣahM’’µQ?Úb¬¶Úfr°³ É•}FMN ‚}¾·çÏ<@+q:ce%¥V1̀¸=ñrXRÇ¢ú?0̉E‡}(eq0l‡'–)%—dăñ½–Mb.-¡Ưíư—è"ƒ* ñ‹=íOPÁpÙe cˆdŒ_P«¡C+t$đaG¶jíQ”ñœé#<‡ư÷=̣#z@‰₫‘m·Èpƶ\{̣Éd0¿Cxë® 3₫s0:¥ëQ#´gN§´=Ce‘ẽ$)—GN?0ÊêÖ#߸Œ¯l6ní“?1‡‹LÖ%º@ú’;Ï[dÂW•=¶ƒÆÈë½>̃ªPÇ¥ˆÉđ£«ºđD°•€—h ̀ÎäÇƠ)\g/}{ ¾F¤&X)¹s#î‹7³ ni|Ü£Au~ÄäzĂ{vS"HQ_`Û!©%M8=”đ&wBm³[‡$‡´º„åë…í²OÆl³'»E¶–wë ÈcƠç×~ïU`l2Œ˜.­iî¦C=Æ ¿/oÂø&2C-Uî–mJ ±̃ûà8¬û}́cƒ42„̉£6ưI©2ñf?za[!Ň}/™ …Œ„¨ªQĂj¹Å%Î –Ö$óE!¿W?Så߃œcµt€hoẼ‰w‚!–]âŸó U×đ ÚrˆÁkÛƯû}6₫Á‚Oí?9‚̉Æ’!Ï_+Äy[fÉZ°¹`”Í5jÍ«"z¥ÊDgöÀÀÖư}ăïcX¨ßŒ÷´`Fœălü,+Ù“kN-³#²S' ˆÅơd)&¾Pu¯+9‰;ùĂ¿á8ô^•û”ljó?vvV(,/p0ëiA…¯́UÍÂ’|ÍzP(w˜Yññ̃2"‚j{Ù[’m¤•(oÉ?e …èxÅ ÇùÄW̉O8Ú]z‘"ÅK ™Ø3|zCø#‹vªƠ endstream endobj 1361 0 obj << /Length1 2127 /Length2 13081 /Length3 0 /Length 14348 /Filter /FlateDecode >> stream xÚ·P›ë¨»»”´¸»»»»,Xq—âîîV´Xñ̉Bq§8Å)VÜ{Ùrv÷9ÿ?sï0̣,}×z×ú’ĐP¨i2‹[9YeœÀfv6€¤²–?€“……†F q₫-F¡ÑººœÀÿ2tC^dRæ;e'0@ÁƯÀÎ `ç`ç`cp°±ñÿÇĐÉU eî²(³œÀ@7I'goW-ä%Í̃è,é́üü¼LºÄ® Ks0@Ùb t|ÉhiîĐt²!̃ÿ‚NÈq`eơôôd1wtcqrµ¡gx‚ ¶  ĐƠhø£`€¹#đ¯ÊXPhZ¶ ·¿äNÖOsW àEಂƯ^<ÜÁV@WÀKr€¦¼@Ơ₫ËXé/&Àß½°³°ÿîoï?À:›[Z:9:›ƒ½A`€5ÈP•QbxA˜æ`«? ÍÜœ^üÍ=̀Aæ/Ü #®0)đị̈Ü,]AÎ77Ă%²₫æ¥Ë̉`+I'GG â†̣Çù¤@®@Ë—¶{³₫u³ö`'O°Ïß` [YÿQ„•»3«6äâ”—úÛäE„̣[f„¸ÙØØø8Ù@ĐË̉–ơđZ̃ÎÀ?•_*đóqvrX¿ôY_₫¡ø¸™{Ww ŸÏ¿ÿM(́́+%`´Q~G­ÿâ—Ëwy Ù^fÀöÇß?ïŒ_ÆËÊ ́àưÛüÏûe•V—‘”Ơaü«âtN^f3''€›‹ÀĂÏđûï jæ ¿ÁöÛSlíàÿë¬/MúÏy=₫¾~º¿Wƒđß±Tœ^f û=âFlÜl–//́ÿσ₫§Ëÿß|ÿåÿ6âÿ{ w‡?Ơtêÿ?jsGƒ÷ß/#ëye§—%ÿ¯©.đ¯•UZÜÿW+1Yq°Ă?m¹É€¼€Vj ˆ¥íŸƒñ—XûsjNn ?)fv6¶ÿѽ́•¥ưËsĂíeÿT_Öæ¿3Jƒ-¬₫Ø/n€¹««¹7 ÛËqps|Ø_Ñ èơçXYÀNÀKu~k'W”?.”‡À*₫‡è/â°Jü&^«äo⯈— À*󛨬²¿‰À*÷›8¬̣¿é%ƒ̉ozÉ ü›ø¬*¿é%Ÿê?Ä÷’Oí7½dĐøM/4€Uë7½Ô§ư›^̣é₫¦— úÿÿ‹Îü7½œÅâ7½XZ₫CÜ/:K'‡—+û„‹ë‰£ăoÿ?î’Ơê_ø̉!à¿đ¥ëáK6ÿ—p¶ÿ—@ÿ—ôÿ—³9₫Fö—¼àáK^§áK^çßÇ~±u~yöƒ€ÖßRö¿¥mî?â—›s~ÙW§ßUñ¿ˆ\Ü Àỵ̈çäÿ[úß₫́́/U¹₫ _ªrûƯÓ'7 #èúúr'nænÿjûKÎßA_'¬[Wà¿ZË₫âă₫/|é–Ç¿đ%çoäxñ÷₫ÿk«,Ư]_ê‡üùØ{Y¹ÿđŸa@ ĐåÛ¼“¥`¨]cèÇÛzqROæqáƯ zfŸo®]î÷ˆ©ôïs‚×]¯ÅS‡û±V¶¤é®Ä–ÈŸ|~´7#Ft$«w>ø>&jLít¢,N|(ù!̃4H†üYKl×÷ÉÅW'ȶºG¦ÀÅC­÷Öó“¬WÓ`Ợhøüúî{EÔǪiæXí£ ̣YB‹Ü9"J3ΙǽƠơ N₫Ä/r…DF¿£XÎRƒ ¸»¹·«5Zn½ÄÔÄDd°W8£S´>ûi „ >e1ë ylô,P‹à¾¢3 +“kÖR fÙFÿó2‹)(̃&€Ê-­Cȳ”̀UÆ&wë§JÛĂØ$œZƒ%ÿ‰6S₫†`6|x¥Æë½†¯Œªâ}VBíj¹6.LJÁ £<Ûu¯A ÆÇ½vÚ•|ú§ÆL”‡ÚnsùŸfĐ¥eâ§,#¸}aN¦ƒ€éàj«ÜLăoG•bné°ÎË é‚=w=Œ'Ë ǻzmƒci^ßtb#±u ¹vsˆ´e4Cí£)¬,Jâ₫WD+–Níâ₫‰Ûë¥Rª ă]> ôtM?Vóộ΂êÊ¡ḳi.>i!t‘LÁ’3ˆy+;×]†ü#¤É¥”%ö¦ïf©¡4¦f,ç2¦l/ІƯă¼*ft”mf•¨9Ơ`2–ñ¦¿ywbpçÔà1ơ8QṆ¾‰Üë`@8–. ‚k0€₫5sPnÙù³j̀‚/Ö•ÚL¦wi­œµ!÷̃ơụ́øcØêm¿q`²€ÄỚ¼µºđlbQóaàDdHkQ\Á·¼Û¡œ¡íĂ´Æ¾ỡfM8S¥qïm½¯6 ]T‚2Vx̃÷üè2,^ư´º+„{Ó–Q†ÓƯµ÷v—µ(!+?Ñ×µr˜míÚ2fáz“æG-,g¼Hïü'm^ÛÁ±d™¤W4ÓÆprÚÄüäÜ=ôtä¸ës–ˆÉ‘ „Ljđw©‘ÁØ8rZ5!‚:“—`˜R˜d©5đ Ÿ¶<ă Âç#=̉o˜gaDzSw‹l/=ûÔwc6®a2ëM.©Î…äƯ·6„±ƒöá ­±{ü™º Ê$q©‡C£Zái[e}Ñh_/ÊWà̃'aYoO/c’́h„bÚûl'~ëÖ%úGçæ₫Áµ)oDGơYW]ˆ ́²ÑX¯6"”{²€ÛÁYDmfèõÛEˆăs5̃́hu!Fu†MÂLúX¹æ°YE¿µvơ¾j[ûŒHÄlªød»äŸp#¸N,®i›©1§K›öÎú-ƠSY˜ÇªûÇu(ƒ]Jméáü{ÏÚÛ'æKèWPb[€‚ß@€ísyÆ TC¬Ñµ´_eƯ‚z%<À®dÙ½Œ'vQÀ…¯†-½¼? ¯™Ḿ’ ‹¾â-£ØDÅƠó¿Ăâ¬E[ûL(UÙG’t…lIƒÖж˜¹́ư^AR¸̣-üaÊ1!ö´!à‘™™̣µR$Xgw³Â1óW?a_đY®°®sY$ă–Ă||x!‚œÓ¦ ‚÷³ÀWơ ¢>±5ÿiæ#w±™©S#R7ÍÊ$Ág/A”…º ôº7ÎñéĐç(̃¢£Ïñ&’ĂW8çẉè¨ädơ 3f$è¡H˜FË„J9v4OÖ59ă°^_4²—b\VWº+đØ…óë· ”§äEœ’-”(ÈŸ×â;/«äSM¾â«úö¸³˜|ŸRÁ̃s¿ Éñ´0;âïài,¹]C²RPC«ÿtÆv|y¡—Pv6Læ|g8¹XƯÀ} ?́¾OnB³XvnFöæ …M+  Ñ™<ŒÇN¸øfÔ3zy¸«´g) ©sd7œøv(ă©abùwđnIÀç¾ ¯ó*¿#BÔA®ùc&ưyú_¼juI‘£˜)ºéuÆÈz:ºZLô¼8l¬G‹‘z,ñàåC’ÁMö¥Æú•twäZ]·)dcïí&Sóu‘˜í“ïëÓO\r₫\8'1 ¼ÁYBEÙ“ưƠx’ Ăj»“Đ9A}~îo÷û}sol°¡]™ ²°H öƯ·¡/ ‰/7 ¤öBzW+f$3lñ¯£†åmg`êUŒ½·¨¾Ë›­¿œñ7i‰$ÈPº)¢KW¨æd,¡er¯_ëç9Åú!ơˆg”ă>̀l–#Đÿˆ²‘ºÅ±Ô°J·êØ»¸Ëg2•ÁÊ.ṿÅuß6¬ùw=«.Ïl‰Oíö>mNă4ö¡+ydŒåÀăÇy»±PnÖµüD€f%¦s³d´­Ö/ ”ÔWêÁ%%¸û'©|'Êy$ ˆlœ»ÙAk±ơ&ÅöuJ÷Ơµ˜¨JätK³”J³h¿^ GßäiºÚ=`¥₫D}̣püå“ưmĐIMÓ.38 ÇÇ7á¶ ¬¬™́Lʤz’mQk]]1á2TN3:n Ç.‡¾ªLÜó¶à .éOø²5Yêo;—: °ăÿđÖfˆ%s¨ÿœµă;— !ùvVItQIẹ́:F8ï>œ¦_ÑÂo›g6­—6@¬Éñ¥:ȱ=©5^™W I2ø₫ik°>’lF|¢iÆ7Å¥m– .‡èI€›üç`— t‹Ûý-®¢ÉÙ~ÀĐåZæ(©lňDf4†³I2.4®ĐcÆg ©ߢW´Î0«¡ĂéÂÎDgV˜û]«Ñpœ_́¤v~y ¥Ơ^¬°£|₫a~‹ ! ’*?—& ä#AfŸèûƠ;ÏR­°'A1öo·Ç‘Yqoê‚₫Tk« çí_ôi®¢ă8¹,%v{ºH½ ïx±₫ ̣DÀRΤl;|5-"EóĐíÈG@Y7(p½áªă‘¸&ÛÚ±ùv¾Êà›o½4??5OÅqiù½( Ô WÑà°¸Äă8»²|1" Úw]î (à¼VjÅÛZ<Í2snơˆ¬̉¤˜…Ờs†¾©EÈoăÈ _®²ŒôET¡7Ư²Ï}ă¬ªí{›üØXÊÜ|*C±₫¾™ió…é92h¤óe8ß ̉K¢¦––†nZ%ơâÛ©•# tm̃#o¡²Ú¾7Æd™DÂl·©iÏgr­ÑOZ½ˆv́¾ÇÍ£^¸L´²gRoL´í'}pÁXK!al̉œûÅVøúđ–Xa@F}¸·+É'Tñi9̃â+uyÚ‡ơÅ*₫n$C_\¡ <£']ă팑?agA59U^DTl–à!¨.½{rÔ¥¢T{ §UÍKÛ÷Ÿ;Pk\a›52q¾ăêJ¾9ɱÁPûX?Œ¡á"HDïMºƒ¼=ºÄ¼œû¼̉Ç£a"gLJ"0™Œ¾²ưZ»Û¦9S±ư¹¾ ®s à[¡Ø«v‡Å%ΉuØÀ¬»9›{œ5}‚c’¾g°-Ï̀_•çḅ£*đ†’^ŒÈ¼6¦Ñ} 9[ÂñcêÓD.¡`èc¹(ACNÎđÈ€́Ḷ†ß\«¶÷“7hÀƯVëˆÀ F8ºJÓ̀Ñœ­âËs`Á‹ûƠĐæ€Éó~G»N¿ă´̣MmÅi‘3 â©pư£±‰€=`È¢sºÑĂÆè9$>>Ư"+¼nœ{Å1ú.DL=(‘×cÊo–û-§ăÆbÖ9ëç«÷M5ùÄͦ˜Q₫=“²ÖgP„²GU‰É\)ÁL¥µï…˸ni —Ú·¥s墭ÁĂË^ï>k¼j>¿ÏWb%ÓàEbÉiƯú „¿™è*MxAj>-ë·F´ßéÚXˆâCVm,D öĂ½¥„TèÉCè|AE ×·H|èQ–ľd•QM¿öóỒkUÁÎ. œWôµ•N5:‡ơgÏ»BŸ‚3ÍƠ_³Ç¸¿e‹TüDC¦1́ ¶Lô©ó¸²¯$=™Üö_Œ˜„!Fợ‰­uVé_·ÎµÑ-’Ôy}K¥ƒ|!§ƠÓ?gî¬åe¨&=g;ơJ¦•>Höx Ú˜S²s26´nr`ÃØ7ˆƯ-•·ˆ³!H˜sóÜĐ¥­®,3m{¢— “«%‡TÑ>Œ̣µ¡û÷sß,|Í!Y¬+høÿ°Ù׸n¹MöÊ•…₫CªCóuaê—i#ákÑHơZƯ)N0Ä,:‡­èdÑ»S¾Aª ̀2i{SÆ,i¯ê4rƠ¤đS„f¶¤T7¤àÛ²¥úëú•àÉ…áXw2‡z1®úO°¾\ƠÖ—˜Ío ˄ب›~•Gù~pQ{ßÙÑZmJ—a³(KªHëø©̉ö¶ÿà±ÖºÊ uÁŒ«ü-W s,/»ư©¦[j‚g…‘ºA~l3ú·Qf–Æ̉¢ơ飳 ¨Q±Ù×ËÙa+»ư-ÍÔpïÏÆ¨̃ “ö›¿iơ™ N5áú+:ØMíèHœü\&:ñDvѯû¨K¤ÔèR­I~’ç´ y^$E²ªÂæwhëa3–ü †7‹ØO¤Œ†ÇR34zØ€ éØ×ë0'ñ•À¥¥ ÉkÉíÛ™HZQgDQbM½9M°ûá-Çnư| ̀!„]ȱB°ßÙ=’Ä ×|°¥§kª‡F0ÑѲđúX³¤xE1HÍZfyûµÈfá3†#Y‹̣ư‹9’d€;1Ñ­̣ÙÜôuØzßÈ=T¢›!9ÉaCÈÓu=̃ưQŸLÙç¹ ƒ? nf̉Ù<Ó~¡p*º h}¿[™ˆÅ©0ªùøö4.ÉáUU„1E)œó“Mî 9¯,)}ä{½á†NÔ”Ja÷â³ÿU“²ˆŒ½˜Yt2³èêG³©GL”ÁH½Û¶§tW‚†~ )»æ¥äѵåîâ- Zæ(̃5y“V¡2Gô„¤êê£N!0_8ơö‹& ï¦{qPªi|(†Wzêơ‘•Á9¨›ưkD•Cª7úÀ_ơ‡¼Âz¥‰HËZâI9pư ̣DÅ×»!_[ ÑÑ*z¯ßOŒlùÛå‰K¤¢/©ºsg ˜Œ̀5?Ö™¬Öª¼­ +=f³!ÈÏ‚pd¤fKØANÍ‹ÄÆ)Ѻr58ơÇú°«~„oÔT̀:4Ư%¬ ¨™rOçRg”®g·/Z…ï=1›ØIu°fwÓ‚2Q#µTÁâbeJ½‘­W×A.w¤â¬Ù¾:ºñ‹’}ÊË2ÍßuË™m‰‡‰/`;Ngu£̀¯Ô&›'¥AíÇœØYƒGµ—3c$ó²ÛÍ‹!­¬1+{Ÿv» Î=–WÖ—Ô\^IS«¨™˜~ ¶ºÛ÷hh».§ÄÔʇ’4<÷øVta”yN±ụ̂â\¦KĐ̀üú°oL^L¨[KiƠ»Éƒ¤(õu31(Ͳ)Ô­™ ʹëKÇˤÇclÉC¥™„Ó7DO®ă¦ˆPtR̉́LW™{tm«f»-u¶ôA#1“ˆ¹;´®Dóü`÷]è^§(rĐyÙÎ\‰&ßy4EU:Ó× ÔĐj ÂW†°fĂ”ˆæ»IưÜóäưTqÄVˆº4úQƯ₫„¬ÍÁ"u‚ÀY™>ªŸéc¿¯¢¼̃·6(¸¶Ä­aEhfƒ2J4b‚}uIZE7w‡¯³ ­Y¾X< 0 5j×Héy=›ñîuZ¯Cr¦̣ƠeôM_V•4ˆ6âH[áƠûm†ỡC¹gé0M&QVј&T’%(‡–Pry¬´—ö«ôè4ørE²37ẓ°®/v«…ç0ê±̃‘È„øn\…AŸ y„Ñd|‹tÂj¢D¿ơ:º9,‰ÔÑ{Dø"2Bñ°7=󽿨â3 ^}ÁÑhEÂÔ²Ư•==éyI\o¾I¹f₫(³V[†]‚)ă@Œª„́kưyWFTy?Đ´(x•Á¼;-æ5iû"̀§>î¹í™®Ô₫Ψb«rtŒw[ăÙ û OVÊ AkƯsʸt¤º-6jl§ĐÓ÷溅‡,cE˽¬–by>=V”â÷­D·Æj~’ˆg ´ˆö^_/ íyV§1¼†C`h:æĐMô8¦”blŒ “nI/ÂFuß·ÖB—)ÛzƯlç«Ñ̉Múä“îÛ<M̀=!*™Mñ=nè ;²²Ú!é9b-_鈕 œMu™PxăY#qR ©ë"-L ȳQ]5Sm((]·œ½lOF«3ÊQd¸`ÍĂ~hƪkCÊüh“ĐÈop-Äæ±-‘ØzùZWQ8=`[=ÑØœKh¢WGˆ¹Vhaâ»X́BZÜKùÉdbtÖ·À÷ ̃íĐôkJ]øy/öÁ•ë ÜÀÑŒxZÚU‰n¦í",Ô\¯?'k@̃¡¥};óèù¹‹` VÔ NÅ1XR; ¼ù~ư1q>>UĐ!°×NĐD¸¼êæ#+ÔWé ªa.ÔÎs¤È¤Z½ˆg„4VEqé1Ô×»•+èy%CkK +ÓX>¾Dđ ë̃Î̉ü4(·«½€åæßœiÊ6Àb̃©@đTT¬.骺Ÿ’ŸLƠ½d₫ †l©÷å{Fc6°¦“X¤4|NE4¥‚eê‹yoÔyZa7P«öÊJi.Ê¿±³ bw"3¥ë¥̃ṣdú¹â₫º‰R±,Vø}w¹ r¨~}Úœmv$9±oQ—đ 8nq!¦O+j́…&4đôÔAYóÀirê΃ vËá’Å7—Ì́ê€fow¦Í®¬r|3ÔŒx0Î5]{¦Uci€ÍÖ6óÉÅ¥—Ê%(2Ûâ(?Ê`-@àf«"£1ƯK}jß{o+k=„“r›Â7ªU >B‹p6"¦ £–v¦c:«Êèt¶›† #Ă}c lg50 ° P[#ìËÈôsÈ64ÛíÚ6÷´K¡+[1ïlÉ¥»ÛÙ ËỚÚ̉ÎȽ´ZpdÂ,""Lp’ƯD¢u¿—̃:Ft±f ̉„'¦ œR>™|¤[±hv£"º̀{‹q'[“ösF‘Ϲö"Ú*ߌ§_„rH#Vˆxí]†¬̉'âRŸgv‡¯oøÎlhüñäe:~%ÇSáfñ)x¡5›çÅp˜±Û陘}q«ß”cT}Y{Cùá§lù›́ª̃`¿L²T*&“v ®ô²œIfKâú ƠÊ—*Ê·9l̀†·~Ï⤲Ÿ—r{0#và'ià:¬ô¡S;-dÍGjḳû‡¢/¹©\æ\ûF¢ÀẺiñOx{3²–‡HDiŒwK±c±z—ơ×[é°Ïó’«% Ê«ü¯C,EÙ]¸To#‹Ou\eZMÇñ¡0Të ·‚w‡<đÀ¦_mÖd4ư ÛzÜŸØ̃-+Â*QQ: FM9ÓdÖq¦oåïÅC”ß¡Ưœ»Ø̣*Óưä¨N¾æ(”»̀Ú×|oơăÿU;̃ Eœ©Ñ6Ẳí‚ G£Ñ+^œqKÀ̀zÏå-ßóÍy$Z̃¶Đ¥ZÓ:ßĐÍƯÆCêÍÑÜíưVÁpÏ¢ÜTCWÂSËvjZ»u°Ä¶Kc¦¼ă¦E™QÔN±9¨jCS|^uh|&‚s¤Bq]Ö¥º§0ÙHwy5çĐ<Ù€çÛxûè”8IÏçºômùâ>D¯^úµvæĐw{F_}1¶kÖŒ’w/»o§†̉TTß`ûgŒ¶›"Ï‘¹&F·å¾’¼¾È/¼wç˜̀Æ,ø´z°Æb­0¤úƒ•XG+bÇÜö»ÅzâÀö±¢%i-̀°Ù‚'yN0-§×bM>ïnÁG±YKf¹82¥·ƒ$ ¥7Rw‘ ‡{:3O™ ûBEy~¶ăØzGÄữ¦iơ§Ûơ0v́f~+ꇃ‘IÈ&â»ơo豦Pkïin>Iú\Tă‹[3àTÔ£§ÏàVå,Á~9}âu*¸]/Ƽ"œ£í—ªHeÏ¿‹âơBº¯Ø̉j;â3A¯ÈAöú±u 0ߺG€Æ°]y¢ç0¥Å̀e¦ä –"MCEi[9 v^Ûp¼+ÚÈÿZyÉ'×ô#k"m¨ư›̀ÛÎX²=~ú³| ²†”óx ¤m­™'Ă/èĐ₫À‚f8Øí'ÿ»&´2ÚDâŸ^£!ÀFNQÛ“àp̣£¹Yx'1₫öû§~<¸è óö4ëúív2[ÿn‡‡x¸bög´/Go¬C>ï|gÙÑWï…ˆ·9ˆœÔ$¾r$=ÁH¢6ÀT7¹Q¨ƠƯh^:¼¡0™ ¬‘o©[̀•µ3É­–¯wvM?Åí- (2SÆÑÛ „uË.V8ÇI‘èüη₫ÎÁI²'̣×úíö4å·‚åÄ™§ÀbÔơGO%©£]b–°Œ)^TFṆhZÇÄÉdÉæ9è:QI7º@yÅ÷¡ºó×$FÈ‚gÉíâñ{®…ÔQ‰Åj•$†”bùŒ{èøè,\đ#A…̉QV”YYÚ®ËVÜ¡(1æi,(¨èź9ôŸ´.c©°›€mfb wàdIwfèÄ9sœ=A G!̣+ăGpăQ‡cÏá^ ¥–û ,à ă©›±Üí£ARJ,!ÑûÅ»{0È®B̉‘ï ÿËú8́ú4öuÏ̀Ă6BÉ*[ÍŒ`›̀ºë‘» Ơ‰0ٵْ“âNf”ÇåägUcaуuK‚ØGåi;­PẺ”h@½Î•7—»°¯½IÛg‘fuµîGBÂè¨jAæ/̉sƒßà—ˆơ¥:Er°Íô|ă ‡ß8»Ü ¤đÚ’±™^'q®ˆóÆéYÚJD-˜èÇB+aiPŒđ …<ÛÑ$ï±Äv¿#‡ă“WÛ&M9i´8xN(Á…k—ö3LˆÙ›u2ư¹w²Æ6QÚ|üÍ´ßÄ’₫f•]®2?ôÜÙæ|quºä[ kqxIqï™=Ö7nEóª4ûÙøơtñÙÊ‹›WÉ:¦œªà* ­XWçlÂnTçoçơ¾2ÊÍÑÄ”Æ'®*F ‰—›Íø¶‘wè (1è>̉t¹‡è×Ë>ơ²©}^Óo>¿â%tÜ—68lÄĐ>;êÏôpÜ÷€ÊÖ-ê±z±O›œ'O‚Ÿ}=‹êEé:{P²·»¹}îUç@_q)́ÄŸ§G¨Ó_Å·+dÍÙ½2|#á̀Ö,A&OÉb<Đ*ty«¥x̃ÁI‘¡ư–Í75đîMïѬËÇ‹ưª;̀Âz¢mJÊ€rV4²jÏpŒ|ïĂ ØWfeĂ‹??§†vy„N[¨~x§ óỄÏ…ÂÇØM‰8 ‡†e"ª¦¶V’©#Dï“a|«ÑăƠfÅ/!³ëđ¨”[ŒB₫C¥ëẠ(QPZ(}n :à«{0 50цǵ”¨₫ów+æđBvC3́~Ó'{=kcWp—À=¥Ÿ %Pjäô±¶ĐßđÖîÊ ë”½rI”±€¦â't;鼄«í=¬@®ESª¯ÛßÍÑ&I!¿ø ®ÙOÊXBøJRËơ2U?iPI{]́$q OÁ?¹8ư9>8¦̀‡Fß³ÎÅlơëµG9&ơm²=¯EO µäÔ—"Øö÷¡FŒ‡¹8¿̃M4Úg{w`PíVí#|c¾|ëÉß3 9±'h¼5Y| gcmđVÊgZî5¦ ªú¹RÛU>î+Ê£­dÑ´§ ă@*ă¥qœ0EŸ‚Ç+%t4Xi×Ù¿·Ă|¨Kíô¤₫¤½¤§´’ăÖàÑ|“4ú\¸MŸùÑZW]Ïé6ÚA,ưáUÎ !Êu&蔾h`°[f¾ư®ˆYÄúăX º~» #çqJ s»íÈüºpï¶ËϪâ-·‰̣&Å’€ă‘—oN<̣Ao˜Å«Úù_ß5CÁ¢™\„™¨V%­WJ`¥LŒÄ‘EÂdx@„q¶5nÍ„€¿¹NÅùF.L‰ĐÀ„¬2/Ăw^Ç)f)¡âgfŮ߼c¯^ÿA€4Üăß¶½&R/ˆ6©ÛđZ(kBd­b¬=›T©ÿºéủRÿY¿#´xü9ỏ§­ºÏ³D¯É́‚öàĐ~ âH>¬°° }¢\DăÀ {íùàû„XºupñMê&̣Ȱz¹X¨äç<ø„fÆØ£!8æÂ(³Ñ:̉Öi\ ”GDœỌ̈E'phâÎi₫0u°²ÁNÖÄ‚dî 9/B€­U/hOvÇa˜,S, Ê]Ä•v#‚Ø$̃¿f,59Iûˆ„"IöÎâí¦̃·p^¹Ü\̣dŒê>€^S@Mî]Ḱ ^Îa}Úsn}¾])Ÿñ‘>ơ¾m×ÿÑT*Œ†LåÈH½Rí”á»NC¯„«äj3–-²̃ø>H®gù}I?=đC#­_†x¢_iæ¥Æé÷oå—ÈæŸÖ&_Ư¹ ‹¦ï ÍÀđ»>JTæ¸Äa0`,Ñ\wÎnF øy%đƒFEîädzœ­Óq₫ªÅäs„çØZ»Zb›ư‚Œ₫¤åU´è”4Œ£’wBMˆđ$ï#ñ)Ê&¿/oøuÁQM~k±+Ueß4[uE]h(®¿÷Öˆ`Ywª´‚/ïJíâ"dû²³}›)cñăüÙ,|E§+&à¼÷i×B\ÿ¸®2Pˆ¯R¢ª÷à»Ï¯ó:·¯Û“Xb¬D̀wLßÛ5@e đ1Q¬ă¦|ho»à»¬æF˜Ø̃__+ !̀&̃ïâh¾1Lôqfv‘D|å,AMM˜µÍx1Đ̃È7ĐŒ‡7WưuGúråC)¢ƒÁG HΣÅ[̉½¦‘PêQ1«m(¶å}¾ÒosÎwíBÚû# S?Ùá긭† 2³ßèâpy…₫ƒØd™ˆè£‰‚Xû&ú­ÁâÄ ÿ̃Z"ÂilxªÎf„˜©ưë+q^äŸ?‡g̃u³>”3Đ×j9s˜G¿üU8•jbà·nUÛe¹#J̀>‡ ºyÆ´ECà ꨂ‹[¢Ü¡³‰‚» *wêñÁ1bf—oĂ.if₫Ÿ¨ê‹‘uÓ̉è–_… 擽m, ˜£è•R&ÙECàÛ¹• %i<å·qû6WFÁ~)‚ ÍÏ=wjê(ÈñÍCº$n(@†ùê©IRcáeËr‡jMF¢GKe|±¸|ärDo”ÆÆk"Çú4v‚âFæ·!Ÿ›ë‹Oaaå’ï­ÙOÜ/º©{D?¤×‚H¹mkĂ“¤Đ¸Ú߆Æ̣­xæáS=Q)E×áïëàÓ{ } ÷D „5̉Å#f~û‘́6nOæ¾rk„«K8€»x(ÈĐA{óÙÎÄw/àÚ‹aÙâC…CĐɸllÖ¸N|ß9Zy³9t4/BıảÎF´ EÏáÏ­B°†…râmùéÉtm‚kügm‹£‘-;먂e˜HEù >ë "]¤êđNhô ÚÅâ¼/Øđ·›ˆÏ;9˜7•´À 5ƒ–é,ËÛæ¬e Û5q¥WׯzTÆ ¡Ktç¸ç÷YÄ?ƒºê3y·ÍØ¡?î¥)8Ó ü*|ó6l^½„$w=z(¥@\v˜Y'¸Ă±v.»¡¿“ib0Á̉’ưÛ*-”j'K›¥¾`@QÊøgxÍö¾íΪ%+#­ÛÀB}Ü\́2¼´zû0rr—7VÎüºùûë ¯´=É*ñxÛ ̀cÔáS’˜-$@I‹Ữ|áv ü8âJª­Îèø³ă3·¯‹‘&fä_é:`ö̀¤”À¢Œ*ơ«í÷»ßHœ“2ĂXñơÍE˜ß 6hăKˆë0à!ׇaơj¿›2ÙÀ*° lyh́±q®Mÿ@ºbâz%öĂAœ£³eçt\jƯx²^¨¿bµ \pè %®g`́7=d„1³åơGÁÙÔ=µÈƠ`/‘µKđºSE"ôƒÙe‚ªg¦ơ=—*àbhơ¬sPCØ–4QæÜnÏ®Ơ,W¯1¯NCđ÷ê;à·–x ÙÛ†gº.íY³{!aºæ‘Ưg·l%ÂQ¢­‰¹ø|¦S‘jn;ˆ́»­Å„f H­¿Vø?'í®Ä`›Úëí;ä‹D#kèGĐ ËƒawaæỂ3äƒñs_}2z‹2e“¹Ă²ßuăvê°3QFtª¬É¸?`€s–€KF—d›ÚlÓNǺ}^,rsxàêX]ǰ{ëÈíÎ8GÿĐÿ 1á¿JÛ¾"È“¢Iï«"”Aú½₫&àÖEN¼à"xØdÇʰ²-°ÀjÅÿ<—½F½kNp8e¯ ®‡,oă–ΦG‡Œ72:íé­ ­;ơ„7˜aJ¿•oùöJFÙÏ]™XT~ÚỊqª— %ƠAr¾#¯Hcup—µ#XL*58v Ơèt¯b‰îswáL+‡X"בΕp‹ TeÏoÁfb™RG$`Ï›FRvÆĐDו2©N¾ñ1 |́LkÉ\¹ÊJQ̀ÊJ©ÆƯÏàr$X„x¥9Œʧ2Pú¨]ØƯù4#”ØdÚ—&º JRÁŒ%nÄÔ2Iº…¦}ÓúQˆm‹*@ÇđZ‡GwKùùËÊYû]üÿi|׉Ÿd A84S ·9~< aʉđ/c…®·œÔ(]iö„€TŒoḿ€W6S=¿æ.¡ERœh‘­V́™+dÖĂô£;×…DOTÔL®îèY=½é|åxF¸:—×Y§0:»}³Ó¿D0p×úEy¾ }\6ÜtË \‹ÉÛJ+<₫H\1vÖn÷̀|ÏgM*iÑ ½rƒ ¿g/AX·Â²7â'µă×TZ¸œâœ§]yŒeđ󛹫,Ö˜ÉùNü¨‹æu¢̀q‚)EæhfA`˜·ÑñÅK‹â1ˆ·f§Do1æXpÊÖcê‡>Mb¿ë̉ur¤»u%2ùà₫4V[­­¦C̣×Ó„¡–èˆÍKkØj/6Y•-×K@»Eágù₫×=÷OË´UÀà‘- tn•á‰À£¸ñ“‰•<ˆEC#£ÜÏù0_å¦rx—<Çù_k»̣ç‘æ̣Å&§#¶àAV1Áø)K„̉‘5h·“¢K¢ë́ ùµ ₫°½[£¢ËwFü*ÈRÔ”X,„†>/$, <¥p e¿Ñœ“v§©Tœ%@¬sị¹ñö÷9ÙƒÇ ôCAĂkZ0©›§ßÄüb*Œ×›úAé×T®Ü¥]Ñû¯\¡Æ­¢†w˜ôƼ1PZÂPŒ›Y3°>ÉÇ ÿæHwY®Îék‰³6j¶–~'́úª3 k¨P™6Đ"ϘQüFïƠâzƯU?í™ÑssăB"©Ưpænh¹%³«Åq«{&¦,œÍ̀!·€yÉÎ5₫Ö˜]–eå,U ̃IđC6VV 3ËNw‰œ•OwXvñDqŸœI‘$_ö†7?ÆVÎé#LÁă»²Ờ}Œ`Œ¹ïbH0Ç4ưw‡Veú¹ˆ¡CØ£ư_ZÁùn¦ ÔưTđ«Ư”§)åßI|ï"Ku Å„<Én@?çkÛqVTÓXp:t<6Öæ÷́ôxŒ¿³[đà{["F —˜b2=BÛđAMaƯR)rO™Ø¦~2–j+₫²¯%Öí*«‰Öñ̃C=E5Úë ±h.,û;~ñÅW±]ÄQ,rÂJoèÔq̀.ÑjêR~†pØÁøù®_uGÁvÆĂKâa|äVÁû—k"“üÓ+IŒCu:ƒˆT%t2wÇ]̉9 RÀMí6j?ëÏ<Ă.ïÖyS³Ă ‰âÛhG9©đ»@8¿|èLÙĂëN“1½úz¬ßI䨘!p°¿ILUêØ%áủ Z®6Iû{~d­To>ÚÚH?A!Ơ›n¬¦É#tS&üô@¢––¶ñ᫲¦×~]Î0K̃v'hÏn¨„§#²e/«Ơë_ÀC4¸̣̉÷‘ô°ö‹}¡´ÎƒÓûS©hµØ_áÀ+C;CØỞ[×W-Ç[đ»[ É´~yßU„h| )·ơµN†K-ƒßë¢"—"²’ỏ̀ ²1•ỒYÀ.Ú#úE-sjÅüä/ûÑZ_Đ~hs`"#nQ‹g>ª₫mé¼;!à¯,+)K<ö”°³Ñă]³ư “_aµ°èè9Í₫öm¤4¯ËæIơ¦̉Sq›[Ơ¡ă”´4Qrɵ\<{ơ‘ƒbiiuăj†™c]ơpg‘ºå©éZÍ #<Ø ¼ăù™Cn@Ц˜ÉƒÀ?u­ÊÛ΃ELÔFƯ\Z©ç|c{ÚÎ́UÙS :{[fÅijC!Q́Ấ¸âˆªc­>ƒlIßLøsoN‰jí¦^à—* €Ç…¯×0³̀ĂS¥Ô¥1Xl"‰Uœ¤Æ j@Û0j¦†¿÷ŒFÛÅñ3ÿ¹Øó­ŸrxR®„¶ –uÀÎm…'<‰Äv?‘0ú^ËW³̀]¦KàqP|/ •Ó‡€ë× #@x¦l²L@W¶¨%:I·ùÍa90Äi›„úˆá¬ö‹Èá÷×'¹Öît3³Oè­ơ¬V€Ú¥J½&₫›Ă1Æcª+H«̉7Yæ«_ å×"憢³ ß“i[vŒ”¨¶Y²†²fv›ªÑ0ÇỤÇæ&¨¾XĨë1± '“‡iÍM¹nà(ß]A >_MqHù”DàØJ¶í­Ó€µuBºM ” ¦tRà%é½è[faª Ĭ`gĂƒËúoÆb,yư`1›…§£×E£Ú¦(˜xrçèg q'Në>•€r̀íó»ÇÓ|?K~ÊæáÀ³…gÖ ˜E5k~2‚„/ȶ ( Ê,¡½V́¨³uÊUïcMÉøbÇ(ßµéÈoxëPÊ{+`SiA6!”ªqá Ơ_‘ŒÏÂøä¡ßd—ó+ä¡™oè̃Ưͽn!¸Đ:Nxg ˜ y];¤Ü¶äöÛ£'á³ü˜¶í·đ*íZÖÜÉa¾×₫Tơ Z}5‹â3d±oKơnûk:-1Ö*Ûơ&–Ëö¬/"7́2‡èÜEO.¯»o¨å·,ÛƒÇÏs¸'¶_1êaLⲆT¤DÀÎ9[qằ,×Y— í ơ´m÷N):J±Œ*‰ÇTÁÅ£Á/"á|zꦔ0rô;¤ ¡×øz”‡;đNÀ'®égđ›1¾âX1Ÿ0ƠOüUe 3Đ[r¾‰ñ+àÿ¹¾~ endstream endobj 1363 0 obj << /Length1 1684 /Length2 1200 /Length3 0 /Length 2222 /Filter /FlateDecode >> stream xÚµTyT×FÖF+Ï-*ê-lfeGDYˆ$lâÜ0'HDw\pCå½§¢¸€KBA¥u-'X‹ œ*>—'ø\»´ §₫ùNÎdæ₫Öï~÷û]›ïĂ%l9™H‚fó9₫aÀƠĂđÑĂèTHÈưÈ”„ZĂbèóÇO4I鹟x2A¦éŸó*pB®`NA®Us# |±û¿ÏA&ÖG["¤ÀÅêdJ.ÓÚ¨Æ̀g̀ˆ’Œt5© L¥¸¢+]ƒ¥B@SZ˜‘₫©càÅwr\F#Ñ£Áa« xô›’®÷r°pĐ<Ù£¡•“„JäPÁâI‰Ăîÿ3sƒzhU*1–í₫ØÁÑX ®̉ÿEü ¸hÈà¶“T ¦äĂ5¸ÊĂqZ¦́'¹ß̃_ʇHTAÀæ;sxN®‚~O$3m*$kt5á̀寸]ùbeÉÔh€3Ï肈™AèÑq0Ø×?P2Wêø1ƒ…„Œ”ăD"¸¸Œ¢0=‹‡"pqé|$|9Ô%¸‚¤Q Pké   )s̀W )œ”3vÖ@ á̀œeÇûˆ́ưf\KhL†Ñ¸]ߟ„ ´®›ÏCá#;ú}øZ0 ÍG¹’íëKểÙNÀ¸ ­đœƯ› /c@¦¬ÿ&1ªøaÍŒ1€Pe¬–‘²+“ «e ÷̃(jăÁy|ø[–7ª&Xúïn³†³ö-;“]4mä¹ së2bŒÍʱª̃Ö-G®¿ÏƯe2'ŒúÔîâD./5g—µ¶ï ÙU{À¹¡¨² rˆ¬}äçQuîÍ:Áµ¾Ñ]Û¬ăJ+ḯVr“Ú‚R}£k₫Ûøê Í7ª‡Đ}o,6äc?ù´84.*^ưmmÈ0u͹1C̣Kf½Í³ë(â=4ÍWÆmèûÉk”cùböÎЇ#÷«ÿƯü».Ø‹5ÆdÈ&ă´ Ïï®y:|»b\vtß¶¾¾{Hêh“)§™ÿ"{ ¾síÊđj–A:wk77ÇjG¯{ÚƯW¢o·UƒÔ%·3bîÚ!³₫açmuñÎæw­ëơÿ₫‡å½¾îJ½ƒăƠº–7̣¡S/ÇÜèíݹók…ËÈ[ù® ÷Ï̀ỵ̈JßÅư[-²ÓQY¶ægRú&¥>;¾Ù4 cL£ÛK|׃ÇĂÍ‚̃Ö…Îk Ö4'_¶­™½ÿDÍË©IO®6\z=u´ợÉ9½E{œÍB:÷zul+kºơ*Ùªª‘¿;?å¦Ûơc…íÇẸ̈ëƠ›*¶sTæóLÓ™ùÎ{ái´Ă“mûûœ‘‹w½Ư£hú¹¦ơ]}Ỡy>̃%·ú¶ŸRHh‹̣¯º¼&}Wàdk¨}Ÿs½"Ï.׌kôït/©ÏÉby«ṇJa{I‘ùE\æÊ5ñóºi{ăƒ£–ù«ÆÏm®œ“ÔSÙ÷zéqEwÖÈû7o‚ñm„™zeÛo׃ÉÚöÈ£½'·]|ízÁí¼¯!´½\ߪ=,¦"¯ï•²Å¤¡èJK÷ù½uëMͪ ß›»pc]ƒûj•âܳ 3°®¨°ºæ7‚bt…oÁ¯”̣z¬’h‰µíy]'˜í῭¢Ÿ<»iü”»¾yÖœ”µqwa~øƒ̣¿°—X:Çú¹0Ñ«Ă—Ÿ=¸t{óØËÇ‹¦̀́Øb½¾~æ•2Ū§)>U¦e@^j̉Ó–üÎv—YÀÛRv¡>P7ö…åÚ́Ç/F6™dwo ^vusknyî(Û ̀’åM1«>ñ²µIàp  >+´̀¸ưpJfˆsË…m?Z™Åä>Œ/9ñ•`¬´Ü:bUÓ·[”9KíV¹ÙWOZ}º8©¦1Đ<Êj 橉fëÖ̃·4ç=]₫˜E›a₫Âli8ü̃:•vú»¾[aøå‡Ú/L4ûÇÖùM˜ù°3µÔÄƯjÅÆåoăÄ_Ƽ )½çe¾t™»Å₫%g^n[̃åµÁ°{₫¸4ĂQÿK&æ£Jwè*÷Hê\zmb̃Ï_‰{₫=ƯǴ'¨J^œ´ˆn^kƯ´jĂ³ĐCµđ¸/µ¸0êNưÖçÜàîaçỷq;,­ƯáWüʬÁụ̂ƒ“ Bÿºưóá_ó®P— »Sv©²» Mí1?¸BË®s,ụ»¥¢¹&¹÷²’æGÚơTÆ?; CØ4y²åÁû—‡U₫Ư,~= endstream endobj 1365 0 obj << /Length1 1684 /Length2 1200 /Length3 0 /Length 2226 /Filter /FlateDecode >> stream xÚµTyT×v©‘(đ*¢\=Bv[d§$"ô1$7ÉH˜ “‰(ˆq÷‰Đª Tq{R7@x*ÖçBq}pÁL‹HRO³“0=rCBĐ¥ø‘ºt Wkh¦†Íf*1Ù¾Œ)’É4}20B ‚9aN¦!#\H$A ¦URä0DË¢d@)så Â2ƒNGRï°øÉäÑRwà/ —8ßH£eræ_ „_íÂåÈÏôALzX€\"_Àç2{|°Rzœi;Ût„ |€†RU™bj\44­óârÓ̉̉8jƒæ”£ÓđÉ5¸¤‘T2@o j¡‰¡Dt̉8P€9+ ¡‡LR 9àLAT¢$d§ÿ†ˆ ™Úp ‡pP ¦7å†FF†‚ 'hH`„̉mĐƒD“ =Pé<?E1=Ẫ»¨?Ú¼‡îK¢Åk3³°´¡'†}ÆGÜ ̃¶‚$ô¸ÖT„@…k!ƒ^ÏœN˜la’đ À™œ´G°ĂHÄÁ¡´)©'ñơ3„B @£ÓBéG¦¤ ÔzCŸ?x¢I*û 'd‘ù)¯ '”*æ”7ÀS 0Èÿ]2±>ØÔ<S4*4\¦µI9Œ™Ï˜%Y™:RT˜V³pD/V¦[ M`VæÇÁ+ß(qD‡eªD¨H0sÀŒ¼w½“ƒ‹€ƒæÉ ­’$´é@ U,n8I#q¸ü537¤W A« ÇR ËŸ;4KÁµé?$.2¸]ÂI*Óñáú@Ü•‘8­Đ <`(%!ÔZØ|O( x¢™iÓ"Y£« g.7ä÷ ñ!Å*’ ¨×“ "f† GÇÁ`\©,V&›çö 1™‚©Ä 5ˆÄ£(,ÅC ˆD “„¯„F“„—C4J:T$ÅbÙC ¸:Hᤒ±³‰dæÔ$;̃dï.0ÓZFSd2ŒÁ•èú₫(¡¥păB̉ ÙÑïưW Nä₫Q¶¯/ìd ù€-¡­đbà)âe ÊT Ü$&µ"߯™1¡‚uư ©˜•»hÓá¼]٥ͻG9Íä<̃c7768ÿ³ë[k'}áÿưiĐ»léÑœâéedè<¯„́Â¥Dy¬S®­¶¯ưXÁ̃¦ʯ|îbÙaÙ“ÆHῊçD/+»–³»nëƒà’ *<.WçWOÑçúͬ­ï]'ø¹ßúyÑ´øƯƠÿÛ>*mç%₫J;̃xmœưñI×§û{m₫¹;)¹₫ekâ<»óÁ£u'ê't́ùZ3̃{Ûë[ó‰©j ¯Ú)û¾lËÛÅi[™X ÏNg¾z}¨ñâ Ëà}n3eËünŒ®Üă=¹̉­¶QX½ËêŸw›¶º7Z̀:Ơ1±_жJX6›Ú¹A/ïqÛ›j¶}—úK•Ư†MW¬\—K_8€,÷yÅB³;© ÏïƠe´Œ÷o­ZS;µah¸ÿMáç ;'EóL®~h?ë·Üë>ÑóŸnÍqW̉ưÈÍêTäƠgù‡'XNw•Ö;[Ÿ|:6̉+Túw,X¿{”t₫ΑuUS¼‹z„ͧ—ÆJoÖ¨Úƒ4»ªV½v̉Fñr½ỴU¹s–y¶.J>₫̀"iCwm³ûOÉăo™°½|Gú¤ô,°đi3—·&n ÚWödÛÏŒô¢8Ă»,_ ÏĐ›Îu>‰ÍÚvÑzzË#Ù~4;ç§Ø‘×û^Ï₫”¶¸Ăăæ£Y¿ÎÎozéÊ{ù-¾=c¾=p+í6^¿$!·;aÁ«“O‚—xµ‹]ë¥r =»,¹gÎ’­Nª7~³oÚ¡.6rŒebà×;́ø=¥cüËRưOöúºªÈ=zêy÷¦qàù®9OÎĂ ­{­‚B̉E[Ä ,ûgG¼Ă¤^ç ̃©ùØ~c—K<á₫«k2CÖ|óÖnæC×Ï›‰öG»DV£¶J.^•V|Ù²­¥ª|ÍŒỴCW³”±Ưqo+¥“~gqîàf‹ ùÏÙ,_Ù<ƯLâÈÉqÛz£ÿ©ƒă›³O}d©Đ¾‰—³~mŒÆMd÷$G=̣`å—ùc- µ·Yo[ºæFü×ăaă|‘ųôhưÑ”)ăX« …۬ǻ»óß ÿ¡l$³œÊëïû^ |ĐPy:Üdó·›QĂ®ä4uG]´ÍK¸/*wøá–Bi9qaóºƠg~,}Ø‘QT»̉Q"Œ‰³üeÏÜÚiy.æ¡̉ư©•qËøMÛécQ²¼ó´¤ètGÉ”ÂgÁg·Yµ§¹/ WT/2Ë«º×g´µ´₫Æ÷8óG¯S½ó—TbeÖ¾½0̣Dçưg¬.Á3#Çè^®¸ù"Àw”{yw˨Ά–k'rf¿Wäg‡(̃̃ù×ê’ÏÛºZ^ÜulÙpo͛ߗ„ƯØá¤̀^ÉƯ˜ß3́·Ư™Ë|œ†gơÏ«r%÷ƬºZ—hí₫æÇ…}ưuœ¯¬s;ï?>eQơf4x^¿Ñ6C|ùåØÇqó:î¶\!}%Ô8ß±X2×ÓgXIиFMÈ™YV"vs{•v'ñ™÷̉ơ‘æ₫2¬}tƯ˜ÊM‰KE{~·Ú®8’¼ßö‹ÿ? } endstream endobj 1367 0 obj << /Length1 1678 /Length2 1203 /Length3 0 /Length 2226 /Filter /FlateDecode >> stream xÚµTy\W÷X±Æ[QAŸ(WלuÅ@AHÁ$輑d&ÎLŒ €º*"¯D„¢ x¬«"R”Ơ®`QĂƒz,Új•º ”¾ Z…uÿÜÏ|2“÷;¿ïû¾¿g;5XÆ«ÈHèK WÈx€À  ŒÑø3˜WºsçĂ(ƒ£€'8¶¶̃Äœ$$=€Đ•ÑÔ3P )€BÜ9¶ÀB~ˆŒAÁäqz(˜iL̉ 7£‘Q8Q7©£đ( ĂÖpârÙJl¶`Êh2†ÆF¨@/ˆ¤d 2âÀ$@$Ô`Z5 Ơ@Ă€Bæ3_üæ­–9̣Pa™A¯'©÷X¼er…ß Kå>†Î~ ™œ}Ë!đGÍR9̣³}P ›ä#ËĂƒ}„|v@VBÆÙ¶}°Ù!dà#4”ª¦H©pĐ0Œ̃ƒÏ‰‰áEh†GRQ<½Ö„O®ÁiCRÑ})¨…&b „ ÑÉh`Oöp@ ®„ Ù$_²Ç©CT¢$dg₫†ˆ`ØÚp@CØ«£M¹ÁÁ@‡á ŒP¢@c 4Xf²¡TÙ÷„ÀÛ@Ql .ê6 {‘hg‹µÆx,¦ï‰a„^ơ 7½·­$ §º§"j\ Yô4{f8a²‰¥₫¾>297ià‘ˆ‚ÇÄ2¦h¶Xè\E.@8Ó°:ơ!T̃¤N‡PÓ–> xbH*ÿy}Gd aüN5N¨Ố¨ z¾‚ÀW ¿ä} 2q>Ú¢ ®0V©á³MºaÍBÖŒ‰7êI=PcZÆăjˆ>#­„€¡ 0̃ø©£÷#œ T¸’A’GcĂ1U÷'Ô$pï1#$\ïÅà â¡irD#«" mPA5‡/%$ ‡ÿÏÄơéåkĐj¥˜:|–×¾Á˜ׯưwxŸ°Eí %)¦íăĂi_<ª‚qF©é¡¸Ç̃SILDi!à y'WQGÁNI]K8{±!¿“°©UM@Nn&D¼ôƒ…ø₫aA’y?^I¦XBIªp" ˆ\\FQXG€ä!rqF!̉¼ Æôø<‚dP Đ˜x &){ÆÎ®€¯‡NªX;§7`vDM|ö₫î2­e EFø ƯÜŸ„ °»H€#Dvô|ø·¤WÛZÿ$ÛË‹Œ5rEî€+rA[ !œé"ˆï•©́¹DLREü}X³ Œ…JNc=©üjỰ]¥$ø|[S<ÈÖ÷́àøÙaéj̀ª9=ÉB²÷¾ ô,H,[›mW@ÎơX’°#‘Øf»nœö·»§¶ºöZ2ç–”0i„¸:7”§HÊjX[|ÖÆñI@n~x¡smvyzùd ¨nóv?}®#Utµ{ô/;m—ßγï¦đ¤9¥Û0Ệ̀¤†3ư™îó´-Øqă—7–åo_`¦?ńĂ₫[öy¾Kqx˜-x<`‹fqZwÅR$³ /,±¥ÀÖ@ó ɱ©̀¿Ÿ7Ùen»:»í̉ ßÊqË;—VóKB/N}\í}0ă­ưà¤Ëûó́8Z_’…åü}T¹đû;YuwβN4d ß:¦p›\÷vÍ÷?º·H¿lrí¥Ṇ̃̀éøơÁ;§ÙÆW['®©¼ñEåg¹6Üøậ €'©¥•¢gGÿC‡ư%³=q˹ºđ°ÑæâÄç;đ&B³³é§ợ´~fç6Ç» +VvV©EÜ¢¶£3N¸å¶.øÊ¡‘ºŸík.÷Z}rƠ½¬$!Ưu* ¥•!qxù̉’¤ißU{¤VÊÚ|»ß­Î9·K£C“—dåwØóĂ¹K₫Yp×’/¾zẩ•û§t¤]W.<ªĐmê6ç̀½rɱƵϖŸ=5â^†kÿ ë+«Íƒg¦<Óx‘l?Tv; bµyÖ·iăî…¶ßlΑøÔ¨í¬¨ØDï~#rT.J™=û¦aéàR\Ó•0öxvÆĂÙ¦º¥Ç®uîjè².ÛíT]x¼ÉOX™̀x'd— J~3E™jøQödcôh׳ÇĂä—W¼ƒ­GÔú¢«gê2ËVjÆØ„§×ú­ó'úÿ~ s̃¸Z-hXäm׺£ÊL1Áú–îđÂÖ3"‰ ¿6u5ÿhzÇâQTXÄF×uÍXÎđÿ, Ø÷¬nFëư º Ÿ̃j»!dê†V¥TŒĐ¥Y•^ôẦ7Î ¹9l»€'³>ỳºØ_Å;íƯÔq:÷Y ïeƯqqK’ărØ N²Úx°`Û•{w91ÂèùÊ‚“•Ơâ¼­;l昭†‡/0ßcÙ9rĂM ì½Ú滳Ĺ ̉d·*lÎu v¥öOÑg4Û3Í¢ƯIüJŸ!q\µHăko¿¨"ÖÖ[·̃);o(9œÓ¢oơ˜€9'çwfb¥ª§5å óˆÁ/Kc̃ˆị́RN«F–Noº^»̃·v₫u³4Àjä/Åè1uÆ™6é“i›ÚÁχ¤?혿*oü5á©UíÍ¿Fü»!»ĂxoÊơ–é6×ưûu¯'Ä{?-)®ơÚºèƠyä_ûïnßáû|œçæaáâc%Tóp¿”ªq7TnyÛüŸU¸×ă«¾]{¹¥É;:l ¤ëù—Œ èĐ7EÄoC†¶XO«|u¤¨~ëAÙÓï]₫–"¤·m£—5î}7ÜL÷¸ø̉ÄÉSÆƠ—¥¼µHæÓÓÓ×Ô»iªtÏíØÚoü̃¡_îºï4ùÑ–§»cË2"³öåïçÎ-)(¬¾¶>9iôùV{ÏŒîüÇ Ơ;$‰ë’ÏZ. ]Êxg€¯‹óœ¶¡™¿Û©‹å endstream endobj 1369 0 obj << /Length1 1717 /Length2 1781 /Length3 0 /Length 2842 /Filter /FlateDecode >> stream xÚµT{Dîr™LUƒó’ư[æ3u7ŒÜY„89R ?1•ăI_ơæÛmó1GpÊ!"†ÚqƠ™!¨ÚÆq đYàÉåQưIí¡TFv¥JBí­ÊçêáïXl;À •N=Q;&‘¬qª}Ù'“%̉¿§đ8S Éß……*ªÎA —̉CP$^ûx| "M”/6LÇXÉ¡««µ£23Tf²))ÉRL „‡S!L¾(É8”B&‡S’¿¾]Qs€á¤́ÉÑ¡¨³û B °‡̀$“ÏĐ'AX0iäDY’c+ÀPq"ÀB =#HyXü¦nX­r±8’Àßé́pwH‚ˆÿWÀ0Ç0XÅÜ"“I ñ0 Á JX„ü˜¡6Ù}ˆœ WT$†•aG³±e1‡ƠĉIi“×¢ºàT8kFª–‡Â8́lÔLöf}̣@Tä}qøBWW«ïéIíí‰̣1‚Ó ™ J¤Ø"aÚÛƒd©~¬T«Đi(F!@*'R€“QT'Ͱcz4Ù_RZ$0dcÙ:‘ñÅ0_u¼CÈ·$ƒTs¬¥ÍÖŸ.8ơKȰ88 ×ûW.äNdˆr‰ ©(i'Ÿ¿–~SÀ́Ë0|íæ†)“©L6 ²Yä. ˜3Ç>å›H₫ĐM£Ö2ÙÜÏkƠ˜VÂ|JGÆwZû˱ộTÏ7*F›±iÏö鹄ûnƠQtăŒÁTí=&đ¼]+O¤ÏÚ…ù{;.MÍ_‰î 7[3YüÏƯ“›÷7ơ Îï…R9©:®ơ%¡´UÅœö´s&–}KJíµk.>µñ”©âÎ>s~0›ÙøQ÷UIDÅ©;;F+vÿÎ8>I&¨lŸ Ö ưÆÙ‘ÄÇÁI9YĐE×Ù-Q¥ézơ¾̉ ç',ù{º_EAÜĂœæ7S/n°ï)ÿí`Ó…±ăçUæ_̉?Đ’Æ»©™gö:6hÜư¨Œm[&́ ,Đ6IØv‡wc/:ç₫‡‡ZgƯª«M=9¥oØog…ZE2/÷¯¨ÓMÉM×ăê¯N¼Ó-±bª÷"ˆZ²fP§WÿEbáẠ̈^e 6­}¶m¦Ex‚‰̣îĂ,¹I³™ÆÙß×8]i¶’ÍËy·í€>+²u¤ÿ®«ÆéˆG/VkçƯÚ<¾vË̉ÍçË5×ƠÉvFWœ16Jm|”zY²¢¢vRC˜®Åe¿Î£¢đ±ADmo²'>v«1ë\Ư[7%ö%U–¶K7gïé4Ó~ÔmÙ“²)ú9v³ë}ëª[+™Iưáă†sÉ¿²5lcF ưfhzÜ©ØUA+)íoGë2S,"Jw ÙzÓ\Œư‹j^µös]ˆ?o†mxå‰5ßiƠ*hÜû!̃qÔƠO¬SŸùÄZ/é˜Æn67©“ü$I½?éÆ'URZç'-ƠÁºoMq3öꌧFcÑvñZ°„ËLÊ3} —L]7sÇ6ƯK]Úỷ£ÚÎ<ù¾cܦOo­ß\>¿ñv]÷ơ×{}Û’ ÙyËO>™bn¤ÿÎzÚœơF9¾ÔiAmT+ïÀù£3¢ ÂJû|sSOêJ¢èÁôh8̃¨ïÿØĂË₫1Êx?¹]–Ÿ%£×ï‘n¡mÿ¹̣öéWcÔ·S[íƠ8«|U/ƠŒ̉Üv÷— o;•F—ç¥U9Sß7­Il3MIơ纲ü`ÓBv6b́™¢Ùœ“Ơ9`\Oq½cBÙJëÅ´éhQ‹R.ÿUSPH½¿c¦k₫AxEâ%gsÁc«ii­1cuÂÉ4‹‰6^ ™¾NÓÉÀüî#…a×»¾rÎ!üRl­ó¾,¥Ó́û£ÓÙdßYæô÷eßxT§Ơ‹ÏÄ<¤Lbuz?æÛå`¡AB,eíîw"U?U2·øHkó"^”Sï¶³}₫È|ÙóƠ«6Yvêé"‡§;³^¾/çÛV.¤Ë÷ưÅ;p é®ïÆ¡î40æÈ¶Ü±-Ôw¿?ºZT²[auëRẵ«æV₫vfÎ,ï]&¹ß₫êĐñ ‡}Ñ›«¸#¤K”qƠ7`¶íå°[zwîBöIN—DΪû,vϽ³´₫₫æ·Á?ƒKÆƯ=̃ϪZZ¦á8Oyzíd·¸*f}ô„“ó¢ê² ÏDƯËjêè̃çÔù×;¤l•¥kà-Ÿ¤W÷4”×ÜṆ=¶uÖÑóÙ¹GåY·Ü#ÀÎ@¥£nÊÙ~ï7Ưjeẹ+é̃Ÿ«ƒ¢ÆXLèäL gÙîiØ>Î):|nÉJåƒăE¶éæ(öăẸ̈sN6\»~3Ío³ÇÅ5÷èxB€ú|¥Eäé¹ é·kÍ ©̃ö¢ưiM&¦ª›Ø3PëP|¥ªóp”mß\E¦₫Jí†ô­BíøøĂ‹á ¾kŸóÙÀÅÉ·ÿp?’éàO=¿ÈJ‡fÀ ưµUë'œ¢†¹ÍÚEóÇ<Ñr‡fnư9-øúä£N¹©S̉¬r &Û•µơ± ø_EÁ©‡#6YX̀-¡L1̣n,ÅûF¼…oÖ'X́Ë‹¸º͈̉xóËœe܈—}7n¬ºº¾êM:*«,~ÆyvïIƇ¢Áu¹¿ìÜơ¡„fQà¼üjBª×´Ê‘‡«Ú=ü˜(ö‹́ÙZ=8—Úµÿv܉ä27fA…á5c´¶¢ ±½qQ7cw‘éĐ̉Ȉ‰Í¥Î^®BÂùă0æàû·]…y¶Œq è«: ¿Dˆgx9¼Í΅ôŸú¬Ö|ư•ÈÄO­_FêÅ=;̃tkTQ“‹ơ­…+ö&Oq9†È ë§ù3W8¢+g}FfKªK”»C[Dæ[æö‚yư½Ư³=vHŸ7]Éßê ²25DMœưÚ›j]¬Ø=zd×o¾˜ϽôÄrüèY¶‚ ơˇ;_øĐƯW'‰vó:Ú·́ˆ-Ư wdLˆˆ̉Ù·öT׺0F¹( >\lcPÇ.ëĐ9¯å”:[̉«±ëÁ-Á!ơ¾ŒÆ®vç+¡E ­îGá鋯×̃üÇỚ€±N˵Ư²^F½&Æ̉ŸÓûç¨Å¹cªư™R¤_ endstream endobj 1329 0 obj << /Type /ObjStm /N 100 /First 997 /Length 3627 /Filter /FlateDecode >> stream xÚí[Yo·~ׯàc‹"Ă}‚N/ÍfÇNâ$ȃlmƯÊ’+Éỉ_ßs¸hmV¤<ô"€EágùÎBr4æ’Y—̀Î )€àŒHåàD…„ Úá`.‰ñ8˜+âà6xa‘€n¦d(¸äÚcpV"…—|4C®æ¼”ÄZ‰| vµ0ÄTC8"˜ 34\(!9‚c¨,2RႾRˆs¥&RKTØKt‘(‡:K”×Hy¢Ăq¥´Jå9rV¨`¥RDkú 1ÜÊ£Đh©1.˜ &Ø¢VÄÚ0Wâ˜D{µ#† ¡Ïâ™E À¯$jj ñÆà » ³…KÆy0If+èƒ'2t f†ù-˜ƠÔ£O$ƒAœ9NĐùB!3¦€‹kîX=F70ß#‚Ü đẵ"úàZ°¤ó¡[‡¡à2\ cj€[½̣ àÖàUáÀ™Á Â#ÆlP•!ÂÀu`ˆ¡P±äYàÂ*¬O4" ,0">2àhUhÑE.¸,xßë0Æ\¡W#ij†ö‹G0÷8øp%à®Ă8Q2Îă]…)€­”':œ«Áa•üP IYÜ!ôÊz˜;m:U^[âŒÅ”€¸ Ñ«Hrt×́p,\ e1P:F’!Z¢~ˆ‡V`ƒƒ€äZCpcµÑ¢óøq‡~»+ Ư †“=¹?Ÿ„ë½ÁŸúd8º,GäƒJÀ>wè›̣bB> Ç €…f Lfá|Iá. ­$ŒÛ!zBè₫đtHè.ùEË_Éï¿wào3™Ú›ÂA2Ne2Y0c~¬Lg L¿,S{Qhç¬L« çt%Ó‰Âq¾L±™LÍÁ>H,ËY! R´ĐèG¸6x=_¦ÚLă}e¢’Ét¡älơ–d:WđÊLăU!­ư±"­-³©Laë̀•iLÁ œNeZfóëN, ÂW2¹*Ü"™fC™‚Vmí¤F%’©BÈùîä›IT ’Đc2êBÀj¢4/p„Á«ù"…ÛP¦6À» N…*¾T¤ÜÔLË ‹Áe:^0Xñ–Ê´Ê„kdÍNơÖ®e2Ơ†vÂ’Z€mS™êî^—ÊÜRrNe¦¨]&S³-ÉLkÊT&¬)œÏONÙXSvÉ'Øeàú†Đ³ l¬ñlo÷ư₫ç??›Ma1Ób+Ábi;‘ÚØÇS¼Ë9¤ư°B…~2ÖÂwag%ñ$c°đÙÔc#x´‹W6œÄ3euđä»A›JRáâ  ́Ơ!SñXucéœÚ¦j̀–Î@o£tJÏĂ-đ‹©ƯD:•Z‹,gö˜®&"´Q¨«y³¦nëƒp$óđJT¾ÂkÏD؆֜ĐF(Y8¥ơ3Ø₫ÓÁ¸`¸A˜Ø}Ê€J@FÚ"·’‹p¤¸1H/já04ªf€âÂLgó}4‡_xÅ₫̀+Úñ$1t5J…kUQă0¥–kø6q¬i,Á­³ÙV<–¸l§ GépWÇpoè ₫p´GWs,tAÉø#‚±SàÀ#œÆ ‘v̉Ă]t‡ux@pF…q>`hD"ck\å+”SG£n‘V³DD?…ov³5ÿboĂëÛØ½æMÇÆûJ£ f¸ä¥ê^D(̉©Å¨«5à©~·_Œzw“á(̣_uoáÎó×go÷_₫öôåΠ¿ß½=$ ’”ć ă‹r0Áv‡>í̃”½ë¸t¦CQ ̃{Äñæá¤Ûï]́ ®û%ö'“̣ö₫¸Ó¡gid đ¸éđÁÁ/ô„véù¨{ñg9é—W“Lp,½ö‡Z̉>̉ñ¯Qɽ°Æ_đ)DóËb£?¿>Ư}‡FŸq1ßj-ÑjüMLú-YíZ½CŸĐ§t—>£{tŸĐCú}A_̉Wô5=¢o•Sú–¾£ïéưuzA/‹À^Ñ+øëÁß—’^ơéƠđ~D¯é ½ùvwSh₫ ¨Ửô%À7„ö̃uGå ਈ̣]9ê /é_tDÇt\~éẵW:îwÇ7tB'7£²¤“¿‡ô~¡Ó¯ôư‡₫S†-Øu<̣̣xçÅ«à‘7‹ÂP±†l•Cäƒbê₫|•?×fvWù>́^Îçø4׌\1Vl,°whx –ßoM¤ÍZ+Ơî₫³?O{ṇ̃ewr¡á́Ñ›̣ú¾ß-Ø6LO3Êm´rq5MA¶₫ˆMËĵV—ư“³““ƒ¦‰b…‰<›(̀–LÔ~=×ZÏ^î>Û0Ñ/·PL÷~VoÉBáÖ³p½eá́xçp'Yx̣íö|د T´Ñă‹¡øê®ïpE;Ààï³Q-Ôó{8@aï.úåÅđîÛ¨µ9%đÙàbx EÄ÷®®J¨å˜|̉.AöùAĂ¹lˆ%\'m>ÏÂ[{];Á„'Ưq̃Yh?Éh8#¾̀‹Đ½̃ha#OÏ|üN¢<×é;Ưüû…x¡“$D&æ211ßj!ña:ñ:1ÓI¨Nư1¨à[n $.¥ÄÛÄ̀Êôû“…Nl Ä%x\bæ“O|ê÷±Ÿ3¶Q—³uf“ùå8c<ßJî‡cßDT ÿ؉¸#‘oÅÍQøÿ­MDŵÙd~q)G"ßË~Q&Ăe2?“‘´ù–ÍHÆDû^Q.Ăå2?—Eù,Ê'ƒÁkˆâ9,€Ê„ÊḌ>Ñ„\é+Q%¢$K̉K×ËØÈ†Êª‰N¬ƒ #ü_»XMRú˜TeœƯHËñ$²·Uö…É1́2.̀­…‹já²²âă¬<Ú¦Ø9èέù¯ï'ữY„UŒŸ¶&¸Œ…ÿú W‘¿ÎíMàlëY:¹́™”­´Oû¨£Qùßçi,viº¬¦óeÓócDú ß‹ÏJµ˜±̀̀e3— ¼œ×³³7Ơlµt¶¨i⼟ÇKV¼ø2^Î7xÍƠ«²Ê-µÊ™¯9p;g+^z)/YçåæÙèTÅK,åż̀<^|ÊËúe¼¬mđ’sxYWñ2óy¥Ùl̃l]ÍnZ5À¨Iă‘H¥XÈ™)g¹¶Ê\Ó27³BZOÊâlSh̀̉Ù sí> stream xÚ}˜K$G †÷u¼€™xèĂ€1xeŒ1¾À,z1`l˜ßfU¦RZ«ÊîŒø$EüR©4úÜÊ6ºl*øè[å†Ï²µ6¶Ñtë…đI[XÖêFŒuulܱ®̣&ëjÛdĐc”¹)á}ám̃—¶ḾƠ9·ZJÁƒà–tẨnJgÙênK‡nu7¦ƒđk:êVaî¡:à́©̣Vwƒª X¨²  ÈÏ0@phÿo‹Y·V‹™¶V ‹¹"¾̉JxƠ^Fñºí1jÇ«ĂhÇ«ĂhÇ®Ă(Üm‡ÑÆ[ kp0mb‡‚ƠæœÅÑô®ô ƒĂé 'ªE¶̃KÇCǃầp4‡9qà ;2qâR£ă|ÇÖ•çCÈ£cñyV,¢OœŸàd©àDûFW+Z6jû5‰âA±¯©ăøĐaçC0úœFá.Fil£xà£Ô6:Œ‚N‡Q:F¡>ŒB>|E´Ü&Èw¸ 8(¦†5¯T©xu”£8k>ŒBF|…x7ÊïFB}đÉn”!$Ụ̀À+Ư·îÎa1îUˆà±a±&+"Ù€wçÇÆ ¼àË~ »QxØâ°t”wáFiîwT¯‡Q˜ÑĂ讳Ăè.‹Ăhß%8ùññăăĂ_¾ÿù¶ ,*Ûï?"çÆóñ·Ï_ß₫ú¾í¹ôüûëÛ¿G‚ưúö̃áö¿>}º³`çbqÊêwVŸ‹ŒƠRVq,‰Xơbµ™±:VXmKR9V‰Xl¬²êợra5c•ŒU‡cQÀªóbUMÝX5b‰±(eµ;ëååÂêÆª1ëµ›£Ư¦ôâ£ê|÷d¯Íw¥¿øùË×oßÍÍ_>³4øđÓßÿ€óC­‹ÍbÑưeå}‰̣©X¼¥&»÷o·›Ç%¾\Ñë)Ëåyä—N5§¬{Ÿ^.,2VKYű$b]y®cf¬¡ä¹a,IYäX%b±±zʺ+ïôra5c•Œ¥Ă±‚‘ÅK=ƯíèÉî´ÏŒƠƯ†~u‹ª§Quw§Ưi·{cw7Ü£»Ưp/«¹ZÖ£›Ơ²¦1ëµ;ª^ͪ×̉‰y­‰¸Ó>Uü̉Úéæ¡µóZO­éj̉‚_¶ËÈ3ø¨RkÑtiÑÖƯ.ø¨ESkÑtiÑV–+Ư±_Vº—ma¹†M£†M­aÓ2R–+Ư5*ƯÅJwá”åJw‰Jw±̉]ZÊri^¢̉]®4—9–L'¼”n™ĂX’²\—±ØX=eƯÓüôra5ceJ—1+Hs—îehÊbǪKŒE)ë®ûÓË…Ơ•é^t:G¬K÷¢#e‰cºUcqʺë₫ôra‘±ZÊ*%Ët/ïè₫µ;Rº˜̉—Fl)×î‡óơEđ,×—›Ïr}.}§5kØdiØ.+¯¯ˆ(Ÿ¬E“¥E[v»M¢M¬E“¥E[YäX‘_Ö¢É̉¢­,—çQĂ&Ö° —ŒE.Ï9Ês²<'MY.Ï9Ês²<'JY.Ï)Ês²<§±ºËṣÜFo²Œ̃V–Ëóhô&6z“eô¶²\G£7±Ñ›ôTénô&ÑèMlô&-Ơ½½I4z½IKuïFõÄFỏ̃Ñưsw4lëƯ¤f?MXë¬l¯úÓî?MÎT¿ê-6«E_}ô—•gô5ʧjñÖîv×(úz‹¾d¬ậ<ô«X/C¹•ạ̊¼FynĂ6Y†m+Ëåy‰̣ÜFo²Œ̃<‹ƯèM¢Ñ›Øè—ÑÛÊrỹØFo¼Œ̃VÖ=Ï9½±̃x½­¬âX±®<çeô¶°†8Vç<,Æ‘Æ8|Œ%bYŒ#q¸Gă°5QƠ±¢uKR9V£²±̃ÉíçnƠh÷•Í,i-+®ª6÷Ó÷róY˪ÿé[y±iưËư•¹‡M j‹Å+=Ưí¢—(z¹E_2Çüâ«–1kÊbǪKŒE)ë^ËN/V7VÍX4‹#–Ơ2)Ëå9GµŒ,ωS–ËsjYSKY.Ï)Ês½ñ2z[XnôvzéY6ză*Ữ8½±̃¸§ºw£7¶ÑÛÿ=đ–– endstream endobj 1400 0 obj << /Producer (pdfTeX-1.40.22) /Creator (TeX) /CreationDate (D:20220114172444Z) /ModDate (D:20220114172444Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021) kpathsea version 6.3.3) >> endobj 1377 0 obj << /Type /ObjStm /N 96 /First 870 /Length 2417 /Filter /FlateDecode >> stream xÚYMo9½ûWđ“¬âH̀ÀØ™Œ1I lrĐÄ=Y¶Èrvæßo›llØC"²Éz¯^±]² (!…Ñ^8KF(£éS MŒ $̉§ài›†ö)í“NXIûhụÊH)œ·ƒ=}¢éS %i½§1¡'&¦B¯…b.tA(&CZV̀†„"º+t’ÜR´Ç̉’Úciɱ´äá'Tä4(T$5JèHJOu$E#t$EÖ§ưB:’‚¥“’,ÍëH>ic‚¢­¦%J$¥°èHJqÑ‘”£#)Eˆô )4I "©TX)úǤ ˆ‚ÀOçÈE …(>à•âDz÷)P| đ’ „Nn‚e>ÒTÈ`ĐcX$-Íúi‰–‘O†˜)XY¶¥ø…:Đ’§࣠DH– ˆÎŸµ¢„@Ú¬e¥P4Hëæ<ñö"! Z=g=¢YY…6ÊÏÜÑÈѵO:b˜85¼V âX­G ,^ш21ZaùÜÇĐZ§xDyê|ya=Å]q¨$ÊZEi¤„ƒè ˆ3À$Ú9gˆƒĂ`[đ2z@éà•”óZ²§¤ÈkW‚¹zơêêúăîô0Ų‘â÷«ë74”óđn{œö§XEóü8ưˆ%gï§¿h æµ×¯Ï±è,2–vC,Sa©–-X8Ä̉çXÉË –a©Pa™–\°”bÙ Kw°”+XfˆçXÉË –bÉ Ëö°Ô‚%ĂKº :X̉,ÛÇJÖ²gmu­o’â _ÉgX. øiw|:7Ụ̀̀¦ÙÍá™p^jƠr.ê1Ôê–™3¸µÇ|±¶CëJ½”=,S°`ˆ¥Î°.ø¥ –ay_auêœ.̃Ë»!–©°TË,b×yö²Á‚‚¥FX.TX¦‡µÔ9:?IJV§Îѹ‚e†Xçu½l°°`é>V²¶=ë’ÛÖê ª[5Wê\O‹›s=¥ÔÍơ¤dĂi‹zÛ¨Ï,3§íÜh‹^«‡Ö•zÛSo‹zFXÆUX=¿L©sc‡XXaơêÜ”:70ĪêÜôêÜ”:7r„…U›^c©stC¬ªÎM¯Î±Ô9⫪śƠ9–:G5‚ªÎ±WçXêü«ªśƠ9”L‡ ™>[C¯²¡¨j:±º6ÁWäªOµ™ƯŒµ™Ë`©Íæ]‡¥cæc[Xfơ½^K†MÖZWê{=– ›­Áªz´ ~•3mz´«d¯GẲ£aÓ£µXƠƯƯëѰôhØôh-Vu—ơz4,=6=ZƒUơhØëѰôhØôh-Vu—ơ:6,JbUw™́Ưe²ÜeR° Tw™́Üe–L‡à†XƠ]&UË,bç}ö²Á‚‚5Ê{đ¡Â2=¬%ïÁ_ÈûdƯÉtđ®Xăè₫©»”|³Í÷Ïâæ|ÿä/ù₫Á–³¨o:¶…%q†ÇEoÓ£µÖ•ú^¥Gƒ¦G«ơö=)]85­°̣©¤Ø¹ó»;»™c-eß¶r¶ßk… 4eĐ4e‹¶'·4e`/ÈMÁ‚J ­&èå‹XKRºbU9¢¨P_qAÖ iÏ›UŸêRBRÚ¦)¬̉ô’È”t6ªo=ÇÅôÊ×ÁM»µ(œ¹s[“æ–ojn&/DµôaĐôa ́L̉ëp t^Đt^PơZĐëµ ôZCºÆªåb%Çr¡È…F®®äBOniÉTßzvzr¡ÈƠc¹¦ÂªåB%ÆrKG†”çoß,¦ÁZ̃¾ B+Y÷Ä+_¬Í¨zuợ^î¤>û™»¾1LËY®¥¦¿ZH̉…!{/4Uc]uTĐ먠tTĐtT-VX=¿JGMGƠbUgÚ먠tTĐtTÍ1ôz(]z(Ưüm«œiâªS”Ơ)æN¹=Å÷ÛÇéIüûÅKµó«P¼x©7BÍM`#ôœ‹4À€xÁé¹’1¿W¿áîqwʘ¼ô¥%S´0w>´ÉLO’ y’·ø4±< -Ÿ|¶Ăçh¿Én{¨4 ›økWœ'Y›–ü̉DñWt„Êk+:Í’L’¤Y’I’4K2I…fI&EP³$›ÙÙßù%Nȸ¼¶&$IZgăÀ“¤/=ÉÏ“TPà”ĐI¤#»‰¿ ÎÇ“$Øßù¦>'d\^[²$H’ˆÏç!K‚$ Y$IÈ’ ¥0²¿ó%^Ñ*¯­è%A’„,Ég–ä3Ḳ™ƒ%ùd×ơÀ¸¼¶"$̀`XR® Ă’| aI>Eа¤Â`ØßùëÅ9¡̣̉…$°¢DÎ;¹̀|œeF®%“Y½ÈÈ/:ơge´Mª,—“RI°Ơq–¢m¹ZTNY‹q–¢j¹^¬t2:/®i£¶lÍÚ §#Ṃ1’Ê|ˆ$1á›çÓǧ ½ Wyʸˆë›ÛƯĂö‡é³Dy»?MÇ?·_'J,o·O»¯¼øa:⛕7w₫Y¸yüé?ÆƠă§í·ÈöÛéøc7ư—6å€̃{^üéyÿơ´;́Y“]ñ’×]€•æ›Ă÷¿wûoî¤1ïe»ß§?'zaÅä»ïç»Û·4ÍÑ₫yÚOÇ —̉âVßlè{nÊđÛưưô¥œ\ñœö¬\»Ư?¶´‡}Ùîïùăá°½Ÿư ))éJ»&rmÊøw·as.Î‡ÅÆŸ_¼›¾§¯ÛÓtÿy³&EÙrw8hÁ%[:Ρµ« {{h¥9m»yØQŸ@oé|*”?=?\~5¦ơÙ{/ÓY}úđöă¯7\%é´₫ù¯Ûù ­û qÚ¹ø÷Ư=íRéóoüó ½wUú‹Äü@·¯8OdÜTÇ*ç•J_öç_ÿÓ sûĐ}!¬ê:ƒ‡́bÈ.†́b€ÿ»œ.D$dÏCö<ôÛ©Æ₫ƯôDk Ÿÿ₫>‰ë›-¥̉á÷‹ß&̃”¿‡ÿö|¢ ›å2fZ₫¨Ç&¿î åÓÓ”÷ǧ¿lÿ˜Ä«Wâúưó#ù%ăø’óåF\×ïÄë×ÀÏh|¤±Kc~₫…₫ vóh U endstream endobj 1401 0 obj << /Type /XRef /Index [0 1402] /Size 1402 /W [1 3 1] /Root 1399 0 R /Info 1400 0 R /ID [<3229765D8748ACCE191CFA28B5AD6B3A> <3229765D8748ACCE191CFA28B5AD6B3A>] /Length 3179 /Filter /FlateDecode >> stream xÚ%˜KlWÆç}DZ;NûÄqüvüÇvllj'q́Øórb'qæÚB¨K…:Kü‡œ+ SØöZ‘ƠƒCSgGA+ÀÙYÀ̃ÙÀ̃Ù)@3]8> ø4àÓ€O> ø4àÓ€O> ø4àÓ€O> ø4àÓ€O> ø4àÓ€O> ø4àÓ€OCÙ§Ö™P ́U`/¨û@ ¨ûÁ Ç^µäü÷tĐ:b13,Í€Y€E³°VÀ%7¾†13|ƯX4+_x¥[çx1kù *K‹” àåUÔaĐH¹€:(¯ £¼Œ: Z(/¡Z¶»Ÿmó”ÇAÛ°í"e;è`÷V£́4y·m³”Ư ‡̣ªœ <êzÖéêg(À å9Ô8I9#üă(Û¦(Õ[¥IÔiÀƒ¶tuŒñ¶MP=2:Ù¦R;OR¡täiJ@×Bßv»Ø6J©[¸@©Sê~ç(=JĂ4O©ëÓè^æl¡T?(u[j̃"åIÔ¸F©1X+”ƒ¨UpR¶nPö£n‚[”âÛàå ”¥÷<¤́BmœXR»SP¢́@mƒîRưÀ%±<·Xÿ€Dc[€Å J̀IY¬¤lEµXE‰#y‹r{ ĐÅJ¼I^”YøEy£Çzp² ER¢¼F*"I‰JJ#JÛ¸z5^¿ê(Ë!”N©¸èPº¾Vʃ(ƯL¥Î«Û—ëêP X”}t‘ŒnT4xnDZ Ư}‹ư”<_"MJ…nGDÍ.³‡QÄCq„R†ë¢ºÀC+bѨTht1u£äáI@d̉VR+ÈBTxF²5$êYˆ3”<,#1ˆL "1Hy¨Fb‰A7"1ˆ\sZB‘€HRŒI@$é# ˆ$ Åu‘D>D‘€HR,I@$é} ˆ$ ÅÏ‘Dn H@$)æÂĂymw)ơ7bjgƒ¤wPº bêȺzb̃BéVw(Ë—QX.'`óơẺ¨ éªH@zµ€tµ€tµ€tU H@z u€t UH@ºˆj$ ½: y»èl ”G/Œô ª€ô2ê( é%Ô1@̉yÔq@̉‹¨v@̉9T' é,ª€ôª€ô<ª€t5H@z5x/¤Ó¨a€ùÓ)Ô)€ùÓIÔi0Ê]ê¶ÎR$ @Ji¡tPêoº¢t¹$ Ơ‰toJ€Gi ”]•FM Aiˆ•Ư‚¢œD©ƒJ€îWíVQ̣† Á‘‘”€~”¬§h$o%àj(ö{€dj@å&PÔ¨@ èBm%@]MĐÚJÈË Øz†äJ@äJ¦ÉI@^ɨo­”Ä —1±YN rÅ E rÅOæÄ W äΉA®4¡ˆA®àöœä¼̉F”¶É*úAP¡t6%@GÑ¥)Qº%@§Ôí+u(Æ*Wt} l®́GÑ\ ĐÍĐ·\ ¨AÑä|’¹tûØ"W ªQx(W 4V.×pV¡pgÎ; ƠÀbå\ ¨Dáû\ P+H@®T H@®¨o$ W Er%@M&9éwP$ ŸçÂq§Ç91ȉ/¡ˆAN ¦²4[̣Ù1•ÇÁ1Kvÿ®ïú ¨nĐfÉûµĐC÷½Ö-øLÛ=z,yæOúNÜí³äë—Uƒ!K¾m*µÈ1bÉswTj>jÉOud>~vÏ‚qK^xN»œ“–ü╺ K~=¢̣"˜µä•wỤ º;oÉëï«\ –¼q[‡×çÿ2X²äÍw´‹FrÅ’·æTªåO­w†UâˆƯ[–d¹JÍÖ-ù÷«*€MK̃O‡×µ<-yüIí² R³ä}ºåYƠwË=û”¶ÑÚ¬`Öđ+•¬e•fî£*k@µYû!Cq9jÍz¾¯]èyVg6ø†Jz5˜ù¯¨lf/©¤ç™3›YUIϳcfó :¼><ù~ËÚ̀W´ ƯÏ:ÍÖºUö³ơ÷TêÁÓo¶ơX%íΆ̀>̣ÿ›¡ƯÙˆÙ'ÖáùĐÉèy6jöÔóÚ…vgăfO¿¥rL}î†J}Ÿ3ụ̂• qvÁ́«̣Z¦ăÍ›}ëe^ ¬́dẀíƠ.¬ñd‹f?üJV{²e³Ÿ~\%íή›½øU•zÜ2‹ŸV©ߺÙË“:¼>Èéy¶iöªüœ±>”i}è¡Ùï~T̃V\ĐÛfo*Ù6~ *€™½ûy•°Í̃ëжJP ª̀ÿSÛ´tzU öY¡ºU?Ô€:°ß ƠÚv4€z+t~AÛ‚Ăà8d…‘'ơ¯6Ơ 8¬0ơ{í̉‚ă  ´ƒĐ º@7è½àèư` ‚!p ƒp xpŒ‚3` Œƒ pL‚)0 tơ3à<¸fÁ¸æÁ%p\ @cº–À5° VÀ*¸ÖÀ pÜ·Á°î‚{`l‚ûàx¶À#‚ؼs<₫]đäwE ‡₫ÀŒÇaÇdÇí̀s\-`ăX‰q̀nk-‰k̀iÜa@ÏƯÀLÆ5&1•ÇüÅ<₫ƯqÀ¬Åµ&,µÇ\Åu¦)®0Cq}€É‰cAĂ13wC€ÙˆLDÜ)ÀÄL?ÜÀ̀Ă&÷Œăă¦S w0Ëpç 7 ˜[¸‹€‰µ»˜L¸+€y„» ˜B¸%À́Á-&n0gpk€é‚» ˜)¸Û€¹²Û¼üƯÀ{ßm-Æ¥€·½Û²E«fçôá̃<·ê­đ„̃LNsưªđzùc<đXÀëy€<đXÀc<đZYÄ xuĂ Û¿Ñ9¬øZ“ưđØÂëQ€-<¶đØÂc -<¶đØÂkV@=̃đxĂ·[á©¯Ă ßÜ’ê´Â_ÿ%Ơesÿ•ê¶o|GªÇ*₫đT¯U<̃‘:aŦi©>+–v¥ú­øl•Ô€Ÿ–´â‹RCVüå—¤0—§¡^ÓAê5\µâ_J¬ø̃ö•%v)iñŒ]JZ7£ç%-™Ñó’VËèyI eô¼¤5²u å1¦ˆ%­Œáƒ’ÅđAIëaø ôÈ₫Gù¼{-ù¾ú“­ endstream endobj startxref 319937 %%EOF instrument-control-0.7.1/doc/instrument-control.texi0000644000000000000000000003310414170330734021124 0ustar0000000000000000\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.1 @set COPYRIGHT_DATE 2019-2022 @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 deprecated 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 deprecated 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 deprecated 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 instrument-control-0.7.1/doc/macros.texi0000644000000000000000000000624114170330734016524 0ustar0000000000000000@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 instrument-control-0.7.1/inst/0000755000000000000000000000000014170330734014552 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_gpib/0000755000000000000000000000000014170330734017134 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_gpib/fclose.m0000644000000000000000000000160214170330734020564 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_gpib/fopen.m0000644000000000000000000000173014170330734020422 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_gpib/fprintf.m0000644000000000000000000000353014170330734020763 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_gpib/fread.m0000644000000000000000000000623214170330734020376 0ustar0000000000000000## Copyright (C) 2015-2021 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"; toread = toread * 2; 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,wasread,eoi] = gpib_read (obj, toread); %% if successful tmp is never negative (uint8) count = count + wasread; toread = toread - wasread; if ((eoi) || (tmp1 < 0)) break; endif tmp = [tmp tmp1]; endwhile ## 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); endif endfunction instrument-control-0.7.1/inst/@octave_gpib/fscanf.m0000644000000000000000000000353314170330734020556 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_gpib/fwrite.m0000644000000000000000000000451014170330734020612 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/0000755000000000000000000000000014170330734016670 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_i2c/fclose.m0000644000000000000000000000156614170330734020331 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/fopen.m0000644000000000000000000000172014170330734020155 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/fread.m0000644000000000000000000000575214170330734020140 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/fwrite.m0000644000000000000000000000373314170330734020354 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/get.m0000644000000000000000000000406514170330734017632 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_i2c/set.m0000644000000000000000000000513214170330734017642 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_parallel/0000755000000000000000000000000014170330734020007 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_parallel/fclose.m0000644000000000000000000000166514170330734021450 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_parallel/fopen.m0000644000000000000000000000174014170330734021276 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_parallel/fread.m0000644000000000000000000000600314170330734021245 0ustar0000000000000000## Copyright (C) 2019-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 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; 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"; toread = toread * 2; 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,tmpc] = pp_data (obj); 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 instrument-control-0.7.1/inst/@octave_parallel/fwrite.m0000644000000000000000000000374314170330734021474 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/0000755000000000000000000000000014170330734017472 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_serial/fclose.m0000644000000000000000000000171414170330734021126 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/flushinput.m0000644000000000000000000000213314170330734022050 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/flushoutput.m0000644000000000000000000000204514170330734022253 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/fopen.m0000644000000000000000000000172214170330734020761 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/fprintf.m0000644000000000000000000000300014170330734021311 0ustar0000000000000000## Copyright (C) 2019-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 ## 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 formargs = varargin(3:nargin); format = varargin{2}; endif if (! ( ischar (format))) print_usage (); endif numbytes = srl_write (varargin{1}, sprintf (format, formargs{:})); endfunction instrument-control-0.7.1/inst/@octave_serial/fread.m0000644000000000000000000000623114170330734020733 0ustar0000000000000000## Copyright (C) 2019-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 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; 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"; toread = toread * 2; 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 = srl_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 instrument-control-0.7.1/inst/@octave_serial/fwrite.m0000644000000000000000000000374114170330734021155 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/get.m0000644000000000000000000000440714170330734020434 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/serialbreak.m0000644000000000000000000000243014170330734022133 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/set.m0000644000000000000000000000714214170330734020447 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_baudrate.m0000644000000000000000000000344114170330734022321 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_bytesize.m0000644000000000000000000000327514170330734022375 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_close.m0000644000000000000000000000230014170330734021630 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_flush.m0000644000000000000000000000304014170330734021646 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_parity.m0000644000000000000000000000335014170330734022041 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_stopbits.m0000644000000000000000000000320714170330734022401 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serial/srl_timeout.m0000644000000000000000000000337514170330734022226 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/0000755000000000000000000000000014170330734020377 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_serialport/configureTerminator.m0000644000000000000000000000326014170330734024604 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/flush.m0000644000000000000000000000305114170330734021675 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/fprintf.m0000644000000000000000000000301514170330734022224 0ustar0000000000000000## Copyright (C) 2019-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 ## 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 formargs = varargin(3:nargin); format = varargin{2}; endif if (! ( ischar (format))) print_usage (); endif numbytes = __srlp_write__ (varargin{1}, sprintf (format, formargs{:})); endfunction instrument-control-0.7.1/inst/@octave_serialport/fread.m0000644000000000000000000000333514170330734021642 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/fwrite.m0000644000000000000000000000253414170330734022061 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/get.m0000644000000000000000000000427614170330734021345 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/getpinstatus.m0000644000000000000000000000222014170330734023303 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/read.m0000644000000000000000000000541414170330734021474 0ustar0000000000000000## Copyright (C) 2019-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} =} 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; toread = toread * 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; endif tmp = [tmp tmp1]; endwhile data = typecast(tmp,toclass); endfunction instrument-control-0.7.1/inst/@octave_serialport/serialbreak.m0000644000000000000000000000244114170330734023042 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/set.m0000644000000000000000000000705714170330734021361 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/setDTR.m0000644000000000000000000000221514170330734021722 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/setRTS.m0000644000000000000000000000220114170330734021734 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_serialport/write.m0000644000000000000000000000407314170330734021713 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/0000755000000000000000000000000014170330734017006 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_spi/fclose.m0000644000000000000000000000160014170330734020434 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/fopen.m0000644000000000000000000000174414170330734020301 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/fread.m0000644000000000000000000000623014170330734020246 0ustar0000000000000000## 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 . ## -*- 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"; toread = toread * 2; 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 instrument-control-0.7.1/inst/@octave_spi/fwrite.m0000644000000000000000000000375314170330734020474 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/get.m0000644000000000000000000000505414170330734017747 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/read.m0000644000000000000000000000233214170330734020077 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/set.m0000644000000000000000000000547714170330734017774 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/write.m0000644000000000000000000000221414170330734020315 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_spi/writeAndRead.m0000644000000000000000000000226214170330734021537 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/0000755000000000000000000000000014170330734017001 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_tcp/fclose.m0000644000000000000000000000156614170330734020442 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/flush.m0000644000000000000000000000301514170330734020277 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/flushinput.m0000644000000000000000000000207514170330734021364 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/flushoutput.m0000644000000000000000000000200414170330734021555 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/fopen.m0000644000000000000000000000172014170330734020266 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/fprintf.m0000644000000000000000000000273014170330734020631 0ustar0000000000000000## Copyright (C) 2018-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 ## 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 formargs = varargin(3:nargin); format = varargin{2}; endif if (! ( ischar (format))) print_usage (); endif numbytes = tcp_write (varargin{1}, sprintf (format, formargs{:})); endfunction instrument-control-0.7.1/inst/@octave_tcp/fread.m0000644000000000000000000000625114170330734020244 0ustar0000000000000000## Copyright (C) 2018-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 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; 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"; toread = toread * 2; 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 = tcp_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 instrument-control-0.7.1/inst/@octave_tcp/fwrite.m0000644000000000000000000000373314170330734020465 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/get.m0000644000000000000000000000417314170330734017743 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/read.m0000644000000000000000000000441614170330734020077 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/set.m0000644000000000000000000000523514170330734017757 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcp/write.m0000644000000000000000000000401214170330734020306 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/0000755000000000000000000000000014170330734020200 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_tcpclient/configureTerminator.m0000644000000000000000000000327214170330734024410 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/flush.m0000644000000000000000000000306114170330734021477 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/get.m0000644000000000000000000000425214170330734021140 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/read.m0000644000000000000000000000461114170330734021273 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/set.m0000644000000000000000000000520014170330734021146 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_tcpclient/write.m0000644000000000000000000000411114170330734021505 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/0000755000000000000000000000000014170330734017003 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_udp/fclose.m0000644000000000000000000000156714170330734020445 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/flush.m0000644000000000000000000000300114170330734020274 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/flushinput.m0000644000000000000000000000207414170330734021365 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/flushoutput.m0000644000000000000000000000200314170330734021556 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/fopen.m0000644000000000000000000000173014170330734020271 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/fprintf.m0000644000000000000000000000276614170330734020644 0ustar0000000000000000## Copyright (C) 2016-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 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 formargs = varargin(3:nargin); format = varargin{2}; endif if (! ( ischar (format))) print_usage (); endif numbytes = udp_write (varargin{1}, sprintf (format, formargs{:})); endfunction instrument-control-0.7.1/inst/@octave_udp/fread.m0000644000000000000000000000631714170330734020251 0ustar0000000000000000## Copyright (C) 2016-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 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"; toread = toread * 2; % this line was missing 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 = udp_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 instrument-control-0.7.1/inst/@octave_udp/fwrite.m0000644000000000000000000000374014170330734020465 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/get.m0000644000000000000000000000422014170330734017736 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/read.m0000644000000000000000000000443114170330734020076 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/set.m0000644000000000000000000000542014170330734017755 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udp/write.m0000644000000000000000000000606114170330734020316 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/0000755000000000000000000000000014170330734017710 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_udpport/configureMulticast.m0000644000000000000000000000307214170330734023737 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/configureTerminator.m0000644000000000000000000000323614170330734024120 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/flush.m0000644000000000000000000000303514170330734021210 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/fprintf.m0000644000000000000000000000277514170330734021551 0ustar0000000000000000## 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 formargs = varargin(3:nargin); format = varargin{2}; endif if (! ( ischar (format))) print_usage (); endif numbytes = __udpport_write__ (varargin{1}, sprintf (format, formargs{:})); endfunction instrument-control-0.7.1/inst/@octave_udpport/fread.m0000644000000000000000000000627314170330734021157 0ustar0000000000000000## 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"; toread = toread * 2; 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 instrument-control-0.7.1/inst/@octave_udpport/fwrite.m0000644000000000000000000000403014170330734021363 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/get.m0000644000000000000000000000451414170330734020651 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/read.m0000644000000000000000000000460414170330734021005 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/set.m0000644000000000000000000000533314170330734020665 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_udpport/write.m0000644000000000000000000000606714170330734021231 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_usbtmc/0000755000000000000000000000000014170330734017510 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_usbtmc/fclose.m0000644000000000000000000000166114170330734021145 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_usbtmc/fopen.m0000644000000000000000000000172014170330734020775 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_usbtmc/fread.m0000644000000000000000000000623414170330734020754 0ustar0000000000000000## Copyright (C) 2019-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 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"; toread = toread * 2; 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 instrument-control-0.7.1/inst/@octave_usbtmc/fwrite.m0000644000000000000000000000407014170330734021167 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_vxi11/0000755000000000000000000000000014170330734017163 5ustar0000000000000000instrument-control-0.7.1/inst/@octave_vxi11/fclose.m0000644000000000000000000000157214170330734020621 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_vxi11/fopen.m0000644000000000000000000000171714170330734020456 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/@octave_vxi11/fread.m0000644000000000000000000000623114170330734020424 0ustar0000000000000000## Copyright (C) 2019-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 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; 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"; toread = toread * 2; 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 = vxi11_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 instrument-control-0.7.1/inst/@octave_vxi11/fwrite.m0000644000000000000000000000374114170330734020646 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/__instrument_control__.m0000644000000000000000000000453614170330734021504 0ustar0000000000000000## 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 (deprecated) ## serial port functionality. It has been deprecated 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 instrument-control-0.7.1/inst/clrdevice.m0000644000000000000000000000204514170330734016671 0ustar0000000000000000## 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); instrument-control-0.7.1/inst/flushinput.m0000644000000000000000000000405514170330734017135 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/flushoutput.m0000644000000000000000000000364514170330734017342 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/instrhelp.m0000644000000000000000000000300314170330734016734 0ustar0000000000000000## 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) instrument-control-0.7.1/inst/instrhwinfo.m0000644000000000000000000001104214170330734017300 0ustar0000000000000000## 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) instrument-control-0.7.1/inst/seriallist.m0000644000000000000000000000230614170330734017104 0ustar0000000000000000## 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")) instrument-control-0.7.1/inst/serialportlist.m0000644000000000000000000000362614170330734020017 0ustar0000000000000000## 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")) instrument-control-0.7.1/inst/spoll.m0000644000000000000000000000333714170330734016067 0ustar0000000000000000## 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 instrument-control-0.7.1/inst/tcpip.m0000644000000000000000000000460514170330734016054 0ustar0000000000000000## 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 deprecated. 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); instrument-control-0.7.1/inst/trigger.m0000644000000000000000000000201214170330734016366 0ustar0000000000000000## 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); instrument-control-0.7.1/inst/udp_demo.m0000644000000000000000000000430314170330734016524 0ustar0000000000000000## 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'); instrument-control-0.7.1/src/0000755000000000000000000000000014170330734014364 5ustar0000000000000000instrument-control-0.7.1/src/Makefile.in0000644000000000000000000000222114170330734016426 0ustar0000000000000000 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 instrument-control-0.7.1/src/aclocal.m40000644000000000000000000003207214170330734016230 0ustar0000000000000000# generated automatically by aclocal 1.16.2 -*- Autoconf -*- # Copyright (C) 1996-2020 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]) instrument-control-0.7.1/src/bootstrap0000755000000000000000000000031714170330734016330 0ustar0000000000000000#!/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 instrument-control-0.7.1/src/common.mk0000644000000000000000000000173414170330734016212 0ustar0000000000000000OCTAVE_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 instrument-control-0.7.1/src/common.mk.in0000644000000000000000000000172514170330734016617 0ustar0000000000000000OCTAVE_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 instrument-control-0.7.1/src/config.h.in0000644000000000000000000000777114170330734016423 0ustar0000000000000000/* 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 /* Dont define guid == ops */ #undef _NO_SYS_GUID_OPERATOR_EQ_ #include "oct-alt-includes.h" instrument-control-0.7.1/src/configure0000755000000000000000000050532314170330734016303 0ustar0000000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for octave instrument control package 0.7.1. # # # 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.1' PACKAGE_STRING='octave instrument control package 0.7.1' 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 runstatedir 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' runstatedir='${localstatedir}/run' 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 ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -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 runstatedir 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.1 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] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --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.1:";; 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.1 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.1, 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 # prevent some warnings by defining this ... $as_echo "#define _NO_SYS_GUID_OPERATOR_EQ_ 1" >>confdefs.h 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.1, 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.1 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;} instrument-control-0.7.1/src/configure.ac0000644000000000000000000002640714170330734016663 0ustar0000000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # ### Copyright (C) 2020-2022 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.1]) 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]) # prevent some warnings by defining this ... AC_DEFINE([_NO_SYS_GUID_OPERATOR_EQ_], [1], [Dont define guid == ops]) 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 ]) instrument-control-0.7.1/src/gpib/0000755000000000000000000000000014170330734015305 5ustar0000000000000000instrument-control-0.7.1/src/gpib/Makefile.in0000644000000000000000000000041714170330734017354 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/gpib/__gpib_clrdevice__.cc0000644000000000000000000000322714170330734021355 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/__gpib_pkg_lock__.cc0000644000000000000000000000276114170330734021210 0ustar0000000000000000// 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 instrument-control-0.7.1/src/gpib/__gpib_spoll__.cc0000644000000000000000000000347214170330734020550 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/__gpib_trigger__.cc0000644000000000000000000000320014170330734021047 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/gpib.cc0000644000000000000000000000615114170330734016540 0ustar0000000000000000// 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 instrument-control-0.7.1/src/gpib/gpib_class.cc0000644000000000000000000002042414170330734017724 0ustar0000000000000000// 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 instrument-control-0.7.1/src/gpib/gpib_class.h0000644000000000000000000000400314170330734017561 0ustar0000000000000000// 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 instrument-control-0.7.1/src/gpib/gpib_close.cc0000644000000000000000000000314614170330734017726 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/gpib_read.cc0000644000000000000000000000551514170330734017536 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/gpib_timeout.cc0000644000000000000000000000472114170330734020307 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/gpib/gpib_write.cc0000644000000000000000000000506114170330734017751 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/hwinfo/0000755000000000000000000000000014170330734015656 5ustar0000000000000000instrument-control-0.7.1/src/hwinfo/Makefile.in0000644000000000000000000000023014170330734017716 0ustar0000000000000000OCT := ../__instr_hwinfo__.oct OBJ := __instr_hwinfo__.o LFLAGS = $(LIBS) @TCPLIBS@ CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ include ../common.mk instrument-control-0.7.1/src/hwinfo/__instr_hwinfo__.cc0000644000000000000000000000415514170330734021477 0ustar0000000000000000// 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 instrument-control-0.7.1/src/i2c/0000755000000000000000000000000014170330734015041 5ustar0000000000000000instrument-control-0.7.1/src/i2c/Makefile.in0000644000000000000000000000032114170330734017102 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/i2c/__i2c_pkg_lock__.cc0000644000000000000000000000275114170330734020477 0ustar0000000000000000// 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 instrument-control-0.7.1/src/i2c/__i2c_properties__.cc0000644000000000000000000000525214170330734021101 0ustar0000000000000000// 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(); } instrument-control-0.7.1/src/i2c/i2c.cc0000644000000000000000000000622214170330734016027 0ustar0000000000000000// 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 instrument-control-0.7.1/src/i2c/i2c_addr.cc0000644000000000000000000000451714170330734017026 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/i2c/i2c_class.cc0000644000000000000000000001605514170330734017221 0ustar0000000000000000// 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 instrument-control-0.7.1/src/i2c/i2c_class.h0000644000000000000000000000551114170330734017056 0ustar0000000000000000// 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 instrument-control-0.7.1/src/i2c/i2c_close.cc0000644000000000000000000000314714170330734017217 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/i2c/i2c_read.cc0000644000000000000000000000524614170330734017027 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/i2c/i2c_write.cc0000644000000000000000000000466614170330734017253 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/m4/0000755000000000000000000000000014170330734014704 5ustar0000000000000000instrument-control-0.7.1/src/m4/octave-forge.m40000644000000000000000000000676214170330734017542 0ustar0000000000000000# 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)] ) ]) instrument-control-0.7.1/src/oct-alt-includes.h0000644000000000000000000000030414170330734017701 0ustar0000000000000000/* generated by configure */ #include #include #include #include #include instrument-control-0.7.1/src/parallel/0000755000000000000000000000000014170330734016160 5ustar0000000000000000instrument-control-0.7.1/src/parallel/Makefile.in0000644000000000000000000000033014170330734020221 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/parallel/__parallel_pkg_lock__.cc0000644000000000000000000000302114170330734022724 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/parallel.cc0000644000000000000000000000655414170330734020275 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/parallel_class.cc0000644000000000000000000001422114170330734021450 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/parallel_class.h0000644000000000000000000000371514170330734021320 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/pp_close.cc0000644000000000000000000000410114170330734020267 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/pp_ctrl.cc0000644000000000000000000000516614170330734020142 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/pp_data.cc0000644000000000000000000000515314170330734020103 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/pp_datadir.cc0000644000000000000000000000612114170330734020576 0ustar0000000000000000// 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 instrument-control-0.7.1/src/parallel/pp_stat.cc0000644000000000000000000000417614170330734020151 0ustar0000000000000000// 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 instrument-control-0.7.1/src/resolvehost/0000755000000000000000000000000014170330734016741 5ustar0000000000000000instrument-control-0.7.1/src/resolvehost/Makefile.in0000644000000000000000000000021514170330734021004 0ustar0000000000000000OCT := ../resolvehost.oct OBJ := resolvehost.o LFLAGS = $(LIBS) @TCPLIBS@ CFLAGS = $(CXXFLAGS) $(CPPFLAGS) @DEFS@ include ../common.mk instrument-control-0.7.1/src/resolvehost/resolvehost.cc0000644000000000000000000001405114170330734021626 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/0000755000000000000000000000000014170330734015643 5ustar0000000000000000instrument-control-0.7.1/src/serial/Makefile.in0000644000000000000000000000045514170330734017714 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/serial/__serial_pkg_lock__.cc0000644000000000000000000000300114170330734022070 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/__srl_properties__.cc0000644000000000000000000002701314170330734022025 0ustar0000000000000000// 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"); } instrument-control-0.7.1/src/serial/serial.cc0000644000000000000000000001063214170330734017433 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class.cc0000644000000000000000000000641314170330734020622 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class.h0000644000000000000000000001245314170330734020465 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class_lin.cc0000644000000000000000000003626714170330734021476 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class_lin.h0000644000000000000000000000406314170330734021325 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class_win32.cc0000644000000000000000000003103414170330734021641 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serial/serial_class_win32.h0000644000000000000000000000422214170330734021502 0ustar0000000000000000// 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 #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #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 instrument-control-0.7.1/src/serial/srl_read.cc0000644000000000000000000000525314170330734017752 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/serial/srl_write.cc0000644000000000000000000000504614170330734020171 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/serialport/0000755000000000000000000000000014170330734016550 5ustar0000000000000000instrument-control-0.7.1/src/serialport/Makefile.in0000644000000000000000000000052014170330734020612 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/serialport/__serialport_pkg_lock__.cc0000644000000000000000000000304114170330734023706 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/__srlp_properties__.cc0000644000000000000000000003363514170330734023121 0ustar0000000000000000// 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"); } instrument-control-0.7.1/src/serialport/__srlp_read__.cc0000644000000000000000000000534014170330734021630 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/serialport/__srlp_write__.cc0000644000000000000000000000513714170330734022053 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/serialport/serialport.cc0000644000000000000000000001616514170330734021254 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class.cc0000644000000000000000000001242314170330734022432 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class.h0000644000000000000000000001306514170330734022277 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class_lin.cc0000644000000000000000000004170614170330734023302 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class_lin.h0000644000000000000000000000415314170330734023137 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class_win32.cc0000644000000000000000000003402214170330734023453 0ustar0000000000000000// 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 instrument-control-0.7.1/src/serialport/serialport_class_win32.h0000644000000000000000000000431614170330734023320 0ustar0000000000000000// 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 #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #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 instrument-control-0.7.1/src/spi/0000755000000000000000000000000014170330734015157 5ustar0000000000000000instrument-control-0.7.1/src/spi/Makefile.in0000644000000000000000000000033114170330734017221 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/spi/__spi_pkg_lock__.cc0000644000000000000000000000275114170330734020733 0ustar0000000000000000// 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 instrument-control-0.7.1/src/spi/__spi_properties__.cc0000644000000000000000000000613214170330734021333 0ustar0000000000000000// 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(); } instrument-control-0.7.1/src/spi/spi.cc0000644000000000000000000001231314170330734016261 0ustar0000000000000000// 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 instrument-control-0.7.1/src/spi/spi_class.cc0000644000000000000000000002257414170330734017460 0ustar0000000000000000// 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 instrument-control-0.7.1/src/spi/spi_class.h0000644000000000000000000000624314170330734017315 0ustar0000000000000000// 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 instrument-control-0.7.1/src/spi/spi_close.cc0000644000000000000000000000314314170330734017447 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/spi/spi_read.cc0000644000000000000000000000513714170330734017262 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/spi/spi_write.cc0000644000000000000000000000455714170330734017506 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/spi/spi_writeAndRead.cc0000644000000000000000000000576314170330734020725 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/tcp/0000755000000000000000000000000014170330734015152 5ustar0000000000000000instrument-control-0.7.1/src/tcp/Makefile.in0000644000000000000000000000034314170330734017217 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/tcp/__tcp_pkg_lock__.cc0000644000000000000000000000275114170330734020721 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/__tcp_properties__.cc0000644000000000000000000001164714170330734021330 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp.cc0000644000000000000000000001450114170330734016250 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_class.cc0000644000000000000000000002436214170330734017443 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_class.h0000644000000000000000000000645514170330734017310 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_close.cc0000644000000000000000000000355314170330734017442 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_read.cc0000644000000000000000000000717314170330734017252 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_timeout.cc0000644000000000000000000000567514170330734020032 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcp/tcp_write.cc0000644000000000000000000000573214170330734017470 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/0000755000000000000000000000000014170330734016351 5ustar0000000000000000instrument-control-0.7.1/src/tcpclient/Makefile.in0000644000000000000000000000037314170330734020421 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/tcpclient/__tcpclient_pkg_lock__.cc0000644000000000000000000000303114170330734023307 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/__tcpclient_properties__.cc0000644000000000000000000001555214170330734023725 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/__tcpclient_read__.cc0000644000000000000000000000733514170330734022444 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/__tcpclient_write__.cc0000644000000000000000000000606014170330734022655 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/tcpclient.cc0000644000000000000000000001347014170330734020652 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/tcpclient_class.cc0000644000000000000000000003117014170330734022034 0ustar0000000000000000// 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 instrument-control-0.7.1/src/tcpclient/tcpclient_class.h0000644000000000000000000000776014170330734021706 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/0000755000000000000000000000000014170330734015154 5ustar0000000000000000instrument-control-0.7.1/src/udp/Makefile.in0000644000000000000000000000034214170330734017220 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/udp/__udp_pkg_lock__.cc0000644000000000000000000000275114170330734020725 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/__udp_properties__.cc0000644000000000000000000001247414170330734021333 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp.cc0000644000000000000000000001411314170330734016253 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_class.cc0000644000000000000000000002757614170330734017461 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_class.h0000644000000000000000000000703114170330734017303 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_close.cc0000644000000000000000000000356514170330734017451 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_read.cc0000644000000000000000000000712514170330734017253 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_timeout.cc0000644000000000000000000000611114170330734020020 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udp/udp_write.cc0000644000000000000000000000636614170330734017500 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/0000755000000000000000000000000014170330734016061 5ustar0000000000000000instrument-control-0.7.1/src/udpport/Makefile.in0000644000000000000000000000035414170330734020130 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/udpport/__udpport_pkg_lock__.cc0000644000000000000000000000301114170330734022525 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/__udpport_properties__.cc0000644000000000000000000002030214170330734023132 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/__udpport_read__.cc0000644000000000000000000001013714170330734021656 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/__udpport_write__.cc0000644000000000000000000001025014170330734022071 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/udpport.cc0000644000000000000000000001377114170330734020076 0ustar0000000000000000// 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 instrument-control-0.7.1/src/udpport/udpport_class.cc0000644000000000000000000004512414170330734021260 0ustar0000000000000000// 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 instrument-control-0.7.1/src/undef-ah-octave.h0000644000000000000000000000070614170330734017506 0ustar0000000000000000/* 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 instrument-control-0.7.1/src/usbtmc/0000755000000000000000000000000014170330734015661 5ustar0000000000000000instrument-control-0.7.1/src/usbtmc/Makefile.in0000644000000000000000000000030614170330734017725 0ustar0000000000000000OCT := ../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 instrument-control-0.7.1/src/usbtmc/__usbtmc_pkg_lock__.cc0000644000000000000000000000300114170330734022124 0ustar0000000000000000// 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 instrument-control-0.7.1/src/usbtmc/usbtmc.cc0000644000000000000000000000470214170330734017470 0ustar0000000000000000// 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 instrument-control-0.7.1/src/usbtmc/usbtmc_class.cc0000644000000000000000000000536314170330734020661 0ustar0000000000000000// 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 instrument-control-0.7.1/src/usbtmc/usbtmc_class.h0000644000000000000000000000337214170330734020521 0ustar0000000000000000// 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 instrument-control-0.7.1/src/usbtmc/usbtmc_close.cc0000644000000000000000000000341514170330734020655 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/usbtmc/usbtmc_read.cc0000644000000000000000000000575014170330734020467 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/usbtmc/usbtmc_write.cc0000644000000000000000000000542114170330734020701 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/vxi11/0000755000000000000000000000000014170330734015334 5ustar0000000000000000instrument-control-0.7.1/src/vxi11/Makefile.in0000644000000000000000000000126314170330734017403 0ustar0000000000000000VXI := 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 instrument-control-0.7.1/src/vxi11/__vxi11_pkg_lock__.cc0000644000000000000000000000277114170330734021267 0ustar0000000000000000// 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 instrument-control-0.7.1/src/vxi11/vxi11.cc0000644000000000000000000000455314170330734016622 0ustar0000000000000000// 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 instrument-control-0.7.1/src/vxi11/vxi11.h0000644000000000000000000002711114170330734016457 0ustar0000000000000000/* * 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 */ instrument-control-0.7.1/src/vxi11/vxi11.x0000644000000000000000000001373014170330734016501 0ustar0000000000000000% %/* 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; instrument-control-0.7.1/src/vxi11/vxi11_class.cc0000644000000000000000000002424714170330734020011 0ustar0000000000000000// 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; } instrument-control-0.7.1/src/vxi11/vxi11_class.h0000644000000000000000000000401714170330734017644 0ustar0000000000000000// 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 instrument-control-0.7.1/src/vxi11/vxi11_clnt.c0000644000000000000000000001351314170330734017473 0ustar0000000000000000/* * 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)); } instrument-control-0.7.1/src/vxi11/vxi11_close.cc0000644000000000000000000000317114170330734020002 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/vxi11/vxi11_read.cc0000644000000000000000000000526114170330734017612 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/vxi11/vxi11_svc.c0000644000000000000000000002317114170330734017327 0ustar0000000000000000/* * 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 */ } instrument-control-0.7.1/src/vxi11/vxi11_write.cc0000644000000000000000000000467014170330734020034 0ustar0000000000000000// 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 } instrument-control-0.7.1/src/vxi11/vxi11_xdr.c0000644000000000000000000003076414170330734017337 0ustar0000000000000000/* * 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; }