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

iio: dac: ltc2664: Device class for LTC2664 4 channel DAC #522

Merged
merged 1 commit into from
Apr 9, 2024
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
iio: dac: ltc2664: Device class for LTC2664 4 channel DAC
The LTC2664 is a family of 4-channel, 12/16-bit +/-10V digital-to-analog
converters with integrated precision references. They are guaranteed
monotonic and have built-in rail-to-rail output buffers.
These SoftSpan DACs offer five output ranges up to +/-10V.
The range of each channel is independently programmable, or the part can
be hardware-configured for operation in a fixed range.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
  • Loading branch information
mhennerich committed Jan 26, 2024
commit f34b02aa27e0506b0098052251dbf4b4839391ae
1 change: 1 addition & 0 deletions adi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
from adi.ltc2314_14 import ltc2314_14
from adi.ltc2387 import ltc2387
from adi.ltc2499 import ltc2499
from adi.ltc2664 import ltc2664
from adi.ltc2688 import ltc2688
from adi.ltc2983 import ltc2983
from adi.max9611 import max9611
Expand Down
166 changes: 166 additions & 0 deletions adi/ltc2664.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Copyright (C) 2024 Analog Devices, Inc.
#
# SPDX short identifier: ADIBSD

from adi.attribute import attribute
from adi.context_manager import context_manager


class ltc2664(context_manager, attribute):
""" LTC2664 DAC """

_complex_data = False
_device_name = "LTC2664"
channel_names = []

def __init__(self, uri="ip:analog.local", device_index=0):
context_manager.__init__(self, uri, self._device_name)

self._ctrl = self._ctx.find_device("ltc2664")

for ch in self._ctrl.channels:
name = ch.id
self.channel_names.append(name)
if "toggle_en" in ch.attrs:
setattr(self, name, self._channel_toggle(self._ctrl, name))
else:
setattr(self, name, self._channel_standard(self._ctrl, name))

class _channel_base(attribute):
""" LTC2664 base channel class """

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

@property
def scale(self):
""" LTC2664 channel gain """
return self._get_iio_attr(self.name, "scale", True, self._ctrl)

@property
def offset(self):
""" LTC2664 channel offset """
return self._get_iio_attr(self.name, "offset", True, self._ctrl)

@property
def volt_available(self):
""" LTC2664 voltage min/max [min, max] in mV """
return [
round((0 + self.offset) * self.scale, 2),
round((65535 + self.offset) * self.scale, 2),
]

@property
def raw_available(self):
""" LTC2664 raw value range [min, increment, max] """
return list(
map(
int,
(self._get_iio_attr(self.name, "raw_available", True, self._ctrl)),
)
)

@property
def powerdown(self):
""" LTC2664 channel powerdown """
return self._get_iio_attr(self.name, "powerdown", True, self._ctrl)

@powerdown.setter
def powerdown(self, val):
""" LTC2664 channel powerdown """
self._set_iio_attr(self.name, "powerdown", True, val, self._ctrl)

class _channel_standard(_channel_base):
def __init__(self, ctrl, channel_name):
super().__init__(ctrl, channel_name)

@property
def raw(self):
""" LTC2664 channel raw value property """
return self._get_iio_attr(self.name, "raw", True, self._ctrl)

@raw.setter
def raw(self, val):
""" LTC2664 channel raw value setter """
raw_span = self._get_iio_attr(self.name, "raw_available", True, self._ctrl)
if val >= raw_span[0] and val <= raw_span[2] and val % raw_span[1] == 0:
self._set_iio_attr(self.name, "raw", True, str(int(val)))

@property
def volt(self):
""" LTC2664 channel volt property (in mV)"""
return (self.raw + self.offset) * self.scale

@volt.setter
def volt(self, val):
""" LTC2664 channel volt setter (in mV)"""
self.raw = int((val / self.scale) - self.offset)

class _channel_toggle(_channel_base):
def __init__(self, ctrl, channel_name):
super().__init__(ctrl, channel_name)

@property
def toggle_en(self):
""" LTC2664 channel toggle enable flag """
return self._get_iio_attr(self.name, "toggle_en", True, self._ctrl)

@toggle_en.setter
def toggle_en(self, val):
""" LTC2664 channel toggle enable flag setter """
self._set_iio_attr(self.name, "toggle_en", True, val)

