Skip to content

Commit 5d11971

Browse files
committed
Add support for AD7490
Signed-off-by: RaduSabau1 <radu.sabau@analog.com>
1 parent 6b33acd commit 5d11971

File tree

9 files changed

+245
-0
lines changed

9 files changed

+245
-0
lines changed

adi/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from adi.ad7124 import ad7124
3131
from adi.ad7134 import ad7134
3232
from adi.ad7291 import ad7291
33+
from adi.ad7490 import ad7490
3334
from adi.ad7606 import ad7606
3435
from adi.ad7689 import ad7689
3536
from adi.ad7746 import ad7746

adi/ad7490.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Copyright (C) 2025 Analog Devices, Inc.
2+
#
3+
# SPDX short identifier: ADIBSD
4+
5+
import numpy as np
6+
7+
from adi.attribute import attribute
8+
from adi.context_manager import context_manager
9+
from adi.rx_tx import rx
10+
11+
12+
class ad7490(rx, context_manager):
13+
"""AD7490 ADC"""
14+
15+
_complex_data = False
16+
channel = [] # type: ignore
17+
_device_name = ""
18+
19+
def __init__(self, uri="", device_name=""):
20+
21+
context_manager.__init__(self, uri, self._device_name)
22+
23+
compatible_parts = [
24+
"ad7490",
25+
]
26+
27+
self._ctrl = None
28+
29+
if not device_name:
30+
device_name = compatible_parts[0]
31+
else:
32+
if device_name not in compatible_parts:
33+
raise Exception("Not a compatible device: " + device_name)
34+
35+
# Select the device matching device_name as working device
36+
for device in self._ctx.devices:
37+
if device.name == device_name:
38+
self._ctrl = device
39+
self._rxadc = device
40+
break
41+
42+
self._rx_channel_names = []
43+
self.channel = []
44+
for ch in self._ctrl.channels:
45+
name = ch._id
46+
self._rx_channel_names.append(name)
47+
self.channel.append(self._channel(self._ctrl, name))
48+
49+
rx.__init__(self)
50+
51+
@property
52+
def polarity_available(self):
53+
"""Provides all available polarity settings for the AD7490 channels"""
54+
return self._get_iio_dev_attr_str("polarity_available")
55+
56+
@property
57+
def range_available(self):
58+
"""Provides all available range settings for the AD7490 channels"""
59+
return self._get_iio_dev_attr_str("range_available")
60+
61+
@property
62+
def polarity(self):
63+
"""AD7490 polarity"""
64+
return self._get_iio_dev_attr_str("polarity")
65+
66+
@polarity.setter
67+
def polarity(self, ptype):
68+
"""Set polarity."""
69+
if ptype in self.polarity_available:
70+
self._set_iio_dev_attr_str("polarity", ptype)
71+
else:
72+
raise ValueError(
73+
"Error: Polarity type not supported \nUse one of: "
74+
+ str(self.polarity_available)
75+
)
76+
77+
@property
78+
def range(self):
79+
"""AD7490 range"""
80+
return self._get_iio_dev_attr_str("range")
81+
82+
@range.setter
83+
def range(self, rtype):
84+
"""Set range."""
85+
if rtype in self.range_available:
86+
self._set_iio_dev_attr_str("range", rtype)
87+
else:
88+
raise ValueError(
89+
"Error: Range type not supported \nUse one of: "
90+
+ str(self.range_available)
91+
)
92+
93+
class _channel(attribute):
94+
"""AD7490 channel"""
95+
96+
def __init__(self, ctrl, channel_name):
97+
self.name = channel_name
98+
self._ctrl = ctrl
99+
100+
@property
101+
def raw(self):
102+
"""AD7490 channel raw value"""
103+
return self._get_iio_attr(self.name, "raw", False)
104+
105+
@property
106+
def scale(self):
107+
"""AD7490 channel scale"""
108+
return float(self._get_iio_attr_str(self.name, "scale", False))
109+
110+
def to_volts(self, index, val):
111+
"""Converts raw value to SI"""
112+
_scale = self.channel[index].scale
113+
114+
ret = None
115+
116+
if isinstance(val, np.int16):
117+
ret = val * _scale
118+
119+
if isinstance(val, np.ndarray):
120+
ret = [x * _scale for x in val]
121+
122+
return ret

