TUI Design & Hot-Swapping
Relevant source files
The following files were used as context for generating this wiki page:
ComChan features a sophisticated Terminal User Interface (TUI) designed for high-performance serial monitoring and data visualization. The system is built upon ratatui and crossterm, providing a responsive environment that supports real-time telemetry, dual-pane monitoring, and interactive 3D rendering. The architecture enables "Instant Mode Hot-Swapping," allowing users to toggle between raw data monitoring and graphical plotting without losing the underlying serial connection.
The TUI design focuses on modularity, separating the terminal management, input handling, and specific view logic (Monitor, Plotter, or Dual-Port). This allows for specialized features like side-by-side serial viewing for debugging bridges and hardware-accelerated 3D spatial telemetry for IMU data.
Sources: README.md:144-150, src/plotter.rs:356-365, src/monitor.rs:567-576
Architecture & State Management
The TUI is managed through distinct state structures for each mode, ensuring that layout calculations, sensor data, and scroll positions are preserved during the rendering loop. Communication between the asynchronous serial reading threads and the synchronous UI rendering thread is achieved via message passing.
Mode State Containers
Each mode maintains its own internal state to handle specific UI requirements:
| Component | State Structure | Key Responsibilities |
|---|---|---|
| Standard Monitor | MonitorCommand | Handles repaints, mode switches, and quit signals via mpsc channels. |
| Plotter | PlotterState | Manages SensorData hash maps, X/Y bounds, 3D model interpolation, and active tab states. |
| Dual Monitor | DualMonitorState | Tracks logs for two independent ports, independent scroll positions, and active pane focus. |
Sources: src/monitor.rs:25-29, src/plotter.rs:77-111, src/dual_ports.rs:43-55
The Hot-Swapping Flow
Hot-swapping is implemented by returning an AppExitState enum from the current mode's run loop. This enum passes ownership of the active serial port or Bluetooth handle back to the main coordinator, which then initializes the alternative mode using the existing connection.
The diagram shows how the system transitions between modes by passing resource ownership, preventing connection resets.
Sources: src/monitor.rs:567-576, src/plotter.rs:356-365
View Implementations
Serial Plotter & 3D Telemetry
The Plotter view utilizes a tabbed interface (ActiveTab) to switch between a 2D line chart and a 3D wireframe dashboard. The 3D view supports both a CPU-rendered Braille engine and a hardware-accelerated "Ratty" engine for .obj files.
- 2D Chart: Uses
ratatui::widgets::Chartto visualize real-time sensor streams with auto-scaling axes. - 3D Gnomon: A stationary X/Y/Z axis triad is rendered in the bottom-right corner to provide spatial context.
- Interpolation: Euler angles (Pitch, Yaw, Roll) are smoothed using Linear Interpolation (Lerp) to prevent visual jitter during high-frequency updates.
Sources: src/plotter.rs:114-118, src/plotter.rs:548-620, crates/ratatui-wireframe/src/widget.rs:105-148
Dual Monitor Design
The Dual Monitor mode implements a split-pane layout for monitoring two serial ports simultaneously. It includes independent auto-scrolling logic and a dedicated TX input mode.
Architecture of the Dual Monitor TUI layout.
Sources: src/dual_ports.rs:271-290
User Interaction & Input Handling
ComChan uses a non-blocking input polling strategy within the TUI loops to remain responsive to serial data while accepting user commands.
Interaction Table
| Keybinding | Action | Scope |
|---|---|---|
Ctrl+P | Hot-swap between Monitor and Plotter | Global |
Tab | Toggle between 2D Chart and 3D Wireframe | Plotter |
i / Esc | Enter/Exit typing mode for TX commands | Dual Monitor |
? | Open interactive help modal | All Modes |
Ctrl+S | Export current 2D chart to SVG | Plotter |
Space | Pause/Resume data ingestion | Plotter |
Sources: src/plotter.rs:360-440, src/dual_ports.rs:215-265, src/monitor.rs:98-130
Help Modals and Overlays
Help menus are implemented as centered popups using the centered_rect helper function. These overlays use ratatui::widgets::Clear to ensure they are rendered on top of the active data streams without visual artifacts.
Sources: src/plotter.rs:57-73, src/dual_ports.rs:389-405
Implementation Snippet: Smooth Rotation
The Plotter uses a delta-time based Lerp to ensure 3D models rotate smoothly even if serial packets arrive at irregular intervals.
// Calculate shortest path for Euler angles to prevent 360 wrap-around spin
let pitch_diff = (target_pitch - state.display_pitch + 180.0).rem_euclid(360.0) - 180.0;
let amount = (lerp_speed * dt).clamp(0.0, 1.0);
state.display_pitch = (state.display_pitch + pitch_diff * amount).rem_euclid(360.0);
Sources: src/plotter.rs:536-545
The TUI design of ComChan effectively balances high-throughput data processing with a rich, interactive user experience, utilizing the AppExitState pattern to maintain continuous device connectivity during interface transitions.