Skip to content

Commit

Permalink
Lint/format files and add more methods for N9040a
Browse files Browse the repository at this point in the history
Signed-off-by: Travis Collins <[email protected]>
  • Loading branch information
tfcollins committed May 24, 2024
1 parent c9f8a31 commit 81e6e15
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 22 deletions.
2 changes: 1 addition & 1 deletion bench/keysight/e36233a.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def operational_mode(self) -> str:
PAR: Channel is in parallel mode
"""
self._set_channel()
return str(self.parent._instr.query("OUTP:PAIR?")).replace("\n","")
return str(self.parent._instr.query("OUTP:PAIR?")).replace("\n", "")

@operational_mode.setter
def operational_mode(self, value: str):
Expand Down
85 changes: 73 additions & 12 deletions bench/keysight/n9040b.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging
import time
import os
import time
from typing import Union

import pyvisa

from bench.common import Common


Expand All @@ -14,7 +13,7 @@ class N9040B(Common):
id = "N9040B"
"""Substring returned by IDN query to identify the device"""

_markers = [*range(1,12+1)]
_markers = [*range(1, 12 + 1)]

def peak_search_marker(self, marker=1):
"""Set max peak search for a specific marker"""
Expand All @@ -37,21 +36,83 @@ def reset(self):
def span(self) -> float:
"""Returns the Span in HZ"""
return float(self._instr.query("FREQ:SPAN?"))

@span.setter
def span(self, value: float):
"""Sets the span in Hz"""
self._instr.write("FREQ:SPAN "+str(value))
self._instr.write("FREQ:SPAN " + str(value))

@property
def center_frequency(self) -> float:
"""Returns the current center frequency in Hz"""
return float(self._instr.query("FREQ:CENT?"))

@center_frequency.setter
def center_frequency(self, value: Union[str, float]):
"""Sets the center frequency in Hz"""
self._instr.write("FREQ:CENT "+str(value))
self._instr.write("FREQ:CENT " + str(value))

@property
def peak_table(self):
"""Get peak table status"""
return self._instr.query(":CALC:MARK:TABLe:STAT?")

@peak_table.setter
def peak_table(self, value: int):
"""Sets the peak table status"""
self._instr.write(f":CALC:MARK:PEAK:TABLe:STAT {value}")
self._instr.write(":CALC:MARK:PEAK:SORT FREQ")
self._instr.write(":CALC:MARK:PEAK:TABLe:READ ALL")

def get_peak_table(
self, peak_threshold_dBm: float, excursion_dB: float = 5
) -> dict:
"""Get table of peaks
Args:
peak_threshold_dBm (float) : Minimum threshold for peak
excursion_dB (float) : Minimum variation to be considered a peak
"""
data = self._instr.query(
f":CALCulate:DATA:PEAKs? {peak_threshold_dBm},{excursion_dB}"
)
data = data.split(",")
num_peaks = data[0]
if num_peaks == 0:
return None
data = data[1:]
data = [float(d) for d in data]
peaks = []
for i in range(0, len(data), 2):
peaks.append({"amplitude_dBm": data[i], "frequency_hz": data[i + 1]})
return peaks

def measure_sfdr(
self,
span_hz=None,
center_frequency_hz=None,
max_iterations: int = 4,
level_step_dBm: float = 6,
) -> float:
"""Determine SFDR in dBc
Args:
span_hz (int optional): Set span in Hz
center_frequency_hz (int optional): Set center frequency in Hz
max_iterations (int optional): Maximum number of iterations to get at least 2 peaks
level_step_dBm (float optional): Noise steps to decrease threshold until peak count > 1
"""
if span_hz:
self.span = span_hz
if center_frequency_hz:
self.center_frequency = center_frequency_hz
level = -100 + level_step_dBm
for _ in range(max_iterations):
level = level - level_step_dBm
peaks = self.get_peak_table(level)
if len(peaks) >= 2:
return peaks[0]["amplitude_dBm"] - peaks[1]["amplitude_dBm"]
raise Exception(f"Not enough peaks found. Min level used ({level} dBm)")

def screenshot(self, filename: str = "N9040B_sc.png"):
"""Takes a screenshot on PXA and returns it locally
Expand All @@ -64,8 +125,8 @@ def screenshot(self, filename: str = "N9040B_sc.png"):
if not os.path.isdir(path):
os.mkdir(path)

if '.png' not in filename:
filename = f'{filename}.png'
if ".png" not in filename:
filename = f"{filename}.png"

just_filename = os.path.basename(filename)
self._instr.write(f':MMEM:STOR:SCR "D:\\{just_filename}"')
Expand All @@ -74,8 +135,8 @@ def screenshot(self, filename: str = "N9040B_sc.png"):
self._instr.write(f':MMEM:DATA? "D:\\{just_filename}"')
data = self._instr.read_raw()
# Extract PNG data
start = data.index(b'PNG') - 1
start = data.index(b"PNG") - 1
data = data[start:]
with open(filename, 'wb') as f:
with open(filename, "wb") as f:
f.write(data)
print(f"Wrote file: {filename}")
print(f"Wrote file: {filename}")
2 changes: 1 addition & 1 deletion bench/rs/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .sma100a import SMA100A
from .sma100a import SMA100A
17 changes: 9 additions & 8 deletions bench/rs/sma100a.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pyvisa
from bench.common import Common


class SMA100A(Common):
"""Rohde & Schwarz SMA100A Signal Generator"""

Expand All @@ -15,30 +16,30 @@ def _post_init_(self, address: str = None, use_config_file=False) -> None:
@property
def frequency(self):
"""Get Frequency in Hz"""
return float(self._instr.query('SOUR:FREQ:CW?'))
return float(self._instr.query("SOUR:FREQ:CW?"))

@frequency.setter
def frequency(self, value:float):
def frequency(self, value: float):
"""Set Frequency in Hz"""
self._instr.write(f'FREQ {value}')
self._instr.write(f"FREQ {value}")

@property
def level(self):
"""Get output power level in dBm"""
return float(self._instr.query('SOUR:POW:POW?'))
return float(self._instr.query("SOUR:POW:POW?"))

@level.setter
def level(self, value):
"""Set output power level in dBm"""
self._instr.write(f'POW {value}')
self._instr.write(f"POW {value}")

@property
def output_enable(self):
"""Get output state"""
return bool(self._instr.query('Output1:STATe?'))
return bool(self._instr.query("Output1:STATe?"))

@output_enable.setter
def output_enable(self, value:bool):
def output_enable(self, value: bool):
"""Set output state (True == On, False == Off)"""
value = "1" if value else "0"
self._instr.write(f'Output1:STATe {value}')
self._instr.write(f"Output1:STATe {value}")

0 comments on commit 81e6e15

Please sign in to comment.