diff --git a/adi/__init__.py b/adi/__init__.py index f6c9792b6..3e0c53163 100644 --- a/adi/__init__.py +++ b/adi/__init__.py @@ -105,6 +105,7 @@ from adi.one_bit_adc_dac import one_bit_adc_dac from adi.QuadMxFE_multi import QuadMxFE_multi from adi.tdd import tdd +from adi.tddn import tddn try: from adi.jesd import jesd diff --git a/adi/adf4159.py b/adi/adf4159.py index c60491b38..90cc9cd3c 100644 --- a/adi/adf4159.py +++ b/adi/adf4159.py @@ -105,3 +105,143 @@ def freq_dev_time(self, value): self._set_iio_attr( "altvoltage0", "frequency_deviation_time", True, value, self._ctrl ) + + @property + def phase_value(self): + """Get/Set the PLL frequency deviation time.""" + return self._get_iio_debug_attr("adi,phase", self._ctrl) + + @phase_value.setter + def phase_value(self, value): + """Get/Set the PLL frequency deviation time.""" + self._set_iio_debug_attr_str("adi,phase", str(value), self._ctrl) + + @property + def trig_delay_en(self): + """Get/Set the txdata-trigger-delay-enable.""" + return self._get_iio_debug_attr("adi,txdata-trigger-delay-enable", self._ctrl) + + @trig_delay_en.setter + def trig_delay_en(self, value): + """Get/Set the txdata-trigger-delay-enable.""" + self._set_iio_debug_attr_str( + "adi,txdata-trigger-delay-enable", str(value), self._ctrl + ) + + @property + def sing_ful_tri(self): + """Get/Set Single-full-triangle-enable.""" + return self._get_iio_debug_attr("adi,single-full-triangle-enable", self._ctrl) + + @sing_ful_tri.setter + def sing_ful_tri(self, value): + """Get/Set Single-full-triangle-enable.""" + self._set_iio_debug_attr_str( + "adi,single-full-triangle-enable", str(value), self._ctrl + ) + + @property + def tx_trig_en(self): + """Get/Set tx data trigger enable.""" + return self._get_iio_debug_attr("adi,txdata-trigger-enable", self._ctrl) + + @tx_trig_en.setter + def tx_trig_en(self, value): + """Get/Set tx data trigger enable.""" + self._set_iio_debug_attr_str( + "adi,txdata-trigger-enable", str(value), self._ctrl + ) + + @property + def ramp_delay_en(self): + """Get/Set ramp delay enable.""" + return self._get_iio_debug_attr("adi,ramp-delay-enable", self._ctrl) + + @ramp_delay_en.setter + def ramp_delay_en(self, value): + """Get/Set ramp delay enable.""" + self._set_iio_debug_attr_str("adi,ramp-delay-enable", str(value), self._ctrl) + + @property + def delay_clk(self): + """Get/Set the clk delay enable.""" + return self._get_iio_debug_attr( + "adi,delay-clk-sel-pfd-x-clk1-enable", self._ctrl + ) + + @delay_clk.setter + def delay_clk(self, value): + """Get/Set the clk delay enable.""" + self._set_iio_debug_attr_str( + "adi,delay-clk-sel-pfd-x-clk1-enable", str(value), self._ctrl + ) + + @property + def delay_start_en(self): + """Get/Set the delay start enable.""" + return self._get_iio_debug_attr("adi,delay-start-enable", self._ctrl) + + @delay_start_en.setter + def delay_start_en(self, value): + """Get/Set the delay start enable.""" + self._set_iio_debug_attr_str("adi,delay-start-enable", str(value), self._ctrl) + + @property + def delay_word(self): + """Get/Set the delay word.""" + return self._get_iio_debug_attr("adi,delay-start-word", self._ctrl) + + @delay_word.setter + def delay_word(self, value): + """Get/Set the delay word.""" + self._set_iio_debug_attr_str("adi,delay-start-word", str(value), self._ctrl) + + @property + def clk1_mode(self): + """Get/Set the mode of 1st clk.""" + return self._get_iio_debug_attr("adi,clk-div-mode", self._ctrl) + + @clk1_mode.setter + def clk1_mode(self, value): + """Get/Set the mode of 1st clk.""" + self._set_iio_debug_attr_str("adi,clk-div-mode", str(value), self._ctrl) + + @property + def ramp_en(self): + """Get/Set the ramp enable.""" + return self._get_iio_debug_attr("adi,ramp-enable", self._ctrl) + + @ramp_en.setter + def ramp_en(self, value): + """Get/Set the ramp enable.""" + self._set_iio_debug_attr_str("adi,ramp-enable", str(value), self._ctrl) + + @property + def clk1_div_value(self): + """Get/Set the PLL frequency deviation time.""" + return self._get_iio_debug_attr("adi,clk1-div", self._ctrl) + + @clk1_div_value.setter + def clk1_div_value(self, value): + """Get/Set the PLL frequency deviation time.""" + self._set_iio_debug_attr_str("adi,clk1-div", str(value), self._ctrl) + + @property + def clk2_div_value(self): + """Get/Set the PLL frequency deviation time.""" + return self._get_iio_debug_attr("adi,clk2-timer-div", self._ctrl) + + @clk2_div_value.setter + def clk2_div_value(self, value): + """Get/Set the PLL frequency deviation time.""" + self._set_iio_debug_attr_str("adi,clk2-timer-div", str(value), self._ctrl) + + @property + def muxout_sel(self): + """Get/Set the PLL frequency deviation time.""" + return self._get_iio_debug_attr("adi,muxout-select", self._ctrl) + + @muxout_sel.setter + def muxout_sel(self, value): + """Get/Set the PLL frequency deviation time.""" + self._set_iio_debug_attr_str("adi,muxout-select", str(value), self._ctrl) diff --git a/adi/tddn.py b/adi/tddn.py new file mode 100644 index 000000000..c56842c1e --- /dev/null +++ b/adi/tddn.py @@ -0,0 +1,204 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +from typing import List + +from adi.attribute import attribute +from adi.context_manager import context_manager + + +class tddn(context_manager, attribute): + + """TDDN Controller""" + + channel = [] # type: ignore + _device_name: str = "" + + def __init__(self, uri=""): + """TDDN Controller""" + context_manager.__init__(self, uri, self._device_name) + self._ctrl = self._ctx.find_device("iio-axi-tdd-0") + + for ch in self._ctrl.channels: + name = ch._id + self.channel.append(self._channel(self._ctrl, name)) + + @property + def frame_length_ms(self) -> float: + """frame_length_ms: TDD frame length (ms)""" + return self._get_iio_dev_attr("frame_length_ms") + + @frame_length_ms.setter + def frame_length_ms(self, value: float): + self._set_iio_dev_attr("frame_length_ms", value) + + @property + def frame_length_raw(self) -> float: + """frame_length_raw: TDD frame length (clock cycles)""" + return self._get_iio_dev_attr("frame_length_raw") + + @frame_length_raw.setter + def frame_length_raw(self, value: float): + self._set_iio_dev_attr("frame_length_raw", value) + + @property + def startup_delay_ms(self) -> float: + """startup_delay_ms: Initial delay before the first frame (ms)""" + return self._get_iio_dev_attr("startup_delay_ms") + + @startup_delay_ms.setter + def startup_delay_ms(self, value: float): + self._set_iio_dev_attr("startup_delay_ms", value) + + @property + def startup_delay_raw(self) -> float: + """startup_delay_raw: Initial delay before the first frame (clock cycles)""" + return self._get_iio_dev_attr("startup_delay_raw") + + @startup_delay_raw.setter + def startup_delay_raw(self, value: float): + self._set_iio_dev_attr("startup_delay_raw", value) + + @property + def internal_sync_period_ms(self) -> float: + """internal_sync_period_ms: Period of the internal sync generator (ms)""" + return self._get_iio_dev_attr("internal_sync_period_ms") + + @internal_sync_period_ms.setter + def internal_sync_period_ms(self, value: float): + self._set_iio_dev_attr("internal_sync_period_ms", value) + + @property + def internal_sync_period_raw(self) -> float: + """internal_sync_period_raw: Period of the internal sync generator (clock cycles)""" + return self._get_iio_dev_attr("internal_sync_period_raw") + + @internal_sync_period_raw.setter + def internal_sync_period_raw(self, value: float): + self._set_iio_dev_attr("internal_sync_period_raw", value) + + @property + def burst_count(self) -> int: + """burst_count: Amount of frames to produce, where 0 means repeat indefinitely""" + return self._get_iio_dev_attr("burst_count") + + @burst_count.setter + def burst_count(self, value: int): + self._set_iio_dev_attr("burst_count", value) + + @property + def sync_soft(self) -> bool: + """sync_soft: Trigger one software sync pulse""" + return bool(int(self._get_iio_dev_attr("sync_soft"))) + + @sync_soft.setter + def sync_soft(self, value: bool): + self._set_iio_dev_attr("sync_soft", int(value)) + + @property + def sync_external(self) -> bool: + """sync_external: Enable the external sync trigger""" + return bool(int(self._get_iio_dev_attr("sync_external"))) + + @sync_external.setter + def sync_external(self, value: bool): + self._set_iio_dev_attr("sync_external", int(value)) + + @property + def sync_internal(self) -> bool: + """sync_internal: Enable the internal sync trigger""" + return bool(int(self._get_iio_dev_attr("sync_internal"))) + + @sync_internal.setter + def sync_internal(self, value: bool): + self._set_iio_dev_attr("sync_internal", int(value)) + + @property + def sync_reset(self) -> bool: + """sync_reset: Reset the internal counter when receiving a sync event""" + return bool(int(self._get_iio_dev_attr("sync_reset"))) + + @sync_reset.setter + def sync_reset(self, value: bool): + self._set_iio_dev_attr("sync_reset", int(value)) + + @property + def enable(self) -> bool: + """enable: Enable or disable the TDD engine""" + return bool(int(self._get_iio_dev_attr("enable"))) + + @enable.setter + def enable(self, value: bool): + self._set_iio_dev_attr("enable", int(value)) + + @property + def state(self) -> int: + """state: The current state of the internal FSM""" + return self._get_iio_dev_attr("state") + + @state.setter + def state(self, value: int): + self._set_iio_dev_attr("state", value) + + class _channel(attribute): + + """TDDN channel""" + + def __init__(self, ctrl, channel_name): + self.name = channel_name + self._ctrl = ctrl + + @property + def enable(self) -> bool: + """channel_enable: Selected channel output enable""" + return bool(int(self._get_iio_attr(self.name, "enable", True))) + + @enable.setter + def enable(self, value: bool): + self._set_iio_attr(self.name, "enable", True, int(value)) + + @property + def polarity(self) -> bool: + """channel_polarity: Selected channel output polarity""" + return bool(int(self._get_iio_attr(self.name, "polarity", True))) + + @polarity.setter + def polarity(self, value: bool): + self._set_iio_attr(self.name, "polarity", True, int(value)) + + @property + def on_ms(self) -> float: + """channel_on_ms: The offset from the beginning of a new frame when the selected channel is set (ms)""" + return self._get_iio_attr(self.name, "on_ms", True) + + @on_ms.setter + def on_ms(self, value: float): + self._set_iio_attr(self.name, "on_ms", True, value) + + @property + def on_raw(self) -> float: + """channel_on_raw: The offset from the beginning of a new frame when the selected channel is set (clock cycles)""" + return self._get_iio_attr(self.name, "on_raw", True) + + @on_raw.setter + def on_raw(self, value: float): + self._set_iio_attr(self.name, "on_raw", True, value) + + @property + def off_ms(self) -> float: + """channel_off_ms: The offset from the beginning of a new frame when the selected channel is reset (ms)""" + return self._get_iio_attr(self.name, "off_ms", True) + + @off_ms.setter + def off_ms(self, value: float): + self._set_iio_attr(self.name, "off_ms", True, value) + + @property + def off_raw(self) -> float: + """channel_off_raw: The offset from the beginning of a new frame when the selected channel is reset (clock cycles)""" + return self._get_iio_attr(self.name, "off_raw", True) + + @off_raw.setter + def off_raw(self, value: float): + self._set_iio_attr(self.name, "off_raw", True, value) diff --git a/doc/source/devices/adi.tddn.rst b/doc/source/devices/adi.tddn.rst new file mode 100644 index 000000000..3ad5e6746 --- /dev/null +++ b/doc/source/devices/adi.tddn.rst @@ -0,0 +1,7 @@ +tddn +================= + +.. automodule:: adi.tddn + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/devices/index.rst b/doc/source/devices/index.rst index e2a1c4fad..cf12e8a56 100644 --- a/doc/source/devices/index.rst +++ b/doc/source/devices/index.rst @@ -115,6 +115,7 @@ Supported Devices adi.one_bit_adc_dac adi.tdd + adi.tddn ----- diff --git a/examples/pluto_tddn.py b/examples/pluto_tddn.py new file mode 100644 index 000000000..7b9ea3216 --- /dev/null +++ b/examples/pluto_tddn.py @@ -0,0 +1,27 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD + +import time + +import adi + +sdr = adi.Pluto() + +# Enable phaser logic in pluto +gpio = adi.one_bit_adc_dac("ip:192.168.2.1") +time.sleep(0.5) +gpio.gpio_phaser_enable = True +time.sleep(0.5) + +# Configure TDD properties +tdd = adi.tddn("ip:pluto.local") +tdd.enable = False # make sure the TDD is disabled before changing properties +tdd.frame_length_ms = 4 # each GPIO toggle is spaced 4ms apart +tdd.startup_delay_ms = 0 # do not set a startup delay +tdd.burst_count = 3 # there is a burst of 3 toggles, then off for a long time +tdd.channel[0].on_ms = 0.5 # the first trigger will happen 0.5ms into the buffer +tdd.channel[0].off_ms = 0.6 # each GPIO pulse will be 100us (0.6ms - 0.5ms) +tdd.channel[0].enable = True # enable CH0 output +tdd.sync_external = True # enable external sync trigger +tdd.enable = True # enable TDD engine