diff --git a/adi/__init__.py b/adi/__init__.py index 1579bd790..cbe06e81d 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -69,6 +69,7 @@ from adi.adrv9009_zu11eg import adrv9009_zu11eg from adi.adrv9009_zu11eg_fmcomms8 import adrv9009_zu11eg_fmcomms8 from adi.adrv9009_zu11eg_multi import adrv9009_zu11eg_multi +from adi.adrv9025 import adrv9025 from adi.adt7420 import adt7420 from adi.adxl313 import adxl313 from adi.adxl345 import adxl345 diff --git a/adi/adrv9025.py b/adi/adrv9025.py new file mode 100644 index 000000000..55228e4d8 --- /dev/null +++ b/adi/adrv9025.py @@ -0,0 +1,303 @@ +# Copyright (C) 2019-2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +from adi.context_manager import context_manager +from adi.jesd import jesd as jesdadi +from adi.obs import obs +from adi.rx_tx import rx_tx +from adi.sync_start import sync_start + + +class adrv9025(rx_tx, context_manager, sync_start): + """ADRV9025 Transceiver + + parameters: + uri: type=string + URI of context with ADRV9025 + jesd_monitor: type=boolean + Boolean flag to enable JESD monitoring. jesd input is + ignored otherwise. + jesd: type=adi.jesd + JESD object associated with ADRV9025 + """ + + _complex_data = True + _rx_channel_names = [ + "voltage0_i", + "voltage0_q", + "voltage1_i", + "voltage1_q", + "voltage2_i", + "voltage2_q", + "voltage3_i", + "voltage3_q", + ] + _tx_channel_names = [ + "voltage0_i", + "voltage0_q", + "voltage1_i", + "voltage1_q", + "voltage2_i", + "voltage2_q", + "voltage3_i", + "voltage3_q", + ] + _device_name = "" + + def __init__(self, uri="", jesd_monitor=False, jesd=None): + + context_manager.__init__(self, uri, self._device_name) + + self._ctrl = self._ctx.find_device("adrv9025-phy") + self._rxadc = self._ctx.find_device("axi-adrv9025-rx-hpc") + self._txdac = self._ctx.find_device("axi-adrv9025-tx-hpc") + self._ctx.set_timeout(30000) # Needed for loading profiles + if jesdadi and jesd_monitor: + self._jesd = jesd if jesd else jesdadi(uri=uri) + rx_tx.__init__(self) + + # @property + # def profile(self): + # """Load profile file. Provide path to profile file to attribute""" + # return self._get_iio_dev_attr("profile_config") + + # @profile.setter + # def profile(self, value): + # with open(value, "r") as file: + # data = file.read() + # # Apply profiles in specific order if multiple phys found + # phys = [p for p in self.__dict__.keys() if "_ctrl" in p] + # phys = sorted(phys) + # for phy in phys[1:] + [phys[0]]: + # self._set_iio_dev_attr_str("profile_config", data, getattr(self, phy)) + + @property + def en0_rx(self): + """en0_rx: Enable channel 0 RX""" + return self._get_iio_attr("voltage0", "en", False) + + @en0_rx.setter + def en0_rx(self, value): + self._set_iio_attr("voltage0", "en", False, value) + + @property + def en1_rx(self): + """en1_rx: Enable channel 1 RX""" + return self._get_iio_attr("voltage1", "en", False) + + @en1_rx.setter + def en1_rx(self, value): + self._set_iio_attr("voltage1", "en", False, value) + + @property + def en0_tx(self): + """en0_tx: Enable channel 0 TX""" + return self._get_iio_attr("voltage0", "en", True) + + @en0_tx.setter + def en0_tx(self, value): + self._set_iio_attr("voltage0", "en", True, value) + + @property + def en1_tx(self): + """en1_tx: Enable channel 1 TX""" + return self._get_iio_attr("voltage1", "en", True) + + @en1_tx.setter + def en1_tx(self, value): + self._set_iio_attr("voltage1", "en", True, value) + + @property + def calibrate_rx_qec_en(self): + """calibrate_rx_qec_en: Enable RX QEC Calibration""" + return self._get_iio_dev_attr("calibrate_rx_qec_en") + + @calibrate_rx_qec_en.setter + def calibrate_rx_qec_en(self, value): + self._set_iio_dev_attr_str("calibrate_rx_qec_en", value) + + @property + def calibrate_tx_qec_en(self): + """calibrate_tx_qec_en: Enable TX QEC Calibration""" + return self._get_iio_dev_attr("calibrate_tx_qec_en") + + @calibrate_tx_qec_en.setter + def calibrate_tx_qec_en(self, value): + self._set_iio_dev_attr_str("calibrate_tx_qec_en", value) + + @property + def calibrate(self): + """calibrate: Trigger Calibration""" + return self._get_iio_dev_attr("calibrate") + + @calibrate.setter + def calibrate(self, value): + self._set_iio_dev_attr_str("calibrate", value) + + @property + def gain_control_mode_chan0(self): + """gain_control_mode_chan0: Mode of receive path AGC. Options are: + slow_attack, manual""" + return self._get_iio_attr_str("voltage0", "gain_control_mode", False) + + @gain_control_mode_chan0.setter + def gain_control_mode_chan0(self, value): + self._set_iio_attr("voltage0", "gain_control_mode", False, value) + + @property + def gain_control_mode_chan1(self): + """gain_control_mode_chan1: Mode of receive path AGC. Options are: + slow_attack, manual""" + return self._get_iio_attr_str("voltage1", "gain_control_mode", False) + + @gain_control_mode_chan1.setter + def gain_control_mode_chan1(self, value): + self._set_iio_attr("voltage1", "gain_control_mode", False, value) + + @property + def rx_quadrature_tracking_en_chan0(self): + """Enable Quadrature tracking calibration for RX1""" + return self._get_iio_attr("voltage0", "quadrature_tracking_en", False) + + @rx_quadrature_tracking_en_chan0.setter + def rx_quadrature_tracking_en_chan0(self, value): + self._set_iio_attr("voltage0", "quadrature_tracking_en", False, value) + + @property + def rx_quadrature_tracking_en_chan1(self): + """Enable Quadrature tracking calibration for RX2""" + return self._get_iio_attr("voltage1", "quadrature_tracking_en", False) + + @rx_quadrature_tracking_en_chan1.setter + def rx_quadrature_tracking_en_chan1(self, value): + self._set_iio_attr("voltage1", "quadrature_tracking_en", False, value) + + @property + def rx_hardwaregain_chan0(self): + """rx_hardwaregain: Gain applied to RX path channel 0. Only applicable when + gain_control_mode is set to 'manual'""" + return self._get_iio_attr("voltage0", "hardwaregain", False) + + @rx_hardwaregain_chan0.setter + def rx_hardwaregain_chan0(self, value): + if self.gain_control_mode_chan0 == "manual": + self._set_iio_attr("voltage0", "hardwaregain", False, value) + + @property + def rx_hardwaregain_chan1(self): + """rx_hardwaregain: Gain applied to RX path channel 1. Only applicable when + gain_control_mode is set to 'manual'""" + return self._get_iio_attr("voltage1", "hardwaregain", False) + + @rx_hardwaregain_chan1.setter + def rx_hardwaregain_chan1(self, value): + if self.gain_control_mode_chan1 == "manual": + self._set_iio_attr("voltage1", "hardwaregain", False, value) + + @property + def tx_quadrature_tracking_en_chan0(self): + """Enable Quadrature tracking calibration for TX1""" + return self._get_iio_attr("voltage0", "quadrature_tracking_en", True) + + @tx_quadrature_tracking_en_chan0.setter + def tx_quadrature_tracking_en_chan0(self, value): + self._set_iio_attr("voltage0", "quadrature_tracking_en", True, value) + + @property + def tx_quadrature_tracking_en_chan1(self): + """Enable Quadrature tracking calibration for TX2""" + return self._get_iio_attr("voltage1", "quadrature_tracking_en", True) + + @tx_quadrature_tracking_en_chan1.setter + def tx_quadrature_tracking_en_chan1(self, value): + self._set_iio_attr("voltage1", "quadrature_tracking_en", True, value) + + @property + def tx_hardwaregain_chan0(self): + """tx_hardwaregain: Attenuation applied to TX path channel 0""" + return self._get_iio_attr("voltage0", "hardwaregain", True) + + @tx_hardwaregain_chan0.setter + def tx_hardwaregain_chan0(self, value): + self._set_iio_attr("voltage0", "hardwaregain", True, value) + + @property + def tx_hardwaregain_chan1(self): + """tx_hardwaregain: Attenuation applied to TX path channel 1""" + return self._get_iio_attr("voltage1", "hardwaregain", True) + + @tx_hardwaregain_chan1.setter + def tx_hardwaregain_chan1(self, value): + self._set_iio_attr("voltage1", "hardwaregain", True, value) + + @property + def rx_rf_bandwidth(self): + """rx_rf_bandwidth: Bandwidth of front-end analog filter of RX path""" + return self._get_iio_attr("voltage0", "rf_bandwidth", False) + + @property + def tx_rf_bandwidth(self): + """tx_rf_bandwidth: Bandwidth of front-end analog filter of TX path""" + return self._get_iio_attr("voltage0", "rf_bandwidth", True) + + @property + def rx_sample_rate(self): + """rx_sample_rate: Sample rate RX path in samples per second""" + return self._get_iio_attr("voltage0", "sampling_frequency", False) + + @property + def tx_sample_rate(self): + """tx_sample_rate: Sample rate TX path in samples per second""" + return self._get_iio_attr("voltage0", "sampling_frequency", True) + + @property + def lo1(self): + """lo1: Carrier frequency of LO1""" + return self._get_iio_attr("LO1", "frequency", True) + + @lo1.setter + def lo1(self, value): + self._set_iio_attr("LO1", "frequency", True, value) + + @property + def lo2(self): + """lo2: Carrier frequency of LO2""" + return self._get_iio_attr("LO2", "frequency", True) + + @lo2.setter + def lo2(self, value): + self._set_iio_attr("LO2", "frequency", True, value) + + @property + def jesd204_fsm_ctrl(self): + """jesd204_fsm_ctrl: jesd204-fsm control""" + return self._get_iio_dev_attr("jesd204_fsm_ctrl") + + @jesd204_fsm_ctrl.setter + def jesd204_fsm_ctrl(self, value): + self._set_iio_dev_attr_str("jesd204_fsm_ctrl", value) + + @property + def jesd204_fsm_resume(self): + """jesd204_fsm_resume: jesd204-fsm resume""" + return self._get_iio_dev_attr("jesd204_fsm_resume") + + @jesd204_fsm_resume.setter + def jesd204_fsm_resume(self, value): + self._set_iio_dev_attr_str("jesd204_fsm_resume", value) + + @property + def jesd204_fsm_state(self): + """jesd204_fsm_state: jesd204-fsm state""" + return self._get_iio_dev_attr_str("jesd204_fsm_state") + + @property + def jesd204_fsm_paused(self): + """jesd204_fsm_paused: jesd204-fsm paused""" + return self._get_iio_dev_attr("jesd204_fsm_paused") + + @property + def jesd204_fsm_error(self): + """jesd204_fsm_error: jesd204-fsm error""" + return self._get_iio_dev_attr("jesd204_fsm_error") diff --git a/adi/dds.py b/adi/dds.py index 1d412cc9a..0d185b731 100644 --- a/adi/dds.py +++ b/adi/dds.py @@ -16,11 +16,34 @@ class dds(attribute): def __update_dds(self, attr, value): split_cores_indx = 0 + altvoltage_channels = [] + for chan in self._txdac.channels: + if hasattr(chan, "id") and chan.id.startswith("altvoltage"): + altvoltage_channels.append(chan.id) + # Sort channels by name. Names are in the format altvoltageX + altvoltage_channels.sort(key=lambda x: int(x[10:])) + if len(value) > len(altvoltage_channels): + raise Exception( + f"Number of values ({len(value)}) exceeds number of DDS channels ({len(altvoltage_channels)})" + ) + + if not self._split_cores: + for i, chan_name in enumerate(altvoltage_channels): + if i >= len(value): + return + chan = self._txdac.find_channel(chan_name, True) + if attr == "raw": + chan.attrs[attr].value = str(int(value[i])) + else: + chan.attrs[attr].value = str(value[i]) + return + # old implementation since it handles split cores for indx in range(len(self._txdac.channels)): - chan = self._txdac.find_channel("altvoltage" + str(indx), True) + chan = self._txdac.find_channel(f"altvoltage{str(indx)}", True) + # Special FMComms5 case if not chan and self._split_cores: chan = self._txdac_chip_b.find_channel( - "altvoltage" + str(split_cores_indx), True + f"altvoltage{str(split_cores_indx)}", True ) split_cores_indx = split_cores_indx + 1 if not chan: @@ -36,6 +59,21 @@ def __update_dds(self, attr, value): def _read_dds(self, attr): values = [] split_cores_indx = 0 + + altvoltage_channels = [] + for chan in self._txdac.channels: + if hasattr(chan, "id") and chan.id.startswith("altvoltage"): + altvoltage_channels.append(chan.id) + # Sort channels by name. Names are in the format altvoltageX + altvoltage_channels.sort(key=lambda x: int(x[10:])) + + if not self._split_cores: + for chan_name in altvoltage_channels: + chan = self._txdac.find_channel(chan_name, True) + values.append(chan.attrs[attr].value) + return values + + # old implementation since it handles split cores for indx in range(len(self._txdac.channels)): chan = self._txdac.find_channel("altvoltage" + str(indx), True) if not chan and self._split_cores: @@ -142,6 +180,8 @@ def dds_single_tone(self, frequency, scale, channel=0): + "_F1", True, ) + if not chan: + Exception(f"Cannot find channel {channel}") chan.attrs["frequency"].value = str(frequency) chan.attrs["phase"].value = str(90000) chan.attrs["scale"].value = str(scale) @@ -157,6 +197,8 @@ def dds_single_tone(self, frequency, scale, channel=0): + "_F1", True, ) + if not chan: + Exception(f"Cannot find channel {channel}") chan.attrs["frequency"].value = str(frequency) chan.attrs["phase"].value = str(0) chan.attrs["scale"].value = str(scale) diff --git a/doc/source/devices/adi.adrv9025.rst b/doc/source/devices/adi.adrv9025.rst new file mode 100644 index 000000000..feeb5236a --- /dev/null +++ b/doc/source/devices/adi.adrv9025.rst @@ -0,0 +1,14 @@ +adrv9025/adrv9026/adrv9029 +=========================== + +`ADRV9026/ADRV9029 product page `_ + +`IC Support `_ + +`Driver documentation `_ + + +.. automodule:: adi.adrv9025 + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index 07441c7d6..fe0a6b09d 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -77,6 +77,7 @@ Supported Devices adi.adrv9009_zu11eg adi.adrv9009_zu11eg_fmcomms8 adi.adrv9009_zu11eg_multi + adi.adrv9025 adi.adt7420 adi.adxl313 adi.adxl345 diff --git a/supported_parts.md b/supported_parts.md index 1673d7740..83598b47e 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -133,6 +133,9 @@ - ADRV9008-1/2 - ADRV9009 - ADRV9009-ZU11EG +- ADRV9025 +- ADRV9026 +- ADRV9029 - ADT7420 - ADXL312 - ADXL313 diff --git a/test/emu/devices/adrv9025.xml b/test/emu/devices/adrv9025.xml new file mode 100644 index 000000000..48c18fb8b --- /dev/null +++ b/test/emu/devices/adrv9025.xml @@ -0,0 +1,1110 @@ + + + + + + + + + + + + + + + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/emu/hardware_map.yml b/test/emu/hardware_map.yml index 72e8aa140..cc3ee2350 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -307,6 +307,14 @@ adrv9375: - iio:device4 - iio:device5 - iio:device6 +adrv9025: +- adrv9025-phy +- emulate: + - filename: adrv9025.xml + - data_devices: + - iio:device3 + - iio:device4 + adxl345: - adxl345 - pyadi_iio_class_support: diff --git a/test/test_adrv9025_p.py b/test/test_adrv9025_p.py new file mode 100644 index 000000000..56b147348 --- /dev/null +++ b/test/test_adrv9025_p.py @@ -0,0 +1,893 @@ +from os import listdir +from os.path import dirname, join, realpath + +import pytest + +import adi.jesd as jesd +skip_jesd = jesd is None + +hardware = ["adrv9025"] +classname = "adi.adrv9025" + +# profile_path = dirname(realpath(__file__)) + "/adrv9025_profiles/" +# test_profiles = [join(profile_path, f) for f in listdir(profile_path)] + +params = dict( + one_cw_tone_manual=dict( + trx_lo=2500000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + one_cw_tone_slow_attack=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_attenuation_5dB_manual=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=-5, + tx_hardwaregain_chan1=-5, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_attenuation_10dB_manual=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_attenuation_0dB_slow_attack=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_attenuation_20dB_slow_attack=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=-20, + tx_hardwaregain_chan1=-20, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_rf_gain_0dB_manual=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + rx_hardwaregain_chan0=0, + rx_hardwaregain_chan1=0, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_rf_gain_20dB_manual=dict( + ensm_mode="radio_on", + trx_lo=2500000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + obs_powerdown_en=1, + rx_powerdown_en_chan0=0, + rx_powerdown_en_chan1=0, + rx_hardwaregain_chan0=20, + rx_hardwaregain_chan1=20, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_trx_lo_1GHz_slow_attack=dict( + trx_lo=1000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_trx_lo_3GHz_slow_attack=dict( + trx_lo=3000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), + change_trx_lo_5GHz_slow_attack=dict( + trx_lo=5000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_rx_qec_en=1, + calibrate_tx_qec_en=1, + calibrate=1, + ), +) + +# params_obs = dict( +# obs_tx=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_TX_LO", +# obs_hardwaregain=0, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_tx_change_attenuation_10dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=-10, +# tx_hardwaregain_chan1=-10, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_TX_LO", +# obs_hardwaregain=0, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_tx_change_rf_gain_10dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_TX_LO", +# obs_hardwaregain=10, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_tx_change_rf_gain_5dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_TX_LO", +# obs_hardwaregain=5, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_aux=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_AUX_LO", +# obs_hardwaregain=0, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_aux_change_attenuation_10dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=-10, +# tx_hardwaregain_chan1=-10, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_AUX_LO", +# obs_hardwaregain=0, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_aux_change_rf_gain_10dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_AUX_LO", +# obs_hardwaregain=10, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# obs_aux_change_rf_gain_5dB=dict( +# ensm_mode="radio_on", +# trx_lo=2500000000, +# rx_powerdown_en_chan0=1, +# rx_powerdown_en_chan1=1, +# obs_powerdown_en=0, +# tx_hardwaregain_chan0=0, +# tx_hardwaregain_chan1=0, +# tx_quadrature_tracking_en_chan0=1, +# tx_quadrature_tracking_en_chan1=1, +# aux_obs_lo=2500000000, +# obs_quadrature_tracking_en=1, +# obs_rf_port_select="OBS_AUX_LO", +# obs_hardwaregain=5, +# calibrate_rx_qec_en=1, +# calibrate_tx_qec_en=1, +# calibrate=1, +# ), +# ) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol", + [ + ("tx_hardwaregain_chan0", -41.95, 0.0, 0.05, 0.05), + ("tx_hardwaregain_chan1", -41.95, 0.0, 0.05, 0.05), + ("trx_lo", 70000000, 6000000000, 1000, 0), + ], +) +def test_adrv9025_attr( + test_attribute_single_value, iio_uri, classname, attr, start, stop, step, tol +): + test_attribute_single_value(iio_uri, classname, attr, start, stop, step, tol) + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", range(2)) +def test_adrv9025_rx_data(test_dma_rx, iio_uri, classname, channel): + test_dma_rx(iio_uri, classname, channel) + + +######################################## +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, frequency, scale, peak_min", + [ + (params["one_cw_tone_manual"], 2000000, 0.5, -42), + (params["one_cw_tone_manual"], 2000000, 0.12, -55), + (params["one_cw_tone_manual"], 2000000, 0.25, -48), + (params["one_cw_tone_slow_attack"], 1000000, 0.12, -44), + (params["one_cw_tone_slow_attack"], 2000000, 0.12, -44), + (params["one_cw_tone_slow_attack"], 500000, 0.12, -44), + (params["change_attenuation_5dB_manual"], 2000000, 0.25, -53), + (params["change_attenuation_10dB_manual"], 2000000, 0.25, -58), + (params["change_attenuation_0dB_slow_attack"], 1000000, 0.12, -35), + (params["change_attenuation_20dB_slow_attack"], 1000000, 0.12, -54), + (params["change_rf_gain_0dB_manual"], 2000000, 0.25, -59), + (params["change_rf_gain_20dB_manual"], 2000000, 0.25, -38), + ], +) +def test_adrv9025_dds_loopback( + test_dds_loopback, + iio_uri, + classname, + param_set, + channel, + frequency, + scale, + peak_min, +): + test_dds_loopback( + iio_uri, classname, param_set, channel, frequency, scale, peak_min + ) + + +######################################## +@pytest.mark.obs_required +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, frequency, scale", + [ + (params["one_cw_tone_manual"], 2000000, 0.5), + (params["one_cw_tone_manual"], 2000000, 0.12), + (params["one_cw_tone_manual"], 2000000, 0.25), + (params["one_cw_tone_slow_attack"], 1000000, 0.12), + (params["one_cw_tone_slow_attack"], 2000000, 0.12), + (params["one_cw_tone_slow_attack"], 500000, 0.12), + (params["change_attenuation_5dB_manual"], 2000000, 0.25), + (params["change_attenuation_10dB_manual"], 2000000, 0.25), + (params["change_attenuation_0dB_slow_attack"], 1000000, 0.12), + (params["change_attenuation_20dB_slow_attack"], 1000000, 0.12), + (params["change_rf_gain_0dB_manual"], 2000000, 0.25), + (params["change_rf_gain_20dB_manual"], 2000000, 0.25), + ], +) +@pytest.mark.parametrize("peak_min", [-50]) +def test_adrv9025_dds_loopback_with_10dB_splitter( + test_dds_loopback, + iio_uri, + classname, + param_set, + channel, + frequency, + scale, + peak_min, +): + test_dds_loopback( + iio_uri, classname, param_set, channel, frequency, scale, peak_min + ) + + +######################################## +# @pytest.mark.obs_required +# @pytest.mark.iio_hardware(hardware) +# @pytest.mark.parametrize("classname", [(classname)]) +# @pytest.mark.parametrize( +# "channel, param_set", +# [ +# (0, params_obs["obs_tx"]), +# (0, params_obs["obs_tx_change_attenuation_10dB"]), +# (0, params_obs["obs_tx_change_rf_gain_10dB"]), +# (0, params_obs["obs_tx_change_rf_gain_5dB"]), +# (0, params_obs["obs_aux"]), +# (0, params_obs["obs_aux_change_attenuation_10dB"]), +# (0, params_obs["obs_aux_change_rf_gain_10dB"]), +# (0, params_obs["obs_aux_change_rf_gain_5dB"]), +# ], +# ) +# @pytest.mark.parametrize( +# "frequency, scale, peak_min, use_obs", [(50000000, 0.25, -40.5, True)] +# ) +# def test_adrv9025_dds_loopback_for_obs( +# test_dds_loopback, +# iio_uri, +# classname, +# param_set, +# channel, +# frequency, +# scale, +# peak_min, +# use_obs, +# ): +# test_dds_loopback( +# iio_uri, classname, param_set, channel, frequency, scale, peak_min, use_obs +# ) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, frequency1, scale1, peak_min1, frequency2, scale2, peak_min2", + [(params["one_cw_tone_slow_attack"], 1000000, 0.06, -21, 2000000, 0.12, -15)], +) +def test_adrv9025_two_tone_loopback( + test_dds_two_tone, + iio_uri, + classname, + channel, + param_set, + frequency1, + scale1, + peak_min1, + frequency2, + scale2, + peak_min2, +): + test_dds_two_tone( + iio_uri, + classname, + channel, + param_set, + frequency1, + scale1, + peak_min1, + frequency2, + scale2, + peak_min2, + ) + + +######################################### +@pytest.mark.obs_required +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, frequency1, scale1, peak_min1, frequency2, scale2, peak_min2", + [(params["one_cw_tone_slow_attack"], 1000000, 0.06, -41, 2000000, 0.12, -35)], +) +def test_adrv9025_two_tone_loopback_with_10dB_splitter( + test_dds_two_tone, + iio_uri, + classname, + channel, + param_set, + frequency1, + scale1, + peak_min1, + frequency2, + scale2, + peak_min2, +): + test_dds_two_tone( + iio_uri, + classname, + channel, + param_set, + frequency1, + scale1, + peak_min1, + frequency2, + scale2, + peak_min2, + ) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set", + [ + params["one_cw_tone_manual"], + params["one_cw_tone_slow_attack"], + params["change_attenuation_5dB_manual"], + params["change_attenuation_10dB_manual"], + params["change_attenuation_0dB_slow_attack"], + params["change_attenuation_20dB_slow_attack"], + params["change_rf_gain_0dB_manual"], + params["change_rf_gain_20dB_manual"], + params["change_trx_lo_1GHz_slow_attack"], + params["change_trx_lo_3GHz_slow_attack"], + params["change_trx_lo_5GHz_slow_attack"], + ], +) +@pytest.mark.parametrize("sfdr_min", [30]) +def test_adrv9025_sfdr(test_sfdr, iio_uri, classname, channel, param_set, sfdr_min): + test_sfdr(iio_uri, classname, channel, param_set, sfdr_min) + + +######################################### +@pytest.mark.obs_required +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set", + [ + params["one_cw_tone_manual"], + params["one_cw_tone_slow_attack"], + params["change_attenuation_5dB_manual"], + params["change_attenuation_10dB_manual"], + params["change_attenuation_0dB_slow_attack"], + params["change_attenuation_20dB_slow_attack"], + params["change_rf_gain_0dB_manual"], + params["change_rf_gain_20dB_manual"], + params["change_trx_lo_1GHz_slow_attack"], + params["change_trx_lo_3GHz_slow_attack"], + params["change_trx_lo_5GHz_slow_attack"], + ], +) +@pytest.mark.parametrize("sfdr_min", [40]) +def test_adrv9025_sfdr_with_10dB_splitter( + test_sfdr, iio_uri, classname, channel, param_set, sfdr_min +): + test_sfdr(iio_uri, classname, channel, param_set, sfdr_min) + + +######################################### +# @pytest.mark.obs_required +# @pytest.mark.iio_hardware(hardware) +# @pytest.mark.parametrize("classname", [(classname)]) +# @pytest.mark.parametrize("channel", [0, 1]) +# @pytest.mark.parametrize( +# "param_set", +# [ +# params_obs["obs_tx"], +# params_obs["obs_tx_change_attenuation_10dB"], +# params_obs["obs_tx_change_rf_gain_10dB"], +# params_obs["obs_tx_change_rf_gain_5dB"], +# params_obs["obs_aux"], +# params_obs["obs_aux_change_attenuation_10dB"], +# params_obs["obs_aux_change_rf_gain_10dB"], +# params_obs["obs_aux_change_rf_gain_5dB"], +# ], +# ) +# @pytest.mark.parametrize("sfdr_min", [45]) +# @pytest.mark.parametrize("use_obs", [True]) +# def test_adrv9025_sfdr_for_obs( +# test_sfdr, iio_uri, classname, channel, param_set, sfdr_min, use_obs +# ): +# test_sfdr(iio_uri, classname, channel, param_set, sfdr_min, use_obs) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, dds_scale, min_rssi, max_rssi", + [ + (params["one_cw_tone_slow_attack"], 0.12, 33.5, 41.5), + (params["change_attenuation_0dB_slow_attack"], 0.12, 24, 32), + (params["change_attenuation_20dB_slow_attack"], 0.12, 40, 45.5), + (params["change_trx_lo_1GHz_slow_attack"], 0, 35, 60), + (params["change_trx_lo_1GHz_slow_attack"], 0.9, 25, 35), + (params["change_trx_lo_3GHz_slow_attack"], 0, 35, 60), + (params["change_trx_lo_3GHz_slow_attack"], 0.9, 0, 22), + (params["change_trx_lo_5GHz_slow_attack"], 0, 35, 60), + (params["change_trx_lo_5GHz_slow_attack"], 0.9, 20, 25), + ], +) +def test_adrv9025_dds_gain_check_agc( + test_gain_check, + iio_uri, + classname, + channel, + param_set, + dds_scale, + min_rssi, + max_rssi, +): + test_gain_check( + iio_uri, classname, channel, param_set, dds_scale, min_rssi, max_rssi + ) + + +######################################### +@pytest.mark.obs_required +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, dds_scale, min_rssi", + [ + (params["one_cw_tone_slow_attack"], 0.12, 40), + (params["change_attenuation_0dB_slow_attack"], 0.12, 30), + (params["change_attenuation_20dB_slow_attack"], 0.12, 43.5), + (params["change_trx_lo_1GHz_slow_attack"], 0, 43.5), + (params["change_trx_lo_1GHz_slow_attack"], 0.9, 30), + (params["change_trx_lo_3GHz_slow_attack"], 0, 43.75), + (params["change_trx_lo_3GHz_slow_attack"], 0.9, 23), + (params["change_trx_lo_5GHz_slow_attack"], 0, 43.75), + (params["change_trx_lo_5GHz_slow_attack"], 0.9, 25), + ], +) +@pytest.mark.parametrize("max_rssi", [50]) +def test_adrv9025_dds_gain_check_agc_with_10db_splitter( + test_gain_check, + iio_uri, + classname, + channel, + param_set, + dds_scale, + min_rssi, + max_rssi, +): + test_gain_check( + iio_uri, classname, channel, param_set, dds_scale, min_rssi, max_rssi + ) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, dds_scale, min_rssi, max_rssi", + [ + (params["one_cw_tone_manual"], 0.5, 30, 40), + (params["one_cw_tone_manual"], 0.12, 40, 45), + (params["one_cw_tone_manual"], 0.25, 35, 45), + (params["change_attenuation_5dB_manual"], 0.25, 40, 45), + (params["change_attenuation_10dB_manual"], 0.25, 40, 45), + (params["change_rf_gain_0dB_manual"], 0.25, 40, 45), + (params["change_rf_gain_20dB_manual"], 0.25, 25, 35), + ( + dict( + trx_lo=1000000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + rx_hardwaregain_chan0=0, + rx_hardwaregain_chan1=0, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_tx_qec_en=1, + calibrate=1, + ), + 0.5, + 20, + 60, + ), + ( + dict( + trx_lo=1000000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + rx_hardwaregain_chan0=30, + rx_hardwaregain_chan1=30, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_tx_qec_en=1, + calibrate=1, + ), + 0.5, + 30, + 45, + ), + ], +) +def test_adrv9025_dds_gain_check_vary_power( + test_gain_check, + iio_uri, + classname, + channel, + param_set, + dds_scale, + min_rssi, + max_rssi, +): + test_gain_check( + iio_uri, classname, channel, param_set, dds_scale, min_rssi, max_rssi + ) + + +######################################### +@pytest.mark.obs_required +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0, 1]) +@pytest.mark.parametrize( + "param_set, dds_scale, min_rssi, max_rssi", + [ + (params["one_cw_tone_manual"], 0.5, 38, 45), + (params["one_cw_tone_manual"], 0.12, 43, 45), + (params["one_cw_tone_manual"], 0.25, 43, 45), + (params["change_attenuation_5dB_manual"], 0.25, 43, 45), + (params["change_attenuation_10dB_manual"], 0.25, 43, 45), + (params["change_rf_gain_0dB_manual"], 0.25, 42.5, 44.5), + (params["change_rf_gain_20dB_manual"], 0.25, 34, 44), + ( + dict( + trx_lo=1000000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + rx_hardwaregain_chan0=0, + rx_hardwaregain_chan1=0, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_tx_qec_en=1, + calibrate=1, + ), + 0.5, + 42.5, + 44.5, + ), + ( + dict( + trx_lo=1000000000, + gain_control_mode_chan0="manual", + gain_control_mode_chan1="manual", + rx_hardwaregain_chan0=30, + rx_hardwaregain_chan1=30, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + calibrate_tx_qec_en=1, + calibrate=1, + ), + 0.5, + 36, + 43.5, + ), + ], +) +def test_adrv9025_dds_gain_check_vary_power_with_10dB_splitter( + test_gain_check, + iio_uri, + classname, + channel, + param_set, + dds_scale, + min_rssi, + max_rssi, +): + test_gain_check( + iio_uri, classname, channel, param_set, dds_scale, min_rssi, max_rssi + ) + + +######################################### +# TODO: Test, see what's its difference with dds_loopback, PROBLEMATIC +# OSError: [Errno 5] Input/output error +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0]) +@pytest.mark.parametrize( + "param_set", + [ + dict( + trx_lo=1000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-20, + tx_hardwaregain_chan1=-20, + calibrate_tx_qec_en=1, + calibrate=1, + ), + dict( + trx_lo=3000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-20, + tx_hardwaregain_chan1=-20, + calibrate_tx_qec_en=1, + calibrate=1, + ), + dict( + trx_lo=5000000000, + trx_lo_chip_b=1000000000, + gain_control_mode_chan0="slow_attack", + gain_control_mode_chan1="slow_attack", + tx_hardwaregain_chan0=-20, + tx_hardwaregain_chan1=-20, + calibrate_tx_qec_en=1, + calibrate=1, + ), + ], +) +def test_adrv9025_iq_loopback(test_iq_loopback, iio_uri, classname, channel, param_set): + test_iq_loopback(iio_uri, classname, channel, param_set) + + +######################################### +# @pytest.mark.iio_hardware(hardware) +# @pytest.mark.parametrize("classname", [(classname)]) +# @pytest.mark.parametrize("attr", ["profile"]) +# @pytest.mark.parametrize( +# "files", test_profiles, +# ) +# def test_adrv9025_profile_write( +# test_attribute_write_only_str, iio_uri, classname, attr, files +# ): +# test_attribute_write_only_str(iio_uri, classname, attr, files) + + +######################################### +@pytest.mark.skipif(skip_jesd, reason="JESD module not importable") +@pytest.mark.iio_hardware(hardware) +def test_adrv9025_jesd(iio_uri): + import adi + + sdr = adi.adrv9025(uri=iio_uri, jesd_monitor=True) + info = sdr._jesd.get_all_statuses() + assert info