some fixes

This commit is contained in:
Ayzen
2026-08-26 15:02:21 +03:00
parent 74723bb635
commit 6ada811c2f
10 changed files with 607 additions and 115 deletions
@@ -83,42 +83,8 @@ class SwitchedMatrixRadarService:
for out_k in range(out_steps):
for in_k in range(in_steps):
step_start_ns = time.monotonic_ns()
if self.output_switch is not None:
self.output_switch.switch_to(out_k)
if self.input_switch is not None:
self.input_switch.switch_to(in_k)
switched_ns = time.monotonic_ns()
# Settle AFTER the last switch change and BEFORE collecting, so the
# cycle we anchor on starts with the RF path already stable.
if self.settling_ms > 0:
time.sleep(self.settling_ms / 1000.0)
settled_ns = time.monotonic_ns()
sub = self.inner.acquire_collection(collection_id)
inner_end_ns = time.monotonic_ns()
logger.debug(
"timing: collection %d step out=%d in=%d | gap_prev_collect_to_switch=%s ms, "
"switch=%.3f ms, settle=%.2f ms, inner_collect=%.2f ms",
collection_id,
out_k,
in_k,
(
f"{(step_start_ns - self._last_inner_end_ns) / 1e6:.2f}"
if self._last_inner_end_ns
else "n/a"
),
(switched_ns - step_start_ns) / 1e6,
(settled_ns - switched_ns) / 1e6,
(inner_end_ns - settled_ns) / 1e6,
)
self._last_inner_end_ns = inner_end_ns
for trace in sub.traces:
input_pos = in_k * self.inner_input_positions + int(trace.combo.input)
output_pos = out_k * self.inner_output_positions + int(trace.combo.output)
slots[output_pos * total_inputs + input_pos] = replace(
trace, combo=ComboKey(input=input_pos, output=output_pos)
)
for trace in self._acquire_step_traces(out_k, in_k, collection_id):
slots[trace.combo.output * total_inputs + trace.combo.input] = trace
if any(trace is None for trace in slots):
missing = sum(1 for trace in slots if trace is None)
@@ -134,6 +100,89 @@ class SwitchedMatrixRadarService:
capture_end_ns=time.monotonic_ns(),
)
def acquire_combo_collection(
self,
*,
input_pos: int,
output_pos: int,
collection_id: int = 1,
) -> SweepCollection:
"""Acquire only the physical switch step that carries one widened combo.
The per-combo capture workflows need a single trace at a time; sweeping
every switch position for that (a full ``acquire_collection``) multiplies
the capture time by the number of physical steps and freezes the caller
for the whole sweep. One widened combo lives entirely inside one
(out_k, in_k) step, so acquiring just that step is sufficient. The result
contains that step's traces with widened combo keys, including the
requested combo.
"""
out_steps = self.output_switch.position_count() if self.output_switch is not None else 1
in_steps = self.input_switch.position_count() if self.input_switch is not None else 1
total_inputs = in_steps * self.inner_input_positions
total_outputs = out_steps * self.inner_output_positions
if not (0 <= int(input_pos) < total_inputs and 0 <= int(output_pos) < total_outputs):
raise ValueError(
f"Widened combo out of range: input={input_pos} (of {total_inputs}), "
f"output={output_pos} (of {total_outputs})"
)
capture_start_ns = time.monotonic_ns()
out_k = int(output_pos) // self.inner_output_positions
in_k = int(input_pos) // self.inner_input_positions
traces = self._acquire_step_traces(out_k, in_k, collection_id)
return SweepCollection(
collection_id=int(collection_id),
monotonic_ns=time.monotonic_ns(),
traces=traces,
capture_start_ns=capture_start_ns,
capture_end_ns=time.monotonic_ns(),
)
def _acquire_step_traces(self, out_k: int, in_k: int, collection_id: int) -> list[TraceData]:
"""Drive both switches to one step, settle, and collect its widened traces."""
step_start_ns = time.monotonic_ns()
if self.output_switch is not None:
self.output_switch.switch_to(out_k)
if self.input_switch is not None:
self.input_switch.switch_to(in_k)
switched_ns = time.monotonic_ns()
# Settle AFTER the last switch change and BEFORE collecting, so the
# cycle we anchor on starts with the RF path already stable.
if self.settling_ms > 0:
time.sleep(self.settling_ms / 1000.0)
settled_ns = time.monotonic_ns()
sub = self.inner.acquire_collection(collection_id)
inner_end_ns = time.monotonic_ns()
logger.debug(
"timing: collection %d step out=%d in=%d | gap_prev_collect_to_switch=%s ms, "
"switch=%.3f ms, settle=%.2f ms, inner_collect=%.2f ms",
collection_id,
out_k,
in_k,
(
f"{(step_start_ns - self._last_inner_end_ns) / 1e6:.2f}"
if self._last_inner_end_ns
else "n/a"
),
(switched_ns - step_start_ns) / 1e6,
(settled_ns - switched_ns) / 1e6,
(inner_end_ns - settled_ns) / 1e6,
)
self._last_inner_end_ns = inner_end_ns
return [
replace(
trace,
combo=ComboKey(
input=in_k * self.inner_input_positions + int(trace.combo.input),
output=out_k * self.inner_output_positions + int(trace.combo.output),
),
)
for trace in sub.traces
]
def build_physical_switch(
model: SwitchModel,
physical_positions: int,