diff --git a/adi/__init__.py b/adi/__init__.py index 5f49b8de8..fc6e920f7 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -9,6 +9,7 @@ from adi.ad719x import ad719x from adi.ad777x import ad777x from adi.ad936x import Pluto, ad9361, ad9363, ad9364 +from adi.ad937x import ad9371, ad9375 from adi.ad4020 import ad4020 from adi.ad4110 import ad4110 from adi.ad4130 import ad4130 @@ -40,7 +41,6 @@ from adi.ad9172 import ad9172 from adi.ad9250 import ad9250 from adi.ad9265 import ad9265 -from adi.ad9371 import ad9371 from adi.ad9434 import ad9434 from adi.ad9467 import ad9467 from adi.ad9625 import ad9625 diff --git a/adi/ad9371.py b/adi/ad9371.py deleted file mode 100644 index cb20fb3d5..000000000 --- a/adi/ad9371.py +++ /dev/null @@ -1,325 +0,0 @@ -# Copyright (C) 2019-2023 Analog Devices, Inc. -# -# SPDX short identifier: ADIBSD - -from adi.context_manager import context_manager -from adi.jesd import jesd -from adi.obs import obs -from adi.rx_tx import rx_tx -from adi.sync_start import sync_start - - -class ad9371(rx_tx, context_manager, sync_start): - """ AD9371 Transceiver """ - - _complex_data = True - _rx_channel_names = ["voltage0_i", "voltage0_q", "voltage1_i", "voltage1_q"] - _tx_channel_names = ["voltage0", "voltage1", "voltage2", "voltage3"] - _obs_channel_names = ["voltage0_i", "voltage0_q"] - _device_name = "" - - def __init__( - self, uri="", username="root", password="analog", disable_jesd_control=False - ): - """Initialize AD9371 interface class. - Args: - uri (str): URI of target platform with AD9371 - username (str): SSH username for target board. Required for JESD monitoring - password (str): SSH password for target board. Required for JESD monitoring - disable_jesd_control (bool): Disable JESD status monitoring over SSH - """ - context_manager.__init__(self, uri, self._device_name) - - self._ctrl = self._ctx.find_device("ad9371-phy") - self._rxadc = self._ctx.find_device("axi-ad9371-rx-hpc") - self._rxobs = self._ctx.find_device("axi-ad9371-rx-obs-hpc") - self._txdac = self._ctx.find_device("axi-ad9371-tx-hpc") - - if not disable_jesd_control and jesd: - self._jesd = jesd(uri, username=username, password=password) - - rx_tx.__init__(self) - - self.obs = obs(self._ctx, self._rxobs, self._obs_channel_names) - - @property - def ensm_mode(self): - """ensm_mode: Enable State Machine State Allows real time control over - the current state of the device. Options are: radio_on, radio_off""" - return self._get_iio_dev_attr_str("ensm_mode") - - @ensm_mode.setter - def ensm_mode(self, value): - self._set_iio_dev_attr_str("ensm_mode", value) - - @property - def gain_control_mode(self): - """gain_control_mode: Mode of receive path AGC. Options are: - automatic, hybrid, manual""" - return self._get_iio_attr_str("voltage0", "gain_control_mode", False) - - @gain_control_mode.setter - def gain_control_mode(self, value): - self._set_iio_attr("voltage0", "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 == "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 == "manual": - self._set_iio_attr("voltage1", "hardwaregain", False, value) - - @property - def rx_temp_comp_gain_chan0(self): - """rx_temp_comp_gain_chan0: """ - return self._get_iio_attr("voltage0", "temp_comp_gain", False) - - @rx_temp_comp_gain_chan0.setter - def rx_temp_comp_gain_chan0(self, value): - self._set_iio_attr("voltage0", "temp_comp_gain", False, value) - - @property - def rx_temp_comp_gain_chan1(self): - """rx_temp_comp_gain_chan1: """ - return self._get_iio_attr("voltage1", "temp_comp_gain", False) - - @rx_temp_comp_gain_chan1.setter - def rx_temp_comp_gain_chan1(self, value): - self._set_iio_attr("voltage1", "temp_comp_gain", 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_enable_dec8(self): - """rx_enable_dec8: Enable x8 decimation filter in RX path""" - avail = self._get_iio_attr_str( - "voltage0_i", "sampling_frequency_available", False, self._rxadc - ) - avail = avail.strip().split(" ") - val = self._get_iio_attr_str( - "voltage0_i", "sampling_frequency", False, self._rxadc - ) - return val == avail[1] - - @rx_enable_dec8.setter - def rx_enable_dec8(self, value): - avail = self._get_iio_attr_str( - "voltage0_i", "sampling_frequency_available", False, self._rxadc - ) - avail = sorted(avail.strip().split(" ")) - val = int(avail[1] if value else avail[0]) - self._set_iio_attr("voltage0_i", "sampling_frequency", False, val, self._rxadc) - - @property - def tx_enable_int8(self): - """tx_enable_int8: Enable x8 interpolation filter in TX path""" - avail = self._get_iio_attr_str( - "voltage0", "sampling_frequency_available", True, self._txdac - ) - avail = avail.strip().split(" ") - val = self._get_iio_attr_str( - "voltage0", "sampling_frequency", True, self._txdac - ) - return val == avail[1] - - @tx_enable_int8.setter - def tx_enable_int8(self, value): - avail = self._get_iio_attr_str( - "voltage0", "sampling_frequency_available", True, self._txdac - ) - avail = sorted(avail.strip().split(" ")) - val = int(avail[1] if value else avail[0]) - self._set_iio_attr("voltage0", "sampling_frequency", True, val, self._txdac) - - @property - def rx_sample_rate(self): - """rx_sample_rate: Sample rate RX path in samples per second - This value will reflect the correct value when 8x decimator is enabled - """ - dec = 8 if self.rx_enable_dec8 else 1 - return self._get_iio_attr("voltage0", "sampling_frequency", False) / dec - - @property - def orx_sample_rate(self): - """orx_sample_rate: Sample rate ORX path in samples per second - This value will reflect the correct value when 8x decimator is enabled - """ - dec = 8 if self.rx_enable_dec8 else 1 - return self._get_iio_attr("voltage2", "sampling_frequency", False) / dec - - @property - def tx_sample_rate(self): - """tx_sample_rate: Sample rate TX path in samples per second - This value will reflect the correct value when 8x interpolator is enabled - """ - dec = 8 if self.tx_enable_int8 else 1 - return self._get_iio_attr("voltage0", "sampling_frequency", True) / dec - - @property - def rx_lo(self): - """rx_lo: Carrier frequency of RX path""" - return self._get_iio_attr("altvoltage0", "frequency", True) - - @rx_lo.setter - def rx_lo(self, value): - self._set_iio_attr("altvoltage0", "frequency", True, value) - - @property - def tx_lo(self): - """tx_lo: Carrier frequency of TX path""" - return self._get_iio_attr("altvoltage1", "frequency", True) - - @tx_lo.setter - def tx_lo(self, value): - self._set_iio_attr("altvoltage1", "frequency", True, value) - - @property - def sn_lo(self): - """sn_lo: Carrier frequency of Sniffer/ORx path""" - return self._get_iio_attr("altvoltage2", "frequency", True) - - @sn_lo.setter - def sn_lo(self, value): - self._set_iio_attr("altvoltage2", "frequency", True, value) - - @property - def obs_gain_control_mode(self): - """obs_gain_control_mode: Mode of Obs/Sniffer receive path AGC. Options are: - automatic, hybrid, manual""" - return self._get_iio_attr_str("voltage2", "gain_control_mode", False) - - @obs_gain_control_mode.setter - def obs_gain_control_mode(self, value): - self._set_iio_attr("voltage2", "gain_control_mode", False, value) - - @property - def obs_hardwaregain(self): - """obs_hardwaregain: Gain applied to Obs/Sniffer receive path chan0. Only applicable when - obs_gain_control_mode is set to 'manual'""" - return self._get_iio_attr("voltage2", "hardwaregain", False) - - @obs_hardwaregain.setter - def obs_hardwaregain(self, value): - if self.obs_gain_control_mode == "manual": - self._set_iio_attr("voltage2", "hardwaregain", False, value) - - @property - def obs_temp_comp_gain(self): - """obs_temp_comp_gain: """ - return self._get_iio_attr("voltage2", "temp_comp_gain", False) - - @obs_temp_comp_gain.setter - def obs_temp_comp_gain(self, value): - self._set_iio_attr("voltage2", "temp_comp_gain", False, value) - - @property - def obs_quadrature_tracking_en(self): - """Enable Quadrature tracking calibration for OBS chan0""" - return self._get_iio_attr("voltage2", "quadrature_tracking_en", False) - - @obs_quadrature_tracking_en.setter - def obs_quadrature_tracking_en(self, value): - self._set_iio_attr("voltage2", "quadrature_tracking_en", False, value) - - @property - def obs_rf_port_select(self): - """obs_rf_port_select: Observation path source. Options are: - - - OFF - SnRx path is disabled - - ORX1_TX_LO – SnRx operates in observation mode on ORx1 with Tx LO synthesizer - - ORX2_TX_LO – SnRx operates in observation mode on ORx2 with Tx LO synthesizer - - INTERNALCALS – enables scheduled Tx calibrations while using SnRx path. The enableTrackingCals function needs to be called in RADIO_OFF state. It sets the calibration mask, which the scheduler will later use to schedule the desired calibrations. This command is issued in RADIO_OFF. Once the AD9371 moves to RADIO_ON state, the internal scheduler will use the enabled calibration mask to schedule calibrations whenever possible, based on the state of the transceiver. The Tx calibrations will not be scheduled until INTERNALCALS is selected and the Tx calibrations are enabled in the cal mask. - - OBS_SNIFFER – SnRx operates in sniffer mode with latest selected Sniffer Input – for hardware pin control operation. In pin mode, the GPIO pins designated for ORX_MODE would select SNIFFER mode. Then MYKONOS_setSnifferChannel function would choose the channel. - - ORX1_SN_LO – SnRx operates in observation mode on ORx1 with SNIFFER LO synthesizer - - ORX2_SN_LO – SnRx operates in observation mode on ORx2 with SNIFFER LO synthesizer - - SN_A – SnRx operates in sniffer mode on SnRxA with SNIFFER LO synthesizer - - SN_B – SnRx operates in sniffer mode on SnRxB with SNIFFER LO synthesizer - - SN_C – SnRx operates in sniffer mode on SnRxC with SNIFFER LO synthesizer - - """ - return self._get_iio_attr_str("voltage2", "rf_port_select", False) - - @obs_rf_port_select.setter - def obs_rf_port_select(self, value): - self._set_iio_attr("voltage2", "rf_port_select", False, value) - - @property - def jesd204_statuses(self): - return self._jesd.get_all_statuses() diff --git a/adi/ad937x.py b/adi/ad937x.py new file mode 100644 index 000000000..5c8e0a802 --- /dev/null +++ b/adi/ad937x.py @@ -0,0 +1,778 @@ +# Copyright (C) 2019-2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +from adi.context_manager import context_manager +from adi.jesd import jesd +from adi.obs import obs +from adi.rx_tx import rx_tx +from adi.sync_start import sync_start + + +class ad9371(rx_tx, context_manager, sync_start): + """ AD9371 Transceiver """ + + _complex_data = True + _rx_channel_names = ["voltage0_i", "voltage0_q", "voltage1_i", "voltage1_q"] + _tx_channel_names = ["voltage0", "voltage1", "voltage2", "voltage3"] + _obs_channel_names = ["voltage0_i", "voltage0_q"] + _device_name = "" + + def __init__( + self, uri="", username="root", password="analog", disable_jesd_control=False + ): + """Initialize AD9371 interface class. + Args: + uri (str): URI of target platform with AD9371 + username (str): SSH username for target board. Required for JESD monitoring + password (str): SSH password for target board. Required for JESD monitoring + disable_jesd_control (bool): Disable JESD status monitoring over SSH + """ + context_manager.__init__(self, uri, self._device_name) + + self._ctrl = self._ctx.find_device("ad9371-phy") + self._rxadc = self._ctx.find_device("axi-ad9371-rx-hpc") + self._rxobs = self._ctx.find_device("axi-ad9371-rx-obs-hpc") + self._txdac = self._ctx.find_device("axi-ad9371-tx-hpc") + self._ctx.set_timeout(30000) # Needed for loading profiles + + if not disable_jesd_control and jesd: + self._jesd = jesd(uri, username=username, password=password) + + rx_tx.__init__(self) + + self.obs = obs(self._ctx, self._rxobs, self._obs_channel_names) + + @property + def ensm_mode(self): + """ensm_mode: Enable State Machine State Allows real time control over + the current state of the device. Options are: radio_on, radio_off""" + return self._get_iio_dev_attr_str("ensm_mode") + + @ensm_mode.setter + def ensm_mode(self, value): + self._set_iio_dev_attr_str("ensm_mode", value) + + @property + def gain_control_mode(self): + """gain_control_mode: Mode of receive path AGC. Options are: + automatic, hybrid, manual""" + return self._get_iio_attr_str("voltage0", "gain_control_mode", False) + + @gain_control_mode.setter + def gain_control_mode(self, value): + self._set_iio_attr("voltage0", "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 == "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 == "manual": + self._set_iio_attr("voltage1", "hardwaregain", False, value) + + @property + def rx_temp_comp_gain_chan0(self): + """rx_temp_comp_gain_chan0: """ + return self._get_iio_attr("voltage0", "temp_comp_gain", False) + + @rx_temp_comp_gain_chan0.setter + def rx_temp_comp_gain_chan0(self, value): + self._set_iio_attr("voltage0", "temp_comp_gain", False, value) + + @property + def rx_temp_comp_gain_chan1(self): + """rx_temp_comp_gain_chan1: """ + return self._get_iio_attr("voltage1", "temp_comp_gain", False) + + @rx_temp_comp_gain_chan1.setter + def rx_temp_comp_gain_chan1(self, value): + self._set_iio_attr("voltage1", "temp_comp_gain", 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_enable_dec8(self): + """rx_enable_dec8: Enable x8 decimation filter in RX path""" + avail = self._get_iio_attr_str( + "voltage0_i", "sampling_frequency_available", False, self._rxadc + ) + avail = avail.strip().split(" ") + val = self._get_iio_attr_str( + "voltage0_i", "sampling_frequency", False, self._rxadc + ) + return val == avail[1] + + @rx_enable_dec8.setter + def rx_enable_dec8(self, value): + avail = self._get_iio_attr_str( + "voltage0_i", "sampling_frequency_available", False, self._rxadc + ) + avail = sorted(avail.strip().split(" ")) + val = int(avail[1] if value else avail[0]) + self._set_iio_attr("voltage0_i", "sampling_frequency", False, val, self._rxadc) + + @property + def tx_enable_int8(self): + """tx_enable_int8: Enable x8 interpolation filter in TX path""" + avail = self._get_iio_attr_str( + "voltage0", "sampling_frequency_available", True, self._txdac + ) + avail = avail.strip().split(" ") + val = self._get_iio_attr_str( + "voltage0", "sampling_frequency", True, self._txdac + ) + return val == avail[1] + + @tx_enable_int8.setter + def tx_enable_int8(self, value): + avail = self._get_iio_attr_str( + "voltage0", "sampling_frequency_available", True, self._txdac + ) + avail = sorted(avail.strip().split(" ")) + val = int(avail[1] if value else avail[0]) + self._set_iio_attr("voltage0", "sampling_frequency", True, val, self._txdac) + + @property + def rx_sample_rate(self): + """rx_sample_rate: Sample rate RX path in samples per second + This value will reflect the correct value when 8x decimator is enabled + """ + dec = 8 if self.rx_enable_dec8 else 1 + return self._get_iio_attr("voltage0", "sampling_frequency", False) / dec + + @property + def orx_sample_rate(self): + """orx_sample_rate: Sample rate ORX path in samples per second + This value will reflect the correct value when 8x decimator is enabled + """ + dec = 8 if self.rx_enable_dec8 else 1 + return self._get_iio_attr("voltage2", "sampling_frequency", False) / dec + + @property + def tx_sample_rate(self): + """tx_sample_rate: Sample rate TX path in samples per second + This value will reflect the correct value when 8x interpolator is enabled + """ + dec = 8 if self.tx_enable_int8 else 1 + return self._get_iio_attr("voltage0", "sampling_frequency", True) / dec + + @property + def rx_lo(self): + """rx_lo: Carrier frequency of RX path""" + return self._get_iio_attr("altvoltage0", "frequency", True) + + @rx_lo.setter + def rx_lo(self, value): + self._set_iio_attr("altvoltage0", "frequency", True, value) + + @property + def tx_lo(self): + """tx_lo: Carrier frequency of TX path""" + return self._get_iio_attr("altvoltage1", "frequency", True) + + @tx_lo.setter + def tx_lo(self, value): + self._set_iio_attr("altvoltage1", "frequency", True, value) + + @property + def sn_lo(self): + """sn_lo: Carrier frequency of Sniffer/ORx path""" + return self._get_iio_attr("altvoltage2", "frequency", True) + + @sn_lo.setter + def sn_lo(self, value): + self._set_iio_attr("altvoltage2", "frequency", True, value) + + @property + def obs_gain_control_mode(self): + """obs_gain_control_mode: Mode of Obs/Sniffer receive path AGC. Options are: + automatic, hybrid, manual""" + return self._get_iio_attr_str("voltage2", "gain_control_mode", False) + + @obs_gain_control_mode.setter + def obs_gain_control_mode(self, value): + self._set_iio_attr("voltage2", "gain_control_mode", False, value) + + @property + def obs_hardwaregain(self): + """obs_hardwaregain: Gain applied to Obs/Sniffer receive path chan0. Only applicable when + obs_gain_control_mode is set to 'manual'""" + return self._get_iio_attr("voltage2", "hardwaregain", False) + + @obs_hardwaregain.setter + def obs_hardwaregain(self, value): + if self.obs_gain_control_mode == "manual": + self._set_iio_attr("voltage2", "hardwaregain", False, value) + + @property + def obs_temp_comp_gain(self): + """obs_temp_comp_gain: """ + return self._get_iio_attr("voltage2", "temp_comp_gain", False) + + @obs_temp_comp_gain.setter + def obs_temp_comp_gain(self, value): + self._set_iio_attr("voltage2", "temp_comp_gain", False, value) + + @property + def obs_quadrature_tracking_en(self): + """Enable Quadrature tracking calibration for OBS chan0""" + return self._get_iio_attr("voltage2", "quadrature_tracking_en", False) + + @obs_quadrature_tracking_en.setter + def obs_quadrature_tracking_en(self, value): + self._set_iio_attr("voltage2", "quadrature_tracking_en", False, value) + + @property + def obs_rf_port_select(self): + """obs_rf_port_select: Observation path source. Options are: + + - OFF - SnRx path is disabled + - ORX1_TX_LO – SnRx operates in observation mode on ORx1 with Tx LO synthesizer + - ORX2_TX_LO – SnRx operates in observation mode on ORx2 with Tx LO synthesizer + - INTERNALCALS – enables scheduled Tx calibrations while using SnRx path. The enableTrackingCals function needs to be called in RADIO_OFF state. It sets the calibration mask, which the scheduler will later use to schedule the desired calibrations. This command is issued in RADIO_OFF. Once the AD9371 moves to RADIO_ON state, the internal scheduler will use the enabled calibration mask to schedule calibrations whenever possible, based on the state of the transceiver. The Tx calibrations will not be scheduled until INTERNALCALS is selected and the Tx calibrations are enabled in the cal mask. + - OBS_SNIFFER – SnRx operates in sniffer mode with latest selected Sniffer Input – for hardware pin control operation. In pin mode, the GPIO pins designated for ORX_MODE would select SNIFFER mode. Then MYKONOS_setSnifferChannel function would choose the channel. + - ORX1_SN_LO – SnRx operates in observation mode on ORx1 with SNIFFER LO synthesizer + - ORX2_SN_LO – SnRx operates in observation mode on ORx2 with SNIFFER LO synthesizer + - SN_A – SnRx operates in sniffer mode on SnRxA with SNIFFER LO synthesizer + - SN_B – SnRx operates in sniffer mode on SnRxB with SNIFFER LO synthesizer + - SN_C – SnRx operates in sniffer mode on SnRxC with SNIFFER LO synthesizer + + """ + return self._get_iio_attr_str("voltage2", "rf_port_select", False) + + @obs_rf_port_select.setter + def obs_rf_port_select(self, value): + self._set_iio_attr("voltage2", "rf_port_select", False, value) + + @property + def jesd204_statuses(self): + return self._jesd.get_all_statuses() + + @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() + self._set_iio_dev_attr_str("profile_config", data) + + +class ad9375(ad9371): + """ AD9375 Transceiver """ + + @property + def tx_clgc_tracking_en_chan0(self): + """Enable CLGC tracking for channel 0""" + return self._get_iio_attr("voltage0", "clgc_tracking_en", True) + + @tx_clgc_tracking_en_chan0.setter + def tx_clgc_tracking_en_chan0(self, value): + self._set_iio_attr("voltage0", "clgc_tracking_en", True, value) + + @property + def tx_clgc_tracking_en_chan1(self): + """Enable CLGC tracking for channel 1""" + return self._get_iio_attr("voltage1", "clgc_tracking_en", True) + + @tx_clgc_tracking_en_chan1.setter + def tx_clgc_tracking_en_chan1(self, value): + self._set_iio_attr("voltage1", "clgc_tracking_en", True, value) + + @property + def tx_clgc_current_gain_chan0(self): + if self.tx_clgc_tracking_en_chan0 == 1: + """tx_clgc_current_gain: Current measured gain in 1/100ths dB scale in channel 0. + Current GaindB = currentGain/100""" + return self._get_iio_attr("voltage0", "clgc_current_gain", True) + return + + @property + def tx_clgc_current_gain_chan1(self): + """tx_clgc_current_gain: Current measured gain in 1/100ths dB scale in channel 1. + Current GaindB = currentGain/100""" + if self.tx_clgc_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "clgc_current_gain", True) + return + + @property + def tx_clgc_desired_gain_chan0(self): + """tx_clgc_desired_gain: Desired gain from channel 0 output to orx input. + Desired_gain (dB) = Desired_gain/100""" + if self.tx_clgc_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "clgc_desired_gain", True) / 100 + return + + @tx_clgc_desired_gain_chan0.setter + def tx_clgc_desired_gain_chan0(self, value): + value *= 100 + self._set_iio_attr("voltage0", "clgc_desired_gain", True, value) + + @property + def tx_clgc_desired_gain_chan1(self): + """tx_clgc_desired_gain: Desired gain from channel 1 output to orx input. + Desired_gain (dB) = Desired_gain/100""" + if self.tx_clgc_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "clgc_desired_gain", True) / 100 + return + + @tx_clgc_desired_gain_chan1.setter + def tx_clgc_desired_gain_chan1(self, value): + value *= 100 + self._set_iio_attr("voltage1", "clgc_desired_gain", True, value) + + @property + def tx_clgc_orx_rms_chan0(self): + """tx_clgc_orx_rms: RMS orx digital sample power measured in the DPD block on the orx side is returned + with measurement resolution of 0.01 dB for channel 0. Prms dBFs = orxRMS/100""" + if self.tx_clgc_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "clgc_orx_rms", True) / 100 + return + + @property + def tx_clgc_track_count_chan0(self): + """tx_clgc_track_count: The control reads back the number of times the CLGC has successfully run since + CLGC initialization calibration for channel 0""" + if self.tx_clgc_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "clgc_track_count", True) + return + + @property + def tx_clgc_track_count_chan1(self): + """tx_clgc_track_count: The control reads back the number of times the CLGC has successfully run since + CLGC initialization calibration for channel 1""" + if self.tx_clgc_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "clgc_track_count", True) + return + + @property + def tx_clgc_tx_gain_chan0(self): + """tx_clgc_tx_gain: It controls the current channel 0 attenuation for a channel in 0.05 dB resolution. + Tx_Attenuation(dB) = Tx_gain/200""" + if self.tx_clgc_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "clgc_tx_gain", True) * 0.05 + return + + @property + def tx_clgc_tx_gain_chan1(self): + """tx_clgc_tx_gain: It controls the current channel 1 attenuation for a channel in 0.05 dB resolution. Tx_Attenuation(dB) = Tx_gain/200""" + if self.tx_clgc_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "clgc_tx_gain", True) * 0.05 + return + + @property + def tx_clgc_tx_rms_chan0(self): + """tx_clgc_tx_rms: The controls returns the RMS channel 0 digital sample power measured at DPD actuator output + with measurement resolution of 0.01 dB. Prms dBFs = txRMS/100""" + if self.tx_clgc_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "clgc_tx_rms", True) / 100 + return + + @property + def tx_clgc_tx_rms_chan1(self): + """tx_clgc_tx_rms: The controls returns the RMS channel 1 digital sample power measured at DPD actuator output + with measurement resolution of 0.01 dB. Prms dBFs = txRMS/100""" + if self.tx_clgc_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "clgc_tx_rms", True) / 100 + return + + @property + def tx_dpd_actuator_en_chan0(self): + """Enable DPD actuator for channel 0""" + return self._get_iio_attr("voltage0", "dpd_actuator_en", True) + + @tx_dpd_actuator_en_chan0.setter + def tx_dpd_actuator_en_chan0(self, value): + self._set_iio_attr("voltage0", "dpd_actuator_en", True, value) + + @property + def tx_dpd_actuator_en_chan1(self): + """Enable DPD actuator for channel 1""" + return self._get_iio_attr("voltage1", "dpd_actuator_en", True) + + @tx_dpd_actuator_en_chan1.setter + def tx_dpd_actuator_en_chan1(self, value): + self._set_iio_attr("voltage1", "dpd_actuator_en", True, value) + + @property + def tx_dpd_tracking_en_chan0(self): + """Enable DPD tracking for channel 0""" + return self._get_iio_attr("voltage0", "dpd_tracking_en", True) + + @tx_dpd_tracking_en_chan0.setter + def tx_dpd_tracking_en_chan0(self, value): + self._set_iio_attr("voltage0", "dpd_tracking_en", True, value) + + @property + def tx_dpd_tracking_en_chan1(self): + """Enable DPD tracking for channel 1""" + return self._get_iio_attr("voltage1", "dpd_tracking_en", True) + + @tx_dpd_tracking_en_chan1.setter + def tx_dpd_tracking_en_chan1(self, value): + self._set_iio_attr("voltage1", "dpd_tracking_en", True, value) + + @property + def tx_dpd_external_path_delay_chan0(self): + """tx_dpd_external_path_delay: The control reads back the external path delay + from channel 0 output to orx input at 1/16 sample resolution of the ORx sample rate""" + if self.tx_dpd_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "dpd_external_path_delay", True) / 16 + return + + @property + def tx_dpd_external_path_delay_chan1(self): + """tx_dpd_external_path_delay: The control reads back the external path delay + from channel 1 output to orx input at 1/16 sample resolution of the ORx sample rate""" + if self.tx_dpd_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "dpd_external_path_delay", True) / 16 + return + + @property + def tx_dpd_model_error_chan0(self): + """tx_dpd_model_error: The control reads back the percent error of the PA model ×10 to include 1 decimal place for channel 0""" + if self.tx_dpd_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "dpd_model_error", True) / 10 + return + + @property + def tx_dpd_model_error_chan1(self): + """tx_dpd_model_error: The control reads back the percent error of the PA model ×10 to include 1 decimal place for channel 1""" + if self.tx_dpd_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "dpd_model_error", True) / 10 + return + + def tx_dpd_reset_en_chan0(self, value): + """Enable DPD reset for channel 0""" + if value == 1: + self._set_iio_attr("voltage0", "dpd_reset_en", True, value) + + def tx_dpd_reset_en_chan1(self, value): + """Enable DPD reset for channel 1""" + if value == 1: + self._set_iio_attr("voltage1", "dpd_reset_en", True, value) + + @property + def tx_dpd_status_chan0(self): + """tx_dpd_status: It reads back the DPD calibration status from the ARM processor for channel 0""" + # DPD status lookup + dpdstat_lookup = { + 0: "No Error", + 1: "Error: ORx disabled", + 2: "Error: Tx disabled", + 3: "Error: DPD initialization not run", + 4: "Error: Path delay not setup", + 5: "Error: ORx signal too low", + 6: "Error: ORx signal saturated", + 7: "Error: Tx signal too low", + 8: "Error: Tx signal saturated", + 9: "Error: Model error high", + 10: "Error: AM AM outliers", + 11: "Error: Invalid Tx profile", + 12: "Error: ORx QEC Disabled", + } + if self.tx_dpd_tracking_en_chan0 == 1: + dpdstat_val = self._get_iio_attr("voltage0", "dpd_status", True) + if dpdstat_val in dpdstat_lookup.keys(): + return dpdstat_lookup[dpdstat_val] + return + + @property + def tx_dpd_status_chan1(self): + """tx_dpd_status: It reads back the DPD calibration status from the ARM processor for channel 1""" + # DPD status lookup + dpdstat_lookup = { + 0: "No Error", + 1: "Error: ORx disabled", + 2: "Error: Tx disabled", + 3: "Error: DPD initialization not run", + 4: "Error: Path delay not setup", + 5: "Error: ORx signal too low", + 6: "Error: ORx signal saturated", + 7: "Error: Tx signal too low", + 8: "Error: Tx signal saturated", + 9: "Error: Model error high", + 10: "Error: AM AM outliers", + 11: "Error: Invalid Tx profile", + 12: "Error: ORx QEC Disabled", + } + if self.tx_dpd_tracking_en_chan1 == 1: + dpdstat_val = self._get_iio_attr("voltage1", "dpd_status", True) + if dpdstat_val in dpdstat_lookup.keys(): + return dpdstat_lookup[dpdstat_val] + return + + @property + def tx_dpd_track_count_chan0(self): + """tx_dpd_track_count: It reads back the number of times the DPD has successfully run since + DPD initialization calibration for channel 0""" + if self.tx_dpd_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "dpd_track_count", True) + return + + @property + def tx_dpd_track_count_chan1(self): + """tx_dpd_track_count: It reads back the number of times the DPD has successfully run since + DPD initialization calibration for channel 1""" + if self.tx_dpd_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "dpd_track_count", True) + return + + @property + def tx_vswr_tracking_en_chan0(self): + """Enable VSWR tracking for channel 0""" + return self._get_iio_attr("voltage0", "vswr_tracking_en", True) + + @tx_vswr_tracking_en_chan0.setter + def tx_vswr_tracking_en_chan0(self, value): + self._set_iio_attr("voltage0", "vswr_tracking_en", True, value) + + @property + def tx_vswr_tracking_en_chan1(self): + """Enable VSWR tracking for channel 1""" + return self._get_iio_attr("voltage1", "vswr_tracking_en", True) + + @tx_vswr_tracking_en_chan1.setter + def tx_vswr_tracking_en_chan1(self, value): + self._set_iio_attr("voltage1", "vswr_tracking_en", True, value) + + @property + def tx_vswr_forward_gain_chan0(self): + """tx_vswr_forward: Forward rms gain measured from channel 0 to orx path. 0.01 dB = 1""" + if self.tx_vswr_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "vswr_forward_gain", True) * 0.01 + return + + @property + def tx_vswr_forward_gain_chan1(self): + """tx_vswr_forward: Forward rms gain measured from channel 1 to orx path. 0.01 dB = 1""" + if self.tx_vswr_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "vswr_forward_gain", True) * 0.01 + return + + @property + def tx_vswr_forward_gain_imag_chan0(self): + """tx_vswr_forward_gain_imag: Imaginary part of the forward path complex gain for channel 0 (1 = 0.01 linear gain)""" + if self.tx_vswr_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "vswr_forward_gain_imag", True) * 0.01 + return + + @property + def tx_vswr_forward_gain_imag_chan1(self): + if self.tx_vswr_tracking_en_chan1 == 1: + """tx_vswr_forward_gain_imag: Imaginary part of the forward path complex gain for channel 1 (1 = 0.01 linear gain)""" + return self._get_iio_attr("voltage1", "vswr_forward_gain_imag", True) * 0.01 + return + + @property + def tx_vswr_forward_gain_real_chan0(self): + """tx_vswr_forward_gain_real: Real part of the forward path complex gain for channel 0 (1 = 0.01 linear gain)""" + if self.tx_vswr_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "vswr_forward_gain_real", True) * 0.01 + return + + @property + def tx_vswr_forward_gain_real_chan1(self): + """tx_vswr_forward_gain_real: Real part of the forward path complex gain for channel 1 (1 = 0.01 linear gain)""" + if self.tx_vswr_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "vswr_forward_gain_real", True) * 0.01 + return + + @property + def tx_vswr_forward_orx_chan0(self): + """tx_vswr_forward_orx: RMS Orx digital sample power measured at DPD block for ORx data in the forward measurement mode + with measurement resolution of 0.01 dB and 21 dB offset for channel 0. Prms dBFS = txRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan0 == 1: + return (self._get_iio_attr("voltage0", "vswr_forward_orx", True) / 100) + 21 + return + + @property + def tx_vswr_forward_tx_chan0(self): + """tx_vswr_forward_tx: RMS Tx digital sample power measured at DPD block for ORx data in the forward measurement mode + with measurement resolution of 0.01 dB and 21 dB offset for channel 0. Prms dBFS = txRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan0 == 1: + return (self._get_iio_attr("voltage0", "vswr_forward_tx", True) / 100) + 21 + return + + @property + def tx_vswr_forward_tx_chan1(self): + """tx_vswr_forward_tx: RMS Tx digital sample power measured at DPD block for ORx data in the forward measurement mode + with measurement resolution of 0.01 dB and 21 dB offset for channel 1. Prms dBFS = txRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan1 == 1: + return (self._get_iio_attr("voltage1", "vswr_forward_tx", True) / 100) + 21 + return + + @property + def tx_vswr_reflected_gain_chan0(self): + """tx_vswr_reflected_gain: Reflected path gain in RMS for channel 0. 1 = 0.01 dB gain""" + if self.tx_vswr_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "vswr_reflected_gain", True) * 0.01 + return + + @property + def tx_vswr_reflected_gain_chan1(self): + """tx_vswr_reflected_gain: Reflected path gain in RMS for channel 1. 1 = 0.01 dB gain""" + if self.tx_vswr_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "vswr_reflected_gain", True) * 0.01 + return + + @property + def tx_vswr_reflected_gain_imag_chan0(self): + """tx_vswr_reflected_gain_imag: Imaginary part of the reflected path complex gain for channel 0. 1 = 0.01 linear gain""" + if self.tx_vswr_tracking_en_chan0 == 1: + return ( + self._get_iio_attr("voltage0", "vswr_reflected_gain_imag", True) * 0.01 + ) + return + + @property + def tx_vswr_reflected_gain_imag_chan1(self): + """tx_vswr_reflected_gain_imag: Imaginary part of the reflected path complex gain for channel 1. 1 = 0.01 linear gain""" + if self.tx_vswr_tracking_en_chan1 == 1: + return ( + self._get_iio_attr("voltage1", "vswr_reflected_gain_imag", True) * 0.01 + ) + return + + @property + def tx_vswr_reflected_gain_real_chan0(self): + """tx_vswr_reflected_gain_real: Real part of the reflected path complex gain for channel 0. 1 = 0.01 linear gain""" + if self.tx_vswr_tracking_en_chan0 == 1: + return ( + self._get_iio_attr("voltage0", "vswr_reflected_gain_real", True) * 0.01 + ) + return + + @property + def tx_vswr_reflected_gain_real_chan1(self): + """tx_vswr_reflected_gain_real: Real part of the reflected path complex gain for channel 1. 1 = 0.01 linear gain""" + if self.tx_vswr_tracking_en_chan1 == 1: + return ( + self._get_iio_attr("voltage1", "vswr_reflected_gain_real", True) * 0.01 + ) + return + + @property + def tx_vswr_reflected_orx_chan0(self): + """tx_vswr_reflected_orx: RMS ORx digital sample power measured at DPD block for the ORx data in the reverse measurement mode + with measurement resolution of 0.01 dB and 21 dB offset for channel 0. Prms dBFS = orxRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan0 == 1: + return ( + self._get_iio_attr("voltage0", "vswr_reflected_orx", True) / 100 + ) + 21 + return + + @property + def tx_vswr_reflected_tx_chan0(self): + """tx_vswr_reflected_tx: RMS Tx digital sample power measured at DPD actuator for the reverse measurement + with measurement resolution of 0.01 dB and 21 dB offset for channel 0. Prms dBFS = txRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan0 == 1: + return ( + self._get_iio_attr("voltage0", "vswr_reflected_tx", True) / 100 + ) + 21 + return + + @property + def tx_vswr_reflected_tx_chan1(self): + """tx_vswr_reflected_tx: RMS Tx digital sample power measured at DPD actuator for the reverse measurement + with measurement resolution of 0.01 dB and 21 dB offset for channel 1. Prms dBFS = txRms/100 + 21 dB""" + if self.tx_vswr_tracking_en_chan1 == 1: + return ( + self._get_iio_attr("voltage1", "vswr_reflected_tx", True) / 100 + ) + 21 + return + + @property + def tx_vswr_track_count_chan0(self): + """tx_vswr_track_count: The control reads back the number of times the VSWR has successfully run + since VSWR initialization calibration for channel 0""" + if self.tx_vswr_tracking_en_chan0 == 1: + return self._get_iio_attr("voltage0", "vswr_track_count", True) + return + + @property + def tx_vswr_track_count_chan1(self): + """tx_vswr_track_count: The control reads back the number of times the VSWR has successfully run since + VSWR initialization calibration for channel 1""" + if self.tx_vswr_tracking_en_chan1 == 1: + return self._get_iio_attr("voltage1", "vswr_track_count", True) + return diff --git a/doc/source/devices/adi.ad9371.rst b/doc/source/devices/adi.ad937x.rst similarity index 68% rename from doc/source/devices/adi.ad9371.rst rename to doc/source/devices/adi.ad937x.rst index 372789577..2ff836b53 100644 --- a/doc/source/devices/adi.ad9371.rst +++ b/doc/source/devices/adi.ad937x.rst @@ -1,7 +1,7 @@ -ad9371 +ad937x ================= -.. automodule:: adi.ad9371 +.. automodule:: adi.ad937x :members: :undoc-members: :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index ddfe0e240..3cd2dc02c 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -46,7 +46,7 @@ Supported Devices adi.ad9250 adi.ad9265 adi.ad936x - adi.ad9371 + adi.ad937x adi.ad9434 adi.ad9467 adi.ad9625 diff --git a/examples/ad9375.py b/examples/ad9375.py new file mode 100644 index 000000000..7d07f576e --- /dev/null +++ b/examples/ad9375.py @@ -0,0 +1,121 @@ +# Copyright (C) 2019 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +import time + +import adi +import matplotlib.pyplot as plt +import numpy as np +from scipy import signal + +# Create radio +sdr = adi.ad9375(uri="ip:192.168.10.231") + +# Configure properties +sdr.rx_enabled_channels = [0, 1] +sdr.tx_enabled_channels = [0, 1] +sdr.rx_lo = 2000000000 +sdr.tx_lo = 2000000000 +sdr.tx_cyclic_buffer = True +sdr.tx_hardwaregain_chan0 = -30 +sdr.tx_hardwaregain_chan1 = -30 +sdr.gain_control_mode = "automatic" + +# Enable int8 filter in FPGA +sdr.tx_enable_int8 = False +print("TX FS Pre int8:", sdr.tx_sample_rate) +sdr.tx_enable_int8 = True +print("TX FS Post int8:", sdr.tx_sample_rate) +fs = int(sdr.tx_sample_rate) + +# Read properties +print("RX LO %s" % (sdr.rx_lo)) + +# Create a sinewave waveform +N = 2 ** 15 +fc = 6000000 +ts = 1 / float(fs) +t = np.arange(0, N * ts, ts) +i = np.cos(2 * np.pi * t * fc) * 2 ** 14 +q = np.sin(2 * np.pi * t * fc) * 2 ** 14 +iq = i + 1j * q + +fc = -3000000 +i = np.cos(2 * np.pi * t * fc) * 2 ** 14 +q = np.sin(2 * np.pi * t * fc) * 2 ** 14 +iq2 = i + 1j * q + +# Send data +sdr.tx([iq, iq2]) + +# Collect data +fsr = int(sdr.rx_sample_rate) +for r in range(20): + x = sdr.rx() + f, Pxx_den = signal.periodogram(x[0], fsr) + f2, Pxx_den2 = signal.periodogram(x[1], fsr) + plt.clf() + plt.semilogy(f, Pxx_den) + plt.semilogy(f2, Pxx_den2) + plt.ylim([1e-7, 1e4]) + plt.xlabel("frequency [Hz]") + plt.ylabel("PSD [V**2/Hz]") + plt.draw() + plt.pause(0.05) + time.sleep(0.1) + +# plt.show() + +# ad9375 ONLY +# Enable CLGC tracking +sdr.tx_clgc_tracking_en_chan0 = 1 +sdr.tx_clgc_tracking_en_chan1 = 1 + +# Configure and read CLGC desired gain property +sdr.tx_clgc_desired_gain_chan0 = -3 +time.sleep(0.3) +print("CLGC desired gain channel 1:", sdr.tx_clgc_desired_gain_chan0) +sdr.tx_clgc_desired_gain_chan1 = -3 +time.sleep(0.3) +print("CLGC desired gain channel 2:", sdr.tx_clgc_desired_gain_chan1) + +# Read CLGC properties +print("CLGC tx rms channel 1", sdr.tx_clgc_tx_rms_chan0) +print("CLGC tx rms channel 2", sdr.tx_clgc_tx_rms_chan1) + +# Disable CLGC tracking +sdr.tx_clgc_tracking_en_chan0 = 0 +sdr.tx_clgc_tracking_en_chan1 = 0 + +# Enable DPD tracking +sdr.tx_dpd_tracking_en_chan0 = 1 +sdr.tx_dpd_tracking_en_chan1 = 1 + +# Enable DPD actuator +sdr.tx_dpd_actuator_en_chan0 = 1 +sdr.tx_dpd_actuator_en_chan1 = 1 + +# Read DPD properties +print("DPD status channel 1:", sdr.tx_dpd_status_chan0) +print("DPD status channel 2:", sdr.tx_dpd_status_chan1) + +# Enable DPD reset +sdr.tx_dpd_reset_en_chan0 = 1 +sdr.tx_dpd_reset_en_chan1 = 1 + +# Disable DPD tracking +sdr.tx_dpd_tracking_en_chan0 = 0 +sdr.tx_dpd_tracking_en_chan1 = 0 + +# Enable VSWR tracking +sdr.tx_vswr_tracking_en_chan0 = 1 +sdr.tx_vswr_tracking_en_chan1 = 1 + +# Read VSWR properties +print("VSWR forward gain channel 1:", sdr.tx_vswr_forward_gain_chan0) +print("VSWR forward gain channel 2:", sdr.tx_vswr_forward_gain_chan1) + +# Disable VSWR tracking +sdr.tx_vswr_tracking_en_chan0 = 0 +sdr.tx_vswr_tracking_en_chan1 = 0 diff --git a/test/attr_tests.py b/test/attr_tests.py index b7f6dc08d..45ea0737a 100644 --- a/test/attr_tests.py +++ b/test/attr_tests.py @@ -258,6 +258,33 @@ def attribute_multiple_values_with_depends( assert dev_interface(uri, classname, val, attr, tol) +def attribute_readonly_with_depends(uri, classname, attr, depends): + """attribute_readonly_with_depends: Read only class + property with dependent write properties + + parameters: + uri: type=string + URI of IIO context of target board/system + classname: type=string + Name of pyadi interface class which contain attribute + attr: type=string + Attribute name to be written. Must be property of classname + depends: type=dict + Dictionary of properties to write before value is written. Keys + are properties and values are values to be written + """ + sdr = eval(classname + "(uri='" + uri + "')") + for p in depends: + setattr(sdr, p, depends[p]) + try: + rval = getattr(sdr, attr) + assert type(rval) != None + del sdr + except Exception as e: + del sdr + raise Exception(e) + + def attribute_write_only_str(uri, classname, attr, value): """attribute_write_only_str: Write only string class property @@ -318,3 +345,37 @@ def attribute_write_only_str_with_depends(uri, classname, attr, value, depends): except Exception as e: del sdr raise Exception(e) + + +def attribute_check_range_readonly_with_depends( + uri, classname, attr, depends, start, stop +): + """attribute_check_range_readonly_with_depends: Read only integer class + property with dependent write properties + + parameters: + uri: type=string + URI of IIO context of target board/system + classname: type=string + Name of pyadi interface class which contain attribute + attr: type=string + Attribute name to be written. Must be property of classname + depends: type=dict + Dictionary of properties to write before value is written. Keys + are properties and values are values to be written + start: type=integer + Lower bound of possible values attribute can be + stop: type=integer + Upper bound of possible values attribute can be + """ + sdr = eval(classname + "(uri='" + uri + "')") + for p in depends: + setattr(sdr, p, depends[p]) + try: + rval = getattr(sdr, attr) + end = stop + 1 + assert rval in range(start, end) + del sdr + except Exception as e: + del sdr + raise Exception(e) diff --git a/test/common.py b/test/common.py index 1c41c24e0..0839dcb07 100644 --- a/test/common.py +++ b/test/common.py @@ -97,7 +97,9 @@ def pytest_generate_tests(metafunc): ################################################# -def dev_interface(uri, classname, val, attr, tol, sub_channel=None, sleep=0): +def dev_interface( + uri, classname, val, attr, tol, sub_channel=None, sleep=0, readonly=False +): sdr = eval(classname + "(uri='" + uri + "')") # Check hardware if not hasattr(sdr, attr): @@ -114,10 +116,16 @@ def dev_interface(uri, classname, val, attr, tol, sub_channel=None, sleep=0): time.sleep(sleep) rval = getattr(sdr, attr) - del sdr - if not isinstance(rval, str) and not is_list: rval = float(rval) + for _ in range(5): + setattr(sdr, attr, val) + time.sleep(0.3) + rval = float(getattr(sdr, attr)) + if rval == val: + break + + del sdr if is_list and isinstance(rval[0], str): return val == rval diff --git a/test/conftest.py b/test/conftest.py index fc6ead0b4..6e56b2e2d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -164,6 +164,11 @@ def test_attribute_multiple_values_with_depends(request): yield attribute_multiple_values_with_depends +@pytest.fixture() +def test_attribute_readonly_with_depends(request): + yield attribute_readonly_with_depends + + @pytest.fixture() def test_attribute_write_only_str_with_depends(request): yield attribute_write_only_str_with_depends @@ -174,6 +179,11 @@ def test_attribute_write_only_str(request): yield attribute_write_only_str +@pytest.fixture +def test_attribute_check_range_readonly_with_depends(request): + yield attribute_check_range_readonly_with_depends + + @pytest.fixture() def test_dma_dac_zeros(request): yield dma_dac_zeros diff --git a/test/emu/devices/ad9375.xml b/test/emu/devices/ad9375.xml new file mode 100644 index 000000000..0fcf00083 --- /dev/null +++ b/test/emu/devices/ad9375.xml @@ -0,0 +1 @@ +]> \ No newline at end of file diff --git a/test/emu/hardware_map.yml b/test/emu/hardware_map.yml index a49b5d79c..3e9efa2ec 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -277,6 +277,14 @@ adrv9371: - data_devices: - iio:device4 - iio:device6 +adrv9375: + - ad9371-phy + - emulate: + - filename: ad9375.xml + - data_devices: + - iio:device4 + - iio:device5 + - iio:device6 adxl355: - adxl355 - emulate: diff --git a/test/test_ad9375.py b/test/test_ad9375.py new file mode 100644 index 000000000..7718fb752 --- /dev/null +++ b/test/test_ad9375.py @@ -0,0 +1,507 @@ +from os import listdir +from os.path import dirname, join, realpath + +import pytest + +hardware = "ad9375" +classname = "adi.ad9375" + +profile_path = dirname(realpath(__file__)) + "/ad9371_5_profiles/" +test_profiles = [join(profile_path, f) for f in listdir(profile_path)] + + +clgc_tracking_en_0 = { + "tx_clgc_tracking_en_chan0": 1, +} + +dpd_tracking_en_0 = { + "tx_dpd_tracking_en_chan0": 1, +} + +vswr_tracking_en_0 = { + "tx_vswr_tracking_en_chan0": 1, +} + +clgc_tracking_en_1 = { + "tx_clgc_tracking_en_chan1": 1, +} + +dpd_tracking_en_1 = { + "tx_dpd_tracking_en_chan1": 1, +} + +vswr_tracking_en_1 = { + "tx_vswr_tracking_en_chan1": 1, +} + + +desired_gain_values = [-5, -4] + + +params = dict( + one_cw_tone_manual=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + one_cw_tone_auto=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="automatic", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_attenuation_5dB_manual=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=-5, + tx_hardwaregain_chan1=-5, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_attenuation_10dB_manual=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=-10, + tx_hardwaregain_chan1=-10, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_attenuation_0dB_auto=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="automatic", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_attenuation_20dB_auto=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="automatic", + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=-20, + tx_hardwaregain_chan1=-20, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_rf_gain_0dB_manual=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=0, + rx_hardwaregain_chan1=0, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_rf_gain_20dB_manual=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=20, + rx_hardwaregain_chan1=20, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=0, + rx_temp_comp_gain_chan1=0, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_temp_gain_up=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=3, + rx_temp_comp_gain_chan1=3, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=1, + ), + change_temp_gain_down=dict( + ensm_mode="radio_on", + tx_lo=2500000000, + rx_lo=2500000000, + gain_control_mode="manual", + rx_hardwaregain_chan0=10, + rx_hardwaregain_chan1=10, + rx_quadrature_tracking_en_chan0=1, + rx_quadrature_tracking_en_chan1=1, + rx_temp_comp_gain_chan0=-3, + rx_temp_comp_gain_chan1=-3, + tx_hardwaregain_chan0=0, + tx_hardwaregain_chan1=0, + tx_quadrature_tracking_en_chan0=1, + tx_quadrature_tracking_en_chan1=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), + ("tx_lo", 70000000, 6000000000, 1000, 0), + ("rx_lo", 70000000, 6000000000, 1000, 0), + ], +) +def test_ad9375_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) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", range(2)) +def test_ad9375_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, -13), + (params["one_cw_tone_manual"], 2000000, 0.12, -25), + (params["one_cw_tone_manual"], 2000000, 0.25, -19), + (params["one_cw_tone_auto"], 1000000, 0.12, -14.7), + (params["one_cw_tone_auto"], 2000000, 0.12, -14.7), + (params["one_cw_tone_auto"], 500000, 0.12, -14.7), + (params["change_attenuation_5dB_manual"], 2000000, 0.25, -23.8), + (params["change_attenuation_10dB_manual"], 2000000, 0.25, -28.75), + (params["change_attenuation_0dB_auto"], 1000000, 0.12, -9), + (params["change_attenuation_20dB_auto"], 1000000, 0.12, -24.7), + (params["change_rf_gain_0dB_manual"], 2000000, 0.25, -29), + (params["change_rf_gain_20dB_manual"], 2000000, 0.25, -9), + (params["change_temp_gain_up"], 2000000, 0.25, -16), + (params["change_temp_gain_down"], 2000000, 0.25, -22), + ], +) +def test_ad9375_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.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_auto"], 1000000, 0.06, -21, 2000000, 0.12, -15)], +) +def test_ad9375_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.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, 8.5, 10.5), + (params["one_cw_tone_manual"], 0.12, 20.5, 23), + (params["one_cw_tone_manual"], 0.25, 14.5, 16.5), + (params["one_cw_tone_auto"], 0.12, 10.5, 13), + (params["change_attenuation_5dB_manual"], 0.25, 19.5, 21.25), + (params["change_attenuation_10dB_manual"], 0.25, 24.25, 26.25), + (params["change_attenuation_0dB_auto"], 0.12, 2.25, 5.25), + (params["change_attenuation_20dB_auto"], 0.12, 20.75, 22.75), + (params["change_rf_gain_0dB_manual"], 0.25, 24.75, 26.75), + (params["change_rf_gain_20dB_manual"], 0.25, 5, 6.5), + (params["change_temp_gain_up"], 0.25, 14.5, 16.75), + (params["change_temp_gain_down"], 0.25, 14.5, 16.75), + ], +) +def test_ad9375_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.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_auto"], + params["change_attenuation_5dB_manual"], + params["change_attenuation_10dB_manual"], + params["change_attenuation_0dB_auto"], + params["change_attenuation_20dB_auto"], + params["change_rf_gain_0dB_manual"], + params["change_rf_gain_20dB_manual"], + params["change_temp_gain_up"], + params["change_temp_gain_down"], + ], +) +@pytest.mark.parametrize("sfdr_min", [45]) +def test_ad9375_sfdr(test_sfdr, iio_uri, classname, channel, param_set, sfdr_min): + test_sfdr(iio_uri, classname, channel, param_set, sfdr_min) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("attr", ["profile"]) +@pytest.mark.parametrize( + "files", test_profiles, +) +def test_ad9375_profile_write( + test_attribute_write_only_str, iio_uri, classname, attr, files +): + test_attribute_write_only_str(iio_uri, classname, attr, files) + + +# AD9375 ONLY +######################################## +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, depends, values, tol, repeats", + [ + ("tx_clgc_desired_gain_chan0", clgc_tracking_en_0, desired_gain_values, 0.5, 2), + ("tx_clgc_desired_gain_chan1", clgc_tracking_en_1, desired_gain_values, 0.5, 2), + ], +) +def test_ad9375_attr_with_depends( + test_attribute_multiple_values_with_depends, + iio_uri, + classname, + attr, + depends, + values, + tol, + repeats, +): + test_attribute_multiple_values_with_depends( + iio_uri, classname, attr, depends, values, tol, repeats + ) + + +######################################## +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, depends", + [ + ("tx_clgc_current_gain_chan0", clgc_tracking_en_0), + ("tx_clgc_current_gain_chan1", clgc_tracking_en_1), + ("tx_clgc_orx_rms_chan0", clgc_tracking_en_0), + ("tx_clgc_track_count_chan0", clgc_tracking_en_0), + ("tx_clgc_track_count_chan1", clgc_tracking_en_1), + ("tx_clgc_tx_gain_chan0", clgc_tracking_en_0), + ("tx_clgc_tx_gain_chan1", clgc_tracking_en_1), + ("tx_clgc_tx_rms_chan0", clgc_tracking_en_0), + ("tx_clgc_tx_rms_chan1", clgc_tracking_en_1), + ("tx_dpd_track_count_chan0", dpd_tracking_en_0), + ("tx_dpd_track_count_chan1", dpd_tracking_en_1), + ("tx_dpd_status_chan0", dpd_tracking_en_0), + ("tx_dpd_status_chan1", dpd_tracking_en_1), + ("tx_vswr_forward_gain_chan0", vswr_tracking_en_0), + ("tx_vswr_forward_gain_chan1", vswr_tracking_en_1), + ("tx_vswr_forward_gain_imag_chan0", vswr_tracking_en_0), + ("tx_vswr_forward_gain_imag_chan1", vswr_tracking_en_1), + ("tx_vswr_forward_gain_real_chan0", vswr_tracking_en_0), + ("tx_vswr_forward_gain_real_chan1", vswr_tracking_en_1), + ("tx_vswr_forward_orx_chan0", vswr_tracking_en_0), + ("tx_vswr_forward_tx_chan0", vswr_tracking_en_0), + ("tx_vswr_forward_tx_chan1", vswr_tracking_en_1), + ("tx_vswr_reflected_gain_chan0", vswr_tracking_en_0), + ("tx_vswr_reflected_gain_chan1", vswr_tracking_en_1), + ("tx_vswr_reflected_gain_imag_chan0", vswr_tracking_en_0), + ("tx_vswr_reflected_gain_imag_chan1", vswr_tracking_en_1), + ("tx_vswr_reflected_gain_real_chan0", vswr_tracking_en_0), + ("tx_vswr_reflected_gain_real_chan1", vswr_tracking_en_1), + ("tx_vswr_reflected_orx_chan0", vswr_tracking_en_0), + ("tx_vswr_reflected_tx_chan0", vswr_tracking_en_0), + ("tx_vswr_reflected_tx_chan1", vswr_tracking_en_1), + ("tx_vswr_track_count_chan0", vswr_tracking_en_0), + ("tx_vswr_track_count_chan1", vswr_tracking_en_1), + ], +) +def test_ad9375_attr_readonly_with_depends( + test_attribute_readonly_with_depends, iio_uri, classname, attr, depends +): + test_attribute_readonly_with_depends(iio_uri, classname, attr, depends) + + +######################################## +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, depends, start, stop", + [ + ("tx_dpd_model_error_chan0", dpd_tracking_en_0, 0, 100), + ("tx_dpd_model_error_chan1", dpd_tracking_en_1, 0, 100), + ], +) +def test_ad9375_attr_range_readonly( + test_attribute_check_range_readonly_with_depends, + iio_uri, + classname, + attr, + depends, + start, + stop, +): + test_attribute_check_range_readonly_with_depends( + iio_uri, classname, attr, depends, start, stop + ) + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, value", + [ + ("tx_clgc_tracking_en_chan0", 1), + ("tx_clgc_tracking_en_chan0", 0), + ("tx_clgc_tracking_en_chan1", 1), + ("tx_clgc_tracking_en_chan1", 0), + ("tx_dpd_actuator_en_chan0", 1), + ("tx_dpd_actuator_en_chan0", 0), + ("tx_dpd_actuator_en_chan1", 1), + ("tx_dpd_actuator_en_chan1", 0), + ("tx_vswr_tracking_en_chan0", 1), + ("tx_vswr_tracking_en_chan0", 0), + ("tx_vswr_tracking_en_chan1", 1), + ("tx_vswr_tracking_en_chan1", 0), + ("tx_dpd_tracking_en_chan0", 1), + ("tx_dpd_tracking_en_chan0", 0), + ("tx_dpd_tracking_en_chan1", 1), + ("tx_dpd_tracking_en_chan1", 0), + ], +) +def test_ad9375_attr_boolean( + test_attribute_single_value_boolean, iio_uri, classname, attr, value +): + test_attribute_single_value_boolean(iio_uri, classname, attr, value) + + +######################################## +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, value", [("tx_dpd_reset_en_chan0", 1), ("tx_dpd_reset_en_chan1", 1),], +) +def test_ad9375_attr_write_only( + test_attribute_write_only_str, iio_uri, classname, attr, value +): + test_attribute_write_only_str(iio_uri, classname, attr, value) diff --git a/test/test_map.py b/test/test_map.py index da9b4366b..50a3a22bd 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -91,6 +91,10 @@ def get_test_map(): "zynq-zc706-adv7511-adrv9375", "zynqmp-zcu102-rev10-adrv9375", ] + test_map["adrv9375"] = [ + "zynq-zc706-adv7511-adrv9375", + "zynqmp-zcu102-rev10-adrv9375", + ] test_map["adrv9009"] = [ "socfpga_arria10_socdk_adrv9009", "zynqmp-zcu102-rev10-adrv9008-1",