├── .gitignore ├── LICENSE.txt ├── README.md ├── iio.h ├── iio_sys_obj.m ├── iio_sys_obj_matlab.m ├── libiio_if.m └── libiio_if_daq2.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2014-2018(c) Analog Devices, Inc. 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | - Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | - Neither the name of Analog Devices, Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | - The use of this software may or may not infringe the patent rights 18 | of one or more patent holders. This license does not release you 19 | from the requirement that you obtain separate licenses from these 20 | patent holders to use this software. 21 | - Use of the software either in source or binary form, must be run 22 | on or directly connected 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libiio-matlab 2 | 3 | MATLAB bindings for libiio 4 | 5 | **_NOTE_**: These interfaces are deprecated. Please use the [Transceiver Toolbox](https://wiki.analog.com/resources/tools-software/transceiver-toolbox) or the [High Speed Converter Toolbox](https://wiki.analog.com/resources/tools-software/hsx-toolbox) 6 | 7 | ## Documentation 8 | - [IIO System Object](https://wiki.analog.com/resources/tools-software/linux-software/libiio/clients/matlab_simulink) 9 | -------------------------------------------------------------------------------- /iio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libiio - Library for interfacing industrial I/O (IIO) devices 3 | * 4 | * Copyright (C) 2014 Analog Devices, Inc. 5 | * Author: Paul Cercueil 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * */ 18 | 19 | /** @file iio.h 20 | * @brief Public interface */ 21 | 22 | #ifndef __IIO_H__ 23 | #define __IIO_H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | //#include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifdef _MSC_BUILD 36 | /* Come on Microsoft, time to get some C99... */ 37 | typedef long ssize_t; 38 | #endif 39 | 40 | /* Breaks with MATLAB on Linux 41 | * #ifdef __GNUC__ 42 | * #define __cnst __attribute__((const)) 43 | * #define __pure __attribute__((pure)) 44 | * #define __notused __attribute__((unused)) 45 | * #else */ 46 | #define __cnst 47 | #define __pure 48 | #define __notused 49 | /* #endif */ 50 | 51 | #ifdef _WIN32 52 | # ifdef LIBIIO_EXPORTS 53 | # define __api __declspec(dllexport) 54 | # else 55 | # define __api __declspec(dllimport) 56 | # endif 57 | /* Breaks with MATLAB on Linux 58 | * #elif __GNUC__ >= 4 59 | * # define __api __attribute__((visibility ("default"))) */ 60 | #else 61 | # define __api 62 | #endif 63 | 64 | struct iio_context; 65 | struct iio_device; 66 | struct iio_channel; 67 | struct iio_buffer; 68 | 69 | 70 | /* ---------------------------------------------------------------------------*/ 71 | /* ------------------------- Top-level functions -----------------------------*/ 72 | /** @defgroup TopLevel Top-level functions 73 | * @{ */ 74 | 75 | 76 | /** @brief Get the version of the libiio library 77 | * @param major A pointer to an unsigned integer (NULL accepted) 78 | * @param minor A pointer to an unsigned integer (NULL accepted) 79 | * @param git_tag A pointer to a 8-characters buffer (NULL accepted) */ 80 | __api void iio_library_get_version(unsigned int *major, 81 | unsigned int *minor, char git_tag[8]); 82 | 83 | 84 | /** @} *//* ------------------------------------------------------------------*/ 85 | /* ------------------------- Context functions -------------------------------*/ 86 | /** @defgroup Context Context 87 | * @{ 88 | * @struct iio_context 89 | * @brief Contains the representation of an IIO context */ 90 | 91 | 92 | /** @brief Create a context from local or remote IIO devices 93 | * @return On success, A pointer to an iio_context structure 94 | * @return On failure, NULL is returned and errno is set appropriately 95 | * 96 | * NOTE: This function will create a network context if the IIOD_REMOTE 97 | * environment variable is set to the hostname where the IIOD server runs. If 98 | * set to an empty string, the server will be discovered using ZeroConf. 99 | * If the environment variable is not set, a local context will be created 100 | * instead. */ 101 | __api struct iio_context * iio_create_default_context(void); 102 | 103 | 104 | /** @brief Create a context from local IIO devices (Linux only) 105 | * @return On success, A pointer to an iio_context structure 106 | * @return On failure, NULL is returned and errno is set appropriately */ 107 | __api struct iio_context * iio_create_local_context(void); 108 | 109 | 110 | /** @brief Create a context from a XML file 111 | * @param xml_file Path to the XML file to open 112 | * @return On success, A pointer to an iio_context structure 113 | * @return On failure, NULL is returned and errno is set appropriately 114 | * 115 | * NOTE: The format of the XML must comply to the one returned by 116 | * iio_context_get_xml. */ 117 | __api struct iio_context * iio_create_xml_context(const char *xml_file); 118 | 119 | 120 | /** @brief Create a context from XML data in memory 121 | * @param xml Pointer to the XML data in memory 122 | * @param len Length of the XML string in memory (excluding the final \0) 123 | * @return On success, A pointer to an iio_context structure 124 | * @return On failure, NULL is returned and errno is set appropriately 125 | * 126 | * NOTE: The format of the XML must comply to the one returned by 127 | * iio_context_get_xml */ 128 | __api struct iio_context * iio_create_xml_context_mem( 129 | const char *xml, size_t len); 130 | 131 | 132 | /** @brief Create a context from the network 133 | * @param host Hostname, IPv4 or IPv6 address where the IIO Daemon is running 134 | * @return On success, a pointer to an iio_context structure 135 | * @return On failure, NULL is returned and errno is set appropriately */ 136 | __api struct iio_context * iio_create_network_context(const char *host); 137 | 138 | 139 | /** @brief Duplicate a pre-existing IIO context 140 | * @param ctx A pointer to an iio_context structure 141 | * @return On success, A pointer to an iio_context structure 142 | * @return On failure, NULL is returned and errno is set appropriately */ 143 | __api struct iio_context * iio_context_clone(const struct iio_context *ctx); 144 | 145 | 146 | /** @brief Destroy the given context 147 | * @param ctx A pointer to an iio_context structure 148 | * 149 | * NOTE: After that function, the iio_context pointer shall be invalid. */ 150 | __api void iio_context_destroy(struct iio_context *ctx); 151 | 152 | 153 | /** @brief Get the version of the backend in use 154 | * @param ctx A pointer to an iio_context structure 155 | * @param major A pointer to an unsigned integer (NULL accepted) 156 | * @param minor A pointer to an unsigned integer (NULL accepted) 157 | * @param git_tag A pointer to a 8-characters buffer (NULL accepted) 158 | * @return On success, 0 is returned 159 | * @return On error, a negative errno code is returned */ 160 | __api int iio_context_get_version(const struct iio_context *ctx, 161 | unsigned int *major, unsigned int *minor, char git_tag[8]); 162 | 163 | 164 | /** @brief Obtain a XML representation of the given context 165 | * @param ctx A pointer to an iio_context structure 166 | * @return A pointer to a static NULL-terminated string */ 167 | __api __pure const char * iio_context_get_xml(const struct iio_context *ctx); 168 | 169 | 170 | /** @brief Get the name of the given context 171 | * @param ctx A pointer to an iio_context structure 172 | * @return A pointer to a static NULL-terminated string 173 | * 174 | * NOTE:The returned string will be local, 175 | * xml or network when the context has been 176 | * created with the local, xml and network backends respectively.*/ 177 | __api __pure const char * iio_context_get_name(const struct iio_context *ctx); 178 | 179 | 180 | /** @brief Get a description of the given context 181 | * @param ctx A pointer to an iio_context structure 182 | * @return A pointer to a static NULL-terminated string 183 | * 184 | * NOTE:The returned string will contain human-readable information about 185 | * the current context. */ 186 | __api __pure const char * iio_context_get_description( 187 | const struct iio_context *ctx); 188 | 189 | 190 | /** @brief Enumerate the devices found in the given context 191 | * @param ctx A pointer to an iio_context structure 192 | * @return The number of devices found */ 193 | __api __pure unsigned int iio_context_get_devices_count( 194 | const struct iio_context *ctx); 195 | 196 | 197 | /** @brief Get the device present at the given index 198 | * @param ctx A pointer to an iio_context structure 199 | * @param index The index corresponding to the device 200 | * @return On success, a pointer to an iio_device structure 201 | * @return If the index is invalid, NULL is returned */ 202 | __api __pure struct iio_device * iio_context_get_device( 203 | const struct iio_context *ctx, unsigned int index); 204 | 205 | 206 | /** @brief Try to find a device structure by its name of ID 207 | * @param ctx A pointer to an iio_context structure 208 | * @param name A NULL-terminated string corresponding to the name or the ID of 209 | * the device to search for 210 | * @return On success, a pointer to an iio_device structure 211 | * @return If the name or ID does not correspond to any known device, NULL is 212 | * returned */ 213 | __api __pure struct iio_device * iio_context_find_device( 214 | const struct iio_context *ctx, const char *name); 215 | 216 | 217 | /** @brief Set a timeout for I/O operations 218 | * @param ctx A pointer to an iio_context structure 219 | * @param timeout_ms A positive integer representing the time in milliseconds 220 | * after which a timeout occurs 221 | * @return On success, 0 is returned 222 | * @return On error, a negative errno code is returned */ 223 | __api int iio_context_set_timeout( 224 | struct iio_context *ctx, unsigned int timeout_ms); 225 | 226 | 227 | /** @} *//* ------------------------------------------------------------------*/ 228 | /* ------------------------- Device functions --------------------------------*/ 229 | /** @defgroup Device Device 230 | * @{ 231 | * @struct iio_device 232 | * @brief Represents a device in the IIO context */ 233 | 234 | 235 | /** @brief Retrieve a pointer to the iio_context structure 236 | * @param dev A pointer to an iio_device structure 237 | * @return A pointer to an iio_context structure */ 238 | __api __pure const struct iio_context * iio_device_get_context( 239 | const struct iio_device *dev); 240 | 241 | 242 | /** @brief Retrieve the device ID (e.g. iio:device0) 243 | * @param dev A pointer to an iio_device structure 244 | * @return A pointer to a static NULL-terminated string */ 245 | __api __pure const char * iio_device_get_id(const struct iio_device *dev); 246 | 247 | 248 | /** @brief Retrieve the device name (e.g. xadc) 249 | * @param dev A pointer to an iio_device structure 250 | * @return A pointer to a static NULL-terminated string 251 | * 252 | * NOTE: if the device has no name, NULL is returned. */ 253 | __api __pure const char * iio_device_get_name(const struct iio_device *dev); 254 | 255 | 256 | /** @brief Enumerate the channels of the given device 257 | * @param dev A pointer to an iio_device structure 258 | * @return The number of channels found */ 259 | __api __pure unsigned int iio_device_get_channels_count( 260 | const struct iio_device *dev); 261 | 262 | 263 | /** @brief Enumerate the device-specific attributes of the given device 264 | * @param dev A pointer to an iio_device structure 265 | * @return The number of device-specific attributes found */ 266 | __api __pure unsigned int iio_device_get_attrs_count( 267 | const struct iio_device *dev); 268 | 269 | 270 | /** @brief Get the channel present at the given index 271 | * @param dev A pointer to an iio_device structure 272 | * @param index The index corresponding to the channel 273 | * @return On success, a pointer to an iio_channel structure 274 | * @return If the index is invalid, NULL is returned */ 275 | __api __pure struct iio_channel * iio_device_get_channel( 276 | const struct iio_device *dev, unsigned int index); 277 | 278 | 279 | /** @brief Get the device-specific attribute present at the given index 280 | * @param dev A pointer to an iio_device structure 281 | * @param index The index corresponding to the attribute 282 | * @return On success, a pointer to a static NULL-terminated string 283 | * @return If the index is invalid, NULL is returned */ 284 | __api __pure const char * iio_device_get_attr( 285 | const struct iio_device *dev, unsigned int index); 286 | 287 | 288 | /** @brief Try to find a channel structure by its name of ID 289 | * @param dev A pointer to an iio_device structure 290 | * @param name A NULL-terminated string corresponding to the name or the ID of 291 | * the channel to search for 292 | * @param output True if the searched channel is output, False otherwise 293 | * @return On success, a pointer to an iio_channel structure 294 | * @return If the name or ID does not correspond to any known channel of the 295 | * given device, NULL is returned */ 296 | __api __pure struct iio_channel * iio_device_find_channel( 297 | const struct iio_device *dev, const char *name, bool output); 298 | 299 | 300 | /** @brief Try to find a device-specific attribute by its name 301 | * @param dev A pointer to an iio_device structure 302 | * @param name A NULL-terminated string corresponding to the name of the 303 | * attribute 304 | * @return On success, a pointer to a static NULL-terminated string 305 | * @return If the name does not correspond to any known attribute of the given 306 | * device, NULL is returned 307 | * 308 | * NOTE: This function is useful to detect the presence of an attribute. 309 | * It can also be used to retrieve the name of an attribute as a pointer to a 310 | * static string from a dynamically allocated string. */ 311 | __api __pure const char * iio_device_find_attr( 312 | const struct iio_device *dev, const char *name); 313 | 314 | 315 | /** @brief Read the content of the given device-specific attribute 316 | * @param dev A pointer to an iio_device structure 317 | * @param attr A NULL-terminated string corresponding to the name of the 318 | * attribute 319 | * @param dst A pointer to the memory area where the NULL-terminated string 320 | * corresponding to the value read will be stored 321 | * @param len The available length of the memory area, in bytes 322 | * @return On success, the number of bytes written to the buffer 323 | * @return On error, a negative errno code is returned 324 | * 325 | * NOTE:By passing NULL as the "attr" argument to iio_device_attr_read, 326 | * it is now possible to read all of the attributes of a device. 327 | * 328 | * The buffer is filled with one block of data per attribute of the device, 329 | * by the order they appear in the iio_device structure. 330 | * 331 | * The first four bytes of one block correspond to a 32-bit signed value in 332 | * network order. If negative, it corresponds to the errno code that were 333 | * returned when reading the attribute; if positive, it corresponds to the 334 | * length of the data read. In that case, the rest of the block contains 335 | * the data. */ 336 | __api ssize_t iio_device_attr_read(const struct iio_device *dev, 337 | const char *attr, char *dst, size_t len); 338 | 339 | 340 | /** @brief Read the content of all device-specific attributes 341 | * @param dev A pointer to an iio_device structure 342 | * @param cb A pointer to a callback function 343 | * @param data A pointer that will be passed to the callback function 344 | * @return On success, 0 is returned 345 | * @return On error, a negative errno code is returned 346 | * 347 | * NOTE: This function is especially useful when used with the network 348 | * backend, as all the device-specific attributes are read in one single 349 | * command. */ 350 | __api int iio_device_attr_read_all(struct iio_device *dev, 351 | int (*cb)(struct iio_device *dev, const char *attr, 352 | const char *value, size_t len, void *d), 353 | void *data); 354 | 355 | 356 | /** @brief Read the content of the given device-specific attribute 357 | * @param dev A pointer to an iio_device structure 358 | * @param attr A NULL-terminated string corresponding to the name of the 359 | * attribute 360 | * @param val A pointer to a bool variable where the value should be stored 361 | * @return On success, 0 is returned 362 | * @return On error, a negative errno code is returned */ 363 | __api int iio_device_attr_read_bool(const struct iio_device *dev, 364 | const char *attr, bool *val); 365 | 366 | 367 | /** @brief Read the content of the given device-specific attribute 368 | * @param dev A pointer to an iio_device structure 369 | * @param attr A NULL-terminated string corresponding to the name of the 370 | * attribute 371 | * @param val A pointer to a long long variable where the value should be stored 372 | * @return On success, 0 is returned 373 | * @return On error, a negative errno code is returned */ 374 | __api int iio_device_attr_read_longlong(const struct iio_device *dev, 375 | const char *attr, long long *val); 376 | 377 | 378 | /** @brief Read the content of the given device-specific attribute 379 | * @param dev A pointer to an iio_device structure 380 | * @param attr A NULL-terminated string corresponding to the name of the 381 | * attribute 382 | * @param val A pointer to a double variable where the value should be stored 383 | * @return On success, 0 is returned 384 | * @return On error, a negative errno code is returned */ 385 | __api int iio_device_attr_read_double(const struct iio_device *dev, 386 | const char *attr, double *val); 387 | 388 | 389 | /** @brief Set the value of the given device-specific attribute 390 | * @param dev A pointer to an iio_device structure 391 | * @param attr A NULL-terminated string corresponding to the name of the 392 | * attribute 393 | * @param src A NULL-terminated string to set the attribute to 394 | * @return On success, the number of bytes written 395 | * @return On error, a negative errno code is returned 396 | * 397 | * NOTE:By passing NULL as the "attr" argument to iio_device_attr_write, 398 | * it is now possible to write all of the attributes of a device. 399 | * 400 | * The buffer must contain one block of data per attribute of the device, 401 | * by the order they appear in the iio_device structure. 402 | * 403 | * The first four bytes of one block correspond to a 32-bit signed value in 404 | * network order. If negative, the attribute is not written; if positive, 405 | * it corresponds to the length of the data to write. In that case, the rest 406 | * of the block must contain the data. */ 407 | __api ssize_t iio_device_attr_write(const struct iio_device *dev, 408 | const char *attr, const char *src); 409 | 410 | 411 | /** @brief Set the value of the given device-specific attribute 412 | * @param dev A pointer to an iio_device structure 413 | * @param attr A NULL-terminated string corresponding to the name of the 414 | * attribute 415 | * @param src A pointer to the data to be written 416 | * @param len The number of bytes that should be written 417 | * @return On success, the number of bytes written 418 | * @return On error, a negative errno code is returned */ 419 | __api ssize_t iio_device_attr_write_raw(const struct iio_device *dev, 420 | const char *attr, const void *src, size_t len); 421 | 422 | 423 | /** @brief Set the values of all device-specific attributes 424 | * @param dev A pointer to an iio_device structure 425 | * @param cb A pointer to a callback function 426 | * @param data A pointer that will be passed to the callback function 427 | * @return On success, 0 is returned 428 | * @return On error, a negative errno code is returned 429 | * 430 | * NOTE: This function is especially useful when used with the network 431 | * backend, as all the device-specific attributes are written in one single 432 | * command. */ 433 | __api int iio_device_attr_write_all(struct iio_device *dev, 434 | ssize_t (*cb)(struct iio_device *dev, 435 | const char *attr, void *buf, size_t len, void *d), 436 | void *data); 437 | 438 | 439 | /** @brief Set the value of the given device-specific attribute 440 | * @param dev A pointer to an iio_device structure 441 | * @param attr A NULL-terminated string corresponding to the name of the 442 | * attribute 443 | * @param val A bool value to set the attribute to 444 | * @return On success, 0 is returned 445 | * @return On error, a negative errno code is returned */ 446 | __api int iio_device_attr_write_bool(const struct iio_device *dev, 447 | const char *attr, bool val); 448 | 449 | 450 | /** @brief Set the value of the given device-specific attribute 451 | * @param dev A pointer to an iio_device structure 452 | * @param attr A NULL-terminated string corresponding to the name of the 453 | * attribute 454 | * @param val A long long value to set the attribute to 455 | * @return On success, 0 is returned 456 | * @return On error, a negative errno code is returned */ 457 | __api int iio_device_attr_write_longlong(const struct iio_device *dev, 458 | const char *attr, long long val); 459 | 460 | 461 | /** @brief Set the value of the given device-specific attribute 462 | * @param dev A pointer to an iio_device structure 463 | * @param attr A NULL-terminated string corresponding to the name of the 464 | * attribute 465 | * @param val A double value to set the attribute to 466 | * @return On success, 0 is returned 467 | * @return On error, a negative errno code is returned */ 468 | __api int iio_device_attr_write_double(const struct iio_device *dev, 469 | const char *attr, double val); 470 | 471 | 472 | /** @brief Associate a pointer to an iio_device structure 473 | * @param dev A pointer to an iio_device structure 474 | * @param data The pointer to be associated */ 475 | __api void iio_device_set_data(struct iio_device *dev, void *data); 476 | 477 | 478 | /** @brief Retrieve a previously associated pointer of an iio_device structure 479 | * @param dev A pointer to an iio_device structure 480 | * @return The pointer previously associated if present, or NULL */ 481 | __api void * iio_device_get_data(const struct iio_device *dev); 482 | 483 | 484 | /** @brief Retrieve the trigger of a given device 485 | * @param dev A pointer to an iio_device structure 486 | * @param trigger a pointer to a pointer of an iio_device structure. The pointed 487 | * pointer will be set to the address of the iio_device structure corresponding 488 | * to the associated trigger device. 489 | * @return On success, 0 is returned 490 | * @return On error, a negative errno code is returned */ 491 | __api int iio_device_get_trigger(const struct iio_device *dev, 492 | const struct iio_device **trigger); 493 | 494 | 495 | /** @brief Associate a trigger to a given device 496 | * @param dev A pointer to an iio_device structure 497 | * @param trigger a pointer to the iio_device structure corresponding to the 498 | * trigger that should be associated. 499 | * @return On success, 0 is returned 500 | * @return On error, a negative errno code is returned */ 501 | __api int iio_device_set_trigger(const struct iio_device *dev, 502 | const struct iio_device *trigger); 503 | 504 | 505 | /** @brief Return True if the given device is a trigger 506 | * @param dev A pointer to an iio_device structure 507 | * @return True if the device is a trigger, False otherwise */ 508 | __api __pure bool iio_device_is_trigger(const struct iio_device *dev); 509 | 510 | 511 | /** @} *//* ------------------------------------------------------------------*/ 512 | /* ------------------------- Channel functions -------------------------------*/ 513 | /** @defgroup Channel Channel 514 | * @{ 515 | * @struct iio_channel 516 | * @brief Represents an input or output channel of a device */ 517 | 518 | 519 | /** @brief Retrieve a pointer to the iio_device structure 520 | * @param chn A pointer to an iio_channel structure 521 | * @return A pointer to an iio_device structure */ 522 | __api __pure const struct iio_device * iio_channel_get_device( 523 | const struct iio_channel *chn); 524 | 525 | 526 | /** @brief Retrieve the channel ID (e.g. voltage0) 527 | * @param chn A pointer to an iio_channel structure 528 | * @return A pointer to a static NULL-terminated string */ 529 | __api __pure const char * iio_channel_get_id(const struct iio_channel *chn); 530 | 531 | 532 | /** @brief Retrieve the channel name (e.g. vccint) 533 | * @param chn A pointer to an iio_channel structure 534 | * @return A pointer to a static NULL-terminated string 535 | * 536 | * NOTE: if the channel has no name, NULL is returned. */ 537 | __api __pure const char * iio_channel_get_name(const struct iio_channel *chn); 538 | 539 | 540 | /** @brief Return True if the given channel is an output channel 541 | * @param chn A pointer to an iio_channel structure 542 | * @return True if the channel is an output channel, False otherwise */ 543 | __api __pure bool iio_channel_is_output(const struct iio_channel *chn); 544 | 545 | 546 | /** @brief Return True if the given channel is a scan element 547 | * @param chn A pointer to an iio_channel structure 548 | * @return True if the channel is a scan element, False otherwise 549 | * 550 | * NOTE: a channel that is a scan element is a channel that can 551 | * generate samples (for an input channel) or receive samples (for an output 552 | * channel) after being enabled. */ 553 | __api __pure bool iio_channel_is_scan_element(const struct iio_channel *chn); 554 | 555 | 556 | /** @brief Enumerate the channel-specific attributes of the given channel 557 | * @param chn A pointer to an iio_channel structure 558 | * @return The number of channel-specific attributes found */ 559 | __api __pure unsigned int iio_channel_get_attrs_count( 560 | const struct iio_channel *chn); 561 | 562 | 563 | /** @brief Get the channel-specific attribute present at the given index 564 | * @param chn A pointer to an iio_channel structure 565 | * @param index The index corresponding to the attribute 566 | * @return On success, a pointer to a static NULL-terminated string 567 | * @return If the index is invalid, NULL is returned */ 568 | __api __pure const char * iio_channel_get_attr( 569 | const struct iio_channel *chn, unsigned int index); 570 | 571 | 572 | /** @brief Try to find a channel-specific attribute by its name 573 | * @param chn A pointer to an iio_channel structure 574 | * @param name A NULL-terminated string corresponding to the name of the 575 | * attribute 576 | * @return On success, a pointer to a static NULL-terminated string 577 | * @return If the name does not correspond to any known attribute of the given 578 | * channel, NULL is returned 579 | * 580 | * NOTE: This function is useful to detect the presence of an attribute. 581 | * It can also be used to retrieve the name of an attribute as a pointer to a 582 | * static string from a dynamically allocated string. */ 583 | __api __pure const char * iio_channel_find_attr( 584 | const struct iio_channel *chn, const char *name); 585 | 586 | 587 | /** @brief Retrieve the filename of an attribute 588 | * @param chn A pointer to an iio_channel structure 589 | * @param attr a NULL-terminated string corresponding to the name of the 590 | * attribute 591 | * @return On success, a pointer to a static NULL-terminated string 592 | * @return If the attribute name is unknown, NULL is returned */ 593 | __api __pure const char * iio_channel_attr_get_filename( 594 | const struct iio_channel *chn, const char *attr); 595 | 596 | 597 | /** @brief Read the content of the given channel-specific attribute 598 | * @param chn A pointer to an iio_channel structure 599 | * @param attr A NULL-terminated string corresponding to the name of the 600 | * attribute 601 | * @param dst A pointer to the memory area where the NULL-terminated string 602 | * corresponding to the value read will be stored 603 | * @param len The available length of the memory area, in bytes 604 | * @return On success, the number of bytes written to the buffer 605 | * @return On error, a negative errno code is returned 606 | * 607 | * NOTE:By passing NULL as the "attr" argument to iio_channel_attr_read, 608 | * it is now possible to read all of the attributes of a channel. 609 | * 610 | * The buffer is filled with one block of data per attribute of the channel, 611 | * by the order they appear in the iio_channel structure. 612 | * 613 | * The first four bytes of one block correspond to a 32-bit signed value in 614 | * network order. If negative, it corresponds to the errno code that were 615 | * returned when reading the attribute; if positive, it corresponds to the 616 | * length of the data read. In that case, the rest of the block contains 617 | * the data. */ 618 | __api ssize_t iio_channel_attr_read(const struct iio_channel *chn, 619 | const char *attr, char *dst, size_t len); 620 | 621 | 622 | /** @brief Read the content of all channel-specific attributes 623 | * @param chn A pointer to an iio_channel structure 624 | * @param cb A pointer to a callback function 625 | * @param data A pointer that will be passed to the callback function 626 | * @return On success, 0 is returned 627 | * @return On error, a negative errno code is returned 628 | * 629 | * NOTE: This function is especially useful when used with the network 630 | * backend, as all the channel-specific attributes are read in one single 631 | * command. */ 632 | __api int iio_channel_attr_read_all(struct iio_channel *chn, 633 | int (*cb)(struct iio_channel *chn, 634 | const char *attr, const char *val, size_t len, void *d), 635 | void *data); 636 | 637 | 638 | /** @brief Read the content of the given channel-specific attribute 639 | * @param chn A pointer to an iio_channel structure 640 | * @param attr A NULL-terminated string corresponding to the name of the 641 | * attribute 642 | * @param val A pointer to a bool variable where the value should be stored 643 | * @return On success, 0 is returned 644 | * @return On error, a negative errno code is returned */ 645 | __api int iio_channel_attr_read_bool(const struct iio_channel *chn, 646 | const char *attr, bool *val); 647 | 648 | 649 | /** @brief Read the content of the given channel-specific attribute 650 | * @param chn A pointer to an iio_channel structure 651 | * @param attr A NULL-terminated string corresponding to the name of the 652 | * attribute 653 | * @param val A pointer to a long long variable where the value should be stored 654 | * @return On success, 0 is returned 655 | * @return On error, a negative errno code is returned */ 656 | __api int iio_channel_attr_read_longlong(const struct iio_channel *chn, 657 | const char *attr, long long *val); 658 | 659 | 660 | /** @brief Read the content of the given channel-specific attribute 661 | * @param chn A pointer to an iio_channel structure 662 | * @param attr A NULL-terminated string corresponding to the name of the 663 | * attribute 664 | * @param val A pointer to a double variable where the value should be stored 665 | * @return On success, 0 is returned 666 | * @return On error, a negative errno code is returned */ 667 | __api int iio_channel_attr_read_double(const struct iio_channel *chn, 668 | const char *attr, double *val); 669 | 670 | 671 | /** @brief Set the value of the given channel-specific attribute 672 | * @param chn A pointer to an iio_channel structure 673 | * @param attr A NULL-terminated string corresponding to the name of the 674 | * attribute 675 | * @param src A NULL-terminated string to set the attribute to 676 | * @return On success, the number of bytes written 677 | * @return On error, a negative errno code is returned 678 | * 679 | * NOTE:By passing NULL as the "attr" argument to iio_channel_attr_write, 680 | * it is now possible to write all of the attributes of a channel. 681 | * 682 | * The buffer must contain one block of data per attribute of the channel, 683 | * by the order they appear in the iio_channel structure. 684 | * 685 | * The first four bytes of one block correspond to a 32-bit signed value in 686 | * network order. If negative, the attribute is not written; if positive, 687 | * it corresponds to the length of the data to write. In that case, the rest 688 | * of the block must contain the data. */ 689 | __api ssize_t iio_channel_attr_write(const struct iio_channel *chn, 690 | const char *attr, const char *src); 691 | 692 | 693 | /** @brief Set the value of the given channel-specific attribute 694 | * @param chn A pointer to an iio_channel structure 695 | * @param attr A NULL-terminated string corresponding to the name of the 696 | * attribute 697 | * @param src A pointer to the data to be written 698 | * @param len The number of bytes that should be written 699 | * @return On success, the number of bytes written 700 | * @return On error, a negative errno code is returned */ 701 | __api ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn, 702 | const char *attr, const void *src, size_t len); 703 | 704 | 705 | /** @brief Set the values of all channel-specific attributes 706 | * @param chn A pointer to an iio_channel structure 707 | * @param cb A pointer to a callback function 708 | * @param data A pointer that will be passed to the callback function 709 | * @return On success, 0 is returned 710 | * @return On error, a negative errno code is returned 711 | * 712 | * NOTE: This function is especially useful when used with the network 713 | * backend, as all the channel-specific attributes are written in one single 714 | * command. */ 715 | __api int iio_channel_attr_write_all(struct iio_channel *chn, 716 | ssize_t (*cb)(struct iio_channel *chn, 717 | const char *attr, void *buf, size_t len, void *d), 718 | void *data); 719 | 720 | 721 | /** @brief Set the value of the given channel-specific attribute 722 | * @param chn A pointer to an iio_channel structure 723 | * @param attr A NULL-terminated string corresponding to the name of the 724 | * attribute 725 | * @param val A bool value to set the attribute to 726 | * @return On success, 0 is returned 727 | * @return On error, a negative errno code is returned */ 728 | __api int iio_channel_attr_write_bool(const struct iio_channel *chn, 729 | const char *attr, bool val); 730 | 731 | 732 | /** @brief Set the value of the given channel-specific attribute 733 | * @param chn A pointer to an iio_channel structure 734 | * @param attr A NULL-terminated string corresponding to the name of the 735 | * attribute 736 | * @param val A long long value to set the attribute to 737 | * @return On success, 0 is returned 738 | * @return On error, a negative errno code is returned */ 739 | __api int iio_channel_attr_write_longlong(const struct iio_channel *chn, 740 | const char *attr, long long val); 741 | 742 | 743 | /** @brief Set the value of the given channel-specific attribute 744 | * @param chn A pointer to an iio_channel structure 745 | * @param attr A NULL-terminated string corresponding to the name of the 746 | * attribute 747 | * @param val A double value to set the attribute to 748 | * @return On success, 0 is returned 749 | * @return On error, a negative errno code is returned */ 750 | __api int iio_channel_attr_write_double(const struct iio_channel *chn, 751 | const char *attr, double val); 752 | 753 | 754 | /** @brief Enable the given channel 755 | * @param chn A pointer to an iio_channel structure 756 | * 757 | * NOTE:Before creating an iio_buffer structure with 758 | * iio_device_create_buffer, it is required to enable at least one channel of 759 | * the device to read from. */ 760 | __api void iio_channel_enable(struct iio_channel *chn); 761 | 762 | 763 | /** @brief Disable the given channel 764 | * @param chn A pointer to an iio_channel structure */ 765 | __api void iio_channel_disable(struct iio_channel *chn); 766 | 767 | 768 | /** @brief Returns True if the channel is enabled 769 | * @param chn A pointer to an iio_channel structure 770 | * @return True if the channel is enabled, False otherwise */ 771 | __api bool iio_channel_is_enabled(const struct iio_channel *chn); 772 | 773 | 774 | /** Demultiplex the samples of a given channel 775 | * @param chn A pointer to an iio_channel structure 776 | * @param buffer A pointer to an iio_buffer structure 777 | * @param dst A pointer to the memory area where the demultiplexed data will be 778 | * stored 779 | * @param len The available length of the memory area, in bytes 780 | * @return The size of the demultiplexed data, in bytes */ 781 | __api size_t iio_channel_read_raw(const struct iio_channel *chn, 782 | struct iio_buffer *buffer, void *dst, size_t len); 783 | 784 | 785 | /** Demultiplex and convert the samples of a given channel 786 | * @param chn A pointer to an iio_channel structure 787 | * @param buffer A pointer to an iio_buffer structure 788 | * @param dst A pointer to the memory area where the converted data will be 789 | * stored 790 | * @param len The available length of the memory area, in bytes 791 | * @return The size of the converted data, in bytes */ 792 | __api size_t iio_channel_read(const struct iio_channel *chn, 793 | struct iio_buffer *buffer, void *dst, size_t len); 794 | 795 | 796 | /** Multiplex the samples of a given channel 797 | * @param chn A pointer to an iio_channel structure 798 | * @param buffer A pointer to an iio_buffer structure 799 | * @param src A pointer to the memory area where the sequential data will 800 | * be read from 801 | * @param len The length of the memory area, in bytes 802 | * @return The number of bytes actually multiplexed */ 803 | __api size_t iio_channel_write_raw(const struct iio_channel *chn, 804 | struct iio_buffer *buffer, const void *src, size_t len); 805 | 806 | 807 | /** Convert and multiplex the samples of a given channel 808 | * @param chn A pointer to an iio_channel structure 809 | * @param buffer A pointer to an iio_buffer structure 810 | * @param src A pointer to the memory area where the sequential data will 811 | * be read from 812 | * @param len The length of the memory area, in bytes 813 | * @return The number of bytes actually converted and multiplexed */ 814 | __api size_t iio_channel_write(const struct iio_channel *chn, 815 | struct iio_buffer *buffer, const void *src, size_t len); 816 | 817 | 818 | /** @brief Associate a pointer to an iio_channel structure 819 | * @param chn A pointer to an iio_channel structure 820 | * @param data The pointer to be associated */ 821 | __api void iio_channel_set_data(struct iio_channel *chn, void *data); 822 | 823 | 824 | /** @brief Retrieve a previously associated pointer of an iio_channel structure 825 | * @param chn A pointer to an iio_channel structure 826 | * @return The pointer previously associated if present, or NULL */ 827 | __api void * iio_channel_get_data(const struct iio_channel *chn); 828 | 829 | 830 | /** @} *//* ------------------------------------------------------------------*/ 831 | /* ------------------------- Buffer functions --------------------------------*/ 832 | /** @defgroup Buffer Buffer 833 | * @{ 834 | * @struct iio_buffer 835 | * @brief An input or output buffer, used to read or write samples */ 836 | 837 | 838 | /** @brief Retrieve a pointer to the iio_device structure 839 | * @param buf A pointer to an iio_buffer structure 840 | * @return A pointer to an iio_device structure */ 841 | __api __pure const struct iio_device * iio_buffer_get_device( 842 | const struct iio_buffer *buf); 843 | 844 | 845 | /** @brief Create an input or output buffer associated to the given device 846 | * @param dev A pointer to an iio_device structure 847 | * @param samples_count The number of samples that the buffer should contain 848 | * @param cyclic If True, enable cyclic mode 849 | * @return On success, a pointer to an iio_buffer structure 850 | * @return On error, NULL is returned, and errno is set to the error code 851 | * 852 | * NOTE: Channels that have to be written to / read from must be enabled 853 | * before creating the buffer. */ 854 | __api struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev, 855 | size_t samples_count, bool cyclic); 856 | 857 | 858 | /** @brief Destroy the given buffer 859 | * @param buf A pointer to an iio_buffer structure 860 | * 861 | * NOTE: After that function, the iio_buffer pointer shall be invalid. */ 862 | __api void iio_buffer_destroy(struct iio_buffer *buf); 863 | 864 | 865 | /** @brief Fetch more samples from the hardware 866 | * @param buf A pointer to an iio_buffer structure 867 | * @return On success, the number of bytes read is returned 868 | * @return On error, a negative errno code is returned 869 | * 870 | * NOTE: Only valid for input buffers */ 871 | __api ssize_t iio_buffer_refill(struct iio_buffer *buf); 872 | 873 | 874 | /** @brief Send the samples to the hardware 875 | * @param buf A pointer to an iio_buffer structure 876 | * @return On success, the number of bytes written is returned 877 | * @return On error, a negative errno code is returned 878 | * 879 | * NOTE: Only valid for output buffers */ 880 | __api ssize_t iio_buffer_push(struct iio_buffer *buf); 881 | 882 | 883 | /** @brief Get the start address of the buffer 884 | * @param buf A pointer to an iio_buffer structure 885 | * @return A pointer corresponding to the start address of the buffer */ 886 | __api void * iio_buffer_start(const struct iio_buffer *buf); 887 | 888 | 889 | /** @brief Find the first sample of a channel in a buffer 890 | * @param buf A pointer to an iio_buffer structure 891 | * @param chn A pointer to an iio_channel structure 892 | * @return A pointer to the first sample found, or to the end of the buffer if 893 | * no sample for the given channel is present in the buffer 894 | * 895 | * NOTE: This fonction, coupled with iio_buffer_step and iio_buffer_end, 896 | * can be used to iterate on all the samples of a given channel present in the 897 | * buffer, doing the following: 898 | * 899 | * @verbatim 900 | for (void *ptr = iio_buffer_first(buffer, chn); ptr < iio_buffer_end(buffer); ptr += iio_buffer_step(buffer)) { 901 | .... 902 | } 903 | @endverbatim */ 904 | __api void * iio_buffer_first(const struct iio_buffer *buf, 905 | const struct iio_channel *chn); 906 | 907 | 908 | /** @brief Get the step size between two samples of one channel 909 | * @param buf A pointer to an iio_buffer structure 910 | * @return the difference between the addresses of two consecutive samples of 911 | * one same channel */ 912 | __api ptrdiff_t iio_buffer_step(const struct iio_buffer *buf); 913 | 914 | 915 | /** @brief Get the address that follows the last sample in a buffer 916 | * @param buf A pointer to an iio_buffer structure 917 | * @return A pointer corresponding to the address that follows the last sample 918 | * present in the buffer */ 919 | __api void * iio_buffer_end(const struct iio_buffer *buf); 920 | 921 | 922 | /** @brief Call the supplied callback for each sample found in a buffer 923 | * @param buf A pointer to an iio_buffer structure 924 | * @param callback A pointer to a function to call for each sample found 925 | * @param data A user-specified pointer that will be passed to the callback 926 | * 927 | * NOTE: The callback receives four arguments: 928 | * * A pointer to the iio_channel structure corresponding to the sample, 929 | * * A pointer to the sample itself, 930 | * * The length of the sample in bytes, 931 | * * The user-specified pointer passed to iio_buffer_foreach_sample. */ 932 | __api ssize_t iio_buffer_foreach_sample(struct iio_buffer *buf, 933 | ssize_t (*callback)(const struct iio_channel *chn, 934 | void *src, size_t bytes, void *d), void *data); 935 | 936 | 937 | /** @brief Associate a pointer to an iio_buffer structure 938 | * @param buf A pointer to an iio_buffer structure 939 | * @param data The pointer to be associated */ 940 | __api void iio_buffer_set_data(struct iio_buffer *buf, void *data); 941 | 942 | 943 | /** @brief Retrieve a previously associated pointer of an iio_buffer structure 944 | * @param buf A pointer to an iio_buffer structure 945 | * @return The pointer previously associated if present, or NULL */ 946 | __api void * iio_buffer_get_data(const struct iio_buffer *buf); 947 | 948 | 949 | /** @} *//* ------------------------------------------------------------------*/ 950 | /* ------------------------- Low-level functions -----------------------------*/ 951 | /** @defgroup Debug Debug and low-level functions 952 | * @{ 953 | * @struct iio_data_format 954 | * @brief Contains the format of a data sample. 955 | * 956 | * The different fields inform about the correct way to convert one sample from 957 | * its raw format (as read from / generated by the hardware) to its real-world 958 | * value. 959 | */ 960 | struct iio_data_format { 961 | /** @brief Total length of the sample, in bits */ 962 | unsigned int length; 963 | 964 | /** @brief Length of valuable data in the sample, in bits */ 965 | unsigned int bits; 966 | 967 | /** @brief Right-shift to apply when converting sample */ 968 | unsigned int shift; 969 | 970 | /** @brief Contains True if the sample is signed */ 971 | bool is_signed; 972 | 973 | /** @brief Contains True if the sample is fully defined, sign extended, etc. */ 974 | bool is_fully_defined; 975 | 976 | /** @brief Contains True if the sample is in big-endian format */ 977 | bool is_be; 978 | 979 | /** @brief Contains True if the sample should be scaled when converted */ 980 | bool with_scale; 981 | 982 | /** @brief Contains the scale to apply if with_scale is set */ 983 | double scale; 984 | }; 985 | 986 | 987 | /** @brief Get the current sample size 988 | * @param dev A pointer to an iio_device structure 989 | * @return On success, the sample size in bytes 990 | * @return On error, a negative errno code is returned 991 | * 992 | * NOTE: The sample size is not constant and will change when channels 993 | * get enabled or disabled. */ 994 | __api ssize_t iio_device_get_sample_size(const struct iio_device *dev); 995 | 996 | 997 | /** @brief Get the index of the given channel 998 | * @param chn A pointer to an iio_channel structure 999 | * @return On success, the index of the specified channel 1000 | * @return On error, a negative errno code is returned */ 1001 | __api __pure long iio_channel_get_index(const struct iio_channel *chn); 1002 | 1003 | 1004 | /** @brief Get a pointer to a channel's data format structure 1005 | * @param chn A pointer to an iio_channel structure 1006 | * @return A pointer to the channel's iio_data_format structure */ 1007 | __api __cnst const struct iio_data_format * iio_channel_get_data_format( 1008 | const struct iio_channel *chn); 1009 | 1010 | 1011 | /** @brief Convert the sample from hardware format to host format 1012 | * @param chn A pointer to an iio_channel structure 1013 | * @param dst A pointer to the destination buffer where the converted sample 1014 | * should be written 1015 | * @param src A pointer to the source buffer containing the sample */ 1016 | __api void iio_channel_convert(const struct iio_channel *chn, 1017 | void *dst, const void *src); 1018 | 1019 | 1020 | /** @brief Convert the sample from host format to hardware format 1021 | * @param chn A pointer to an iio_channel structure 1022 | * @param dst A pointer to the destination buffer where the converted sample 1023 | * should be written 1024 | * @param src A pointer to the source buffer containing the sample */ 1025 | __api void iio_channel_convert_inverse(const struct iio_channel *chn, 1026 | void *dst, const void *src); 1027 | 1028 | 1029 | /** @brief Enumerate the debug attributes of the given device 1030 | * @param dev A pointer to an iio_device structure 1031 | * @return The number of debug attributes found */ 1032 | __api __pure unsigned int iio_device_get_debug_attrs_count( 1033 | const struct iio_device *dev); 1034 | 1035 | 1036 | /** @brief Get the debug attribute present at the given index 1037 | * @param dev A pointer to an iio_device structure 1038 | * @param index The index corresponding to the debug attribute 1039 | * @return On success, a pointer to a static NULL-terminated string 1040 | * @return If the index is invalid, NULL is returned */ 1041 | __api __pure const char * iio_device_get_debug_attr( 1042 | const struct iio_device *dev, unsigned int index); 1043 | 1044 | 1045 | /** @brief Try to find a debug attribute by its name 1046 | * @param dev A pointer to an iio_device structure 1047 | * @param name A NULL-terminated string corresponding to the name of the 1048 | * debug attribute 1049 | * @return On success, a pointer to a static NULL-terminated string 1050 | * @return If the name does not correspond to any known debug attribute of the 1051 | * given device, NULL is returned 1052 | * 1053 | * NOTE: This function is useful to detect the presence of a debug 1054 | * attribute. 1055 | * It can also be used to retrieve the name of a debug attribute as a pointer 1056 | * to a static string from a dynamically allocated string. */ 1057 | __api __pure const char * iio_device_find_debug_attr( 1058 | const struct iio_device *dev, const char *name); 1059 | 1060 | 1061 | /** @brief Read the content of the given debug attribute 1062 | * @param dev A pointer to an iio_device structure 1063 | * @param attr A NULL-terminated string corresponding to the name of the 1064 | * debug attribute 1065 | * @param dst A pointer to the memory area where the NULL-terminated string 1066 | * corresponding to the value read will be stored 1067 | * @param len The available length of the memory area, in bytes 1068 | * @return On success, the number of bytes written to the buffer 1069 | * @return On error, a negative errno code is returned 1070 | * 1071 | * NOTE:By passing NULL as the "attr" argument to 1072 | * iio_device_debug_attr_read, it is now possible to read all of the debug 1073 | * attributes of a device. 1074 | * 1075 | * The buffer is filled with one block of data per debug attribute of the 1076 | * device, by the order they appear in the iio_device structure. 1077 | * 1078 | * The first four bytes of one block correspond to a 32-bit signed value in 1079 | * network order. If negative, it corresponds to the errno code that were 1080 | * returned when reading the debug attribute; if positive, it corresponds 1081 | * to the length of the data read. In that case, the rest of the block contains 1082 | * the data. */ 1083 | __api ssize_t iio_device_debug_attr_read(const struct iio_device *dev, 1084 | const char *attr, char *dst, size_t len); 1085 | 1086 | 1087 | /** @brief Read the content of all debug attributes 1088 | * @param dev A pointer to an iio_device structure 1089 | * @param cb A pointer to a callback function 1090 | * @param data A pointer that will be passed to the callback function 1091 | * @return On success, 0 is returned 1092 | * @return On error, a negative errno code is returned 1093 | * 1094 | * NOTE: This function is especially useful when used with the network 1095 | * backend, as all the debug attributes are read in one single command. */ 1096 | __api int iio_device_debug_attr_read_all(struct iio_device *dev, 1097 | int (*cb)(struct iio_device *dev, const char *attr, 1098 | const char *value, size_t len, void *d), 1099 | void *data); 1100 | 1101 | 1102 | /** @brief Set the value of the given debug attribute 1103 | * @param dev A pointer to an iio_device structure 1104 | * @param attr A NULL-terminated string corresponding to the name of the 1105 | * debug attribute 1106 | * @param src A NULL-terminated string to set the debug attribute to 1107 | * @return On success, the number of bytes written 1108 | * @return On error, a negative errno code is returned 1109 | * 1110 | * NOTE:By passing NULL as the "attr" argument to 1111 | * iio_device_debug_attr_write, it is now possible to write all of the 1112 | * debug attributes of a device. 1113 | * 1114 | * The buffer must contain one block of data per debug attribute of the device, 1115 | * by the order they appear in the iio_device structure. 1116 | * 1117 | * The first four bytes of one block correspond to a 32-bit signed value in 1118 | * network order. If negative, the debug attribute is not written; if positive, 1119 | * it corresponds to the length of the data to write. In that case, the rest 1120 | * of the block must contain the data. */ 1121 | __api ssize_t iio_device_debug_attr_write(const struct iio_device *dev, 1122 | const char *attr, const char *src); 1123 | 1124 | 1125 | /** @brief Set the value of the given debug attribute 1126 | * @param dev A pointer to an iio_device structure 1127 | * @param attr A NULL-terminated string corresponding to the name of the 1128 | * debug attribute 1129 | * @param src A pointer to the data to be written 1130 | * @param len The number of bytes that should be written 1131 | * @return On success, the number of bytes written 1132 | * @return On error, a negative errno code is returned */ 1133 | __api ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev, 1134 | const char *attr, const void *src, size_t len); 1135 | 1136 | 1137 | /** @brief Set the values of all debug attributes 1138 | * @param dev A pointer to an iio_device structure 1139 | * @param cb A pointer to a callback function 1140 | * @param data A pointer that will be passed to the callback function 1141 | * @return On success, 0 is returned 1142 | * @return On error, a negative errno code is returned 1143 | * 1144 | * NOTE: This function is especially useful when used with the network 1145 | * backend, as all the debug attributes are written in one single command. */ 1146 | __api int iio_device_debug_attr_write_all(struct iio_device *dev, 1147 | ssize_t (*cb)(struct iio_device *dev, 1148 | const char *attr, void *buf, size_t len, void *d), 1149 | void *data); 1150 | 1151 | 1152 | /** @brief Read the content of the given debug attribute 1153 | * @param dev A pointer to an iio_device structure 1154 | * @param attr A NULL-terminated string corresponding to the name of the 1155 | * debug attribute 1156 | * @param val A pointer to a bool variable where the value should be stored 1157 | * @return On success, 0 is returned 1158 | * @return On error, a negative errno code is returned */ 1159 | __api int iio_device_debug_attr_read_bool(const struct iio_device *dev, 1160 | const char *attr, bool *val); 1161 | 1162 | 1163 | /** @brief Read the content of the given debug attribute 1164 | * @param dev A pointer to an iio_device structure 1165 | * @param attr A NULL-terminated string corresponding to the name of the 1166 | * debug attribute 1167 | * @param val A pointer to a long long variable where the value should be stored 1168 | * @return On success, 0 is returned 1169 | * @return On error, a negative errno code is returned */ 1170 | __api int iio_device_debug_attr_read_longlong(const struct iio_device *dev, 1171 | const char *attr, long long *val); 1172 | 1173 | 1174 | /** @brief Read the content of the given debug attribute 1175 | * @param dev A pointer to an iio_device structure 1176 | * @param attr A NULL-terminated string corresponding to the name of the 1177 | * debug attribute 1178 | * @param val A pointer to a double variable where the value should be stored 1179 | * @return On success, 0 is returned 1180 | * @return On error, a negative errno code is returned */ 1181 | __api int iio_device_debug_attr_read_double(const struct iio_device *dev, 1182 | const char *attr, double *val); 1183 | 1184 | 1185 | /** @brief Set the value of the given debug attribute 1186 | * @param dev A pointer to an iio_device structure 1187 | * @param attr A NULL-terminated string corresponding to the name of the 1188 | * debug attribute 1189 | * @param val A bool value to set the debug attribute to 1190 | * @return On success, 0 is returned 1191 | * @return On error, a negative errno code is returned */ 1192 | __api int iio_device_debug_attr_write_bool(const struct iio_device *dev, 1193 | const char *attr, bool val); 1194 | 1195 | 1196 | /** @brief Set the value of the given debug attribute 1197 | * @param dev A pointer to an iio_device structure 1198 | * @param attr A NULL-terminated string corresponding to the name of the 1199 | * debug attribute 1200 | * @param val A long long value to set the debug attribute to 1201 | * @return On success, 0 is returned 1202 | * @return On error, a negative errno code is returned */ 1203 | __api int iio_device_debug_attr_write_longlong(const struct iio_device *dev, 1204 | const char *attr, long long val); 1205 | 1206 | 1207 | /** @brief Set the value of the given debug attribute 1208 | * @param dev A pointer to an iio_device structure 1209 | * @param attr A NULL-terminated string corresponding to the name of the 1210 | * debug attribute 1211 | * @param val A double value to set the debug attribute to 1212 | * @return On success, 0 is returned 1213 | * @return On error, a negative errno code is returned */ 1214 | __api int iio_device_debug_attr_write_double(const struct iio_device *dev, 1215 | const char *attr, double val); 1216 | 1217 | 1218 | /** @brief Identify the channel or debug attribute corresponding to a filename 1219 | * @param dev A pointer to an iio_device structure 1220 | * @param filename A NULL-terminated string corresponding to the filename 1221 | * @param chn A pointer to a pointer of an iio_channel structure. The pointed 1222 | * pointer will be set to the address of the iio_channel structure if the 1223 | * filename correspond to the attribute of a channel, or NULL otherwise. 1224 | * @param attr A pointer to a NULL-terminated string. The pointer 1225 | * pointer will be set to point to the name of the attribute corresponding to 1226 | * the filename. 1227 | * @return On success, 0 is returned, and *chn and *attr are modified. 1228 | * @return On error, a negative errno code is returned. *chn and *attr are not 1229 | * modified. */ 1230 | __api int iio_device_identify_filename(const struct iio_device *dev, 1231 | const char *filename, struct iio_channel **chn, 1232 | const char **attr); 1233 | 1234 | 1235 | /** @brief Set the value of a hardware register 1236 | * @param dev A pointer to an iio_device structure 1237 | * @param address The address of the register 1238 | * @param value The value to set the register to 1239 | * @return On success, 0 is returned 1240 | * @return On error, a negative errno code is returned */ 1241 | __api int iio_device_reg_write(struct iio_device *dev, 1242 | uint32_t address, uint32_t value); 1243 | 1244 | 1245 | /** @brief Get the value of a hardware register 1246 | * @param dev A pointer to an iio_device structure 1247 | * @param address The address of the register 1248 | * @param value A pointer to the variable where the value will be written 1249 | * @return On success, 0 is returned 1250 | * @return On error, a negative errno code is returned */ 1251 | __api int iio_device_reg_read(struct iio_device *dev, 1252 | uint32_t address, uint32_t *value); 1253 | 1254 | 1255 | /** @} */ 1256 | 1257 | #ifdef __cplusplus 1258 | } 1259 | #endif 1260 | 1261 | #endif /* __IIO_H__ */ 1262 | -------------------------------------------------------------------------------- /iio_sys_obj.m: -------------------------------------------------------------------------------- 1 | % Copyright 2014-15(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 | 35 | classdef iio_sys_obj < matlab.System & matlab.system.mixin.Propagates ... 36 | & matlab.system.mixin.CustomIcon 37 | % iio_sys_obj System Object block for IIO devices 38 | 39 | properties (Nontunable) 40 | % Public, non-tunable properties. 41 | 42 | %ip_address IP address 43 | ip_address = ''; 44 | 45 | %dev_name Device name 46 | dev_name = ''; 47 | 48 | %in_ch_no Number of input data channels 49 | in_ch_no = 0; 50 | 51 | %in_ch_size Input data channel size [samples] 52 | in_ch_size = 8192; 53 | 54 | %out_ch_no Number of output data channels 55 | out_ch_no = 0; 56 | 57 | %out_ch_size Output data channel size [samples] 58 | out_ch_size = 8192; 59 | end 60 | 61 | properties (Access = protected) 62 | % Protected class properties. 63 | 64 | %iio_dev_cfg Device configuration structure 65 | iio_dev_cfg = []; 66 | end 67 | 68 | properties (Access = private) 69 | % Private class properties. 70 | 71 | %libiio_data_in_dev libiio IIO interface object for the input data device 72 | libiio_data_in_dev = {}; 73 | 74 | %libiio_data_out_dev libiio IIO interface object for the output data device 75 | libiio_data_out_dev = {}; 76 | 77 | %libiio_ctrl_dev libiio IIO interface object for the control device 78 | libiio_ctrl_dev = {}; 79 | 80 | %sys_obj_initialized Holds the initialization status of the system object 81 | sys_obj_initialized = 0; 82 | end 83 | 84 | properties (DiscreteState) 85 | % Discrete state properties. 86 | 87 | %num_cfg_in Numeric type input control channels data 88 | num_cfg_in; 89 | 90 | %str_cfg_in String type input control channels data 91 | str_cfg_in; 92 | end 93 | 94 | methods 95 | %% Constructor 96 | function obj = iio_sys_obj(varargin) 97 | % Construct the libiio interface objects 98 | obj.libiio_data_in_dev = libiio_if(); 99 | obj.libiio_data_out_dev = libiio_if(); 100 | obj.libiio_ctrl_dev = libiio_if(); 101 | 102 | % Support name-value pair arguments when constructing the object. 103 | setProperties(obj,nargin,varargin{:}); 104 | end 105 | end 106 | 107 | methods (Access = protected) 108 | %% Utility functions 109 | 110 | function config = getObjConfig(obj) 111 | % Read the selected device configuration 112 | 113 | % Open the configuration file 114 | fname = sprintf('%s.cfg', obj.dev_name); 115 | fp_cfg = fopen(fname); 116 | if(fp_cfg < 0) 117 | config = {}; 118 | return; 119 | end 120 | 121 | % Build the object configuration structure 122 | config = struct('data_in_device', '',... % Pointer to the data input device 123 | 'data_out_device', '',... % Pointer to the data output device 124 | 'ctrl_device', '',... % Pointer to the control device 125 | 'cfg_ch', [],... % Configuration channels list 126 | 'mon_ch', []); % Monitoring channels list 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 | elseif(strcmp(strtrim(line{2}), 'OUT')) 155 | config.mon_ch = [config.mon_ch ch_cfg]; 156 | end 157 | elseif(~isempty(strfind(line, 'data_in_device'))) 158 | % Get the associated data input device 159 | idx = strfind(line, '='); 160 | tmp = line(idx+1:end); 161 | tmp = strtrim(tmp); 162 | config.data_in_device = tmp; 163 | elseif(~isempty(strfind(line, 'data_out_device'))) 164 | % Get the associated data output device 165 | idx = strfind(line, '='); 166 | tmp = line(idx+1:end); 167 | tmp = strtrim(tmp); 168 | config.data_out_device = tmp; 169 | elseif(~isempty(strfind(line, 'ctrl_device'))) 170 | % Get the associated control device 171 | idx = strfind(line, '='); 172 | tmp = line(idx+1:end); 173 | tmp = strtrim(tmp); 174 | config.ctrl_device = tmp; 175 | end 176 | end 177 | fclose(fp_cfg); 178 | end 179 | 180 | end 181 | 182 | methods (Access = protected) 183 | %% Common functions 184 | function setupImpl(obj) 185 | % Implement tasks that need to be performed only once. 186 | 187 | % Set the initialization status to fail 188 | obj.sys_obj_initialized = 0; 189 | 190 | % Read the object's configuration from the associated configuration file 191 | obj.iio_dev_cfg = getObjConfig(obj); 192 | if(isempty(obj.iio_dev_cfg)) 193 | msgbox('Could not read device configuration!', 'Error','error'); 194 | return; 195 | end 196 | 197 | % Initialize discrete-state properties. 198 | obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch)); 199 | obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64); 200 | 201 | % Initialize the libiio data input device 202 | if(obj.in_ch_no ~= 0) 203 | [ret, err_msg, msg_log] = init(obj.libiio_data_in_dev, obj.ip_address, ... 204 | obj.iio_dev_cfg.data_in_device, 'OUT', ... 205 | obj.in_ch_no, obj.in_ch_size); 206 | fprintf('%s', msg_log); 207 | if(ret < 0) 208 | msgbox(err_msg, 'Error','error'); 209 | return; 210 | end 211 | end 212 | 213 | % Initialize the libiio data output device 214 | if(obj.out_ch_no ~= 0) 215 | [ret, err_msg, msg_log] = init(obj.libiio_data_out_dev, obj.ip_address, ... 216 | obj.iio_dev_cfg.data_out_device, 'IN', ... 217 | obj.out_ch_no, obj.out_ch_size); 218 | fprintf('%s', msg_log); 219 | if(ret < 0) 220 | msgbox(err_msg, 'Error','error'); 221 | return; 222 | end 223 | end 224 | 225 | % Initialize the libiio control device 226 | if(~isempty(obj.iio_dev_cfg.ctrl_device)) 227 | [ret, err_msg, msg_log] = init(obj.libiio_ctrl_dev, obj.ip_address, ... 228 | obj.iio_dev_cfg.ctrl_device, '', ... 229 | 0, 0); 230 | fprintf('%s', msg_log); 231 | if(ret < 0) 232 | msgbox(err_msg, 'Error','error'); 233 | return; 234 | end 235 | end 236 | 237 | % Assign the control device for each monitoring channel 238 | for i = 1 : length(obj.iio_dev_cfg.mon_ch) 239 | if(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_in_device')) 240 | obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_in_dev; 241 | elseif(strcmp(obj.iio_dev_cfg.mon_ch(i).ctrl_dev_name, 'data_out_device')) 242 | obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_data_out_dev; 243 | else 244 | obj.iio_dev_cfg.mon_ch(i).ctrl_dev = obj.libiio_ctrl_dev; 245 | end 246 | end 247 | 248 | % Assign the control device for each configuration channel 249 | for i = 1 : length(obj.iio_dev_cfg.cfg_ch) 250 | if(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_in_device')) 251 | obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_in_dev; 252 | elseif(strcmp(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev_name, 'data_out_device')) 253 | obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_data_out_dev; 254 | else 255 | obj.iio_dev_cfg.cfg_ch(i).ctrl_dev = obj.libiio_ctrl_dev; 256 | end 257 | end 258 | 259 | % Set the initialization status to success 260 | obj.sys_obj_initialized = 1; 261 | end 262 | 263 | function releaseImpl(obj) 264 | % Release any resources used by the system object. 265 | obj.iio_dev_cfg = {}; 266 | delete(obj.libiio_data_in_dev); 267 | delete(obj.libiio_data_out_dev); 268 | delete(obj.libiio_ctrl_dev); 269 | end 270 | 271 | function varargout = stepImpl(obj, varargin) 272 | % Implement the system object's processing flow. 273 | varargout = cell(1, obj.out_ch_no + length(obj.iio_dev_cfg.mon_ch)); 274 | if(obj.sys_obj_initialized == 0) 275 | return; 276 | end 277 | 278 | % Implement the device configuration flow 279 | for i = 1 : length(obj.iio_dev_cfg.cfg_ch) 280 | if(~isempty(varargin{i + obj.in_ch_no})) 281 | if(length(varargin{i + obj.in_ch_no}) == 1) 282 | new_data = (varargin{i + obj.in_ch_no} ~= obj.num_cfg_in(i)); 283 | else 284 | new_data = ~strncmp(char(varargin{i + obj.in_ch_no}'), char(obj.str_cfg_in(i,:)), length(varargin{i + obj.in_ch_no})); 285 | end 286 | if(new_data == 1) 287 | if(length(varargin{i + obj.in_ch_no}) == 1) 288 | obj.num_cfg_in(i) = varargin{i + obj.in_ch_no}; 289 | str = num2str(obj.num_cfg_in(i)); 290 | else 291 | for j = 1:length(varargin{i + obj.in_ch_no}) 292 | obj.str_cfg_in(i,j) = varargin{i + obj.in_ch_no}(j); 293 | end 294 | obj.str_cfg_in(i,j+1) = 0; 295 | str = char(obj.str_cfg_in(i,:)); 296 | end 297 | writeAttributeString(obj.iio_dev_cfg.cfg_ch(i).ctrl_dev, obj.iio_dev_cfg.cfg_ch(i).port_attr, str); 298 | end 299 | end 300 | end 301 | 302 | % Implement the data transmit flow 303 | writeData(obj.libiio_data_in_dev, varargin); 304 | 305 | % Implement the data capture flow 306 | [~, data] = readData(obj.libiio_data_out_dev); 307 | for i = 1 : obj.out_ch_no 308 | varargout{i} = data{i}; 309 | end 310 | 311 | % Implement the parameters monitoring flow 312 | for i = 1 : length(obj.iio_dev_cfg.mon_ch) 313 | [~, val] = readAttributeDouble(obj.iio_dev_cfg.mon_ch(i).ctrl_dev, obj.iio_dev_cfg.mon_ch(i).port_attr); 314 | varargout{obj.out_ch_no + i} = val; 315 | end 316 | 317 | 318 | end 319 | 320 | function resetImpl(obj) 321 | % Initialize discrete-state properties. 322 | obj.num_cfg_in = zeros(1, length(obj.iio_dev_cfg.cfg_ch)); 323 | obj.str_cfg_in = zeros(length(obj.iio_dev_cfg.cfg_ch), 64); 324 | end 325 | 326 | function num = getNumInputsImpl(obj) 327 | % Get number of inputs. 328 | num = obj.in_ch_no; 329 | 330 | config = getObjConfig(obj); 331 | if(~isempty(config)) 332 | num = num + length(config.cfg_ch); 333 | end 334 | end 335 | 336 | function varargout = getInputNamesImpl(obj) 337 | % Get input names 338 | 339 | % Get the number of input data channels 340 | data_ch_no = obj.in_ch_no; 341 | 342 | % Get number of control channels 343 | cfg_ch_no = 0; 344 | config = getObjConfig(obj); 345 | if(~isempty(config)) 346 | cfg_ch_no = length(config.cfg_ch); 347 | end 348 | 349 | if(data_ch_no + cfg_ch_no ~= 0) 350 | varargout = cell(1, data_ch_no + cfg_ch_no); 351 | for i = 1 : data_ch_no 352 | varargout{i} = sprintf('DATA_IN%d', i); 353 | end 354 | for i = data_ch_no + 1 : data_ch_no + cfg_ch_no 355 | varargout{i} = config.cfg_ch(i - data_ch_no).port_name; 356 | end 357 | else 358 | varargout = {}; 359 | end 360 | end 361 | 362 | function num = getNumOutputsImpl(obj) 363 | % Get number of outputs. 364 | num = obj.out_ch_no; 365 | 366 | config = getObjConfig(obj); 367 | if(~isempty(config)) 368 | num = num + length(config.mon_ch); 369 | end 370 | end 371 | 372 | function varargout = getOutputNamesImpl(obj) 373 | % Get output names 374 | 375 | % Get the number of output data channels 376 | data_ch_no = obj.out_ch_no; 377 | 378 | % Get number of monitoring channels 379 | mon_ch_no = 0; 380 | config = getObjConfig(obj); 381 | if(~isempty(config)) 382 | mon_ch_no = length(config.mon_ch); 383 | end 384 | 385 | if(data_ch_no + mon_ch_no ~= 0) 386 | varargout = cell(1, data_ch_no + mon_ch_no); 387 | for i = 1 : data_ch_no 388 | varargout{i} = sprintf('DATA_OUT%d', i); 389 | end 390 | for i = data_ch_no + 1 : data_ch_no + mon_ch_no 391 | varargout{i} = config.mon_ch(i - data_ch_no).port_name; 392 | end 393 | else 394 | varargout = {}; 395 | end 396 | end 397 | 398 | function varargout = isOutputFixedSizeImpl(obj) 399 | % Get outputs fixed size. 400 | varargout = cell(1, getNumOutputs(obj)); 401 | for i = 1 : getNumOutputs(obj) 402 | varargout{i} = true; 403 | end 404 | end 405 | 406 | function varargout = getOutputDataTypeImpl(obj) 407 | % Get outputs data types. 408 | varargout = cell(1, getNumOutputs(obj)); 409 | for i = 1 : getNumOutputs(obj) 410 | varargout{i} = 'double'; 411 | end 412 | end 413 | 414 | function varargout = isOutputComplexImpl(obj) 415 | % Get outputs data types. 416 | varargout = cell(1, getNumOutputs(obj)); 417 | for i = 1 : getNumOutputs(obj) 418 | varargout{i} = false; 419 | end 420 | end 421 | 422 | function varargout = getOutputSizeImpl(obj) 423 | % Implement if input size does not match with output size. 424 | varargout = cell(1, getNumOutputs(obj)); 425 | for i = 1:obj.out_ch_no 426 | varargout{i} = [obj.out_ch_size 1]; 427 | end 428 | for i = obj.out_ch_no + 1 : length(varargout) 429 | varargout{i} = [1 1]; 430 | end 431 | end 432 | 433 | function icon = getIconImpl(obj) 434 | % Define a string as the icon for the System block in Simulink. 435 | if(~isempty(obj.dev_name)) 436 | icon = obj.dev_name; 437 | else 438 | icon = mfilename('class'); 439 | end 440 | end 441 | 442 | %% Backup/restore functions 443 | function s = saveObjectImpl(obj) 444 | % Save private, protected, or state properties in a 445 | % structure s. This is necessary to support Simulink 446 | % features, such as SimState. 447 | end 448 | 449 | function loadObjectImpl(obj, s, wasLocked) 450 | % Read private, protected, or state properties from 451 | % the structure s and assign it to the object obj. 452 | end 453 | 454 | %% Simulink functions 455 | function z = getDiscreteStateImpl(obj) 456 | % Return structure of states with field names as 457 | % DiscreteState properties. 458 | z = struct([]); 459 | end 460 | end 461 | 462 | methods(Static, Access = protected) 463 | %% Simulink customization functions 464 | function header = getHeaderImpl(obj) 465 | % Define header for the System block dialog box. 466 | header = matlab.system.display.Header(mfilename('class')); 467 | end 468 | 469 | function group = getPropertyGroupsImpl(obj) 470 | % Define section for properties in System block dialog box. 471 | group = matlab.system.display.Section(mfilename('class')); 472 | end 473 | end 474 | end 475 | -------------------------------------------------------------------------------- /iio_sys_obj_matlab.m: -------------------------------------------------------------------------------- 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 | 35 | classdef 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 | 350 | end 351 | end 352 | -------------------------------------------------------------------------------- /libiio_if.m: -------------------------------------------------------------------------------- 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 | 35 | classdef 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 | calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1}); 243 | is_scan_element = calllib(obj.libname, 'iio_channel_is_scan_element', obj.iio_channel{j+1}); 244 | if(is_scan_element == 1) 245 | obj.iio_scan_elm_no = obj.iio_scan_elm_no + 1; 246 | end 247 | end 248 | 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)]; 249 | 250 | % Check if the number of channels in the device 251 | % is greater or equal to the system object 252 | % input channels 253 | if(obj.iio_scan_elm_no < ch_no) 254 | obj.iio_channel = {}; 255 | err_msg = 'The selected device does not have enough output channels!'; 256 | return; 257 | end 258 | 259 | % Enable the DAC buffer output 260 | obj.if_initialized = 1; 261 | ret = writeAttributeString(obj, 'altvoltage0*raw', '0'); 262 | obj.if_initialized = 0; 263 | if(ret < 0) 264 | obj.iio_channel = {}; 265 | err_msg = 'Could not enable the DAC buffer output!'; 266 | return; 267 | end 268 | 269 | % Create the IIO buffer used to write data 270 | obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no; 271 | obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,... 272 | obj.data_ch_size, 1); 273 | end 274 | 275 | msg_log = [msg_log sprintf('%s: %s output data channels successfully initialized\n', class(obj), obj.dev_name)]; 276 | 277 | % Set the return code to success 278 | ret = 0; 279 | end 280 | 281 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 282 | %% Initializes the input data channels 283 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 284 | function [ret, err_msg, msg_log] = initInputDataChannels(obj, ch_no, ch_size) 285 | % Initialize the return values 286 | ret = -1; 287 | err_msg = ''; 288 | msg_log = []; 289 | 290 | % Save the number of channels and size 291 | obj.data_ch_no = ch_no; 292 | obj.data_ch_size = ch_size; 293 | 294 | % Get the number of channels that the device has 295 | nb_channels = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev); 296 | if(nb_channels == 0) 297 | err_msg = 'The selected device does not have any channels!'; 298 | return; 299 | end 300 | 301 | % Enable the system object output channels 302 | if(ch_no ~= 0) 303 | % Check if the device has input channels. The 304 | % logic here assumes that a device can have 305 | % only input or only output channels 306 | obj.iio_channel{1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, 0); 307 | is_output = calllib(obj.libname, 'iio_channel_is_output', obj.iio_channel{1}); 308 | if(is_output == 1) 309 | err_msg = 'The selected device does not have input channels!'; 310 | return; 311 | end 312 | msg_log = [msg_log sprintf('%s: Found %d input channels for the device %s\n', class(obj), nb_channels, obj.dev_name)]; 313 | 314 | % Check if the number of channels in the device 315 | % is greater or equal to the system object 316 | % output channels 317 | if(nb_channels < ch_no) 318 | obj.iio_channel = {}; 319 | err_msg = 'The selected device does not have enough input channels!'; 320 | return; 321 | end 322 | 323 | % Enable the channels 324 | for j = 0 : ch_no - 1 325 | obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j); 326 | calllib(obj.libname, 'iio_channel_enable', obj.iio_channel{j+1}); 327 | end 328 | for j = ch_no : nb_channels - 1 329 | obj.iio_channel{j+1} = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, j); 330 | calllib(obj.libname, 'iio_channel_disable', obj.iio_channel{j+1}); 331 | end 332 | % Create the IIO buffer used to read data 333 | obj.iio_buf_size = obj.data_ch_size * obj.data_ch_no; 334 | obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev, obj.iio_buf_size, 0); 335 | end 336 | 337 | msg_log = [msg_log sprintf('%s: %s input data channels successfully initialized\n', class(obj), obj.dev_name)]; 338 | 339 | % Set the return code to success 340 | ret = 0; 341 | end 342 | 343 | end 344 | 345 | 346 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 347 | %% Public methods 348 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 349 | methods 350 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 351 | %% Constructor 352 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353 | function obj = libiio_if() 354 | % Constructor 355 | obj.if_initialized = 0; 356 | end 357 | 358 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 359 | %% Destructor 360 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 361 | function delete(obj) 362 | % Release any resources used by the system object. 363 | if((obj.if_initialized == 1) && libisloaded(obj.libname)) 364 | if(~isempty(obj.iio_buffer)) 365 | calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer); 366 | end 367 | if(~isempty(obj.iio_ctx)) 368 | calllib(obj.libname, 'iio_context_destroy', obj.iio_ctx); 369 | end 370 | obj.iio_buffer = {}; 371 | obj.iio_channel = {}; 372 | obj.iio_dev = {}; 373 | obj.iio_ctx = {}; 374 | instCnt = libiio_if.modInstanceCnt(-1); 375 | if(instCnt == 0) 376 | unloadlibrary(obj.libname); 377 | end 378 | end 379 | end 380 | 381 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 382 | %% Initializes the libiio interface 383 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 384 | function [ret, err_msg, msg_log] = init(obj, ip_address, ... 385 | dev_name, dev_type, ... 386 | data_ch_no, data_ch_size) 387 | % Initialize the return values 388 | ret = -1; 389 | err_msg = ''; 390 | msg_log = []; 391 | 392 | % Save the device type 393 | obj.dev_type = dev_type; 394 | 395 | % Set the initialization status to fail 396 | obj.if_initialized = 0; 397 | 398 | % Load the libiio library 399 | if(~libisloaded(obj.libname)) 400 | try 401 | [notfound, warnings] = loadlibrary(obj.libname, obj.hname); 402 | catch exception 403 | err_msg = exception.message; 404 | return; 405 | end 406 | end 407 | 408 | if(~libisloaded(obj.libname)) 409 | err_msg = 'Could not load the libiio library!'; 410 | return; 411 | end 412 | 413 | % Create the network context 414 | [ret, err_msg, msg_log] = createNetworkContext(obj, ip_address); 415 | if(ret < 0) 416 | return; 417 | end 418 | 419 | % Check the software versions 420 | [ret, err_msg, msg_log_new] = checkVersions(obj); 421 | msg_log = [msg_log msg_log_new]; 422 | if(ret < 0) 423 | releaseContext(obj); 424 | return; 425 | end 426 | 427 | % Initialize the device 428 | [ret, err_msg, msg_log_new] = initDevice(obj, dev_name); 429 | msg_log = [msg_log msg_log_new]; 430 | if(ret < 0) 431 | releaseContext(obj); 432 | return; 433 | end 434 | 435 | % Initialize the output data channels 436 | if(strcmp(dev_type, 'OUT')) 437 | [ret, err_msg, msg_log_new] = initOutputDataChannels(obj, data_ch_no, data_ch_size); 438 | msg_log = [msg_log msg_log_new]; 439 | if(ret < 0) 440 | releaseContext(obj); 441 | return; 442 | end 443 | end 444 | 445 | % Initialize the input data channels 446 | if(strcmp(dev_type, 'IN')) 447 | [ret, err_msg, msg_log_new] = initInputDataChannels(obj, data_ch_no, data_ch_size); 448 | msg_log = [msg_log msg_log_new]; 449 | if(ret < 0) 450 | releaseContext(obj); 451 | return; 452 | end 453 | end 454 | 455 | % Set the initialization status to success 456 | obj.if_initialized = 1; 457 | end 458 | 459 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 460 | %% Implement the data capture flow 461 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 462 | function [ret, data] = readData(obj) 463 | % Initialize the return values 464 | ret = -1; 465 | data = cell(1, obj.data_ch_no); 466 | for i = 1 : obj.data_ch_no 467 | data{i} = zeros(obj.data_ch_size, 1); 468 | end 469 | 470 | % Check if the interface is initialized 471 | if(obj.if_initialized == 0) 472 | return; 473 | end 474 | 475 | % Check if the device type is output 476 | if(~strcmp(obj.dev_type, 'IN')) 477 | return; 478 | end 479 | 480 | % Read the data 481 | calllib(obj.libname, 'iio_buffer_refill', obj.iio_buffer); 482 | buffer = calllib(obj.libname, 'iio_buffer_first', obj.iio_buffer, obj.iio_channel{1}); 483 | setdatatype(buffer, 'int16Ptr', obj.iio_buf_size); 484 | for i = 1 : obj.data_ch_no 485 | data{i} = double(buffer.Value(i:obj.data_ch_no:end)); 486 | end 487 | 488 | % Set the return code to success 489 | ret = 0; 490 | end 491 | 492 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 493 | %% Implement the data transmit flow 494 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 495 | function ret = writeData(obj, data) 496 | % Initialize the return values 497 | ret = -1; 498 | 499 | % Check if the interface is initialized 500 | if(obj.if_initialized == 0) 501 | return; 502 | end 503 | 504 | % Check if the device type is input 505 | if(~strcmp(obj.dev_type, 'OUT')) 506 | return; 507 | end 508 | 509 | % Destroy the buffer 510 | calllib(obj.libname, 'iio_buffer_destroy', obj.iio_buffer); 511 | obj.iio_buffer = {}; 512 | 513 | % Enable the DAC buffer output 514 | ret = writeAttributeString(obj, 'altvoltage0*raw', '0'); 515 | if(ret < 0) 516 | obj.iio_channel = {}; 517 | err_msg = 'Could not enable the DAC buffer output!'; 518 | return; 519 | end 520 | 521 | % Create the IIO buffer used to write data 522 | obj.iio_buf_size = obj.data_ch_size * obj.iio_scan_elm_no; 523 | obj.iio_buffer = calllib(obj.libname, 'iio_device_create_buffer', obj.iio_dev,... 524 | obj.data_ch_size, 1); 525 | 526 | % Transmit the data 527 | buffer = calllib(obj.libname, 'iio_buffer_start', obj.iio_buffer); 528 | setdatatype(buffer, 'int16Ptr', obj.iio_buf_size); 529 | for i = 1 : obj.data_ch_no 530 | buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = int16(data{i}); 531 | end 532 | for i = obj.data_ch_no + 1 : obj.iio_scan_elm_no 533 | buffer.Value(i : obj.iio_scan_elm_no : obj.iio_buf_size) = 0; 534 | end 535 | calllib(obj.libname, 'iio_buffer_push', obj.iio_buffer); 536 | 537 | % Set the return code to success 538 | ret = 0; 539 | end 540 | 541 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 542 | %% Find an attribute based on the name. The name can contain wildcard '*' characters 543 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 544 | function [ret, ch, attr] = findAttribute(obj, attr_name) 545 | % Initialize the return values 546 | ret = -1; 547 | ch = 0; 548 | attr = ''; 549 | 550 | % Check if the interface is initialized 551 | if(obj.if_initialized == 0) 552 | return; 553 | end 554 | 555 | % Check if this is a device attribute 556 | name = calllib(obj.libname, 'iio_device_find_attr', obj.iio_dev, attr_name); 557 | if(~isempty(name)) 558 | ret = 0; 559 | return; 560 | end 561 | 562 | % This is a channel attribute, search for the corresponding channel 563 | chn_no = calllib(obj.libname, 'iio_device_get_channels_count', obj.iio_dev); 564 | for k = 0 : chn_no - 1 565 | ch = calllib(obj.libname, 'iio_device_get_channel', obj.iio_dev, k); 566 | attr_no = calllib(obj.libname, 'iio_channel_get_attrs_count', ch); 567 | attr_found = 0; 568 | for l = 0 : attr_no - 1 569 | attr = calllib(obj.libname, 'iio_channel_get_attr', ch, l); 570 | name = calllib(obj.libname, 'iio_channel_attr_get_filename', ch, attr); 571 | % The attribute to find can contain wildcard '*' characters, 572 | % search for all the substrings in the attribute name 573 | str_find = strsplit(attr_name, '*'); 574 | str_find = str_find(find(~strcmp(str_find, ''))); 575 | has_wildcard = ~isempty(strfind(attr_name, '*')); 576 | attr_found = 1; 577 | for i = 1 : length(str_find) 578 | if(has_wildcard == 0) 579 | ret = strcmp(name, str_find{i}); 580 | if(ret == 0) 581 | ret = []; 582 | end 583 | else 584 | ret = strfind(name, str_find{i}); 585 | end 586 | if(isempty(ret)) 587 | attr_found = 0; 588 | break; 589 | end 590 | end 591 | if(attr_found == 1) 592 | break; 593 | end 594 | clear attr; 595 | end 596 | % Check if the attribute was found 597 | if(attr_found == 0) 598 | clear ch; 599 | else 600 | ret = 1; 601 | break; 602 | end 603 | end 604 | end 605 | 606 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 607 | %% Read an attribute as a double value 608 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 609 | function [ret, val] = readAttributeDouble(obj, attr_name) 610 | % Find the attribute 611 | [ret, ch, attr] = findAttribute(obj, attr_name); 612 | if(ret < 0) 613 | val = 0; 614 | return; 615 | end 616 | 617 | % Create a double pointer to be used for data read 618 | data = zeros(1, 10); 619 | pData = libpointer('doublePtr', data(1)); 620 | 621 | % Read the attribute value 622 | if(ret > 0) 623 | calllib(obj.libname, 'iio_channel_attr_read_double', ch, attr, pData); 624 | clear ch; 625 | clear attr; 626 | else 627 | calllib(obj.libname, 'iio_device_attr_read_double', obj.iio_dev, attr_name, pData); 628 | end 629 | val = pData.Value; 630 | end 631 | 632 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 633 | %% Read an attribute as a string value 634 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 635 | function [ret, val] = readAttributeString(obj, attr_name) 636 | % Find the attribute 637 | [ret, ch, attr] = findAttribute(obj, attr_name); 638 | if(ret < 0) 639 | val = ''; 640 | return; 641 | end 642 | 643 | % Create a pointer to be used for data read 644 | data = char(ones(1, 512)); 645 | pData = libpointer('stringPtr', data); 646 | 647 | % Read the attribute value 648 | if(ret > 0) 649 | [~, ~, ~, val] = calllib(obj.libname, 'iio_channel_attr_read', ch, attr, pData, 512); 650 | clear ch; 651 | clear attr; 652 | else 653 | [~, ~, ~, val] = calllib(obj.libname, 'iio_device_attr_read', obj.iio_dev, attr_name, pData, 512); 654 | end 655 | end 656 | 657 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 658 | %% Write a string double value 659 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 660 | function ret = writeAttributeDouble(obj, attr_name, val) 661 | % Find the attribute 662 | [ret, ch, attr] = findAttribute(obj, attr_name); 663 | if(ret < 0) 664 | return; 665 | end 666 | 667 | % Write the attribute 668 | if(ret > 0) 669 | calllib(obj.libname, 'iio_channel_attr_write_double', ch, attr, val); 670 | clear ch; 671 | clear attr; 672 | else 673 | calllib(obj.libname, 'iio_device_attr_write_double', obj.iio_dev, attr_name, val); 674 | end 675 | end 676 | 677 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 678 | %% Write a string attribute value 679 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 680 | function ret = writeAttributeString(obj, attr_name, str) 681 | % Find the attribute 682 | [ret, ch, attr] = findAttribute(obj, attr_name); 683 | if(ret < 0) 684 | return; 685 | end 686 | 687 | % Write the attribute 688 | if(ret > 0) 689 | calllib(obj.libname, 'iio_channel_attr_write', ch, attr, str); 690 | clear ch; 691 | clear attr; 692 | else 693 | calllib(obj.libname, 'iio_device_attr_write', obj.iio_dev, attr_name, str); 694 | end 695 | end 696 | end 697 | end 698 | -------------------------------------------------------------------------------- /libiio_if_daq2.m: -------------------------------------------------------------------------------- 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 | 35 | classdef 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 701 | end 702 | --------------------------------------------------------------------------------