From 9c3f492708d0892cee23c386176dddc64e449f5e Mon Sep 17 00:00:00 2001 From: Reema Saleem Date: Tue, 22 Aug 2023 11:55:14 -0400 Subject: [PATCH] API to configure RF properties on 2-24 GHz XMW TX/RX Platform Adding python classes (with tests and examples) for all digitally controlled RF components on platform: ADRF5020, ADRF5730, ADRF5740 as well as for complete TX/RX Front End Platforms Signed-off-by: Reema Saleem --- adi/__init__.py | 48 ++- adi/adrf5020.py | 68 ++++ adi/adrf5730.py | 142 ++++++++ adi/adrf5740.py | 181 ++++++++++ adi/xmw_rx_platform.py | 398 +++++++++++++++++++++ adi/xmw_tx_platform.py | 250 +++++++++++++ doc/source/devices/adi.adrf5020.rst | 7 + doc/source/devices/adi.adrf5730.rst | 7 + doc/source/devices/adi.adrf5740.rst | 7 + doc/source/devices/adi.xmw_rx_platform.rst | 7 + doc/source/devices/adi.xmw_tx_platform.rst | 7 + doc/source/devices/index.rst | 10 +- examples/adrf5020_example.py | 46 +++ examples/adrf5730_example.py | 64 ++++ examples/adrf5740_example.py | 64 ++++ examples/xmw_rx_platform_example.py | 101 ++++++ examples/xmw_tx_platform_example.py | 66 ++++ supported_parts.md | 11 +- test/test_adrf5020.py | 27 ++ test/test_adrf5730.py | 26 ++ test/test_adrf5740.py | 26 ++ test/test_xmw_rx_platform.py | 38 ++ test/test_xmw_tx_platform.py | 34 ++ 23 files changed, 1616 insertions(+), 19 deletions(-) create mode 100644 adi/adrf5020.py create mode 100644 adi/adrf5730.py create mode 100644 adi/adrf5740.py create mode 100644 adi/xmw_rx_platform.py create mode 100644 adi/xmw_tx_platform.py create mode 100644 doc/source/devices/adi.adrf5020.rst create mode 100644 doc/source/devices/adi.adrf5730.rst create mode 100644 doc/source/devices/adi.adrf5740.rst create mode 100644 doc/source/devices/adi.xmw_rx_platform.rst create mode 100644 doc/source/devices/adi.xmw_tx_platform.rst create mode 100644 examples/adrf5020_example.py create mode 100644 examples/adrf5730_example.py create mode 100644 examples/adrf5740_example.py create mode 100644 examples/xmw_rx_platform_example.py create mode 100644 examples/xmw_tx_platform_example.py create mode 100644 test/test_adrf5020.py create mode 100644 test/test_adrf5730.py create mode 100644 test/test_adrf5740.py create mode 100644 test/test_xmw_rx_platform.py create mode 100644 test/test_xmw_tx_platform.py diff --git a/adi/__init__.py b/adi/__init__.py index 1f1143935..35cece255 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -1,6 +1,38 @@ -# Copyright (C) 2019-2023 Analog Devices, Inc. +# Copyright (C) 2023 Analog Devices, Inc. # # SPDX short identifier: ADIBSD +# Copyright (C) 2019 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from adi.ad469x import ad469x from adi.ad717x import ad717x @@ -11,7 +43,6 @@ from adi.ad4110 import ad4110 from adi.ad4130 import ad4130 from adi.ad4630 import ad4630 -from adi.ad4858 import ad4858 from adi.ad5592r import ad5592r from adi.ad5686 import ad5686 from adi.ad5940 import ad5940 @@ -21,13 +52,11 @@ from adi.ad7606 import ad7606 from adi.ad7689 import ad7689 from adi.ad7746 import ad7746 -from adi.ad7768 import ad7768, ad7768_4 +from adi.ad7768 import ad7768 from adi.ad7799 import ad7799 from adi.ad9081 import ad9081 from adi.ad9081_mc import QuadMxFE, ad9081_mc from adi.ad9083 import ad9083 -from adi.ad9084 import ad9084 -from adi.ad9084_mc import Triton, ad9084_mc from adi.ad9094 import ad9094 from adi.ad9136 import ad9136 from adi.ad9144 import ad9144 @@ -59,7 +88,10 @@ from adi.adpd188 import adpd188 from adi.adpd410x import adpd410x from adi.adpd1080 import adpd1080 +from adi.adrf5020 import adrf5020 from adi.adrf5720 import adrf5720 +from adi.adrf5730 import adrf5730 +from adi.adrf5740 import adrf5740 from adi.adrv9002 import adrv9002 from adi.adrv9009 import adrv9009 from adi.adrv9009_zu11eg import adrv9009_zu11eg @@ -73,9 +105,7 @@ from adi.cn0511 import cn0511 from adi.cn0532 import cn0532 from adi.cn0554 import cn0554 -from adi.cn0566 import CN0566 from adi.cn0575 import cn0575 -from adi.cn0579 import cn0579 from adi.daq2 import DAQ2 from adi.daq3 import DAQ3 from adi.fmc_vna import fmcvna @@ -99,11 +129,13 @@ from adi.one_bit_adc_dac import one_bit_adc_dac from adi.QuadMxFE_multi import QuadMxFE_multi from adi.tdd import tdd +from adi.xmw_rx_platform import xmw_rx_platform +from adi.xmw_tx_platform import xmw_tx_platform try: from adi.jesd import jesd except ImportError: pass -__version__ = "0.0.17" +__version__ = "0.0.16" name = "Analog Devices Hardware Interfaces" diff --git a/adi/adrf5020.py b/adi/adrf5020.py new file mode 100644 index 000000000..095e4f569 --- /dev/null +++ b/adi/adrf5020.py @@ -0,0 +1,68 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from adi.attribute import attribute +from adi.context_manager import context_manager + + +class adrf5020(attribute, context_manager): + """ADRF5020, Digital Switch + parameters: + uri: type=string + URI of IIO context with ADRF5020 + dev_name: type=string + label of ADRF5020 as defined in device tree + """ + + def __init__(self, uri="", dev_name=""): + context_manager.__init__(self, uri, dev_name) + # Default device for attribute writes + self._ctrl = self._ctx.find_device(dev_name) + # Raise an exception if the device isn't found + if not self._ctrl: + raise Exception("ADRF5020 device not found") + + @property + def control_signal_value(self): + """control_signal_value: Get/Set the Control voltage signal. + Valid options are 1 or 0. + """ + return self._get_iio_attr("voltage0", "raw", True, self._ctrl) + + @control_signal_value.setter + def control_signal_value(self, value): + print(f"Setting control signal input for RF switch to {value}.") + self._set_iio_attr("voltage0", "raw", True, value, self._ctrl) diff --git a/adi/adrf5730.py b/adi/adrf5730.py new file mode 100644 index 000000000..e4448a14a --- /dev/null +++ b/adi/adrf5730.py @@ -0,0 +1,142 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from adi.attribute import attribute +from adi.context_manager import context_manager + + +class adrf5730(attribute, context_manager): + """ADRF5730, Digital Signal Attenuator with parallel GPIO control + parameters: + uri: type=string + URI of IIO context with ADRF5730 + dev_name: type=string + label of ADRF5730 as defined in device tree + """ + + def __init__(self, uri="", dev_name="adrf5730_control"): + context_manager.__init__(self, uri, dev_name) + # Default device for attribute writes + self._ctrl = self._ctx.find_device("adrf5730_control") + # Raise an exception if the device isn't found + if not self._ctrl: + raise Exception("ADRF5730 device not found") + + self._atten_decimal = 0 + self._atten_dB = 0 + self._D5 = 0 + self._D4 = 0 + self._D3 = 0 + self._D2 = 0 + self._D1 = 0 + self._D0 = 0 + + @property + def GPIO_attenuation(self): + """GPIO_attenuation: Get/Set the Attenuation Decimal value when + ADRF5730 is controlled by 6 GPIO channels D5-D0. + Valid options are 0-63 with a step size of 1. + """ + atten_D5_dB = 0 + atten_D4_dB = 0 + atten_D3_dB = 0 + atten_D2_dB = 0 + atten_D1_dB = 0 + atten_D0_dB = 0 + self._D5 = self._get_iio_attr("voltage5", "raw", True, self._ctrl) + self._D4 = self._get_iio_attr("voltage4", "raw", True, self._ctrl) + self._D3 = self._get_iio_attr("voltage3", "raw", True, self._ctrl) + self._D2 = self._get_iio_attr("voltage2", "raw", True, self._ctrl) + self._D1 = self._get_iio_attr("voltage1", "raw", True, self._ctrl) + self._D0 = self._get_iio_attr("voltage0", "raw", True, self._ctrl) + if self._D5 == 1: + atten_D5_dB = 16 + if self._D4 == 1: + atten_D4_dB = 8 + if self._D3 == 1: + atten_D3_dB = 4 + if self._D2 == 1: + atten_D2_dB = 2 + if self._D1 == 1: + atten_D1_dB = 1 + if self._D0 == 1: + atten_D0_dB = 0.5 + self._atten_dB = ( + atten_D5_dB + + atten_D4_dB + + atten_D3_dB + + atten_D2_dB + + atten_D1_dB + + atten_D0_dB + ) + self._atten_decimal = self._atten_dB * 2 + print(f"Attenuation for GPIO controlled DSA is {self._atten_dB} dB.") + print("*** Attenuation Decimal = 2 * Attenuation (dB) ***") + print( + f"Attenuation Decimal (0~63) for GPIO controlled DSA is {self._atten_decimal}." + ) + return self._atten_decimal + + @GPIO_attenuation.setter + def GPIO_attenuation(self, value): + if value < 0 or value >= 64: + print("Please choose a valid value for Attenuation Decimal (0~63)") + return + self._atten_decimal = value + self._atten_dB = value / 2 + print( + f"Setting Attenuation Decimal (0~63) for GPIO controlled DSA to {self._atten_decimal}." + ) + print("*** Attenuation (dB) = 0.5 * Attenuation Decimal ***") + print(f"Setting attenuation for GPIO controlled DSA to {self._atten_dB} dB.") + # Set D0 based on whether or not the Attenuation Decimal value is odd + # (since odd Attenuation Decimal value / 2 gives an Attenuation dB value ending in 0.5) + if value % 2 != 0: + self._D0 = 1 + else: + self._D0 = 0 + # Mask out each of the remaining bits from the Attenuation Decimal value to determine D5-D1 + self._D5 = (self._atten_decimal & (1 << 5)) >> 5 + self._D4 = (self._atten_decimal & (1 << 4)) >> 4 + self._D3 = (self._atten_decimal & (1 << 3)) >> 3 + self._D2 = (self._atten_decimal & (1 << 2)) >> 2 + self._D1 = (self._atten_decimal & (1 << 1)) >> 1 + self._set_iio_attr("voltage5", "raw", True, self._D5, self._ctrl) + self._set_iio_attr("voltage4", "raw", True, self._D4, self._ctrl) + self._set_iio_attr("voltage3", "raw", True, self._D3, self._ctrl) + self._set_iio_attr("voltage2", "raw", True, self._D2, self._ctrl) + self._set_iio_attr("voltage1", "raw", True, self._D1, self._ctrl) + self._set_iio_attr("voltage0", "raw", True, self._D0, self._ctrl) diff --git a/adi/adrf5740.py b/adi/adrf5740.py new file mode 100644 index 000000000..04ebfe7ea --- /dev/null +++ b/adi/adrf5740.py @@ -0,0 +1,181 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from adi.attribute import attribute +from adi.context_manager import context_manager + + +class adrf5740(attribute, context_manager): + """ADRF5740, Digital Signal Attenuator with parallel GPIO control + parameters: + uri: type=string + URI of IIO context with ADRF5740 + dev_name: type=string + label of ADRF5740 as defined in device tree + """ + + def __init__(self, uri="", dev_name="adrf5740_control"): + context_manager.__init__(self, uri, dev_name) + # Default device for attribute writes + self._ctrl = self._ctx.find_device("adrf5740_control") + # Raise an exception if the device isn't found + if not self._ctrl: + raise Exception("ADRF5740 device not found") + + self._atten = 0 + self._D5 = 0 + self._D4 = 0 + self._D3 = 0 + self._D2 = 0 + self._dig_ctrl_input = 0 + + @property + def GPIO_attenuation(self): + """GPIO_attenuation: Get/Set the dB Attenuation value when + ADRF5740 is controlled by 4 GPIO channels D5-D2. + Valid options are 0-22 with a step size of 2. + """ + self._D5 = self._get_iio_attr("voltage3", "raw", True, self._ctrl) + self._D4 = self._get_iio_attr("voltage2", "raw", True, self._ctrl) + self._D3 = self._get_iio_attr("voltage1", "raw", True, self._ctrl) + self._D2 = self._get_iio_attr("voltage0", "raw", True, self._ctrl) + self._dig_ctrl_input = ( + (self._D5 << 3) | (self._D4 << 2) | (self._D3 << 1) | (self._D2 << 0) + ) + if self._dig_ctrl_input == 0b0000: + self._atten = 0.0 + elif self._dig_ctrl_input == 0b0001: + self._atten = 2.0 + elif self._dig_ctrl_input == 0b0010: + self._atten = 4.0 + elif self._dig_ctrl_input == 0b0011: + self._atten = 6.0 + elif self._dig_ctrl_input == 0b0100: + self._atten = 8.0 + elif self._dig_ctrl_input == 0b0101: + self._atten = 10.0 + elif self._dig_ctrl_input == 0b0110: + self._atten = 12.0 + elif self._dig_ctrl_input == 0b0111: + self._atten = 14.0 + elif self._dig_ctrl_input == 0b1100: + self._atten = 16.0 + elif self._dig_ctrl_input == 0b1101: + self._atten = 18.0 + elif self._dig_ctrl_input == 0b1110: + self._atten = 20.0 + elif self._dig_ctrl_input == 0b1111: + self._atten = 22.0 + else: + self._atten = 0.0 + print("Invalid bit settings for DSA attenuation!") + return -1 + print(f"Attenuation for GPIO controlled DSA is {self._atten} dB.") + return self._atten + + @GPIO_attenuation.setter + def GPIO_attenuation(self, value): + self._atten = value + if value == 0: + self._D5 = 0 + self._D4 = 0 + self._D3 = 0 + self._D2 = 0 + elif value == 2: + self._D5 = 0 + self._D4 = 0 + self._D3 = 0 + self._D2 = 1 + elif value == 4: + self._D5 = 0 + self._D4 = 0 + self._D3 = 1 + self._D2 = 0 + elif value == 6: + self._D5 = 0 + self._D4 = 0 + self._D3 = 1 + self._D2 = 1 + elif value == 8: + self._D5 = 0 + self._D4 = 1 + self._D3 = 0 + self._D2 = 0 + elif value == 10: + self._D5 = 0 + self._D4 = 1 + self._D3 = 0 + self._D2 = 1 + elif value == 12: + self._D5 = 0 + self._D4 = 1 + self._D3 = 1 + self._D2 = 0 + elif value == 14: + self._D5 = 0 + self._D4 = 1 + self._D3 = 1 + self._D2 = 1 + elif value == 16: + self._D5 = 1 + self._D4 = 1 + self._D3 = 0 + self._D2 = 0 + elif value == 18: + self._D5 = 1 + self._D4 = 1 + self._D3 = 0 + self._D2 = 1 + elif value == 20: + self._D5 = 1 + self._D4 = 1 + self._D3 = 1 + self._D2 = 0 + elif value == 22: + self._D5 = 1 + self._D4 = 1 + self._D3 = 1 + self._D2 = 1 + else: + print( + "Please choose a valid value for attenuation (0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0 or 22.0)." + ) + return + print(f"Setting attenuation for GPIO controlled DSA to {value} dB.") + self._set_iio_attr("voltage3", "raw", True, self._D5, self._ctrl) + self._set_iio_attr("voltage2", "raw", True, self._D4, self._ctrl) + self._set_iio_attr("voltage1", "raw", True, self._D3, self._ctrl) + self._set_iio_attr("voltage0", "raw", True, self._D2, self._ctrl) diff --git a/adi/xmw_rx_platform.py b/adi/xmw_rx_platform.py new file mode 100644 index 000000000..4c8df304d --- /dev/null +++ b/adi/xmw_rx_platform.py @@ -0,0 +1,398 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from adi.ad9081 import ad9081 +from adi.adrf5020 import adrf5020 +from adi.adrf5730 import adrf5730 +from adi.adrf5740 import adrf5740 +from adi.context_manager import context_manager + + +class xmw_rx_platform(ad9081): + """2-24 GHz XMW RX Platform + parameters: + uri: type=string + Optional parameter for the URI of IIO context with XMW RX Platform. + """ + + _device_name = "" + + def __init__(self, uri="ip:analog.local"): + + context_manager.__init__(self, uri, self._device_name) + + # Find and initialize all devices in the XMW RX Platform + self._rx_clock_chip = self._ctx.find_device("hmc7044") + self._rx_image_bpf = self._ctx.find_device("admv8818_img_filter") + self._rx_preselector_bpf = self._ctx.find_device("admv8818_preselector") + self._rx_fixed_pll = self._ctx.find_device("adf4371_fixed_PLL") + self._rx_tunable_pll = self._ctx.find_device("adf4371_tunable_PLL") + + self._rx_input_switch = adrf5020( + uri="ip:analog.local", dev_name="adrf5020_control_sw_1" + ) + self._rx_if_switch = adrf5020( + uri="ip:analog.local", dev_name="adrf5020_control_sw_3" + ) + self._rx_input_dsa = adrf5740( + uri="ip:analog.local", dev_name="adrf5740_control" + ) + self._rx_if_dsa = adrf5730(uri="ip:analog.local", dev_name="adrf5730_control") + + # Default values for GPIO controlled Switch + self._input_mode_switch = 1 + self._input_freq_range = 1 + self._input_freq_MHz = 4500 + + # Default values for GPIO controlled Digital Signal Attenuators at Input stage and + # Intermediate Frequency stage + self._if_dsa_atten = 0 + self._input_dsa_atten = 0 + + # Default values for preselector and Image Band Pass Filters + self._image_bpf_center_freq = 4500 + self._image_bpf_bandwidth = 1000 + self._image_bpf_high_pass_freq = 4000 + self._image_bpf_low_pass_freq = 5000 + self._preselector_bpf_center_freq = 4500 + self._preselector_bpf_bandwidth = 1000 + self._preselector_bpf_high_pass_freq = 4000 + self._preselector_bpf_low_pass_freq = 5000 + + # Default values for Fixed and Tunable PLLs + self._fixed_pll_freq_MHz = 18000 + self._tunable_pll_freq_MHz = 16000 + + # PLL output is from RF32x but this script is setting/getting frequency on RF8x (factor of 4) + # Also, the linux driver for the ADF4371 PLL requires frequency to be in Hz while this script + # takes frequency in MHz (factor of 1000000) + # Net conversion factor is 1000000/4 = 250000 + self._channel_conv_factor = 250000 + + # Default input mode (through Low Noise Amplifier) + self._input_mode = 0 + + # Default value for Intermediate Frequency to be generated by RX Platform + self._if_freq_MHz = 4500 + + @property + def input_mode(self): + """input mode: Get/Set the mode of operation for the input stage. + Valid options are: + 0: Default LNA + 1: Tunable Pre-Selector + """ + return self._input_mode + + @input_mode.setter + def input_mode(self, value): + self._input_mode = value + if value == 0: + print("Setting Input Mode to 0 (Default LNA)!") + self.input_mode_switch = 1 + elif value == 1: + print("Setting Input Mode to 1 (Pre-Selector Filter)!") + self.input_mode_switch = 0 + # Ensure center frequency of Pre-Selector band pass filter is set to correct RF input frequency + if self._preselector_bpf_center_freq != self._input_freq_MHz: + self.preselector_bpf_freq_MHz = self._input_freq_MHz + else: + print("Setting Input Mode to 0 (Default LNA)!") + self.input_mode_switch = 1 + + @property + def input_freq_MHz(self): + """input_freq_MHz: Get/Set the desired input frequency in order to select + the appropriate RF path. + Valid options are 2-24 GHz with 0.5 GHz step size. + """ + return self._input_freq_MHz + + @input_freq_MHz.setter + def input_freq_MHz(self, value): + print( + f"Setting IF switch to select the appropriate path for an RF input of {value} MHz." + ) + self._input_freq_MHz = value + if self._input_freq_MHz <= 7000: + self.input_freq_range = 1 + self.tunable_pll_freq_MHz = ( + self._fixed_pll_freq_MHz - self._input_freq_MHz + self._if_freq_MHz + ) + elif self._input_freq_MHz > 7000: + self.input_freq_range = 0 + self.tunable_pll_freq_MHz = self._input_freq_MHz + self._if_freq_MHz + else: + self.input_freq_range = 1 + self.tunable_pll_freq_MHz = ( + self._fixed_pll_freq_MHz - self._input_freq_MHz + self._if_freq_MHz + ) + # Set center frequency of Pre-Selector Band Pass Filter to desired RF input frequency if + # input mode 1 is selected + if self._input_mode == 1: + self.preselector_bpf_freq_MHz = value + # Set center frequency of Image Band Pass Filter to desired RF input frequency + self.image_bpf_freq_MHz = value + + @property + def input_mode_switch(self): + """ input_mode_switch: Get/Set input mode switch value to control input mode. + Valid options are through Bypass LNA ('1') or through Preselector Filter ('0'). + """ + self._input_mode_switch = self._rx_input_switch.control_signal_value + if self._input_mode_switch == 1: + print("Input path is through the bypass LNA.") + elif self._input_mode_switch == 0: + print("Input path is through the preselector filter.") + return self._input_mode_switch + + @input_mode_switch.setter + def input_mode_switch(self, value): + if value == 1: + print("Selecting input path through the bypass LNA.") + self._rx_input_switch.control_signal_value = value + elif value == 0: + print("Selecting input path through the preselector filter.") + self._rx_input_switch.control_signal_value = value + else: + print( + "Please select a valid option for input mode switch (1 through Bypass LNA or 0 through Preselector Filter)" + ) + + @property + def input_freq_range(self): + """ input_freq_range: Get/Set input frequency range to control IF switches. + Valid options are: + 7.1-24 GHz ('0') or 2-7 GHz ('1') + """ + self._input_freq_range = self._rx_if_switch.control_signal_value + if self._input_freq_range == 0: + print("Input frequency range is 7.1-24 GHz.") + elif self._input_freq_range == 1: + print("Input frequency range is 2-7 GHz.") + return self._input_freq_range + + @input_freq_range.setter + def input_freq_range(self, value): + if value == 0: + print("Selecting input frequency range of 7.1-24 GHz.") + self._rx_if_switch.control_signal_value = value + elif value == 1: + print("Selecting input frequency range of 2-7 GHz.") + self._rx_if_switch.control_signal_value = value + else: + print( + "Please select a valid option for input frequency range (0 for 7.1-24 GHz or 1 for 2-7 GHz)" + ) + + @property + def input_attenuation_dB(self): + """ input_attenuation_dB: Get/Set attenuation value in dB for input stage. + Valid options are 0-22 dB in steps of 2. + """ + self._input_dsa_atten = self._rx_input_dsa.GPIO_attenuation + return self._input_dsa_atten + + @input_attenuation_dB.setter + def input_attenuation_dB(self, value): + print(f"Setting attenuation of Input stage to {value} dB.") + self._rx_input_dsa.GPIO_attenuation = value + + @property + def if_attenuation_decimal(self): + """ if_attenuation_decimal: Get/Set Attenuation Decimal value for Intermediate Frequency stage. + Valid options are 0-63, corresponding to 0-31.5 dB. + """ + self._if_dsa_atten = self._rx_if_dsa.GPIO_attenuation + return self._if_dsa_atten + + @if_attenuation_decimal.setter + def if_attenuation_decimal(self, value): + print( + f"Setting Attenuation Decimal of Intermediate Frequency stage to {value}." + ) + self._rx_if_dsa.GPIO_attenuation = value + + @property + def preselector_bpf_freq_MHz(self): + """ preselector_bpf_freq_MHz: Get/Set the center frequency for the preselector Band Pass Filter + with a fixed bandwidth of 1000 MHz. + """ + self._preselector_bpf_center_freq = self._get_iio_attr( + "altvoltage0", + "filter_band_pass_center_frequency", + True, + self._rx_preselector_bpf, + ) + print( + f"Center frequency for preselector Band Pass Filter is {self._preselector_bpf_center_freq} MHz." + ) + return self._preselector_bpf_center_freq + + @preselector_bpf_freq_MHz.setter + def preselector_bpf_freq_MHz(self, value): + print( + f"Setting Center frequency of preselector Band Pass Filter to {value} MHz with a bandwidth of {self._preselector_bpf_bandwidth} MHz." + ) + self._preselector_bpf_center_freq = value + self._preselector_bpf_high_pass_freq = value - ( + self._preselector_bpf_bandwidth / 2 + ) + self._preselector_bpf_low_pass_freq = value + ( + self._preselector_bpf_bandwidth / 2 + ) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_center_frequency", + True, + self._preselector_bpf_center_freq, + self._rx_preselector_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_bandwidth_3db_frequency", + True, + self._preselector_bpf_bandwidth, + self._rx_preselector_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_high_pass_3db_frequency", + True, + self._preselector_bpf_high_pass_freq, + self._rx_preselector_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_low_pass_3db_frequency", + True, + self._preselector_bpf_low_pass_freq, + self._rx_preselector_bpf, + ) + + @property + def image_bpf_freq_MHz(self): + """ image_bpf_freq_MHz: Get/Set the center frequency for the image Band Pass Filter + with a fixed bandwidth of 1000 MHz. + """ + self._image_bpf_center_freq = self._get_iio_attr( + "altvoltage0", "filter_band_pass_center_frequency", True, self._rx_image_bpf + ) + print( + f"Center frequency for preselector Band Pass Filter is {self._image_bpf_center_freq} MHz." + ) + return self._image_bpf_center_freq + + @image_bpf_freq_MHz.setter + def image_bpf_freq_MHz(self, value): + print( + f"Setting Center frequency of image Band Pass Filter to {value} MHz with a bandwidth of {self._image_bpf_bandwidth} MHz." + ) + self._image_bpf_center_freq = value + self._image_bpf_high_pass_freq = value - (self._image_bpf_bandwidth / 2) + self._image_bpf_low_pass_freq = value + (self._image_bpf_bandwidth / 2) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_center_frequency", + True, + self._image_bpf_center_freq, + self._rx_image_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_bandwidth_3db_frequency", + True, + self._image_bpf_bandwidth, + self._rx_image_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_high_pass_3db_frequency", + True, + self._image_bpf_high_pass_freq, + self._rx_image_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_low_pass_3db_frequency", + True, + self._image_bpf_low_pass_freq, + self._rx_image_bpf, + ) + + @property + def fixed_pll_freq_MHz(self): + """ fixed_pll_freq_MHz: Get/Set the LO frequency generated by the fixed PLL.""" + self._fixed_pll_freq_MHz = ( + self._get_iio_attr("altvoltage0", "frequency", True, self._rx_fixed_pll) + ) / self._channel_conv_factor + print(f"LO frequency generated by Fixed PLL is {self._fixed_pll_freq_MHz} MHz.") + return self._fixed_pll_freq_MHz + + @fixed_pll_freq_MHz.setter + def fixed_pll_freq_MHz(self, value): + print(f"Setting LO frequency generated by Fixed PLL to {value} MHz.") + self._fixed_pll_freq_MHz = value * self._channel_conv_factor + self._set_iio_attr( + "altvoltage0", + "frequency", + True, + self._fixed_pll_freq_MHz, + self._rx_fixed_pll, + ) + + @property + def tunable_pll_freq_MHz(self): + """ tunable_pll_freq_MHz: Get/Set the LO frequency generated by the Tunable PLL.""" + self._tunable_pll_freq_MHz = ( + self._get_iio_attr("altvoltage0", "frequency", True, self._rx_tunable_pll) + ) / self._channel_conv_factor + print( + f"LO frequency generated by Tunable PLL is {self._tunable_pll_freq_MHz} MHz." + ) + return self._tunable_pll_freq_MHz + + @tunable_pll_freq_MHz.setter + def tunable_pll_freq_MHz(self, value): + print(f"Setting LO frequency generated by Tunable PLL to {value} MHz.") + self._tunable_pll_freq_MHz = value * self._channel_conv_factor + self._set_iio_attr( + "altvoltage0", + "frequency", + True, + self._tunable_pll_freq_MHz, + self._rx_tunable_pll, + ) diff --git a/adi/xmw_tx_platform.py b/adi/xmw_tx_platform.py new file mode 100644 index 000000000..a86faba3a --- /dev/null +++ b/adi/xmw_tx_platform.py @@ -0,0 +1,250 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from adi.ad9081 import ad9081 +from adi.adrf5020 import adrf5020 +from adi.adrf5730 import adrf5730 +from adi.context_manager import context_manager + + +class xmw_tx_platform(ad9081): + """2-24 GHz XMW TX Platform + parameters: + uri: type=string + Optional parameter for the URI of IIO context with XMW TX Platform. + """ + + _device_name = "" + + def __init__(self, uri="ip:analog.local"): + + context_manager.__init__(self, uri, self._device_name) + + # Find and initialize all devices in the XMW TX Platform + self._tx_clock_chip = self._ctx.find_device("hmc7044") + self._tx_bpf = self._ctx.find_device("admv8818") + self._tx_fixed_pll = self._ctx.find_device("adf4371_fixed_PLL") + self._tx_tunable_pll = self._ctx.find_device("adf4371_tunable_PLL") + + self._tx_switch = adrf5020(uri="ip:analog.local", dev_name="adrf5020_control") + self._tx_dsa = adrf5730(uri="ip:analog.local", dev_name="adrf5730_control") + + # Default values for GPIO controlled Switch + self._output_freq_range = 1 + self._output_freq_MHz = 4500 + + # Default values for GPIO controlled Digital Signal Attenuator + self._dsa_atten = 0 + + # Default values for output Band Pass Filter + self._bpf_center_freq = 4500 + self._bpf_bandwidth = 1000 + self._bpf_high_pass_freq = 4000 + self._bpf_low_pass_freq = 5000 + + # Default values for Fixed and Tunable PLLs + self._fixed_pll_freq_MHz = 18000 + self._tunable_pll_freq_MHz = 16000 + + # PLL output is from RF32x but this script is setting/getting frequency on RF8x (factor of 4) + # Also, the linux driver for the ADF4371 PLL requires frequency to be in Hz while this + # script takes frequency in MHz (factor of 1000000) + # Net conversion factor is 1000000/4 = 250000 + self._channel_conv_factor = 250000 + + # This is the intermediate frequency generated by the DAC of the MxFE chip + self._if_freq_MHz = 4500 + + @property + def output_freq_MHz(self): + """output_freq_MHz: Get/Set the desired output frequency in order to select the appropriate conversion path and tune LO to the required frequency. + Valid options are 2-24 GHz with 0.5 GHz step size. + """ + return self._output_freq_MHz + + @output_freq_MHz.setter + def output_freq_MHz(self, value): + print( + f"Setting appropriate frequency conversion path and Tunable LO frequency for an RF out of {value} MHz." + ) + self._output_freq_MHz = value + if self._output_freq_MHz <= 7000: + self.output_freq_range = 1 + self.tunable_pll_freq_MHz = ( + self._fixed_pll_freq_MHz - self._output_freq_MHz + self._if_freq_MHz + ) + elif self._output_freq_MHz > 7000: + self.output_freq_range = 0 + self.tunable_pll_freq_MHz = self._output_freq_MHz + self._if_freq_MHz + else: + self.output_freq_range = 1 + self.tunable_pll_freq_MHz = ( + self._fixed_pll_freq_MHz - self._output_freq_MHz + self._if_freq_MHz + ) + # Set center frequency of output Band Pass Filter to desired RF out frequency + self.output_bpf_freq_MHz = value + + @property + def output_freq_range(self): + """ output_freq_range: Get/Set frequency output range. + Valid options are 7.1-24 GHz ('0') or 2-7 GHz ('1'). + """ + self._output_freq_range = self._tx_switch.control_signal_value + if self._output_freq_range == 0: + print("Output frequency range is 7.1-24 GHz.") + elif self._output_freq_range == 1: + print("Output frequency range is 2-7 GHz.") + return self._output_freq_range + + @output_freq_range.setter + def output_freq_range(self, value): + if value == 0: + print("Selecting output frequency range of 7.1-24 GHz.") + self._tx_switch.control_signal_value = value + elif value == 1: + print("Selecting output frequency range of 2-7 GHz.") + self._tx_switch.control_signal_value = value + else: + print( + "Please select a valid option for output frequency range (0 for 7.1-24 GHz or 1 for 2-7 GHz)." + ) + + @property + def if_attenuation_decimal(self): + """ if_attenuation_decimal: Get/Set Attenuation Decimal value for Intermediate Frequency input. + Valid options are 0-63, corresponding to 0-31.5 dB. + """ + self._dsa_atten = self._tx_dsa.GPIO_attenuation + return self._dsa_atten + + @if_attenuation_decimal.setter + def if_attenuation_decimal(self, value): + print( + f"Setting Attenuation Decimal of Intermediate Frequency stage to {value}." + ) + self._tx_dsa.GPIO_attenuation = value + + @property + def output_bpf_freq_MHz(self): + """ output_bpf_freq_MHz: Get/Set the center frequency for output Band Pass Filter with a fixed bandwidth of 1000 MHz.""" + self._bpf_center_freq = self._get_iio_attr( + "altvoltage0", "filter_band_pass_center_frequency", True, self._tx_bpf + ) + print( + f"Center frequency for output Band Pass Filter is {self._bpf_center_freq} MHz." + ) + return self._bpf_center_freq + + @output_bpf_freq_MHz.setter + def output_bpf_freq_MHz(self, value): + print( + f"Setting Center frequency of output Band Pass Filter to {value} MHz with a bandwidth of {self._bpf_bandwidth} MHz." + ) + self._bpf_center_freq = value + self._bpf_high_pass_freq = value - (self._bpf_bandwidth / 2) + self._bpf_low_pass_freq = value + (self._bpf_bandwidth / 2) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_center_frequency", + True, + self._bpf_center_freq, + self._tx_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_band_pass_bandwidth_3db_frequency", + True, + self._bpf_bandwidth, + self._tx_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_high_pass_3db_frequency", + True, + self._bpf_high_pass_freq, + self._tx_bpf, + ) + self._set_iio_attr( + "altvoltage0", + "filter_low_pass_3db_frequency", + True, + self._bpf_low_pass_freq, + self._tx_bpf, + ) + + @property + def fixed_pll_freq_MHz(self): + """ fixed_pll_freq_MHz: Get/Set the LO frequency generated by the fixed PLL.""" + self._fixed_pll_freq_MHz = ( + self._get_iio_attr("altvoltage0", "frequency", True, self._tx_fixed_pll) + ) / self._channel_conv_factor + print(f"LO frequency generated by Fixed PLL is {self._fixed_pll_freq_MHz} MHz.") + return self._fixed_pll_freq_MHz + + @fixed_pll_freq_MHz.setter + def fixed_pll_freq_MHz(self, value): + print(f"Setting LO frequency generated by Fixed PLL to {value} MHz.") + self._fixed_pll_freq_MHz = value * self._channel_conv_factor + self._set_iio_attr( + "altvoltage0", + "frequency", + True, + self._fixed_pll_freq_MHz, + self._tx_fixed_pll, + ) + + @property + def tunable_pll_freq_MHz(self): + """ tunable_pll_freq_MHz: Get/Set the LO frequency generated by the Tunable PLL.""" + self._tunable_pll_freq_MHz = ( + self._get_iio_attr("altvoltage0", "frequency", True, self._tx_tunable_pll) + ) / self._channel_conv_factor + print( + f"LO frequency generated by Tunable PLL is {self._tunable_pll_freq_MHz} MHz." + ) + return self._tunable_pll_freq_MHz + + @tunable_pll_freq_MHz.setter + def tunable_pll_freq_MHz(self, value): + print(f"Setting LO frequency generated by Tunable PLL to {value} MHz.") + self._tunable_pll_freq_MHz = value * self._channel_conv_factor + self._set_iio_attr( + "altvoltage0", + "frequency", + True, + self._tunable_pll_freq_MHz, + self._tx_tunable_pll, + ) diff --git a/doc/source/devices/adi.adrf5020.rst b/doc/source/devices/adi.adrf5020.rst new file mode 100644 index 000000000..7a28c0ea4 --- /dev/null +++ b/doc/source/devices/adi.adrf5020.rst @@ -0,0 +1,7 @@ +adrf5020 +================= + +.. automodule:: adi.adrf5020 + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/adi.adrf5730.rst b/doc/source/devices/adi.adrf5730.rst new file mode 100644 index 000000000..b915cf248 --- /dev/null +++ b/doc/source/devices/adi.adrf5730.rst @@ -0,0 +1,7 @@ +adrf5730 +================= + +.. automodule:: adi.adrf5730 + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/adi.adrf5740.rst b/doc/source/devices/adi.adrf5740.rst new file mode 100644 index 000000000..1e36fc5e4 --- /dev/null +++ b/doc/source/devices/adi.adrf5740.rst @@ -0,0 +1,7 @@ +adrf5740 +================= + +.. automodule:: adi.adrf5740 + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/adi.xmw_rx_platform.rst b/doc/source/devices/adi.xmw_rx_platform.rst new file mode 100644 index 000000000..9775a889c --- /dev/null +++ b/doc/source/devices/adi.xmw_rx_platform.rst @@ -0,0 +1,7 @@ +xmw_rx_platform +================= + +.. automodule:: adi.xmw_rx_platform + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/adi.xmw_tx_platform.rst b/doc/source/devices/adi.xmw_tx_platform.rst new file mode 100644 index 000000000..194aa6494 --- /dev/null +++ b/doc/source/devices/adi.xmw_tx_platform.rst @@ -0,0 +1,7 @@ +xmw_tx_platform +================= + +.. automodule:: adi.xmw_tx_platform + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index b2339eef0..eb13dd0e5 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -31,8 +31,6 @@ Supported Devices adi.ad9081 adi.ad9081_mc adi.ad9083 - adi.ad9084 - adi.ad9084_mc adi.ad9094 adi.ad9136 adi.ad9144 @@ -48,7 +46,6 @@ Supported Devices adi.ad9467 adi.ad9625 adi.ad9680 - adi.ad4858 adi.ad9739a adi.ada4961 adi.adaq8092 @@ -67,7 +64,10 @@ Supported Devices adi.adpd1080 adi.adpd188 adi.adpd410x + adi.adrf5020 adi.adrf5720 + adi.adrf5730 + adi.adrf5740 adi.adrv9002 adi.adrv9009 adi.adrv9009_zu11eg @@ -82,9 +82,7 @@ Supported Devices adi.cn0532 adi.cn0540 adi.cn0554 - adi.cn0566 adi.cn0575 - adi.cn0579 adi.daq2 adi.daq3 adi.fmc_vna @@ -106,6 +104,8 @@ Supported Devices adi.max31855 adi.max31865 adi.max9611 + adi.xmw_rx_platform + adi.xmw_tx_platform adi.one_bit_adc_dac adi.tdd diff --git a/examples/adrf5020_example.py b/examples/adrf5020_example.py new file mode 100644 index 000000000..a69507a97 --- /dev/null +++ b/examples/adrf5020_example.py @@ -0,0 +1,46 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import adi + +rf_switch = adi.adrf5020(uri="ip:analog.local") + +print("---This example script sets control signal input for the RF switch to 0 and 1.") + +# Set Control Signal Value to logic '0' and observe resultant RF path +rf_switch.control_signal_value = 0 +input("RF path is from RFC to RF2, press Enter to continue.") + +# Set Control Signal Value to logic '1' and observe resultant RF path +rf_switch.control_signal_value = 1 +input("RF path is from RFC to RF1, press Enter to end program.") diff --git a/examples/adrf5730_example.py b/examples/adrf5730_example.py new file mode 100644 index 000000000..3630fa131 --- /dev/null +++ b/examples/adrf5730_example.py @@ -0,0 +1,64 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import adi + +dsa = adi.adrf5730(uri="ip:analog.local") + +print( + "---This example script produces attenuation values of 0, 4.0, 16.0 and 31.5 dB, corresponding to attenuation decimal values of 0, 8, 32 and 63, to be observed on the Spectrum Analyzer." +) + +# Set GPIO attenuation of GPIO controlled DSA to 0 dB +dsa.GPIO_attenuation = 0 +input( + "Observe an attenuation of 0 dB = 0 decimal on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 4.0 dB +dsa.GPIO_attenuation = 4.0 +input( + "Observe an attenuation of 4.0 dB = 8 decimal on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 16.0 dB +dsa.GPIO_attenuation = 16.0 +input( + "Observe an attenuation of 16.0 dB = 32 decimal on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 31.5 dB +dsa.GPIO_attenuation = 31.5 +input( + "Observe an attenuation of 31.5 dB = 63 decimal on the Spectrum Analyzer, press Enter to end program." +) diff --git a/examples/adrf5740_example.py b/examples/adrf5740_example.py new file mode 100644 index 000000000..8872aa3eb --- /dev/null +++ b/examples/adrf5740_example.py @@ -0,0 +1,64 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import adi + +dsa = adi.adrf5740(uri="ip:analog.local") + +print( + "---This example script produces attenuation values of 0, 4.0, 16.0 and 22.0 dB, to be observed on the Spectrum Analyzer." +) + +# Set GPIO attenuation of GPIO controlled DSA to 0 dB +dsa.GPIO_attenuation = 0 +input( + "Observe an attenuation of 0 dB on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 4.0 dB +dsa.GPIO_attenuation = 4.0 +input( + "Observe an attenuation of 4.0 dB on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 16.0 dB +dsa.GPIO_attenuation = 16.0 +input( + "Observe an attenuation of 16.0 dB on the Spectrum Analyzer, press Enter to continue." +) + +# Set GPIO attenuation of GPIO controlled DSA to 22.0 dB +dsa.GPIO_attenuation = 22.0 +input( + "Observe an attenuation of 22.0 dB on the Spectrum Analyzer, press Enter to end program." +) diff --git a/examples/xmw_rx_platform_example.py b/examples/xmw_rx_platform_example.py new file mode 100644 index 000000000..56e21627b --- /dev/null +++ b/examples/xmw_rx_platform_example.py @@ -0,0 +1,101 @@ +# Copyright (C) 2023 Analog if_devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import time + +import adi +import matplotlib.pyplot as plt +from scipy import signal + +# Set up MxFE chip to receive Intermediate Frequency of 4.5 GHz (refer to ad9081_example.py) +if_dev = adi.ad9081(uri="ip:analog.local") +print("--Setting up MxFE chip") + +# Configure RX properties +# Taking ADC Frequency = 6000 MHz, Main Decimation = 4 and Channel Decimation = 1 (refer to dts file for these values) +if_dev.rx_channel_nco_frequencies = [0] * 2 +if_dev.rx_main_nco_frequencies = [1000000000, 0] +if_dev.rx_enabled_channels = [0] +# 4500 MHz lies in second (even) Nyquist zone +if_dev.rx_nyquist_zone = ["even"] * 2 +if_dev.rx_buffer_size = 2 ** 16 + +# fs = RX Sample Rate = ADC Freq / (Main Decimation x Channel Decimation) = 6000/(4x1) = 1500 MHz +fs = int(if_dev.rx_sample_rate) + +# Set up RF front end system and configure properties +rf_system = adi.xmw_rx_platform(uri="ip:analog.local") +print("--Setting up RF platform") + +# Set up IF Attenuation (0dB) +rf_system.if_attenuation_decimal = 0 + +# Set up Input Attenuation (0dB) +rf_system.input_attenuation_dB = 0 + +# Set up Input Frequency Range +rf_system.input_freq_MHz = 12500 + +# Set up Input Mode (Through Preselector Bandpass Filter) +rf_system.input_mode = 1 + +# Observe IF on Spectrum Analyzer then digitized tone on plot +print( + "Observe IF output from the RF front end system at 4500 MHz on the Spectrum Analyzer." +) +print(f"ADC Frequency: {if_dev.adc_frequency / 1000000} MHz.") +print( + f"NCO frequency shift on Channel 0: {if_dev.rx_main_nco_frequencies[0] / 1000000} GHz." +) +print( + f"IF of 4500 MHz is aliased into first Nyquist zone (4500 - ADC Frequency/2) and shifted by NCO Frequency Shift to {4500 - (if_dev.adc_frequency / 1000000) / 2 - if_dev.rx_main_nco_frequencies[0] / 1000000} MHz." +) +input( + "Reconnect IF to ADC0 on the MxFE and press Enter to see a plot of the digitized tone at the above frequency." +) + +# Collect data +for r in range(20): + x = if_dev.rx() + + f, Pxx_den = signal.periodogram(x, fs, return_onesided=False) + plt.clf() + plt.semilogy(f, Pxx_den) + plt.ylim([1e-7, 1e5]) + plt.xlabel("frequency [Hz]") + plt.ylabel("PSD [V**2/Hz]") + plt.draw() + plt.pause(0.05) + time.sleep(0.1) + +plt.show() diff --git a/examples/xmw_tx_platform_example.py b/examples/xmw_tx_platform_example.py new file mode 100644 index 000000000..ec66144fd --- /dev/null +++ b/examples/xmw_tx_platform_example.py @@ -0,0 +1,66 @@ +# Copyright (C) 2023 Analog if_devices, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# - Neither the name of Analog Devices, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# - The use of this software may or may not infringe the patent rights +# of one or more patent holders. This license does not release you +# from the requirement that you obtain separate licenses from these +# patent holders to use this software. +# - Use of the software either in source or binary form, must be run +# on or directly connected to an Analog Devices Inc. component. +# +# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. +# +# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import adi + +# Set up MxFE chip to generate Intermediate Frequency (refer to ad9081_example.py) +if_dev = adi.ad9081(uri="ip:analog.local") +print("--Setting up MxFE chip") + +# Configure TX properties +if_dev.tx_channel_nco_frequencies = [0] * 2 + +# Set Intermediate Frequency to 4.5 GHz on Channel 0 +if_dev.tx_main_nco_frequencies = [4500000000, 0] +print( + f"Intermediate frequency is set to {if_dev.tx_main_nco_frequencies[0] / 1000000} MHz." +) + +fs = 0 +# Set single DDS tone for TX on one transmitter +if_dev.dds_single_tone(fs / 10, 0.5, channel=0) + +# Set up RF front end system and configure properties +rf_system = adi.xmw_tx_platform(uri="ip:analog.local") +print("--Setting up RF platform") + +# Set up IF Attenuation (0dB) +rf_system.if_attenuation_decimal = 0 + +# Set up Output Frequency to transmit (2~24 GHz) +rf_system.output_freq_MHz = 12500 + +# Observe output on Spectrum Analyzer +input( + f"Observe RF output at {rf_system.output_freq_MHz} MHz on the Spectrum Analyzer. Press Enter to end program." +) diff --git a/supported_parts.md b/supported_parts.md index edbf4044d..3d04a9c8a 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -71,14 +71,12 @@ - AD7195 - AD7291 - AD7768 -- AD7768-4 - AD7770 - AD7771 - AD7779 - AD7799 - AD9081 - AD9083 -- AD9084 - AD9094 - AD9136 - AD9144 @@ -95,7 +93,6 @@ - AD9467 - AD9625 - AD9680 -- AD4858 - AD9739A - ADA4961 - ADAQ8092 @@ -112,7 +109,10 @@ - ADL5960 - ADMV8818 - ADPD410x +- ADRF5020 - ADRF5720 +- ADRF5730 +- ADRF5740 - ADRV9002 - ADRV9008-1/2 - ADRV9009 @@ -130,9 +130,7 @@ - CN0540 - CN0554 - CN0549 -- CN0566 - CN0575 -- CN0579 - DAQ2 - DAQ3 - FMCADC3 @@ -162,4 +160,5 @@ - MAX31855 - MAX31865 - MAX9611 -- AD7690 +- XMW-RX-Platform +- XMW-TX-Platform diff --git a/test/test_adrf5020.py b/test/test_adrf5020.py new file mode 100644 index 000000000..985b00503 --- /dev/null +++ b/test/test_adrf5020.py @@ -0,0 +1,27 @@ +import pytest + +hardware = "adrf5020" +classname = "adi.adrf5020" + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, param_set", + [("control_signal_value", 0, 1, 1, 0, 10),], +) +def test_adrf5020_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + param_set, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, param_set + ) diff --git a/test/test_adrf5730.py b/test/test_adrf5730.py new file mode 100644 index 000000000..569df0a12 --- /dev/null +++ b/test/test_adrf5730.py @@ -0,0 +1,26 @@ +import pytest + +hardware = "adrf5730" +classname = "adi.adrf5730" + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, param_set", [("GPIO_attenuation", 0, 63, 1, 1, 10),] +) +def test_adrf5730_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + param_set, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, param_set + ) diff --git a/test/test_adrf5740.py b/test/test_adrf5740.py new file mode 100644 index 000000000..430cc31a9 --- /dev/null +++ b/test/test_adrf5740.py @@ -0,0 +1,26 @@ +import pytest + +hardware = "adrf5740" +classname = "adi.adrf5740" + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, param_set", [("GPIO_attenuation", 0, 22, 2, 1, 10),] +) +def test_adrf5740_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + param_set, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, param_set + ) diff --git a/test/test_xmw_rx_platform.py b/test/test_xmw_rx_platform.py new file mode 100644 index 000000000..e2226a655 --- /dev/null +++ b/test/test_xmw_rx_platform.py @@ -0,0 +1,38 @@ +import pytest + +hardware = "xmw_rx_platform" +classname = "adi.xmw_rx_platform" + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, param_set", + [ + ("input_mode_switch", 0, 1, 1, 0, 10), + ("input_freq_range", 0, 1, 1, 0, 10), + ("input_freq_MHz", 2000, 24000, 500, 500, 10), + ("input_mode", 0, 1, 1, 0, 10), + ("preselector_bpf_freq_MHz", 2000, 17000, 500, 1000, 10), + ("image_bpf_freq_MHz", 2000, 17000, 500, 1000, 10), + ("fixed_pll_freq_MHz", 11000, 28000, 500, 100, 10), + ("tunable_pll_freq_MHz", 11000, 28000, 500, 100, 10), + ("if_attenuation_decimal", 0, 63, 1, 1, 10), + ("input_attenuation_dB", 0, 22, 2, 0, 10), + ], +) +def test_xmw_rx_platform_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + param_set, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, param_set + ) diff --git a/test/test_xmw_tx_platform.py b/test/test_xmw_tx_platform.py new file mode 100644 index 000000000..03eb6daac --- /dev/null +++ b/test/test_xmw_tx_platform.py @@ -0,0 +1,34 @@ +import pytest + +hardware = "xmw_tx_platform" +classname = "adi.xmw_tx_platform" + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, param_set", + [ + ("output_freq_range", 0, 1, 1, 0, 10), + ("output_freq_MHz", 2000, 24000, 500, 0, 10), + ("output_bpf_freq_MHz", 2000, 17000, 500, 1000, 10), + ("fixed_pll_freq_MHz", 11000, 28000, 500, 100, 10), + ("tunable_pll_freq_MHz", 11000, 28000, 500, 100, 10), + ("if_attenuation_decimal", 0, 63, 1, 1, 10), + ], +) +def test_xmw_tx_platform_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + param_set, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, param_set + )