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 libiio_if < handle 36 % libiio_if Interface object for for IIO devices 37 38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 %% Protected properties 40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 41 properties (Access = protected) 42 libname = 'libiio'; 43 hname = 'iio.h'; 44 dev_name = ''; 45 data_ch_no = 0; 46 data_ch_size = 0; 47 dev_type = ''; 48 iio_ctx = {}; 49 iio_dev = {}; 50 iio_buffer = {}; 51 iio_channel = {}; 52 iio_buf_size = 8192; 53 iio_scan_elm_no = 0; 54 if_initialized = 0; 55 end 56 57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 %% Static private methods 59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 60 methods (Static, Access = private) 61 function out = modInstanceCnt(val) 62 % Manages the number of object instances to handle proper DLL unloading 63 persistent instance_cnt; 64 if isempty(instance_cnt) 65 instance_cnt = 0; 66 end 67 instance_cnt = instance_cnt + val; 68 out = instance_cnt; 69 end 70 end 71 72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 %% Protected methods 74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 methods (Access = protected) 76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 %% Creates the network context 78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 function [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address) 80 % Initialize the return values 81 ret = -1; 82 err_msg = ''; 83 msg_log = []; 84 85 % Create the network context 86 obj.iio_ctx = calllib(obj.libname, 'iio_create_network_context', ip_address); 87 88 % Check if the network context is valid 89 if (isNull(obj.iio_ctx)) 90 obj.iio_ctx = {}; 91 err_msg = 'Could not connect to the IIO server!'; 92 return; 93 end 94 95 % Increase the object's instance count 96 libiio_if.modInstanceCnt(1); 97 msg_log = [msg_log sprintf('%s: Connected to IP %s\n', class(obj), ip_address)]; 98 99 % Set the return code to success 100 ret = 0; 101 end 102 103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 104 %% Releases the network context and unload the libiio library 105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 106 function releaseContext(obj) 107 calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx); 108 obj.iio_ctx = {}; 109 instCnt = libiio_if.modInstanceCnt(-1); 110 if(instCnt == 0) 111 unloadlibrary(obj.libname); 112 end 113 end 114 115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 116 %% Checks the compatibility of the different software modules. 117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 118 function [ret, err_msg, msg_log] = checkVersions(obj) 119 % Initialize the return values 120 ret = -1; 121 err_msg = ''; 122 msg_log = []; 123 124 % Create a set of pointers to read the iiod and dll versions 125 data = zeros(1, 10); 126 remote_pMajor = libpointer('uint32Ptr', data(1)); 127 remote_pMinor = libpointer('uint32Ptr', data(2)); 128 remote_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]); 129 local_pMajor = libpointer('uint32Ptr', data(1)); 130 local_pMinor = libpointer('uint32Ptr', data(2)); 131 local_pGitTag = libpointer('int8Ptr', [int8(data(3:end)) 0]); 132 133 % get remote libiio version 134 calllib(obj.libname, 'iio_context_get_version', obj.iio_ctx, remote_pMajor, remote_pMinor, remote_pGitTag); 135 % extract git hash without trailing null char 136 remote_githash = remote_pGitTag.Value(1:7); 137 remote_version_str = sprintf('Remote libiio version: %d.%d, (git-%s)', remote_pMajor.Value, remote_pMinor.Value, remote_githash); 138 msg_log = [msg_log sprintf('%s: %s\n', class(obj), remote_version_str)]; 139 140 % get local libiio version 141 calllib(obj.libname, 'iio_library_get_version', local_pMajor, local_pMinor, local_pGitTag); 142 local_githash = local_pGitTag.Value(1:7); 143 local_version_str = sprintf('Local libiio version: %d.%d, (git-%s)', local_pMajor.Value, local_pMinor.Value, local_githash); 144 msg_log = [msg_log sprintf('%s: %s\n', class(obj), local_version_str)]; 145 146 if(remote_pMajor.Value < local_pMajor.Value) 147 err_msg = ['The libiio version running on the device is outdated! ' ... 148 'Run the adi_update_tools.sh script to get libiio up to date.']; 149 return; 150 elseif(remote_pMajor.Value > local_pMajor.Value) 151 err_msg = ['The libiio version on the local host is outdated! ' ... 152 'On Windows, reinstall the dll using the latest installer ' ... 153 'from the Analog Devices wiki.']; 154 return; 155 end 156 157 % Set the return code to success 158 ret = 0; 159 end 160 161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 162 %% Detect if the specified device is present in the system 163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 164 function [ret, err_msg, msg_log] = initDevice(obj, dev_name) 165 % Initialize the return values 166 ret = -1; 167 err_msg = ''; 168 msg_log = []; 169 170 % Store the device name 171 obj.dev_name = dev_name; 172 173 % Get the number of devices 174 nb_devices = calllib(obj.libname, 'iio_context_get_devices_count', obj.iio_ctx); 175 176 % If no devices are present return with error 177 if(nb_devices == 0) 178 err_msg = 'No devices were detected in the system!'; 179 return; 180 end 181 msg_log = [msg_log sprintf('%s: Found %d devices in the system\n', class(obj), nb_devices)]; 182 183 % Detect if the targeted device is installed 184 dev_found = 0; 185 for i = 0 : nb_devices - 1 186 dev = calllib(obj.libname, 'iio_context_get_device', obj.iio_ctx, i); 187 name = calllib(obj.libname, 'iio_device_get_name', dev); 188 if(strcmp(name, dev_name)) 189 obj.iio_dev = dev; 190 dev_found = 1; 191 break; 192 end 193 clear dev; 194 end 195 196 % Check if the target device was detected 197 if(dev_found == 0) 198 err_msg = 'Could not find target configuration device!'; 199 return; 200 end 201 202 msg_log = [msg_log sprintf('%s: %s was found in the system\n', class(obj), obj.dev_name)]; 203 204 % Set the return code to success 205 ret = 0; 206 end 207 208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 209 %% Initializes the output data channels 210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 211 function [ret, err_msg, msg_log] = initOutputDataChannels(obj, ch_no, ch_size) 212 % Initialize the return values 213 ret = -1; 214 err_msg = ''; 215 msg_log = []; 216 217 % Save the number of channels and size 218 obj.data_ch_no = ch_no; 219 obj.data_ch_size = ch_size; 220 221 % Get the number of channels that the device has 222 nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev); 223 if(nb_channels == 0) 224 err_msg = 'The selected device does not have any channels!'; 225 return; 226 end 227 228 % Enable the data channels 229 if(ch_no ~= 0) 230 % Check if the device has output channels. The 231 % logic here assumes that a device can have 232 % only input or only output channels 233 obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0); 234 is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1}); 235 if(is_output == 0) 236 err_msg = 'The selected device does not have output channels!'; 237 return; 238 end 239 % Enable all the channels 240 for j = 0 : nb_channels - 1 241 obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j); 242 if(j < ch_no) 243 calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1}); 244 is_scan_element = calllib(obj.libname, 'iio_channel_is_scan_element', obj.iio_channel{j+1}); 245 if(is_scan_element == 1) 246 obj.iio_scan_elm_no = obj.iio_scan_elm_no + 1; 247 end 248 else 249 calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1}); 250 end 251 end 252 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)]; 253 254 % Check if the number of channels in the device 255 % is greater or equal to the system object 256 % input channels 257 if(obj.iio_scan_elm_no < ch_no) 258 obj.iio_channel = {}; 259 err_msg = 'The selected device does not have enough output channels!'; 260 return; 261 end 262 263 % Enable the DAC buffer output 264 obj.if_initialized = 1; 265 ret = writeAttributeString(obj, 'altvoltage0*raw', '0'); 266 obj.if_initialized = 0; 267 if(ret < 0) 268 obj.iio_channel = {}; 269 err_msg = 'Could not enable the DAC buffer output!'; 270 return; 271 end 272 273 % Create the IIO buffer used to write data 274 obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no; 275 obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,... 276 obj.data_ch_size, 1); 277 end 278 279 msg_log = [msg_log sprintf('%s: %s output data channels successfully initialized\n', class(obj), obj.dev_name)]; 280 281 % Set the return code to success 282 ret = 0; 283 end 284 285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 286 %% Initializes the input data channels 287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 288 function [ret, err_msg, msg_log] = initInputDataChannels(obj, ch_no, ch_size) 289 % Initialize the return values 290 ret = -1; 291 err_msg = ''; 292 msg_log = []; 293 294 % Save the number of channels and size 295 obj.data_ch_no = ch_no; 296 obj.data_ch_size = ch_size; 297 298 % Get the number of channels that the device has 299 nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev); 300 if(nb_channels == 0) 301 err_msg = 'The selected device does not have any channels!'; 302 return; 303 end 304 305 % Enable the system object output channels 306 if(ch_no ~= 0) 307 % Check if the device has input channels. The 308 % logic here assumes that a device can have 309 % only input or only output channels 310 obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0); 311 is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1}); 312 if(is_output == 1) 313 err_msg = 'The selected device does not have input channels!'; 314 return; 315 end 316 msg_log = [msg_log sprintf('%s: Found %d input channels for the device %s\n', class(obj), nb_channels, obj.dev_name)]; 317 318 % Check if the number of channels in the device 319 % is greater or equal to the system object 320 % output channels 321 if(nb_channels < ch_no) 322 obj.iio_channel = {}; 323 err_msg = 'The selected device does not have enough input channels!'; 324 return; 325 end 326 327 % Enable the channels 328 for j = 0 : ch_no - 1 329 obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j); 330 calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1}); 331 end 332 for j = ch_no : nb_channels - 1 333 obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j); 334 calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1}); 335 end 336 % Create the IIO buffer used to read data 337 obj.iio_buf_size = obj.data_ch_size * obj.data_ch_no; 338 obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev, obj.iio_buf_size, 0); 339 end 340 341 msg_log = [msg_log sprintf('%s: %s input data channels successfully initialized\n', class(obj), obj.dev_name)]; 342 343 % Set the return code to success 344 ret = 0; 345 end 346 347 end 348 349 350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 351 %% Public methods 352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353 methods 354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 355 %% Constructor 356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 357 function obj = libiio_if() 358 % Constructor 359 obj.if_initialized = 0; 360 end 361 362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 363 %% Destructor 364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 365 function delete(obj) 366 % Release any resources used by the system object. 367 if((obj.if_initialized == 1) && libisloaded(obj.libname)) 368 if(~isempty(obj.iio_buffer)) 369 calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer); 370 end 371 if(~isempty(obj.iio_ctx)) 372 calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx); 373 end 374 obj.iio_buffer = {}; 375 obj.iio_channel = {}; 376 obj.iio_dev = {}; 377 obj.iio_ctx = {}; 378 instCnt = libiio_if.modInstanceCnt(-1); 379 if(instCnt == 0) 380 unloadlibrary(obj.libname); 381 end 382 end 383 end 384 385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 386 %% Initializes the libiio interface 387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 388 function [ret, err_msg, msg_log] = init(obj, ip_address, ... 389 dev_name, dev_type, ... 390 data_ch_no, data_ch_size) 391 % Initialize the return values 392 ret = -1; 393 err_msg = ''; 394 msg_log = []; 395 396 % Save the device type 397 obj.dev_type = dev_type; 398 399 % Set the initialization status to fail 400 obj.if_initialized = 0; 401 402 % Load the libiio library 403 if(~libisloaded(obj.libname)) 404 try 405 [notfound, warnings] = loadlibrary(obj.libname, obj.hname); 406 catch exception 407 err_msg = exception.message; 408 return; 409 end 410 end 411 412 if(~libisloaded(obj.libname)) 413 err_msg = 'Could not load the libiio library!'; 414 return; 415 end 416 417 % Create the network context 418 [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address); 419 if(ret < 0) 420 return; 421 end 422 423 % Check the software versions 424 [ret, err_msg, msg_log_new] = checkVersions(obj); 425 msg_log = [msg_log msg_log_new]; 426 if(ret < 0) 427 releaseContext(obj); 428 return; 429 end 430 431 % Initialize the device 432 [ret, err_msg, msg_log_new] = initDevice(obj, dev_name); 433 msg_log = [msg_log msg_log_new]; 434 if(ret < 0) 435 releaseContext(obj); 436 return; 437 end 438 439 % Initialize the output data channels 440 if(strcmp(dev_type, 'OUT')) 441 [ret, err_msg, msg_log_new] = initOutputDataChannels(obj, data_ch_no, data_ch_size); 442 msg_log = [msg_log msg_log_new]; 443 if(ret < 0) 444 releaseContext(obj); 445 return; 446 end 447 end 448 449 % Initialize the input data channels 450 if(strcmp(dev_type, 'IN')) 451 [ret, err_msg, msg_log_new] = initInputDataChannels(obj, data_ch_no, data_ch_size); 452 msg_log = [msg_log msg_log_new]; 453 if(ret < 0) 454 releaseContext(obj); 455 return; 456 end 457 end 458 459 % Set the initialization status to success 460 obj.if_initialized = 1; 461 end 462 463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 464 %% Implement the data capture flow 465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 466 function [ret, data] = readData(obj) 467 % Initialize the return values 468 ret = -1; 469 data = cell(1, obj.data_ch_no); 470 for i = 1 : obj.data_ch_no 471 data{i} = zeros(obj.data_ch_size, 1); 472 end 473 474 % Check if the interface is initialized 475 if(obj.if_initialized == 0) 476 return; 477 end 478 479 % Check if the device type is output 480 if(~strcmp(obj.dev_type, 'IN')) 481 return; 482 end 483 484 % Read the data 485 calllib(obj.libname, 'iio_buffer_refill', obj.iio_buffer); 486 buffer = calllib(obj.libname, 'iio_buffer_first', obj.iio_buffer, obj.iio_channel{1}); 487 setdatatype(buffer, 'int16Ptr', obj.iio_buf_size); 488 for i = 1 : obj.data_ch_no 489 data{i} = double(buffer.Value(i:obj.data_ch_no:end)); 490 end 491 492 % Set the return code to success 493 ret = 0; 494 end 495 496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 497 %% Implement the data transmit flow 498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 499 function ret = writeData(obj, data) 500 % Initialize the return values 501 ret = -1; 502 503 % Check if the interface is initialized 504 if(obj.if_initialized == 0) 505 return; 506 end 507 508 % Check if the device type is input 509 if(~strcmp(obj.dev_type, 'OUT')) 510 return; 511 end 512 513 % Destroy the buffer 514 calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer); 515 obj.iio_buffer = {}; 516 517 % Enable the DAC buffer output 518 ret = writeAttributeString(obj, 'altvoltage0*raw', '0'); 519 if(ret < 0) 520 obj.iio_channel = {}; 521 err_msg = 'Could not enable the DAC buffer output!'; 522 return; 523 end 524 525 % Create the IIO buffer used to write data 526 obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no; 527 obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,... 528 obj.data_ch_size, 1); 529 530 % Transmit the data 531 buffer = calllib(obj.libname, 'iio_buffer_start', obj.iio_buffer); 532 setdatatype(buffer, 'int16Ptr', obj.iio_buf_size); 533 for i = 1 : obj.data_ch_no 534 buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = int16(data{i}); 535 end 536 for i = obj.data_ch_no + 1 : obj.iio_scan_elm_no 537 buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = 0; 538 end 539 calllib(obj.libname, 'iio_buffer_push', obj.iio_buffer); 540 541 % Set the return code to success 542 ret = 0; 543 end 544 545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 546 %% Find an attribute based on the name. The name can contain wildcard '*' characters 547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 548 function [ret, ch, attr] = findAttribute(obj, attr_name) 549 % Initialize the return values 550 ret = -1; 551 ch = 0; 552 attr = ''; 553 554 % Check if the interface is initialized 555 if(obj.if_initialized == 0) 556 return; 557 end 558 559 % Check if this is a device attribute 560 name = calllib(obj.libname, 'iio_device_find_attr', obj.iio_dev, attr_name); 561 if(~isempty(name)) 562 ret = 0; 563 return; 564 end 565 566 % This is a channel attribute, search for the corresponding channel 567 chn_no = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev); 568 for k = 0 : chn_no - 1 569 ch = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, k); 570 attr_no = calllib(obj.libname, 'iio_channel_get_attrs_count', ch); 571 attr_found = 0; 572 for l = 0 : attr_no - 1 573 attr = calllib(obj.libname, 'iio_channel_get_attr', ch, l); 574 name = calllib(obj.libname, 'iio_channel_attr_get_filename', ch, attr); 575 % The attribute to find can contain wildcard '*' characters, 576 % search for all the substrings in the attribute name 577 str_find = strsplit(attr_name, '*'); 578 str_find = str_find(find(~strcmp(str_find, ''))); 579 has_wildcard = ~isempty(strfind(attr_name, '*')); 580 attr_found = 1; 581 for i = 1 : length(str_find) 582 if(has_wildcard == 0) 583 ret = strcmp(name, str_find{i}); 584 if(ret == 0) 585 ret = []; 586 end 587 else 588 ret = strfind(name, str_find{i}); 589 end 590 if(isempty(ret)) 591 attr_found = 0; 592 break; 593 end 594 end 595 if(attr_found == 1) 596 break; 597 end 598 clear attr; 599 end 600 % Check if the attribute was found 601 if(attr_found == 0) 602 clear ch; 603 else 604 ret = 1; 605 break; 606 end 607 end 608 end 609 610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 611 %% Read an attribute as a double value 612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 613 function [ret, val] = readAttributeDouble(obj, attr_name) 614 % Find the attribute 615 [ret, ch, attr] = findAttribute(obj, attr_name); 616 if(ret < 0) 617 val = 0; 618 return; 619 end 620 621 % Create a double pointer to be used for data read 622 data = zeros(1, 10); 623 pData = libpointer('doublePtr', data(1)); 624 625 % Read the attribute value 626 if(ret > 0) 627 calllib(obj.libname, 'iio_channel_attr_read_double', ch, attr, pData); 628 clear ch; 629 clear attr; 630 else 631 calllib(obj.libname, 'iio_device_attr_read_double', obj.iio_dev, attr_name, pData); 632 end 633 val = pData.Value; 634 end 635 636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 637 %% Read an attribute as a string value 638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 639 function [ret, val] = readAttributeString(obj, attr_name) 640 % Find the attribute 641 [ret, ch, attr] = findAttribute(obj, attr_name); 642 if(ret < 0) 643 val = ''; 644 return; 645 end 646 647 % Create a pointer to be used for data read 648 data = char(ones(1, 512)); 649 pData = libpointer('stringPtr', data); 650 651 % Read the attribute value 652 if(ret > 0) 653 [~, ~, ~, val] = calllib(obj.libname, 'iio_channel_attr_read', ch, attr, pData, 512); 654 clear ch; 655 clear attr; 656 else 657 [~, ~, ~, val] = calllib(obj.libname, 'iio_device_attr_read', obj.iio_dev, attr_name, pData, 512); 658 end 659 end 660 661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 662 %% Write a string double value 663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 664 function ret = writeAttributeDouble(obj, attr_name, val) 665 % Find the attribute 666 [ret, ch, attr] = findAttribute(obj, attr_name); 667 if(ret < 0) 668 return; 669 end 670 671 % Write the attribute 672 if(ret > 0) 673 calllib(obj.libname, 'iio_channel_attr_write_double', ch, attr, val); 674 clear ch; 675 clear attr; 676 else 677 calllib(obj.libname, 'iio_device_attr_write_double', obj.iio_dev, attr_name, val); 678 end 679 end 680 681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 682 %% Write a string attribute value 683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 684 function ret = writeAttributeString(obj, attr_name, str) 685 % Find the attribute 686 [ret, ch, attr] = findAttribute(obj, attr_name); 687 if(ret < 0) 688 return; 689 end 690 691 % Write the attribute 692 if(ret > 0) 693 calllib(obj.libname, 'iio_channel_attr_write', ch, attr, str); 694 clear ch; 695 clear attr; 696 else 697 calllib(obj.libname, 'iio_device_attr_write', obj.iio_dev, attr_name, str); 698 end 699 end 700 end 701end 702