100 lines
11 KiB
Markdown
100 lines
11 KiB
Markdown
# 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., 30–60 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.
|