-
Notifications
You must be signed in to change notification settings - Fork 356
Expand file tree
/
Copy pathmainpage.dox
More file actions
326 lines (247 loc) · 18.6 KB
/
mainpage.dox
File metadata and controls
326 lines (247 loc) · 18.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/**
@mainpage
@tableofcontents
<a href="../index.html">Back to libIIO</a>
@section license License
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.
Separately, the IIO Library also includes a set of test examples and utilities, (collectively known as iio-utils) which are developed and released under the terms of the GNU General Public License, version 2 or (at your option) any later version.
The full terms of the library license can be found at: http://opensource.org/licenses/LGPL-2.1 and the iio-utils license can be found at: https://opensource.org/licenses/GPL-2.0
@section code_model Code Model
The basic bricks of the libiio API are the iio_context, iio_device, iio_channel, iio_buffer, iio_buffer_stream and iio_block classes.

- A iio_context object may contain zero or more iio_device objects.
A iio_device object is associated with only one iio_context.
This object represents an instance of the library.
- A iio_device object may contain zero or more iio_channel objects. A iio_channel object is associated with only one iio_device.
- A iio_device object may be associated with one iio_buffer object, and a iio_buffer object is associated with only one iio_device.
@if CPP_BINDINGS
A C++ API is provided in @ref iio.hpp
@endif
@section scan_contexts Scanning for IIO contexts
The first step when dealing with a collection of IIO devices (known as a context) is to find the context. This can be connected via usb, network, serial or local. Having these different connectivity options could prove to be problematic, but libiio abstracts the low level communications away, and allows you just to find contexts, and talk to devices without being interested in the low level aspects. Many find this convenient to develop applications and algorithms on a host, and quickly move to an embedded Linux system without having to change any code.
To find what IIO contexts are available, use the following:
- iio_create_scan_context(): Create a iio_scan_context object. Depending on what backends were enabled with compiling the library, some of them may not be available. The first argument to this function is a string which is used as a filter ("usb:", "ip:", "local:", "usb:ip", where the default (NULL) means any backend that is compiled in).
- iio_scan_context_get_info_list(): get the iio_context_info object from the iio_scan_context object. The iio_context_info object can be examined with the iio_context_info_get_description() and iio_context_info_get_uri() to determine which uri you want to attach to.
@section creating_context Creating a context
Different functions are available to create the iio_context object. Depending on what backends were enabled when compiling the library, some of them may not be available.
Each function will result in a different backend being used.
Those functions are:
- iio_create_context_from_uri(): This should be the main function to create contexts, which takes a Uniform Resource Identifier (uri), and returns a iio_context.
- iio_create_default_context(): Create a "local" context if we can, otherwise use the ENV_VAR IIOD_REMOTE.
- iio_create_local_context(): Create a "local" context, to use the IIO devices connected to the system (typically for cross-compiled applications).
- iio_create_network_context(): Create a "network" context that will work with a remotely connected target.
Note that every function that compose the API of libiio will work independently of the function that was used to create the iio_context object.
The iio_context object can later be destroyed with iio_context_destroy().
@subsection navigation Navigation
@subsubsection device_obj Device objects
- From the iio_context object, you can obtain the number of available devices with iio_context_get_devices_count().
- Then, each iio_device object can be accessed with iio_context_get_device().
- Alternatively, it is possible to lookup for a device name or ID with iio_context_find_device().
Each iio_device object has an ID that can be used as identifier. This ID can be retrieved with iio_device_get_id().
It optionally also has a name, that can be retrieved with iio_device_get_name().
@subsubsection channel_obj Channel objects
- From the iio_device object, you can obtain the number of available channels with iio_device_get_channels_count().
- Then, each iio_channel object can be accessed with iio_device_get_channel().
- Alternatively, it is possible to lookup for a channel name or ID with iio_device_find_channel().
Each iio_channel can be either input, or output. This information can be retrieved with iio_channel_is_output().
As for the Device objects, the iio_channel object features an ID and optionally a name.
The ID can be obtained with iio_channel_get_id(), and the name can be obtained with iio_channel_get_name().
Important note: two iio_channel can have the same ID, as long as one is input and the other is output.
@subsection list_params Parameters
Different kinds of parameters are available: parameters that apply to a iio_device, and parameters that apply to one or more iio_channel.
- The number of device-specific parameters can be obtained with iio_device_get_attrs_count(). Each attribute name can be obtained with iio_device_get_attr().
- The number of channel-specific attributes can be obtained with iio_channel_get_attrs_count(). Each attribute name can be obtained with iio_channel_get_attr().
Alternatively, it is possible to lookup for the name of an attribute with iio_device_find_attr() and iio_channel_find_attr().
@section reading_modify_params Reading and modifying parameters
@subsection read_param Reading a parameter
Read device-specific attributes with those functions:
- iio_device_attr_read()
- iio_device_attr_read_all()
- iio_device_attr_read_bool()
- iio_device_attr_read_longlong()
- iio_device_attr_read_double()
Read channel-specific attributes with those functions:
- iio_channel_attr_read()
- iio_channel_attr_read_all()
- iio_channel_attr_read_bool()
- iio_channel_attr_read_longlong()
- iio_channel_attr_read_double()
Read debug attributes with those functions:
- iio_device_debug_attr_read()
- iio_device_debug_attr_read_all()
- iio_device_debug_attr_read_bool()
- iio_device_debug_attr_read_longlong()
- iio_device_debug_attr_read_double()
@subsection write_param Modifying a parameter
Write device-specific attributes with those functions:
- iio_device_attr_write()
- iio_device_attr_write_all()
- iio_device_attr_write_bool()
- iio_device_attr_write_longlong()
- iio_device_attr_write_double()
Write channel-specific attributes with those functions:
- iio_channel_attr_write()
- iio_channel_attr_write_all()
- iio_channel_attr_write_bool()
- iio_channel_attr_write_longlong()
- iio_channel_attr_write_double()
Write debug attributes with those functions:
- iio_device_debug_attr_write()
- iio_device_debug_attr_write_all()
- iio_device_debug_attr_write_bool()
- iio_device_debug_attr_write_longlong()
- iio_device_debug_attr_write_double()
@section trigger Triggers
Some devices, mostly low-speed ADCs and DACs, require a trigger to be set for the capture or upload process to work.
In libiio, triggers are just regular iio_device objects. To check if an iio_device can be used as a trigger, you can use iio_device_is_trigger().
To see if one device is associated with a trigger, use iio_device_get_trigger().
To assign one trigger to a iio_device, you can use iio_device_set_trigger(). If you want to disassociate a iio_device from its trigger, pass NULL to the "trigger" parameter of this function.
@section capture_upload Capturing or uploading samples
The process of capturing samples from the hardware and uploading samples to the hardware is done using the iio_buffer, iio_buffer_stream and iio_block objects.
@subsection create_buffer Enabling channels and opening a Buffer stream
The very first step is to enable the capture channels that we want to use, and disable those that we don't need.
This is done by creating an iio_channels_mask with iio_create_channels_mask() and then calling iio_channel_enable() for the desired channels.
Also, not all channels can be enabled. To know whether or not one channel can be enabled, use iio_channel_is_scan_element().
Buffers are pre-created during device context creation. To obtain a buffer, use iio_device_get_buffer(). To open it for streaming, call iio_buffer_open() with the channels mask, which returns an iio_buffer_stream object.
This call will fail if no channels have been enabled in the mask, or for triggered buffers, if the trigger has not been assigned.
When the stream is no longer needed, it can be closed with iio_buffer_close().
@subsection streaming Streaming with blocks
Data is transferred to and from the hardware using iio_block objects. There are two approaches: manual block management or the high-level iio_stream API.
@subsubsection manual_blocks Manual block management
Create one or more blocks from the buffer stream with iio_buffer_stream_create_block(). Each block represents a contiguous region of memory for sample data.
To start data flow, call iio_buffer_stream_start(). Then use iio_block_enqueue() to submit a block for I/O, and iio_block_dequeue() to wait for the transfer to complete. To stop, call iio_buffer_stream_stop() or iio_buffer_stream_cancel().
~~~{.c}
struct iio_buffer *buf = iio_device_get_buffer(dev, 0);
struct iio_buffer_stream *stream = iio_buffer_open(buf, mask);
struct iio_block *block = iio_buffer_stream_create_block(stream, block_size);
iio_buffer_stream_start(stream);
/* Streaming loop */
while (!stop) {
iio_block_enqueue(block, 0, false);
iio_block_dequeue(block, false);
/* Process samples via iio_block_start()/iio_block_end() */
}
iio_block_destroy(block);
iio_buffer_close(stream);
~~~
@subsubsection stream_api High-level Stream API
The iio_stream API simplifies streaming by managing blocks internally. Create a stream with iio_buffer_create_stream(), specifying the number of blocks and the number of samples per block. Then iterate by calling iio_stream_get_next_block() in a loop.
~~~{.c}
struct iio_buffer *buf = iio_device_get_buffer(dev, 0);
struct iio_stream *stream = iio_buffer_create_stream(buf, 4, num_samples, mask);
while (!stop) {
const struct iio_block *block = iio_stream_get_next_block(stream);
/* Process samples via iio_block_start()/iio_block_end() */
}
iio_stream_destroy(stream);
~~~
To abort a running stream from another thread or signal context, use iio_stream_cancel(). Destroying the stream with iio_stream_destroy() will also close the underlying buffer stream.
@subsection read_write Reading or writing samples to a Block
Libiio offers various ways to interact with the iio_block object.
@subsubsection memcpy Direct copy
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_block object using `memcpy`:
~~~{.c}
size_t block_size = iio_block_end(block) - iio_block_start(block);
size_t count = MIN(sizeof(samples_buffer), block_size);
memcpy(iio_block_start(block), samples_buffer, count);
~~~
Using `memcpy` to copy samples from the iio_block is <b>not recommended</b>.
When capturing samples from an input device, you cannot assume that the iio_block object contains only the samples you're interested in.
@subsubsection iterating_cb Iterating over a block with a callback
Libiio provides a way to iterate over a block by registering a callback function, with the iio_block_foreach_sample() function.
The callback function will be called for each "sample slot" of the block,
which will contain a valid sample if the block has been dequeued from an input device,
or correspond to an area where a sample should be stored if using an output device.
~~~{.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 */
}
int main(void)
{
...
iio_block_foreach_sample(block, mask, sample_cb, NULL);
...
}
~~~
Note that the callback will be called in the order that the samples appear in the block,
and only for samples that correspond to channels that were enabled.
@subsubsection iterating_for Iterating on the samples with a for loop
This method allows you to iterate over the sample slots that correspond to one channel.
As such, it is interesting if you want to process the data channel by channel.
Use iio_block_first() to find the first sample for a given channel, iio_block_end() for the end,
and iio_device_get_sample_size() for the step between consecutive samples:
~~~{.c}
size_t step = iio_device_get_sample_size(dev, mask);
for (void *ptr = iio_block_first(block, channel);
ptr < iio_block_end(block);
ptr += step) {
/* Use "ptr" to read or write a sample for this channel */
}
~~~
@subsubsection deinterleave Extracting from/to a second buffer
Finally, it is possible to use the iio_channel_read() and iio_channel_read_raw()
functions to read samples from an iio_block to a second byte array.
The samples will be deinterleaved if needed.
The "raw" variant will only deinterleave the samples, while the other variant will deinterleave and convert the samples.
For output devices, the iio_channel_write() and iio_channel_write_raw() functions are also available.
The "raw" variant will only interleave the samples (if needed), while the other variant will interleave and convert the samples
back to their hardware format.
@subsection convert Convert the samples from/to hardware format
The raw stream of samples generally isn't in a format that can be directly used in algorithms.
Some operations, like endianness conversion and bit-shifting of the samples, have to be performed first.
Libiio offers two functions that can be used to convert samples:
- iio_channel_convert(), to convert from the hardware format
- iio_channel_convert_inverse(), to convert to the hardware format.
Those two functions should always be used when manipulating the samples of an iio_block.
The exception is when iio_channel_read() or iio_channel_write() are used, as the conversion is then done internally.
@subsection push Enqueuing blocks (output devices only)
When all the samples have been written to the iio_block object, you can submit the block to the hardware with a call to iio_block_enqueue().
As soon as the block has been submitted, it can be dequeued and reused to store new samples.
If the iio_block_enqueue() call is made with the "cyclic" parameter set, and the kernel driver supports cyclic buffers,
the submitted block will be repeated until the buffer stream is closed, and no subsequent call to iio_block_enqueue() will be allowed.
@section advanced Advanced options
@subsection userdata Register and retrieve a pointer
The iio_device and iio_channel allow you to register a pointer, that can then be retrieved at a later moment.
- A pointer can be registered with a iio_device object using iio_device_set_data(), and can be retrieved with iio_device_get_data().
- A pointer can be registered with a iio_channel object using iio_channel_set_data(), and can be retrieved with iio_channel_get_data().
@subsection debug_attr Debug attributes
Some IIO devices provide debug parameters, but their presence is optional. In a similar way than with regular device parameters,
the number of debug parameters can be obtained with iio_device_get_debug_attrs_count(). Each individual parameter can be retrieved with iio_device_get_debug_attr().
Alternatively, it is possible to lookup for the name of a debug attribute with iio_device_find_debug_attr().
Those debug parameters can be read using the following functions:
- iio_device_debug_attr_read(),
- iio_device_debug_attr_read_all(),
- iio_device_debug_attr_read_bool(),
- iio_device_debug_attr_read_longlong(),
- iio_device_debug_attr_read_double().
Those debug parameters can be written using the following functions:
- iio_device_debug_attr_write(),
- iio_device_debug_attr_write_all(),
- iio_device_debug_attr_write_bool(),
- iio_device_debug_attr_write_longlong(),
- iio_device_debug_attr_write_double().
@subsection registers Reading and writing registers
As for debug attributes, some IIO devices also offer the possibility to read and write hardware registers directly.
In libiio, this can be done with two functions, iio_device_reg_read() and iio_device_reg_write().
@section abi Application Binary Interface
The libiio ABI tries to be both backwards and forwards compatible.
This means applications compiled against an older version will work fine with a newer dynamically linked library. Applications compiled against a newer version will work fine with an older dynamically linked library so long as they don't access any new features. Applications using new features should ensure the libiio version is compatible by using iio_library_get_version() to avoid undefined behavior.
\example iio_attr.c Part of the libiio-utilites, iio_attr is a utility for displaying information about local or remote IIO devices. By providing an optional value, iio_attr will attempt to write the new value to the attribute.
\example iio_info.c Part of the libiio-utilites, iio_info is a utility for displaying information about local or remote IIO devices.
\example iio_readdev.c Part of the libiio-utilites, iio_readdev is a utility for reading buffers from connected IIO devices, and sending results to standard out.
\example iio_writedev.c Part of the libiio-utilites, iio_writedev is a utility for writing buffers from connected IIO devices.
\example iio_reg.c Part of the libiio-utilites, iio_reg is a utility for debugging local IIO devices. It should not be used by normal users, and is normally used by driver developers during development, or by end users debugging a driver, or sending in a feature request. It provides a mechanism to read or write SPI or I2C registers for IIO devices.
\example ad9361-iiostream.c This example libiio program is meant to exercise the features of IIO functionality on the AD9361 found on the AD-FMCOMMS2-EBZ, AD-FMCOMMS3-EBZ, and the ADRV9361-Z7035 RF SOM.
\example ad9371-iiostream.c This example libiio program is meant to exercise the features of IIO functionality on the AD9371.
\example adrv9009-iiostream.c This example libiio program is meant to exercise the features of IIO functionality on the ADRV9009.
\example dummy-iiostream.c This example libiio program is meant to exercise the features of IIO present in the sample dummy IIO device in the linux kernel.
\example iio-monitor.c A Curses based application which implements real time monitoring of IIO non-buffer samples.
@if CPP_BINDINGS
\example iiopp-enum.cpp This example demonstrates usage of the C++ API to enumerate devices, channels and attributes.
@endif
*/