Skip to content

Commit

Permalink
ad77681 pyadi-iio support
Browse files Browse the repository at this point in the history
Implemented ad7768-1 pyadi-iio device driver class and example script

Signed-off-by: MPhalke <[email protected]>
  • Loading branch information
mphalke committed Jul 24, 2023
1 parent ff613be commit cca31eb
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 0 deletions.
1 change: 1 addition & 0 deletions adi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from adi.ad7689 import ad7689
from adi.ad7746 import ad7746
from adi.ad7768 import ad7768, ad7768_4
from adi.ad7768_1 import ad7768_1
from adi.ad7799 import ad7799
from adi.ad9081 import ad9081
from adi.ad9081_mc import QuadMxFE, ad9081_mc
Expand Down
166 changes: 166 additions & 0 deletions adi/ad7768_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Copyright (C) 2023 Analog Devices, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# - Neither the name of Analog Devices, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
# - The use of this software may or may not infringe the patent rights
# of one or more patent holders. This license does not release you
# from the requirement that you obtain separate licenses from these
# patent holders to use this software.
# - Use of the software either in source or binary form, must be run
# on or directly connected to an Analog Devices Inc. component.
#
# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED.
#
# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


from decimal import Decimal

import numpy as np
from adi.attribute import attribute
from adi.context_manager import context_manager
from adi.rx_tx import rx


class ad7768_1(rx, context_manager):

""" AD7768-1 ADC """

_complex_data = False
channel = [] # type: ignore
_device_name = ""

def __init__(self, uri="", device_name=""):
"""Constructor for ad7768_1 class."""
context_manager.__init__(self, uri, self._device_name)

compatible_parts = ["ad7768-1"]

self._ctrl = 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}")

# Select the device matching device_name as working device
for device in self._ctx.devices:
if device.name == device_name:
self._ctrl = device
self._rxadc = device
break

if not self._ctrl:
raise Exception("Error in selecting matching device")

if not self._rxadc:
raise Exception("Error in selecting matching device")

for ch in self._ctrl.channels:
name = ch._id
self._rx_channel_names.append(name)
self.channel.append(self._channel(self._ctrl, name))

rx.__init__(self)


@property
def sampling_frequency(self):
"""Get sampling frequency."""
return self._get_iio_dev_attr("sampling_frequency")

@sampling_frequency.setter
def sampling_frequency(self, rate):
"""Set sampling frequency."""
self._set_iio_dev_attr("sampling_frequency", rate)


class _channel(attribute):

""" ad7768-1 channel """

def __init__(self, ctrl, channel_name):
self.name = channel_name
self._ctrl = ctrl

@property
def raw(self):
"""Get channel raw value."""
return self._get_iio_attr(self.name, "raw", False)

@property
def scale(self):
"""Get channel scale."""
return self._get_iio_attr(self.name, "scale", False)

@scale.setter
def scale(self, value):
"""Set channel scale."""
self._set_iio_attr(self.name, "scale", False, Decimal(value).real)

@property
def offset(self):
"""Get channel offset."""
return self._get_iio_attr(self.name, "offset", False)

@offset.setter
def offset(self, value):
"""Set channel offset."""
self._set_iio_attr(self.name, "offset", False, value)

@property
def filter_low_pass_3db_frequency_avail(self):
"""Get available low pass filter 3db frequencies."""
return self._get_iio_attr_str(self.name, "filter_low_pass_3db_frequency_available", False)

@property
def filter_low_pass_3db_frequency(self):
"""Get low pass filter 3db frequency."""
return self._get_iio_attr_str(self.name, "filter_low_pass_3db_frequency", False)

@filter_low_pass_3db_frequency.setter
def filter_low_pass_3db_frequency(self, freq):
"""Set low pass filter 3db frequency."""
if freq in self.filter_low_pass_3db_frequency_avail:
self._set_iio_attr(self.name, "filter_low_pass_3db_frequency", False, freq)
else:
raise ValueError(
"Error: Low pass filter 3db frequency not supported \nUse one of: "
+ str(self.filter_low_pass_3db_frequency_avail)
)

def to_volts(self, index, val):
"""Converts raw value to SI."""
_scale = self.channel[index].scale

ret = None

if isinstance(val, np.int16):
ret = val * _scale

if isinstance(val, np.ndarray):
ret = [x * _scale for x in val]

if ret is None:
raise Exception("Error in converting to actual voltage")

return ret
7 changes: 7 additions & 0 deletions doc/source/devices/adi.ad7768_1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ad7768_1
=================

.. automodule:: adi.ad7768_1
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions doc/source/devices/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Supported Devices
adi.ad7689
adi.ad7746
adi.ad7768
adi.ad7768_1
adi.ad777x
adi.ad7799
adi.ad9081
Expand Down
81 changes: 81 additions & 0 deletions examples/ad7768_1_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright (C) 2023 Analog Devices, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# - Neither the name of Analog Devices, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
# - The use of this software may or may not infringe the patent rights
# of one or more patent holders. This license does not release you
# from the requirement that you obtain separate licenses from these
# patent holders to use this software.
# - Use of the software either in source or binary form, must be run
# on or directly connected to an Analog Devices Inc. component.
#
# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED.
#
# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import sys
from time import sleep

import matplotlib.pyplot as plt
from adi import ad7768_1

