Commit Graph
15 Commits
Author SHA1 Message Date
Jeremy Shen 09be20791f feat: forward UART parsed boot info to main log window
UartMonitorWindow now accepts on_log callback. When boot info
(IP, version) is parsed from serial output, it:
- Appears in the UART window's own log (prefix [UART])
- Forwards to main window's log panel via on_log callback
- Unified [UART] prefix across both windows (was [BOOT] in
  UART window, [UART] Boot detected: in main log)
2026-06-10 15:40:09 +08:00
Jeremy Shen a47e3b78ae fix: avoid serial port conflict between workflow and UART window
Flow execution's _start_uart_monitor() now checks if a UART window
is already monitoring before starting its own UartMonitor instance.
This prevents two UartMonitor threads from fighting over the same
serial port.

Changes:
- UartMonitorWindow: add is_monitoring property
- MainWindow._uart_window: store reference to open UART window
- _start_uart_monitor(): skip if UART window already monitoring
- _on_close(): destroy UART window on main window close
2026-06-10 15:23:28 +08:00
Jeremy Shen 2695180c8f fix: auto-start UART monitoring on port open success
_on_open_success(): directly call _on_start() instead of just
enabling the button. User no longer needs to click Start —
monitoring begins automatically when the port is available.

Start/Stop buttons remain for manual control.
2026-06-10 15:21:12 +08:00
Jeremy Shen 8130578f70 fix: remove grab_set() to allow main window interaction
UART Monitor window was modal (grab_set) preventing main window
from being used while the UART window is open. Remove grab_set
to make it modeless.
2026-06-10 15:04:39 +08:00
Jeremy Shen 778bee5d19 fix: import DARK_CARD + use hasattr for vitis_path
- widgets.py: add DARK_CARD to gui.styles imports
- zynq_checker.py: wrap config.vitis_path with hasattr
- bitstream_programmer.py: wrap config.vitis_path with hasattr
2026-06-10 15:00:15 +08:00
Jeremy Shen b4126a14ac fix: add missing DARK_CARD import in widgets.py 2026-06-10 14:58:48 +08:00
Jeremy Shen 7afc9051ab fix: defer grab_set() to avoid 'window not viewable' error
CTkToplevel grab_set() fails when called before the window is
fully realized on screen. Defer to after(50ms) so the window
has time to become viewable.
2026-06-10 14:53:22 +08:00
Jeremy Shen d5fd816ff9 feat: UART Monitor standalone window
Replace 'Read Serial' button with 'Open UART' that opens a new
UART Monitor window (CTkToplevel) with:

- Title bar with status indicator (● connecting/ready/monitoring/error)
- Port info display + Start/Stop/Clear buttons
- Large scrollable log area (CTkTextbox) with monospace font
- Auto-scroll to bottom, line counter in status bar
- Boot info parsing (IP, version) shown as [BOOT] prefix
- Background serial monitoring via UartMonitor class

UART unavailable handling:
- On init, tries to open serial port in background thread
- If port can't open → shows 'UART 不可用' state with error message
- If port opens → shows 'Ready', user clicks Start to begin monitoring

Window features:
- Modal (grab_set) — focus stays on monitor window
- Clean up UartMonitor on close (WM_DELETE_WINDOW handler)
- Thread-safe UI updates via after(0, ...)
- Reuses existing UartMonitor from serial_monitor.py
2026-06-10 14:51:13 +08:00
Jeremy Shen 699ad82834 🐛 fix: sub-step default expanded, real-time checkbox, startup freeze, color sync
1. SubStepFrame defaults to expanded (▼), not collapsed
2. erase_all checkbox has command=_on_erase_toggle → immediate config update
3. _deferred_init runs _check_vitis/_refresh_ports in background thread
   Fixes UI freeze during startup (subprocess.run for tool versions)
