|
|
@@ -16,10 +16,27 @@ from PySide6.QtGui import QFont, QColor
|
|
|
from PySide6.QtWidgets import (
|
|
|
QApplication, QWidget, QSplitter, QVBoxLayout, QHBoxLayout,
|
|
|
QGroupBox, QFormLayout, QLabel, QListWidget, QListWidgetItem,
|
|
|
- QFrame, QPushButton, QProgressBar,
|
|
|
+ QFrame, QPushButton, QProgressBar, QComboBox,
|
|
|
QMessageBox, QScrollArea, QSizePolicy, QFileDialog,
|
|
|
)
|
|
|
|
|
|
+# ADC dynamic-range codes → (code, label shown in UI)
|
|
|
+_ADC_RANGES: list[tuple[int, str]] = [
|
|
|
+ (0, "10 мВ"),
|
|
|
+ (1, "20 мВ"),
|
|
|
+ (2, "50 мВ"),
|
|
|
+ (3, "100 мВ"),
|
|
|
+ (4, "200 мВ"),
|
|
|
+ (5, "500 мВ"),
|
|
|
+ (6, "1 В"),
|
|
|
+ (7, "2 В"),
|
|
|
+ (8, "5 В"),
|
|
|
+ (9, "10 В"),
|
|
|
+ (10, "20 В"),
|
|
|
+ (11, "50 В"),
|
|
|
+]
|
|
|
+_ADC_RANGE_DEFAULT_CODE = 2 # 50 мВ
|
|
|
+
|
|
|
from src.gui.tr_widgets import TrGroupBox, TrPushButton
|
|
|
from src.gui.adapters import (
|
|
|
build_block_rows, seq_metadata, validate_timing, find_block_at_time,
|
|
|
@@ -192,6 +209,28 @@ class SeqInterpTab(QWidget):
|
|
|
|
|
|
lay.addStretch()
|
|
|
|
|
|
+ # -- ADC dynamic range selector ----------------------------------------
|
|
|
+ lay.addWidget(sep())
|
|
|
+ _range_lbl = QLabel("АЦП диап.:")
|
|
|
+ _range_lbl.setToolTip("Динамический диапазон АЦП (channel_ranges в iadc)")
|
|
|
+ lay.addWidget(_range_lbl)
|
|
|
+
|
|
|
+ self._adc_range_combo = QComboBox()
|
|
|
+ self._adc_range_combo.setToolTip(
|
|
|
+ "Динамический диапазон АЦП.\n"
|
|
|
+ "Значение записывается в iadc.channel_ranges для всех каналов."
|
|
|
+ )
|
|
|
+ for code, label in _ADC_RANGES:
|
|
|
+ self._adc_range_combo.addItem(label, userData=code)
|
|
|
+ # set default
|
|
|
+ default_idx = next(
|
|
|
+ (i for i, (c, _) in enumerate(_ADC_RANGES) if c == _ADC_RANGE_DEFAULT_CODE),
|
|
|
+ 0,
|
|
|
+ )
|
|
|
+ self._adc_range_combo.setCurrentIndex(default_idx)
|
|
|
+ self._adc_range_combo.currentIndexChanged.connect(self._on_adc_range_changed)
|
|
|
+ lay.addWidget(self._adc_range_combo)
|
|
|
+
|
|
|
self._progress = QProgressBar()
|
|
|
self._progress.setRange(0, 0)
|
|
|
self._progress.setFixedWidth(120)
|
|
|
@@ -489,8 +528,11 @@ class SeqInterpTab(QWidget):
|
|
|
try:
|
|
|
post_info = result.get("post_json", {})
|
|
|
self._post_info = post_info.get("info", post_info)
|
|
|
+ self._sync_combo_from_post_info() # reflect hw_config range in combo
|
|
|
+ self._patch_adc_range(self._post_info) # then apply current selection
|
|
|
xml_text = result.get("xml_text", "")
|
|
|
- post_text = __import__("json").dumps(post_info, indent=2, default=str)
|
|
|
+ import json as _json
|
|
|
+ post_text = _json.dumps({"info": self._post_info}, indent=2, default=str)
|
|
|
self._preview.set_xml_text(xml_text)
|
|
|
self._preview.set_post_json_text(post_text)
|
|
|
|
|
|
@@ -542,6 +584,8 @@ class SeqInterpTab(QWidget):
|
|
|
import json as _json
|
|
|
payload = _json.loads(post_text)
|
|
|
self._post_info = payload.get("info", payload)
|
|
|
+ self._sync_combo_from_post_info()
|
|
|
+ self._patch_adc_range(self._post_info)
|
|
|
except Exception:
|
|
|
self._post_info = None
|
|
|
if self._post_info:
|
|
|
@@ -551,8 +595,52 @@ class SeqInterpTab(QWidget):
|
|
|
self, "Export complete", f"Artifacts written to:\n{output_dir}"
|
|
|
)
|
|
|
|
|
|
+ # -- ADC range helpers -------------------------------------------------
|
|
|
+
|
|
|
+ def _selected_adc_code(self) -> int:
|
|
|
+ """Return the currently selected ADC range code (0–11)."""
|
|
|
+ return self._adc_range_combo.currentData()
|
|
|
+
|
|
|
+ def _patch_adc_range(self, info: dict) -> None:
|
|
|
+ """
|
|
|
+ Overwrite channel_ranges in info['iadc'] with the selected code
|
|
|
+ for every channel. Operates in-place.
|
|
|
+ """
|
|
|
+ iadc = info.get("iadc")
|
|
|
+ if not isinstance(iadc, dict):
|
|
|
+ return
|
|
|
+ code = self._selected_adc_code()
|
|
|
+ n = len(iadc.get("channel_ranges", [])) or 1
|
|
|
+ iadc["channel_ranges"] = [code] * n
|
|
|
+
|
|
|
+ def _sync_combo_from_post_info(self) -> None:
|
|
|
+ """
|
|
|
+ After loading post_info, update the combo to reflect the first
|
|
|
+ channel_ranges value (if it corresponds to a known code).
|
|
|
+ """
|
|
|
+ if not self._post_info:
|
|
|
+ return
|
|
|
+ iadc = self._post_info.get("iadc", {})
|
|
|
+ ranges = iadc.get("channel_ranges", [])
|
|
|
+ if ranges:
|
|
|
+ code = ranges[0]
|
|
|
+ idx = next(
|
|
|
+ (i for i, (c, _) in enumerate(_ADC_RANGES) if c == code),
|
|
|
+ None,
|
|
|
+ )
|
|
|
+ if idx is not None:
|
|
|
+ self._adc_range_combo.blockSignals(True)
|
|
|
+ self._adc_range_combo.setCurrentIndex(idx)
|
|
|
+ self._adc_range_combo.blockSignals(False)
|
|
|
+
|
|
|
+ def _on_adc_range_changed(self) -> None:
|
|
|
+ """Live-patch _post_info when the user changes the range selector."""
|
|
|
+ if self._post_info:
|
|
|
+ self._patch_adc_range(self._post_info)
|
|
|
+
|
|
|
def _send_to_scanner(self) -> None:
|
|
|
if self._post_info:
|
|
|
+ self._patch_adc_range(self._post_info) # ensure latest selection applied
|
|
|
self.ready_for_scan.emit(self._post_info)
|
|
|
|
|
|
def _on_worker_error(self, msg: str) -> None:
|