Wiki

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Last revisionBoth sides next revision
university:tools:pluto:controlling_the_transceiver_and_transferring_data [27 Apr 2017 14:18] – created Michael Hennerichuniversity:tools:pluto:controlling_the_transceiver_and_transferring_data [28 Apr 2017 16:29] – [Controlling the transceiver] Michael Hennerich
Line 1: Line 1:
 ====== Controlling the transceiver and transferring data ====== ====== Controlling the transceiver and transferring data ======
 +
 +PlutoSDR runs [[wp>Linux]]. The [[university:tools:pluto:device_drivers|device drivers]] allowing you to control the transceiver and capture samples are therefore part of to the Linux Industrial IO (IIO) framework. 
 +IIO is a kernel subsystem for analog to digital or digital to analog converters and related hardware.
 +IIO communicates with user space via [[wp>sysfs]] and a character devices. From a plain user interaction point of view this is quite intuitive, since everything is just a file. However when controlling the device from software, this can be quite painful, since you simple want to call a function or method, instead of doing string manipulation and file IO. LibIIO fills this gap, provides all sorts of device abstraction and handles all kind of IIO internals. LibIIO is cross platform and also provides different language bindings, so that you can control IIO devices from C, C++, C# or Python.  
 +
 +
 +If you’re not familiar with IIO, please start reading  here:
 +
 +{{ youtube>CS9NuRBzN5Y?small}}
 +  * [[/resources/tools-software/linux-software/libiio|libiio - IIO system library]]
 +  * [[resources:tools-software:linux-software:libiio_internals|libiio - Internals]]
 +  * [[https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing | IIO Linux Kernel Documentation sysfs-bus-iio-*]]
 +  * [[http://git.kernel.org/?p=linux/kernel/git/gregkh/staging.git;a=tree;f=drivers/staging/iio/Documentation;hb=refs/heads/staging-next | IIO Documentation]]
 +  * [[http://events.linuxfoundation.org/sites/events/files/slides/iio_high_speed.pdf|IIO High Speed]]
 +  * [[http://ftp.heanet.ie/mirrors/fosdem-video/2015/devroom-software_defined_radio/iiosdr.mp4|Video from FOSDEM of how IIO is used in SDR applications]]
 +  * [[https://www.youtube.com/watch?v=CS9NuRBzN5Y|libiio API introduction presentation video]]
 +
 +===== Controlling the transceiver =====
 +
 +The code snippet below is a minimalistic example without error checking.
 +It shows how to control the AD936x transceiver via a remote connection.
 +
 +  - Create IIO IP Network context. Instead of ''ip:xxx.xxx.xxx.xxx'' it'll also accept ''usb:XX.XX.X''
 +  - Get the AD936x PHY device structure
 +  - Set the TX LO frequency (see [[resources:tools-software:linux-drivers:iio-transceiver:ad9361|AD9361 device driver documentation]]) 
 +  - Set RX baseband rate
 + 
 +\\
 +<code c>
 +#include <iio.h>
 +
 +int main (int argc, char **argv)
 +{
 + struct iio_context *ctx;
 + struct iio_device *phy;
 +
 + ctx = iio_create_context_from_uri("ip:192.168.2.1");
 +
 + phy = iio_context_find_device(ctx, "ad9361-phy");
 +
 + iio_channel_attr_write_longlong(
 + iio_device_find_channel(phy, "altvoltage0", true),
 + "frequency",
 + 2400000000); /* RX LO frequency 2.4GHz */
 +
 + iio_channel_attr_write_longlong(
 + iio_device_find_channel(phy, "voltage0", false),
 + "sampling_frequency",
 + 5000000); /* RX baseband rate 5 MSPS */
 +
 + receive(ctx);
 +
 + iio_context_destroy(ctx);
 +
 + return 0;
 +
 +</code>
 +
 +===== Receiving data =====
 +
 +  - Get the RX capture device structure
 +  - Get the IQ input channels
 +  - Enable I and Q channel
 +  - Create the RX buffer
 +  - Fill the buffer 
 +  - Process samples
 +
 +\\
 +
 +<code c>
 +int receive(struct iio_context *ctx)
 +{
 + struct iio_device *dev;
 + struct iio_channel *rx0_i, *rx0_q;
 + struct iio_buffer *rxbuf;
 +
 + dev = iio_context_find_device(ctx, "cf-ad9361-lpc");
 +
 + rx0_i = iio_device_find_channel(dev, "voltage0", 0);
 + rx0_q = iio_device_find_channel(dev, "voltage1", 0);
 +
 + iio_channel_enable(rx0_i);
 + iio_channel_enable(rx0_q);
 +
 + rxbuf = iio_device_create_buffer(dev, 4096, false);
 + if (!rxbuf) {
 + perror("Could not create RX buffer");
 + shutdown();
 + }
 +
 + while (true) {
 + void *p_dat, *p_end, *t_dat;
 + ptrdiff_t p_inc;
 +
 + iio_buffer_refill(rxbuf);
 +
 + p_inc = iio_buffer_step(rxbuf);
 + p_end = iio_buffer_end(rxbuf);
 +
 + for (p_dat = iio_buffer_first(rxbuf, rx0_i); p_dat < p_end; p_dat += p_inc, t_dat += p_inc) {
 + const int16_t i = ((int16_t*)p_dat)[0]; // Real (I)
 + const int16_t q = ((int16_t*)p_dat)[1]; // Imag (Q)
 +
 + /* Process here */
 +
 + }
 + }
 +
 + iio_buffer_destroy(rxbuf);
 +
 +}
 +</code>
  
university/tools/pluto/controlling_the_transceiver_and_transferring_data.txt · Last modified: 18 Dec 2020 17:55 by Rob Riggs