4. Sub-step colors now match StepHeader:
   - pending: gray ACCENT_PENDING (#888888)
   - running: blue CIRCLE_RUNNING (#0078D4) with pulse animation
   - complete: green ACCENT_COMPLETE (#107C10)
   - error: red ACCENT_ERROR (#D13438)
   - Running sub-step pulses between light/dark blue like StepHeader
2026-06-10 14:11:59 +08:00
Jeremy Shen 35bd6e600c Revert sub-step custom colors — use default CTkLabel white text
SubStepFrame now uses default CustomTkinter label colors (white
in dark mode, black in light mode) instead of manually set
CIRCLE_*/ACCENT_* colors that were unreadable on dark backgrounds.
Simplified grid layout — no nested sub-frames.
2026-06-10 13:54:06 +08:00
Jeremy Shen e3e3763dc4 🐛 fix: sub-step readability, erase_all workaround, error state
Fix 1 — SubStepFrame readability:
- FONT_BODY (12pt) instead of FONT_SMALL dots/labels
- Number-circle colored dots (CIRCLE_PENDING/RUNNING/COMPLETE/ERROR)
- Accent-colored labels matching StepHeader (ACCENT_*)
- Percentage label next to running phase name

Fix 2 — erase_all full-chip erase:
- Creates temp zero-filled file of flash capacity (from flash_model)
- Uses -erase_only with dummy file instead of failing -erase_all flag
- Supports s25fl256s1 (32MB) which lacks density info for -erase_all
- _flash_capacity() maps model name→bytes

Fix 3 — Error state:
- set_phase('error') shows ✗ red on all sub-steps
- Only shows 'done' (green ●) on actual success

Fix 4 — Style consistency:
- Sub-step colors match StepHeader: CIRCLE_*/ACCENT_*/SUCCESS/DANGER
2026-06-10 13:51:41 +08:00
Jeremy Shen 95c04d94ae feat: collapsible flash sub-steps UI + erase_all checkbox
Rename erase_before_program → erase_all (semantics fix):
- erase_all: true  → -erase_all -erase_only (entire flash chip)
- erase_all: false → -erase_only (sectors matching BIN size)
Both options always erase; the checkbox controls scope, not yes/no.

UI additions:
- SubStepFrame widget: collapsible Erase/Program/Verify sub-steps
  with status dots (○/◉/●) and colored labels
- Automatically expands on Step 2 start, collapses on completion
- Phase and progress driven by real-time program_flash output parsing
- Checkbox label: '整片Flash擦除 (Erase entire flash)'

subprocess_utils.py phase detection:
- Parses 'Performing Erase/Program/Verify Operation' for phase transitions
- Emits 'phase' callbacks (erase/program/verify/done)
- Progress % tracked within current phase
2026-06-10 13:45:57 +08:00
Jeremy Shen 91a7843dbe 🐛 fix(gui): resolve step header layout overlaps and improve scaling
- Fix 6 overlapping widget bugs in StepHeader (title/desc, btn/icon,
  run/rerun) with proper 5-column grid layout
- Merge run/rerun buttons into single _action_btn with state-driven text
- Fix DARK_CARD NameError (undefined import → STEP_CARD_BG)
- Replace fragile vertical connector lines with full-width dividers
- Add panel.grid_columnconfigure(0, weight=1) for horizontal scaling
- Unify button text across all states (▶ pending/disabled, ↻ retry)
- Tighten padding and reduce whitespace between steps
2026-06-09 17:30:36 +08:00
Jeremy Shen bda64d5f46 ♻️ refactor(gui): improve left panel readability with better fonts, colors, and layout
- Replace Segoe UI with Roboto for cross-platform compatibility
- Increase font sizes for better readability (9→11, 11→12, 14→15)
- Update dark theme to VS Code-like colors (#1E1E1E bg)
- Brighten accent colors and improve contrast ratios
- Fix StepHeader: number circle background, status icon positioning
- Enlarge accent bar (4→5px) and buttons (28→32px)
- Simplify status text (Completed → Done)
- Improve connector line sizing and alignment
2026-06-09 17:12:41 +08:00
Jeremy Shen bd39023ba7 feat: initial Zynq XC7Z100 Flasher GUI project
Add cross-platform GUI application for programming Zynq devices
with step-by-step workflow:

- CustomTkinter GUI with dark/light theme support
- 4-step workflow: Check Env → Flash → Bootloader → Main Program
- YAML configuration with relative path resolution
- Serial monitoring and boot log parsing
- TFTP upload with CRC32 verification
- SSH/serial reboot management
- Vivado/Impact tool auto-detection

Project structure:
- app.py: Entry point
- src/: Core modules (config, flash, bitstream, tftp, serial, gui)
- config/: Default configuration template
- .flasher_env/: Python virtual environment
2026-06-08 11:33:50 +08:00