doc/source/devices/adi.ad7490.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
ad7490
2+
=================
3+
4+
.. automodule:: adi.ad7490
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

doc/source/devices/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Supported Devices
3333
adi.ad719x
3434
adi.ad7291
3535
adi.ad738x
36+
adi.ad7490
3637
adi.ad7606
3738
adi.ad7689
3839
adi.ad7746

examples/ad7490_example.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright (C) 2025 Analog Devices, Inc.
2+
#
3+
# SPDX short identifier: ADIBSD
4+
5+
import sys
6+
from time import sleep
7+
8+
import matplotlib.pyplot as plt
9+
10+
import numpy as np
11+
from scipy import signal
12+
13+
import argparse
14+
15+
import adi
16+
from adi import ad7490
17+
18+
# Optionally pass URI as command line argument with -u option,
19+
# else use default to "ip:analog.local"
20+
parser = argparse.ArgumentParser(description="AD7490 Example Script")
21+
parser.add_argument(
22+
"-u",
23+
default=["serial:/dev/ttyACM0,57600,8n1"],
24+
help="-u (arg) URI of target device's context, eg: 'ip:analog.local',\
25+
'ip:192.168.2.1',\
26+
'serial:/dev/ttyACM0,57600,8n1n'",
27+
action="store",
28+
nargs="*",
29+
)
30+
args = parser.parse_args()
31+
my_uri = args.u[0]
32+
33+
print("uri: " + str(my_uri))
34+
35+
# Set up AD7490
36+
my_adc = adi.ad7490(uri=my_uri)
37+
my_adc.rx_buffer_size = 200
38+
39+
# Choose Polarity
40+
my_adc.polarity = "UNIPOLAR"
41+
# my_adc.polarity = "BIPOLAR"
42+
43+
# Choose range:
44+
my_adc.range = "REF_IN"
45+
# my_adc.range = "2X_REF_IN"
46+
47+
# Choose output format:
48+
my_adc.rx_output_type = "raw"
49+
# my_adc.rx_output_type = "SI"
50+
51+
# Verify settings:
52+
print("Polarity: ", my_adc.polarity)
53+
print("Range: ", my_adc.range)
54+
print("Enabled Channels: ", my_adc.rx_enabled_channels)
55+
56+
57+
plt.clf()
58+
sleep(0.5)
59+
data = my_adc.rx()
60+
for ch in my_adc.rx_enabled_channels:
61+
plt.plot(range(0, len(data[0])), data[ch], label="voltage" + str(ch))
62+
plt.xlabel("Data Point")
63+
if my_adc.rx_output_type == "SI":
64+
plt.ylabel("Millivolts")
65+
else:
66+
plt.ylabel("ADC counts")
67+
plt.legend(
68+
bbox_to_anchor=(0.0, 1.02, 1.0, 0.102),
69+
loc="lower left",
70+
ncol=4,
71+
mode="expand",
72+
borderaxespad=0.0,
73+
)
74+
plt.pause(10)
75+
76+
del my_adc

supported_parts.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
- AD7194
9494
- AD7195
9595
- AD7291
96+
- AD7490
9697
- AD7768
9798
- AD7768-4
9899
- AD7770

