• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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