1% Copyright 2014(c) Analog Devices, Inc. 2% 3% All rights reserved. 4% 5% Redistribution and use in source and binary forms, with or without modification, 6% are permitted provided that the following conditions are met: 7% - Redistributions of source code must retain the above copyright 8% notice, this list of conditions and the following disclaimer. 9% - Redistributions in binary form must reproduce the above copyright 10% notice, this list of conditions and the following disclaimer in 11% the documentation and/or other materials provided with the 12% distribution. 13% - Neither the name of Analog Devices, Inc. nor the names of its 14% contributors may be used to endorse or promote products derived 15% from this software without specific prior written permission. 16% - The use of this software may or may not infringe the patent rights 17% of one or more patent holders. This license does not release you 18% from the requirement that you obtain separate licenses from these 19% patent holders to use this software. 20% - Use of the software either in source or binary form or filter designs 21% resulting from the use of this software, must be connected to, run 22% on or loaded to an Analog Devices Inc. component. 23% 24% THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 25% INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A 26% PARTICULAR PURPOSE ARE DISCLAIMED. 27% 28% IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY 30% RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 32% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 33% THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 35classdef iio_sys_obj_matlab 36 % iio_sys_obj System Object block for IIO devices 37 38 properties (Access = public) 39 % Public, non-tunable properties. 40 41 %ip_address IP address 42 ip_address = ''; 43 44 %dev_name Device name 45 dev_name = ''; 46 47 %in_ch_no Number of input data channels 48 in_ch_no = 0; 49 50 %in_ch_size Input data channel size [samples] 51 in_ch_size = 8192; 52 53 %out_ch_no Number of output data channels 54 out_ch_no = 0; 55 56 %out_ch_size Output data channel size [samples] 57 out_ch_size = 8192; 58 end 59 60 properties (Access = public) 61 % Protected class properties. 62 63 %iio_dev_cfg Device configuration structure 64 iio_dev_cfg = []; 65 end 66 67 properties (Access = private) 68 % Private class properties. 69 70 %libiio_data_in_dev libiio IIO interface object for the input data device 71 libiio_data_in_dev = {}; 72 73 %libiio_data_out_dev libiio IIO interface object for the output data device 74 libiio_data_out_dev = {}; 75 76 %libiio_ctrl_dev libiio IIO interface object for the control device 77 libiio_ctrl_dev = {}; 78 79 %sys_obj_initialized Holds the initialization status of the system object 80 sys_obj_initialized = 0; 81 end 82 83 properties (Access = private) 84 % Discrete state properties. 85 86 %num_cfg_in Numeric type input control channels data 87 num_cfg_in; 88 89 %str_cfg_in String type input control channels data 90 str_cfg_in; 91 end 92 93 methods 94 %% Constructor 95 function obj = iio_sys_obj_matlab(varargin) 96 % Construct the libiio interface objects 97 obj.libiio_data_in_dev = libiio_if(); 98 obj.libiio_data_out_dev = libiio_if(); 99 obj.libiio_ctrl_dev = libiio_if(); 100 end 101 end 102 103 methods (Access = protected) 104 %% Utility functions 105 106 function config = getObjConfig(obj) 107 % Read the selected device configuration 108 109 % Open the configuration file 110 fname = sprintf('%s.cfg', obj.dev_name); 111 fp_cfg = fopen(fname); 112 if(fp_cfg < 0) 113 config = {}; 114 return; 115 end 116 117 % Build the object configuration structure 118 config = struct('data_in_device', '',... % Pointer to the data input device 119 'data_out_device', '',... % Pointer to the data output device 120 'ctrl_device', '',... % Pointer to the control device 121 'cfg_ch', [],... % Configuration channels list 122 'mon_ch', [],... % Monitoring channels list 123 'in_ch_names', [],... % Configuration channels names 124 'out_ch_names', []); % Monitoring channels names 125 config.in_ch_names = {}; 126 config.out_ch_names = {}; 127 128 % Build the configuration/monitoring channels structure 129 ch_cfg = struct('port_name', '',... % Name of the port to be displayed on the object block 130 'port_attr', '',... % Associated device attribute name 131 'ctrl_dev_name', '',... % Control device name 132 'ctrl_dev', 0); % Pointer to the control device object 133 134 % Read the object's configuration 135 while(~feof(fp_cfg)) 136 line = fgets(fp_cfg); 137 if(strfind(line,'#')) 138 continue; 139 end 140 if(~isempty(strfind(line, 'channel'))) 141 % Get the associated configuration/monitoring channels 142 idx = strfind(line, '='); 143 line = line(idx+1:end); 144 line = strsplit(line, ','); 145 ch_cfg.port_name = strtrim(line{1}); 146 ch_cfg.port_attr = strtrim(line{3}); 147 if(length(line) > 4) 148 ch_cfg.ctrl_dev_name = strtrim(line{4}); 149 else 150 ch_cfg.ctrl_dev_name = 'ctrl_device'; 151 end 152 if(strcmp(strtrim(line{2}), 'IN')) 153 config.cfg_ch = [config.cfg_ch ch_cfg]; 154 config.in_ch_names = [config.in_ch_names ch_cfg.port_name]; 155 elseif(strcmp(strtrim(line{2}), 'OUT')) 156 config.mon_ch = [config.mon_ch ch_cfg]; 157 config.out_ch_names = [config.out_ch_names ch_cfg.port_name]; 158 end 159 elseif(~isempty(strfind(line, 'data_in_device'))) 160 % Get the associated data input device 161 idx = strfind(line, '='); 162 tmp = line(idx+1:end); 163 tmp = strtrim(tmp); 164 config.data_in_device = tmp; 165 elseif(~isempty(strfind(line, 'data_out_device'))) 166 % Get the associated data output device 167 idx = strfind(line, '='); 168 tmp = line(idx+1:end); 169 tmp = strtrim(tmp); 170 config.data_out_device = tmp; 171 elseif(~isempty(strfind(line, 'ctrl_device'))) 172 % Get the associated control device 173 idx = strfind(line, '='); 174 tmp = line(idx+1:end); 175 tmp = strtrim(tmp); 176 config.ctrl_device = tmp; 177 end 178 end 179 fclose(fp_cfg); 180 end 181 182 end 183 184 methods (Access = public) 185 %% Helper functions 186 function ret = getInChannel(obj, channelName) 187 % Returns the index of a named input channel 188 ret = obj.in_ch_no + find(strcmp(obj.iio_dev_cfg.in_ch_names, channelName)); 189 end 190 191 function ret = getOutChannel(obj, channelName) 192 % Returns the index of a named output channel 193 ret = obj.out_ch_no + find(strcmp(obj.iio_dev_cfg.out_ch_names, channelName)); 194 end 195 196 %% Common functions 197 function ret = setupImpl(obj) 198 % Implement tasks that need to be performed only once. 199 200 % Set the initialization status to fail 201 obj.sys_obj_initialized = 0; 202 203 % Read the object's configuration from the associated configuration file 204 obj.iio_dev_cfg = getObjConfig(obj); 205 if(isempty(obj.iio_dev_cfg)) 206 msgbox('Could not read device configuration!', 'Error','error'); 207 return; 208 end 209 210 % Initialize discrete-state properties. 211 obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch)); 212 obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64); 213 214 % Initialize the libiio data input device 215 if(obj.in_ch_no ~= 0) 216 [ret, err_msg, msg_log] = init(obj.libiio_data_in_dev, obj.ip_address, ... 217 obj.iio_dev_cfg.data_in_device, 'OUT', ... 218 obj.in_ch_no, obj.in_ch_size); 219 fprintf('%s', msg_log); 220 if(ret < 0) 221 msgbox(err_msg, 'Error','error'); 222 return; 223 end 224 end 225 226 % Initialize the libiio data output device 227 if(obj.out_ch_no ~= 0) 228 [ret, err_msg, msg_log] = init(obj.libiio_data_out_dev, obj.ip_address, ... 229 obj.iio_dev_cfg.data_out_device, 'IN', ... 230 obj.out_ch_no, obj.out_ch_size); 231 fprintf('%s', msg_log); 232 if(ret < 0) 233 msgbox(err_msg, 'Error','error'); 234 return; 235 end 236 end 237 238 % Initialize the libiio control device 239 if(~isempty(obj.iio_dev_cfg.ctrl_device)) 240 [ret, err_msg, msg_log] = init(obj.libiio_ctrl_dev, obj.ip_address, ... 241 obj.iio_dev_cfg.ctrl_device, '', ... 242 0, 0); 243 fprintf('%s', msg_log); 244 if(ret < 0) 245 msgbox(err_msg, 'Error','error'); 246 return; 247 end 248 end 249 250 % Assign the control device for each monitoring channel 251 for i = 1 : length(obj.iio_dev_cfg.mon_ch) 252 if(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_in_device')) 253 obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_in_dev; 254 elseif(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_out_device')) 255 obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_out_dev; 256 else 257 obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_ctrl_dev; 258 end 259 end 260 261 % Assign the control device for each configuration channel 262 for i = 1 : length(obj.iio_dev_cfg.cfg_ch) 263 if(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_in_device')) 264 obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_in_dev; 265 elseif(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_out_device')) 266 obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_out_dev; 267 else 268 obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_ctrl_dev; 269 end 270 end 271 272 % Set the initialization status to success 273 obj.sys_obj_initialized = 1; 274 ret = obj; 275 end 276 277 function releaseImpl(obj) 278 % Release any resources used by the system object. 279 obj.iio_dev_cfg = {}; 280 delete(obj.libiio_data_in_dev); 281 delete(obj.libiio_data_out_dev); 282 delete(obj.libiio_ctrl_dev); 283 end 284 285 function ret = stepImpl(obj, varargin) 286 % Implement the system object's processing flow. 287 varargout = cell(1, obj.out_ch_no + length(obj.iio_dev_cfg.mon_ch)); 288 if(obj.sys_obj_initialized == 0) 289 return; 290 end 291 292 % Implement the device configuration flow 293 for i = 1 : length(obj.iio_dev_cfg.cfg_ch) 294 if(~isempty(varargin{1}{i + obj.in_ch_no})) 295 if(length(varargin{1}{i + obj.in_ch_no}) == 1) 296 new_data = (varargin{1}{i + obj.in_ch_no} ~= obj.num_cfg_in(i)); 297 else 298 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})); 299 end 300 if(new_data == 1) 301 if(length(varargin{1}{i + obj.in_ch_no}) == 1) 302 obj.num_cfg_in(i) = varargin{1}{i + obj.in_ch_no}; 303 str = num2str(obj.num_cfg_in(i)); 304 else 305 for j = 1:length(varargin{1}{i + obj.in_ch_no}) 306 obj.str_cfg_in(i,j) = varargin{1}{i + obj.in_ch_no}(j); 307 end 308 obj.str_cfg_in(i,j+1) = 0; 309 str = char(obj.str_cfg_in(i,:)); 310 end 311 writeAttributeString(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev, obj.iio_dev_cfg.cfg_ch(i).port_attr, str); 312 end 313 end 314 end 315 316 % Implement the data transmit flow 317 writeData(obj.libiio_data_in_dev, varargin{1}); 318 319 % Implement the data capture flow 320 [~, data] = readData(obj.libiio_data_out_dev); 321 for i = 1 : obj.out_ch_no 322 varargout{i} = data{i}; 323 end 324 325 % Implement the parameters monitoring flow 326 for i = 1 : length(obj.iio_dev_cfg.mon_ch) 327 [~, val] = readAttributeDouble(obj.iio_dev_cfg.mon_ch(i).ctrl_dev, obj.iio_dev_cfg.mon_ch(i).port_attr); 328 varargout{obj.out_ch_no + i} = val; 329 end 330 331 ret=varargout; 332 end 333 334 function ret = writeFirData(obj, fir_data_file) 335 fir_data_str = fileread(fir_data_file); 336 ret = writeAttributeString(obj.libiio_ctrl_dev, 'in_out_voltage_filter_fir_en', '0'); 337 if ret<0 338 return; 339 end 340 ret = writeAttributeString(obj.libiio_ctrl_dev, 'filter_fir_config', fir_data_str); 341 if ret<0 342 return; 343 end 344 ret = writeAttributeString(obj.libiio_ctrl_dev, 'in_out_voltage_filter_fir_en', '1'); 345 if ret<0 346 return; 347 end 348 end 349 end 350end 351