From 9ece94135cbb9d0cac9e97aaee9bbe69688b13d4 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 7 Nov 2023 22:13:55 -0300 Subject: [PATCH 1/8] examples: ad4630: Iterate over control channels ad4630 simple plot example intended to iterate over the list of channels but incorrect attribute name prevented it from doing so. Use the correct channel list attribute name to iterate over ad4630/adaq42xx channel list. Fixes: <5cf933d91787> (Added ad4630 support) Signed-off-by: Marcelo Schmitt --- examples/ad4630/ad4630_example_simple_plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ad4630/ad4630_example_simple_plot.py b/examples/ad4630/ad4630_example_simple_plot.py index 2571b2c22..25be7279c 100644 --- a/examples/ad4630/ad4630_example_simple_plot.py +++ b/examples/ad4630/ad4630_example_simple_plot.py @@ -29,6 +29,6 @@ for ch in range(0, len(data)): x = np.arange(0, len(data[ch])) - plt.figure(adc._ctrl._channels[ch]._name) + plt.figure(adc._ctrl.channels[ch]._name) plt.plot(x, data[ch]) plt.show() From 0af794f9940a17ba979d30a8d05c1b91d816ec38 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 5 Jul 2023 11:27:21 -0300 Subject: [PATCH 2/8] Add support for ADAQ42xx AD4630 and ADAQ42xx designs are very similar, differing mainly on the availability (or not) of PGIA gain. Add input scale properties to handle ADAQ42xx PGIA control and add ADAQ4216, ADAQ4220, and ADAQ4224 to the list of supported devices. Signed-off-by: Marcelo Schmitt --- adi/__init__.py | 2 +- adi/ad4630.py | 35 +++++++++++++++++++++++++++++++---- supported_parts.md | 3 +++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/adi/__init__.py b/adi/__init__.py index 7387aabd3..ab6ed6486 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -10,7 +10,7 @@ from adi.ad4020 import ad4020 from adi.ad4110 import ad4110 from adi.ad4130 import ad4130 -from adi.ad4630 import ad4630 +from adi.ad4630 import ad4630, adaq42xx from adi.ad4858 import ad4858 from adi.ad5592r import ad5592r from adi.ad5686 import ad5686 diff --git a/adi/ad4630.py b/adi/ad4630.py index cd9039864..571353475 100644 --- a/adi/ad4630.py +++ b/adi/ad4630.py @@ -2,6 +2,7 @@ # # SPDX short identifier: ADIBSD +from decimal import Decimal import numpy as np from adi.attribute import attribute @@ -25,6 +26,7 @@ class ad4630(rx, context_manager, attribute): """ AD4630 is low power 24-bit precision SAR ADC """ + _compatible_parts = ["ad4630-24", "ad4030-24", "ad4630-16"] _complex_data = False _data_type = np.uint32 _device_name = "" @@ -36,14 +38,12 @@ def __init__(self, uri="", device_name="ad4630-24"): context_manager.__init__(self, uri, self._device_name) - compatible_parts = ["ad4630-24", "ad4030-24", "ad4630-16"] - - if device_name not in compatible_parts: + if device_name not in self._compatible_parts: raise Exception( "Not a compatible device: " + str(device_name) + ". Please select from " - + str(compatible_parts) + + str(self.self._compatible_parts) ) else: self._ctrl = self._ctx.find_device(device_name) @@ -166,3 +166,30 @@ def calibscale(self): def calibscale(self, calibscale): """Set calibration scale value.""" self._set_iio_attr(self.name, "calibscale", False, calibscale, self._ctrl) + + +class adaq42xx(ad4630): + + """ ADAQ4224 is a 24-bit precision SAR ADC data acquisition module """ + + _compatible_parts = ["adaq4224", "adaq4216", "adaq4220"] + + def __init__(self, uri="", device_name="adaq4224"): + super().__init__(uri, device_name) + + class _channel(ad4630._channel): + """ADAQ42xx differential channel.""" + + @property + def scale_available(self): + """Provides all available scale(gain) settings for the ADAQ42xx channel""" + return self._get_iio_attr(self.name, "scale_available", False) + + @property + def scale(self): + """ADAQ42xx 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)) diff --git a/supported_parts.md b/supported_parts.md index faf881689..d4635db66 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -99,6 +99,9 @@ - AD4858 - AD9739A - ADA4961 +- ADAQ4216 +- ADAQ4220 +- ADAQ4224 - ADAQ8092 - ADAR1000 - ADF4159 From 96413f9af0a63b6d2eb5c3f4c0764ab83df83549 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 7 Nov 2023 18:00:04 -0300 Subject: [PATCH 3/8] examples: Add adaq4224 example Add simple adaq4224 example featuring adjustable input scale. Signed-off-by: Marcelo Schmitt --- examples/adaq4224_example.py | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 examples/adaq4224_example.py diff --git a/examples/adaq4224_example.py b/examples/adaq4224_example.py new file mode 100644 index 000000000..44c3669b2 --- /dev/null +++ b/examples/adaq4224_example.py @@ -0,0 +1,53 @@ +# Copyright (C) 2023 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +import sys + +import adi +import matplotlib.pyplot as plt +import numpy as np + +# Optionally pass URI as command line argument, +# else use default context manager search +my_uri = sys.argv[1] if len(sys.argv) >= 2 else None +print("uri: " + str(my_uri)) + +device_name = "adaq4224" + +adc = adi.adaq42xx(uri=my_uri, device_name=device_name) +adc.rx_buffer_size = 500 +adc.sample_rate = 2000000 +try: + adc.sample_averaging = 16 +except: + print("Sample average not supported in this mode") + +# Available gains are 0.33, 0.56, 2.22, 6.67 +# but due to Linux ABI technicalities they must be expressed with different values. + +gains_avail = adc.chan0.scale_available + +adc.chan0.scale = gains_avail[0] +print("Sampling with gain set to 0.33") + +data = adc.rx() + +for ch in range(0, len(data)): + x = np.arange(0, len(data[ch])) + plt.figure(adc._ctrl.channels[ch]._name) + plt.plot(x, data[ch]) +plt.title("Samples read with 0.33 gain") +plt.show() + +adc.chan0.scale = gains_avail[1] +print("Sampling with gain set to 0.56") + +data = adc.rx() + +for ch in range(0, len(data)): + x = np.arange(0, len(data[ch])) + plt.figure(adc._ctrl.channels[ch]._name) + plt.plot(x, data[ch]) +plt.title("Samples read with 0.56 gain") +plt.show() From 442c5bdc0038f4f4ed1a2a22046fdb8f3746d381 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 8 Nov 2023 16:14:47 -0300 Subject: [PATCH 4/8] test: common: Add sleep param for sub channel tests We have sleep parameter for class interface tests. Add sleep parameter for sub class inteface tests so class and sub class tests can provide similar functionality. Signed-off-by: Marcelo Schmitt --- test/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/common.py b/test/common.py index 81001e56c..1c41c24e0 100644 --- a/test/common.py +++ b/test/common.py @@ -138,7 +138,7 @@ def dev_interface(uri, classname, val, attr, tol, sub_channel=None, sleep=0): def dev_interface_sub_channel( - uri, classname, sub_channel, val, attr, tol, readonly=False + uri, classname, sub_channel, val, attr, tol, readonly=False, sleep=0, ): sdr = eval(classname + "(uri='" + uri + "')") # Check hardware @@ -155,6 +155,8 @@ def dev_interface_sub_channel( if readonly is False: setattr(getattr(sdr, sub_channel), attr, val) + if sleep > 0: + time.sleep(sleep) rval = getattr(getattr(sdr, sub_channel), attr) del sdr From c3fe8a18a5b2c8d8be875bc70b4a799ed4334a6d Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 8 Nov 2023 16:23:30 -0300 Subject: [PATCH 5/8] test: attr_tests: Add documentation for sleep parameter Add short description for test sleep parameter. Signed-off-by: Marcelo Schmitt --- test/attr_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/attr_tests.py b/test/attr_tests.py index a3fa0ab6f..56e6bd946 100644 --- a/test/attr_tests.py +++ b/test/attr_tests.py @@ -201,6 +201,8 @@ def attribute_multiple_values(uri, classname, attr, values, tol, repeats=1, slee Allowable error of written value compared to read back value repeats: type=integer Number of times to repeatedly write values + sleep: type=integer + Seconds to sleep between writing to attribute and reading it back """ for _ in range(repeats): for val in values: From abf360617dcfb308660d75467045a58db28c8eb5 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 8 Nov 2023 16:24:46 -0300 Subject: [PATCH 6/8] test: attr_tests: Enable multiple values test for sub channel attributes Make attribute_multiple_values() test support sub channel attributes. This might be useful for testing channel attributes which values must match some available list such as scale_available, sampling_frequency_available, etc. Signed-off-by: Marcelo Schmitt --- test/attr_tests.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/attr_tests.py b/test/attr_tests.py index 56e6bd946..b7f6dc08d 100644 --- a/test/attr_tests.py +++ b/test/attr_tests.py @@ -183,7 +183,9 @@ def attribute_single_value_pow2(uri, classname, attr, max_pow, tol, repeats=1): assert dev_interface(uri, classname, val, attr, tol) -def attribute_multiple_values(uri, classname, attr, values, tol, repeats=1, sleep=0): +def attribute_multiple_values( + uri, classname, attr, values, tol, repeats=1, sleep=0, sub_channel=None +): """attribute_multiple_values: Write and read back multiple class properties in a loop where all values are pre-defined. This is performed a defined number of times. @@ -203,11 +205,17 @@ def attribute_multiple_values(uri, classname, attr, values, tol, repeats=1, slee Number of times to repeatedly write values sleep: type=integer Seconds to sleep between writing to attribute and reading it back + sub_channel: type=string + Name of sub channel (nested class) to be tested """ for _ in range(repeats): for val in values: if isinstance(val, str): - assert dev_interface(uri, classname, val, attr, 0, sleep=sleep) + tol = 0 + if sub_channel: + assert dev_interface_sub_channel( + uri, classname, sub_channel, val, attr, tol, sleep=sleep + ) else: assert dev_interface(uri, classname, val, attr, tol, sleep=sleep) From 6489cce41c40d87429a0969ac8a855cb8c783ad6 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 8 Nov 2023 18:01:39 -0300 Subject: [PATCH 7/8] test: emu: Add emulation support for ADAQ4224 Add adaq4224 device xml file and update hardware map with info about new hardware emulation. Signed-off-by: Marcelo Schmitt --- test/emu/devices/adaq4224.xml | 1 + test/emu/hardware_map.yml | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 test/emu/devices/adaq4224.xml diff --git a/test/emu/devices/adaq4224.xml b/test/emu/devices/adaq4224.xml new file mode 100644 index 000000000..9921dd9c5 --- /dev/null +++ b/test/emu/devices/adaq4224.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 9e95b374c..e97baf071 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -299,6 +299,14 @@ ad4020: - filename: ad4020.xml - data_devices: - iio:device0 +adaq4224: + - adaq4224 + - pyadi_iio_class_support: + - adaq42xx + - emulate: + - filename: adaq4224.xml + - data_devices: + - iio:device0 ltc2387: - ltc2387 - pyadi_iio_class_support: From 65fd32ac17581f1cd2e0db579d924c4b353b5826 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 8 Nov 2023 18:05:31 -0300 Subject: [PATCH 8/8] test: ad4630: Add test for ADAQ4224 scale attribute Add test for ADAQ4224 scale attribue. Signed-off-by: Marcelo Schmitt --- test/test_ad4630.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/test_ad4630.py b/test/test_ad4630.py index 35ab3ba37..53fdc8ec0 100644 --- a/test/test_ad4630.py +++ b/test/test_ad4630.py @@ -1,3 +1,4 @@ +import adi import pytest hardware = ["ad4030-24", "ad4630-24"] @@ -55,3 +56,40 @@ def test_ad4630_channel_attrs( test_attribute_single_value( iio_uri, classname, attr, start, stop, step, tol, repeats, sub_channel ) + + +hardware = ["adaq4224"] +classname = "adi.adaq42xx" + +######################################### +@pytest.mark.iio_hardware(hardware) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, avail_attr, tol, repeats, sub_channel", + [("scale", "scale_available", 0, 1, "chan0",),], +) +def test_adaq42xx_scale_attr( + test_attribute_multiple_values, + iio_uri, + classname, + attr, + avail_attr, + tol, + repeats, + sub_channel, +): + # Get the device + sdr = eval(classname + "(uri='" + iio_uri + "')") + + # Check hardware + if not hasattr(sdr, sub_channel): + raise AttributeError(sub_channel + " not defined in " + classname) + if not hasattr(getattr(sdr, sub_channel), avail_attr): + raise AttributeError(avail_attr + " not defined in " + classname) + + # Get the list of available scale values + val = getattr(getattr(sdr, sub_channel), avail_attr) + + test_attribute_multiple_values( + iio_uri, classname, attr, val, tol, repeats, sub_channel=sub_channel + )