Skip to content

Commit

Permalink
Add FFT Sniffer support for AD9084
Browse files Browse the repository at this point in the history
Signed-off-by: Travis F. Collins <[email protected]>
  • Loading branch information
tfcollins committed May 20, 2024
1 parent 9fc9082 commit fd2289e
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 0 deletions.
6 changes: 6 additions & 0 deletions adi/ad9084.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from adi.rx_tx import rx_tx
from adi.sync_start import sync_start

from .fftsniffer import fftsniffer


def _map_to_dict(paths, ch):
if ch.attrs["label"].value == "buffer_only":
Expand Down Expand Up @@ -88,6 +90,10 @@ def __init__(self, uri=""):
# Devices with buffers
self._rxadc = self._ctx.find_device("axi-ad9084-rx-hpc")
self._txdac = self._ctx.find_device("axi-ad9084-tx-hpc")
self._fftsniffer_a = self._ctx.find_device("ad9088-fft-sniffer-A")
self._fftsniffer_b = self._ctx.find_device("ad9088-fft-sniffer-B")
self.fftsniffer_a = fftsniffer(self._fftsniffer_a)
self.fftsniffer_b = fftsniffer(self._fftsniffer_b)

# Get DDC and DUC mappings
paths = {}
Expand Down
208 changes: 208 additions & 0 deletions adi/fftsniffer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
"""FFT Sniffer Module for AD9084/AD9088"""

from adi.rx_tx import rx, attribute

def reset_buffer(func):
"""Wrapper for set calls to clear the buffer after setting a new value.
"""

def wrapper(*args, **kwargs):
if args[0]._rx:
args[0]._rx.rx_destroy_buffer()
args[0]._rx = None
func(*args, **kwargs)

return wrapper

class fftsniffer_rx(rx):
_rx_channel_names = ["index", "voltage0_i", "voltage0_q", "magn0"]
_skip_channel_order_check = True
def __init__(self):
pass

def _super_init(self, rx_buffer_size=2**16):
super().__init__(rx_buffer_size=rx_buffer_size)

class fftsniffer(attribute):
"""FFT Sniffer Class"""

def __init__(self, fft_sniffer, ctx=None):
self._fft_sniffer = fft_sniffer
self._rx = None

def capture_fft(self):
"""Capture FFT"""
if not self._rx:
self._rx = fftsniffer_rx()
self._rx._rxadc = self._fft_sniffer
self._rx._super_init(rx_buffer_size=self.fft_size)
if self.fft_mode == "Magnitude":
self._rx.rx_enabled_channels = [3]
else:
self._rx.rx_enabled_channels = [1, 2]
if self.fft_mode == "Magnitude":
return self._rx.rx()
data = self._rx.rx()
return data[0] + 1j * data[1]

def get_bins_freq(self):
"""Get Bins Frequency"""
bin_size = self.adc_sampling_rate_Hz / 512
if self.real_mode:
# 0 -> Fs/2
return [bin_size * i for i in range(256)]
# -Fs/2 -> Fs/2
return [bin_size * i for i in range(-256, 256)]


@property
def fft_size(self):
return 256 if self.real_mode else 512

_fft_mode = "Magnitude"
@property
def fft_mode(self):
"""FFT Mode"""
return self._fft_mode

@fft_mode.setter
@reset_buffer
def fft_mode(self, value):
if value in ["Complex", "Magnitude"]:
self._fft_mode = value
else:
raise ValueError("Invalid FFT Mode. Choose 'Complex' or 'Magnitude'")
self._fft_mode = value

@property
def real_mode(self):
"""Real Mode"""
return self._get_iio_debug_attr("real_mode", self._fft_sniffer)

@real_mode.setter
@reset_buffer
def real_mode(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("real_mode", value, self._fft_sniffer)

@property
def sorting_enable(self):
"""Sorting Enable"""
v = self._get_iio_debug_attr("sort_enable", self._fft_sniffer)
return v == "1"

@sorting_enable.setter
@reset_buffer
def sorting_enable(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("sort_enable", value, self._fft_sniffer)

@property
def continuous_mode(self):
"""Continuous Mode"""
return self._get_iio_debug_attr("continuous_mode", self._fft_sniffer)

@continuous_mode.setter
@reset_buffer
def continuous_mode(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("continuous_mode", value, self._fft_sniffer)

@property
def alpha_factor(self):
"""Alpha Factor"""
return self._get_iio_debug_attr("alpha_factor", self._fft_sniffer)

@alpha_factor.setter
@reset_buffer
def alpha_factor(self, value):
self._set_iio_debug_attr_str("alpha_factor", value, self._fft_sniffer)

@property
def adc_sampling_rate_Hz(self):
"""ADC Sampling Rate"""
return self._get_iio_debug_attr("adc_sampling_rate_Hz", self._fft_sniffer)


@property
def dither_enable(self):
"""Dither Enable"""
return self._get_iio_debug_attr("dither_enable", self._fft_sniffer)

@dither_enable.setter
@reset_buffer
def dither_enable(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("dither_enable", value, self._fft_sniffer)

@property
def delay_capture_ms(self):
"""Delay Capture"""
return self._get_iio_debug_attr("delay_capture_ms", self._fft_sniffer)

@delay_capture_ms.setter
@reset_buffer
def delay_capture_ms(self, value):
self._set_iio_debug_attr_str("delay_capture_ms", value, self._fft_sniffer)

@property
def window_enable(self):
"""Window Enable"""
return self._get_iio_debug_attr("window_enable", self._fft_sniffer)

@window_enable.setter
@reset_buffer
def window_enable(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("window_enable", value, self._fft_sniffer)

@property
def bottom_fft_enable(self):
"""Bottom FFT Enable"""
return self._get_iio_debug_attr("bottom_fft_enable", self._fft_sniffer)

@bottom_fft_enable.setter
@reset_buffer
def bottom_fft_enable(self, value):
value = "1" if value else "0"
self._set_iio_debug_attr_str("bottom_fft_enable", value, self._fft_sniffer)

@property
def min_threshold(self):
"""Min Threshold"""
return self._get_iio_debug_attr("min_threshold", self._fft_sniffer)

@min_threshold.setter
@reset_buffer
def min_threshold(self, value):
self._set_iio_debug_attr_str("min_threshold", value, self._fft_sniffer)

@property
def max_threshold(self):
"""Max Threshold"""
return self._get_iio_debug_attr("max_threshold", self._fft_sniffer)

@max_threshold.setter
@reset_buffer
def max_threshold(self, value):
self._set_iio_debug_attr_str("max_threshold", value, self._fft_sniffer)

@property
def fft_enable_select(self):
"""FFT Enable Select"""
return self._get_iio_debug_attr("fft_enable_sel", self._fft_sniffer)

@fft_enable_select.setter
@reset_buffer
def fft_enable_select(self, value):
self._set_iio_debug_attr_str("fft_enable_sel", value, self._fft_sniffer)

@property
def fft_hold_select(self):
"""FFT Hold Select"""
return self._get_iio_debug_attr("fft_hold_sel", self._fft_sniffer)

@fft_hold_select.setter
@reset_buffer
def fft_hold_select(self, value):
self._set_iio_debug_attr_str("fft_hold_sel", value, self._fft_sniffer)

0 comments on commit fd2289e

Please sign in to comment.