Two satellites orbiting Earth

Using Open Source IIO to Program the Phaser Phased Array

In one of my blog posts, I described the Phaser--a new phased array prototyping and exploration platform from Analog Devices.  In a previous blog, I described the advantages of using the IIO open source ecosystem to control a wide variety of hardware (like ADAR1000, ADF4159, Pluto SDR, etc.) in languages such as Matlab, Python, and GNU Radio.    

 Matlab, Python, and GNU Radio

With that background, let’s now walk through a practical example of how this all worksFirst, I’ll cover the hardware to software connectionsAnd then in my next blog, we’ll use those connections to control the phased array and plot data in both Python and MatlabWhile this example focuses on the Phaser kit, I hope that these blog posts will also be helpful for prototyping with many other devices in the IIO universe.   

Getting Started with IIO 

For a great example of how IIO works with real hardware, please see Mark Thoren’s Introduction to IIO here.  It is a thorough, but easy-to-follow, presentation of the setup and control of a simple accelerometerWe’ll use this same template in this blog, but apply it to the PhaserAnd that starts with a quick understanding of “device trees.” 

Device Trees 

In a Linux operating system, the “device tree” tells the OS what it is physically connected to.  And so, if we’re going to connect hardware (Phaser) to our Linux OS (Raspberry Pi), then we’ll need to tell the device tree what we’re connecting.  We wouldn’t want to rewrite the device tree for the entire Linux computer, so instead we just tack on a device tree overlay.  The overlay will add our Phaser connections to whatever device tree was already installed.   Take a look at Phaser's device tree overlay here.   

If this is your first time seeing a device tree, you may find it a bit difficult to readThere’s a lot of odd syntax in thereBut luckily our goal isn’t to write our device treeWe’re just trying to understand what’s there so that we can control it with the IIO softwareTherefore, let’s focus on a few key lines to understand the connection between hardware and the IIO software.   

Under a section of code labeled “fragment@2”, you’ll see 3 main sections:  adar1000@0, adar1000@1, and adf4159@2And it seems like these 3 devices are all going to use the Raspberry Pi’s spi0 busAnd have their SPI CS pin controlled by GPIO 8, 7, and 27 (respectively for the 3 devices). 

 A section of code

For the two ADAR1000s on Phaser, you’ll see that they have a label “BEAM0” and “BEAM1”And the ADF4159 is given the label “pll0”.   Remember thoseWe’ll use these labels to tell Python which device we want to control.   

 Python code

You’ll also see a list of “one-bit-adc-dacchannelsThese are GPIOs (general purpose inputs/outputs) on the Raspberry PiEach one also has a “label”, and we’ll again use those labels to read or set the voltage on that pinThe actual pins, located on the Raspberry Pi 40 pin header, are given in the list of “in-gpios” (for pins where we read the voltage) and “out-gpios” (for pins where we set the voltage)That might be useful if you want to probe a pin and see if you are setting it correctly.   

 Raspberry Pi code

A Simple Python Beam Steering Program for Phaser 

Now that we’ve told the OS what is connected, we can control it through the LIBIIO language bindings.  We’ve used LIBIIO and Python before--specifically PYADI-IIO in the Pluto Digital Beamformer blog series. So, I won’t repeat all of that here.  Instead, let’s look at a simple Python script, and see how IIO makes use of the device tree to control the hardware. 

You can find a few example beam steering Python scripts here.  Open up “beamsteer.py” and you’ll notice that we map each element of Phaser’s receive array to a specific channel on the two ADAR1000s.  Here’s what that looks like: 

 Python scripts

So “rx_array” is an array of 2 ADAR1000s called “BEAM0” and “BEAM1.”  The “device_mapsets BEAM0 as device 1, and BEAM1 as device 2The element map is how we are arranging elements 1 through 8This is for a linear array, but you could also add another row for a two-dimensional arrayThe physical arrangement looks like this: 

 The element map is showing how to arrange elements 1 through 8

Now we map each of the ADAR1000’s 4 channels to one of those elements.  For example, channel 2 (RX2 pin of the ADAR1000) of device 1 (BEAM0) will map to element #8.   Or channel 3 of device 2 (BEAM1) maps to element # 1.   The great thing about this setup is we never again need to refer to which ADAR1000 we are controlling.  We just refer to the antenna element number or the beam output number.  This minimizes the changes required to software if you want to build a prototype with more elements or a different arrangement of the elements.   

And remember those GPIOs?  Here’s a snippet on how we access them to set them high or low: 

 GPIOs

Summary: 

Hopefully, this blog post has helped you to understand how the hardware devices connect to IIO software.  For the next blog post, we’ll implement a simple program to control these devices in a phased array and plot data in Python and Matlab.