fix(gui): PR-Q.4 — per-subframe WaveformConfig + 48-bin parser (C-5)

Refactor v7.WaveformConfig from single-PRI to PR-Q's 3-PRI staggered
ladder (SHORT 175 us / MEDIUM 161 us / LONG 167 us) and update the
host-side bulk-frame parser dimension to match the FPGA's 48-bin
Doppler output (RP_NUM_DOPPLER_BINS = 48). The parser was rejecting
every production frame with n_doppler != 32, masking the PR-F widening
end-to-end.

WaveformConfig:
- pri_short_s/pri_medium_s/pri_long_s replace single pri_s
- n_doppler_bins 32 -> 48; new num_subframes=3
- Per-subframe velocity_resolution_{short,medium,long}_mps
- Per-subframe max_velocity_{short,medium,long}_mps
- extended_max_velocity_mps_crt(K=6) for 3-PRI alias-resolution ceiling
- Drop pri_s, velocity_resolution_mps, max_velocity_mps (no aliases)

Other:
- radar_protocol.NUM_DOPPLER_BINS 32 -> 48 (NUM_CELLS auto 16384 -> 24576;
  BULK_FRAME_MAX_SIZE flows from NUM_CELLS, no other edits needed)
- v7/dashboard.py constant + stale "(64x32)" title replaced with f-string
- v7/processing.py 32-bin fallback -> 48
- v7/workers.py: derive doppler_center from frame.shape; LONG-PRI v_res
  used as conservative single-PRI placeholder until PR-Q.5 lands the
  CRT extractor (markers in place at both call sites)
- test_v7.py: TestWaveformConfig rewritten (8 tests, per-subframe + CRT
  extension); TestExtractTargetsFromFrame center 16 -> 24

Local tests:
  TestWaveformConfig            8/8 PASS
  TestExtractTargetsFromFrame   6/6 PASS
  test_GUI_V65_Tk             117/0/2 PASS
This commit is contained in:
Jason
2026-05-02 14:33:43 +05:45
parent 7ed4d5d405
commit 71afa96d68
6 changed files with 162 additions and 63 deletions
+7 -4
View File
@@ -73,9 +73,9 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
# Frame dimensions from FPGA
# Frame dimensions from FPGA (mirrors radar_protocol.NUM_*; PR-F/PR-Q)
NUM_RANGE_BINS = 64
NUM_DOPPLER_BINS = 32
NUM_DOPPLER_BINS = 48
# Force C locale (period as decimal separator) for all QDoubleSpinBox instances.
_C_LOCALE = QLocale(QLocale.Language.C)
@@ -94,7 +94,7 @@ def _make_dspin() -> QDoubleSpinBox:
# =============================================================================
class RangeDopplerCanvas(FigureCanvasQTAgg):
"""Matplotlib canvas showing the 64x32 Range-Doppler map with dark theme."""
"""Matplotlib canvas showing the Range-Doppler map (NUM_RANGE_BINS x NUM_DOPPLER_BINS) with dark theme."""
def __init__(self, _parent=None):
fig = Figure(figsize=(10, 6), facecolor=DARK_BG)
@@ -106,7 +106,10 @@ class RangeDopplerCanvas(FigureCanvasQTAgg):
extent=[0, NUM_DOPPLER_BINS, 0, NUM_RANGE_BINS], origin="lower",
)
self.ax.set_title("Range-Doppler Map (64x32)", color=DARK_FG)
self.ax.set_title(
f"Range-Doppler Map ({NUM_RANGE_BINS}x{NUM_DOPPLER_BINS})",
color=DARK_FG,
)
self.ax.set_xlabel("Doppler Bin", color=DARK_FG)
self.ax.set_ylabel("Range Bin", color=DARK_FG)
self.ax.tick_params(colors=DARK_FG)