# Optionally pass URI as command line argument,
# else use default ip:analog.local
my_uri = sys.argv[1] if len(sys.argv) >= 2 else "ip:analog.local"
print("uri: " + str(my_uri))

my_adc = ad7768_1(uri=my_uri)
my_adc.rx_buffer_size = 1024

# Set Sample Rate. Options are 1ksps to 256ksps, 1k* power of 2.
# Note that sample rate and power mode are not orthogonal - refer
# to datasheet.
my_adc.sampling_frequency = 8000

# Choose output format:
# my_adc.rx_output_type = "raw"
my_adc.rx_output_type = "SI"

# Verify settings:
print("Sampling Frequency: ", my_adc.sampling_frequency)
print("Enabled Channels: ", my_adc.rx_enabled_channels)


plt.clf()
sleep(0.5)
data = my_adc.rx()
for ch in my_adc.rx_enabled_channels:
plt.plot(range(0, len(data[0])), data[ch], label="voltage" + str(ch))
plt.xlabel("Data Point")
if my_adc.rx_output_type == "SI":
plt.ylabel("Millivolts")
else:
plt.ylabel("ADC counts")
plt.legend(
bbox_to_anchor=(0.0, 1.02, 1.0, 0.102),
loc="lower left",
ncol=4,
mode="expand",
borderaxespad=0.0,
)
plt.pause(0.01)

del my_adc
1 change: 1 addition & 0 deletions supported_parts.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
- AD7291
- AD7768
- AD7768-4
- AD7768-1
- AD7770
- AD7771
- AD7779
Expand Down
1 change: 1 addition & 0 deletions test/emu/devices/ad7768_1.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.121.135.62 Linux analog 5.10.0-98759-ga60a72f32cb9 #128 SMP PREEMPT Fri Jun 16 00:19:22 EEST 2023 armv7l" ><context-attribute name="hdl_system_id" value="[ad77681evb] on [zed] git [ecd880d44cdd000691283f2edbd31aa52d6ccc3e] clean [2020-11-10 23:42:11] UTC" /><context-attribute name="hw_model" value="on Xilinx Zynq ZED" /><context-attribute name="hw_carrier" value="Xilinx Zynq ZED" /><context-attribute name="ace,guid" value="1958558906" /><context-attribute name="local,kernel" value="5.10.0-98759-ga60a72f32cb9" /><context-attribute name="uri" value="ip:10.121.135.62" /><context-attribute name="ip,ip-addr" value="10.121.135.62" /><device id="iio:device0" name="xadc" ><channel id="voltage5" name="vccoddr" type="input" ><attribute name="raw" filename="in_voltage5_vccoddr_raw" value="2033" /><attribute name="scale" filename="in_voltage5_vccoddr_scale" value="0.732421875" /></channel><channel id="voltage0" name="vccint" type="input" ><attribute name="raw" filename="in_voltage0_vccint_raw" value="1377" /><attribute name="scale" filename="in_voltage0_vccint_scale" value="0.732421875" /></channel><channel id="voltage4" name="vccpaux" type="input" ><attribute name="raw" filename="in_voltage4_vccpaux_raw" value="2439" /><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="2554" /><attribute name="scale" filename="in_temp0_scale" value="123.040771484" /></channel><channel id="voltage7" name="vrefn" type="input" ><attribute name="raw" filename="in_voltage7_vrefn_raw" value="-11" /><attribute name="scale" filename="in_voltage7_vrefn_scale" value="0.732421875" /></channel><channel id="voltage1" name="vccaux" type="input" ><attribute name="raw" filename="in_voltage1_vccaux_raw" value="2437" /><attribute name="scale" filename="in_voltage1_vccaux_scale" value="0.732421875" /></channel><channel id="voltage2" name="vccbram" type="input" ><attribute name="raw" filename="in_voltage2_vccbram_raw" value="1375" /><attribute name="scale" filename="in_voltage2_vccbram_scale" value="0.732421875" /></channel><channel id="voltage3" name="vccpint" type="input" ><attribute name="raw" filename="in_voltage3_vccpint_raw" value="1370" /><attribute name="scale" filename="in_voltage3_vccpint_scale" value="0.732421875" /></channel><channel id="voltage6" name="vrefp" type="input" ><attribute name="raw" filename="in_voltage6_vrefp_raw" value="1692" /><attribute name="scale" filename="in_voltage6_vrefp_scale" value="0.732421875" /></channel><attribute name="sampling_frequency" value="961538" /></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 @@ -339,6 +339,14 @@ ad7768-4:
- ad7768_4
- emulate:
- filename: ad7768-4.xml
- iio:device0

ad7768_1:
- ad7768-1
- pyadi_iio_class_support:
- ad7768_1
- emulate:
- filename: ad7768_1.xml
- data_devices:
- iio:device0

Expand Down
11 changes: 11 additions & 0 deletions test/test_ad7768_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest

hardware = "ad7768-1"
classname = "adi.ad7768_1"


#########################################
@pytest.mark.iio_hardware(hardware)
@pytest.mark.parametrize("classname", [(classname)])
def test_ad7768_1_rx_data(test_dma_rx, iio_uri, classname, channel):
test_dma_rx(iio_uri, classname, channel)

0 comments on commit cca31eb

Please sign in to comment.