2026-02-06 09:52:23 +08:00

11 KiB
Raw Permalink Blame History

Ameba Control Panel (PySide)

Goal

Build a PySide-based desktop app titled “Ameba Control Panel”. It serves three Ameba families—AmebaPro3 (RTL8735C), AmebaPro2 (RTL8735B), AmebaSmart (RTL8730E)—each on its own tab. The app must prioritize responsive UART interactions, smooth log rendering, and safe concurrent execution.

Architecture & Design

  • Use an explicit OOP structure: separate UI widgets (views), controllers (signal/slot glue), and services (serial I/O, command history, process runners). No “minimal” scripts—prefer clearly named classes and modules.
  • Tabs: one tab per device class; each tab owns its own controller/service instances (no shared mutable state across tabs).
  • Event loop: base on PySide6 (Qt 6). Encapsulate threading via QThread/QObject workers for serial I/O; use multiprocessing (or concurrent.futures.ProcessPoolExecutor) for heavy parsing or binary tasks to keep the UI thread idle.
  • Allow optional C/C++ extensions (e.g., pybind11) for high-throughput UART parsing; isolate behind a Python service interface so the GUI remains unchanged if the extension is absent.

Per-Tab Requirements

  • Connection controls: COM port dropdown (full system path/name), baudrate dropdown+editable field (populate with common values; default 1500000). Connect/Disconnect toggle shows live status.
  • UART console: fast-rendering log view with timestamps per line; color-differentiate TX vs RX (no text prefixes); must support copy/paste, multi-range selection, and full scrolling (vertical and horizontal). Provide Clear, Save, and Copy actions. Maintain an in-memory ring buffer to avoid UI lag on high traffic. (Current build hides TX lines in the UI log; only RX/INFO show.)
  • Find/search: non-blocking search over buffered logs; case-sensitive toggle plus case-insensitive default; highlight matches; provide Find/Next/Previous/All actions. Perform search in a worker to avoid UI stalls and apply highlights on completion.
  • Command entry: text input + Send button + Enter to send. On send, append to history unless it is a duplicate of the most recent entry (skip duplicates).
  • Command history pane on the left: scrollable (vertical and horizontal), single-click focuses and loads the command into the input bar; double-click sends immediately without duplicating the entry; Delete key removes the selected record. Persist history per device tab under %LocalAppData%/AmebaControlPanel/<device>/history.txt.
  • Background port refresh on change events; only mutate the COM list when a port is added or removed. Maintain a stable, non-reordered dropdown: preserve existing order/selection and insert newcomers deterministically (e.g., append sorted new ports). Log connection state changes in the console. (Port additions are intentionally not logged; removals are.)
  • Command-list loader: file Browseer accepts .txt with one command per line; Load CmdList button streams commands out automatically with a user-configurable per-command delay and per-character delay.

Logging & Performance

  • Timestamp format YYYY-MM-DD HH:MM:SS.mmm. Store both full archive and UI tail (e.g., last 100k lines) for quick redraws.
  • Use a batched append pipeline: gather serial lines in a thread-safe queue; UI thread flushes at short intervals (e.g., 3060 Hz) to keep scrolling smooth.
  • Multi-select copy should concatenate selected ranges with timestamps preserved.

Concurrency Rules

  • Serial read/write happens in dedicated QThread workers; UI never blocks on I/O.
  • Use signals for crossing threads; avoid direct widget access from workers.
  • For CPU-heavy tasks (parsing, file save), delegate to a ProcessPoolExecutor; C/C++ extensions (e.g., pybind11 modules) are encouraged where performance-critical, keeping a Python fallback.
  • Ensure clean teardown: on tab close or app exit, stop workers, flush queues, and close ports gracefully.

Backend Interfaces

  • Serial service API: open(port, baud), close(), write(bytes), signal line_received(str, direction), signal status_changed(state).
  • History service: load(), save(entries), add(entry), delete(entry).
  • Optional C/C++ module: provide drop-in replacements for line framing or log buffering; keep a pure-Python fallback.

Current Implementation Notes (2026-02-05)

  • UART writes default to \r\n (CRLF) line endings to satisfy Ameba monitor commands.
  • Flash action closes the DUT UART, runs flash_amebapro3.py, reconnects, then triggers an auto “Normal mode” step after ~100 ms while keeping the port open.
  • Download mode, Normal mode (manual button), and Device Reset now run without closing/reopening the DUT UART; connection state stays steady.
  • TX log lines are suppressed in the UI; RX/INFO still render with timestamps and colors.
  • Port additions are not logged; port removals are.
  • In frozen/packaged builds, the flash helper runs in-process (inline) using the bundled Python runtime; no external Python is required. Non-frozen/dev builds still shell out to the system interpreter.
  • When packaging, include hidden imports pyDes, colorama; package_exe.py already adds these.

