Files
MARTe-Integrated-Components/Client/udpstreamer/static/index.html
T
Martino FerrariandClaude Sonnet 4.6 21d084d2ea webui: add pure calibration module with unit tests
Implements Calib JS module (calibration.js) with affine transform primitives,
CalTable, and normaliseCal matching Go CalConfig.Normalise semantics; 14 node
--test cases all pass. Loads before app.js in index.html.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-17 00:29:53 +02:00

222 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>
<span id="ruler-readout" style="display:none">
<span class="cur-sep"></span>
<span id="cur-y1">Y1: —</span><span class="cur-sep"></span>
<span id="cur-y2">Y2: —</span><span class="cur-sep"></span>
<span id="cur-dy">ΔY: —</span>
</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">Cursors</button>
<button id="btn-ruler" class="ctrl-btn" title="Horizontal value rulers">Rulers</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>
<label class="ctrl-check" title="Snap jittery inter-frame timestamps to ideal spacing (eliminates overlaps/gaps from software-dispatch jitter)">
<input type="checkbox" id="cb-monotonic"> Sync TS
</label>
</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-force" title="Capture now, ignoring the threshold">Force</button>
<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>
<span id="history-badge" style="display:none;font-size:10px;color:#f9e2af;margin-left:8px"></span>
</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-offset-row" style="display:none;align-items:center;gap:4px">
<label class="vstb-lbl" title="Raw value at screen centre — unbounded, may lie outside the plotted range">Offset</label>
<input type="number" id="vscale-offset" class="ctx-num" step="any" value="0">
</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>
<!-- Follows the mouse over a plot: time + per-trace values. -->
<div id="hover-readout" style="display:none"></div>
<script src="/calibration.js"></script>
<script src="/app.js"></script>
</body>
</html>