diff --git a/adi/__init__.py b/adi/__init__.py index bf1f21657..57dfd9ce8 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -73,6 +73,7 @@ adis16547, ) from adi.adis16507 import adis16507 +from adi.adis16550 import adis16550 from adi.adl5240 import adl5240 from adi.adl5960 import adl5960 from adi.admv8818 import admv8818 diff --git a/adi/adis16550.py b/adi/adis16550.py new file mode 100644 index 000000000..7c483dba4 --- /dev/null +++ b/adi/adis16550.py @@ -0,0 +1,473 @@ +# Copyright (C) 2019-2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +from adi.attribute import attribute +from adi.context_manager import context_manager +from adi.rx_tx import rx + + +class adis16550(rx, context_manager): + _complex_data = False + + _rx_channel_names = [ + "anglvel_x", + "anglvel_y", + "anglvel_z", + "accel_x", + "accel_y", + "accel_z", + "temp0", + "deltaangl_x", + "deltaangl_y", + "deltaangl_z", + "deltavelocity_x", + "deltavelocity_y", + "deltavelocity_z", + ] + + _device_name = "" + + """Disable mapping of trigger to RX device.""" + disable_trigger = False + + def __init__(self, uri="", device_name=None, trigger_name=None): + context_manager.__init__(self, uri, self._device_name) + + compatible_parts = ["adis16550", "adis16550w"] + + if not device_name: + device_name = compatible_parts[0] + + if device_name not in compatible_parts: + raise Exception( + "Not a compatible device:" + + str(device_name) + + ".Please select from:" + + str(compatible_parts) + ) + else: + self._ctrl = self._ctx.find_device(device_name) + self._rxadc = self._ctx.find_device(device_name) + if not trigger_name: + trigger_name = device_name + "-dev0" + + if self._ctrl is None: + print( + "No device found with device_name = " + + device_name + + ". Searching for a device found in the compatible list." + ) + for i in compatible_parts: + self._ctrl = self._ctx.find_device(i) + self._rxadc = self._ctx.find_device(i) + if self._ctrl is not None: + print("Found device = " + i + ". Will use this device instead.") + break + if self._ctrl is None: + raise Exception("No compatible device found") + + self.anglvel_x = self._anglvel_accel_channels(self._ctrl, "anglvel_x") + self.anglvel_y = self._anglvel_accel_channels(self._ctrl, "anglvel_y") + self.anglvel_z = self._anglvel_accel_channels(self._ctrl, "anglvel_z") + self.accel_x = self._anglvel_accel_channels(self._ctrl, "accel_x") + self.accel_y = self._anglvel_accel_channels(self._ctrl, "accel_y") + self.accel_z = self._anglvel_accel_channels(self._ctrl, "accel_z") + self.temp = self._temp_channel(self._ctrl, "temp0") + self.deltaangl_x = self._delta_channels(self._ctrl, "deltaangl_x") + self.deltaangl_y = self._delta_channels(self._ctrl, "deltaangl_y") + self.deltaangl_z = self._delta_channels(self._ctrl, "deltaangl_z") + self.deltavelocity_x = self._delta_channels(self._ctrl, "deltavelocity_x") + self.deltavelocity_y = self._delta_channels(self._ctrl, "deltavelocity_y") + self.deltavelocity_z = self._delta_channels(self._ctrl, "deltavelocity_z") + + # Set default trigger + if not self.disable_trigger: + self._trigger = self._ctx.find_device(trigger_name) + self._rxadc._set_trigger(self._trigger) + + rx.__init__(self) + self.rx_buffer_size = 16 # Make default buffer smaller + + def __get_scaled_sensor(self, channel_name: str) -> float: + raw = self._get_iio_attr(channel_name, "raw", False) + scale = self._get_iio_attr(channel_name, "scale", False) + + return raw * scale + + def __get_scaled_sensor_temp(self, channel_name: str) -> float: + raw = self._get_iio_attr(channel_name, "raw", False) + scale = self._get_iio_attr(channel_name, "scale", False) + offset = self._get_iio_attr(channel_name, "offset", False) + + return (raw + offset) * scale + + def get_anglvel_x(self): + """Value returned in radians per second.""" + return self.__get_scaled_sensor("anglvel_x") + + anglvel_x_conv = property(get_anglvel_x, None) + + def get_anglvel_y(self): + """Value returned in radians per second.""" + return self.__get_scaled_sensor("anglvel_y") + + anglvel_y_conv = property(get_anglvel_y, None) + + def get_anglvel_z(self): + """Value returned in radians per second.""" + return self.__get_scaled_sensor("anglvel_z") + + anglvel_z_conv = property(get_anglvel_z, None) + + def get_accel_x(self): + """Value returned in meters per squared second.""" + return self.__get_scaled_sensor("accel_x") + + accel_x_conv = property(get_accel_x, None) + + def get_accel_y(self): + """Value returned in meters per squared second.""" + return self.__get_scaled_sensor("accel_y") + + accel_y_conv = property(get_accel_y, None) + + def get_accel_z(self): + """Value returned in meters per squared second.""" + return self.__get_scaled_sensor("accel_z") + + accel_z_conv = property(get_accel_z, None) + + def get_temp(self): + """Value returned in millidegrees Celsius.""" + return self.__get_scaled_sensor_temp("temp0") + + temp_conv = property(get_temp, None) + + def get_deltaangl_x(self): + """Value returned in radians.""" + return self.__get_scaled_sensor("deltaangl_x") + + deltaangl_x_conv = property(get_deltaangl_x, None) + + def get_deltaangl_y(self): + """Value returned in radians.""" + return self.__get_scaled_sensor("deltaangl_y") + + deltaangl_y_conv = property(get_deltaangl_y, None) + + def get_deltaangl_z(self): + """Value returned in radians.""" + return self.__get_scaled_sensor("deltaangl_z") + + deltaangl_z_conv = property(get_deltaangl_z, None) + + def get_deltavelocity_x(self): + """Value returned in meters per second.""" + return self.__get_scaled_sensor("deltavelocity_x") + + deltavelocity_x_conv = property(get_deltavelocity_x, None) + + def get_deltavelocity_y(self): + """Value returned in meters per second.""" + return self.__get_scaled_sensor("deltavelocity_y") + + deltavelocity_y_conv = property(get_deltavelocity_y, None) + + def get_deltavelocity_z(self): + """Value returned in meters per second.""" + return self.__get_scaled_sensor("deltavelocity_z") + + deltavelocity_z_conv = property(get_deltavelocity_z, None) + + @property + def sample_rate(self): + """sample_rate: Sample rate in samples per second""" + return self._get_iio_dev_attr("sampling_frequency") + + @sample_rate.setter + def sample_rate(self, value): + self._set_iio_dev_attr_str("sampling_frequency", value) + + @property + def current_timestamp_clock(self): + """current_timestamp_clock: Source clock for timestamps""" + return self._get_iio_dev_attr("current_timestamp_clock") + + @current_timestamp_clock.setter + def current_timestamp_clock(self, value): + self._set_iio_dev_attr_str("current_timestamp_clock", value) + + @property + def anglvel_x_calibbias(self): + """User calibration offset for gyroscope for the x-axis.""" + return self._get_iio_attr("anglvel_x", "calibbias", False) + + @anglvel_x_calibbias.setter + def anglvel_x_calibbias(self, value): + self._set_iio_attr("anglvel_x", "calibbias", False, value) + + @property + def anglvel_y_calibbias(self): + """User calibration offset for gyroscope for the y-axis.""" + return self._get_iio_attr("anglvel_y", "calibbias", False) + + @anglvel_y_calibbias.setter + def anglvel_y_calibbias(self, value): + self._set_iio_attr("anglvel_y", "calibbias", False, value) + + @property + def anglvel_z_calibbias(self): + """User calibration offset for gyroscope for the z-axis.""" + return self._get_iio_attr("anglvel_z", "calibbias", False) + + @anglvel_z_calibbias.setter + def anglvel_z_calibbias(self, value): + self._set_iio_attr("anglvel_z", "calibbias", False, value) + + @property + def accel_x_calibbias(self): + """User calibration offset for accelerometer for the x-axis.""" + return self._get_iio_attr("accel_x", "calibbias", False) + + @accel_x_calibbias.setter + def accel_x_calibbias(self, value): + self._set_iio_attr("accel_x", "calibbias", False, value) + + @property + def accel_y_calibbias(self): + """User calibration offset for accelerometer for the y-axis.""" + return self._get_iio_attr("accel_y", "calibbias", False) + + @accel_y_calibbias.setter + def accel_y_calibbias(self, value): + self._set_iio_attr("accel_y", "calibbias", False, value) + + @property + def accel_z_calibbias(self): + """User calibration offset for accelerometer for the z-axis.""" + return self._get_iio_attr("accel_z", "calibbias", False) + + @accel_z_calibbias.setter + def accel_z_calibbias(self, value): + self._set_iio_attr("accel_z", "calibbias", False, value) + + @property + def anglvel_x_calibscale(self): + """Calibscale value for gyroscope for the x-axis.""" + return self._get_iio_attr("anglvel_x", "calibscale", False) + + @anglvel_x_calibscale.setter + def anglvel_x_calibscale(self, value): + self._set_iio_attr("anglvel_x", "calibscale", False, value) + + @property + def anglvel_y_calibscale(self): + """Calibscale value for gyroscope for the y-axis.""" + return self._get_iio_attr("anglvel_y", "calibscale", False) + + @anglvel_y_calibscale.setter + def anglvel_y_calibscale(self, value): + self._set_iio_attr("anglvel_y", "calibscale", False, value) + + @property + def anglvel_z_calibscale(self): + """Calibscale value for gyroscope for the z-axis.""" + return self._get_iio_attr("anglvel_z", "calibscale", False) + + @anglvel_z_calibscale.setter + def anglvel_z_calibscale(self, value): + self._set_iio_attr("anglvel_z", "calibscale", False, value) + + @property + def accel_x_calibscale(self): + """Calibscale value for accelerometer for the x-axis.""" + return self._get_iio_attr("accel_x", "calibscale", False) + + @accel_x_calibscale.setter + def accel_x_calibscale(self, value): + self._set_iio_attr("accel_x", "calibscale", False, value) + + @property + def accel_y_calibscale(self): + """Calibcale value for accelerometer for the y-axis.""" + return self._get_iio_attr("accel_y", "calibscale", False) + + @accel_y_calibscale.setter + def accel_y_calibscale(self, value): + self._set_iio_attr("accel_y", "calibscale", False, value) + + @property + def accel_z_calibscale(self): + """Calibscale for accelerometer for the z-axis.""" + return self._get_iio_attr("accel_z", "calibscale", False) + + @accel_z_calibscale.setter + def accel_z_calibscale(self, value): + self._set_iio_attr("accel_z", "calibscale", False, value) + + @property + def anglvel_x_filter_low_pass_3db_frequency(self): + """Bandwidth for gyroscope for the x-axis.""" + return self._get_iio_attr("anglvel_x", "filter_low_pass_3db_frequency", False) + + @anglvel_x_filter_low_pass_3db_frequency.setter + def anglvel_x_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("anglvel_x", "filter_low_pass_3db_frequency", False, value) + + @property + def anglvel_y_filter_low_pass_3db_frequency(self): + """Bandwidth for gyroscope for the y-axis.""" + return self._get_iio_attr("anglvel_y", "filter_low_pass_3db_frequency", False) + + @anglvel_y_filter_low_pass_3db_frequency.setter + def anglvel_y_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("anglvel_y", "filter_low_pass_3db_frequency", False, value) + + @property + def anglvel_z_filter_low_pass_3db_frequency(self): + """Bandwidth for gyroscope for the z-axis.""" + return self._get_iio_attr("anglvel_z", "filter_low_pass_3db_frequency", False) + + @anglvel_z_filter_low_pass_3db_frequency.setter + def anglvel_z_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("anglvel_z", "filter_low_pass_3db_frequency", False, value) + + @property + def accel_x_filter_low_pass_3db_frequency(self): + """Bandwidth for accelerometer for the x-axis.""" + return self._get_iio_attr("accel_x", "filter_low_pass_3db_frequency", False) + + @accel_x_filter_low_pass_3db_frequency.setter + def accel_x_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("accel_x", "filter_low_pass_3db_frequency", False, value) + + @property + def accel_y_filter_low_pass_3db_frequency(self): + """Bandwidth for accelerometer for the y-axis.""" + return self._get_iio_attr("accel_y", "filter_low_pass_3db_frequency", False) + + @accel_y_filter_low_pass_3db_frequency.setter + def accel_y_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("accel_y", "filter_low_pass_3db_frequency", False, value) + + @property + def accel_z_filter_low_pass_3db_frequency(self): + """Bandwidth for accelerometer for the z-axis.""" + return self._get_iio_attr("accel_z", "filter_low_pass_3db_frequency", False) + + @accel_z_filter_low_pass_3db_frequency.setter + def accel_z_filter_low_pass_3db_frequency(self, value): + self._set_iio_attr("accel_z", "filter_low_pass_3db_frequency", False, value) + + @property + def firmware_revision(self): + """firmware_revision: the firmware revision for the internal firmware""" + return self._get_iio_debug_attr_str("firmware_revision") + + @property + def firmware_date(self): + """firmware_date: the factory configuration date""" + return self._get_iio_debug_attr_str("firmware_date") + + @property + def product_id(self): + """product_id: the numerical portion of the device number""" + return self._get_iio_debug_attr("product_id") + + @property + def serial_number(self): + """serial_number: lot specific serial number""" + return self._get_iio_debug_attr_str("serial_number") + + @property + def flash_count(self): + """flash_counter: flash memory write count""" + return self._get_iio_debug_attr("flash_count") + + class _temp_channel(attribute): + """ADIS16550 temperature channel.""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + @property + def raw(self): + """ADIS16550 raw value""" + return self._get_iio_attr(self.name, "raw", False) + + @property + def scale(self): + """ADIS16550 scale value""" + return self._get_iio_attr(self.name, "scale", False) + + @property + def offset(self): + """ADIS16550 offset value""" + return self._get_iio_attr(self.name, "offset", False) + + class _simple_channel(attribute): + """ADIS16550 basic channel, only scale an raw values""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + @property + def raw(self): + """ADIS16550 raw value""" + return self._get_iio_attr(self.name, "raw", False) + + @property + def scale(self): + """ADIS16550 scale value""" + return self._get_iio_attr(self.name, "scale", False) + + class _extended_channel(_simple_channel): + """ADIS16550 pressure channel.""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + @property + def calibbias(self): + """ADIS16550 calibration offset""" + return self._get_iio_attr(self.name, "calibbias", False) + + @calibbias.setter + def calibbias(self, value): + self._set_iio_attr(self.name, "calibbias", False, value) + + @property + def calibscale(self): + """ADIS16550 calibration scale""" + return self._get_iio_attr(self.name, "calibscale", False) + + @calibscale.setter + def calibscale(self, value): + self._set_iio_attr(self.name, "calibscale", False, value) + + @property + def filter_low_pass_3db_frequency(self): + """ADIS16550 channel bandwidth""" + return self._get_iio_attr(self.name, "filter_low_pass_3db_frequency", False) + + @filter_low_pass_3db_frequency.setter + def filter_low_pass_3db_frequency(self, value): + self._set_iio_attr(self.name, "filter_low_pass_3db_frequency", False, value) + + class _anglvel_accel_channels(_extended_channel): + """ADIS16550 gyro and accelerometer channels.""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + class _delta_channels(_simple_channel): + """ADIS16550 delta angle and delta velocity channels.""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl diff --git a/doc/source/devices/adi.adis16550.rst b/doc/source/devices/adi.adis16550.rst new file mode 100644 index 000000000..f16fb307c --- /dev/null +++ b/doc/source/devices/adi.adis16550.rst @@ -0,0 +1,8 @@ +adis16550 +==================== + +.. autoclass:: adi.adis16550 + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index 52df1b849..b22265878 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -79,6 +79,7 @@ Supported Devices adi.adis16507 adi.adis16545 adi.adis16547 + adi.adis16550 adi.adl5240 adi.adl5960 adi.admv8818 diff --git a/examples/adis16550_example.py b/examples/adis16550_example.py new file mode 100644 index 000000000..95b8f8ad4 --- /dev/null +++ b/examples/adis16550_example.py @@ -0,0 +1,59 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD +import sys + +import adi +import matplotlib.pyplot as plt + +# Set up ADIS16550 +my_dev_name = sys.argv[1] +my_uri = sys.argv[2] + +dev = adi.adis16550(device_name=my_dev_name, uri=my_uri) + +dev.rx_output_type = "raw" +dev.rx_enabled_channels = [0, 1, 2, 3, 4, 5] +# dev.rx_enabled_delta_channels = [7, 8, 9, 10, 11, 12] +dev.sample_rate = 10 +dev.rx_buffer_size = 10 + +print("\nX acceleration: " + str(dev.accel_x_conv) + " m/s^2") +print("Y acceleration: " + str(dev.accel_y_conv) + " m/s^2") +print("Z acceleration: " + str(dev.accel_z_conv) + " m/s^2") + +print("\nX angular velocity: " + str(dev.anglvel_x_conv) + " rad/s") +print("Y angular velocity: " + str(dev.anglvel_y_conv) + " rad/s") +print("Z angular velocity: " + str(dev.anglvel_z_conv) + " rad/s") + +print("\nX delta velocity: " + str(dev.deltavelocity_x_conv) + " m/s") +print("Y delta velocity: " + str(dev.deltavelocity_y_conv) + " m/s") +print("Z delta velocity: " + str(dev.deltavelocity_z_conv) + " m/s") + +print("\nX delta angle: " + str(dev.deltaangl_x_conv) + " rad") +print("Y delta angle: " + str(dev.deltaangl_y_conv) + " rad") +print("Z delta angle: " + str(dev.deltaangl_z_conv) + " rad") + +dev.sample_rate = 2000 +dev.magn_x_filter_low_pass_3db_frequency = 100 +dev.anglvel_y_calibscale = 30 +dev.anglvel_x_calibbias = 100 + +print("\nSampling frequency: " + str(dev.sample_rate)) + +print("Temperature raw value: " + str(dev.temp.raw)) +print("Temperature scale value: " + str(dev.temp.scale)) +print("Temperature offset value: " + str(dev.temp.offset)) + +print("X-axis gyro channel calibbias value: " + str(dev.anglvel_x_calibbias)) +print("X-axis gyro channel calibscale value: " + str(dev.anglvel_y_calibscale)) +print("X-axis magnetometer bandwidth: " + str(dev.magn_x_filter_low_pass_3db_frequency)) + +for _ in range(100): + data = dev.rx() + plt.clf() + for i, d in enumerate(data): + plt.plot(d, label=dev._rx_channel_names[dev.rx_enabled_channels[i]]) + plt.legend() + plt.show(block=False) + plt.pause(0.1) diff --git a/supported_parts.md b/supported_parts.md index b99b05617..035de9857 100644 --- a/supported_parts.md +++ b/supported_parts.md @@ -143,6 +143,8 @@ - ADIS16507 - ADIS16545 - ADIS16547 +- ADIS16550 +- ADIS16550W - ADL5240 - ADL5960 - ADMV8818 diff --git a/test/emu/devices/adis16550.xml b/test/emu/devices/adis16550.xml new file mode 100644 index 000000000..45c2a414b --- /dev/null +++ b/test/emu/devices/adis16550.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/emu/hardware_map.yml b/test/emu/hardware_map.yml index 6477c641c..48b1938f9 100644 --- a/test/emu/hardware_map.yml +++ b/test/emu/hardware_map.yml @@ -584,6 +584,15 @@ adis16480: - pyadi_iio_class_support: - adis16480 +adis16550: + - adis16550 + - emulate: + - filename: adis16550.xml + - data_devices: + - iio:device0 + - pyadi_iio_class_support: + - adis16550 + ad7124-8: - ad7124 - pyadi_iio_class_support: diff --git a/test/test_adis16550.py b/test/test_adis16550.py new file mode 100644 index 000000000..43b19888a --- /dev/null +++ b/test/test_adis16550.py @@ -0,0 +1,80 @@ +import iio + +import adi +import pytest + +hardware = "adis16550" +classname = "adi.adis16550" +device_name = "adis16550" + + +def do_mock(): + def mock_set_trigger(self, value): + pass + + # Mock the _set_trigger method in iio.Device + iio.Device._set_trigger = mock_set_trigger + + +######################################### +@pytest.mark.iio_hardware(hardware, False) +def test_adis16550_conv_data(iio_uri): + do_mock() + adis16550 = adi.adis16550(uri=iio_uri) + + assert adis16550.accel_x_conv != 0.0 + assert adis16550.accel_y_conv != 0.0 + assert adis16550.accel_z_conv != 0.0 + assert adis16550.anglvel_x_conv != 0.0 + assert adis16550.anglvel_y_conv != 0.0 + assert adis16550.anglvel_z_conv != 0.0 + assert adis16550.temp_conv != 0.0 + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, start, stop, step, tol", + [ + ("anglvel_x_calibbias", -2147483648, 2147483647, 1, 0), + ("anglvel_y_calibbias", -2147483648, 2147483647, 1, 0), + ("anglvel_z_calibbias", -2147483648, 2147483647, 1, 0), + ("accel_x_calibbias", -2147483648, 2147483647, 1, 0), + ("accel_y_calibbias", -2147483648, 2147483647, 1, 0), + ("accel_z_calibbias", -2147483648, 2147483647, 1, 0), + ("anglvel_x_calibscale", 0, 65535, 1, 0), + ("anglvel_y_calibscale", 0, 65535, 1, 0), + ("anglvel_z_calibscale", 0, 65535, 1, 0), + ("accel_x_calibscale", 0, 65535, 1, 0), + ("accel_y_calibscale", 0, 65535, 1, 0), + ("accel_z_calibscale", 0, 65535, 1, 0), + ], +) +def test_adis16550_attr( + test_attribute_single_value, iio_uri, classname, attr, start, stop, step, tol +): + do_mock() + test_attribute_single_value(iio_uri, classname, attr, start, stop, step, tol) + + +######################################### +@pytest.mark.iio_hardware(hardware, True) +@pytest.mark.parametrize("classname", [(classname)]) +@pytest.mark.parametrize( + "attr, values, tol, repeats", + [ + ("sample_rate", [5, 10, 246, 1230, 2460], 0.5, 2), + ("anglvel_x_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ("anglvel_y_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ("anglvel_z_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ("accel_x_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ("accel_y_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ("accel_z_filter_low_pass_3db_frequency", [0, 55, 275, 310], 0.5, 2), + ], +) +def test_adis16550_attr_multiple_val( + test_attribute_multiple_values, iio_uri, classname, attr, values, tol, repeats, +): + do_mock() + test_attribute_multiple_values(iio_uri, classname, attr, values, tol, repeats)