summaryrefslogtreecommitdiff
path: root/bindings/matlab
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/matlab')
-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
7 files changed, 2315 insertions, 0 deletions
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