Skip to content

Commit

Permalink
Merge pull request #510 from analogdevicesinc/tfcollins/libiio-v1-sup…
Browse files Browse the repository at this point in the history
…port

Add libiio v1.X support
  • Loading branch information
tfcollins authored Dec 22, 2023
2 parents 15b7cb9 + ffdda12 commit 34c7b10
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 92 deletions.
23 changes: 21 additions & 2 deletions .github/scripts/install_libiio.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
#!/bin/bash

# Set LIBIIO_BRANCH if not set
if [ -z "$LIBIIO_BRANCH" ]; then
LIBIIO_BRANCH="v0.25"
fi

sudo apt-get -qq update
sudo apt-get install -y git cmake graphviz libavahi-common-dev libavahi-client-dev libaio-dev libusb-1.0-0-dev libxml2-dev rpm tar bzip2 gzip flex bison git
git clone -b 'v0.25' --single-branch --depth 1 https://github.com/analogdevicesinc/libiio.git
sudo apt-get install -y git cmake graphviz libavahi-common-dev libavahi-client-dev libaio-dev libusb-1.0-0-dev libxml2-dev rpm tar bzip2 gzip flex bison git libzstd-dev
git clone -b $LIBIIO_BRANCH --single-branch --depth 1 https://github.com/analogdevicesinc/libiio.git
cd libiio
cmake . -DHAVE_DNS_SD=OFF
make
sudo make install
cd ..
rm -rf libiio

# Python pieces
sudo apt-get install -y python3-pip python3-setuptools
git clone -b $LIBIIO_BRANCH --single-branch --depth 1 https://github.com/analogdevicesinc/libiio.git
cd libiio
cmake . -DHAVE_DNS_SD=OFF -DPYTHON_BINDINGS=ON
make
cd bindings/python
pip install .
cd ../..
cd ..
rm -rf libiio
24 changes: 22 additions & 2 deletions .github/scripts/install_part_libs.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
#!/bin/bash

# Set LIBIIO_BRANCH if not set
if [ -z "$LIBIIO_BRANCH" ]; then
LIBIIO_BRANCH="v0.25"
fi

if [ "$LIBIIO_BRANCH" = "main" ]; then
exit 0
fi



git clone -b 'master' --single-branch --depth 1 https://github.com/analogdevicesinc/libad9361-iio.git
cd libad9361-iio
cmake -DPYTHON_BINDINGS=ON .
if [ "$LIBIIO_BRANCH" = "main" ]; then
cmake -DPYTHON_BINDINGS=ON -DLIBIIO_INCLUDEDIR=/usr/include/iio .
else
cmake -DPYTHON_BINDINGS=ON .
fi
make
cd bindings/python
pip install .
Expand All @@ -13,7 +29,11 @@ rm -rf libad9361-iio

git clone -b 'master' --single-branch --depth 1 https://github.com/analogdevicesinc/libad9166-iio.git
cd libad9166-iio
cmake -DPYTHON_BINDINGS=ON .
if [ "$LIBIIO_BRANCH" = "main" ]; then
cmake -DPYTHON_BINDINGS=ON -DLIBIIO_INCLUDEDIR=/usr/include/iio .
else
cmake -DPYTHON_BINDINGS=ON .
fi
make
cd bindings/python
pip install .
Expand Down
18 changes: 17 additions & 1 deletion .github/scripts/install_pydeps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,20 @@
sudo apt-get install -y python3-pip python3-setuptools
pip install -r requirements.txt
pip install -r requirements_dev.txt
pip install pylibiio

if [ "$LIBIIO_BRANCH" = "main" ]; then
pip install --no-deps --force-reinstall pytest-libiio@git+https://github.com/tfcollins/pytest-libiio.git@master
pip install lxml pyyaml
# Update python bindings again
git clone -b $LIBIIO_BRANCH --single-branch --depth 1 https://github.com/analogdevicesinc/libiio.git
cd libiio
cmake . -DHAVE_DNS_SD=OFF -DPYTHON_BINDINGS=ON
make
cd bindings/python
pip install .
cd ../..
cd ..
rm -rf libiio
else
pip install "pytest-libiio>=0.0.18"
fi
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, "3.10"]
libiio: ['main', 'v0.25']

steps:
- uses: actions/checkout@v2
Expand All @@ -18,6 +19,7 @@ jobs:

- name: Install dependencies
run: |
export LIBIIO_BRANCH=${{ matrix.libiio }}
bash ./.github/scripts/install_libiio.sh
bash ./.github/scripts/install_pydeps.sh
bash ./.github/scripts/install_part_libs.sh
Expand Down
192 changes: 192 additions & 0 deletions adi/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Copyright (C) 2023 Analog Devices, Inc.
#
# SPDX short identifier: ADIBSD
"""Compatibility module for libiio v1.X."""

from typing import List, Union

import iio

import numpy as np


def _is_libiio_v1() -> bool:
"""Check is we are using >= v1.X."""
v = iio.version
return v[0] >= 1


class compat_libiio_v1_rx:
"""Compatibility class for libiio v1.X RX."""

_rx_buffer_mask = None
_rx_stream = None
_rx_buffer_num_blocks = 4

def _rx_init_channels(self):
if not self._rx_buffer_mask:
self._rx_buffer_mask = iio.ChannelsMask(self._rxadc)

