From f2a89fd437d95be15362d23fe4cacc950805ac0d Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Tue, 14 May 2024 15:01:51 +0200 Subject: [PATCH] add support for ad3552r Add ad3552r driver, test script, example code, rst file and emu xml. Tested: - pytest - invoke precommit - pre-commit run --all-files - executed sample on target All tests passed. Signed-off-by: Angelo Dureghello Reviewed-by: Trevor Gamblin --- adi/__init__.py | 1 + adi/ad3552r.py | 105 +++++++++++++++++++++++++++++ doc/source/devices/adi.ad3552r.rst | 30 +++++++++ doc/source/devices/index.rst | 1 + examples/ad3552r_example.py | 32 +++++++++ supported_parts.md | 1 + test/emu/devices/ad3552r.xml | 1 + test/emu/hardware_map.yml | 10 ++- test/test_ad3552r.py | 30 +++++++++ 9 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 adi/ad3552r.py create mode 100644 doc/source/devices/adi.ad3552r.rst create mode 100644 examples/ad3552r_example.py create mode 100644 test/emu/devices/ad3552r.xml create mode 100644 test/test_ad3552r.py diff --git a/adi/__init__.py b/adi/__init__.py index ef351d282..70cbffaf7 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -10,6 +10,7 @@ from adi.ad777x import ad777x from adi.ad936x import Pluto, ad9361, ad9363, ad9364 from adi.ad937x import ad9371, ad9375 +from adi.ad3552r import ad3552r from adi.ad4020 import ad4000, ad4001, ad4002, ad4003, ad4020 from adi.ad4110 import ad4110 from adi.ad4130 import ad4130 diff --git a/adi/ad3552r.py b/adi/ad3552r.py new file mode 100644 index 000000000..d4f3ed528 --- /dev/null +++ b/adi/ad3552r.py @@ -0,0 +1,105 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +from decimal import Decimal + +from adi.attribute import attribute +from adi.context_manager import context_manager +from adi.rx_tx import tx + + +class ad3552r(tx, context_manager): + """ AD3552R DAC """ + + _complex_data = False + _device_name = "AD3552R" + channels = [] + + def __init__(self, uri="", device_name=""): + """ Constructor for AD3552R driver class """ + + context_manager.__init__(self, uri, self._device_name) + + compatible_parts = [ + "ad3552r", + "ad3542r", + ] + + self._ctrl = None + self._txdac = None + + if not device_name: + device_name = compatible_parts[0] + else: + if device_name not in compatible_parts: + raise Exception( + f"Not a compatible device: {device_name}. Supported device names " + f"are: {','.join(compatible_parts)}" + ) + + # Select the device matching device_name as working device + for device in self._ctx.devices: + if device.name == device_name: + self._ctrl = device + self._txdac = device + break + + if not self._ctrl: + raise Exception("Error in selecting matching device") + + if not self._txdac: + raise Exception("Error in selecting matching device") + + self.output_bits = [] + self.channel = [] + self._tx_channel_names = [] + for ch in self._ctrl.channels: + name = ch._id + output = ch._output + self.output_bits.append(ch.data_format.bits) + self._tx_channel_names.append(name) + self.channel.append(self._channel(self._ctrl, name, output)) + if output is True: + setattr(self, name, self._channel(self._ctrl, name, output)) + + tx.__init__(self) + + class _channel(attribute): + """AD3552R channel""" + + def __init__(self, ctrl, channel_name, output): + self.name = channel_name + self._ctrl = ctrl + self._output = output + + @property + def raw(self): + """Get channel raw value + DAC code in the range 0-65535""" + return self._get_iio_attr(self.name, "raw", True) + + @raw.setter + def raw(self, value): + """Set channel raw value""" + self._set_iio_attr(self.name, "raw", True, str(int(value))) + + @property + def offset(self): + """Get channel offset""" + return self._get_iio_attr_str(self.name, "offset", True) + + @offset.setter + def offset(self, value): + """Set channel offset""" + self._set_iio_attr(self.name, "offset", True, str(Decimal(value).real)) + + @property + def scale(self): + """Get channel scale""" + return float(self._get_iio_attr_str(self.name, "scale", True)) + + @scale.setter + def scale(self, value): + """Set channel scale""" + self._set_iio_attr(self.name, "scale", True, str(Decimal(value).real)) diff --git a/doc/source/devices/adi.ad3552r.rst b/doc/source/devices/adi.ad3552r.rst new file mode 100644 index 000000000..35e0a9d77 --- /dev/null +++ b/doc/source/devices/adi.ad3552r.rst @@ -0,0 +1,30 @@ +ad3552r +================= + +The device class in this module supports multiple parts, as follows: + +**ad3552r:** ad3542r, ad3552r + +By default, the device_name parameter in the class constructor is the +same as the class name (e.g. "ad3552r" for the ad3552r). To use the class +with another supported model, the name must be given when instantiating +the object. For example, if working with an ad3552r with a URI of +"10.2.5.222", use the ad3552r class, but specify the device_name. + +The number of individual channels is based on the device variant. + +.. automodule:: adi.ad3552r + :members: + :undoc-members: + :show-inheritance: + + +.. code-block:: python + + dev = ad3552r("", "ad3552r") + + dev.channel[0].raw = 10 + dev.channel[1].raw = 30 + + data = dev.channel[0].raw + print(data) diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index 879e714a5..b9b217f10 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -9,6 +9,7 @@ Supported Devices adi.QuadMxFE_multi adi.ad2s1210 + adi.ad3552r adi.ad4020 adi.ad4110 adi.ad4130 diff --git a/examples/ad3552r_example.py b/examples/ad3552r_example.py new file mode 100644 index 000000000..c186a63f0 --- /dev/null +++ b/examples/ad3552r_example.py @@ -0,0 +1,32 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +import adi + +# Set up AD3552R +dev = adi.ad3552r("ip:analog", "ad3552r") + +print("raw output cleanup ...") +dev.voltage0.raw = 0 +dev.voltage1.raw = 0 +print("current ch 0: " + str(dev.voltage0.raw)) +print("current ch 1: " + str(dev.voltage1.raw)) + +for ch_num in (0, 1): + ad3552r_chan = dev.channel[ch_num] + print("channel: " + str(ch_num)) + print("writing raw: 100") + ad3552r_chan.raw = 100 + print("reading raw:", end=" ") + print(ad3552r_chan.raw) + print("reading offset:", end=" ") + print(ad3552r_chan.offset) + print("reading scale:", end=" ") + print(ad3552r_chan.scale) + +print("setting ch 0 and 1 respectively as 10 and 30 ...") +dev.voltage0.raw = 10 +dev.voltage1.raw = 30 +print("current ch 0 raw: " + str(dev.voltage0.raw)) +print("current ch 1 raw: " + str(dev.voltage1.raw)) diff --git a/supported_parts.md b/supported_parts.md index 2fd64315f..813db0cb8 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -11,6 +11,7 @@ ### Currently supported hardware - AD2S1210 +- AD3552r (AD3542r) - AD4000 (AD4004, AD4008) - AD4001 (AD4005) - AD4002 (AD4006, AD4010) diff --git a/test/emu/devices/ad3552r.xml b/test/emu/devices/ad3552r.xml new file mode 100644 index 000000000..d465decde --- /dev/null +++ b/test/emu/devices/ad3552r.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 4cedbfc16..a9219a88a 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -323,6 +323,14 @@ adxl355: - filename: adxl355.xml - data_devices: - iio:device0 +ad3552r: + - ad3552r + - pyadi_iio_class_support: + - ad3552r + - emulate: + - filename: ad3552r.xml + - data_devices: + - iio:device0 ad9434: - axi-ad9434-core-lpc - ad9517-4 @@ -566,4 +574,4 @@ lm75: - emulate: - filename: lm75.xml - data_devices: - - hwmon0 \ No newline at end of file + - hwmon0 diff --git a/test/test_ad3552r.py b/test/test_ad3552r.py new file mode 100644 index 000000000..6fd4b5318 --- /dev/null +++ b/test/test_ad3552r.py @@ -0,0 +1,30 @@ +import pytest + +hardware = ["ad3552r", "ad3542r"] +classname = "adi.ad3552r" + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol, repeats, sub_channel", + [ + ("raw", 0, 4000, 1000, 1, 3, "voltage0"), + ("raw", 0, 4000, 1000, 1, 3, "voltage1"), + ], +) +def test_ad3552r_raw_attr( + test_attribute_single_value, + iio_uri, + classname, + attr, + start, + stop, + step, + tol, + repeats, + sub_channel, +): + test_attribute_single_value( + iio_uri, classname, attr, start, stop, step, tol, repeats, sub_channel + )