added timing
This commit is contained in:
@@ -60,8 +60,6 @@ class Sn9000Service:
|
||||
if self.timeout_ms <= 0:
|
||||
raise ValueError("SN9000 timeout_ms must be > 0")
|
||||
self.visa_library = str(self.visa_library).strip() or "@ivi"
|
||||
if self.visa_library == "@py" or self.visa_library.endswith("@py"):
|
||||
raise ValueError("SN9000 requires an IVI/Vendor VISA backend, not pyvisa-py")
|
||||
|
||||
@property
|
||||
def resource(self) -> str:
|
||||
@@ -146,6 +144,10 @@ class Sn9000Service:
|
||||
return {
|
||||
"min_frequency_hz": float(instrument.query("SERV:SWE:FREQ:MIN?")),
|
||||
"max_frequency_hz": float(instrument.query("SERV:SWE:FREQ:MAX?")),
|
||||
# SN9000 SCPI does not expose IFBW capability queries; use the
|
||||
# documented hardware sequence (1 Hz .. 300 kHz, manual p. 58, 1261).
|
||||
"min_ifbw_hz": 1.0,
|
||||
"max_ifbw_hz": 300_000.0,
|
||||
"max_points": int(float(instrument.query("SERV:SWE:POIN?"))),
|
||||
"min_power_dbm": float(instrument.query("SERV:SWE:POW:MIN?")),
|
||||
"max_power_dbm": float(instrument.query("SERV:SWE:POW:MAX?")),
|
||||
@@ -208,18 +210,37 @@ class Sn9000Service:
|
||||
|
||||
def _query_sweep_s_parameters(self, points: int) -> dict[str, np.ndarray]:
|
||||
instrument = self._require_instrument()
|
||||
if self._uses_pyvisa_py_backend():
|
||||
# pyvisa-py HiSLIP loses synchronization when a single packet aggregates
|
||||
# *OPC? plus multiple binary blocks, so issue trigger and data queries
|
||||
# one at a time. The corrected-data buffer holds the last completed
|
||||
# sweep, so reading each S-parameter sequentially is safe.
|
||||
instrument.write("TRIG:SING")
|
||||
self._expect_opc("*OPC?", context="SN9000 sweep")
|
||||
complex_values: dict[str, np.ndarray] = {}
|
||||
for parameter_name in _S_PARAMETER_QUERY_ORDER:
|
||||
instrument.write(f"SENS:DATA:CORR? {parameter_name}")
|
||||
interleaved = self._read_float32_block(
|
||||
f"SENS:DATA:CORR? {parameter_name}", points * 2
|
||||
)
|
||||
complex_values[parameter_name] = self._complex_from_interleaved(interleaved)
|
||||
return complex_values
|
||||
|
||||
data_queries = ";".join(f":SENS:DATA:CORR? {name}" for name in _S_PARAMETER_QUERY_ORDER)
|
||||
instrument.write(f"TRIG:SING;*OPC?;{data_queries}")
|
||||
opc_token = self._read_ascii_token()
|
||||
if opc_token != "1":
|
||||
raise RuntimeError(f"SN9000 sweep returned unexpected *OPC? response: {opc_token!r}")
|
||||
|
||||
complex_values: dict[str, np.ndarray] = {}
|
||||
complex_values = {}
|
||||
for parameter_name in _S_PARAMETER_QUERY_ORDER:
|
||||
interleaved = self._read_float32_block(f"SENS:DATA:CORR? {parameter_name}", points * 2)
|
||||
complex_values[parameter_name] = self._complex_from_interleaved(interleaved)
|
||||
return complex_values
|
||||
|
||||
def _uses_pyvisa_py_backend(self) -> bool:
|
||||
return self.visa_library == "@py" or self.visa_library.endswith("@py")
|
||||
|
||||
def _assemble_traces(self, s_parameters: dict[str, np.ndarray]) -> list[TraceData]:
|
||||
frequency_hz = self._require_frequency_axis()
|
||||
traces: list[TraceData] = []
|
||||
@@ -286,8 +307,26 @@ class Sn9000Service:
|
||||
f"SN9000 response for {context!r} returned {array.size} float32 values, "
|
||||
f"expected {expected_values}"
|
||||
)
|
||||
self._drain_trailing_terminators()
|
||||
return array
|
||||
|
||||
def _drain_trailing_terminators(self) -> None:
|
||||
"""Consume the SCPI terminator that follows IEEE binary blocks.
|
||||
|
||||
SCPI responses end with `\\n`, which over HiSLIP closes the DataEnd
|
||||
message group. pyvisa-py's HiSLIP layer needs the terminator drained
|
||||
before the next request, otherwise it loses message-frame
|
||||
synchronization on subsequent reads.
|
||||
"""
|
||||
instrument = self._require_instrument()
|
||||
deadline = time.monotonic() + 0.2
|
||||
while time.monotonic() < deadline:
|
||||
try:
|
||||
instrument.read_bytes(1, break_on_termchar=True)
|
||||
return
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def _read_response_bytes(self, count: int) -> bytes:
|
||||
instrument = self._require_instrument()
|
||||
data = instrument.read_bytes(count, break_on_termchar=False)
|
||||
|
||||
Reference in New Issue
Block a user