Bug #1 — Range calibration for Raw IQ Replay: - Add WaveformConfig dataclass (models.py) with FMCW waveform params (fs, BW, T_chirp, fc) and methods to compute range/velocity resolution - Add waveform parameter spinboxes to playback controls (dashboard.py) - Auto-parse waveform params from ADI phaser filename convention - Create replay-specific RadarSettings with correct calibration instead of using FPGA defaults (781.25 m/bin → 0.334 m/bin for ADI phaser) - Add 4 unit tests validating WaveformConfig math Bug #2 — Demo + radar mutual exclusion: - _start_demo() now refuses if radar is running (_running=True) - _start_radar() stops demo first if _demo_mode is active - Demo buttons disabled while radar/replay is running, re-enabled on stop Bug #3 — Refactor adi_agc_analysis.py: - Remove 60+ lines of duplicated AGC functions (signed_to_encoding, encoding_to_signed, clamp_gain, apply_gain_shift) - Import from v7.agc_sim canonical implementation - Rewrite simulate_agc() to use process_agc_frame() in a loop - Rewrite process_frame_rd() to use quantize_iq() from agc_sim
92 lines
2.5 KiB
Python
92 lines
2.5 KiB
Python
"""
|
|
v7 — PLFM Radar GUI V7 (PyQt6 edition).
|
|
|
|
Re-exports all public classes and functions from sub-modules for convenient
|
|
top-level imports:
|
|
|
|
from v7 import RadarDashboard, RadarTarget, RadarSettings, ...
|
|
"""
|
|
|
|
# Models / constants
|
|
from .models import (
|
|
RadarTarget,
|
|
RadarSettings,
|
|
WaveformConfig,
|
|
GPSData,
|
|
ProcessingConfig,
|
|
TileServer,
|
|
DARK_BG, DARK_FG, DARK_ACCENT, DARK_HIGHLIGHT, DARK_BORDER,
|
|
DARK_TEXT, DARK_BUTTON, DARK_BUTTON_HOVER,
|
|
DARK_TREEVIEW, DARK_TREEVIEW_ALT,
|
|
DARK_SUCCESS, DARK_WARNING, DARK_ERROR, DARK_INFO,
|
|
USB_AVAILABLE, FTDI_AVAILABLE, SCIPY_AVAILABLE,
|
|
SKLEARN_AVAILABLE, FILTERPY_AVAILABLE,
|
|
)
|
|
|
|
# Hardware interfaces — production protocol via radar_protocol.py
|
|
from .hardware import (
|
|
FT2232HConnection,
|
|
ReplayConnection,
|
|
RadarProtocol,
|
|
Opcode,
|
|
RadarAcquisition,
|
|
RadarFrame,
|
|
StatusResponse,
|
|
DataRecorder,
|
|
STM32USBInterface,
|
|
)
|
|
|
|
# Processing pipeline
|
|
from .processing import (
|
|
RadarProcessor,
|
|
USBPacketParser,
|
|
apply_pitch_correction,
|
|
)
|
|
|
|
# Workers, map widget, and dashboard require PyQt6 — import lazily so that
|
|
# tests/CI environments without PyQt6 can still access models/hardware/processing.
|
|
try:
|
|
from .workers import (
|
|
RadarDataWorker,
|
|
GPSDataWorker,
|
|
TargetSimulator,
|
|
polar_to_geographic,
|
|
)
|
|
|
|
from .map_widget import (
|
|
MapBridge,
|
|
RadarMapWidget,
|
|
)
|
|
|
|
from .dashboard import (
|
|
RadarDashboard,
|
|
RangeDopplerCanvas,
|
|
)
|
|
except ImportError: # PyQt6 not installed (e.g. CI headless runner)
|
|
pass
|
|
|
|
__all__ = [ # noqa: RUF022
|
|
# models
|
|
"RadarTarget", "RadarSettings", "WaveformConfig", "GPSData", "ProcessingConfig", "TileServer",
|
|
"DARK_BG", "DARK_FG", "DARK_ACCENT", "DARK_HIGHLIGHT", "DARK_BORDER",
|
|
"DARK_TEXT", "DARK_BUTTON", "DARK_BUTTON_HOVER",
|
|
"DARK_TREEVIEW", "DARK_TREEVIEW_ALT",
|
|
"DARK_SUCCESS", "DARK_WARNING", "DARK_ERROR", "DARK_INFO",
|
|
"USB_AVAILABLE", "FTDI_AVAILABLE", "SCIPY_AVAILABLE",
|
|
"SKLEARN_AVAILABLE", "FILTERPY_AVAILABLE",
|
|
# hardware — production FPGA protocol
|
|
"FT2232HConnection", "ReplayConnection", "RadarProtocol", "Opcode",
|
|
"RadarAcquisition", "RadarFrame", "StatusResponse", "DataRecorder",
|
|
"STM32USBInterface",
|
|
# processing
|
|
"RadarProcessor", "USBPacketParser",
|
|
"apply_pitch_correction",
|
|
# workers
|
|
"RadarDataWorker", "GPSDataWorker", "TargetSimulator",
|
|
"polar_to_geographic",
|
|
# map
|
|
"MapBridge", "RadarMapWidget",
|
|
# dashboard
|
|
"RadarDashboard", "RangeDopplerCanvas",
|
|
]
|