From 3e595a5a7accf77bc3d8f34a8c29e2f60495cfe1 Mon Sep 17 00:00:00 2001 From: SGudla Date: Mon, 2 Sep 2024 16:44:11 +0530 Subject: [PATCH] Add support for AD7091R-2, AD7091R-4 and AD7091R-8 Add ad7091r.py driver Add test script, example code Update index.rst, init.py, supported_parts.md files Add xml emu context file Update hardware_map.yml file for test emulation Signed-off-by: SGudla --- adi/__init__.py | 1 + adi/ad7091r.py | 163 +++++++++++++++++++++++++++++ doc/source/devices/adi.ad7091r.rst | 7 ++ doc/source/devices/index.rst | 1 + examples/ad7091r_example.py | 64 +++++++++++ supported_parts.md | 3 + test/emu/devices/ad7091r.xml | 1 + test/emu/hardware_map.yml | 9 ++ test/test_ad7091r.py | 12 +++ 9 files changed, 261 insertions(+) create mode 100644 adi/ad7091r.py create mode 100644 doc/source/devices/adi.ad7091r.rst create mode 100644 examples/ad7091r_example.py create mode 100644 test/emu/devices/ad7091r.xml create mode 100644 test/test_ad7091r.py diff --git a/adi/__init__.py b/adi/__init__.py index ed2ce0c0a..96580a6f7 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.ad7091r import ad7091rx from adi.ad7124 import ad7124 from adi.ad7134 import ad7134 from adi.ad7291 import ad7291 diff --git a/adi/ad7091r.py b/adi/ad7091r.py new file mode 100644 index 000000000..a30be12f7 --- /dev/null +++ b/adi/ad7091r.py @@ -0,0 +1,163 @@ +# 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. + +from decimal import Decimal + +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[0] + 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)) + + 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 offset(self): + """AD7091r channel offset value""" + return self._get_iio_attr_str(self.name, "offset", False) + + @offset.setter + def offset(self, value): + self._set_iio_attr(self.name, "offset", False, str(Decimal(value).real)) + + @property + def scale(self): + """AD7091r channel scale""" + return float(self._get_iio_attr_str(self.name, "scale", False)) + + @scale.setter + def scale(self, value): + self._set_iio_attr(self.name, "scale", False, str(Decimal(value).real)) + + @property + def thresh_falling_value(self): + """Get channel threshold falling value""" + return self._get_iio_attr(self.name, "thresh_falling_value", False) + + @thresh_falling_value.setter + def thresh_falling_value(self, value): + """Set channel threshold falling value""" + self._set_iio_attr( + self.name, "thresh_falling_value", False, str(Decimal(value)) + ) + + @property + def thresh_rising_value(self): + """Get channel threshold rising value""" + return self._get_iio_attr(self.name, "thresh_rising_value", False) + + @thresh_rising_value.setter + def thresh_rising_value(self, value): + """Set channel threshold rising value""" + self._set_iio_attr( + self.name, "thresh_rising_value", False, str(Decimal(value)) + ) + + @property + def thresh_either_hysteresis(self): + """Get channel threshold either hysteresis value""" + return self._get_iio_attr(self.name, "thresh_either_hysteresis", False) + + @thresh_either_hysteresis.setter + def thresh_either_hysteresis(self, value): + """Set channel threshold either hysteresis value""" + self._set_iio_attr( + self.name, "thresh_either_hysteresis", False, str(Decimal(value)) + ) + + def to_volts(self, index, val): + """Converts raw value to SI""" + _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.ad7091r.rst b/doc/source/devices/adi.ad7091r.rst new file mode 100644 index 000000000..086b32fb6 --- /dev/null +++ b/doc/source/devices/adi.ad7091r.rst @@ -0,0 +1,7 @@ +ad7091r +================= + +.. automodule:: adi.ad7091r + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index fff19a767..e7eccf9af 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.ad7091r adi.ad7124 adi.ad7134 adi.ad717x diff --git a/examples/ad7091r_example.py b/examples/ad7091r_example.py new file mode 100644 index 000000000..c05ab28c9 --- /dev/null +++ b/examples/ad7091r_example.py @@ -0,0 +1,64 @@ +# 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.ad7091r import ad7091rx + +# Set up AD7091r8 +ad7091r8_dev = ad7091rx(uri="serial:COM46,230400,8n1", device_name="ad7091r-8") + +# Get ADC channel 0 raw value and print it +raw = ad7091r8_dev.channel[0].raw +print(f"Raw value read from channel0 is {raw}") + +# Set threshold falling and rising values for channel 0 +ad7091r8_dev.channel[0].thresh_rising_value = 0x10F +print( + f"Channel 0 threshold rising value set to {ad7091r8_dev.channel[0].thresh_rising_value}" +) + +ad7091r8_dev.channel[0].thresh_falling_value = 0x0F +print( + f"Channel 0 threshold falling value set to {ad7091r8_dev.channel[0].thresh_falling_value}" +) + +# Capture a buffer of 100 samples from channel 0 and display them +chn = 0 +ad7091r8_dev._rx_data_type = np.int32 +ad7091r8_dev.rx_output_type = "raw" +ad7091r8_dev.rx_enabled_channels = [chn] +ad7091r8_dev.rx_buffer_size = 100 + +data = ad7091r8_dev.rx() + +print(data) diff --git a/supported_parts.md b/supported_parts.md index 14a4d7ca1..b09b9ae8f 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -71,6 +71,9 @@ - AD5754R - AD5940 - AD6676 +- AD7091R-2 +- AD7091R-4 +- AD7091R-8 - AD7124 - AD7134 - AD7172-2 diff --git a/test/emu/devices/ad7091r.xml b/test/emu/devices/ad7091r.xml new file mode 100644 index 000000000..3e5957e42 --- /dev/null +++ b/test/emu/devices/ad7091r.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..7b571d986 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -454,6 +454,15 @@ ad6676: - data_devices: - iio:device1 +ad7091r: + - ad7091r + - pyadi_iio_class_support: + - ad7091r + - emulate: + - filename: ad7091r.xml + - data_devices: + - iio:device0 + ad7768: - ad7768 - pyadi_iio_class_support: diff --git a/test/test_ad7091r.py b/test/test_ad7091r.py new file mode 100644 index 000000000..88ee80861 --- /dev/null +++ b/test/test_ad7091r.py @@ -0,0 +1,12 @@ +import pytest + +hardware = "ad7091r-8" +classname = "adi.ad7091rx" + + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize("channel", [0]) +def test_ad7091rx_rx_data(test_dma_rx, iio_uri, classname, channel): + test_dma_rx(iio_uri, classname, channel)