first attempt at radioradar

This commit is contained in:
Ayzen
2026-05-06 18:15:50 +03:00
parent cf3f3cbd67
commit bde86813e5
28 changed files with 3224 additions and 30 deletions
+110
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
from dataclasses import dataclass, field
import hashlib
import json
from pathlib import Path
from typing import Any
@@ -37,6 +38,61 @@ class RadarMultiDeviceModel:
recovery_attempts: int = 3
@dataclass(slots=True)
class KamilAdcModel:
"""External Kamil ADC acquisition process settings."""
project_dir: str = ""
executable_path: str = ""
tty_path: str = ""
args: list[str] = field(default_factory=list)
env: dict[str, str] = field(default_factory=dict)
startup_timeout_s: float = 5.0
sweep_timeout_s: float = 5.0
stop_timeout_s: float = 2.0
@dataclass(slots=True)
class LaserManualModeModel:
"""Manual laser-control setpoints."""
temp1: float = 25.0
temp2: float = 25.0
current1: float = 30.0
current2: float = 30.0
@dataclass(slots=True)
class LaserVariationModeModel:
"""Laser-control variation task parameters."""
variation_type: str = "CHANGE_CURRENT_LD1"
static_temp1: float = 25.0
static_temp2: float = 25.0
static_current1: float = 30.0
static_current2: float = 30.0
min_value: float = 30.0
max_value: float = 35.0
step: float = 0.1
time_step: int = 20
delay_time: int = 3
@dataclass(slots=True)
class LaserControlModel:
"""Laser-control board settings applied before Kamil ADC acquisition."""
enabled: bool = False
port: str = ""
mode: str = "manual"
pi_coeff1_p: int = 2560
pi_coeff1_i: int = 128
pi_coeff2_p: int = 2560
pi_coeff2_i: int = 128
manual: LaserManualModeModel = field(default_factory=LaserManualModeModel)
variation: LaserVariationModeModel = field(default_factory=LaserVariationModeModel)
@dataclass(slots=True)
class RadarModel:
"""Radar section of run configuration."""
@@ -49,6 +105,8 @@ class RadarModel:
mock_signal_hz: float = 1_000_000.0
sweep: RadarSweepModel = field(default_factory=RadarSweepModel)
multi_device: RadarMultiDeviceModel = field(default_factory=RadarMultiDeviceModel)
kamil_adc: KamilAdcModel = field(default_factory=KamilAdcModel)
laser_control: LaserControlModel = field(default_factory=LaserControlModel)
@dataclass(slots=True)
@@ -204,6 +262,7 @@ class RunConfigModel:
LIBREVNA_MODEL = "librevna"
LIBREVNA_MULTI_MODEL = "librevna_multi"
COMPACT_M_K209_MODEL = "compact_m_k209"
KAMIL_ADC_MODEL = "kamil_adc"
MULTI_DEVICE_INPUT_POSITIONS = 4
MULTI_DEVICE_OUTPUT_POSITIONS = 2
@@ -229,6 +288,57 @@ class RunConfigModel:
"""Return whether this config targets synchronized multi-device acquisition."""
return self.radar.model == self.LIBREVNA_MULTI_MODEL
@property
def is_kamil_adc(self) -> bool:
"""Return whether this config targets the external Kamil ADC acquisition path."""
return self.radar.model == self.KAMIL_ADC_MODEL
def radar_key_extra_parts(self) -> list[str]:
"""Return model-specific identity parts that affect captured data."""
if self.is_multi_device:
return list(self.radar.multi_device.slave_serials)
if self.is_kamil_adc:
payload = {
"kamil_adc": {
"project_dir": self.radar.kamil_adc.project_dir,
"executable_path": self.radar.kamil_adc.executable_path,
"tty_path": self.radar.kamil_adc.tty_path,
"args": list(self.radar.kamil_adc.args),
"env": dict(sorted(self.radar.kamil_adc.env.items())),
},
"laser_control": {
"enabled": self.radar.laser_control.enabled,
"port": self.radar.laser_control.port,
"mode": self.radar.laser_control.mode,
"pi_coeff1_p": self.radar.laser_control.pi_coeff1_p,
"pi_coeff1_i": self.radar.laser_control.pi_coeff1_i,
"pi_coeff2_p": self.radar.laser_control.pi_coeff2_p,
"pi_coeff2_i": self.radar.laser_control.pi_coeff2_i,
"manual": {
"temp1": self.radar.laser_control.manual.temp1,
"temp2": self.radar.laser_control.manual.temp2,
"current1": self.radar.laser_control.manual.current1,
"current2": self.radar.laser_control.manual.current2,
},
"variation": {
"variation_type": self.radar.laser_control.variation.variation_type,
"static_temp1": self.radar.laser_control.variation.static_temp1,
"static_temp2": self.radar.laser_control.variation.static_temp2,
"static_current1": self.radar.laser_control.variation.static_current1,
"static_current2": self.radar.laser_control.variation.static_current2,
"min_value": self.radar.laser_control.variation.min_value,
"max_value": self.radar.laser_control.variation.max_value,
"step": self.radar.laser_control.variation.step,
"time_step": self.radar.laser_control.variation.time_step,
"delay_time": self.radar.laser_control.variation.delay_time,
},
},
}
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256(encoded.encode("utf-8")).hexdigest()[:16]
return [f"kamil_{digest}"]
return []
def apply_device_model_constraints(self) -> None:
"""Apply only required wire-format constraints for the selected device model."""
if not self.is_multi_device: