diff --git a/docs-site/public/audio/lightning-talk.mp3 b/docs-site/public/audio/lightning-talk.mp3 new file mode 100644 index 0000000..c8b403d Binary files /dev/null and b/docs-site/public/audio/lightning-talk.mp3 differ diff --git a/docs-site/src/components/CuckooClock.astro b/docs-site/src/components/CuckooClock.astro new file mode 100644 index 0000000..84a6d28 --- /dev/null +++ b/docs-site/src/components/CuckooClock.astro @@ -0,0 +1,298 @@ +--- +// A cuckoo clock you can click. It strikes the current hour. +// +// Two things here are deliberate rather than decorative: +// +// 1. THE PENDULUM TICKS, it does not sweep. `steps(2)` over 2s means it lands +// in exactly two discrete positions per period — one per second. That IS an +// escapement: the mechanism that takes continuous energy (a falling weight, +// a crystal oscillator, a satellite) and chops it into countable ticks. The +// whole site is an argument about what happens when you put a scheduler in +// front of that chop, so the hero ought to do it correctly. +// +// 2. THE CALL IS SYNTHESIZED, not a sample. A real cuckoo clock is two wooden +// pipes pushed by a bellows, tuned a MINOR THIRD apart, high note first. +// That's ~700 Hz down to ~590 Hz — about twenty lines of Web Audio. So the +// sound isn't an asset we shipped; it's the mechanism, rebuilt. Also it +// means the hero costs zero bytes of audio and works offline. +// +// Audio only ever starts from a click, which is both good manners and the only +// thing browsers permit — an AudioContext can't be resumed without a gesture. +--- + +
+ + +

+
+ + + + diff --git a/docs-site/src/components/ListenToTalk.astro b/docs-site/src/components/ListenToTalk.astro new file mode 100644 index 0000000..0dee9c7 --- /dev/null +++ b/docs-site/src/components/ListenToTalk.astro @@ -0,0 +1,136 @@ +--- +// "Listen to the talk" — the 90-second version of this site. +// +// preload="none" matters: without it every reader's browser downloads the whole +// MP3 on page load whether or not they ever press play. On a docs page that's +// ~800 KB of bandwidth for a feature most people skip. The cost is a ~200 ms +// delay before audio starts, which nobody notices on a 90-second talk. +// +// The transcript below is not an accessibility afterthought — it's the reason +// the page is searchable and the reason someone in an open-plan office can +// still get the argument. Audio is the alternative to reading, never a +// replacement for the text. + +interface Props { + src?: string; + seconds?: number; +} +const { src = "/audio/lightning-talk.mp3", seconds = 89 } = Astro.props; +--- + +
+ + + + +
+ Transcript + +
+
+ + + + diff --git a/docs-site/src/content/docs/index.mdx b/docs-site/src/content/docs/index.mdx index 3a74dbb..07cd3bb 100644 --- a/docs-site/src/content/docs/index.mdx +++ b/docs-site/src/content/docs/index.mdx @@ -4,6 +4,41 @@ description: A field report on GPS Stratum 1 timekeeping on a Raspberry Pi 4 — --- import { Aside, CardGrid, Card } from '@astrojs/starlight/components'; +import CuckooClock from '../../components/CuckooClock.astro'; +import ListenToTalk from '../../components/ListenToTalk.astro'; + + + + +Here's a thing that cost us a week. It might be costing you right now, and you'd +have no way to know. + +We built a GPS-disciplined time server on a Raspberry Pi 4. Stratum 1 — a +satellite pulse, once a second, straight into a GPIO pin. Then we did what every +guide says to do next. Install a realtime kernel. Isolate the interrupt. Pin it +to a quiet core. + +**The realtime kernel made it three times worse.** Not slightly worse. Three +times. 2134 ns of jitter became 6947 ns. + +Here is why. PREEMPT_RT buys its determinism by turning interrupt handlers into +schedulable threads. For almost every driver that's a good trade. But the PPS +driver takes its timestamp *inside* its handler. So threading it doesn't defer +some work — it defers **the act of looking at the clock**. We didn't make the +system more predictable. We put a scheduler between the pulse and the clock. + +The fix is four lines. One flag: `IRQF_NO_THREAD`. Keep that one handler in +hard-IRQ context, and let everything else stay preemptible. Our error went from +2468 ns to **199 ns**. + +As far as we can tell, nobody has applied this. Which means anyone running GPS +timing on a realtime kernel is quietly eating microseconds of error and has no +reason to suspect it — because nothing looks broken. chrony still says Stratum 1. +The dashboard still says locked. The number is just silently worse. + +So that's the talk. Measure your clock. Don't trust the guide. And if you take +one thing from us, [take the patch](/reference/the-patch/). + **This is not a build guide.**