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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
This commit is contained in:
@@ -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
|
must carry it out of the chain walk. Losing it means losing the ability to
|
||||||
name the file correctly.
|
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 float32 extracted from `0x0C` runs 2–5% above `max(Tran, Vert, Long)` from
|
||||||
the decoded samples:
|
the decoded samples:
|
||||||
@@ -1824,15 +1872,38 @@ the decoded samples:
|
|||||||
| `…84` | 3.5152 | 3.4419 |
|
| `…84` | 3.5152 | 3.4419 |
|
||||||
| `…85` | 0.4227 | 0.4198 |
|
| `…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,
|
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
|
Worth noting the histogram (`…81`) and the loudest waveform (`…84`) report
|
||||||
*identical* peaks to four decimals, in both measures. That is self-consistent:
|
*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
|
the histogram's single 1-minute interval spans the whole thumping session, so
|
||||||
its maximum should equal the loudest event in it.
|
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)
|
## Event download, per-event delete, and ACH config (2026-09-25)
|
||||||
|
|
||||||
Three captures with operator-supplied ground truth, including Thor screenshots of
|
Three captures with operator-supplied ground truth, including Thor screenshots of
|
||||||
|
|||||||
Reference in New Issue
Block a user