summaryrefslogtreecommitdiff
path: root/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'bindings')
-rw-r--r--bindings/CMakeLists.txt3
-rw-r--r--bindings/csharp/.gitignore3
-rw-r--r--bindings/csharp/AssemblyInfo.cs.in5
-rw-r--r--bindings/csharp/Attr.cs102
-rw-r--r--bindings/csharp/CMakeLists.txt70
-rw-r--r--bindings/csharp/Channel.cs236
-rw-r--r--bindings/csharp/Context.cs231
-rw-r--r--bindings/csharp/Device.cs262
-rw-r--r--bindings/csharp/IOBuffer.cs143
-rw-r--r--bindings/csharp/Trigger.cs67
-rw-r--r--bindings/csharp/examples/ExampleProgram.cs82
-rw-r--r--bindings/csharp/key.snkbin0 -> 596 bytes
-rw-r--r--bindings/csharp/libiio-sharp.dll.config.cmakein3
-rw-r--r--bindings/csharp/libiio-sharp.pc.cmakein10
-rw-r--r--bindings/matlab/CMakeLists.txt26
-rw-r--r--bindings/matlab/iio-wrapper.h46
-rw-r--r--bindings/matlab/iio_installer_script.m17
-rw-r--r--bindings/matlab/iio_sys_obj.m474
-rw-r--r--bindings/matlab/iio_sys_obj_matlab.m350
-rw-r--r--bindings/matlab/libiio_if.m701
-rw-r--r--bindings/matlab/libiio_if_daq2.m701
-rw-r--r--bindings/python/.gitignore3
-rw-r--r--bindings/python/CMakeLists.txt21
-rwxr-xr-xbindings/python/examples/iio_info.py89
-rw-r--r--bindings/python/iio.py864
-rw-r--r--bindings/python/setup.py.cmakein24
26 files changed, 4533 insertions, 0 deletions
diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
new file mode 100644
index 0000000..e2afcf0
--- /dev/null
+++ b/bindings/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_subdirectory(csharp)
+add_subdirectory(matlab)
+add_subdirectory(python)
diff --git a/bindings/csharp/.gitignore b/bindings/csharp/.gitignore
new file mode 100644
index 0000000..475b306
--- /dev/null
+++ b/bindings/csharp/.gitignore
@@ -0,0 +1,3 @@
+AssemblyInfo.cs
+libiio-sharp-0.5.pc
+libiio-sharp.dll.config
diff --git a/bindings/csharp/AssemblyInfo.cs.in b/bindings/csharp/AssemblyInfo.cs.in
new file mode 100644
index 0000000..5d1de04
--- /dev/null
+++ b/bindings/csharp/AssemblyInfo.cs.in
@@ -0,0 +1,5 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly:AssemblyVersion("@LIBIIO_CS_VERSION@")]
+[assembly:AssemblyDelaySign(false)]
diff --git a/bindings/csharp/Attr.cs b/bindings/csharp/Attr.cs
new file mode 100644
index 0000000..2ddcc3e
--- /dev/null
+++ b/bindings/csharp/Attr.cs
@@ -0,0 +1,102 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ /// <summary><see cref="iio.Attr"/> class:
+ /// Contains the representation of a channel or device attribute.</summary>
+ public abstract class Attr
+ {
+ /// <summary>The name of this attribute.</summary>
+ public readonly string name;
+
+ /// <summary>The filename in sysfs to which this attribute is bound.</summary>
+ public readonly string filename;
+
+ internal Attr(string name, string filename = null)
+ {
+ this.filename = filename == null ? name : filename;
+ this.name = name;
+ }
+
+ /// <summary>Read the value of this attribute as a <c>string</c>.</summary>
+ /// <exception cref="System.Exception">The attribute could not be read.</exception>
+ public abstract string read();
+
+ /// <summary>Set this attribute to the value contained in the <c>string</c> argument.</summary>
+ /// <param name="val">The <c>string</c> value to set the parameter to.</param>
+ /// <exception cref="System.Exception">The attribute could not be written.</exception>
+ public abstract void write(string val);
+
+ /// <summary>Read the value of this attribute as a <c>bool</c>.</summary>
+ /// <exception cref="System.Exception">The attribute could not be read.</exception>
+ public bool read_bool()
+ {
+ string val = read();
+ return (val.CompareTo("1") == 0) || (val.CompareTo("Y") == 0);
+ }
+
+ /// <summary>Read the value of this attribute as a <c>double</c>.</summary>
+ /// <exception cref="System.Exception">The attribute could not be read.</exception>
+ public double read_double()
+ {
+ return double.Parse(read(), CultureInfo.InvariantCulture);
+ }
+
+ /// <summary>Read the value of this attribute as a <c>long</c>.</summary>
+ /// <exception cref="System.Exception">The attribute could not be read.</exception>
+ public long read_long()
+ {
+ return long.Parse(read(), CultureInfo.InvariantCulture);
+ }
+
+ /// <summary>Set this attribute to the value contained in the <c>bool</c> argument.</summary>
+ /// <param name="val">The <c>bool</c> value to set the parameter to.</param>
+ /// <exception cref="System.Exception">The attribute could not be written.</exception>
+ public void write(bool val)
+ {
+ if (val)
+ write("1");
+ else
+ write("0");
+ }
+
+ /// <summary>Set this attribute to the value contained in the <c>long</c> argument.</summary>
+ /// <param name="val">The <c>long</c> value to set the parameter to.</param>
+ /// <exception cref="System.Exception">The attribute could not be written.</exception>
+ public void write(long val)
+ {
+ write(val.ToString(CultureInfo.InvariantCulture));
+ }
+
+ /// <summary>Set this attribute to the value contained in the <c>double</c> argument.</summary>
+ /// <param name="val">The <c>double</c> value to set the parameter to.</param>
+ /// <exception cref="System.Exception">The attribute could not be written.</exception>
+ public void write(double val)
+ {
+ write(val.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+}
diff --git a/bindings/csharp/CMakeLists.txt b/bindings/csharp/CMakeLists.txt
new file mode 100644
index 0000000..7e9d19b
--- /dev/null
+++ b/bindings/csharp/CMakeLists.txt
@@ -0,0 +1,70 @@
+cmake_minimum_required(VERSION 2.8.7)
+project(libiio-sharp NONE)
+
+if (WIN32)
+ set(MCS_EXECUTABLE_NAME csc)
+else()
+ set(MCS_EXECUTABLE_NAME mcs)
+endif()
+
+find_program(MCS_EXECUTABLE
+ NAMES ${MCS_EXECUTABLE_NAME}
+ HINTS "C:/Windows/Microsoft.NET/Framework/v4.0.30319"
+ PATHS ENV MCS_EXECUTABLE_PATH
+ DOC "C# compiler")
+mark_as_advanced(MCS_EXECUTABLE)
+
+if (MCS_EXECUTABLE)
+ option(CSHARP_BINDINGS "Install C# bindings" ON)
+
+ if (CSHARP_BINDINGS)
+ set(LIBIIO_CS_PC_IN "${CMAKE_CURRENT_SOURCE_DIR}/libiio-sharp.pc.cmakein")
+ set(LIBIIO_CS_PC "${CMAKE_CURRENT_BINARY_DIR}/libiio-sharp-${VERSION}.pc")
+ configure_file(${LIBIIO_CS_PC_IN} ${LIBIIO_CS_PC} @ONLY)
+ if(NOT SKIP_INSTALL_ALL)
+ install(FILES ${LIBIIO_CS_PC} DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
+ endif()
+
+ set(LIBIIO_CS_DLL_CONFIG_IN "${CMAKE_CURRENT_SOURCE_DIR}/libiio-sharp.dll.config.cmakein")
+ set(LIBIIO_CS_DLL_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/libiio-sharp.dll.config")
+ configure_file(${LIBIIO_CS_DLL_CONFIG_IN} ${LIBIIO_CS_DLL_CONFIG} @ONLY)
+ if(NOT SKIP_INSTALL_ALL)
+ install(FILES ${LIBIIO_CS_DLL_CONFIG} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/cli/libiio-sharp-${VERSION})
+ endif()
+
+ set(LIBIIO_CS_VERSION ${VERSION}.0.0)
+ set(LIBIIO_CS_INFO_IN ${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cs.in)
+ set(LIBIIO_CS_INFO ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs)
+ configure_file(${LIBIIO_CS_INFO_IN} ${LIBIIO_CS_INFO} @ONLY)
+
+ set(LIBIIO_CS_DLL "${CMAKE_CURRENT_BINARY_DIR}/libiio-sharp.dll")
+ set(LIBIIO_CS_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/Attr.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/Channel.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/Context.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/Device.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/IOBuffer.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/Trigger.cs
+ ${LIBIIO_CS_INFO}
+ )
+
+ foreach(SRC ${LIBIIO_CS_SOURCES})
+ file(TO_NATIVE_PATH ${SRC} TMP)
+ set(LIBIIO_CS_SOURCES_REALPATH ${LIBIIO_CS_SOURCES_REALPATH} ${TMP})
+ endforeach(SRC)
+
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/key.snk SIGN_KEY)
+ file(TO_NATIVE_PATH ${LIBIIO_CS_DLL} LIBIIO_CS_DLL_OUT)
+
+ add_custom_command(OUTPUT ${LIBIIO_CS_DLL}
+ COMMAND ${MCS_EXECUTABLE} /target:library /out:${LIBIIO_CS_DLL_OUT} /debug /keyfile:${SIGN_KEY} ${LIBIIO_CS_SOURCES_REALPATH}
+ DEPENDS ${LIBIIO_CS_SOURCES}
+ )
+
+ add_custom_target(libiio-sharp ALL DEPENDS ${LIBIIO_CS_DLL})
+
+ if(NOT SKIP_INSTALL_ALL)
+ install(FILES ${LIBIIO_CS_DLL} ${LIBIIO_CS_DLL}.mdb DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/cli/libiio-sharp-${VERSION})
+ endif()
+ endif()
+endif()
diff --git a/bindings/csharp/Channel.cs b/bindings/csharp/Channel.cs
new file mode 100644
index 0000000..491a4ad
--- /dev/null
+++ b/bindings/csharp/Channel.cs
@@ -0,0 +1,236 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ /// <summary><see cref="iio.Channel"/> class:
+ /// Contains the representation of an input or output channel.</summary>
+ public class Channel
+ {
+ private class ChannelAttr : Attr
+ {
+ private IntPtr chn;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_channel_attr_read(IntPtr chn, [In()] string name, [Out()] StringBuilder val, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_channel_attr_write(IntPtr chn, [In()] string name, string val);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_channel_attr_get_filename(IntPtr chn, [In()] string attr);
+
+ public ChannelAttr(IntPtr chn, string name) : base(name, Marshal.PtrToStringAnsi(iio_channel_attr_get_filename(chn, name)))
+ {
+ this.chn = chn;
+ }
+
+ public override string read()
+ {
+ StringBuilder builder = new StringBuilder(1024);
+ int err = iio_channel_attr_read(chn, name, builder, (uint) builder.Capacity);
+ if (err < 0)
+ throw new Exception("Unable to read channel attribute " + err);
+ return builder.ToString();
+ }
+
+ public override void write(string str)
+ {
+ int err = iio_channel_attr_write(chn, name, str);
+ if (err < 0)
+ throw new Exception("Unable to write channel attribute " + err);
+ }
+ }
+
+
+ private IntPtr chn;
+ private uint sample_size;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_channel_get_id(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_channel_get_name(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_channel_get_attrs_count(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_channel_get_attr(IntPtr chn, uint index);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool iio_channel_is_output(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool iio_channel_is_scan_element(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void iio_channel_enable(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void iio_channel_disable(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool iio_channel_is_enabled(IntPtr chn);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_channel_get_data_format(IntPtr chn);
+
+ /// <summary>The name of this channel.</summary>
+ public readonly string name;
+
+ /// <summary>An identifier of this channel.</summary>
+ /// <remarks>It is possible that two channels have the same ID,
+ /// if one is an input channel and the other is an output channel.</remarks>
+ public readonly string id;
+
+ /// <summary>Contains <c>true</c> if the channel is an output channel,
+ /// <c>false</c> otherwise.</summary>
+ public readonly bool output;
+
+ /// <summary>Contains <c>true</c> if the channel is a scan element,
+ /// <c>false</c> otherwise.</summary>
+ /// <remarks>If a channel is a scan element, then it is possible to enable it
+ /// and use it for I/O operations.</remarks>
+ public readonly bool scan_element;
+
+ /// <summary>A <c>list</c> of all the attributes that this channel has.</summary>
+ public readonly List<Attr> attrs;
+
+ internal Channel(IntPtr chn)
+ {
+ this.chn = chn;
+ attrs = new List<Attr>();
+ sample_size = (uint)Marshal.ReadInt32(iio_channel_get_data_format(this.chn)) / 8;
+ uint nb_attrs = iio_channel_get_attrs_count(chn);
+
+ for (uint i = 0; i < nb_attrs; i++)
+ attrs.Add(new ChannelAttr(this.chn, Marshal.PtrToStringAnsi(iio_channel_get_attr(chn, i))));
+
+ IntPtr name_ptr = iio_channel_get_name(this.chn);
+ if (name_ptr == IntPtr.Zero)
+ name = "";
+ else
+ name = Marshal.PtrToStringAnsi(name_ptr);
+
+ id = Marshal.PtrToStringAnsi(iio_channel_get_id(this.chn));
+ output = iio_channel_is_output(this.chn);
+ scan_element = iio_channel_is_scan_element(this.chn);
+ }
+
+ /// <summary>Enable the current channel, so that it can be used for I/O operations.</summary>
+ public void enable()
+ {
+ iio_channel_enable(this.chn);
+ }
+
+ /// <summary>Disable the current channel.</summary>
+ public void disable()
+ {
+ iio_channel_disable(this.chn);
+ }
+
+ /// <summary>Returns whether or not the channel has been enabled.</summary>
+ public bool is_enabled()
+ {
+ return iio_channel_is_enabled(this.chn);
+ }
+
+ /// <summary>Extract the samples corresponding to this channel from the
+ /// given <see cref="iio.IOBuffer"/> object.</summary>
+ /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param>
+ /// <param name="raw">If set to <c>true</c>, the samples are not converted from their
+ /// hardware format to their host format.</param>
+ /// <returns>A <c>byte</c> array containing the extracted samples.</returns>
+ /// <exception cref="System.Exception">The samples could not be read.</exception>
+ public byte[] read(IOBuffer buffer, bool raw = false)
+ {
+ if (!is_enabled())
+ throw new Exception("Channel must be enabled before the IOBuffer is instantiated");
+ if (this.output)
+ throw new Exception("Unable to read from output channel");
+
+ byte[] array = new byte[(int) (buffer.samples_count * sample_size)];
+ MemoryStream stream = new MemoryStream(array, true);
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ IntPtr addr = handle.AddrOfPinnedObject();
+ uint count;
+
+ if (raw)
+ count = iio_channel_read_raw(this.chn, buffer.buf, addr, buffer.samples_count * sample_size);
+ else
+ count = iio_channel_read(this.chn, buffer.buf, addr, buffer.samples_count * sample_size);
+ handle.Free();
+ stream.SetLength((long) count);
+ return stream.ToArray();
+
+ }
+
+ /// <summary>
+ /// Write the specified array of samples corresponding to this channel into the
+ /// given <see cref="iio.IOBuffer"/> object.</summary>
+ /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param>
+ /// <param name="array">A <c>byte</c> array containing the samples to write.</param>
+ /// <param name="raw">If set to <c>true</c>, the samples are not converted from their
+ /// host format to their native format.</param>
+ /// <returns>The number of bytes written.</returns>
+ /// <exception cref="System.Exception">The samples could not be written.</exception>
+ public uint write(IOBuffer buffer, byte[] array, bool raw = false)
+ {
+ if (!is_enabled())
+ throw new Exception("Channel must be enabled before the IOBuffer is instantiated");
+ if (!this.output)
+ throw new Exception("Unable to write to an input channel");
+
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ IntPtr addr = handle.AddrOfPinnedObject();
+ uint count;
+
+ if (raw)
+ count = iio_channel_write_raw(this.chn, buffer.buf, addr, (uint) array.Length);
+ else
+ count = iio_channel_write(this.chn, buffer.buf, addr, (uint) array.Length);
+ handle.Free();
+
+ return count;
+ }
+ }
+}
diff --git a/bindings/csharp/Context.cs b/bindings/csharp/Context.cs
new file mode 100644
index 0000000..e5c478f
--- /dev/null
+++ b/bindings/csharp/Context.cs
@@ -0,0 +1,231 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ public class Version
+ {
+ public readonly uint major;
+ public readonly uint minor;
+ public readonly string git_tag;
+
+ internal Version(uint major, uint minor, string git_tag)
+ {
+ this.major = major;
+ this.minor = minor;
+ this.git_tag = git_tag;
+ }
+ }
+
+ /// <summary><see cref="iio.Context"/> class:
+ /// Contains the representation of an IIO context.</summary>
+ public class Context : IDisposable
+ {
+ private IntPtr ctx;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_create_network_context(
+ [In()][MarshalAs(UnmanagedType.LPStr)] string hostname
+ );
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_create_context_from_uri(
+ [In()][MarshalAs(UnmanagedType.LPStr)] string uri
+ );
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_create_default_context();
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void iio_context_destroy(IntPtr ctx);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_context_get_name(IntPtr ctx);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_context_get_description(IntPtr ctx);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_context_get_xml(IntPtr ctx);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void iio_library_get_version(ref uint major, ref uint minor, [Out()] StringBuilder git_tag);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_context_get_version(IntPtr ctx, ref uint major, ref uint minor, [Out()] StringBuilder git_tag);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_context_get_devices_count(IntPtr ctx);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_context_get_device(IntPtr ctx, uint index);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool iio_device_is_trigger(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_context_set_timeout(IntPtr ctx, uint timeout_ms);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_context_clone(IntPtr ctx);
+
+ /// <summary>A XML representation of the current context.</summary>
+ public readonly string xml;
+
+ /// <summary>The name of the current context.</summary>
+ public readonly string name;
+
+ /// <summary>Retrieve a human-readable information string about the current context.</summary>
+ public readonly string description;
+ public readonly Version library_version, backend_version;
+
+ /// <summary>A <c>List</c> of all the IIO devices present on the current context.</summary>
+ public readonly List<Device> devices;
+
+ /// <summary>Initializes a new instance of the <see cref="iio.Context"/> class,
+ /// using the provided URI. For compatibility with existing code, providing
+ /// an IP address or a hostname here will automatically create a network
+ /// context.</summary>
+ /// <param name="uri">URI to use for the IIO context creation</param>
+ /// <returns>an instance of the <see cref="iio.Context"/> class</returns>
+ /// <exception cref="System.Exception">The IIO context could not be created.</exception>
+ public Context(string uri) : this(getContextFromString(uri)) {}
+
+ /// <summary>Initializes a new instance of the <see cref="iio.Context"/> class,
+ /// using the local or the network backend of the IIO library.</summary>
+ /// <remarks>This function will create a network context if the IIOD_REMOTE
+ /// environment variable is set to the hostname where the IIOD server runs.
+ /// If set to an empty string, the server will be discovered using ZeroConf.
+ /// If the environment variable is not set, a local context will be created
+ /// instead.</remarks>
+ /// <exception cref="System.Exception">The IIO context could not be created.</exception>
+ public Context() : this(iio_create_default_context()) {}
+
+ private static IntPtr getContextFromString(string str)
+ {
+ IntPtr ptr = iio_create_context_from_uri(str);
+ if (ptr == IntPtr.Zero)
+ ptr = iio_create_network_context(str);
+ return ptr;
+ }
+
+ private Context(IntPtr ctx)
+ {
+ this.ctx = ctx;
+
+ if (ctx == IntPtr.Zero)
+ throw new Exception("Unable to create IIO context");
+
+ uint nb_devices = iio_context_get_devices_count(ctx);
+
+ devices = new List<Device>();
+ for (uint i = 0; i < nb_devices; i++)
+ {
+ IntPtr ptr = iio_context_get_device(ctx, i);
+ if (iio_device_is_trigger(ptr))
+ devices.Add(new Trigger(this, ptr));
+ else
+ devices.Add(new Device(this, ptr));
+ }
+
+ xml = Marshal.PtrToStringAnsi(iio_context_get_xml(ctx));
+ name = Marshal.PtrToStringAnsi(iio_context_get_name(ctx));
+ description = Marshal.PtrToStringAnsi(iio_context_get_description(ctx));
+
+ uint major = 0;
+ uint minor = 0;
+ StringBuilder builder = new StringBuilder(8);
+ iio_library_get_version(ref major, ref minor, builder);
+ library_version = new Version(major, minor, builder.ToString());
+
+ major = 0;
+ minor = 0;
+ builder.Clear();
+ int err = iio_context_get_version(ctx, ref major, ref minor, builder);
+ if (err < 0)
+ throw new Exception("Unable to read backend version");
+ backend_version = new Version(major, minor, builder.ToString());
+ }
+
+ ~Context()
+ {
+ if (ctx != IntPtr.Zero)
+ Dispose(false);
+ }
+
+ /// <summary>Clone this instance.</summary>
+ public Context clone()
+ {
+ return new Context(iio_context_clone(this.ctx));
+ }
+
+ /// <summary>Get the <see cref="iio.Device"/> object of the specified name.</summary>
+ /// <param name="name">Name or ID of the device to look for</param>
+ /// <exception cref="System.Exception">The IIO device with the specified
+ /// name or ID could not be found in the current context.</exception>
+ public Device get_device(string name)
+ {
+ foreach (Device each in devices) {
+ if (each.name.CompareTo(name) == 0 ||
+ each.id.CompareTo(name) == 0)
+ return each;
+ }
+
+ throw new Exception("Device " + name + " not found");
+ }
+
+ /// <summary>Set a timeout for I/O operations.</summary>
+ /// <param name="timeout">The timeout value, in milliseconds</param>
+ /// <exception cref="System.Exception">The timeout could not be applied.</exception>
+ public void set_timeout(uint timeout)
+ {
+ int ret = iio_context_set_timeout(ctx, timeout);
+ if (ret < 0)
+ throw new Exception("Unable to set timeout");
+ }
+
+ /// <summary>Releases all resource used by the <see cref="iio.Context"/> object.</summary>
+ /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="iio.Context"/>. The
+ /// <see cref="Dispose"/> method leaves the <see cref="iio.Context"/> in an unusable state. After calling
+ /// <see cref="Dispose"/>, you must release all references to the <see cref="iio.Context"/> so the garbage
+ /// collector can reclaim the memory that the <see cref="iio.Context"/> was occupying.</remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ private void Dispose(bool clean)
+ {
+ if (ctx != IntPtr.Zero)
+ {
+ if (clean)
+ GC.SuppressFinalize(this);
+ iio_context_destroy(ctx);
+ ctx = IntPtr.Zero;
+ }
+ }
+ }
+}
diff --git a/bindings/csharp/Device.cs b/bindings/csharp/Device.cs
new file mode 100644
index 0000000..8d7fa82
--- /dev/null
+++ b/bindings/csharp/Device.cs
@@ -0,0 +1,262 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ /// <summary><see cref="iio.Device"/> class:
+ /// Contains the representation of an IIO device.</summary>
+ public class Device
+ {
+ private class DeviceAttr : Attr
+ {
+ private IntPtr dev;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_attr_write(IntPtr dev, [In()] string name, [In()] string val);
+
+ public DeviceAttr(IntPtr dev, string name) : base(name)
+ {
+ this.dev = dev;
+ }
+
+ public override string read()
+ {
+ StringBuilder builder = new StringBuilder(1024);
+ int err = iio_device_attr_read(dev, name, builder, 1024);
+ if (err < 0)
+ throw new Exception("Unable to read device attribute " + err);
+ return builder.ToString();
+ }
+
+ public override void write(string str)
+ {
+ int err = iio_device_attr_write(dev, name, str);
+ if (err < 0)
+ throw new Exception("Unable to write device attribute " + err);
+ }
+ }
+
+ private class DeviceDebugAttr : Attr
+ {
+ private IntPtr dev;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_debug_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_debug_attr_write(IntPtr dev, [In()] string name, [In()] string val);
+
+ public DeviceDebugAttr(IntPtr dev, string name) : base(name)
+ {
+ this.dev = dev;
+ }
+
+ public override string read()
+ {
+ StringBuilder builder = new StringBuilder(1024);
+ int err = iio_device_debug_attr_read(dev, name, builder, 1024);
+ if (err < 0)
+ throw new Exception("Unable to read debug attribute " + err);
+ return builder.ToString();
+ }
+
+ public override void write(string str)
+ {
+ int err = iio_device_debug_attr_write(dev, name, str);
+ if (err < 0)
+ throw new Exception("Unable to write debug attribute " + err);
+ }
+ }
+
+ private Context ctx;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_get_id(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_get_name(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_device_get_channels_count(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_get_channel(IntPtr dev, uint index);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_device_get_attrs_count(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern uint iio_device_get_debug_attrs_count(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_get_attr(IntPtr dev, uint index);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_get_debug_attr(IntPtr dev, uint index);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_get_trigger(IntPtr dev, IntPtr triggerptr);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_set_trigger(IntPtr dev, IntPtr trigger);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_get_sample_size(IntPtr dev);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_reg_write(IntPtr dev, uint addr, uint value);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_device_reg_read(IntPtr dev, uint addr, ref uint value);
+
+ internal IntPtr dev;
+
+ /// <summary>An identifier of this device.</summary>
+ /// <remarks>The identifier is only valid in this IIO context</remarks>
+ public readonly string id;
+
+ /// <summary>The name of this device.</summary>
+ public readonly string name;
+
+ /// <summary>A <c>list</c> of all the attributes that this device has.</summary>
+ public readonly List<Attr> attrs;
+
+ /// <summary>A <c>list</c> of all the debug attributes that this device has.</summary>
+ public readonly List<Attr> debug_attrs;
+
+ /// <summary>A <c>list</c> of all the <see cref="iio.Channel"/> objects that this device possesses.</summary>
+ public readonly List<Channel> channels;
+
+ internal Device(Context ctx, IntPtr dev)
+ {
+ this.ctx = ctx;
+ this.dev = dev;
+ channels = new List<Channel>();
+ attrs = new List<Attr>();
+ debug_attrs = new List<Attr>();
+
+ uint nb_channels = iio_device_get_channels_count(dev),
+ nb_attrs = iio_device_get_attrs_count(dev),
+ nb_debug_attrs = iio_device_get_debug_attrs_count(dev);
+
+ for (uint i = 0; i < nb_channels; i++)
+ channels.Add(new Channel(iio_device_get_channel(dev, i)));
+
+ for (uint i = 0; i < nb_attrs; i++)
+ attrs.Add(new DeviceAttr(dev, Marshal.PtrToStringAnsi(iio_device_get_attr(dev, i))));
+ for (uint i = 0; i < nb_debug_attrs; i++)
+ debug_attrs.Add(new DeviceDebugAttr(dev, Marshal.PtrToStringAnsi(iio_device_get_debug_attr(dev, i))));
+
+ id = Marshal.PtrToStringAnsi(iio_device_get_id(dev));
+
+ IntPtr name_ptr = iio_device_get_name(dev);
+ if (name_ptr == IntPtr.Zero)
+ name = "";
+ else
+ name = Marshal.PtrToStringAnsi(name_ptr);
+ }
+
+ /// <summary>Get the <see cref="iio.Channel"/> object of the specified name.</summary>
+ /// <param name="name">Name or ID of the channel to look for</param>
+ /// <exception cref="System.Exception">The IIO device with the specified
+ /// name or ID could not be found in the current context.</exception>
+ public Channel get_channel(string name)
+ {
+ foreach (Channel each in channels) {
+ if (each.name.CompareTo(name) == 0 ||
+ each.id.CompareTo(name) == 0)
+ return each;
+ }
+
+ throw new Exception("Channel " + name + " not found");
+ }
+
+ /// <summary>Affect a trigger to this device.</summary>
+ /// <param name="trig">A valid instance of the <see cref="iio.Trigger"/> class.</param>
+ /// <exception cref="System.Exception">The trigger could not be set.</exception>
+ public void set_trigger(Trigger trig)
+ {
+ int err = iio_device_set_trigger(this.dev, trig == null ? IntPtr.Zero : trig.dev);
+ if (err < 0)
+ throw new Exception("Unable to set trigger: err=" + err);
+ }
+
+ /// <summary>Get the current trigger affected to this device.</summary>
+ /// <returns>An instance of the <see cref="iio.Trigger"/> class.</returns>
+ /// <exception cref="System.Exception">The instance could not be retrieved.</exception>
+ public Trigger get_trigger()
+ {
+ IntPtr ptr = (IntPtr)0;
+ int err = iio_device_get_trigger(this.dev, ptr);
+ if (err < 0)
+ throw new Exception("Unable to get trigger: err=" + err);
+
+ ptr = Marshal.ReadIntPtr(ptr);
+
+ foreach (Trigger trig in ctx.devices) {
+ if (trig.dev == ptr)
+ return trig;
+ }
+
+ return null;
+ }
+
+ /// <summary>Get the current sample size of the device.</summary>
+ /// <remarks>The sample size varies each time channels get enabled or disabled.</remarks>
+ /// <exception cref="System.Exception">Internal error. Please report any bug.</exception>
+ public uint get_sample_size()
+ {
+ int ret = iio_device_get_sample_size(dev);
+ if (ret < 0)
+ throw new Exception("Internal error. Please report any bug.");
+ return (uint) ret;
+ }
+ /// <summary>Set a value to one register of this device.</summary>
+ /// <param name="addr">The address of the register concerned.</param>
+ /// <param name="value">The value that will be used for this register.</param>
+ /// <exception cref="System.Exception">The register could not be written.</exception>
+ public void reg_write(uint addr, uint value)
+ {
+ int err = iio_device_reg_write(dev, addr, value);
+ if (err < 0)
+ throw new Exception("Unable to write register");
+ }
+
+ /// <summary>Read the content of a register of this device.</summary>
+ /// <param name="addr">The address of the register concerned.</param>
+ /// <exception cref="System.Exception">The register could not be read.</exception>
+ public uint reg_read(uint addr)
+ {
+ uint value = 0;
+ int err = iio_device_reg_read(dev, addr, ref value);
+ if (err < 0)
+ throw new Exception("Unable to read register");
+ return value;
+ }
+ }
+}
diff --git a/bindings/csharp/IOBuffer.cs b/bindings/csharp/IOBuffer.cs
new file mode 100644
index 0000000..1697f6e
--- /dev/null
+++ b/bindings/csharp/IOBuffer.cs
@@ -0,0 +1,143 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ /// <summary><see cref="iio.IOBuffer"/> class:
+ /// The class used for all I/O operations.</summary>
+ public class IOBuffer : IDisposable
+ {
+ private bool circular_buffer_pushed;
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_device_create_buffer(IntPtr dev, uint samples_count,
+ [MarshalAs(UnmanagedType.I1)] bool circular);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void iio_buffer_destroy(IntPtr buf);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_buffer_refill(IntPtr buf);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int iio_buffer_push_partial(IntPtr buf, uint samples_count);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_buffer_start(IntPtr buf);
+
+ [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr iio_buffer_end(IntPtr buf);
+
+ internal IntPtr buf;
+
+ /// <summary>The size of this buffer, in samples.</summary>
+ public readonly uint samples_count;
+
+ /// <summary>If <c>true</c>, the buffer is circular.</summary>
+ public readonly bool circular;
+
+ /// <summary>Initializes a new instance of the <see cref="iio.IOBuffer"/> class.</summary>
+ /// <param name="dev">The <see cref="iio.Device"/> object that represents the device
+ /// where the I/O operations will be performed.</param>
+ /// <param name="samples_count">The size of the buffer, in samples.</param>
+ /// <param name="circular">If set to <c>true</c>, the buffer is circular.</param>
+ /// <exception cref="System.Exception">The buffer could not be created.</exception>
+ public IOBuffer(Device dev, uint samples_count, bool circular = false)
+ {
+ this.samples_count = samples_count;
+ this.circular = circular;
+ this.circular_buffer_pushed = false;
+
+ buf = iio_device_create_buffer(dev.dev, samples_count, circular);
+ if (buf == IntPtr.Zero)
+ throw new Exception("Unable to create buffer");
+ }
+
+ ~IOBuffer()
+ {
+ if (buf != IntPtr.Zero)
+ Dispose(false);
+ }
+
+ /// <summary>Fetch a new set of samples from the hardware.</summary>
+ /// <exception cref="System.Exception">The buffer could not be refilled.</exception>
+ public void refill()
+ {
+ int err = iio_buffer_refill(this.buf);
+ if (err < 0)
+ throw new Exception("Unable to refill buffer: err=" + err);
+ }
+
+ /// <summary>Submit the samples contained in this buffer to the hardware.</summary>
+ /// <exception cref="System.Exception">The buffer could not be pushed.</exception>
+ public void push(uint samples_count)
+ {
+ if (circular && circular_buffer_pushed)
+ throw new Exception("Circular buffer already pushed\n");
+
+ int err = iio_buffer_push_partial(this.buf, samples_count);
+ if (err < 0)
+ throw new Exception("Unable to push buffer: err=" + err);
+ circular_buffer_pushed = true;
+ }
+
+ public void push()
+ {
+ push(this.samples_count);
+ }
+
+ /// <summary>Releases all resource used by the <see cref="iio.IOBuffer"/> object.</summary>
+ /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="iio.IOBuffer"/>. The
+ /// <see cref="Dispose"/> method leaves the <see cref="iio.IOBuffer"/> in an unusable state. After calling
+ /// <see cref="Dispose"/>, you must release all references to the <see cref="iio.IOBuffer"/> so the garbage
+ /// collector can reclaim the memory that the <see cref="iio.IOBuffer"/> was occupying.</remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ private void Dispose(bool clean)
+ {
+ if (buf != IntPtr.Zero)
+ {
+ if (clean)
+ GC.SuppressFinalize(this);
+ iio_buffer_destroy(buf);
+ buf = IntPtr.Zero;
+ }
+ }
+
+ /// <summary>Copy the given array of samples inside the <see cref="iio.IOBuffer"/> object.</summary>
+ /// <param name="array">A <c>byte</c> array containing the samples that should be written.</param>
+ /// <remarks>The number of samples written will not exceed the size of the buffer.</remarks>
+ public void fill(byte[] array)
+ {
+ int length = (int) iio_buffer_end(buf) - (int) iio_buffer_start(buf);
+ if (length > array.Length)
+ length = array.Length;
+ Marshal.Copy(array, 0, iio_buffer_start(buf), length);
+ }
+ }
+}
diff --git a/bindings/csharp/Trigger.cs b/bindings/csharp/Trigger.cs
new file mode 100644
index 0000000..4614143
--- /dev/null
+++ b/bindings/csharp/Trigger.cs
@@ -0,0 +1,67 @@
+/*
+ * libiio - Library for interfacing industrial I/O (IIO) devices
+ *
+ * Copyright (C) 2015 Analog Devices, Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace iio
+{
+ /// <summary><see cref="iio.Trigger"/> class:
+ /// Contains the representation of an IIO device that can act as a trigger.</summary>
+ public class Trigger : Device
+ {
+ internal Trigger(Context ctx, IntPtr ptr) : base(ctx, ptr) { }
+
+ /// <summary>Configure a new frequency for this trigger.</summary>
+ /// <exception cref="System.Exception">The new frequency could not be set.</exception>
+ public void set_rate(ulong rate)
+ {
+ foreach (Attr each in attrs)
+ if (each.name.Equals("frequency"))
+ {
+ each.write((long) rate);
+ return;
+ }
+ throw new Exception("Trigger has no frequency?");
+ }
+
+ /// <summary>Get the currently configured frequency of this trigger.</summary>
+ /// <exception cref="System.Exception">The configured frequency could not be obtained.</exception>
+ public ulong get_rate()
+ {
+ foreach (Attr each in attrs)
+ if (each.name.Equals("frequency"))
+ return (ulong) each.read_long();
+ throw new Exception("Trigger has no frequency?");
+ }
+
+ public new void set_trigger(Trigger trig)
+ {
+ throw new InvalidComObjectException("Device is already a trigger");
+ }
+
+ public new Trigger get_trigger()
+ {
+ throw new InvalidComObjectException("Device is already a trigger");
+ }
+ }
+}
diff --git a/bindings/csharp/examples/ExampleProgram.cs b/bindings/csharp/examples/ExampleProgram.cs
new file mode 100644
index 0000000..f33e381
--- /dev/null
+++ b/bindings/csharp/examples/ExampleProgram.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using iio;
+
+namespace IIOCSharp
+{
+ class ExampleProgram
+ {
+ static void Main(string[] args)
+ {
+ Context ctx = new Context("10.44.2.241");
+ if (ctx == null)
+ {
+ Console.WriteLine("Unable to create IIO context");
+ return;
+ }
+
+ Console.WriteLine("IIO context created: " + ctx.name);
+ Console.WriteLine("IIO context description: " + ctx.description);
+
+ Console.WriteLine("IIO context has " + ctx.devices.Count + " devices:");
+ foreach (Device dev in ctx.devices) {
+ Console.WriteLine("\t" + dev.id + ": " + dev.name);
+
+ if (dev is Trigger)
+ {
+ Console.WriteLine("Found trigger! Rate=" + ((Trigger) dev).get_rate());
+ }
+
+ Console.WriteLine("\t\t" + dev.channels.Count + " channels found:");
+
+ foreach (Channel chn in dev.channels)
+ {
+ string type = "input";
+ if (chn.output)
+ type = "output";
+ Console.WriteLine("\t\t\t" + chn.id + ": " + chn.name + " (" + type + ")");
+
+ if (chn.attrs.Count == 0)
+ continue;
+
+ Console.WriteLine("\t\t\t" + chn.attrs.Count + " channel-specific attributes found:");
+ foreach (Attr attr in chn.attrs)
+ {
+ Console.WriteLine("\t\t\t\t" + attr.name);
+ if (attr.name.CompareTo("frequency") == 0)
+ {
+ Console.WriteLine("Attribute content: " + attr.read());
+ }
+ }
+
+ }
+
+ /* If we find cf-ad9361-lpc, try to read a few bytes from the first channel */
+ if (dev.name.CompareTo("cf-ad9361-lpc") == 0)
+ {
+ Channel chn = dev.channels[0];
+ chn.enable();
+ IOBuffer buf = new IOBuffer(dev, 0x8000);
+ buf.refill();
+
+ Console.WriteLine("Read " + chn.read(buf).Length + " bytes from hardware");
+ buf.Dispose();
+ }
+
+ if (dev.attrs.Count == 0)
+ continue;
+
+ Console.WriteLine("\t\t" + dev.attrs.Count + " device-specific attributes found:");
+ foreach (Attr attr in dev.attrs)
+ Console.WriteLine("\t\t\t" + attr.name);
+
+ }
+
+ /* Wait for user input */
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/bindings/csharp/key.snk b/bindings/csharp/key.snk
new file mode 100644
index 0000000..fc21149
--- /dev/null
+++ b/bindings/csharp/key.snk
Binary files differ
diff --git a/bindings/csharp/libiio-sharp.dll.config.cmakein b/bindings/csharp/libiio-sharp.dll.config.cmakein
new file mode 100644
index 0000000..c9ef9bb
--- /dev/null
+++ b/bindings/csharp/libiio-sharp.dll.config.cmakein
@@ -0,0 +1,3 @@
+<configuration>
+ <dllmap dll="libiio.dll" target="libiio.so.@LIBIIO_VERSION_MAJOR@"/>
+</configuration>
diff --git a/bindings/csharp/libiio-sharp.pc.cmakein b/bindings/csharp/libiio-sharp.pc.cmakein
new file mode 100644
index 0000000..5e6fd22
--- /dev/null
+++ b/bindings/csharp/libiio-sharp.pc.cmakein
@@ -0,0 +1,10 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_PREFIX@/lib
+
+Name: libiio-cs
+Description: CLI bindings for libiio
+Version: @VERSION@
+
+Requires:
+Libs: -r:${libdir}/cli/libiio-sharp-@VERSION@/libiio-sharp.dll
diff --git a/bindings/matlab/CMakeLists.txt b/bindings/matlab/CMakeLists.txt
new file mode 100644
index 0000000..4eea7d5
--- /dev/null
+++ b/bindings/matlab/CMakeLists.txt
@@ -0,0 +1,26 @@
+find_program(
+ MATLAB_EXECUTABLE
+ NAMES matlab
+ DOC "Matlab main program"
+)
+mark_as_advanced(MATLAB_EXECUTABLE)
+
+option(WITH_MATLAB_BINDINGS_API "Enable MATLAB bindings API" ON)
+
+if (MATLAB_EXECUTABLE AND NOT SKIP_INSTALL_ALL)
+ option(MATLAB_BINDINGS "Install MATLAB bindings" ON)
+
+ if (MATLAB_BINDINGS)
+ install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/share/libiio"
+ PATTERN "CMakeLists.txt" EXCLUDE
+ )
+ install(
+ CODE "execute_process(
+ COMMAND ${MATLAB_EXECUTABLE} -nodesktop
+ -nodisplay -r \"cd('${CMAKE_INSTALL_PREFIX}/share/libiio/matlab');iio_installer_script;exit;\"
+ OUTPUT_QUIET)")
+ set(WITH_MATLAB_BINDINGS_API ON CACHE BOOL "" FORCE)
+ endif()
+endif()
diff --git a/bindings/matlab/iio-wrapper.h b/bindings/matlab/iio-wrapper.h
new file mode 100644
index 0000000..ce2b046
--- /dev/null
+++ b/bindings/matlab/iio-wrapper.h
@@ -0,0 +1,46 @@
+#ifndef MATLAB_LOADLIBRARY
+#define MATLAB_LOADLIBRARY
+#include <iio.h>
+
+#ifndef __api
+#define __api
+#endif
+
+struct iio_scan_block;
+
+/** @brief Create a scan block
+* @param backend A NULL-terminated string containing the backend to use for
+* scanning. If NULL, all the available backends are used.
+* @param flags Unused for now. Set to 0.
+* @return on success, a pointer to a iio_scan_block structure
+* @return On failure, NULL is returned and errno is set appropriately */
+__api struct iio_scan_block * iio_create_scan_block(
+ const char *backend, unsigned int flags);
+
+
+/** @brief Destroy the given scan block
+* @param ctx A pointer to an iio_scan_block structure
+*
+* <b>NOTE:</b> After that function, the iio_scan_block pointer shall be invalid. */
+__api void iio_scan_block_destroy(struct iio_scan_block *blk);
+
+
+/** @brief Enumerate available contexts via scan block
+* @param blk A pointer to a iio_scan_block structure.
+* @returns On success, the number of contexts found.
+* @returns On failure, a negative error number.
+*/
+__api ssize_t iio_scan_block_scan(struct iio_scan_block *blk);
+
+
+/** @brief Get the iio_context_info for a particular context
+* @param blk A pointer to an iio_scan_block structure
+* @param index The index corresponding to the context.
+* @return A pointer to the iio_context_info for the context
+* @returns On success, a pointer to the specified iio_context_info
+* @returns On failure, NULL is returned and errno is set appropriately
+*/
+__api struct iio_context_info *iio_scan_block_get_info(
+ struct iio_scan_block *blk, unsigned int index);
+
+#endif
diff --git a/bindings/matlab/iio_installer_script.m b/bindings/matlab/iio_installer_script.m
new file mode 100644
index 0000000..1276729
--- /dev/null
+++ b/bindings/matlab/iio_installer_script.m
@@ -0,0 +1,17 @@
+function installer_script(varargin)
+ if nargin > 0
+ install = varargin{1}; % use the command line arguement
+ else
+ install = true; % assume install
+ end
+ thisDir = fileparts(mfilename('fullpath')); % path to this script
+
+ if install
+ pathfunc = @addpath; % add paths for installation
+ else
+ pathfunc = @rmpath; % remove paths for uninstall
+ end
+
+ pathfunc(thisDir);
+ savepath;
+end
diff --git a/bindings/matlab/iio_sys_obj.m b/bindings/matlab/iio_sys_obj.m
new file mode 100644
index 0000000..1f8380f
--- /dev/null
+++ b/bindings/matlab/iio_sys_obj.m
@@ -0,0 +1,474 @@
+% Copyright 2014-15(c) Analog Devices, Inc.
+%
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without modification,
+% are permitted provided that the following conditions are met:
+% - Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% - Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in
+% the documentation and/or other materials provided with the
+% distribution.
+% - Neither the name of Analog Devices, Inc. nor the names of its
+% contributors may be used to endorse or promote products derived
+% from this software without specific prior written permission.
+% - The use of this software may or may not infringe the patent rights
+% of one or more patent holders. This license does not release you
+% from the requirement that you obtain separate licenses from these
+% patent holders to use this software.
+% - Use of the software either in source or binary form or filter designs
+% resulting from the use of this software, must be connected to, run
+% on or loaded to an Analog Devices Inc. component.
+%
+% THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+% INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+% PARTICULAR PURPOSE ARE DISCLAIMED.
+%
+% IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
+% RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+classdef iio_sys_obj < matlab.System & matlab.system.mixin.Propagates ...
+ & matlab.system.mixin.CustomIcon
+ % iio_sys_obj System Object block for IIO devices
+
+ properties (Nontunable)
+ % Public, non-tunable properties.
+
+ %ip_address IP address
+ ip_address = '';
+
+ %dev_name Device name
+ dev_name = '';
+
+ %in_ch_no Number of input data channels
+ in_ch_no = 0;
+
+ %in_ch_size Input data channel size [samples]
+ in_ch_size = 8192;
+
+ %out_ch_no Number of output data channels
+ out_ch_no = 0;
+
+ %out_ch_size Output data channel size [samples]
+ out_ch_size = 8192;
+ end
+
+ properties (Access = protected)
+ % Protected class properties.
+
+ %iio_dev_cfg Device configuration structure
+ iio_dev_cfg = [];
+ end
+
+ properties (Access = private)
+ % Private class properties.
+
+ %libiio_data_in_dev libiio IIO interface object for the input data device
+ libiio_data_in_dev = {};
+
+ %libiio_data_out_dev libiio IIO interface object for the output data device
+ libiio_data_out_dev = {};
+
+ %libiio_ctrl_dev libiio IIO interface object for the control device
+ libiio_ctrl_dev = {};
+
+ %sys_obj_initialized Holds the initialization status of the system object
+ sys_obj_initialized = 0;
+ end
+
+ properties (DiscreteState)
+ % Discrete state properties.
+
+ %num_cfg_in Numeric type input control channels data
+ num_cfg_in;
+
+ %str_cfg_in String type input control channels data
+ str_cfg_in;
+ end
+
+ methods
+ %% Constructor
+ function obj = iio_sys_obj(varargin)
+ % Construct the libiio interface objects
+ obj.libiio_data_in_dev = libiio_if();
+ obj.libiio_data_out_dev = libiio_if();
+ obj.libiio_ctrl_dev = libiio_if();
+
+ % Support name-value pair arguments when constructing the object.
+ setProperties(obj,nargin,varargin{:});
+ end
+ end
+
+ methods (Access = protected)
+ %% Utility functions
+
+ function config = getObjConfig(obj)
+ % Read the selected device configuration
+
+ % Open the configuration file
+ fname = sprintf('%s.cfg', obj.dev_name);
+ fp_cfg = fopen(fname);
+ if(fp_cfg < 0)
+ config = {};
+ return;
+ end
+
+ % Build the object configuration structure
+ config = struct('data_in_device', '',... % Pointer to the data input device
+ 'data_out_device', '',... % Pointer to the data output device
+ 'ctrl_device', '',... % Pointer to the control device
+ 'cfg_ch', [],... % Configuration channels list
+ 'mon_ch', []); % Monitoring channels list
+
+ % Build the configuration/monitoring channels structure
+ ch_cfg = struct('port_name', '',... % Name of the port to be displayed on the object block
+ 'port_attr', '',... % Associated device attribute name
+ 'ctrl_dev_name', '',... % Control device name
+ 'ctrl_dev', 0); % Pointer to the control device object
+
+ % Read the object's configuration
+ while(~feof(fp_cfg))
+ line = fgets(fp_cfg);
+ if(strfind(line,'#'))
+ continue;
+ end
+ if(~isempty(strfind(line, 'channel')))
+ % Get the associated configuration/monitoring channels
+ idx = strfind(line, '=');
+ line = line(idx+1:end);
+ line = strsplit(line, ',');
+ ch_cfg.port_name = strtrim(line{1});
+ ch_cfg.port_attr = strtrim(line{3});
+ if(length(line) > 4)
+ ch_cfg.ctrl_dev_name = strtrim(line{4});
+ else
+ ch_cfg.ctrl_dev_name = 'ctrl_device';
+ end
+ if(strcmp(strtrim(line{2}), 'IN'))
+ config.cfg_ch = [config.cfg_ch ch_cfg];
+ elseif(strcmp(strtrim(line{2}), 'OUT'))
+ config.mon_ch = [config.mon_ch ch_cfg];
+ end
+ elseif(~isempty(strfind(line, 'data_in_device')))
+ % Get the associated data input device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.data_in_device = tmp;
+ elseif(~isempty(strfind(line, 'data_out_device')))
+ % Get the associated data output device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.data_out_device = tmp;
+ elseif(~isempty(strfind(line, 'ctrl_device')))
+ % Get the associated control device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.ctrl_device = tmp;
+ end
+ end
+ fclose(fp_cfg);
+ end
+
+ end
+
+ methods (Access = protected)
+ %% Common functions
+ function setupImpl(obj)
+ % Implement tasks that need to be performed only once.
+
+ % Set the initialization status to fail
+ obj.sys_obj_initialized = 0;
+
+ % Read the object's configuration from the associated configuration file
+ obj.iio_dev_cfg = getObjConfig(obj);
+ if(isempty(obj.iio_dev_cfg))
+ msgbox('Could not read device configuration!', 'Error','error');
+ return;
+ end
+
+ % Initialize discrete-state properties.
+ obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch));
+ obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64);
+
+ % Initialize the libiio data input device
+ if(obj.in_ch_no ~= 0)
+ [ret, err_msg, msg_log] = init(obj.libiio_data_in_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.data_in_device, 'OUT', ...
+ obj.in_ch_no, obj.in_ch_size);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Initialize the libiio data output device
+ if(obj.out_ch_no ~= 0)
+ [ret, err_msg, msg_log] = init(obj.libiio_data_out_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.data_out_device, 'IN', ...
+ obj.out_ch_no, obj.out_ch_size);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Initialize the libiio control device
+ if(~isempty(obj.iio_dev_cfg.ctrl_device))
+ [ret, err_msg, msg_log] = init(obj.libiio_ctrl_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.ctrl_device, '', ...
+ 0, 0);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Assign the control device for each monitoring channel
+ for i = 1 : length(obj.iio_dev_cfg.mon_ch)
+ if(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_in_device'))
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_in_dev;
+ elseif(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_out_device'))
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_out_dev;
+ else
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_ctrl_dev;
+ end
+ end
+
+ % Assign the control device for each configuration channel
+ for i = 1 : length(obj.iio_dev_cfg.cfg_ch)
+ if(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_in_device'))
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_in_dev;
+ elseif(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_out_device'))
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_out_dev;
+ else
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_ctrl_dev;
+ end
+ end
+
+ % Set the initialization status to success
+ obj.sys_obj_initialized = 1;
+ end
+
+ function releaseImpl(obj)
+ % Release any resources used by the system object.
+ obj.iio_dev_cfg = {};
+ delete(obj.libiio_data_in_dev);
+ delete(obj.libiio_data_out_dev);
+ delete(obj.libiio_ctrl_dev);
+ end
+
+ function varargout = stepImpl(obj, varargin)
+ % Implement the system object's processing flow.
+ varargout = cell(1, obj.out_ch_no + length(obj.iio_dev_cfg.mon_ch));
+ if(obj.sys_obj_initialized == 0)
+ return;
+ end
+
+ % Implement the device configuration flow
+ for i = 1 : length(obj.iio_dev_cfg.cfg_ch)
+ if(~isempty(varargin{i + obj.in_ch_no}))
+ if(length(varargin{i + obj.in_ch_no}) == 1)
+ new_data = (varargin{i + obj.in_ch_no} ~= obj.num_cfg_in(i));
+ else
+ new_data = ~strncmp(char(varargin{i + obj.in_ch_no}'), char(obj.str_cfg_in(i,:)), length(varargin{i + obj.in_ch_no}));
+ end
+ if(new_data == 1)
+ if(length(varargin{i + obj.in_ch_no}) == 1)
+ obj.num_cfg_in(i) = varargin{i + obj.in_ch_no};
+ str = num2str(obj.num_cfg_in(i));
+ else
+ for j = 1:length(varargin{i + obj.in_ch_no})
+ obj.str_cfg_in(i,j) = varargin{i + obj.in_ch_no}(j);
+ end
+ obj.str_cfg_in(i,j+1) = 0;
+ str = char(obj.str_cfg_in(i,:));
+ end
+ writeAttributeString(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev, obj.iio_dev_cfg.cfg_ch(i).port_attr, str);
+ end
+ end
+ end
+
+ % Implement the data transmit flow
+ writeData(obj.libiio_data_in_dev, varargin);
+
+ % Implement the data capture flow
+ [~, data] = readData(obj.libiio_data_out_dev);
+ for i = 1 : obj.out_ch_no
+ varargout{i} = data{i};
+ end
+
+ % Implement the parameters monitoring flow
+ for i = 1 : length(obj.iio_dev_cfg.mon_ch)
+ [~, val] = readAttributeDouble(obj.iio_dev_cfg.mon_ch(i).ctrl_dev, obj.iio_dev_cfg.mon_ch(i).port_attr);
+ varargout{obj.out_ch_no + i} = val;
+ end
+
+
+ end
+
+ function resetImpl(obj)
+ % Initialize discrete-state properties.
+ obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch));
+ obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64);
+ end
+
+ function num = getNumInputsImpl(obj)
+ % Get number of inputs.
+ num = obj.in_ch_no;
+
+ config = getObjConfig(obj);
+ if(~isempty(config))
+ num = num + length(config.cfg_ch);
+ end
+ end
+
+ function varargout = getInputNamesImpl(obj)
+ % Get input names
+
+ % Get the number of input data channels
+ data_ch_no = obj.in_ch_no;
+
+ % Get number of control channels
+ cfg_ch_no = 0;
+ config = getObjConfig(obj);
+ if(~isempty(config))
+ cgf_ch_no = length(config.cfg_ch);
+ end
+
+ if(data_ch_no + cgf_ch_no ~= 0)
+ varargout = cell(1, data_ch_no + cgf_ch_no);
+ for i = 1 : data_ch_no
+ varargout{i} = sprintf('DATA_IN%d', i);
+ end
+ for i = data_ch_no + 1 : data_ch_no + cgf_ch_no
+ varargout{i} = config.cfg_ch(i - data_ch_no).port_name;
+ end
+ else
+ varargout = {};
+ end
+ end
+
+ function num = getNumOutputsImpl(obj)
+ % Get number of outputs.
+ num = obj.out_ch_no;
+
+ config = getObjConfig(obj);
+ if(~isempty(config))
+ num = num + length(config.mon_ch);
+ end
+ end
+
+ function varargout = getOutputNamesImpl(obj)
+ % Get output names
+
+ % Get the number of output data channels
+ data_ch_no = obj.out_ch_no;
+
+ % Get number of monitoring channels
+ mon_ch_no = 0;
+ config = getObjConfig(obj);
+ if(~isempty(config))
+ mon_ch_no = length(config.mon_ch);
+ end
+
+ if(data_ch_no + mon_ch_no ~= 0)
+ varargout = cell(1, data_ch_no + mon_ch_no);
+ for i = 1 : data_ch_no
+ varargout{i} = sprintf('DATA_OUT%d', i);
+ end
+ for i = data_ch_no + 1 : data_ch_no + mon_ch_no
+ varargout{i} = config.mon_ch(i - data_ch_no).port_name;
+ end
+ else
+ varargout = {};
+ end
+ end
+
+ function varargout = isOutputFixedSizeImpl(obj)
+ % Get outputs fixed size.
+ varargout = cell(1, getNumOutputs(obj));
+ for i = 1 : getNumOutputs(obj)
+ varargout{i} = true;
+ end
+ end
+
+ function varargout = getOutputDataTypeImpl(obj)
+ % Get outputs data types.
+ varargout = cell(1, getNumOutputs(obj));
+ for i = 1 : getNumOutputs(obj)
+ varargout{i} = 'double';
+ end
+ end
+
+ function varargout = isOutputComplexImpl(obj)
+ % Get outputs data types.
+ varargout = cell(1, getNumOutputs(obj));
+ for i = 1 : getNumOutputs(obj)
+ varargout{i} = false;
+ end
+ end
+
+ function varargout = getOutputSizeImpl(obj)
+ % Implement if input size does not match with output size.
+ varargout = cell(1, getNumOutputs(obj));
+ for i = 1:obj.out_ch_no
+ varargout{i} = [obj.out_ch_size 1];
+ end
+ for i = obj.out_ch_no + 1 : length(varargout)
+ varargout{i} = [1 1];
+ end
+ end
+
+ function icon = getIconImpl(obj)
+ % Define a string as the icon for the System block in Simulink.
+ if(~isempty(obj.dev_name))
+ icon = obj.dev_name;
+ else
+ icon = mfilename('class');
+ end
+ end
+
+ %% Backup/restore functions
+ function s = saveObjectImpl(obj)
+ % Save private, protected, or state properties in a
+ % structure s. This is necessary to support Simulink
+ % features, such as SimState.
+ end
+
+ function loadObjectImpl(obj, s, wasLocked)
+ % Read private, protected, or state properties from
+ % the structure s and assign it to the object obj.
+ end
+
+ %% Simulink functions
+ function z = getDiscreteStateImpl(obj)
+ % Return structure of states with field names as
+ % DiscreteState properties.
+ z = struct([]);
+ end
+ end
+
+ methods(Static, Access = protected)
+ %% Simulink customization functions
+ function header = getHeaderImpl(obj)
+ % Define header for the System block dialog box.
+ header = matlab.system.display.Header(mfilename('class'));
+ end
+
+ function group = getPropertyGroupsImpl(obj)
+ % Define section for properties in System block dialog box.
+ group = matlab.system.display.Section(mfilename('class'));
+ end
+ end
+end
diff --git a/bindings/matlab/iio_sys_obj_matlab.m b/bindings/matlab/iio_sys_obj_matlab.m
new file mode 100644
index 0000000..572ec03
--- /dev/null
+++ b/bindings/matlab/iio_sys_obj_matlab.m
@@ -0,0 +1,350 @@
+% Copyright 2014(c) Analog Devices, Inc.
+%
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without modification,
+% are permitted provided that the following conditions are met:
+% - Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% - Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in
+% the documentation and/or other materials provided with the
+% distribution.
+% - Neither the name of Analog Devices, Inc. nor the names of its
+% contributors may be used to endorse or promote products derived
+% from this software without specific prior written permission.
+% - The use of this software may or may not infringe the patent rights
+% of one or more patent holders. This license does not release you
+% from the requirement that you obtain separate licenses from these
+% patent holders to use this software.
+% - Use of the software either in source or binary form or filter designs
+% resulting from the use of this software, must be connected to, run
+% on or loaded to an Analog Devices Inc. component.
+%
+% THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+% INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+% PARTICULAR PURPOSE ARE DISCLAIMED.
+%
+% IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
+% RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+classdef iio_sys_obj_matlab
+ % iio_sys_obj System Object block for IIO devices
+
+ properties (Access = public)
+ % Public, non-tunable properties.
+
+ %ip_address IP address
+ ip_address = '';
+
+ %dev_name Device name
+ dev_name = '';
+
+ %in_ch_no Number of input data channels
+ in_ch_no = 0;
+
+ %in_ch_size Input data channel size [samples]
+ in_ch_size = 8192;
+
+ %out_ch_no Number of output data channels
+ out_ch_no = 0;
+
+ %out_ch_size Output data channel size [samples]
+ out_ch_size = 8192;
+ end
+
+ properties (Access = public)
+ % Protected class properties.
+
+ %iio_dev_cfg Device configuration structure
+ iio_dev_cfg = [];
+ end
+
+ properties (Access = private)
+ % Private class properties.
+
+ %libiio_data_in_dev libiio IIO interface object for the input data device
+ libiio_data_in_dev = {};
+
+ %libiio_data_out_dev libiio IIO interface object for the output data device
+ libiio_data_out_dev = {};
+
+ %libiio_ctrl_dev libiio IIO interface object for the control device
+ libiio_ctrl_dev = {};
+
+ %sys_obj_initialized Holds the initialization status of the system object
+ sys_obj_initialized = 0;
+ end
+
+ properties (Access = private)
+ % Discrete state properties.
+
+ %num_cfg_in Numeric type input control channels data
+ num_cfg_in;
+
+ %str_cfg_in String type input control channels data
+ str_cfg_in;
+ end
+
+ methods
+ %% Constructor
+ function obj = iio_sys_obj_matlab(varargin)
+ % Construct the libiio interface objects
+ obj.libiio_data_in_dev = libiio_if();
+ obj.libiio_data_out_dev = libiio_if();
+ obj.libiio_ctrl_dev = libiio_if();
+ end
+ end
+
+ methods (Access = protected)
+ %% Utility functions
+
+ function config = getObjConfig(obj)
+ % Read the selected device configuration
+
+ % Open the configuration file
+ fname = sprintf('%s.cfg', obj.dev_name);
+ fp_cfg = fopen(fname);
+ if(fp_cfg < 0)
+ config = {};
+ return;
+ end
+
+ % Build the object configuration structure
+ config = struct('data_in_device', '',... % Pointer to the data input device
+ 'data_out_device', '',... % Pointer to the data output device
+ 'ctrl_device', '',... % Pointer to the control device
+ 'cfg_ch', [],... % Configuration channels list
+ 'mon_ch', [],... % Monitoring channels list
+ 'in_ch_names', [],... % Configuration channels names
+ 'out_ch_names', []); % Monitoring channels names
+ config.in_ch_names = {};
+ config.out_ch_names = {};
+
+ % Build the configuration/monitoring channels structure
+ ch_cfg = struct('port_name', '',... % Name of the port to be displayed on the object block
+ 'port_attr', '',... % Associated device attribute name
+ 'ctrl_dev_name', '',... % Control device name
+ 'ctrl_dev', 0); % Pointer to the control device object
+
+ % Read the object's configuration
+ while(~feof(fp_cfg))
+ line = fgets(fp_cfg);
+ if(strfind(line,'#'))
+ continue;
+ end
+ if(~isempty(strfind(line, 'channel')))
+ % Get the associated configuration/monitoring channels
+ idx = strfind(line, '=');
+ line = line(idx+1:end);
+ line = strsplit(line, ',');
+ ch_cfg.port_name = strtrim(line{1});
+ ch_cfg.port_attr = strtrim(line{3});
+ if(length(line) > 4)
+ ch_cfg.ctrl_dev_name = strtrim(line{4});
+ else
+ ch_cfg.ctrl_dev_name = 'ctrl_device';
+ end
+ if(strcmp(strtrim(line{2}), 'IN'))
+ config.cfg_ch = [config.cfg_ch ch_cfg];
+ config.in_ch_names = [config.in_ch_names ch_cfg.port_name];
+ elseif(strcmp(strtrim(line{2}), 'OUT'))
+ config.mon_ch = [config.mon_ch ch_cfg];
+ config.out_ch_names = [config.out_ch_names ch_cfg.port_name];
+ end
+ elseif(~isempty(strfind(line, 'data_in_device')))
+ % Get the associated data input device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.data_in_device = tmp;
+ elseif(~isempty(strfind(line, 'data_out_device')))
+ % Get the associated data output device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.data_out_device = tmp;
+ elseif(~isempty(strfind(line, 'ctrl_device')))
+ % Get the associated control device
+ idx = strfind(line, '=');
+ tmp = line(idx+1:end);
+ tmp = strtrim(tmp);
+ config.ctrl_device = tmp;
+ end
+ end
+ fclose(fp_cfg);
+ end
+
+ end
+
+ methods (Access = public)
+ %% Helper functions
+ function ret = getInChannel(obj, channelName)
+ % Returns the index of a named input channel
+ ret = obj.in_ch_no + find(strcmp(obj.iio_dev_cfg.in_ch_names, channelName));
+ end
+
+ function ret = getOutChannel(obj, channelName)
+ % Returns the index of a named output channel
+ ret = obj.out_ch_no + find(strcmp(obj.iio_dev_cfg.out_ch_names, channelName));
+ end
+
+ %% Common functions
+ function ret = setupImpl(obj)
+ % Implement tasks that need to be performed only once.
+
+ % Set the initialization status to fail
+ obj.sys_obj_initialized = 0;
+
+ % Read the object's configuration from the associated configuration file
+ obj.iio_dev_cfg = getObjConfig(obj);
+ if(isempty(obj.iio_dev_cfg))
+ msgbox('Could not read device configuration!', 'Error','error');
+ return;
+ end
+
+ % Initialize discrete-state properties.
+ obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch));
+ obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64);
+
+ % Initialize the libiio data input device
+ if(obj.in_ch_no ~= 0)
+ [ret, err_msg, msg_log] = init(obj.libiio_data_in_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.data_in_device, 'OUT', ...
+ obj.in_ch_no, obj.in_ch_size);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Initialize the libiio data output device
+ if(obj.out_ch_no ~= 0)
+ [ret, err_msg, msg_log] = init(obj.libiio_data_out_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.data_out_device, 'IN', ...
+ obj.out_ch_no, obj.out_ch_size);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Initialize the libiio control device
+ if(~isempty(obj.iio_dev_cfg.ctrl_device))
+ [ret, err_msg, msg_log] = init(obj.libiio_ctrl_dev, obj.ip_address, ...
+ obj.iio_dev_cfg.ctrl_device, '', ...
+ 0, 0);
+ fprintf('%s', msg_log);
+ if(ret < 0)
+ msgbox(err_msg, 'Error','error');
+ return;
+ end
+ end
+
+ % Assign the control device for each monitoring channel
+ for i = 1 : length(obj.iio_dev_cfg.mon_ch)
+ if(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_in_device'))
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_in_dev;
+ elseif(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_out_device'))
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_out_dev;
+ else
+ obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_ctrl_dev;
+ end
+ end
+
+ % Assign the control device for each configuration channel
+ for i = 1 : length(obj.iio_dev_cfg.cfg_ch)
+ if(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_in_device'))
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_in_dev;
+ elseif(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_out_device'))
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_out_dev;
+ else
+ obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_ctrl_dev;
+ end
+ end
+
+ % Set the initialization status to success
+ obj.sys_obj_initialized = 1;
+ ret = obj;
+ end
+
+ function releaseImpl(obj)
+ % Release any resources used by the system object.
+ obj.iio_dev_cfg = {};
+ delete(obj.libiio_data_in_dev);
+ delete(obj.libiio_data_out_dev);
+ delete(obj.libiio_ctrl_dev);
+ end
+
+ function ret = stepImpl(obj, varargin)
+ % Implement the system object's processing flow.
+ varargout = cell(1, obj.out_ch_no + length(obj.iio_dev_cfg.mon_ch));
+ if(obj.sys_obj_initialized == 0)
+ return;
+ end
+
+ % Implement the device configuration flow
+ for i = 1 : length(obj.iio_dev_cfg.cfg_ch)
+ if(~isempty(varargin{1}{i + obj.in_ch_no}))
+ if(length(varargin{1}{i + obj.in_ch_no}) == 1)
+ new_data = (varargin{1}{i + obj.in_ch_no} ~= obj.num_cfg_in(i));
+ else
+ new_data = ~strncmp(char(varargin{1}{i + obj.in_ch_no}'), char(obj.str_cfg_in(i,:)), length(varargin{1}{i + obj.in_ch_no}));
+ end
+ if(new_data == 1)
+ if(length(varargin{1}{i + obj.in_ch_no}) == 1)
+ obj.num_cfg_in(i) = varargin{1}{i + obj.in_ch_no};
+ str = num2str(obj.num_cfg_in(i));
+ else
+ for j = 1:length(varargin{1}{i + obj.in_ch_no})
+ obj.str_cfg_in(i,j) = varargin{1}{i + obj.in_ch_no}(j);
+ end
+ obj.str_cfg_in(i,j+1) = 0;
+ str = char(obj.str_cfg_in(i,:));
+ end
+ writeAttributeString(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev, obj.iio_dev_cfg.cfg_ch(i).port_attr, str);
+ end
+ end
+ end
+
+ % Implement the data transmit flow
+ writeData(obj.libiio_data_in_dev, varargin{1});
+
+ % Implement the data capture flow
+ [~, data] = readData(obj.libiio_data_out_dev);
+ for i = 1 : obj.out_ch_no
+ varargout{i} = data{i};
+ end
+
+ % Implement the parameters monitoring flow
+ for i = 1 : length(obj.iio_dev_cfg.mon_ch)
+ [~, val] = readAttributeDouble(obj.iio_dev_cfg.mon_ch(i).ctrl_dev, obj.iio_dev_cfg.mon_ch(i).port_attr);
+ varargout{obj.out_ch_no + i} = val;
+ end
+
+ ret=varargout;
+ end
+
+ function ret = writeFirData(obj, fir_data_file)
+ fir_data_str = fileread(fir_data_file);
+ ret = writeAttributeString(obj.libiio_ctrl_dev, 'in_out_voltage_filter_fir_en', '0');
+ if ret<0
+ return;
+ end
+ ret = writeAttributeString(obj.libiio_ctrl_dev, 'filter_fir_config', fir_data_str);
+ if ret<0
+ return;
+ end
+ ret = writeAttributeString(obj.libiio_ctrl_dev, 'in_out_voltage_filter_fir_en', '1');
+ if ret<0
+ return;
+ end
+ end
+ end
+end
diff --git a/bindings/matlab/libiio_if.m b/bindings/matlab/libiio_if.m
new file mode 100644
index 0000000..9fde04d
--- /dev/null
+++ b/bindings/matlab/libiio_if.m
@@ -0,0 +1,701 @@
+% Copyright 2014(c) Analog Devices, Inc.
+%
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without modification,
+% are permitted provided that the following conditions are met:
+% - Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% - Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in
+% the documentation and/or other materials provided with the
+% distribution.
+% - Neither the name of Analog Devices, Inc. nor the names of its
+% contributors may be used to endorse or promote products derived
+% from this software without specific prior written permission.
+% - The use of this software may or may not infringe the patent rights
+% of one or more patent holders. This license does not release you
+% from the requirement that you obtain separate licenses from these
+% patent holders to use this software.
+% - Use of the software either in source or binary form or filter designs
+% resulting from the use of this software, must be connected to, run
+% on or loaded to an Analog Devices Inc. component.
+%
+% THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+% INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+% PARTICULAR PURPOSE ARE DISCLAIMED.
+%
+% IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
+% RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+classdef libiio_if < handle
+ % libiio_if Interface object for for IIO devices
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Protected properties
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ properties (Access = protected)
+ libname = 'libiio';
+ hname = 'iio-wrapper.h';
+ dev_name = '';
+ data_ch_no = 0;
+ data_ch_size = 0;
+ dev_type = '';
+ iio_ctx = {};
+ iio_dev = {};
+ iio_buffer = {};
+ iio_channel = {};
+ iio_buf_size = 8192;
+ iio_scan_elm_no = 0;
+ if_initialized = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Static private methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods (Static, Access = private)
+ function out = modInstanceCnt(val)
+ % Manages the number of object instances to handle proper DLL unloading
+ persistent instance_cnt;
+ if isempty(instance_cnt)
+ instance_cnt = 0;
+ end
+ instance_cnt = instance_cnt + val;
+ out = instance_cnt;
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Protected methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods (Access = protected)
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Creates the network context
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Create the network context
+ obj.iio_ctx = calllib(obj.libname, 'iio_create_network_context', ip_address);
+
+ % Check if the network context is valid
+ if (isNull(obj.iio_ctx))
+ obj.iio_ctx = {};
+ err_msg = 'Could not connect to the IIO server!';
+ return;
+ end
+
+ % Increase the object's instance count
+ libiio_if.modInstanceCnt(1);
+ msg_log = [msg_log sprintf('%s: Connected to IP %s\n', class(obj), ip_address)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Releases the network context and unload the libiio library
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function releaseContext(obj)
+ calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx);
+ obj.iio_ctx = {};
+ instCnt = libiio_if.modInstanceCnt(-1);
+ if(instCnt == 0)
+ unloadlibrary(obj.libname);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Checks the compatibility of the different software modules.
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = checkVersions(obj)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Create a set of pointers to read the iiod and dll versions
+ data = zeros(1, 10);
+ remote_pMajor = libpointer('uint32Ptr', data(1));
+ remote_pMinor = libpointer('uint32Ptr', data(2));
+ remote_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]);
+ local_pMajor = libpointer('uint32Ptr', data(1));
+ local_pMinor = libpointer('uint32Ptr', data(2));
+ local_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]);
+
+ % get remote libiio version
+ calllib(obj.libname, 'iio_context_get_version', obj.iio_ctx, remote_pMajor, remote_pMinor, remote_pGitTag);
+ % extract git hash without trailing null char
+ remote_githash = remote_pGitTag.Value(1:7);
+ remote_version_str = sprintf('Remote libiio version: %d.%d, (git-%s)', remote_pMajor.Value, remote_pMinor.Value, remote_githash);
+ msg_log = [msg_log sprintf('%s: %s\n', class(obj), remote_version_str)];
+
+ % get local libiio version
+ calllib(obj.libname, 'iio_library_get_version', local_pMajor, local_pMinor, local_pGitTag);
+ local_githash = local_pGitTag.Value(1:7);
+ local_version_str = sprintf('Local libiio version: %d.%d, (git-%s)', local_pMajor.Value, local_pMinor.Value, local_githash);
+ msg_log = [msg_log sprintf('%s: %s\n', class(obj), local_version_str)];
+
+ if(remote_pMajor.Value < local_pMajor.Value)
+ err_msg = ['The libiio version running on the device is outdated! ' ...
+ 'Run the adi_update_tools.sh script to get libiio up to date.'];
+ return;
+ elseif(remote_pMajor.Value > local_pMajor.Value)
+ err_msg = ['The libiio version on the local host is outdated! ' ...
+ 'On Windows, reinstall the dll using the latest installer ' ...
+ 'from the Analog Devices wiki.'];
+ return;
+ end
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Detect if the specified device is present in the system
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initDevice(obj, dev_name)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Store the device name
+ obj.dev_name = dev_name;
+
+ % Get the number of devices
+ nb_devices = calllib(obj.libname, 'iio_context_get_devices_count', obj.iio_ctx);
+
+ % If no devices are present return with error
+ if(nb_devices == 0)
+ err_msg = 'No devices were detected in the system!';
+ return;
+ end
+ msg_log = [msg_log sprintf('%s: Found %d devices in the system\n', class(obj), nb_devices)];
+
+ % Detect if the targeted device is installed
+ dev_found = 0;
+ for i = 0 : nb_devices - 1
+ dev = calllib(obj.libname, 'iio_context_get_device', obj.iio_ctx, i);
+ name = calllib(obj.libname, 'iio_device_get_name', dev);
+ if(strcmp(name, dev_name))
+ obj.iio_dev = dev;
+ dev_found = 1;
+ break;
+ end
+ clear dev;
+ end
+
+ % Check if the target device was detected
+ if(dev_found == 0)
+ err_msg = 'Could not find target configuration device!';
+ return;
+ end
+
+ msg_log = [msg_log sprintf('%s: %s was found in the system\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the output data channels
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initOutputDataChannels(obj, ch_no, ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the number of channels and size
+ obj.data_ch_no = ch_no;
+ obj.data_ch_size = ch_size;
+
+ % Get the number of channels that the device has
+ nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ if(nb_channels == 0)
+ err_msg = 'The selected device does not have any channels!';
+ return;
+ end
+
+ % Enable the data channels
+ if(ch_no ~= 0)
+ % Check if the device has output channels. The
+ % logic here assumes that a device can have
+ % only input or only output channels
+ obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0);
+ is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1});
+ if(is_output == 0)
+ err_msg = 'The selected device does not have output channels!';
+ return;
+ end
+ % Enable all the channels
+ for j = 0 : nb_channels - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1});
+ is_scan_element = calllib(obj.libname, 'iio_channel_is_scan_element', obj.iio_channel{j+1});
+ if(is_scan_element == 1)
+ obj.iio_scan_elm_no = obj.iio_scan_elm_no + 1;
+ end
+ end
+ msg_log = [msg_log sprintf('%s: Found %d output channels for the device %s\n', class(obj), obj.iio_scan_elm_no, obj.dev_name)];
+
+ % Check if the number of channels in the device
+ % is greater or equal to the system object
+ % input channels
+ if(obj.iio_scan_elm_no < ch_no)
+ obj.iio_channel = {};
+ err_msg = 'The selected device does not have enough output channels!';
+ return;
+ end
+
+ % Enable the DAC buffer output
+ obj.if_initialized = 1;
+ ret = writeAttributeString(obj, 'altvoltage0*raw', '0');
+ obj.if_initialized = 0;
+ if(ret < 0)
+ obj.iio_channel = {};
+ err_msg = 'Could not enable the DAC buffer output!';
+ return;
+ end
+
+ % Create the IIO buffer used to write data
+ obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,...
+ obj.data_ch_size, 1);
+ end
+
+ msg_log = [msg_log sprintf('%s: %s output data channels successfully initialized\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the input data channels
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initInputDataChannels(obj, ch_no, ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the number of channels and size
+ obj.data_ch_no = ch_no;
+ obj.data_ch_size = ch_size;
+
+ % Get the number of channels that the device has
+ nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ if(nb_channels == 0)
+ err_msg = 'The selected device does not have any channels!';
+ return;
+ end
+
+ % Enable the system object output channels
+ if(ch_no ~= 0)
+ % Check if the device has input channels. The
+ % logic here assumes that a device can have
+ % only input or only output channels
+ obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0);
+ is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1});
+ if(is_output == 1)
+ err_msg = 'The selected device does not have input channels!';
+ return;
+ end
+ msg_log = [msg_log sprintf('%s: Found %d input channels for the device %s\n', class(obj), nb_channels, obj.dev_name)];
+
+ % Check if the number of channels in the device
+ % is greater or equal to the system object
+ % output channels
+ if(nb_channels < ch_no)
+ obj.iio_channel = {};
+ err_msg = 'The selected device does not have enough input channels!';
+ return;
+ end
+
+ % Enable the channels
+ for j = 0 : ch_no - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1});
+ end
+ for j = ch_no : nb_channels - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1});
+ end
+ % Create the IIO buffer used to read data
+ obj.iio_buf_size = obj.data_ch_size * obj.data_ch_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev, obj.iio_buf_size, 0);
+ end
+
+ msg_log = [msg_log sprintf('%s: %s input data channels successfully initialized\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ end
+
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Public methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Constructor
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function obj = libiio_if()
+ % Constructor
+ obj.if_initialized = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Destructor
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function delete(obj)
+ % Release any resources used by the system object.
+ if((obj.if_initialized == 1) && libisloaded(obj.libname))
+ if(~isempty(obj.iio_buffer))
+ calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer);
+ end
+ if(~isempty(obj.iio_ctx))
+ calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx);
+ end
+ obj.iio_buffer = {};
+ obj.iio_channel = {};
+ obj.iio_dev = {};
+ obj.iio_ctx = {};
+ instCnt = libiio_if.modInstanceCnt(-1);
+ if(instCnt == 0)
+ unloadlibrary(obj.libname);
+ end
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the libiio interface
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = init(obj, ip_address, ...
+ dev_name, dev_type, ...
+ data_ch_no, data_ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the device type
+ obj.dev_type = dev_type;
+
+ % Set the initialization status to fail
+ obj.if_initialized = 0;
+
+ % Load the libiio library
+ if(~libisloaded(obj.libname))
+ try
+ % ignore unknown type warnings due to header parsing limitations
+ warnState = warning('off', 'MATLAB:loadlibrary:TypeNotFound');
+ cleanupObj = onCleanup(@()warning(warnState));
+ [notfound, warnings] = loadlibrary(obj.libname, obj.hname, 'addheader', 'iio.h');
+ cleanupObj = []; % restore the warning state
+ catch exception
+ err_msg = exception.message;
+ return;
+ end
+ end
+
+ if(~libisloaded(obj.libname))
+ err_msg = 'Could not load the libiio library!';
+ return;
+ end
+
+ % Create the network context
+ [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address);
+ if(ret < 0)
+ return;
+ end
+
+ % Check the software versions
+ [ret, err_msg, msg_log_new] = checkVersions(obj);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+
+ % Initialize the device
+ [ret, err_msg, msg_log_new] = initDevice(obj, dev_name);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+
+ % Initialize the output data channels
+ if(strcmp(dev_type, 'OUT'))
+ [ret, err_msg, msg_log_new] = initOutputDataChannels(obj, data_ch_no, data_ch_size);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+ end
+
+ % Initialize the input data channels
+ if(strcmp(dev_type, 'IN'))
+ [ret, err_msg, msg_log_new] = initInputDataChannels(obj, data_ch_no, data_ch_size);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+ end
+
+ % Set the initialization status to success
+ obj.if_initialized = 1;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Implement the data capture flow
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, data] = readData(obj)
+ % Initialize the return values
+ ret = -1;
+ data = cell(1, obj.data_ch_no);
+ for i = 1 : obj.data_ch_no
+ data{i} = zeros(obj.data_ch_size, 1);
+ end
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if the device type is output
+ if(~strcmp(obj.dev_type, 'IN'))
+ return;
+ end
+
+ % Read the data
+ calllib(obj.libname, 'iio_buffer_refill', obj.iio_buffer);
+ buffer = calllib(obj.libname, 'iio_buffer_first', obj.iio_buffer, obj.iio_channel{1});
+ setdatatype(buffer, 'int16Ptr', obj.iio_buf_size);
+ for i = 1 : obj.data_ch_no
+ data{i} = double(buffer.Value(i:obj.data_ch_no:end));
+ end
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Implement the data transmit flow
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeData(obj, data)
+ % Initialize the return values
+ ret = -1;
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if the device type is input
+ if(~strcmp(obj.dev_type, 'OUT'))
+ return;
+ end
+
+ % Destroy the buffer
+ calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer);
+ obj.iio_buffer = {};
+
+ % Enable the DAC buffer output
+ ret = writeAttributeString(obj, 'altvoltage0*raw', '0');
+ if(ret < 0)
+ obj.iio_channel = {};
+ err_msg = 'Could not enable the DAC buffer output!';
+ return;
+ end
+
+ % Create the IIO buffer used to write data
+ obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,...
+ obj.data_ch_size, 1);
+
+ % Transmit the data
+ buffer = calllib(obj.libname, 'iio_buffer_start', obj.iio_buffer);
+ setdatatype(buffer, 'int16Ptr', obj.iio_buf_size);
+ for i = 1 : obj.data_ch_no
+ buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = int16(data{i});
+ end
+ for i = obj.data_ch_no + 1 : obj.iio_scan_elm_no
+ buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = 0;
+ end
+ calllib(obj.libname, 'iio_buffer_push', obj.iio_buffer);
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Find an attribute based on the name. The name can contain wildcard '*' characters
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, ch, attr] = findAttribute(obj, attr_name)
+ % Initialize the return values
+ ret = -1;
+ ch = 0;
+ attr = '';
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if this is a device attribute
+ name = calllib(obj.libname, 'iio_device_find_attr', obj.iio_dev, attr_name);
+ if(~isempty(name))
+ ret = 0;
+ return;
+ end
+
+ % This is a channel attribute, search for the corresponding channel
+ chn_no = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ for k = 0 : chn_no - 1
+ ch = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, k);
+ attr_no = calllib(obj.libname, 'iio_channel_get_attrs_count', ch);
+ attr_found = 0;
+ for l = 0 : attr_no - 1
+ attr = calllib(obj.libname, 'iio_channel_get_attr', ch, l);
+ name = calllib(obj.libname, 'iio_channel_attr_get_filename', ch, attr);
+ % The attribute to find can contain wildcard '*' characters,
+ % search for all the substrings in the attribute name
+ str_find = strsplit(attr_name, '*');
+ str_find = str_find(find(~strcmp(str_find, '')));
+ has_wildcard = ~isempty(strfind(attr_name, '*'));
+ attr_found = 1;
+ for i = 1 : length(str_find)
+ if(has_wildcard == 0)
+ ret = strcmp(name, str_find{i});
+ if(ret == 0)
+ ret = [];
+ end
+ else
+ ret = strfind(name, str_find{i});
+ end
+ if(isempty(ret))
+ attr_found = 0;
+ break;
+ end
+ end
+ if(attr_found == 1)
+ break;
+ end
+ clear attr;
+ end
+ % Check if the attribute was found
+ if(attr_found == 0)
+ clear ch;
+ else
+ ret = 1;
+ break;
+ end
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Read an attribute as a double value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, val] = readAttributeDouble(obj, attr_name)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ val = 0;
+ return;
+ end
+
+ % Create a double pointer to be used for data read
+ data = zeros(1, 10);
+ pData = libpointer('doublePtr', data(1));
+
+ % Read the attribute value
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_read_double', ch, attr, pData);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_read_double', obj.iio_dev, attr_name, pData);
+ end
+ val = pData.Value;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Read an attribute as a string value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, val] = readAttributeString(obj, attr_name)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ val = '';
+ return;
+ end
+
+ % Create a pointer to be used for data read
+ data = char(ones(1, 512));
+ pData = libpointer('stringPtr', data);
+
+ % Read the attribute value
+ if(ret > 0)
+ [~, ~, ~, val] = calllib(obj.libname, 'iio_channel_attr_read', ch, attr, pData, 512);
+ clear ch;
+ clear attr;
+ else
+ [~, ~, ~, val] = calllib(obj.libname, 'iio_device_attr_read', obj.iio_dev, attr_name, pData, 512);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Write a string double value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeAttributeDouble(obj, attr_name, val)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ return;
+ end
+
+ % Write the attribute
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_write_double', ch, attr, val);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_write_double', obj.iio_dev, attr_name, val);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Write a string attribute value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeAttributeString(obj, attr_name, str)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ return;
+ end
+
+ % Write the attribute
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_write', ch, attr, str);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_write', obj.iio_dev, attr_name, str);
+ end
+ end
+ end
+end
diff --git a/bindings/matlab/libiio_if_daq2.m b/bindings/matlab/libiio_if_daq2.m
new file mode 100644
index 0000000..0ac5708
--- /dev/null
+++ b/bindings/matlab/libiio_if_daq2.m
@@ -0,0 +1,701 @@
+% Copyright 2014(c) Analog Devices, Inc.
+%
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without modification,
+% are permitted provided that the following conditions are met:
+% - Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+% - Redistributions in binary form must reproduce the above copyright
+% notice, this list of conditions and the following disclaimer in
+% the documentation and/or other materials provided with the
+% distribution.
+% - Neither the name of Analog Devices, Inc. nor the names of its
+% contributors may be used to endorse or promote products derived
+% from this software without specific prior written permission.
+% - The use of this software may or may not infringe the patent rights
+% of one or more patent holders. This license does not release you
+% from the requirement that you obtain separate licenses from these
+% patent holders to use this software.
+% - Use of the software either in source or binary form or filter designs
+% resulting from the use of this software, must be connected to, run
+% on or loaded to an Analog Devices Inc. component.
+%
+% THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+% INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+% PARTICULAR PURPOSE ARE DISCLAIMED.
+%
+% IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
+% RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+classdef libiio_if < handle
+ % libiio_if Interface object for for IIO devices
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Protected properties
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ properties (Access = protected)
+ libname = 'libiio';
+ hname = 'iio.h';
+ dev_name = '';
+ data_ch_no = 0;
+ data_ch_size = 0;
+ dev_type = '';
+ iio_ctx = {};
+ iio_dev = {};
+ iio_buffer = {};
+ iio_channel = {};
+ iio_buf_size = 8192;
+ iio_scan_elm_no = 0;
+ if_initialized = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Static private methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods (Static, Access = private)
+ function out = modInstanceCnt(val)
+ % Manages the number of object instances to handle proper DLL unloading
+ persistent instance_cnt;
+ if isempty(instance_cnt)
+ instance_cnt = 0;
+ end
+ instance_cnt = instance_cnt + val;
+ out = instance_cnt;
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Protected methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods (Access = protected)
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Creates the network context
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Create the network context
+ obj.iio_ctx = calllib(obj.libname, 'iio_create_network_context', ip_address);
+
+ % Check if the network context is valid
+ if (isNull(obj.iio_ctx))
+ obj.iio_ctx = {};
+ err_msg = 'Could not connect to the IIO server!';
+ return;
+ end
+
+ % Increase the object's instance count
+ libiio_if.modInstanceCnt(1);
+ msg_log = [msg_log sprintf('%s: Connected to IP %s\n', class(obj), ip_address)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Releases the network context and unload the libiio library
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function releaseContext(obj)
+ calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx);
+ obj.iio_ctx = {};
+ instCnt = libiio_if.modInstanceCnt(-1);
+ if(instCnt == 0)
+ unloadlibrary(obj.libname);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Checks the compatibility of the different software modules.
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = checkVersions(obj)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Create a set of pointers to read the iiod and dll versions
+ data = zeros(1, 10);
+ remote_pMajor = libpointer('uint32Ptr', data(1));
+ remote_pMinor = libpointer('uint32Ptr', data(2));
+ remote_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]);
+ local_pMajor = libpointer('uint32Ptr', data(1));
+ local_pMinor = libpointer('uint32Ptr', data(2));
+ local_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]);
+
+ % get remote libiio version
+ calllib(obj.libname, 'iio_context_get_version', obj.iio_ctx, remote_pMajor, remote_pMinor, remote_pGitTag);
+ % extract git hash without trailing null char
+ remote_githash = remote_pGitTag.Value(1:7);
+ remote_version_str = sprintf('Remote libiio version: %d.%d, (git-%s)', remote_pMajor.Value, remote_pMinor.Value, remote_githash);
+ msg_log = [msg_log sprintf('%s: %s\n', class(obj), remote_version_str)];
+
+ % get local libiio version
+ calllib(obj.libname, 'iio_library_get_version', local_pMajor, local_pMinor, local_pGitTag);
+ local_githash = local_pGitTag.Value(1:7);
+ local_version_str = sprintf('Local libiio version: %d.%d, (git-%s)', local_pMajor.Value, local_pMinor.Value, local_githash);
+ msg_log = [msg_log sprintf('%s: %s\n', class(obj), local_version_str)];
+
+ if(remote_pMajor.Value < local_pMajor.Value)
+ err_msg = ['The libiio version running on the device is outdated! ' ...
+ 'Run the adi_update_tools.sh script to get libiio up to date.'];
+ return;
+ elseif(remote_pMajor.Value > local_pMajor.Value)
+ err_msg = ['The libiio version on the local host is outdated! ' ...
+ 'On Windows, reinstall the dll using the latest installer ' ...
+ 'from the Analog Devices wiki.'];
+ return;
+ end
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Detect if the specified device is present in the system
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initDevice(obj, dev_name)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Store the device name
+ obj.dev_name = dev_name;
+
+ % Get the number of devices
+ nb_devices = calllib(obj.libname, 'iio_context_get_devices_count', obj.iio_ctx);
+
+ % If no devices are present return with error
+ if(nb_devices == 0)
+ err_msg = 'No devices were detected in the system!';
+ return;
+ end
+ msg_log = [msg_log sprintf('%s: Found %d devices in the system\n', class(obj), nb_devices)];
+
+ % Detect if the targeted device is installed
+ dev_found = 0;
+ for i = 0 : nb_devices - 1
+ dev = calllib(obj.libname, 'iio_context_get_device', obj.iio_ctx, i);
+ name = calllib(obj.libname, 'iio_device_get_name', dev);
+ if(strcmp(name, dev_name))
+ obj.iio_dev = dev;
+ dev_found = 1;
+ break;
+ end
+ clear dev;
+ end
+
+ % Check if the target device was detected
+ if(dev_found == 0)
+ err_msg = 'Could not find target configuration device!';
+ return;
+ end
+
+ msg_log = [msg_log sprintf('%s: %s was found in the system\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the output data channels
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initOutputDataChannels(obj, ch_no, ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the number of channels and size
+ obj.data_ch_no = ch_no;
+ obj.data_ch_size = ch_size;
+
+ % Get the number of channels that the device has
+ nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ if(nb_channels == 0)
+ err_msg = 'The selected device does not have any channels!';
+ return;
+ end
+
+ % Enable the data channels
+ if(ch_no ~= 0)
+ % Check if the device has output channels. The
+ % logic here assumes that a device can have
+ % only input or only output channels
+ obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0);
+ is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1});
+ if(is_output == 0)
+ err_msg = 'The selected device does not have output channels!';
+ return;
+ end
+ % Enable all the channels
+ for j = 0 : nb_channels - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ if(j < ch_no)
+ calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1});
+ is_scan_element = calllib(obj.libname, 'iio_channel_is_scan_element', obj.iio_channel{j+1});
+ if(is_scan_element == 1)
+ obj.iio_scan_elm_no = obj.iio_scan_elm_no + 1;
+ end
+ else
+ calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1});
+ end
+ end
+ msg_log = [msg_log sprintf('%s: Found %d output channels for the device %s\n', class(obj), obj.iio_scan_elm_no, obj.dev_name)];
+
+ % Check if the number of channels in the device
+ % is greater or equal to the system object
+ % input channels
+ if(obj.iio_scan_elm_no < ch_no)
+ obj.iio_channel = {};
+ err_msg = 'The selected device does not have enough output channels!';
+ return;
+ end
+
+ % Enable the DAC buffer output
+ obj.if_initialized = 1;
+ ret = writeAttributeString(obj, 'altvoltage0*raw', '0');
+ obj.if_initialized = 0;
+ if(ret < 0)
+ obj.iio_channel = {};
+ err_msg = 'Could not enable the DAC buffer output!';
+ return;
+ end
+
+ % Create the IIO buffer used to write data
+ obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,...
+ obj.data_ch_size, 1);
+ end
+
+ msg_log = [msg_log sprintf('%s: %s output data channels successfully initialized\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the input data channels
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = initInputDataChannels(obj, ch_no, ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the number of channels and size
+ obj.data_ch_no = ch_no;
+ obj.data_ch_size = ch_size;
+
+ % Get the number of channels that the device has
+ nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ if(nb_channels == 0)
+ err_msg = 'The selected device does not have any channels!';
+ return;
+ end
+
+ % Enable the system object output channels
+ if(ch_no ~= 0)
+ % Check if the device has input channels. The
+ % logic here assumes that a device can have
+ % only input or only output channels
+ obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0);
+ is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1});
+ if(is_output == 1)
+ err_msg = 'The selected device does not have input channels!';
+ return;
+ end
+ msg_log = [msg_log sprintf('%s: Found %d input channels for the device %s\n', class(obj), nb_channels, obj.dev_name)];
+
+ % Check if the number of channels in the device
+ % is greater or equal to the system object
+ % output channels
+ if(nb_channels < ch_no)
+ obj.iio_channel = {};
+ err_msg = 'The selected device does not have enough input channels!';
+ return;
+ end
+
+ % Enable the channels
+ for j = 0 : ch_no - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1});
+ end
+ for j = ch_no : nb_channels - 1
+ obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j);
+ calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1});
+ end
+ % Create the IIO buffer used to read data
+ obj.iio_buf_size = obj.data_ch_size * obj.data_ch_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev, obj.iio_buf_size, 0);
+ end
+
+ msg_log = [msg_log sprintf('%s: %s input data channels successfully initialized\n', class(obj), obj.dev_name)];
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ end
+
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Public methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ methods
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Constructor
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function obj = libiio_if()
+ % Constructor
+ obj.if_initialized = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Destructor
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function delete(obj)
+ % Release any resources used by the system object.
+ if((obj.if_initialized == 1) && libisloaded(obj.libname))
+ if(~isempty(obj.iio_buffer))
+ calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer);
+ end
+ if(~isempty(obj.iio_ctx))
+ calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx);
+ end
+ obj.iio_buffer = {};
+ obj.iio_channel = {};
+ obj.iio_dev = {};
+ obj.iio_ctx = {};
+ instCnt = libiio_if.modInstanceCnt(-1);
+ if(instCnt == 0)
+ unloadlibrary(obj.libname);
+ end
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Initializes the libiio interface
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, err_msg, msg_log] = init(obj, ip_address, ...
+ dev_name, dev_type, ...
+ data_ch_no, data_ch_size)
+ % Initialize the return values
+ ret = -1;
+ err_msg = '';
+ msg_log = [];
+
+ % Save the device type
+ obj.dev_type = dev_type;
+
+ % Set the initialization status to fail
+ obj.if_initialized = 0;
+
+ % Load the libiio library
+ if(~libisloaded(obj.libname))
+ try
+ [notfound, warnings] = loadlibrary(obj.libname, obj.hname);
+ catch exception
+ err_msg = exception.message;
+ return;
+ end
+ end
+
+ if(~libisloaded(obj.libname))
+ err_msg = 'Could not load the libiio library!';
+ return;
+ end
+
+ % Create the network context
+ [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address);
+ if(ret < 0)
+ return;
+ end
+
+ % Check the software versions
+ [ret, err_msg, msg_log_new] = checkVersions(obj);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+
+ % Initialize the device
+ [ret, err_msg, msg_log_new] = initDevice(obj, dev_name);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+
+ % Initialize the output data channels
+ if(strcmp(dev_type, 'OUT'))
+ [ret, err_msg, msg_log_new] = initOutputDataChannels(obj, data_ch_no, data_ch_size);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+ end
+
+ % Initialize the input data channels
+ if(strcmp(dev_type, 'IN'))
+ [ret, err_msg, msg_log_new] = initInputDataChannels(obj, data_ch_no, data_ch_size);
+ msg_log = [msg_log msg_log_new];
+ if(ret < 0)
+ releaseContext(obj);
+ return;
+ end
+ end
+
+ % Set the initialization status to success
+ obj.if_initialized = 1;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Implement the data capture flow
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, data] = readData(obj)
+ % Initialize the return values
+ ret = -1;
+ data = cell(1, obj.data_ch_no);
+ for i = 1 : obj.data_ch_no
+ data{i} = zeros(obj.data_ch_size, 1);
+ end
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if the device type is output
+ if(~strcmp(obj.dev_type, 'IN'))
+ return;
+ end
+
+ % Read the data
+ calllib(obj.libname, 'iio_buffer_refill', obj.iio_buffer);
+ buffer = calllib(obj.libname, 'iio_buffer_first', obj.iio_buffer, obj.iio_channel{1});
+ setdatatype(buffer, 'int16Ptr', obj.iio_buf_size);
+ for i = 1 : obj.data_ch_no
+ data{i} = double(buffer.Value(i:obj.data_ch_no:end));
+ end
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Implement the data transmit flow
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeData(obj, data)
+ % Initialize the return values
+ ret = -1;
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if the device type is input
+ if(~strcmp(obj.dev_type, 'OUT'))
+ return;
+ end
+
+ % Destroy the buffer
+ calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer);
+ obj.iio_buffer = {};
+
+ % Enable the DAC buffer output
+ ret = writeAttributeString(obj, 'altvoltage0*raw', '0');
+ if(ret < 0)
+ obj.iio_channel = {};
+ err_msg = 'Could not enable the DAC buffer output!';
+ return;
+ end
+
+ % Create the IIO buffer used to write data
+ obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no;
+ obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,...
+ obj.data_ch_size, 1);
+
+ % Transmit the data
+ buffer = calllib(obj.libname, 'iio_buffer_start', obj.iio_buffer);
+ setdatatype(buffer, 'int16Ptr', obj.iio_buf_size);
+ for i = 1 : obj.data_ch_no
+ buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = int16(data{i});
+ end
+ for i = obj.data_ch_no + 1 : obj.iio_scan_elm_no
+ buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = 0;
+ end
+ calllib(obj.libname, 'iio_buffer_push', obj.iio_buffer);
+
+ % Set the return code to success
+ ret = 0;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Find an attribute based on the name. The name can contain wildcard '*' characters
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, ch, attr] = findAttribute(obj, attr_name)
+ % Initialize the return values
+ ret = -1;
+ ch = 0;
+ attr = '';
+
+ % Check if the interface is initialized
+ if(obj.if_initialized == 0)
+ return;
+ end
+
+ % Check if this is a device attribute
+ name = calllib(obj.libname, 'iio_device_find_attr', obj.iio_dev, attr_name);
+ if(~isempty(name))
+ ret = 0;
+ return;
+ end
+
+ % This is a channel attribute, search for the corresponding channel
+ chn_no = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev);
+ for k = 0 : chn_no - 1
+ ch = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, k);
+ attr_no = calllib(obj.libname, 'iio_channel_get_attrs_count', ch);
+ attr_found = 0;
+ for l = 0 : attr_no - 1
+ attr = calllib(obj.libname, 'iio_channel_get_attr', ch, l);
+ name = calllib(obj.libname, 'iio_channel_attr_get_filename', ch, attr);
+ % The attribute to find can contain wildcard '*' characters,
+ % search for all the substrings in the attribute name
+ str_find = strsplit(attr_name, '*');
+ str_find = str_find(find(~strcmp(str_find, '')));
+ has_wildcard = ~isempty(strfind(attr_name, '*'));
+ attr_found = 1;
+ for i = 1 : length(str_find)
+ if(has_wildcard == 0)
+ ret = strcmp(name, str_find{i});
+ if(ret == 0)
+ ret = [];
+ end
+ else
+ ret = strfind(name, str_find{i});
+ end
+ if(isempty(ret))
+ attr_found = 0;
+ break;
+ end
+ end
+ if(attr_found == 1)
+ break;
+ end
+ clear attr;
+ end
+ % Check if the attribute was found
+ if(attr_found == 0)
+ clear ch;
+ else
+ ret = 1;
+ break;
+ end
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Read an attribute as a double value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, val] = readAttributeDouble(obj, attr_name)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ val = 0;
+ return;
+ end
+
+ % Create a double pointer to be used for data read
+ data = zeros(1, 10);
+ pData = libpointer('doublePtr', data(1));
+
+ % Read the attribute value
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_read_double', ch, attr, pData);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_read_double', obj.iio_dev, attr_name, pData);
+ end
+ val = pData.Value;
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Read an attribute as a string value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function [ret, val] = readAttributeString(obj, attr_name)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ val = '';
+ return;
+ end
+
+ % Create a pointer to be used for data read
+ data = char(ones(1, 512));
+ pData = libpointer('stringPtr', data);
+
+ % Read the attribute value
+ if(ret > 0)
+ [~, ~, ~, val] = calllib(obj.libname, 'iio_channel_attr_read', ch, attr, pData, 512);
+ clear ch;
+ clear attr;
+ else
+ [~, ~, ~, val] = calllib(obj.libname, 'iio_device_attr_read', obj.iio_dev, attr_name, pData, 512);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Write a string double value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeAttributeDouble(obj, attr_name, val)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ return;
+ end
+
+ % Write the attribute
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_write_double', ch, attr, val);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_write_double', obj.iio_dev, attr_name, val);
+ end
+ end
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Write a string attribute value
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ function ret = writeAttributeString(obj, attr_name, str)
+ % Find the attribute
+ [ret, ch, attr] = findAttribute(obj, attr_name);
+ if(ret < 0)
+ return;
+ end
+
+ % Write the attribute
+ if(ret > 0)
+ calllib(obj.libname, 'iio_channel_attr_write', ch, attr, str);
+ clear ch;
+ clear attr;
+ else
+ calllib(obj.libname, 'iio_device_attr_write', obj.iio_dev, attr_name, str);
+ end
+ end
+ end
+end
diff --git a/bindings/python/.gitignore b/bindings/python/.gitignore
new file mode 100644
index 0000000..cbf6e08
--- /dev/null
+++ b/bindings/python/.gitignore
@@ -0,0 +1,3 @@
+setup.py
+*.pyc
+__pycache__/
diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt
new file mode 100644
index 0000000..4ba6aca
--- /dev/null
+++ b/bindings/python/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.7)
+project(libiio-py NONE)
+
+include(FindPythonInterp)
+
+if (PYTHONINTERP_FOUND)
+ option(PYTHON_BINDINGS "Install Python bindings" ON)
+
+ if (PYTHON_BINDINGS)
+ set(SETUP_PY_IN ${CMAKE_CURRENT_SOURCE_DIR}/setup.py.cmakein)
+ set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
+
+ configure_file(${SETUP_PY_IN} ${SETUP_PY})
+
+ add_custom_target(libiio-py ALL DEPENDS ${SETUP_PY} COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} --quiet build)
+
+ if(NOT SKIP_INSTALL_ALL)
+ install(CODE "execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install --root=\$ENV{DESTDIR}/ --prefix=${CMAKE_INSTALL_PREFIX})")
+ endif()
+ endif()
+endif()
diff --git a/bindings/python/examples/iio_info.py b/bindings/python/examples/iio_info.py
new file mode 100755
index 0000000..e29b297
--- /dev/null
+++ b/bindings/python/examples/iio_info.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2015 Analog Devices, Inc.
+# Author: Paul Cercueil <paul.cercueil@analog.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+import iio
+from sys import argv
+
+def main():
+ print('Library version: %u.%u (git tag: %s)' % iio.version)
+
+ if len(argv) == 3 and argv[1] == '--uri':
+ uri = argv[2]
+ else:
+ contexts = iio.scan_contexts()
+ if len(contexts) > 1:
+ print('Multiple contexts found. Please select one using --uri:')
+ for index, each in enumerate(contexts):
+ print('\t%d: %s [%s]' % (index, contexts[each], each))
+ return
+
+ uri = next(iter(contexts), None)
+
+ ctx = iio.Context(uri)
+
+ if uri is not None:
+ print('Using auto-detected IIO context at URI \"%s\"' % uri)
+
+ print('IIO context created: ' + ctx.name)
+ print('Backend version: %u.%u (git tag: %s)' % ctx.version)
+ print('Backend description string: ' + ctx.description)
+
+ if len(ctx.attrs) > 0:
+ print('IIO context has %u attributes:' % len(ctx.attrs))
+ for attr, value in ctx.attrs.items():
+ print('\t' + attr + ': ' + value)
+
+ print('IIO context has %u devices:' % len(ctx.devices))
+
+ for dev in ctx.devices:
+ print('\t' + dev.id + ': ' + dev.name)
+
+ if dev is iio.Trigger:
+ print('Found trigger! Rate: %u Hz' % dev.frequency)
+
+ print('\t\t%u channels found:' % len(dev.channels))
+
+ for chn in dev.channels:
+ print('\t\t\t%s: %s (%s)' % (chn.id, chn.name or "", 'output' if chn.output else 'input'))
+
+ if len(chn.attrs) != 0:
+ print('\t\t\t%u channel-specific attributes found:' % len(chn.attrs))
+
+ for attr in chn.attrs:
+ try:
+ print('\t\t\t\t' + attr + ', value: ' + chn.attrs[attr].value)
+ except OSError as e:
+ print('Unable to read ' + attr + ': ' + e.strerror)
+
+ if len(dev.attrs) != 0:
+ print('\t\t%u device-specific attributes found:' % len(dev.attrs))
+
+ for attr in dev.attrs:
+ try:
+ print('\t\t\t' + attr + ', value: ' + dev.attrs[attr].value)
+ except OSError as e:
+ print('Unable to read ' + attr + ': ' + e.strerror)
+
+ if len(dev.debug_attrs) != 0:
+ print('\t\t%u debug attributes found:' % len(dev.debug_attrs))
+
+ for attr in dev.debug_attrs:
+ try:
+ print('\t\t\t' + attr + ', value: ' + dev.debug_attrs[attr].value)
+ except OSError as e:
+ print('Unable to read ' + attr + ': ' + e.strerror)
+
+if __name__ == '__main__':
+ main()
diff --git a/bindings/python/iio.py b/bindings/python/iio.py
new file mode 100644
index 0000000..3ffe2a2
--- /dev/null
+++ b/bindings/python/iio.py
@@ -0,0 +1,864 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2014 Analog Devices, Inc.
+# Author: Paul Cercueil <paul.cercueil@analog.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+from ctypes import Structure, c_char_p, c_uint, c_int, c_size_t, \
+ c_ssize_t, c_char, c_void_p, c_bool, create_string_buffer, \
+ POINTER as _POINTER, CDLL as _cdll, memmove as _memmove, byref as _byref
+from os import strerror as _strerror
+from platform import system as _system
+import weakref
+
+if 'Windows' in _system():
+ from ctypes import get_last_error
+else:
+ from ctypes import get_errno
+
+def _checkNull(result, func, arguments):
+ if result:
+ return result
+ else:
+ err = get_last_error() if 'Windows' in _system() else get_errno()
+ raise OSError(err, _strerror(err))
+
+def _checkNegative(result, func, arguments):
+ if result >= 0:
+ return result
+ else:
+ raise OSError(-result, _strerror(-result))
+
+class _ScanContext(Structure):
+ pass
+class _ContextInfo(Structure):
+ pass
+class _Context(Structure):
+ pass
+class _Device(Structure):
+ pass
+class _Channel(Structure):
+ pass
+class _Buffer(Structure):
+ pass
+
+_ScanContextPtr = _POINTER(_ScanContext)
+_ContextInfoPtr = _POINTER(_ContextInfo)
+_ContextPtr = _POINTER(_Context)
+_DevicePtr = _POINTER(_Device)
+_ChannelPtr = _POINTER(_Channel)
+_BufferPtr = _POINTER(_Buffer)
+
+_lib = _cdll('libiio.dll' if 'Windows' in _system() else 'libiio.so.0',
+ use_errno = True, use_last_error = True)
+
+_get_backends_count = _lib.iio_get_backends_count
+_get_backends_count.restype = c_uint
+
+_get_backend = _lib.iio_get_backend
+_get_backend.argtypes = (c_uint, )
+_get_backend.restype = c_char_p
+_get_backend.errcheck = _checkNull
+
+_create_scan_context = _lib.iio_create_scan_context
+_create_scan_context.argtypes = (c_char_p, c_uint)
+_create_scan_context.restype = _ScanContextPtr
+_create_scan_context.errcheck = _checkNull
+
+_destroy_scan_context = _lib.iio_scan_context_destroy
+_destroy_scan_context.argtypes = (_ScanContextPtr, )
+
+_get_context_info_list = _lib.iio_scan_context_get_info_list
+_get_context_info_list.argtypes = (_ScanContextPtr, _POINTER(_POINTER(_ContextInfoPtr)))
+_get_context_info_list.restype = c_ssize_t
+_get_context_info_list.errcheck = _checkNegative
+
+_context_info_list_free = _lib.iio_context_info_list_free
+_context_info_list_free.argtypes = (_POINTER(_ContextInfoPtr), )
+
+_context_info_get_description = _lib.iio_context_info_get_description
+_context_info_get_description.argtypes = (_ContextInfoPtr, )
+_context_info_get_description.restype = c_char_p
+
+_context_info_get_uri = _lib.iio_context_info_get_uri
+_context_info_get_uri.argtypes = (_ContextInfoPtr, )
+_context_info_get_uri.restype = c_char_p
+
+_new_local = _lib.iio_create_local_context
+_new_local.restype = _ContextPtr
+_new_local.errcheck = _checkNull
+
+_new_xml = _lib.iio_create_xml_context
+_new_xml.restype = _ContextPtr
+_new_xml.argtypes = (c_char_p, )
+_new_xml.errcheck = _checkNull
+
+_new_network = _lib.iio_create_network_context
+_new_network.restype = _ContextPtr
+_new_network.argtypes = (c_char_p, )
+_new_network.errcheck = _checkNull
+
+_new_default = _lib.iio_create_default_context
+_new_default.restype = _ContextPtr
+_new_default.errcheck = _checkNull
+
+_new_uri = _lib.iio_create_context_from_uri
+_new_uri.restype = _ContextPtr
+_new_uri.errcheck = _checkNull
+
+_destroy = _lib.iio_context_destroy
+_destroy.argtypes = (_ContextPtr, )
+
+_get_name = _lib.iio_context_get_name
+_get_name.restype = c_char_p
+_get_name.argtypes = (_ContextPtr, )
+_get_name.errcheck = _checkNull
+
+_get_description = _lib.iio_context_get_description
+_get_description.restype = c_char_p
+_get_description.argtypes = (_ContextPtr, )
+
+_get_xml = _lib.iio_context_get_xml
+_get_xml.restype = c_char_p
+_get_xml.argtypes = (_ContextPtr, )
+
+_get_library_version = _lib.iio_library_get_version
+_get_library_version.argtypes = (_POINTER(c_uint), _POINTER(c_uint), c_char_p, )
+
+_get_version = _lib.iio_context_get_version
+_get_version.restype = c_int
+_get_version.argtypes = (_ContextPtr, _POINTER(c_uint), _POINTER(c_uint), c_char_p, )
+_get_version.errcheck = _checkNegative
+
+_get_attrs_count = _lib.iio_context_get_attrs_count
+_get_attrs_count.restype = c_uint
+_get_attrs_count.argtypes = (_ContextPtr, )
+
+_get_attr = _lib.iio_context_get_attr
+_get_attr.restype = c_int
+_get_attr.argtypes = (_ContextPtr, c_uint, _POINTER(c_char_p), _POINTER(c_char_p))
+_get_attr.errcheck = _checkNegative
+
+_devices_count = _lib.iio_context_get_devices_count
+_devices_count.restype = c_uint
+_devices_count.argtypes = (_ContextPtr, )
+
+_get_device = _lib.iio_context_get_device
+_get_device.restype = _DevicePtr
+_get_device.argtypes = (_ContextPtr, c_uint)
+_get_device.errcheck = _checkNull
+
+_set_timeout = _lib.iio_context_set_timeout
+_set_timeout.restype = c_int
+_set_timeout.argtypes = (_ContextPtr, c_uint, )
+_set_timeout.errcheck = _checkNegative
+
+_clone = _lib.iio_context_clone
+_clone.restype = _ContextPtr
+_clone.argtypes = (_ContextPtr, )
+_clone.errcheck = _checkNull
+
+_d_get_id = _lib.iio_device_get_id
+_d_get_id.restype = c_char_p
+_d_get_id.argtypes = (_DevicePtr, )
+_d_get_id.errcheck = _checkNull
+
+_d_get_name = _lib.iio_device_get_name
+_d_get_name.restype = c_char_p
+_d_get_name.argtypes = (_DevicePtr, )
+
+_d_attr_count = _lib.iio_device_get_attrs_count
+_d_attr_count.restype = c_uint
+_d_attr_count.argtypes = (_DevicePtr, )
+
+_d_get_attr = _lib.iio_device_get_attr
+_d_get_attr.restype = c_char_p
+_d_get_attr.argtypes = (_DevicePtr, )
+_d_get_attr.errcheck = _checkNull
+
+_d_read_attr = _lib.iio_device_attr_read
+_d_read_attr.restype = c_ssize_t
+_d_read_attr.argtypes = (_DevicePtr, c_char_p, c_char_p, c_size_t)
+_d_read_attr.errcheck = _checkNegative
+
+_d_write_attr = _lib.iio_device_attr_write
+_d_write_attr.restype = c_ssize_t
+_d_write_attr.argtypes = (_DevicePtr, c_char_p, c_char_p)
+_d_write_attr.errcheck = _checkNegative
+
+_d_debug_attr_count = _lib.iio_device_get_debug_attrs_count
+_d_debug_attr_count.restype = c_uint
+_d_debug_attr_count.argtypes = (_DevicePtr, )
+
+_d_get_debug_attr = _lib.iio_device_get_debug_attr
+_d_get_debug_attr.restype = c_char_p
+_d_get_debug_attr.argtypes = (_DevicePtr, )
+_d_get_debug_attr.errcheck = _checkNull
+
+_d_read_debug_attr = _lib.iio_device_debug_attr_read
+_d_read_debug_attr.restype = c_ssize_t
+_d_read_debug_attr.argtypes = (_DevicePtr, c_char_p, c_char_p, c_size_t)
+_d_read_debug_attr.errcheck = _checkNegative
+
+_d_write_debug_attr = _lib.iio_device_debug_attr_write
+_d_write_debug_attr.restype = c_ssize_t
+_d_write_debug_attr.argtypes = (_DevicePtr, c_char_p, c_char_p)
+_d_write_debug_attr.errcheck = _checkNegative
+
+_d_reg_write = _lib.iio_device_reg_write
+_d_reg_write.restype = c_int
+_d_reg_write.argtypes = (_DevicePtr, c_uint, c_uint)
+_d_reg_write.errcheck = _checkNegative
+
+_d_reg_read = _lib.iio_device_reg_read
+_d_reg_read.restype = c_int
+_d_reg_read.argtypes = (_DevicePtr, c_uint, _POINTER(c_uint))
+_d_reg_read.errcheck = _checkNegative
+
+_channels_count = _lib.iio_device_get_channels_count
+_channels_count.restype = c_uint
+_channels_count.argtypes = (_DevicePtr, )
+
+_get_channel = _lib.iio_device_get_channel
+_get_channel.restype = _ChannelPtr
+_get_channel.argtypes = (_DevicePtr, c_uint)
+_get_channel.errcheck = _checkNull
+
+_get_sample_size = _lib.iio_device_get_sample_size
+_get_sample_size.restype = c_int
+_get_sample_size.argtypes = (_DevicePtr, )
+_get_sample_size.errcheck = _checkNegative
+
+_d_is_trigger = _lib.iio_device_is_trigger
+_d_is_trigger.restype = c_bool
+_d_is_trigger.argtypes = (_DevicePtr, )
+
+_d_get_trigger = _lib.iio_device_get_trigger
+_d_get_trigger.restype = c_int
+_d_get_trigger.argtypes = (_DevicePtr, _DevicePtr, )
+_d_get_trigger.errcheck = _checkNegative
+
+_d_set_trigger = _lib.iio_device_set_trigger
+_d_set_trigger.restype = c_int
+_d_set_trigger.argtypes = (_DevicePtr, _DevicePtr, )
+_d_set_trigger.errcheck = _checkNegative
+
+_d_set_buffers_count = _lib.iio_device_set_kernel_buffers_count
+_d_set_buffers_count.restype = c_int
+_d_set_buffers_count.argtypes = (_DevicePtr, c_uint)
+_d_set_buffers_count.errcheck = _checkNegative
+
+_c_get_id = _lib.iio_channel_get_id
+_c_get_id.restype = c_char_p
+_c_get_id.argtypes = (_ChannelPtr, )
+_c_get_id.errcheck = _checkNull
+
+_c_get_name = _lib.iio_channel_get_name
+_c_get_name.restype = c_char_p
+_c_get_name.argtypes = (_ChannelPtr, )
+
+_c_is_output = _lib.iio_channel_is_output
+_c_is_output.restype = c_bool
+_c_is_output.argtypes = (_ChannelPtr, )
+
+_c_is_scan_element = _lib.iio_channel_is_scan_element
+_c_is_scan_element.restype = c_bool
+_c_is_scan_element.argtypes = (_ChannelPtr, )
+
+_c_attr_count = _lib.iio_channel_get_attrs_count
+_c_attr_count.restype = c_uint
+_c_attr_count.argtypes = (_ChannelPtr, )
+
+_c_get_attr = _lib.iio_channel_get_attr
+_c_get_attr.restype = c_char_p
+_c_get_attr.argtypes = (_ChannelPtr, )
+_c_get_attr.errcheck = _checkNull
+
+_c_get_filename = _lib.iio_channel_attr_get_filename
+_c_get_filename.restype = c_char_p
+_c_get_filename.argtypes = (_ChannelPtr, c_char_p, )
+_c_get_filename.errcheck = _checkNull
+
+_c_read_attr = _lib.iio_channel_attr_read
+_c_read_attr.restype = c_ssize_t
+_c_read_attr.argtypes = (_ChannelPtr, c_char_p, c_char_p, c_size_t)
+_c_read_attr.errcheck = _checkNegative
+
+_c_write_attr = _lib.iio_channel_attr_write
+_c_write_attr.restype = c_ssize_t
+_c_write_attr.argtypes = (_ChannelPtr, c_char_p, c_char_p)
+_c_write_attr.errcheck = _checkNegative
+
+_c_enable = _lib.iio_channel_enable
+_c_enable.argtypes = (_ChannelPtr, )
+
+_c_disable = _lib.iio_channel_disable
+_c_disable.argtypes = (_ChannelPtr, )
+
+_c_is_enabled = _lib.iio_channel_is_enabled
+_c_is_enabled.restype = c_bool
+_c_is_enabled.argtypes = (_ChannelPtr, )
+
+_c_read = _lib.iio_channel_read
+_c_read.restype = c_ssize_t
+_c_read.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
+
+_c_read_raw = _lib.iio_channel_read_raw
+_c_read_raw.restype = c_ssize_t
+_c_read_raw.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
+
+_c_write = _lib.iio_channel_write
+_c_write.restype = c_ssize_t
+_c_write.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
+
+_c_write_raw = _lib.iio_channel_write_raw
+_c_write_raw.restype = c_ssize_t
+_c_write_raw.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
+
+_create_buffer = _lib.iio_device_create_buffer
+_create_buffer.restype = _BufferPtr
+_create_buffer.argtypes = (_DevicePtr, c_size_t, c_bool, )
+_create_buffer.errcheck = _checkNull
+
+_buffer_destroy = _lib.iio_buffer_destroy
+_buffer_destroy.argtypes = (_BufferPtr, )
+
+_buffer_refill = _lib.iio_buffer_refill
+_buffer_refill.restype = c_ssize_t
+_buffer_refill.argtypes = (_BufferPtr, )
+_buffer_refill.errcheck = _checkNegative
+
+_buffer_push_partial = _lib.iio_buffer_push_partial
+_buffer_push_partial.restype = c_ssize_t
+_buffer_push_partial.argtypes = (_BufferPtr, c_uint, )
+_buffer_push_partial.errcheck = _checkNegative
+
+_buffer_start = _lib.iio_buffer_start
+_buffer_start.restype = c_void_p
+_buffer_start.argtypes = (_BufferPtr, )
+
+_buffer_end = _lib.iio_buffer_end
+_buffer_end.restype = c_void_p
+_buffer_end.argtypes = (_BufferPtr, )
+
+def _get_lib_version():
+ major = c_uint()
+ minor = c_uint()
+ buf = create_string_buffer(8)
+ _get_library_version(_byref(major), _byref(minor), buf)
+ return (major.value, minor.value, buf.value.decode('ascii') )
+
+version = _get_lib_version()
+backends = [ _get_backend(x).decode('ascii') for x in range(0, _get_backends_count()) ]
+
+class _Attr(object):
+ def __init__(self, name, filename = None):
+ self._name = name
+ self._name_ascii = name.encode('ascii')
+ self._filename = name if filename is None else filename
+
+ def __str__(self):
+ return self._name
+
+ name = property(lambda self: self._name, None, None,
+ "The name of this attribute.\n\ttype=str")
+ filename = property(lambda self: self._filename, None, None,
+ "The filename in sysfs to which this attribute is bound.\n\ttype=str")
+ value = property(lambda self: self.__read(), lambda self, x: self.__write(x),
+ None, "Current value of this attribute.\n\ttype=str")
+
+class ChannelAttr(_Attr):
+ """Represents an attribute of a channel."""
+
+ def __init__(self, channel, name):
+ super(ChannelAttr, self).__init__(name, _c_get_filename(channel, name.encode('ascii')).decode('ascii'))
+ self._channel = channel
+
+ def _Attr__read(self):
+ buf = create_string_buffer(1024)
+ _c_read_attr(self._channel, self._name_ascii, buf, len(buf))
+ return buf.value.decode('ascii')
+
+ def _Attr__write(self, value):
+ _c_write_attr(self._channel, self._name_ascii, value.encode('ascii'))
+
+class DeviceAttr(_Attr):
+ """Represents an attribute of an IIO device."""
+
+ def __init__(self, device, name):
+ super(DeviceAttr, self).__init__(name)
+ self._device = device
+
+ def _Attr__read(self):
+ buf = create_string_buffer(1024)
+ _d_read_attr(self._device, self._name_ascii, buf, len(buf))
+ return buf.value.decode('ascii')
+
+ def _Attr__write(self, value):
+ _d_write_attr(self._device, self._name_ascii, value.encode('ascii'))
+
+class DeviceDebugAttr(DeviceAttr):
+ """Represents a debug attribute of an IIO device."""
+
+ def __init__(self, device, name):
+ super(DeviceDebugAttr, self).__init__(device, name)
+
+ def _Attr__read(self):
+ buf = create_string_buffer(1024)
+ _d_read_debug_attr(self._device, self._name_ascii, buf, len(buf))
+ return buf.value.decode('ascii')
+
+ def _Attr__write(self, value):
+ _d_write_debug_attr(self._device, self._name_ascii, value.encode('ascii'))
+
+class Channel(object):
+ def __init__(self, _channel):
+ self._channel = _channel
+ self._attrs = { name : ChannelAttr(_channel, name) for name in \
+ [_c_get_attr(_channel, x).decode('ascii') for x in range(0, _c_attr_count(_channel))] }
+ self._id = _c_get_id(self._channel).decode('ascii')
+
+ name_raw = _c_get_name(self._channel)
+ self._name = name_raw.decode('ascii') if name_raw is not None else None
+ self._output = _c_is_output(self._channel)
+ self._scan_element = _c_is_scan_element(self._channel)
+
+ def read(self, buf, raw = False):
+ """
+ Extract the samples corresponding to this channel from the given iio.Buffer object.
+
+ parameters:
+ buf: type=iio.Buffer
+ A valid instance of the iio.Buffer class
+ raw: type=bool
+ If set to True, the samples are not converted from their
+ native format to their host format
+
+ returns: type=bytearray
+ An array containing the samples for this channel
+ """
+ array = bytearray(buf._length)
+ mytype = c_char * len(array)
+ c_array = mytype.from_buffer(array)
+ if raw:
+ length = _c_read_raw(self._channel, buf._buffer, c_array, len(array))
+ else:
+ length = _c_read(self._channel, buf._buffer, c_array, len(array))
+ return array[:length]
+
+ def write(self, buf, array, raw = False):
+ """
+ Write the specified array of samples corresponding to this channel into the given iio.Buffer object.
+
+ parameters:
+ buf: type=iio.Buffer
+ A valid instance of the iio.Buffer class
+ array: type=bytearray
+ The array containing the samples to copy
+ raw: type=bool
+ If set to True, the samples are not converted from their
+ host format to their native format
+
+ returns: type=int
+ The number of bytes written
+ """
+ mytype = c_char * len(array)
+ c_array = mytype.from_buffer(array)
+ if raw:
+ return _c_write_raw(self._channel, buf._buffer, c_array, len(array))
+ else:
+ return _c_write(self._channel, buf._buffer, c_array, len(array))
+
+ id = property(lambda self: self._id, None, None,
+ "An identifier of this channel.\n\tNote that it is possible that two channels have the same ID, if one is an input channel and the other is an output channel.\n\ttype=str")
+ name = property(lambda self: self._name, None, None,
+ "The name of this channel.\n\ttype=str")
+ attrs = property(lambda self: self._attrs, None, None,
+ "List of attributes for this channel.\n\ttype=dict of iio.ChannelAttr")
+ output = property(lambda self: self._output, None, None,
+ "Contains True if the channel is an output channel, False otherwise.\n\ttype=bool")
+ scan_element = property(lambda self: self._scan_element, None, None,
+ "Contains True if the channel is a scan element, False otherwise.\n\tIf a channel is a scan element, then it is possible to enable it and use it for I/O operations.\n\ttype=bool")
+ enabled = property(lambda self: _c_is_enabled(self._channel), \
+ lambda self, x: _c_enable(self._channel) if x else _c_disable(self._channel),
+ None, "Configured state of the channel\n\ttype=bool")
+
+class Buffer(object):
+ """The class used for all I/O operations."""
+
+ def __init__(self, device, samples_count, cyclic = False):
+ """
+ Initializes a new instance of the Buffer class.
+
+ parameters:
+ device: type=iio.Device
+ The iio.Device object that represents the device where the I/O
+ operations will be performed
+ samples_count: type=int
+ The size of the buffer, in samples
+ circular: type=bool
+ If set to True, the buffer is circular
+
+ returns: type=iio.Buffer
+ An new instance of this class
+ """
+ try:
+ self._buffer = _create_buffer(device._device, samples_count, cyclic)
+ except:
+ self._buffer = None
+ raise
+ self._length = samples_count * device.sample_size
+ self._samples_count = samples_count
+
+ self._ctx = device.ctx()
+ # Holds a reference to the corresponding IIO Context. This ensures that
+ # every iio.Buffer object is destroyed before its corresponding IIO Context.
+
+ def __del__(self):
+ if self._buffer is not None:
+ _buffer_destroy(self._buffer)
+
+ def __len__(self):
+ """The size of this buffer, in bytes."""
+ return self._length
+
+ def refill(self):
+ """Fetch a new set of samples from the hardware."""
+ _buffer_refill(self._buffer)
+
+ def push(self, samples_count = None):
+ """
+ Submit the samples contained in this buffer to the hardware.
+
+ parameters:
+ samples_count: type=int
+ The number of samples to submit, default = full buffer
+ """
+ _buffer_push_partial(self._buffer, samples_count or self._samples_count)
+
+ def read(self):
+ """
+ Retrieve the samples contained inside the Buffer object.
+
+ returns: type=bytearray
+ An array containing the samples
+ """
+
+ start = _buffer_start(self._buffer)
+ end = _buffer_end(self._buffer)
+ array = bytearray(end - start)
+ mytype = c_char * len(array)
+ c_array = mytype.from_buffer(array)
+ _memmove(c_array, start, len(array))
+ return array
+
+ def write(self, array):
+ """
+ Copy the given array of samples inside the Buffer object.
+
+ parameters:
+ array: type=bytearray
+ The array containing the samples to copy
+
+ returns: type=int
+ The number of bytes written into the buffer
+ """
+ start = _buffer_start(self._buffer)
+ end = _buffer_end(self._buffer)
+ length = end - start
+ if length > len(array):
+ length = len(array)
+ mytype = c_char * len(array)
+ c_array = mytype.from_buffer(array)
+ _memmove(start, c_array, length)
+ return length
+
+class _DeviceOrTrigger(object):
+ def __init__(self, _device):
+ self._device = _device
+ self._attrs = { name : DeviceAttr(_device, name) for name in \
+ [_d_get_attr(_device, x).decode('ascii') for x in range(0, _d_attr_count(_device))] }
+ self._debug_attrs = { name: DeviceDebugAttr(_device, name) for name in \
+ [_d_get_debug_attr(_device, x).decode('ascii') for x in range(0, _d_debug_attr_count(_device))] }
+
+ # TODO(pcercuei): Use a dictionary for the channels.
+ chans = [ Channel(_get_channel(self._device, x))
+ for x in range(0, _channels_count(self._device)) ]
+ self._channels = sorted(chans, key=lambda c: c.id)
+ self._id = _d_get_id(self._device).decode('ascii')
+
+ name_raw = _d_get_name(self._device)
+ self._name = name_raw.decode('ascii') if name_raw is not None else None
+
+ def reg_write(self, reg, value):
+ """
+ Set a value to one register of this device.
+
+ parameters:
+ reg: type=int
+ The register address
+ value: type=int
+ The value that will be used for this register
+ """
+ _d_reg_write(self._device, reg, value)
+
+ def reg_read(self, reg):
+ """
+ Read the content of a register of this device.
+
+ parameters:
+ reg: type=int
+ The register address
+
+ returns: type=int
+ The value of the register
+ """
+ value = c_uint()
+ _d_reg_read(self._device, reg, _byref(value))
+ return value.value
+
+ def find_channel(self, name_or_id, is_output = False):
+ """
+
+ Find a IIO channel by its name or ID.
+
+ parameters:
+ name_or_id: type=str
+ The name or ID of the channel to find
+ is_output: type=bool
+ Set to True to search for an output channel
+
+ returns: type=iio.Device or type=iio.Trigger
+ The IIO Device
+ """
+ return next((x for x in self.channels \
+ if name_or_id == x.name or name_or_id == x.id and \
+ x.output == is_output), None)
+
+ def set_kernel_buffers_count(self, count):
+ """
+
+ Set the number of kernel buffers to use with the specified device.
+
+ parameters:
+ count: type=int
+ The number of kernel buffers
+
+ """
+ return _d_set_buffers_count(self._device, count)
+
+ @property
+ def sample_size(self):
+ """
+ Current sample size of this device.
+ type: int
+
+ The sample size varies each time channels get enabled or disabled."""
+ return _get_sample_size(self._device)
+
+ id = property(lambda self: self._id, None, None,
+ "An identifier of this device, only valid in this IIO context.\n\ttype=str")
+ name = property(lambda self: self._name, None, None,
+ "The name of this device.\n\ttype=str")
+ attrs = property(lambda self: self._attrs, None, None,
+ "List of attributes for this IIO device.\n\ttype=dict of iio.DeviceAttr")
+ debug_attrs = property(lambda self: self._debug_attrs, None, None,
+ "List of debug attributes for this IIO device.\n\ttype=dict of iio.DeviceDebugAttr")
+ channels = property(lambda self: self._channels, None, None,
+ "List of channels available with this IIO device.\n\ttype=list of iio.Channel objects")
+
+class Trigger(_DeviceOrTrigger):
+ """Contains the representation of an IIO device that can act as a trigger."""
+
+ def __init__(self, _device):
+ super(Trigger, self).__init__(_device)
+
+ def _get_rate(self):
+ return int(self._attrs['frequency'].value)
+
+ def _set_rate(self, value):
+ self._attrs['frequency'].value = str(value)
+
+ frequency = property(_get_rate, _set_rate, None,
+ "Configured frequency (in Hz) of this trigger\n\ttype=int")
+
+class Device(_DeviceOrTrigger):
+ """Contains the representation of an IIO device."""
+
+ def __init__(self, ctx, _device):
+ super(Device, self).__init__(_device)
+ self.ctx = weakref.ref(ctx)
+
+ def _set_trigger(self, trigger):
+ _d_set_trigger(self._device, trigger._device if trigger else None)
+
+ def _get_trigger(self):
+ value = _Device()
+ _d_get_trigger(self._device, _byref(value))
+
+ for dev in self.ctx()._devices:
+ if value == dev._device:
+ return dev
+ return None
+
+ trigger = property(_get_trigger, _set_trigger, None, \
+ "Contains the configured trigger for this IIO device.\n\ttype=iio.Trigger")
+
+class Context(object):
+ """Contains the representation of an IIO context."""
+
+ def __init__(self, _context=None):
+ """
+ Initializes a new instance of the Context class, using the local or the network backend of the IIO library.
+
+ returns: type=iio.Context
+ An new instance of this class
+
+ This function will create a network context if the IIOD_REMOTE
+ environment variable is set to the hostname where the IIOD server runs.
+ If set to an empty string, the server will be discovered using ZeroConf.
+ If the environment variable is not set, a local context will be created instead.
+ """
+ self._context = None
+
+ if(_context is None):
+ self._context = _new_default()
+ elif type(_context) is str or type(_context) is unicode:
+ self._context = _new_uri(_context.encode('ascii'))
+ else:
+ self._context = _context
+
+ self._attrs = {}
+ for x in range(0, _get_attrs_count(self._context)):
+ str1 = c_char_p()
+ str2 = c_char_p()
+ _get_attr(self._context, x, _byref(str1), _byref(str2))
+ self._attrs[str1.value.decode('ascii')] = str2.value.decode('ascii')
+
+ # TODO(pcercuei): Use a dictionary for the devices.
+ self._devices = [ Trigger(dev) if _d_is_trigger(dev) else Device(self, dev) for dev in \
+ [ _get_device(self._context, x) for x in range(0, _devices_count(self._context)) ]]
+ self._name = _get_name(self._context).decode('ascii')
+ self._description = _get_description(self._context).decode('ascii')
+ self._xml = _get_xml(self._context).decode('ascii')
+
+ major = c_uint()
+ minor = c_uint()
+ buf = create_string_buffer(8)
+ _get_version(self._context, _byref(major), _byref(minor), buf)
+ self._version = (major.value, minor.value, buf.value.decode('ascii') )
+
+ def __del__(self):
+ if(self._context is not None):
+ _destroy(self._context)
+
+ def set_timeout(self, timeout):
+ """
+ Set a timeout for I/O operations.
+
+ parameters:
+ timeout: type=int
+ The timeout value, in milliseconds
+ """
+ _set_timeout(self._context, timeout)
+
+ def clone(self):
+ """
+ Clone this instance.
+
+ returns: type=iio.LocalContext
+ An new instance of this class
+ """
+ return Context(_clone(self._context))
+
+ def find_device(self, name_or_id):
+ """
+
+ Find a IIO device by its name or ID.
+
+ parameters:
+ name_or_id: type=str
+ The name or ID of the device to find
+
+ returns: type=iio.Device or type=iio.Trigger
+ The IIO Device
+ """
+ return next((x for x in self.devices \
+ if name_or_id == x.name or name_or_id == x.id), None)
+
+ name = property(lambda self: self._name, None, None, \
+ "Name of this IIO context.\n\ttype=str")
+ description = property(lambda self: self._description, None, None, \
+ "Description of this IIO context.\n\ttype=str")
+ xml = property(lambda self: self._xml, None, None, \
+ "XML representation of the current context.\n\ttype=str")
+ version = property(lambda self: self._version, None, None, \
+ "Version of the backend.\n\ttype=(int, int, str)")
+ attrs = property(lambda self: self._attrs, None, None, \
+ "List of context-specific attributes\n\ttype=dict of str objects")
+ devices = property(lambda self: self._devices, None, None, \
+ "List of devices contained in this context.\n\ttype=list of iio.Device and iio.Trigger objects")
+
+class LocalContext(Context):
+ def __init__(self):
+ """
+ Initializes a new instance of the Context class, using the local backend of the IIO library.
+
+ returns: type=iio.LocalContext
+ An new instance of this class
+ """
+ ctx = _new_local()
+ super(LocalContext, self).__init__(ctx)
+
+class XMLContext(Context):
+ def __init__(self, xmlfile):
+ """
+ Initializes a new instance of the Context class, using the XML backend of the IIO library.
+
+ parameters:
+ xmlfile: type=str
+ Filename of the XML file to build the context from
+
+ returns: type=iio.XMLContext
+ An new instance of this class
+ """
+ ctx = _new_xml(xmlfile.encode('ascii'))
+ super(XMLContext, self).__init__(ctx)
+
+class NetworkContext(Context):
+ def __init__(self, hostname = None):
+ """
+ Initializes a new instance of the Context class, using the network backend of the IIO library.
+
+ parameters:
+ hostname: type=str
+ Hostname, IPv4 or IPv6 address where the IIO Daemon is running
+
+ returns: type=iio.NetworkContext
+ An new instance of this class
+ """
+ ctx = _new_network(hostname.encode('ascii') if hostname is not None else None)
+ super(NetworkContext, self).__init__(ctx)
+
+def scan_contexts():
+ d = dict()
+ ptr = _POINTER(_ContextInfoPtr)()
+
+ ctx = _create_scan_context(None, 0)
+ nb = _get_context_info_list(ctx, _byref(ptr));
+
+ for i in range(0, nb):
+ d[_context_info_get_uri(ptr[i]).decode('ascii')] = _context_info_get_description(ptr[i]).decode('ascii')
+
+ _context_info_list_free(ptr)
+ _destroy_scan_context(ctx)
+ return d
diff --git a/bindings/python/setup.py.cmakein b/bindings/python/setup.py.cmakein
new file mode 100644
index 0000000..4cf1b50
--- /dev/null
+++ b/bindings/python/setup.py.cmakein
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2015 Analog Devices, Inc.
+# Author: Paul Cercueil <paul.cercueil@analog.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+from distutils.core import setup
+
+setup(name='libiio',
+ version='${VERSION}',
+ package_dir={'': '${CMAKE_CURRENT_SOURCE_DIR}'},
+ description='Library to use the Industrial IO devices',
+ url='https://github.com/analogdevicesinc/libiio',
+ py_modules=['iio'],
+ )