test/emu/devices/ad7490.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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 version-major CDATA #REQUIRED version-minor CDATA #REQUIRED version-git CDATA #REQUIRED description CDATA #IMPLIED><!ATTLIST context-attribute name CDATA #REQUIRED value CDATA #REQUIRED><!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED label 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><!ATTLIST debug-attribute name CDATA #REQUIRED><!ATTLIST buffer-attribute name CDATA #REQUIRED>]><context name="xml" version-major="0" version-minor="26" version-git="a0eca0d" description="no-OS/projects/eval-ad7490sdz staging/ad7940-07432d3f3" ><device id="iio:device0" name="ad7490" ><channel id="voltage0" type="input" ><scan-element index="0" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage0_raw" /><attribute name="scale" filename="in_voltage0_scale" /></channel><channel id="voltage1" type="input" ><scan-element index="1" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage1_raw" /><attribute name="scale" filename="in_voltage1_scale" /></channel><channel id="voltage2" type="input" ><scan-element index="2" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage2_raw" /><attribute name="scale" filename="in_voltage2_scale" /></channel><channel id="voltage3" type="input" ><scan-element index="3" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage3_raw" /><attribute name="scale" filename="in_voltage3_scale" /></channel><channel id="voltage4" type="input" ><scan-element index="4" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage4_raw" /><attribute name="scale" filename="in_voltage4_scale" /></channel><channel id="voltage5" type="input" ><scan-element index="5" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage5_raw" /><attribute name="scale" filename="in_voltage5_scale" /></channel><channel id="voltage6" type="input" ><scan-element index="6" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage6_raw" /><attribute name="scale" filename="in_voltage6_scale" /></channel><channel id="voltage7" type="input" ><scan-element index="7" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage7_raw" /><attribute name="scale" filename="in_voltage7_scale" /></channel><channel id="voltage8" type="input" ><scan-element index="8" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage8_raw" /><attribute name="scale" filename="in_voltage8_scale" /></channel><channel id="voltage9" type="input" ><scan-element index="9" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage9_raw" /><attribute name="scale" filename="in_voltage9_scale" /></channel><channel id="voltage10" type="input" ><scan-element index="10" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage10_raw" /><attribute name="scale" filename="in_voltage10_scale" /></channel><channel id="voltage11" type="input" ><scan-element index="11" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage11_raw" /><attribute name="scale" filename="in_voltage11_scale" /></channel><channel id="voltage12" type="input" ><scan-element index="12" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage12_raw" /><attribute name="scale" filename="in_voltage12_scale" /></channel><channel id="voltage13" type="input" ><scan-element index="13" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage13_raw" /><attribute name="scale" filename="in_voltage13_scale" /></channel><channel id="voltage14" type="input" ><scan-element index="14" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage14_raw" /><attribute name="scale" filename="in_voltage14_scale" /></channel><channel id="voltage15" type="input" ><scan-element index="15" format="le:u12/16&gt;&gt;0" /><attribute name="raw" filename="in_voltage15_raw" /><attribute name="scale" filename="in_voltage15_scale" /></channel><attribute name="polarity" /><attribute name="polarity_available" /><attribute name="range" /><attribute name="range_available" /></device></context>

test/emu/hardware_map.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,3 +748,11 @@ ad738x:
748748
- data_devices:
749749
- iio:device0
750750

751+
ad7490:
752+
- ad7490
753+
- pyadi_iio_class_support:
754+
- ad7490
755+
- emulate:
756+
- filename: ad7490.xml
757+
- data_devices:
758+
- iio:device0

test/test_ad7490.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
3+
hardware = "ad7490"
4+
classname = "adi.ad7490"
5+
6+
7+
#########################################
8+
@pytest.mark.iio_hardware(hardware, True)
9+
@pytest.mark.parametrize("classname", [(classname)])
10+
@pytest.mark.parametrize("channel", [0])
11+
def test_ad7490_rx_data(test_dma_rx, iio_uri, classname, channel):
12+
test_dma_rx(iio_uri, classname, channel)
13+
14+
15+
#########################################
16+
@pytest.mark.iio_hardware(hardware)
17+
@pytest.mark.parametrize("classname", [(classname)])
18+
@pytest.mark.parametrize(
19+
"attr, val",
20+
[
21+
("polarity", ["BIPOLAR", "UNIPOLAR"],),
22+
("range", ["2X_REF_IN", "REF_IN"],),
23+
],
24+
)
25+
def test_ad7490_attr_multiple(
26+
test_attribute_multiple_values, iio_uri, classname, attr, val
27+
):
28+
test_attribute_multiple_values(iio_uri, classname, attr, val, 0)

0 commit comments

Comments
 (0)