channels = []
if self._complex_data:
for m in self.rx_enabled_channels:
v = self._rxadc.find_channel(self._rx_channel_names[m * 2])
channels.append(v)
v = self._rxadc.find_channel(self._rx_channel_names[m * 2 + 1])
channels.append(v)
else:
for m in self.rx_enabled_channels:
v = self._rxadc.find_channel(self._rx_channel_names[m])
channels.append(v)

self._rx_buffer_mask.channels = channels

self._rxbuf = iio.Buffer(self._rxadc, self._rx_buffer_mask)
self._rx_stream = iio.Stream(
buffer=self._rxbuf,
nb_blocks=self._rx_buffer_num_blocks,
samples_count=self.rx_buffer_size,
)

def _rx_buffered_data(self):
if not self._rx_stream:
self._rx_init_channels()

block = next(self._rx_stream)

data_channel_interleaved = []
for chan in self._rx_buffer_mask.channels:
bytearray_data = chan.read(block)
# create format strings
df = chan.data_format
fmt = ("i" if df.is_signed is True else "u") + str(df.length // 8)
data_channel_interleaved.append(np.frombuffer(bytearray_data, dtype=fmt))

return data_channel_interleaved


class compat_libiio_v1_tx:
"""Compatibility class for libiio v1.X TX."""

_tx_buffer_mask = None
_tx_stream = None
_tx_buffer_num_blocks = 4
_tx_block = None

def _tx_init_channels(self):
if not self._tx_buffer_mask:
self._tx_buffer_mask = iio.ChannelsMask(self._txdac)

channels = []
if self._complex_data:
for m in self.tx_enabled_channels:
v = self._txdac.find_channel(self._tx_channel_names[m * 2], True)
channels.append(v)
v = self._txdac.find_channel(self._tx_channel_names[m * 2 + 1], True)
channels.append(v)
else:
for m in self.tx_enabled_channels:
v = self._txdac.find_channel(self._tx_channel_names[m], True)
channels.append(v)

self._tx_buffer_mask.channels = channels

self._txbuf = iio.Buffer(self._txdac, self._tx_buffer_mask)
if not self._tx_cyclic_buffer:
self._tx_stream = iio.Stream(
buffer=self._txbuf,
nb_blocks=self._tx_buffer_num_blocks,
samples_count=self._tx_buffer_size,
)
else:
self._tx_block = iio.Block(self._txbuf, self._tx_buffer_size)

def _tx_buffer_push(self, data):
"""Push data to TX buffer.
data: bytearray
"""
if self._tx_cyclic_buffer:
self._tx_block.write(data)
self._tx_block.enqueue(None, self._tx_cyclic_buffer)
self._txbuf.enabled = True
else:
block = next(self._tx_stream)
block.write(data)


class compat_libiio_v0_rx:
"""Compatibility class for libiio v0.X RX."""

def _rx_init_channels(self):
for m in self._rx_channel_names:
v = self._rxadc.find_channel(m)
if not v:
raise Exception(f"Channel {m} not found")
v.enabled = False

if self._complex_data:
for m in self.rx_enabled_channels:
v = self._rxadc.find_channel(self._rx_channel_names[m * 2])
v.enabled = True
v = self._rxadc.find_channel(self._rx_channel_names[m * 2 + 1])
v.enabled = True
else:
for m in self.rx_enabled_channels:
v = self._rxadc.find_channel(self._rx_channel_names[m])
v.enabled = True
self._rxbuf = iio.Buffer(self._rxadc, self._rx_buffer_size, False)

def _rx_buffered_data(self) -> Union[List[np.ndarray], np.ndarray]:
"""_rx_buffered_data: Read data from RX buffer
Returns:
List of numpy arrays containing the data from the RX buffer that are
channel interleaved
"""
if not self._rxbuf:
self._rx_init_channels()
self._rxbuf.refill()

data_channel_interleaved = []
ecn = []
if self._complex_data:
for m in self.rx_enabled_channels:
ecn.extend(
(self._rx_channel_names[m * 2], self._rx_channel_names[m * 2 + 1])
)
else:
ecn = [self._rx_channel_names[m] for m in self.rx_enabled_channels]

for name in ecn:
chan = self._rxadc.find_channel(name)
bytearray_data = chan.read(self._rxbuf) # Do local type conversion
# create format strings
df = chan.data_format
fmt = ("i" if df.is_signed is True else "u") + str(df.length // 8)
data_channel_interleaved.append(np.frombuffer(bytearray_data, dtype=fmt))

return data_channel_interleaved


class compat_libiio_v0_tx:
"""Compatibility class for libiio v0.X TX."""

def _tx_init_channels(self):
if self._complex_data:
for m in self.tx_enabled_channels:
v = self._txdac.find_channel(self._tx_channel_names[m * 2], True)
v.enabled = True
v = self._txdac.find_channel(self._tx_channel_names[m * 2 + 1], True)
v.enabled = True
else:
for m in self.tx_enabled_channels:
v = self._txdac.find_channel(self._tx_channel_names[m], True)
v.enabled = True
self._txbuf = iio.Buffer(
self._txdac, self._tx_buffer_size, self._tx_cyclic_buffer
)

def _tx_buffer_push(self, data):
self._txbuf.write(bytearray(data))
self._txbuf.push()
Loading

0 comments on commit 34c7b10

Please sign in to comment.