203 lines
9.8 KiB
HTML
203 lines
9.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>UDP Scope</title>
|
||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||
<link rel="stylesheet" href="/uPlot.min.css">
|
||
<link rel="stylesheet" href="/style.css">
|
||
<script src="/uPlot.iife.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<!-- ── Top bar ───────────────────────────────────────────────── -->
|
||
<div id="topbar">
|
||
<button id="btn-sidebar" class="ctrl-btn active" title="Toggle sidebar">☰</button>
|
||
<span id="app-title">UDP Scope</span>
|
||
<div class="topbar-vsep"></div>
|
||
<button id="btn-layout" class="ctrl-btn layout-toggle" title="Select layout">⊞ 1×1 ▾</button>
|
||
<div class="topbar-sep"></div>
|
||
<div id="cursor-readout">
|
||
<span id="cur-ta">A: —</span><span class="cur-sep">│</span>
|
||
<span id="cur-tb">B: —</span><span class="cur-sep">│</span>
|
||
<span id="cur-dt">ΔT: —</span>
|
||
</div>
|
||
<span class="ctrl-label" id="lbl-window">Window:</span>
|
||
<select id="window-select" class="ctrl-select">
|
||
<option value="1">1 s</option><option value="5" selected>5 s</option>
|
||
<option value="10">10 s</option><option value="30">30 s</option>
|
||
<option value="60">60 s</option>
|
||
</select>
|
||
<button id="btn-cursor" class="ctrl-btn" style="display:none">Cursor</button>
|
||
<button id="btn-zoom-back" class="ctrl-btn" style="display:none">← Back</button>
|
||
<button id="btn-zoom-fit" class="ctrl-btn">Fit</button>
|
||
<button id="btn-csv-all" class="ctrl-btn" title="Export all signals to CSV">⬇ CSV</button>
|
||
<button id="btn-sync-resume" class="ctrl-btn resume-btn" style="display:none">↺ Auto</button>
|
||
<button id="btn-trigger" class="ctrl-btn">⚡ Trigger</button>
|
||
<button id="btn-pause-global" class="ctrl-btn">⏸ Pause</button>
|
||
</div>
|
||
<!-- ── Trigger bar ───────────────────────────────────────────── -->
|
||
<div id="trigbar">
|
||
<div class="trig-group">
|
||
<span class="trig-label">Signal</span>
|
||
<select id="trig-signal" class="trig-select"><option value="">— none —</option></select>
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group">
|
||
<span class="trig-label">Edge</span>
|
||
<select id="trig-edge" class="trig-select">
|
||
<option value="rising">Rising ↑</option>
|
||
<option value="falling">Falling ↓</option>
|
||
<option value="both">Both ↕</option>
|
||
</select>
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group">
|
||
<span class="trig-label">Threshold</span>
|
||
<input id="trig-threshold" class="trig-input" type="number" value="0" step="any">
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group">
|
||
<span class="trig-label">Window</span>
|
||
<select id="trig-window" class="trig-select">
|
||
<option value="0.0001">100 μs</option><option value="0.001">1 ms</option>
|
||
<option value="0.01">10 ms</option><option value="0.1">100 ms</option>
|
||
<option value="0.5">500 ms</option><option value="1" selected>1 s</option>
|
||
<option value="5">5 s</option><option value="10">10 s</option>
|
||
</select>
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group">
|
||
<span class="trig-label">Pre</span>
|
||
<input id="trig-pre" class="trig-range" type="range" min="0" max="100" value="20">
|
||
<span class="trig-range-val" id="trig-pre-val">20%</span>
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group">
|
||
<span class="trig-label">Mode</span>
|
||
<select id="trig-mode" class="trig-select">
|
||
<option value="normal">Normal</option>
|
||
<option value="single">Single</option>
|
||
</select>
|
||
</div>
|
||
<div class="trig-sep"></div>
|
||
<div class="trig-group" style="gap:8px">
|
||
<span id="trig-status-badge">IDLE</span>
|
||
<button id="btn-trig-stop" style="display:none">Stop</button>
|
||
<button id="btn-trig-rearm">Rearm</button>
|
||
</div>
|
||
</div>
|
||
<!-- ── Body ─────────────────────────────────────────────────── -->
|
||
<div id="body">
|
||
<div id="sidebar">
|
||
<div id="sidebar-header">Signals</div>
|
||
<div id="signal-list"></div>
|
||
</div>
|
||
<div id="main">
|
||
<div id="plot-grid" class="l1x1"></div>
|
||
</div>
|
||
</div>
|
||
<!-- ── Stats panel ─────────────────────────────────────────────── -->
|
||
<div id="stats-panel">
|
||
<div id="stats-panel-hdr">
|
||
<span class="stats-hdr-label">Source Statistics</span>
|
||
<select id="stats-source-sel" class="stats-source-sel"></select>
|
||
<button id="btn-stats-close">✕</button>
|
||
</div>
|
||
<div id="stats-body"></div>
|
||
</div>
|
||
<!-- ── Status bar ─────────────────────────────────────────────── -->
|
||
<div id="statusbar">
|
||
<div id="sb-left">
|
||
<div id="status-led"></div>
|
||
<span id="status-text">Disconnected</span>
|
||
<span id="sb-tsage"></span>
|
||
<button id="btn-stats" class="ctrl-btn" style="height:16px;padding:0 7px;font-size:10px;line-height:1">📊 Stats</button>
|
||
</div>
|
||
<span id="build-version"></span>
|
||
</div>
|
||
<div id="layout-menu"></div>
|
||
<!-- ── Signal style context menu ─────────────────────────────── -->
|
||
<div id="sig-ctx-menu" style="display:none">
|
||
<div class="ctx-menu-header">Style:
|
||
<span id="ctx-menu-key" class="ctx-menu-key"></span></div>
|
||
<div class="ctx-row">
|
||
<label>Color</label>
|
||
<input type="color" id="ctx-color">
|
||
</div>
|
||
<div class="ctx-row">
|
||
<label>Width</label>
|
||
<div class="ctx-btns" id="ctx-width-btns">
|
||
<button class="ctx-btn" data-w="1">1px</button>
|
||
<button class="ctx-btn active" data-w="1.5">1.5</button>
|
||
<button class="ctx-btn" data-w="2">2px</button>
|
||
<button class="ctx-btn" data-w="3">3px</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctx-row">
|
||
<label>Line</label>
|
||
<div class="ctx-btns" id="ctx-dash-btns">
|
||
<button class="ctx-btn active" data-dash="solid">——</button>
|
||
<button class="ctx-btn" data-dash="dashed">╌╌</button>
|
||
<button class="ctx-btn" data-dash="dotted">·····</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctx-row">
|
||
<label>Marker</label>
|
||
<div class="ctx-btns" id="ctx-marker-btns">
|
||
<button class="ctx-btn active" data-marker="none">none</button>
|
||
<button class="ctx-btn" data-marker="circle">●</button>
|
||
<button class="ctx-btn" data-marker="square">■</button>
|
||
<button class="ctx-btn" data-marker="cross">✕</button>
|
||
<button class="ctx-btn" data-marker="diamond">◆</button>
|
||
</div>
|
||
</div>
|
||
<div class="ctx-row">
|
||
<label>Size</label>
|
||
<input type="range" class="ctx-range" id="ctx-marker-size" min="2" max="10" value="4">
|
||
<span class="ctx-range-val" id="ctx-marker-size-val">4px</span>
|
||
</div>
|
||
</div>
|
||
<!-- ── Array index picker (trigger signal) ──────────────────────── -->
|
||
<div id="array-idx-picker" style="display:none">
|
||
<div class="ctx-menu-header">Element index: <span id="aip-sig" class="ctx-menu-key"></span></div>
|
||
<div class="ctx-row">
|
||
<label>Index</label>
|
||
<input type="number" id="aip-idx" class="ctx-num" min="0" step="1" value="0">
|
||
<span id="aip-range" style="font-size:10px;color:var(--overlay0)"></span>
|
||
</div>
|
||
<div class="ctx-row" style="justify-content:flex-end;gap:6px">
|
||
<button class="ctx-btn" id="aip-cancel">Cancel</button>
|
||
<button class="ctx-btn active" id="aip-ok">OK</button>
|
||
</div>
|
||
</div>
|
||
<!-- ── VScale toolbar (moved into plot card when active) ─────────── -->
|
||
<div id="vscale-menu" style="display:none">
|
||
<div class="vstb-header">
|
||
<span class="vstb-label">V-Scale: <span id="vscale-menu-key" class="ctx-menu-key"></span></span>
|
||
<div class="ctx-btns" id="vscale-mode-btns">
|
||
<button class="ctx-btn active" data-mode="auto">Auto</button>
|
||
<button class="ctx-btn" data-mode="range">Range</button>
|
||
<button class="ctx-btn" data-mode="manual">Manual</button>
|
||
</div>
|
||
<div id="vscale-manual-row" style="display:none;align-items:center;gap:4px">
|
||
<label class="vstb-lbl">V/div</label>
|
||
<input type="number" id="vscale-vdiv" class="ctx-num" min="1e-30" step="any" value="1">
|
||
</div>
|
||
<div id="vscale-pos-row" style="display:none;align-items:center;gap:4px">
|
||
<label class="vstb-lbl">Pos</label>
|
||
<input type="number" id="vscale-pos" class="ctx-num" step="0.1" value="0">
|
||
</div>
|
||
<div id="vscale-type-row" style="display:none;align-items:center;gap:4px">
|
||
<label class="vstb-lbl">Type</label>
|
||
<div class="ctx-btns" id="vscale-type-btns">
|
||
<button class="ctx-btn active" data-type="analog">Analog</button>
|
||
<button class="ctx-btn" data-type="digital">Digital</button>
|
||
</div>
|
||
</div>
|
||
<button id="btn-vscale-close" class="vstb-close" title="Close">✕</button>
|
||
</div>
|
||
</div>
|
||
<script src="/app.js"></script>
|
||
</body>
|
||
</html> |