Snapshot for PySide Rewrite (layout + behavior)

  • Tabs: three device tabs, each fully isolated (own controller/services). Keep the per-tab state separation when porting.
  • Layout (per tab):
    • Top rows: DUT COM dropdown + Refresh + Baud + Connect toggle; Control COM dropdown + Baud; Mode buttons (Normal/Download/Reset) aligned right.
    • Flash rows: App path + Browse, Boot path + Browse + Flash.
    • Bottom split: left fixed-width history list (~220 px); right column with Log view, Find row (input + case toggle + find/next/prev/all), Command-list row (file path + Browse + per-cmd delay + per-char delay + Load), Command entry row (input + Send).
  • Styling: light “Fusion” palette; monospaced log font (JetBrains Mono/Consolas fallback), modest padding/margins; log colors—RX green-ish (#1b5e20), TX (currently hidden) blue-ish (#0d47a1), INFO gray (#424242); timestamps YYYY-MM-DD HH:MM:SS.mmm.
  • Logging pipeline: serial worker enqueues lines into SimpleQueue; a Qt timer flushes every ~30 ms, appends to the log view, maintains tail buffer via LogBuffer (max ~10k lines in UI tail, full archive available for save); perf label shows lines/sec and queue depth updated ~1 Hz.
  • Search: uses Qt document find for next/prev; “Find all” scans full log text, highlights matches.
  • History: single-click loads into input; double-click sends immediately; Delete key removes; duplicates skipped on consecutive add; persisted per device under %LocalAppData%/AmebaControlPanel/<device>/history.txt.
  • Command send: Enter or Send button; CRLF appended; TX hidden from UI log.
  • Command list playback: loads .txt (one command/line); per-command delay (ms) and per-char delay; stops if disconnected; appends to history without duplicate of last.
  • Port refresh: 2s timer; stable ordering; auto-reconnect when previously active port returns; logs removals only.
  • Flash/mode/reset: uses Flash/flash_amebapro3.py; in packaged build runs inline (no external python) with stdout/stderr piped to log; flash closes DUT UART, reopens, auto Normal-mode after 300 ms; mode/reset keep UART open.

UI Layout (per tab)

  • Top bar uses three rows: Row 1 houses the COM port dropdown (full path/name), baudrate input, and the right-aligned Normal Mode, Download Mode, Device Reset buttons. Row 2 holds the application filepath bar (editable, shows full path/name) with its Browseer. Row 3 holds the bootloader filepath bar with its Browseer and the Flash button (flashes app + bootloader via UART).
  • Bottom split: left pane is the command history list (fixed ~220px) with delete/load/save; right pane is the console/log area with the log view, a dedicated find bar immediately below the log (case toggle + find/find next/prev/all), then a row for the command-list loader (filepath input + Browseer + delay + Load CmdList) directly above the bottom command input row (text field left, Send button right).
  • Apply a light theme; use consistent spacing/padding; fonts legible and monospaced for log areas.
  • COM port dropdown should show port name plus description; actions use the underlying device path.
  • File Browseers must expose an editable input bar showing the selected file name and full path; the application/bootloader filepath bars, their Browseer buttons, and the Flash button sit on the second row alongside the COM port dropdown and baudrate input.
  • Command list filepath input + file Browseer and its controls live in the bottom section, on the row above command entry; the Browseer still appears to the left of the cmd delay controls.
  • Flash/Mode/Reset actions call Flash/flash_amebapro3.py:
    • Flash: --boot <path> --app <path> -t <DUT COM port> -p <Control Device COM port> -B <baudrate> (baudrate matches DUT COM port, Close the UART before invoking (tool needs exclusive handle) and reconnect afterward if it was previously connected.)
    • Download Mode: --download-mode 1 -t <DUT COM port> -p <Control Device COM port> -B <baud> (baudrate matches DUT COM port)
    • Normal Mode: --download-mode 0 -t <DUT COM port> -p <Control Device COM port> -B <baud> (baudrate matches DUT COM port)
    • Device Reset: --reset -t <DUT COM port> -p <Control Device COM port -B <baud> (baudrate matches DUT COM port)
  • Log text color adapts to theme: white on dark, black on light; RX/TX/INFO colors adjust accordingly.

Layout sketch (not to scale)

Top Row 1: [ DUT COM dropdown | Baudrate | Connect/Disconnect | Refresh]
Top Row 2: [ Control Devices COM dropdown | Baudrate | Connect] ]---- [ Normal Mode ][ Download Mode ][ Device Reset ]
Top Row 3: [ Application filepath input ]---- [ Browse ]
Top Row 4: [ Bootloader filepath input ]----[ Browse | Flash ]

Bottom Left Pane:  Command History list (fixed ~220px width, no wrap, left & right scrollable)
Bottom Right Pane:
  [ Log view ]
  [ Find row: text input ---------------------- case toggle | find | next | prev | all ]
  [ Command-list row: Command File filepath | Browse | Delay | Load ]
  [ Command entry row: text input --------------------------- | Send ]

Testing & Diagnostics

  • Add simple perf counters (lines/sec, queue depth) displayed in status bar or debug overlay to verify “fast enough” logging.

Packaging

  • Target Python 3.11+ with PySide6. Provide requirements.txt and a short README snippet for running.
  • Keep C/C++ extension optional; guard imports and present a clear message if missing.
  • Add a script/ directory containing:
    • auto_run.py: launches the GUI with any needed environment bootstrapping (PYTHONPATH, dll search path, etc.).
    • package_exe.py (or .bat/.sh wrapper) to build a standalone executable (e.g., via PyInstaller) bundling all Python deps, C/C++ extensions, and helper scripts; ensure the packaged env includes needed DLLs and preserves the light theme assets. When bundling, include the entire Flash/ folder (e.g., PyInstaller --add-data "Flash;Flash" on Windows pathsep rules) so flash_amebapro3.py is available inside the frozen bundle.