@property
def toggle_state(self):
""" LTC2664 SW toggle enable flag """
return self._get_iio_attr(self.name, "symbol", True, self._ctrl)

@toggle_state.setter
def toggle_state(self, val):
""" LTC2664 SW toggle enable flag setter """
self._set_iio_attr(self.name, "symbol", True, str(int(val)))

@property
def raw0(self):
""" LTC2664 channel toggle state 0 raw value """
return self._get_iio_attr(self.name, "raw0", True, self._ctrl)

@raw0.setter
def raw0(self, val):
""" LTC2664 channel toggle state 0 raw value setter """
raw_span = self._get_iio_attr(self.name, "raw_available", True, self._ctrl)
if val >= raw_span[0] and val <= raw_span[2] and val % raw_span[1] == 0:
self._set_iio_attr(self.name, "raw0", True, str(int(val)))

@property
def raw1(self):
""" LTC2664 channel toggle state 1 raw value """
return self._get_iio_attr(self.name, "raw1", True, self._ctrl)

@raw1.setter
def raw1(self, val):
""" LTC2664 channel toggle state 1 raw value setter """
raw_span = self._get_iio_attr(self.name, "raw_available", True, self._ctrl)
if val >= raw_span[0] and val <= raw_span[2] and val % raw_span[1] == 0:
self._set_iio_attr(self.name, "raw1", True, str(int(val)))

@property
def volt0(self):
""" LTC2664 channel toggle state 0 voltage value (in mV)"""
return (self.raw0 + self.offset) * self.scale

@volt0.setter
def volt0(self, val):
""" LTC2664 channel toggle state 0 voltage value setter (in mV)"""
self.raw0 = int(((val / self.scale) - self.offset))

@property
def volt1(self):
""" LTC2664 channel toggle state 1 voltage value (in mV)"""
return (self.raw1 + self.offset) * self.scale

@volt1.setter
def volt1(self, val):
""" LTC2664 channel toggle state 1 voltage value setter (in mV)"""
self.raw1 = int(((val / self.scale) - self.offset))
7 changes: 7 additions & 0 deletions doc/source/devices/adi.ltc2664.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ltc2664
==================

.. automodule:: adi.ltc2664
: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 @@ -105,6 +105,7 @@ Supported Devices
adi.ltc2314_14
adi.ltc2387
adi.ltc2499
adi.ltc2664
adi.ltc2688
adi.ltc2983
adi.max11205
Expand Down
40 changes: 40 additions & 0 deletions examples/ltc2664_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright (C) 2023 Analog Devices, Inc.
#
# SPDX short identifier: ADIBSD

import sys
import time

import adi

# Device initialization
try:
myDAC = adi.ltc2664(uri="ip:analog.local")

for ch in myDAC.channel_names:
ch_object = eval("myDAC." + str(ch))
voltage_range = ch_object.volt_available
raw_value_range = ch_object.raw_available
print(
"LTC2644 channel "
+ ch
+ " configured output range "
+ str(voltage_range)
+ " mV: RAW value range "
+ str(raw_value_range)
)

except Exception as e:
print(str(e))
print("Failed to open LTC2664 device")
sys.exit(0)

# sweep entire output range in 100mV steps
voltage_range = myDAC.voltage0.volt_available

for v in range(int(voltage_range[0]), int(voltage_range[1]), 100):
print("setting voltage0 = " + str(v / 1000) + " Volt")
myDAC.voltage0.volt = v
time.sleep(0.05)

