diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 8458a9c02..04ea6dde3 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -21,6 +21,7 @@ jobs: cd build cmake .. -DWITH_MAN=ON -DHAVE_DNS_SD=OFF make + sudo make install cd .. cd docs pip install -r requirements_doc.txt diff --git a/docs/source/api.rst b/docs/source/api.rst index 87f17d910..f266466c1 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -17,4 +17,5 @@ This section provides a detailed description of the C API. The API is divided in api/c/buffer api/c/event api/c/hwmon - api/c/debug \ No newline at end of file + api/c/debug + diff --git a/docs/source/api/c/scan.rst b/docs/source/api/c/scan.rst index 1803ab5fa..2642c5a1d 100644 --- a/docs/source/api/c/scan.rst +++ b/docs/source/api/c/scan.rst @@ -1,6 +1,20 @@ Scanning Functions ================== -.. doxygengroup:: Scan - :content-only: - :members: \ No newline at end of file +.. doxygenfunction:: iio_scan + + +.. doxygenfunction:: iio_scan_destroy + + +.. doxygenfunction:: iio_scan_get_results_count + + +.. doxygenfunction:: iio_scan_get_description + + +.. doxygenfunction:: iio_scan_get_uri + + +.. .. doxygenstruct:: iio_scan + diff --git a/docs/source/api/matlab/context.rst b/docs/source/api/matlab/context.rst deleted file mode 100644 index 184ea6699..000000000 --- a/docs/source/api/matlab/context.rst +++ /dev/null @@ -1,9 +0,0 @@ -Context Functions -================= - -.. mat:currentmodule:: bindings.matlab - -.. mat:autoclass:: context - :show-inheritance: - :members: - diff --git a/docs/source/api/matlab/index.md b/docs/source/api/matlab/index.md deleted file mode 100644 index 72b65fa34..000000000 --- a/docs/source/api/matlab/index.md +++ /dev/null @@ -1,7 +0,0 @@ -# MATLAB - -```{toctree} - -context - -``` \ No newline at end of file diff --git a/docs/source/api/python/buffer.rst b/docs/source/api/python/buffer.rst new file mode 100644 index 000000000..6c9d1bb2a --- /dev/null +++ b/docs/source/api/python/buffer.rst @@ -0,0 +1,7 @@ +Buffer +================== + +Members +-------------- +.. autoclass:: iio.Buffer + :members: diff --git a/docs/source/api/python/channel.rst b/docs/source/api/python/channel.rst new file mode 100644 index 000000000..62a62fc64 --- /dev/null +++ b/docs/source/api/python/channel.rst @@ -0,0 +1,18 @@ +Channels +================== + +Members +-------------- +.. autoclass:: iio.Channel + :members: + +-------------------- + +Channel attributes +-------------------- +.. autoclass:: iio.DataFormat + :members: +.. autoclass:: iio.ChannelModifier + :members: +.. autoclass:: iio.ChannelType + :members: diff --git a/docs/source/api/python/context.rst b/docs/source/api/python/context.rst new file mode 100644 index 000000000..f1916a374 --- /dev/null +++ b/docs/source/api/python/context.rst @@ -0,0 +1,20 @@ +Contexts +================== + +Members +-------------- +.. autoclass:: iio.Context + :members: + +.. autoclass:: iio.LocalContext + :members: + :inherited-members: + +.. autoclass:: iio.XMLContext + :members: + :inherited-members: + +.. autoclass:: iio.NetworkContext + :members: + :inherited-members: + diff --git a/docs/source/api/python/device.rst b/docs/source/api/python/device.rst new file mode 100644 index 000000000..ae1410d3f --- /dev/null +++ b/docs/source/api/python/device.rst @@ -0,0 +1,20 @@ +Device +================== + +Members +-------------- +.. autoclass:: iio.Device + :members: + :inherited-members: + +------------------ + +.. Device attributes +.. ------------------ +.. .. autoclass:: iio.DeviceDebugAttr +.. :members: +.. :inherited-members: +.. .. autoclass:: iio.DeviceBufferAttr +.. :members: +.. :inherited-members: + diff --git a/docs/source/api/python/examples.rst b/docs/source/api/python/examples.rst new file mode 100644 index 000000000..280787aee --- /dev/null +++ b/docs/source/api/python/examples.rst @@ -0,0 +1,31 @@ +Examples +================== + + +Complete Application Examples +------------------------------ +.. toctree:: + iio_readdev + iio_writedev + iio_attr + iio_info + + +Code Snippets +----------------------------- + +Scan contexts and list channels of each device + +.. code-block:: python + + import iio + + for ctxname in iio.scan_contexts(): + ctx = iio.Context(ctxname) + for dev in ctx.devices: + if dev.channels: + for chan in dev.channels: + print("{} - {} - {}".format(ctxname, dev.name, chan._id)) + else: + print("{} - {}".format(ctxname, dev.name)) + diff --git a/docs/source/api/python/iio_attr.rst b/docs/source/api/python/iio_attr.rst new file mode 100644 index 000000000..0bfbf3153 --- /dev/null +++ b/docs/source/api/python/iio_attr.rst @@ -0,0 +1,9 @@ +iio_attr +====================== +| iio_attr is part of the Libiio package, a library that has been developed to ease the development of software interfacing Linux Industrial I/O (IIO) devices. +| This tool is written using the libiio Python bindings. It works in a very similar way of how the base iio_attr works. You can find more information about it on this `page `_. + + +.. literalinclude:: ../../../../bindings/python/examples/iio_attr.py + :language: python + diff --git a/docs/source/api/python/iio_info.rst b/docs/source/api/python/iio_info.rst new file mode 100644 index 000000000..b2187adde --- /dev/null +++ b/docs/source/api/python/iio_info.rst @@ -0,0 +1,10 @@ +iio_info +===================== +| iio_info is part of the Libiio package, a library that has been developed to ease the development of software interfacing Linux Industrial I/O (IIO) devices. +| This tool is written using the libiio Python bindings. It works in the same way as the base iio_info works. You can find more information about it on this `page `_. + + + +.. literalinclude:: ../../../../bindings/python/examples/iio_info.py + :language: python + diff --git a/docs/source/api/python/iio_readdev.rst b/docs/source/api/python/iio_readdev.rst new file mode 100644 index 000000000..b27975001 --- /dev/null +++ b/docs/source/api/python/iio_readdev.rst @@ -0,0 +1,9 @@ +iio_readdev +===================== +| iio_readdev is part of the Libiio package, a library that has been developed to ease the development of software interfacing Linux Industrial I/O (IIO) devices. +| This tool is written using the libiio Python bindings. It works in the same way as the base iio_readdev works. You can find more information about it on this `page `_. + + +.. literalinclude:: ../../../../bindings/python/examples/iio_readdev.py + :language: python + diff --git a/docs/source/api/python/iio_writedev.rst b/docs/source/api/python/iio_writedev.rst new file mode 100644 index 000000000..d456413f5 --- /dev/null +++ b/docs/source/api/python/iio_writedev.rst @@ -0,0 +1,9 @@ +iio_writedev +===================== +| iio_writedev is part of the Libiio package, a library that has been developed to ease the development of software interfacing Linux Industrial I/O (IIO) devices. +| This tool is written using the libiio Python bindings. It works in the same way as the base iio_writedev works. You can find more information about it on this `page `_. + + +.. literalinclude:: ../../../../bindings/python/examples/iio_writedev.py + :language: python + diff --git a/docs/source/api/python/index.rst b/docs/source/api/python/index.rst new file mode 100644 index 000000000..5c246b7c4 --- /dev/null +++ b/docs/source/api/python/index.rst @@ -0,0 +1,47 @@ +Python Bindings +=============== + +Python bindings for the `Industrial I/O <../index.html>`_ interface library. + +Installation +############ + +The libiio python bindings can be installed from pip + +.. code-block:: bash + + (sudo) pip install pylibiio + +or by grabbing the source directly + +.. code-block:: bash + + git clone https://github.com/analogdevicesinc/libiio.git + cd bindings/python + (sudo) python3 setup.py install + +.. note:: + + On Linux the libiio python bindings are sometimes installed in locations not on path. On Ubuntu this is a common fix + + .. code-block:: bash + + export PYTHONPATH=$PYTHONPATH:/usr/lib/python{python-version}/site-packages + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + +Components +########## + +.. toctree:: + :maxdepth: 1 + + context + buffer + device + channel + trigger + examples + diff --git a/docs/source/api/python/trigger.rst b/docs/source/api/python/trigger.rst new file mode 100644 index 000000000..6ddc1453d --- /dev/null +++ b/docs/source/api/python/trigger.rst @@ -0,0 +1,8 @@ +Trigger +================== + +Members +-------------- +.. autoclass:: iio.Trigger + :members: + :inherited-members: diff --git a/docs/source/bindings.rst b/docs/source/bindings.rst index 63e485e38..b382778a6 100644 --- a/docs/source/bindings.rst +++ b/docs/source/bindings.rst @@ -5,4 +5,4 @@ Bindings .. toctree:: :maxdepth: 2 - api/matlab/index \ No newline at end of file + api/python/index \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index eb72a62e8..df4c22c6d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,6 +10,13 @@ os.system("doxygen doxyfile.in") os.chdir(cwd) +# Add bindings and examples to path +import sys +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "bindings", "python"))) +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "bindings", "examples"))) + +import iio + # -- Project information ----------------------------------------------------- project = 'libiio' year = datetime.datetime.now().year diff --git a/docs/source/examples.md b/docs/source/examples.md index a2c56ff80..9ff07c72b 100644 --- a/docs/source/examples.md +++ b/docs/source/examples.md @@ -1,6 +1,6 @@ # Examples -This page provides a few examples of how to use the libIIO library. The examples are written in C and are intended to be used as a starting point for your own application. For other languages, please refer to the [Bindings](bindings.md) page. +This page provides a few examples of how to use the libIIO library. The examples are written in C and are intended to be used as a starting point for your own application. For other languages, please refer to the [Bindings](bindings.rst) page. :::{note} To reduce verbosity, the error handling code has been omitted from the examples. In a real application, you should always check the return value of each function call. diff --git a/docs/source/index.md b/docs/source/index.md index 6258dd493..c4e1c545a 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -11,13 +11,13 @@ It is portable: Using a single cross-platform API, it provides access to IIO dev It is entirely user-mode: No special privilege or elevation is required for the application to communicate with a device. One of the most powerful things about libiio is its [Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call) style interface. Moving backends from USB to Networking to local embedded does not require any code changes. The users of the libIIO do not need to code any differently for the remote interaction, making it easy to move from remote (debug on PC over Ethernet) to local (deployed on embedded Linux). -### What platforms are supported? +## What platforms are supported? Any host running Linux, macOS, Windows, or OpenBSD/NetBSD, should be trivial to get libIIO running on. If you are interested in porting to other hosts that support either networking (socket interface), [libusb](https://libusb.info/) or serial, it should be very straightforward. [Pull Requests](https://github.com/analogdevicesinc/libiio/pulls) are always reviewed, and well written ones are normally accepted. The local backend and Linux daemon can run on any embedded Linux based system, from purpose built systems like [PlutoSDR](http://www.analog.com/plutosdr) or [ADALM2000](http://www.analog.com/adalm2000) to [Raspberry Pi](https://www.raspberrypi.org/) or [BeagleBoard](https://beagleboard.org/) to [Jetson](https://www.nvidia.com/en-us/autonomous-machines/jetson). [tiny-iiod](https://github.com/analogdevicesinc/libtinyiiod) requires a modern C compiler and is known to work on a variety of non-Linux frameworks including [Mbed](https://www.mbed.com/) and [FreeRTOS](https://www.freertos.org/). -### Sounds good! How do I get started? +## Sounds good! How do I get started? If you are using Linux, chances are your distribution already includes libIIO, so you probably just need to reference the `iio.h` header in your source. @@ -27,11 +27,11 @@ If you prefer, you can also access the source directly from [github](https://git Once you have secured your access to the library and its header, please check the [libIIO API](https://analogdevicesinc.github.io/libiio/api/index.html) or the [libIIO examples](https://analogdevicesinc.github.io/libiio/examples/index.html). -### Where is (insert my favourite language) support? +## Where is (insert my favourite language) support? The mainline library is written in C, and has built in bindings for C++, Python and C# (C-Sharp). [Node.js](https://github.com/drom/node-iio) and [Rust](https://github.com/fpagliughi/rust-industrial-io) are maintained outside the main repo. If you are interested in creating more language bindings, please [reach out](https://github.com/analogdevicesinc/libiio/issues) to the developers by posting an issue on github. -## Licensing +# Licensing Libiio has been developed and is released under the terms of the GNU Lesser General Public License, version 2 or (at your option) any later version. This open-source license allows anyone to use the library for proprietary or open-source, commercial or non-commercial applications. diff --git a/docs/source/install.md b/docs/source/install.md index 3f854f62c..8f12ea508 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -39,9 +39,7 @@ Please reference your OS's package manager for the correct package names. Altern For macOS there are four options: -- [Homebrew](install/homebrew.md) +- [Homebrew](#homebrew) - [MacPorts](https://ports.macports.org/port/libiio/) -- DMG installer from the [GitHub releases page](ttps://github.com/analogdevicesinc/libiio/releases) +- DMG installer from the [GitHub releases page](https://github.com/analogdevicesinc/libiio/releases) - [Building from source](install/source.md) - - diff --git a/docs/source/install/source.md b/docs/source/install/source.md index 0e4a88b53..eeb64e586 100644 --- a/docs/source/install/source.md +++ b/docs/source/install/source.md @@ -12,7 +12,7 @@ git checkout v0.25 This section describes how to build libIIO from source. This is useful if you want to use the latest features or if you are developing libIIO itself. -### Install Prerequisites/Dependencies and Build +## Install Prerequisites/Dependencies and Build ````{tab} Linux (Debian/Ubuntu) @@ -125,7 +125,8 @@ This process relies on [Homebrew](https://brew.sh/), a package manager for macOS /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` -### Easy: Using a homebrew formula +(homebrew)= +### Easy: Using a homebrew formula ```shell brew install tfcollins/libiio @@ -165,7 +166,7 @@ sudo make install --- - +(configuration-options)= ## Configuration Options when configuring libiio with cmake, there are a few optional settings that you can use to control the build. diff --git a/docs/source/landing.md b/docs/source/landing.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/source/related.md b/docs/source/related.md index 0ca9501d3..fdcdc9fae 100644 --- a/docs/source/related.md +++ b/docs/source/related.md @@ -1,13 +1,12 @@ # Related Projects -- [IIO-Oscilloscope]() -- [pyadi-iio]() +- [IIO-Oscilloscope](https://wiki.analog.com/resources/tools-software/linux-software/iio_oscilloscope) +- [pyadi-iio](https://analogdevicesinc.github.io/pyadi-iio/) - MATLAB Toolboxes - - [Analog Devices Transceiver Toolbox]() - - [Analog Devices High Speed Converter Toolbox]() - - [Analog Devices RF and Microwave Toolbox]() - - [Analog Devices Precision Toolbox]() -- [Scopy]() -- [libad9361-iio]() -- [libad9166-iio]() -- [iio-emu]() \ No newline at end of file + - [Analog Devices Transceiver Toolbox](https://analogdevicesinc.github.io/TransceiverToolbox/master/) + - [Analog Devices High Speed Converter Toolbox](https://analogdevicesinc.github.io/HighSpeedConverterToolbox/master/) + - [Analog Devices RF and Microwave Toolbox](https://analogdevicesinc.github.io/RFMicrowaveToolbox/master/) + - [Analog Devices Precision Toolbox](https://analogdevicesinc.github.io/PrecisionToolbox/) +- [Scopy](https://wiki.analog.com/university/tools/m2k/scopy) +- [libad9361-iio](https://analogdevicesinc.github.io/libad9361-iio) +- [libad9166-iio](https://analogdevicesinc.github.io/libad9166-iio) \ No newline at end of file diff --git a/docs/source/theory.md b/docs/source/theory.md index b3d6c5047..045b01c8d 100644 --- a/docs/source/theory.md +++ b/docs/source/theory.md @@ -1,11 +1,11 @@ # Theory of Operation -### Objectives +## Objectives Why did Analog Devices develop libiio? To answer that question, it is needed to understand the state of things before libiio was introduced. -#### Simplification and standardization +### Simplification and standardization The Linux kernel features a IIO subsystem, which provides a standardized interface with the user-space for client applications. The various drivers designed to interface different IIO devices @@ -31,7 +31,7 @@ to support a wide range of devices. For instance, if the application requests on a capture channel without specifying its name, then it will be compatible with all IIO devices with at least one capture channel that exist to date, as well as future hardware that has yet to be invented. -#### Advanced features +### Advanced features Beyond resolving issues, libiio was also announcing new features. The major planned improvement being a network backend, which would broaden the set of possibilities: running the @@ -40,9 +40,11 @@ device from anywhere in the network in an application. That network backend was also opening questions about other possible improvements: for instance, using IIO devices from applications running on different operating systems, like Windows, -using those devices in environments like [GNU Radio](gnuradio), [MATLAB](/libiio/clients/matlab_simulink) or [Simulink](/libiio/clients/matlab_simulink), etc. +using those devices in environments like [GNU Radio](https://wiki.analog.com/resources/tools-software/linux-software/gnuradio), [MATLAB](https://wiki.analog.com/resources/tools-software/mathworks) or [Simulink](https://wiki.analog.com/resources/tools-software/mathworks), etc. -### License and code management + + +## License and code management Libiio has been developed and is released under the terms of the GNU Lesser General Public License, version 2. This open-source license allows anyone to use the library for proprietary or @@ -52,7 +54,7 @@ clients with a better and easier way of using this hardware. The full terms of the license can be found here: -### Code conformance +## Code conformance A good part of libiio fully complies with the C99 and POSIX standards, and should be compilable on any POSIX-compliant operating system supported by a C99 compiler. The exception @@ -63,7 +65,7 @@ a design decision since the beginning of the project, porting the library to Win exceptionally easy and required very little change, thanks to the recent POSIX sockets compatibility layer provided in Windows. -### Code visibility +## Code visibility While the public API declares and references iio_context, iio_device, iio_channel and iio_buffer objects, their content is never known to the client application. All the public functions use pointers @@ -86,7 +88,7 @@ token marks the corresponding functions as visible in the library. The functions are considered hidden and will not be callable from outside the library. This ensures that client applications cannot call internal functions, and use the API functions instead. -### Backends +## Backends The libiio library has been designed from the start to support multiple backends. The current 0.1 version features three different backends: a XML backend, a local backend, a network backend. @@ -122,7 +124,7 @@ library to work. For instance, the Windows versions are built without the local is Linux-specific; and a build of the library meant to run on a development board with IIO devices attached could be compiled without the network and XML backends, as those would be unused. -### Layering +## Layering The libiio library is built with two distincts layers. The top layer contains the implementations of all the public functions. It is high-level, in the sense that those functions can be used independently @@ -175,6 +177,7 @@ file. #### Document Type Definition +```xml @@ -190,6 +193,7 @@ file. ]> +``` This DTD corresponds to the format expected by the XML backend of the latest libiio. It is always embedded at the top of the XML generated with iio_context_get_xml, and the XML backend @@ -341,15 +345,10 @@ samples: This method can be very useful if the data of a channel has to be processed sample by sample, as in this case, there is no copy to an intermediate buffer. As the inner loops gets a pointer to the sample\'s emplacement, it can be used either to read or write the buffer. -```{=html} - -``` -- Alternatively, the iio_buffer class contains a method called iio_buffer_foreach_sample. This function takes a function pointer as argument: the supplied callback will be called for each sample of the buffer. The callback receives four arguments: a pointer to the iio_channel structure corresponding to the sample, a pointer to the sample itself, the length of the sample in bytes, plus a pointer optionally set as argument of iio_buffer_foreach_sample. Again, this function can be used to read from or write to the buffer.\ - The main difference with the previous method, is that the callback is called for each sample of the buffer, in the order that they appear in the buffer, and not ordered by channels. As said previously, the buffer can contain samples of channels that we didn\'t request; the callback can just check whether or not the sample\'s channel is enabled with iio_channel_is_enabled, and just return zero if it\'s not. -```{=html} - -``` + + - The last method is to use one of the higher-level functions provided by the iio_channel class: iio_channel_read_raw, iio_channel_write_raw, iio_channel_read, iio_channel_write. The former two will basically copy the first N samples of one channel to/from a user-specified buffer (N depending of the size of this one buffer). Note that this function can be replaced with the first method and a memcpy (that\'s what it does internally, after all). The latter two will do the same, but will additionally convert all the samples copied from the raw format to the format that can be used by the applications. ### Refilling and submitting a buffer @@ -362,7 +361,7 @@ As stated previously, the **iio_channel_read** and **iio_channel_write** functio First, here is a textual representation of the hardware format as reported by the kernel: - >## cat /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_type + ># cat /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_type le:s12/16>>4 What it says, is that the hardware samples are in little-endian order ("le"), that the sample size is 16 bits, but with only 12 bits worth of data. The "\>\>4" shift informs that those 12 bits are located after 4 most-significant bits (MSB), so in this particular case they correspond to the 12 less-significant bits (LSB), as 16 -- 4 = 12. The "s" character of "s12" means that the 12-bit value is signed. @@ -703,7 +702,7 @@ C is a good language, but not everybody is familiar with it; some people might p #### Python bindings -The Python bindings were developed very early in the project to facilitate generating XML strings modeling IIO contexts in order to properly test the XML backend. They quickly became outdated as the project moved on, but were later greatly improved and should now be on par with the C## bindings. +The Python bindings were developed very early in the project to facilitate generating XML strings modeling IIO contexts in order to properly test the XML backend. They quickly became outdated as the project moved on, but were later greatly improved and should now be on par with the C# bindings. To create the bindings, The "ctypes" module has been used: @@ -745,11 +744,11 @@ Since v0.21 the python bindings have been available through pypi, and therefore ##### PyADI-IIO -An additional module was created which leverages the libiio python bindings call [pyadi-iio](resources/tools-software/linux-software/pyadi-iio). pyadi-iio is recommended if a device specific class exists for your [current hardware](https://github.com/analogdevicesinc/pyadi-iio/blob/master/supported_parts.md). However, since pyadi-iio uses libiio all the libiio python APIs are available in that module if needed. +An additional module was created which leverages the libiio python bindings call [pyadi-iio](https://analogdevicesinc.github.io/pyadi-iio/). pyadi-iio is recommended if a device specific class exists for your [current hardware](https://github.com/analogdevicesinc/pyadi-iio/blob/master/supported_parts.md). However, since pyadi-iio uses libiio all the libiio python APIs are available in that module if needed. -#### C## bindings +#### C# bindings -The C## bindings in particular are fully functional and cover the whole panel of features that +The C# bindings in particular are fully functional and cover the whole panel of features that libiio provides. Its API consists in the Context, Device, Channel and IOBuffer classes, each one providing a couple of methods, that directly call their C counterpart: @@ -775,9 +774,9 @@ namespace iio In this example, if you call the id method on an object of type Device, as a result the C function iio_device_get_id will be called. All the others methods implement a similar mechanism. -The C## bindings are especially interesting for Windows users, because they permit to use libiio +The C# bindings are especially interesting for Windows users, because they permit to use libiio in a .NET application (with the network backend, of course). By using Mono, it is also possible to -use libiio in C## programs running on Linux. +use libiio in C# programs running on Linux. ### Future improvements @@ -785,7 +784,7 @@ use libiio in C## programs running on Linux. The current version of the IIOD server is extremely fast, provided that client-side demultiplexing is used. On a weak 400 MHz CPU, it has no problems to stream samples at speeds of 3MSPS (3 million samples per second) without dropping a single one. -However, 3 MSPS is really far from the maximum capacity of the typical converters. The [AD-FMCOMMS3-EBZ](/resources/eval/user-guides/ad-fmcomms3-ebz/) board, for instance, can digitize at a speed up to 61.44 MSPS (time 4 channels, for a total of 245.76 MSPS) \... nearly 100 times faster. And the recent [AD-FMCDAQ2-EBZ](/resources/eval/user-guides/ad-fmcdaq2-ebz/) is capable of 1000 MSPS for dual 16-bit channels, which +However, 3 MSPS is really far from the maximum capacity of the typical converters. The [AD-FMCOMMS3-EBZ](https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms3-ebz/) board, for instance, can digitize at a speed up to 61.44 MSPS (time 4 channels, for a total of 245.76 MSPS) \... nearly 100 times faster. And the recent [AD-FMCDAQ2-EBZ](https://wiki.analog.com/resources/eval/user-guides/ad-fmcdaq2-ebz/) is capable of 1000 MSPS for dual 16-bit channels, which represents a maximum transfer speed of 2000 MSPS, or 32.0 Gb/s. So how to reach those extremely high speeds, with a 400 MHz CPU? That\'s where [Zero copy](https://en.wikipedia.org/wiki/Zero-copy) @@ -795,15 +794,9 @@ IIOD uploads the samples from one device to a connected client: - When the low-speed interface is used, the samples are acquired from the hardware using DMA, and stored into a kernel buffer; the local backend of libiio will then use the CPU to copy the samples to the iio_buffer object, and then copy again to the packet buffer of the Linux kernel by writing the client\'s socket.\ ![](_static/libiio_route_lowspeed.png){.align-center width="600" query="?600"} -```{=html} - -``` -- The high-speed interface works roughly the same, but the manual copy from the kernel\'s IIO buffer to the iio_buffer object is avoided by swapping the buffers from user space and kernel space. However, it is still required to write the buffer to each client\'s socket.\ - ![](_static/libiio_route_highspeed.png){.align-center width="600" query="?600"} + -```{=html} - -``` - Then comes zerocopy. The principle, is to avoid the second manual copy of the samples, when the data is written to the socket. So how can this work? How is it possible to send data through the network, without writing the socket?\ The answer is to be found deep inside the Linux kernel. A particular system call, named "[vmsplice](https://en.wikipedia.org/wiki/Splice_(system_call))", allows to "give" virtual pages of memory to the Linux kernel through a file descriptor. This trick, introduced in Linux 2.6.17, works by re-configuring the Memory Management Unit of the CPU. Let\'s say the buffer to write to the socket starts at address 0x4000; the vmsplice system call will map the exact same area to a different address in kernel space, e.g. 0x8000, so that the buffer can be addressed from both addresses. Then, it will re-map the original 0x4000 address to point to a different physical location. As a result, a complete buffer of samples has been moved to kernel space, without copying a single byte of it! Then, from the hardware to the network link, the CPU never has to copy anything, and the 400 MHz ARM board can push hundreds of megabytes of samples on the network while having a CPU usage staying close to zero.\ ![](_static/libiio_route_zerocopy.png){.align-center width="600" query="?600"}\ diff --git a/docs/source/usage.md b/docs/source/usage.md index cabf8368b..bea21c451 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -141,11 +141,11 @@ Libiio offers various ways to interact with the iio_buffer object. If you already have a buffer of samples, correctly interleaved and in the format that the hardware expects, it is possible to copy the samples directly into the iio_buffer object using `memcpy`: -~~~{.c} +```c size_t iio_buf_size = iio_buffer_end(buffer) - iio_buffer_start(buffer); size_t count = MAX(sizeof(samples_buffer), iio_buf_size); memcpy(iio_buffer_start(buffer), samples_buffer, count); -~~~ +``` Using `memcpy` to copy samples from the iio_buffer is not recommended. When capturing samples from an input device, you cannot assume that the iio_buffer object contains only the samples you're interested in. @@ -157,7 +157,7 @@ The callback function will be called for each "sample slot" of the buffer, which will contain a valid sample if the buffer has been refilled, or correspond to an area where a sample should be stored if using an output device. -~~~{.c} +```c ssize_t sample_cb(const struct iio_channel *chn, void *src, size_t bytes, void *d) { /* Use "src" to read or write a sample for this channel */ @@ -169,7 +169,7 @@ int main(void) iio_buffer_foreach_sample(buffer, sample_cb, NULL); ... } -~~~ +``` Note that the callback will be called in the order that the samples appear in the buffer, and only for samples that correspond to channels that were enabled. @@ -180,13 +180,13 @@ As such, it is interesting if you want to process the data channel by channel. It basically consists in a for loop that uses the functions iio_buffer_first(), iio_buffer_step() and iio_buffer_end(): -~~~{.c} +```c for (void *ptr = iio_buffer_first(buffer, channel); ptr < iio_buffer_end(buffer); ptr += iio_buffer_step(buffer)) { /* Use "ptr" to read or write a sample for this channel */ } -~~~ +``` #### Extracting from/to a second buffer