Major refactor of Ameba Control Panel v3.1.0: - Three-column layout: icon sidebar, config+history, log view - Dracula PRO theme with light/dark toggle - DTR/RTS GPIO control (replaces ASCII commands) - Multi-CDC firmware support for AmebaSmart control device - Dynamic DUT tabs with +/- management - NN Model flash image support - Settings dialog (Font, Serial, Flash, Command tabs) - Background port scanning, debounced session store - Adaptive log flush rate, format cache optimization - Smooth sidebar animation, deferred startup - pytest test framework with session/log/settings tests - Thread safety fixes: _alive guards, parented timers, safe baud parsing - Find highlight: needle-only highlighting with focused match color - Partial line buffering for table output - PyInstaller packaging with version stamp and module exclusions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
1.7 KiB
Python
84 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
from pathlib import Path
|
|
from typing import Tuple
|
|
|
|
|
|
class _StrEnumMixin(str, Enum):
|
|
"""Behaves like StrEnum on Python < 3.11."""
|
|
|
|
|
|
class Direction(_StrEnumMixin):
|
|
RX = "rx"
|
|
TX = "tx"
|
|
INFO = "info"
|
|
|
|
|
|
class Mode(_StrEnumMixin):
|
|
NORMAL = "normal"
|
|
DOWNLOAD = "download"
|
|
RESET = "reset"
|
|
|
|
|
|
CHECKBOX_STYLE = (
|
|
"QCheckBox::indicator {"
|
|
" width: 14px; height: 14px; border: 1px solid #666; border-radius: 2px; background: #ffffff;"
|
|
"}"
|
|
"QCheckBox::indicator:checked {"
|
|
" background: #1b5e20; border: 1px solid #1b5e20;"
|
|
"}"
|
|
)
|
|
|
|
APP_NAME = "Ameba Control Panel"
|
|
APP_VERSION = "3.1.0"
|
|
UI_LOG_TAIL_LINES = 100_000
|
|
LOG_FLUSH_INTERVAL_MS = 30
|
|
LOG_ARCHIVE_MAX = 500_000
|
|
LOG_FLUSH_BATCH_LIMIT = 200
|
|
PARTIAL_LINE_HOLD_SEC = 0.3
|
|
PERF_UPDATE_INTERVAL_MS = 1_000
|
|
PORT_REFRESH_INTERVAL_MS = 5_000
|
|
DEFAULT_BAUD = 1_500_000
|
|
COMMON_BAUD_RATES = [
|
|
115_200,
|
|
230_400,
|
|
460_800,
|
|
921_600,
|
|
1_000_000,
|
|
DEFAULT_BAUD,
|
|
2_000_000,
|
|
3_000_000,
|
|
]
|
|
|
|
TIMESTAMP_FMT = "%Y-%m-%d %H:%M:%S.%f"
|
|
|
|
|
|
@dataclass
|
|
class DeviceProfile:
|
|
key: str
|
|
label: str
|
|
rx_color: str = "#1a8a3d"
|
|
tx_color: str = "#2944a8"
|
|
info_color: str = "#7970a9"
|
|
|
|
|
|
DEFAULT_PROFILE = DeviceProfile("dut_1", "DUT 1")
|
|
|
|
|
|
def parse_baud(text: str) -> int:
|
|
try:
|
|
return int(text)
|
|
except (ValueError, TypeError):
|
|
return DEFAULT_BAUD
|
|
|
|
|
|
def app_data_dir() -> Path:
|
|
base = os.environ.get("LOCALAPPDATA")
|
|
if base:
|
|
return Path(base) / "AmebaControlPanel"
|
|
# Fallback for non-Windows dev environments.
|
|
return Path.home() / ".local" / "share" / "AmebaControlPanel"
|