myDAC.voltage0.powerdown = 1
1 change: 1 addition & 0 deletions supported_parts.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
- LTC2314-14
- LTC2387-18
- LTC2499
- LTC2664
- LTC2688
- LTC2983
- AD7606
Expand Down
1 change: 1 addition & 0 deletions test/emu/devices/ltc2664.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.44.3.92 Linux analog 6.1.54-v7l+ #3472 SMP Thu Jan 25 16:22:37 CET 2024 armv7l" ><context-attribute name="hw_carrier" value="Raspberry Pi 4 Model B Rev 1.4" /><context-attribute name="dtoverlay" value="rpi-ltc2664,vc4-kms-v3d" /><context-attribute name="hw_model" value="0x0001 on Raspberry Pi 4 Model B Rev 1.4" /><context-attribute name="hw_mezzanine" value="0x0001" /><context-attribute name="hw_name" value="PMD-RPI-INTZ" /><context-attribute name="hw_vendor" value="Analog Devices, Inc." /><context-attribute name="hw_serial" value="13837e96-186d-45af-ac0b-e252c8d49a78" /><context-attribute name="local,kernel" value="6.1.54-v7l+" /><context-attribute name="uri" value="ip:analog.local" /><context-attribute name="ip,ip-addr" value="10.44.3.92" /><device id="hwmon0" name="rpi_volt" ><channel id="in0" type="input" ><attribute name="lcrit_alarm" filename="in0_lcrit_alarm" value="0" /></channel></device><device id="iio:device0" name="ltc2664" ><channel id="voltage2" type="output" ><attribute name="offset" filename="out_voltage2_offset" value="-32768" /><attribute name="powerdown" filename="out_voltage2_powerdown" value="0" /><attribute name="raw" filename="out_voltage2_raw" value="0" /><attribute name="raw_available" filename="out_voltage2_raw_available" value="[0 1 65535]" /><attribute name="scale" filename="out_voltage2_scale" value="0.305175781" /></channel><channel id="voltage0" type="output" ><attribute name="offset" filename="out_voltage0_offset" value="-32768" /><attribute name="powerdown" filename="out_voltage0_powerdown" value="1" /><attribute name="raw" filename="out_voltage0_raw" value="65208" /><attribute name="raw_available" filename="out_voltage0_raw_available" value="[0 1 65535]" /><attribute name="scale" filename="out_voltage0_scale" value="0.305175781" /></channel><channel id="voltage3" type="output" ><attribute name="offset" filename="out_voltage3_offset" value="-32768" /><attribute name="powerdown" filename="out_voltage3_powerdown" value="0" /><attribute name="raw" filename="out_voltage3_raw" value="16000" /><attribute name="raw_available" filename="out_voltage3_raw_available" value="[0 1 65535]" /><attribute name="scale" filename="out_voltage3_scale" value="0.305175781" /></channel><channel id="voltage1" type="output" ><attribute name="offset" filename="out_voltage1_offset" value="-32768" /><attribute name="powerdown" filename="out_voltage1_powerdown" value="0" /><attribute name="raw0" filename="out_voltage1_raw0" value="0" /><attribute name="raw1" filename="out_voltage1_raw1" value="0" /><attribute name="raw_available" filename="out_voltage1_raw_available" value="[0 1 65535]" /><attribute name="scale" filename="out_voltage1_scale" value="0.305175781" /><attribute name="symbol" filename="out_voltage1_symbol" value="0" /><attribute name="toggle_en" filename="out_voltage1_toggle_en" value="0" /></channel><attribute name="waiting_for_supplier" value="0" /><debug-attribute name="direct_reg_access" value="ERROR" /></device></context>
9 changes: 9 additions & 0 deletions test/emu/hardware_map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,15 @@ ltc2387:
- filename: ltc2387.xml
- data_devices:
- iio:device0
ltc2664:
- ltc2664
- pyadi_iio_class_support:
- ltc2664
- emulate:
- filename: ltc2664.xml
- data_devices:
- iio:device0

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

hardware = "ltc2664"
classname = "adi.ltc2664"


#########################################
@pytest.mark.iio_hardware(hardware)
@pytest.mark.parametrize("classname", [(classname)])
@pytest.mark.parametrize(
"attr, start, stop, step, tol, repeats, sub_channel",
[
("raw", 0, 65000, 1000, 1, 3, "voltage0"), # Standard Channel
("raw0", 0, 65000, 1000, 1, 3, "voltage1"), # Toggle Channel
("raw1", 0, 65000, 1000, 1, 3, "voltage1"), # Toggle Channel
("raw", 0, 65000, 1000, 1, 3, "voltage2"), # Standard Channel
("raw", 0, 65000, 1000, 1, 3, "voltage3"), # Standard Channel
],
)
def test_ltc2688_raw_attr(
test_attribute_single_value,
iio_uri,
classname,
attr,
start,
stop,
step,
tol,
repeats,
sub_channel,
):
test_attribute_single_value(
iio_uri, classname, attr, start, stop, step, tol, repeats, sub_channel
)
Loading