Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ADAQ42xx #487

Merged
merged 8 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion adi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 31 additions & 4 deletions adi/ad4630.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# SPDX short identifier: ADIBSD

from decimal import Decimal

import numpy as np
from adi.attribute import attribute
Expand All @@ -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 = ""
Expand All @@ -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)
Expand Down Expand Up @@ -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))
2 changes: 1 addition & 1 deletion examples/ad4630/ad4630_example_simple_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
53 changes: 53 additions & 0 deletions examples/adaq4224_example.py
Original file line number Diff line number Diff line change
@@ -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()
3 changes: 3 additions & 0 deletions supported_parts.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@
- AD4858
- AD9739A
- ADA4961
- ADAQ4216
- ADAQ4220
- ADAQ4224
- ADAQ8092
- ADAR1000
- ADF4159
Expand Down
14 changes: 12 additions & 2 deletions test/attr_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -201,11 +203,19 @@ 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
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)

Expand Down
4 changes: 3 additions & 1 deletion test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions test/emu/devices/adaq4224.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE context [<!ELEMENT context (device | context-attribute)*><!ELEMENT context-attribute EMPTY><!ELEMENT device (channel | attribute | debug-attribute | buffer-attribute)*><!ELEMENT channel (scan-element?, attribute*)><!ELEMENT attribute EMPTY><!ELEMENT scan-element EMPTY><!ELEMENT debug-attribute EMPTY><!ELEMENT buffer-attribute EMPTY><!ATTLIST context name CDATA #REQUIRED description CDATA #IMPLIED><!ATTLIST context-attribute name CDATA #REQUIRED value CDATA #REQUIRED><!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED><!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED><!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED><!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED value CDATA #IMPLIED><!ATTLIST debug-attribute name CDATA #REQUIRED value CDATA #IMPLIED><!ATTLIST buffer-attribute name CDATA #REQUIRED value CDATA #IMPLIED>]><context name="network" description="10.48.65.140 Linux analog 5.15.0-175797-g686d161a4f43 #385 SMP PREEMPT Fri Sep 22 17:08:22 EEST 2023 armv7l" ><context-attribute name="hdl_system_id" value="[AD463XADAQ42XXN0_CLKMODE0_NUMOFSDI1_CAPTUREZONE2_DDREN0/ad463x_adaq42xx_zed] [sys rom custom string placeholder] on [zed] git branch [dev_adaq4224_final] git [7df56bd2d04bdccc44d9bbfa94c800b828abb80f] dirty [2023-11-01 14:03:21] UTC" /><context-attribute name="hw_carrier" value="Xilinx Zynq ZED" /><context-attribute name="hw_model" value="EVAL-ADAQ4224-FMCZ on Xilinx Zynq ZED" /><context-attribute name="local,kernel" value="5.15.0-175797-g686d161a4f43" /><context-attribute name="uri" value="ip:10.48.65.140" /><context-attribute name="ip,ip-addr" value="10.48.65.140" /><device id="hwmon0" name="e000b000ethernetffffffff00" ><channel id="temp1" type="input" ><attribute name="crit" filename="temp1_crit" value="100000" /><attribute name="input" filename="temp1_input" value="31000" /><attribute name="max_alarm" filename="temp1_max_alarm" value="0" /></channel></device><device id="hwmon1" name="max31827" ><channel id="temp1" type="input" ><attribute name="enable" filename="temp1_enable" value="1" /><attribute name="input" filename="temp1_input" value="37437" /><attribute name="max" filename="temp1_max" value="100000" /><attribute name="max_alarm" filename="temp1_max_alarm" value="1" /><attribute name="max_hyst" filename="temp1_max_hyst" value="-312" /><attribute name="min" filename="temp1_min" value="-40000" /><attribute name="min_alarm" filename="temp1_min_alarm" value="0" /><attribute name="min_hyst" filename="temp1_min_hyst" value="-30000" /><attribute name="resolution" filename="temp1_resolution" value="62" /></channel><attribute name="pec" value="0" /><attribute name="update_interval" value="1000" /></device><device id="iio:device0" name="adaq4224" ><channel id="voltage0" type="input" ><scan-element index="0" format="le:s24/64&gt;&gt;0" scale="0.000197" /><attribute name="calibbias" filename="in_voltage0_calibbias" value="0" /><attribute name="calibscale" filename="in_voltage0_calibscale" value="1.000000" /><attribute name="scale" filename="in_voltage_scale" value="0.000196695" /><attribute name="scale_available" filename="in_voltage_scale_available" value="0.000196695 0.000333786 0.001323223 0.003975629" /></channel><attribute name="sampling_frequency" value="2000000" /><buffer-attribute name="data_available" value="0" /><buffer-attribute name="length_align_bytes" value="8" /><debug-attribute name="test_pattern_enable" value="0" /><debug-attribute name="test_pattern" value="1515851535" /><debug-attribute name="direct_reg_access" value="0x10" /></device><device id="iio:device1" name="xadc" ><channel id="voltage5" name="vccoddr" type="input" ><attribute name="label" filename="in_voltage5_vccoddr_label" value="vccoddr" /><attribute name="raw" filename="in_voltage5_vccoddr_raw" value="2028" /><attribute name="scale" filename="in_voltage5_vccoddr_scale" value="0.732421875" /></channel><channel id="voltage0" name="vccint" type="input" ><attribute name="label" filename="in_voltage0_vccint_label" value="vccint" /><attribute name="raw" filename="in_voltage0_vccint_raw" value="1348" /><attribute name="scale" filename="in_voltage0_vccint_scale" value="0.732421875" /></channel><channel id="voltage4" name="vccpaux" type="input" ><attribute name="label" filename="in_voltage4_vccpaux_label" value="vccpaux" /><attribute name="raw" filename="in_voltage4_vccpaux_raw" value="2454" /><attribute name="scale" filename="in_voltage4_vccpaux_scale" value="0.732421875" /></channel><channel id="temp0" type="input" ><attribute name="offset" filename="in_temp0_offset" value="-2219" /><attribute name="raw" filename="in_temp0_raw" value="2591" /><attribute name="scale" filename="in_temp0_scale" value="123.040771484" /></channel><channel id="voltage7" name="vrefn" type="input" ><attribute name="label" filename="in_voltage7_vrefn_label" value="vrefn" /><attribute name="raw" filename="in_voltage7_vrefn_raw" value="-2" /><attribute name="scale" filename="in_voltage7_vrefn_scale" value="0.732421875" /></channel><channel id="voltage1" name="vccaux" type="input" ><attribute name="label" filename="in_voltage1_vccaux_label" value="vccaux" /><attribute name="raw" filename="in_voltage1_vccaux_raw" value="2460" /><attribute name="scale" filename="in_voltage1_vccaux_scale" value="0.732421875" /></channel><channel id="voltage2" name="vccbram" type="input" ><attribute name="label" filename="in_voltage2_vccbram_label" value="vccbram" /><attribute name="raw" filename="in_voltage2_vccbram_raw" value="1351" /><attribute name="scale" filename="in_voltage2_vccbram_scale" value="0.732421875" /></channel><channel id="voltage3" name="vccpint" type="input" ><attribute name="label" filename="in_voltage3_vccpint_label" value="vccpint" /><attribute name="raw" filename="in_voltage3_vccpint_raw" value="1346" /><attribute name="scale" filename="in_voltage3_vccpint_scale" value="0.732421875" /></channel><channel id="voltage6" name="vrefp" type="input" ><attribute name="label" filename="in_voltage6_vrefp_label" value="vrefp" /><attribute name="raw" filename="in_voltage6_vrefp_raw" value="1701" /><attribute name="scale" filename="in_voltage6_vrefp_scale" value="0.732421875" /></channel><attribute name="sampling_frequency" value="961538" /></device><device id="iio:device2" name="one-bit-adc-dac" ><channel id="voltage0" type="input" ><attribute name="label" filename="in_voltage0_label" value="MAX17687_RST" /><attribute name="raw" filename="in_voltage0_raw" value="1" /></channel></device><device id="iio_sysfs_trigger" ><attribute name="add_trigger" value="ERROR" /><attribute name="remove_trigger" value="ERROR" /></device></context>
8 changes: 8 additions & 0 deletions test/emu/hardware_map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
38 changes: 38 additions & 0 deletions test/test_ad4630.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import adi
import pytest

hardware = ["ad4030-24", "ad4630-24"]
Expand Down Expand Up @@ -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
)
Loading