From bd1113b303c687a00b2dc46b8fe63ff8d430abba Mon Sep 17 00:00:00 2001 From: "Travis F. Collins" Date: Fri, 1 Nov 2024 10:33:22 -0600 Subject: [PATCH 1/5] Enhance AD9084 class to access side B DMAs and DDSs Signed-off-by: Travis F. Collins --- adi/ad9084.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/adi/ad9084.py b/adi/ad9084.py index 4f48d97ce..3b689386b 100644 --- a/adi/ad9084.py +++ b/adi/ad9084.py @@ -4,7 +4,9 @@ from typing import Dict, List +from adi.adrv9002 import rx1, rx2, tx1, tx2 from adi.context_manager import context_manager +from adi.obs import obs, remap, tx_two from adi.rx_tx import rx_tx from adi.sync_start import sync_start @@ -59,19 +61,39 @@ class ad9084(rx_tx, context_manager, sync_start): _complex_data = True _rx_channel_names: List[str] = [] + _rx2_channel_names: List[str] = [] _tx_channel_names: List[str] = [] + _tx2_channel_names: List[str] = [] _tx_control_channel_names: List[str] = [] _rx_coarse_ddc_channel_names: List[str] = [] _tx_coarse_duc_channel_names: List[str] = [] _rx_fine_ddc_channel_names: List[str] = [] _tx_fine_duc_channel_names: List[str] = [] _dds_channel_names: List[str] = [] + _dds2_channel_names: List[str] = [] _device_name = "" _path_map: Dict[str, Dict[str, Dict[str, List[str]]]] = {} - def __init__(self, uri=""): - + def __init__( + self, + uri="", + rx1_device_name="axi-ad9084-rx-hpc", + rx2_device_name="axi-ad9084b-rx-b", + tx1_device_name="axi-ad9084-tx-hpc", + tx2_device_name="axi-ad9084-tx-b", + ): + """Create a new instance of the AD9084 MxFE + + rx1_device_name is used as the name for the control device and RX1/TX1 data device + + Args: + uri: URI of device + rx1_device_name: Name of RX1 device driver. Default is 'axi-ad9084-rx-hpc' + rx2_device_name: Name of RX2 device driver. Default is 'axi-ad9084b-rx-b' + tx1_device_name: Name of TX1 device driver. Default is 'axi-ad9084-tx-hpc' + tx2_device_name: Name of TX2 device driver. Default is 'axi-ad9084-tx-b' + """ # Reset default channel lists self._rx_channel_names = [] self._tx_channel_names = [] @@ -84,10 +106,19 @@ def __init__(self, uri=""): context_manager.__init__(self, uri, self._device_name) # Default device for attribute writes - self._ctrl = self._ctx.find_device("axi-ad9084-rx-hpc") + self._ctrl = self._ctx.find_device(rx1_device_name) # Devices with buffers - self._rxadc = self._ctx.find_device("axi-ad9084-rx-hpc") - self._txdac = self._ctx.find_device("axi-ad9084-tx-hpc") + self._rxadc = self._ctx.find_device(rx1_device_name) + self._txdac = self._ctx.find_device(tx1_device_name) + self._rxadc2 = self._ctx.find_device(rx2_device_name) + self._txdac2 = self._ctx.find_device(tx2_device_name) + # Checks + for dev, name in zip( + [self._rxadc, self._txdac, self._rxadc2, self._txdac2], + [rx1_device_name, tx1_device_name, rx2_device_name, tx2_device_name], + ): + if dev is None: + raise Exception(f"No device found with name {name}") # Get DDC and DUC mappings paths = {} @@ -101,16 +132,27 @@ def __init__(self, uri=""): for ch in self._rxadc.channels: if ch.scan_element and not ch.output: self._rx_channel_names.append(ch._id) + for ch in self._rxadc2.channels: + if ch.scan_element and not ch.output: + self._rx2_channel_names.append(ch._id) for ch in self._txdac.channels: if ch.scan_element: self._tx_channel_names.append(ch._id) else: self._dds_channel_names.append(ch._id) + for ch in self._txdac2.channels: + if ch.scan_element: + self._tx2_channel_names.append(ch._id) + else: + self._dds2_channel_names.append(ch._id) # Sort channel names self._rx_channel_names = _sortconv(self._rx_channel_names) + self._rx2_channel_names = _sortconv(self._rx2_channel_names) self._tx_channel_names = _sortconv(self._tx_channel_names) + self._tx2_channel_names = _sortconv(self._tx2_channel_names) self._dds_channel_names = _sortconv(self._dds_channel_names, dds=True) + self._dds2_channel_names = _sortconv(self._dds2_channel_names, dds=True) # Map unique attributes to channel properties self._rx_fine_ddc_channel_names = [] @@ -132,6 +174,18 @@ def __init__(self, uri=""): self._tx_coarse_duc_channel_names.append(channels[0]) self._tx_fine_duc_channel_names += channels + # Setup second DMA path + self._rx2 = obs(self._ctx, self._rxadc2, self._rx2_channel_names) + setattr(ad9084, "rx1", rx1) + setattr(ad9084, "rx2", rx2) + remap(self._rx2, "rx_", "rx2_", type(self)) + + self._tx2 = tx_two(self._ctx, self._txdac2, self._tx2_channel_names) + setattr(ad9084, "tx1", tx1) + setattr(ad9084, "tx2", tx2) + remap(self._tx2, "tx_", "tx2_", type(self)) + remap(self._tx2, "dds_", "dds2_", type(self)) + rx_tx.__init__(self) sync_start.__init__(self) self.rx_buffer_size = 2 ** 16 From d3f281733b2a2ab65fe82da4ecb3d18f95b1e810 Mon Sep 17 00:00:00 2001 From: "Travis F. Collins" Date: Fri, 1 Nov 2024 10:33:46 -0600 Subject: [PATCH 2/5] Add tests for new AD9084 side B features Signed-off-by: Travis F. Collins --- test/emu/hardware_map.yml | 14 ++++++++++++++ test/test_ad9084.py | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/test/emu/hardware_map.yml b/test/emu/hardware_map.yml index 48b1938f9..4ba0ac05d 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -272,6 +272,20 @@ packrf: - cf-ad9361-lpc,4 - pyadi_iio_class_support: - ad9361 +adsy1100: + - axi-ad9084-rx-hpc + - axi-ad9084-tx-hpc + - axi-ad9084b-rx-b + - axi-ad9084-tx-b + - pyadi_iio_class_support: + - ad9084 + - emulate: + - filename: adsy1100.xml + - data_devices: + - iio:device4 + - iio:device5 + - iio:device6 + - iio:device7 # Generics ad9361: diff --git a/test/test_ad9084.py b/test/test_ad9084.py index 291b5e3b8..6c994686f 100644 --- a/test/test_ad9084.py +++ b/test/test_ad9084.py @@ -304,3 +304,28 @@ def test_ad9084_nco_loopback( ######################################### +@pytest.mark.iio_hardware("adsy1100") +def test_split_rx_buffers(iio_uri): + import adi + + dev = adi.ad9084(uri=iio_uri) + dev.rx_buffer_size = 2 ** 10 + + d = dev.rx() + d1 = dev.rx1() + d2 = dev.rx2() + + assert d is not None + assert d1 is not None + assert d2 is not None + + +######################################### +@pytest.mark.iio_hardware("adsy1100") +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize("use_tx2", [False, True]) +def test_ad9084_tx_data_split_buffers( + test_dma_tx, iio_uri, classname, channel, use_tx2 +): + test_dma_tx(iio_uri, classname, channel, use_tx2) From c1f4ddbbb1809817764d4e4248068453516e69a5 Mon Sep 17 00:00:00 2001 From: "Travis F. Collins" Date: Fri, 1 Nov 2024 10:34:06 -0600 Subject: [PATCH 3/5] Update doc for AD9084 side B features Signed-off-by: Travis F. Collins --- doc/source/devices/adi.ad9084.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/source/devices/adi.ad9084.rst b/doc/source/devices/adi.ad9084.rst index 7025ab869..c3e6cc560 100644 --- a/doc/source/devices/adi.ad9084.rst +++ b/doc/source/devices/adi.ad9084.rst @@ -1,6 +1,8 @@ ad9081 ================= +AD9084 is a tiled chip with 2 halves or sides. The control interfaces are unified but the DMA and DDS controls are split into multiple methods. This is similar to ADRV9002 and its split DMA modes. There are multiple **rx** and **tx** methods to control the DMA and DDS for each side of the chip. The **rx** (and **rx1**) and **tx** (and **tx1**) methods are used to control the DMA and DDS for the first side of the chip. The **rx2** and **tx2** methods are used to control the DMA and DDS for the second side of the chip. + .. automodule:: adi.ad9084 :members: :undoc-members: From 9a63a61a747c181886f147bb202164fa5e90cccd Mon Sep 17 00:00:00 2001 From: "Travis F. Collins" Date: Fri, 1 Nov 2024 10:34:26 -0600 Subject: [PATCH 4/5] Add emulate context for ADSY1100 Signed-off-by: Travis F. Collins --- test/emu/devices/adsy1100.xml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 test/emu/devices/adsy1100.xml diff --git a/test/emu/devices/adsy1100.xml b/test/emu/devices/adsy1100.xml new file mode 100755 index 000000000..31ac21939 --- /dev/null +++ b/test/emu/devices/adsy1100.xml @@ -0,0 +1,4 @@ +]> \ No newline at end of file From e7acf211c1e8942d07803dd72e1da7403d8b0eea Mon Sep 17 00:00:00 2001 From: "Travis F. Collins" Date: Tue, 12 Nov 2024 09:24:06 -0700 Subject: [PATCH 5/5] Use newer ADSY1100 devices modeles for emulation Signed-off-by: Travis F. Collins --- test/test_ad9084.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/test_ad9084.py b/test/test_ad9084.py index 6c994686f..65550eee0 100644 --- a/test/test_ad9084.py +++ b/test/test_ad9084.py @@ -3,7 +3,8 @@ import pytest -hardware = ["ad9084", "ad9084_tdd"] +# hardware = ["ad9084", "ad9084_tdd"] # older builds +hardware = ["adsy1100"] classname = "adi.ad9084" @@ -96,7 +97,7 @@ def test_ad9084_rx_data(test_dma_rx, iio_uri, classname, channel): ######################################### @pytest.mark.iio_hardware(hardware) @pytest.mark.parametrize("classname", [(classname)]) -@pytest.mark.parametrize("channel", [0, 1, 2, 3]) +@pytest.mark.parametrize("channel", [0, 1]) def test_ad9084_tx_data(test_dma_tx, iio_uri, classname, channel): test_dma_tx(iio_uri, classname, channel) @@ -104,7 +105,7 @@ def test_ad9084_tx_data(test_dma_tx, iio_uri, classname, channel): ######################################### @pytest.mark.iio_hardware(hardware) @pytest.mark.parametrize("classname", [(classname)]) -@pytest.mark.parametrize("channel", [0, 1, 2, 3]) +@pytest.mark.parametrize("channel", [0, 1]) @pytest.mark.parametrize( "param_set", [ @@ -134,7 +135,7 @@ def test_ad9084_cyclic_buffers( ######################################### @pytest.mark.iio_hardware(hardware) @pytest.mark.parametrize("classname", [(classname)]) -@pytest.mark.parametrize("channel", [0, 1, 2, 3]) +@pytest.mark.parametrize("channel", [0, 1]) @pytest.mark.parametrize( "param_set", [