What the Raspberry Pi time-server guides get wrong on a Pi 4, with the measurements. The headline artifact is a four-line pps-gpio patch: PREEMPT_RT force-threads IRQ handlers, and pps-gpio takes its timestamp inside its handler, so the realtime kernel puts a scheduler between the electrical edge and the clock. IRQF_NO_THREAD takes RMS offset from 2468 ns to 199 ns. - kernel/ the patch - dashboard/ live status page (position hidden by default) - docs-site/ the write-up (Astro/Starlight, brass, no tutorial section)
181 lines
8.9 KiB
HTML
181 lines
8.9 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="color-scheme" content="dark" />
|
|
<title>gps-ntp · time server</title>
|
|
<link rel="stylesheet" href="/static/style.css" />
|
|
<link rel="icon"
|
|
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><text y='18' font-size='18'>🛰️</text></svg>" />
|
|
</head>
|
|
<body>
|
|
<!-- lucide icon sprite (inline so the dashboard works fully offline) -->
|
|
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
|
<defs>
|
|
<symbol id="i-dish" viewBox="0 0 24 24"><path d="M4 10a7.31 7.31 0 0 0 10 10Z"/><path d="m9 15 3-3"/><path d="M17 13a6 6 0 0 0-6-6"/><path d="M21 13A10 10 0 0 0 11 3"/></symbol>
|
|
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
|
<symbol id="i-activity" viewBox="0 0 24 24"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></symbol>
|
|
<symbol id="i-zap" viewBox="0 0 24 24"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></symbol>
|
|
<symbol id="i-gauge" viewBox="0 0 24 24"><path d="m12 14 4-4"/><path d="M3.34 19a10 10 0 1 1 17.32 0"/></symbol>
|
|
<symbol id="i-server" viewBox="0 0 24 24"><rect width="20" height="8" x="2" y="2" rx="2"/><rect width="20" height="8" x="2" y="14" rx="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></symbol>
|
|
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
|
<symbol id="i-pin" viewBox="0 0 24 24"><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/></symbol>
|
|
<symbol id="i-radio" viewBox="0 0 24 24"><path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9"/><path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"/><circle cx="12" cy="12" r="2"/><path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"/><path d="M19.1 4.9C23 8.8 23 15.1 19.1 19"/></symbol>
|
|
<symbol id="i-check" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
|
</defs>
|
|
</svg>
|
|
|
|
<header class="topbar">
|
|
<div class="brand">
|
|
<svg class="brand-icon" aria-hidden="true"><use href="#i-dish"/></svg>
|
|
<div>
|
|
<h1 id="hostname">gps-ntp</h1>
|
|
<p class="brand-sub">GPS · PPS disciplined time server</p>
|
|
</div>
|
|
</div>
|
|
<div class="conn" id="conn" data-state="init">
|
|
<span class="conn-dot" aria-hidden="true"></span>
|
|
<span id="conn-label">connecting…</span>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
<!-- Hero: live clock + stratum verdict -->
|
|
<section class="hero panel" aria-label="Current time and sync status">
|
|
<div class="clock-wrap">
|
|
<div class="clock" id="utc-clock">--:--:--<span class="clock-frac" id="utc-frac">.000</span></div>
|
|
<div class="clock-meta"><span id="utc-date">—</span> · <span class="mono">UTC</span></div>
|
|
</div>
|
|
<div class="verdict">
|
|
<div class="stratum-badge" id="stratum-badge" data-ok="false">
|
|
<svg aria-hidden="true"><use href="#i-check"/></svg>
|
|
<div>
|
|
<span class="stratum-num" id="stratum-num">—</span>
|
|
<span class="stratum-word">stratum</span>
|
|
</div>
|
|
</div>
|
|
<div class="ref-line">synced to <strong id="ref-name">—</strong></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Key stat cards -->
|
|
<section class="cards" aria-label="Key metrics">
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-zap"/></svg> System offset</div>
|
|
<div class="card-value" id="sys-offset">—</div>
|
|
<div class="card-sub">of true time · last <span id="last-offset">—</span></div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-activity"/></svg> PPS lock</div>
|
|
<div class="card-value" id="pps-state">—</div>
|
|
<div class="card-sub">jitter <span id="pps-jitter">—</span></div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-dish"/></svg> GPS fix</div>
|
|
<div class="card-value" id="fix-mode">—</div>
|
|
<div class="card-sub"><span id="sats-line">—</span> · HDOP <span id="hdop">—</span></div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-gauge"/></svg> Root delay</div>
|
|
<div class="card-value" id="root-delay">—</div>
|
|
<div class="card-sub">dispersion <span id="root-disp">—</span></div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-server"/></svg> Clock freq</div>
|
|
<div class="card-value" id="freq">—</div>
|
|
<div class="card-sub">skew <span id="skew">—</span></div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-head"><svg aria-hidden="true"><use href="#i-users"/></svg> Clients served</div>
|
|
<div class="card-value" id="clients-count">—</div>
|
|
<div class="card-sub" id="location"><svg aria-hidden="true" class="ic-inline"><use href="#i-pin"/></svg> —</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- Offset history sparkline -->
|
|
<section class="panel spark-panel" aria-label="System offset history">
|
|
<div class="panel-head">
|
|
<h2><svg aria-hidden="true"><use href="#i-activity"/></svg> System offset · last 3 min</h2>
|
|
<div class="spark-meta" id="spark-meta">—</div>
|
|
</div>
|
|
<svg id="spark" class="spark-big" viewBox="0 0 1000 120" preserveAspectRatio="none"
|
|
role="img" aria-label="System clock offset over the last three minutes"></svg>
|
|
</section>
|
|
|
|
<div class="grid-2">
|
|
<!-- Sky plot -->
|
|
<section class="panel sky-panel" aria-label="Satellite sky view">
|
|
<div class="panel-head">
|
|
<h2><svg aria-hidden="true"><use href="#i-dish"/></svg> Sky view</h2>
|
|
<div class="legend" id="legend"></div>
|
|
</div>
|
|
<div class="sky-hold">
|
|
<svg id="sky" viewBox="0 0 400 400" role="img" aria-label="Polar plot of satellites overhead"></svg>
|
|
<div class="sky-tip" id="sky-tip" hidden></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Signal bars -->
|
|
<section class="panel snr-panel" aria-label="Satellite signal strength">
|
|
<div class="panel-head"><h2><svg aria-hidden="true"><use href="#i-radio"/></svg> Signal (C/N₀ dB-Hz)</h2></div>
|
|
<div class="snr" id="snr"></div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Sources -->
|
|
<section class="panel" aria-label="Time sources">
|
|
<div class="panel-head"><h2><svg aria-hidden="true"><use href="#i-server"/></svg> Time sources</h2></div>
|
|
<div class="table-hold">
|
|
<table class="tbl" id="sources">
|
|
<thead>
|
|
<tr><th>Source</th><th>Type</th><th class="num">Str</th><th class="num">Reach</th><th class="num">Last</th><th class="num">Offset</th><th>State</th></tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Clients -->
|
|
<section class="panel" aria-label="Clients">
|
|
<div class="panel-head"><h2><svg aria-hidden="true"><use href="#i-users"/></svg> Network clients</h2></div>
|
|
<div id="clients" class="clients"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer class="foot">
|
|
<!-- The maker's plate. Clockmakers signed the BACKPLATE — the brass face
|
|
only a repairer ever sees, once the case is open. A footer is the same
|
|
thing: a quiet engraved signature, not a billboard. -->
|
|
<aside class="ss-plate" aria-label="Supported Systems">
|
|
<a class="ss-plate__link" href="https://supported.systems" rel="noopener">
|
|
<img class="ss-plate__logo" src="/static/supported-systems-logo.svg"
|
|
alt="" width="52" height="39" loading="lazy" />
|
|
<span class="ss-plate__copy">
|
|
<span class="ss-plate__heading">A Supported Systems Joint</span>
|
|
<span class="ss-plate__body">
|
|
This clock is built and maintained by
|
|
<span class="ss-plate__name">Supported Systems</span> — a boutique
|
|
software studio focused on thoughtful, user-first technology. We
|
|
measure things before we believe them.
|
|
</span>
|
|
<span class="ss-plate__cta">
|
|
Visit supported.systems
|
|
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
|
|
<path d="M4 8h7M8 5l3 3-3 3" stroke-width="1.5" />
|
|
</svg>
|
|
</span>
|
|
</span>
|
|
</a>
|
|
</aside>
|
|
|
|
<div class="foot-meta">
|
|
<span id="foot-version">gpsntp-dashboard</span>
|
|
<span id="foot-updated">—</span>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="/static/app.js"></script>
|
|
</body>
|
|
</html>
|