You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Your command table lists 0x05 as "History (922-byte record, purpose unknown)" and the TODOs ask for GET_RT_PPG's opcode bytes. They're the same command. Findings below are from an O2Ring-S (S8AW2100, the T8520 platform), validated against ~49 recording sessions; parser + evidence live in [Plantucha/Tepna](https://github.com/Plantucha/Tepna) (Apache-2.0 — capture-host/ for the parser, briefs/O2RING-RAW-DUAL-WAVELENGTH-2026-08-05-BRIEF.md for the evidence trail).
1. The argument is load-bearing.0x05 with no args / 00/01/02 returns a fixed 922-byte reply that scores as noise — we swept all 256 opcodes that way and wrongly concluded raw PPG didn't exist. The vendor SDK (lepu-blepro, oxyIIGetRtPpg) sends {0x07, 0x01}, and with that argument both channels are ordered waveforms (successive-difference ratio ~0.015 vs 0.34 for the same bytes shuffled). General lesson for the doc: an opcode sweep tests opcodes, not the argument space behind each one — a "no response to arguments tried" is not "no such capability."
2. Wire format. Reply = header (record count is a field in the reply — parse it, don't assume) + up to 102 records × 9 bytes: int32 ch0, int32 ch1, uint8 motion (device order) + a 2-byte trailer. No timestamp per record.
3. It's a drain buffer, not a rate. Every reply at ≥1 Hz polling carries exactly 102 records — that's a buffer-cap signature. Poll it twice back-to-back per cycle or you lose samples (~18% loss at single 1 Hz drains in our corpus). True fill rate is >102 Hz; the AFE (TI AFE4403 per FCC internal photos, alongside the nRF52840) makes 125 Hz the likely ADC rate. Don't stamp records on a borrowed 125 Hz grid — derive cadence from your own drain times.
4. Channel identity (functional, not spectral). The ratio-of-ratios R = (AC/DC)₀/(AC/DC)₁ tracks the device's own 1 Hz SpO₂ with the sign that implies ch0 = IR, ch1 = RED — monotonic dose-response across 49 sessions, and a per-session linear calibration reproduces the device's SpO₂ output at held-out per-session median r ≈ 0.72, RMSE ≈ 0.56%. Flag it as functional inference: a swapped pair yields a confident wrong saturation, so treat the assignment as unconfirmed until someone does a spectral test.
5. The firmware's displayed SpO₂ lags this waveform by ~10 s (its averaging window) — measured as the peak of the lag-correlation. Useful if you're aligning 0x05 data against the 1 Hz output.
Smaller items for the table:
0x83 — buzzer trigger (undocumented; fires the motor — we use it as a cross-device timing fiducial).
0x03 caveat: single channel only, and it silently truncates past ~2 s of backlog — worth a warning box in the LIVE_SAMPLES_A section.
GET_INFO bytes [24:31] carry the readable RTC — the clock is readable, not push-only via 0xC0.
The stored-file duration counter is ±1 s quantized (not a frame index): a +2 step is not a dropped frame.
Firmware ≤ mid-2026 had an hourly HR artifact in recordings (vendor-confirmed to us; fixed around 2026-05-27) — relevant to anyone parsing stored files.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Your command table lists
0x05as "History (922-byte record, purpose unknown)" and the TODOs ask forGET_RT_PPG's opcode bytes. They're the same command. Findings below are from an O2Ring-S (S8AW2100, the T8520 platform), validated against ~49 recording sessions; parser + evidence live in [Plantucha/Tepna](https://github.com/Plantucha/Tepna) (Apache-2.0 —capture-host/for the parser,briefs/O2RING-RAW-DUAL-WAVELENGTH-2026-08-05-BRIEF.mdfor the evidence trail).1. The argument is load-bearing.
0x05with no args /00/01/02returns a fixed 922-byte reply that scores as noise — we swept all 256 opcodes that way and wrongly concluded raw PPG didn't exist. The vendor SDK (lepu-blepro,oxyIIGetRtPpg) sends{0x07, 0x01}, and with that argument both channels are ordered waveforms (successive-difference ratio ~0.015 vs 0.34 for the same bytes shuffled). General lesson for the doc: an opcode sweep tests opcodes, not the argument space behind each one — a "no response to arguments tried" is not "no such capability."2. Wire format. Reply = header (record count is a field in the reply — parse it, don't assume) + up to 102 records × 9 bytes:
int32 ch0, int32 ch1, uint8 motion(device order) + a 2-byte trailer. No timestamp per record.3. It's a drain buffer, not a rate. Every reply at ≥1 Hz polling carries exactly 102 records — that's a buffer-cap signature. Poll it twice back-to-back per cycle or you lose samples (~18% loss at single 1 Hz drains in our corpus). True fill rate is >102 Hz; the AFE (TI AFE4403 per FCC internal photos, alongside the nRF52840) makes 125 Hz the likely ADC rate. Don't stamp records on a borrowed 125 Hz grid — derive cadence from your own drain times.
4. Channel identity (functional, not spectral). The ratio-of-ratios
R = (AC/DC)₀/(AC/DC)₁tracks the device's own 1 Hz SpO₂ with the sign that implies ch0 = IR, ch1 = RED — monotonic dose-response across 49 sessions, and a per-session linear calibration reproduces the device's SpO₂ output at held-out per-session median r ≈ 0.72, RMSE ≈ 0.56%. Flag it as functional inference: a swapped pair yields a confident wrong saturation, so treat the assignment as unconfirmed until someone does a spectral test.5. The firmware's displayed SpO₂ lags this waveform by ~10 s (its averaging window) — measured as the peak of the lag-correlation. Useful if you're aligning 0x05 data against the 1 Hz output.
Smaller items for the table:
0x83— buzzer trigger (undocumented; fires the motor — we use it as a cross-device timing fiducial).0x03caveat: single channel only, and it silently truncates past ~2 s of backlog — worth a warning box in the LIVE_SAMPLES_A section.All reactions