From a5237bb3b4bf013eda438d33d686191bd2d85b27 Mon Sep 17 00:00:00 2001 From: serversdown Date: Wed, 30 Sep 2026 14:27:31 -0400 Subject: [PATCH] docs(series4): RESOLVED -- the 0x0C float is the PER-SAMPLE peak vector sum Exact to 0.000% on all four bench waveforms, against a PVS recomputed from the decoded samples. The offset (Tran label - 12) is now established rather than inferred: four independent confirmations plus a fifth on the other firmware line. RETRACTION. The previous entry observed the float running 2-5% above max(T,V,L) and concluded it was NOT the peak vector sum, "because computed PVS runs higher than both". That computed PVS was sqrt(T^2+V^2+L^2) from the three REPORTED CHANNEL PEAKS, which is an upper bound on the real quantity rather than the quantity -- the channel maxima do not occur at the same instant, so combining them overstates the true peak. Every row of the old table is in fact consistent with max(T,V,L) <= stored <= sqrt(sum of squares). I also got this wrong in the other direction today and want it recorded. On UM20147's event the stored float matched sqrt(sum of peak squares) to 0.048%, and I called it the vector sum on that basis. It is not -- that event's peaks merely happen to be nearly coincident in time. The six CB events separated the two formulas immediately, with errors to -9.5%. ONE SAMPLE AGREEING WITH A FORMULA IS NOT EVIDENCE WHEN A SECOND FORMULA FITS IT EQUALLY WELL. Why it is worth having: it is a FREE SELF-CHECK ON THE DECODER. The device computed this number from the same samples we decode, independently of our codec, so a mismatch means the decode is wrong. Given this codebase's history of silent channel truncation -- walker bugs that shorten a channel and raise nothing -- a per-event invariant costing one float comparison is cheap insurance, and worth wiring into the download path. Also added the full 0x0C field map from real UM20147 bytes: timestamp, the record-type byte, sensor-location label, setup name, serial, the PVS float and the four channel labels with their offsets. Noted in passing: the setup name appears as "test2" in 0x0C, "test2.MMB" in 0x41 and "test2.mmb" in 0x40 -- three commands, three spellings of one file, in one session. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL --- docs/micromate_protocol_reference.md | 77 ++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/docs/micromate_protocol_reference.md b/docs/micromate_protocol_reference.md index ad2020b..d93d0ba 100644 --- a/docs/micromate_protocol_reference.md +++ b/docs/micromate_protocol_reference.md @@ -1811,7 +1811,55 @@ given it, and `/db/import/idf_file` needs no change at all. must carry it out of the chain walk. Losing it means losing the ability to name the file correctly. -### ⚠ Unresolved: the `0x0C` peak float +### ✅ RESOLVED 2026-09-30: the `0x0C` float is the PER-SAMPLE peak vector sum + +**`0x0C` content[`Tran` label − 12], float32 BE, = the peak vector sum computed +sample by sample.** Exact to 0.000% on all four bench waveforms, against a PVS +recomputed from the decoded samples: + +| key | `0x0C` float | per-sample PVS | err | `sqrt(Σpeak²)` | `max(T,V,L)` | +|---|---|---|---|---|---| +| `…82` | 1.37198 | 1.37198 | **+0.000%** | 1.41746 | 1.37063 | +| `…83` | 2.35414 | 2.35414 | **+0.000%** | 2.37824 | 2.22274 | +| `…84` | 3.51515 | 3.51515 | **−0.000%** | 3.78731 | 3.44194 | +| `…85` | 0.42267 | 0.42267 | **−0.000%** | 0.46678 | 0.41985 | + +> #### ⚠ Retraction — why this looked unresolved +> +> The previous entry (below, kept) observed the float running 2–5% above +> `max(T,V,L)` and concluded it was **not** the peak vector sum, because +> "computed PVS runs *higher* than both". +> +> That computed PVS was `sqrt(T² + V² + L²)` **from the three reported channel +> peaks** — and that is an *upper bound* on the real thing, not the real thing. +> The channel maxima do not occur at the same instant, so combining them +> overstates the true peak. Every measurement in the old table is consistent +> with the correct answer: `max(T,V,L) ≤ stored ≤ sqrt(Σpeak²)`, in all five rows. +> +> A near-miss worth recording: on UM20147's event the stored float matched +> `sqrt(Σpeak²)` to **0.048%**, which briefly looked like proof it *was* that +> quantity. It is not — the peaks on that event simply happen to be nearly +> coincident in time. **One sample agreeing with a formula is not evidence when +> a second formula fits it equally well;** the six CB events separated them +> immediately (errors to −9.5%). + +**The offset is now established, not inferred** — four independent confirmations +at 0.000%, plus a fifth on the other firmware line. + +**Why this is worth having: it is a free self-check on the decoder.** The device +computed this number from the same samples we decode, independently of our +codec. If a decoded event's per-sample PVS does not match the stored float, the +decode is wrong. Given this codebase's history of *silent* channel truncation — +walker bugs that shorten a channel and raise nothing — a per-event invariant +that costs one float comparison is cheap insurance. Worth wiring into the +download path. + +⚠ It remains true that `max(T,V,L)` and `sqrt(Σpeak²)` are **not** +interchangeable with it, so a consumer wanting the vector sum must use this +field or decode the samples — it cannot be reconstructed from the three +per-channel peaks. + +#### Superseded: the original "unresolved" entry The float32 extracted from `0x0C` runs 2–5% above `max(Tran, Vert, Long)` from the decoded samples: @@ -1824,15 +1872,38 @@ the decoded samples: | `…84` | 3.5152 | 3.4419 | | `…85` | 0.4227 | 0.4198 | -It is not peak vector sum either (computed PVS runs *higher* than both). The +~~It is not peak vector sum either (computed PVS runs *higher* than both). The field may not be the peak at all — its offset was inferred from a byte marker, -not established. **Do not rely on it** until it is pinned properly. +not established. **Do not rely on it** until it is pinned properly.~~ Worth noting the histogram (`…81`) and the loudest waveform (`…84`) report *identical* peaks to four decimals, in both measures. That is self-consistent: the histogram's single 1-minute interval spans the whole thumping session, so its maximum should equal the loudest event in it. +### `0x0C` field map, from UM20147 (11.0BD, 2026-09-30) + +Real bytes, 221 B response → 210 B content declared at `data[0] = 0xd2`: + +``` +content[ 0] day 0x1e = 30 +content[ 1] month 0x09 +content[ 2:4] year BE 0x07ea = 2026 +content[ 4] ⚠ 0xb3 = 179 — unidentified, same slot as 0x1C's content[6] +content[ 5:8] h:m:s 13:27:33 +content[11] RECORD TYPE 0x08 histogram / 0x07 waveform +content[12] "Location\0" sensor-location label +content[34] "test2\0" the setup file name, without its extension +content[76] "UM20147\0" serial +content[86] float32 BE the per-sample PEAK VECTOR SUM (= Tran − 12) +content[98] "Tran\0\0" + float32 BE at +6 +content[112] "Vert" … content[126] "Long" … content[140] "Mic" … +``` + +⚠ The setup name here is `test2` — no extension — where `0x41` reported +`test2.MMB` and `0x40` reported `test2.mmb` in the same session. Three commands, +three spellings of one file. See *Setup-name case*. + ## Event download, per-event delete, and ACH config (2026-09-25) Three captures with operator-supplied ground truth, including Thor screenshots of