AnsweredAssumed Answered

AD9361 libiio API Python Binding

Question asked by rmm92vt on Oct 17, 2017
Latest reply on Oct 17, 2017 by rmm92vt

I am creating a custom HDL design on the Avnet Mini-ITX-100 platform with an AD-FMCOMMS4 daughtercard. I started with the AD HDL repo reference design and I'm running the Linux image and rootfs provided in the prepared SD card image found here: Zynq & Altera SoC Quick Start Guide [Analog Devices Wiki] 

 

Here are the basic steps I took:

Cloned AD reference design from from hdl repo on github (hdl_2016_r2 branch)

Changed part for "mitx045" on projects/scripts/adi-project.tcl line 74 to "xc7z100ffg900-2"

Built for fmcomms2.mitx045 using Vivado 2016.2

Modified HDL design to include my custom application - leaving the AD cores and DMA paths intact

Created bitstream - met timing

Created FSBL from SDK

Downloaded SD Card image (2016_R2-2017_06_29.img.xz) from link above

Prepared SD card image and retrieved u-boot from the bootgen_sysfiles.tgz found in

/BOOT/zynq-mini-itx-adv7511-ad9361-fmcomms2-3/

Created my own BOOT.BIN from SDK with using the FSBL, u-boot and new bitstream

Booted system using:

My BOOT.BIN

devicetree.dtb from /BOOT/zynq-mini-itx-adv7511-ad9361-fmcomms2-3/

uImage and uEnv.txt from /BOOT/zynq-common

 

The system appears to work perfectly fine. As a test I can run both IIOScope and the ad9361-iiostream.c example without problems. For my application though I would *like* to use Python and take advantage of the Python bindings provided through iio.py (libiio/bindings/python at master · analogdevicesinc/libiio · GitHub )

 

My first attempt was to basically try and duplicate what ad9361-iiostream does: fill/dump TX/RX buffers inside a loop continuously. So here's what I tried:

 

==========================

 

import iio, time, struct

 

TXLO = 400e6
TX0BW = 2.5e6
TX0FS = 2.5e6
RXLO = 500e6
RX0BW = 2.5e6
RX0FS = 2.5e6

 

# Setup IIO Context and device handles

ctx = iio.Context()
ctrl = ctx.find_device("ad9361-phy") # Register control
txdac = ctx.find_device("cf-ad9361-dds-core-lpc") # TX/DAC Core in HDL for DMA (plus DDS)
rxadc = ctx.find_device("cf-ad9361-lpc") # RX/ADC Core in HDL for DMA

 

# Set LO, BW, FS for TX/RX
ctrl.channels[1].attrs["frequency"].value = str(int(TXLO))
ctrl.channels[5].attrs["rf_bandwidth"].value = str(int(TX0BW))
ctrl.channels[5].attrs["sampling_frequency"].value = str(int(TX0FS))
ctrl.channels[0].attrs["frequency"].value = str(int(RXLO))
ctrl.channels[4].attrs["rf_bandwidth"].value = str(int(RX0BW))
ctrl.channels[4].attrs["sampling_frequency"].value = str(int(RX0FS))

 

# Enable I/Q channels to be associated with RX buffer
rxadc.channels[0].enabled = True
rxadc.channels[1].enabled = True
txdac.channels[0].enabled = True
txdac.channels[1].enabled = True

 

# Create IIO Buffers
rxbuf = iio.Buffer(rxadc, 8192, False) # False = non-cyclic buffer
txbuf = iio.Buffer(txdac, 8192, False) # False = non-cyclic buffer

 

for i in range(4000):
    rxbuf.refill()
    x = rxbuf.read()
    txbuf.write(x)
    txbuf.push()

 

========================

 

Output:

Traceback (most recent call last):
  File "rf_setup_only.py", line 33, in <module>
    txbuf = iio.Buffer(txdac, 8192, False)  # False = non-cyclic buffer
  File "/usr/lib/python2.7/dist-packages/iio.py", line 446, in __init__
    self._buffer = _create_buffer(device._device, samples_count, cyclic)
  File "/usr/lib/python2.7/dist-packages/iio.py", line 26, in _checkNull
    raise Exception("Null pointer")
Exception: Null pointer
Exception AttributeError: "'Buffer' object has no attribute '_buffer'" in <bound method Buffer.__del__ of <iio.Bu
ffer object at 0xb6ba0cd0>> ignored
analog@analog:~/work$

 

=========================

 

Listing the device names in ctx, I get the following:

0 = ad7291

1 = ad9361-phy

2 = xadc

3 = cf-ad9361-dds-core-lpc

4 = cf-ad9361-lpc

 

From what I could gather:

device1 is for serial register access to the ad9361

device3 is for streaming output to the ad9361 TX/DAC

device4 is for streaming input from the ad9361 RX/ADC

 

Furthermore:

Channels on device1

0 = RX LO setup

1 = TX LO setup

4 = RX channel setup

5 = TX channel setup

 

Running ad9361-iiostream I get streaming input/output. And I can verify that the channels are enabled and running:

 

cat /sys/bus/iio/devices/iio:device3/buffer/enable

1

cat /sys/bus/iio/devices/iio:device4/buffer/enable

1

 

If I run my python code above with the txbuf lines commented out (33,38,39), I can at least get streaming input. The loop and buffer size I have above provide about 15 seconds of streaming data:

 

cat /sys/bus/iio/devices/iio:device3/buffer/enable

0

cat /sys/bus/iio/devices/iio:device4/buffer/enable

1

 

=========================

 

So, what am I doing wrong here? Why can't I set up a TX buffer and stream data?

 

Bob

Outcomes