diff --git a/adi/__init__.py b/adi/__init__.py index ed2ce0c0a..d577ef229 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -23,6 +23,7 @@ from adi.ad5754r import ad5754r from adi.ad5940 import ad5940 from adi.ad6676 import ad6676 +from adi.ad7091rx import ad7091rx from adi.ad7124 import ad7124 from adi.ad7134 import ad7134 from adi.ad7291 import ad7291 diff --git a/adi/ad7091rx.py b/adi/ad7091rx.py new file mode 100644 index 000000000..a4b9e2c8c --- /dev/null +++ b/adi/ad7091rx.py @@ -0,0 +1,113 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +# Copyright (C) 2024 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 numpy as np +from adi.attribute import attribute +from adi.context_manager import context_manager +from adi.rx_tx import rx + + +class ad7091rx(rx, context_manager): + """AD7091R-2/AD7091R-4/AD7091R-8 SPI interface, + 2-/4-/8-channel, 12-bit SAR ADC""" + + _complex_data = False + channel = [] # type: ignore + _device_name = "" + + def __init__(self, uri="", device_name=""): + + context_manager.__init__(self, uri, self._device_name) + + compatible_parts = [ + "ad7091r-2", + "ad7091r-4", + "ad7091r-8", + ] + + self._ctrl = None + + if not device_name: + device_name = compatible_parts[2] + else: + if device_name not in compatible_parts: + raise Exception("Not a compatible device: " + device_name) + + # Selecting the device matching device_name AD7091RX family as working device. + for device in self._ctx.devices: + if device.name == device_name: + self._ctrl = device + self._rxadc = device + break + + for ch in self._ctrl.channels: + name = ch._id + self._rx_channel_names.append(name) + self.channel.append(self._channel(self._ctrl, name)) + setattr(self, name, self._channel(self._ctrl, name)) + + rx.__init__(self) + + class _channel(attribute): + """AD7091R-8/-4/-2 Input Voltage Channels""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + @property + def raw(self): + """AD7091r channel raw value""" + return self._get_iio_attr(self.name, "raw", False) + + @property + def scale(self): + """AD7091r channel scale""" + return float(self._get_iio_attr_str(self.name, "scale", False)) + + def to_mvolts(self, index, val): + """Converts raw value to mV""" + _scale = self.channel[index].scale + + ret = None + + if isinstance(val, np.uint16): + ret = val * _scale + + if isinstance(val, np.ndarray): + ret = [x * _scale for x in val] + + return ret diff --git a/doc/source/devices/adi.ad7091rx.rst b/doc/source/devices/adi.ad7091rx.rst new file mode 100644 index 000000000..80a8e5b5d --- /dev/null +++ b/doc/source/devices/adi.ad7091rx.rst @@ -0,0 +1,7 @@ +ad7091rx +================= + +.. automodule:: adi.ad7091rx + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index fff19a767..b7b802614 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -23,6 +23,7 @@ Supported Devices adi.ad5754r adi.ad5940 adi.ad6676 + adi.ad7091rx adi.ad7124 adi.ad7134 adi.ad717x diff --git a/examples/ad7091rx_example.py b/examples/ad7091rx_example.py new file mode 100644 index 000000000..bb83fc8ad --- /dev/null +++ b/examples/ad7091rx_example.py @@ -0,0 +1,80 @@ +# Copyright (C) 2024 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 argparse + +import numpy as np +from adi.ad7091rx import ad7091rx + + +def main(): + # Set up argument parser + parser = argparse.ArgumentParser(description="AD7091R Example Script") + parser.add_argument( + "--uri", + type=str, + help="The URI for the AD7091R device", + default="serial:COM7,230400,8n1", + ) + parser.add_argument( + "--device_name", + type=str, + choices=["ad7091r-2", "ad7091r-4", "ad7091r-8"], + help="The device name (Supported devices are ad7091r-2, ad7091r-4, ad7091r-8)", + default="ad7091r-8", + ) + + # Parse arguments + args = parser.parse_args() + + # Set up AD7091R device + ad7091r_dev = ad7091rx(uri=args.uri, device_name=args.device_name) + + # Get ADC channel 0 raw value and print it + raw = ad7091r_dev.channel[0].raw + print(f"Raw value read from channel0 is {raw}") + + # Capture a buffer of 100 samples from channel 0 and display them + chn = 0 + ad7091r_dev._rx_data_type = np.int32 + ad7091r_dev.rx_output_type = "raw" + ad7091r_dev.rx_enabled_channels = [chn] + ad7091r_dev.rx_buffer_size = 100 + + data = ad7091r_dev.rx() + + print(data) + + +if __name__ == "__main__": + main() diff --git a/supported_parts.md b/supported_parts.md index 14a4d7ca1..2923b9a95 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -71,6 +71,7 @@ - AD5754R - AD5940 - AD6676 +- AD7091RX (AD7091R-2, AD7091R-4, AD7091R-8) - AD7124 - AD7134 - AD7172-2 diff --git a/test/emu/devices/ad7091rx.xml b/test/emu/devices/ad7091rx.xml new file mode 100644 index 000000000..2e1b4ce17 --- /dev/null +++ b/test/emu/devices/ad7091rx.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 74a93f9e1..c0449c131 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -454,6 +454,15 @@ ad6676: - data_devices: - iio:device1 +ad7091r8: + - ad7091r8 + - pyadi_iio_class_support: + - ad7091rx + - emulate: + - filename: ad7091rx.xml + - data_devices: + - iio:device0 + ad7768: - ad7768 - pyadi_iio_class_support: diff --git a/test/test_ad7091rx.py b/test/test_ad7091rx.py new file mode 100644 index 000000000..71871bc7f --- /dev/null +++ b/test/test_ad7091rx.py @@ -0,0 +1,26 @@ +import pytest + +hardware = "ad7091r8" +classname = "adi.ad7091rx" + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("attr", ["raw"]) +@pytest.mark.parametrize( + "channel", + [ + "voltage0", + "voltage1", + "voltage2", + "voltage3", + "voltage4", + "voltage5", + "voltage6", + "voltage7", + ], +) +def test_ad7091rx_channel_attr_raw( + test_attribute_single_value_channel_readonly, iio_uri, classname, channel, attr +): + test_attribute_single_value_channel_readonly(iio_uri, classname, channel, attr)