# Sauna — Baseline Understanding

Synthesis of 8 sibling-repo deep-dives. This is the forward-carried "where we start" doc.
Detail lives in the per-repo files in this directory; this ties them together, reconciles
conflicts, and states the critical path + open risks.

**Goal restated:** Use the Bigscreen Beyond as a 3DOF (stretch: 6DOF) wearable spatial
display. No hardware changes. No external tracking (no SteamVR lighthouses). Low-friction UX.
Windows + Linux minimum. SteamVR optional. Stretch: drop the linkbox.

---

## 1. The headset, as a system

```
PC GPU ──DP1.4──▶ Linkbox ──USB-C cable──▶ Beyond HMD
                              (4 DP lanes + AUX + USB2.0 + VBUS + CC)

Inside the HMD:
  USB-C ─▶ PI3USB31532 flip-mux ─▶ VXR7200 (DP→MIPI bridge, I2C 0x72)
                                     │  autonomously boots from SPI flash,
                                     │  trains DP link, serves EDID, decodes nothing
                                     ▼
                                 dual MIPI-DSI ─▶ 2× SeeYA SY103WAM01 microOLED
                                                  (I2C 0x98, DSC decoded IN panel,
                                                   internal 1.33:1 upscaler, 2544²/eye native)

  USB2.0 ─▶ hub ─▶ several logical USB devices (see §2)

  ATSAMG55G19 MCU (Cortex-M4F, 512KB) — the brain. Owns the 35BD HID interface,
     overwrites VXR EDID RAM at boot, drives panels, brightness, LEDs, fan, proximity.

  Tundra TL448K6D "Watchman" SiP — Valve lighthouse tracking module.
     Holds the IMU (gyro+accel) AND all per-unit optical calibration in its flash.
     Enumerates under Valve's VID, separate from the MCU.

  [BS2/BS2E only] Gowin GW5A-LV25MG121 FPGA — eye-tracking. 2× inward IR cameras.
     Presents as a UVC webcam. Reflashable. Spare resources. Faces the EYES, not the world.
```

**Generations:** BS1 (no eye tracking, hardware-SKU IPD baked per unit), BS2 (adjustable IPD),
BS2E (BS2 + eye tracking). Detected by HMD-serial prefix `BS1`/`BS2`/`BS2E` (flash TLV tag 0x08).

---

## 2. USB device / interface map (the access surface)

| Device | VID:PID | What it is | Sauna relevance |
|---|---|---|---|
| Bigscreen HID | `35BD:0101` | MCU control interface (app mode) | Display/brightness/EDID/persistence/proximity/config |
| MCU bootloader | `35BD:4004` | Custom HID DFU for MCU app | Ship custom MCU firmware (if ever needed) |
| BL overwriter | `35BD:5004` | Rewrites the bootloader itself | Brick risk; avoid |
| Crash handler | `35BD:1001` | — | — |
| ET FPGA DFU | `35BD:0282` | USB-DFU 1.1 for eye-track FPGA | Reflash FPGA (if ever needed) |
| ET camera | `35BD:0202` "Bigeye" | UVC MJPEG 800×400@90 | Eye cameras (inward — not for SLAM) |
| **Tundra Watchman** | **`28DE:2300`** | **Valve SiP: 3 HID interfaces MI_00 IMU / MI_01 Optical / MI_02 Controller** | **THE IMU SOURCE + calibration flash** |

The two worlds: **`35BD:*` is Bigscreen's MCU** (display + housekeeping). **`28DE:2300` is Valve's
Tundra** (tracking + calibration). They are independent USB devices on the same hub. Sauna needs both.

---

## 3. The three pillars and their starting state

### Pillar A — Head tracking (3DOF)
- **Raw IMU is readable from the host with NO SteamVR and NO driver.** Predecessor
  (`openvr-resilient`, branch `resilient-imu`) proved it: plain Win32 `ReadFile` on the Tundra's
  **MI_00** HID interface (`28DE:2300`) returns 52-byte, report-ID `0x20` packets =
  **3 samples × {int16 accel[3], int16 gyro[3], uint32 timecode, uint8 seq}**, Watchman layout.
  Scales: accel ±8g ≈ 4096 LSB/g (**measured**), gyro ≈ 0.001 rad/s/LSB (plausible, unverified).
  `HidD_GetInputReport` fails (err 87) — must use streaming reads. MI_01 (`0x28`, 64B) is OPTICAL,
  not IMU — predecessor misparsed it once.
- **This collapses "reverse-engineer the Tundra SiP" to "parse a known format + verify it streams."**
- **All predecessor fusion math is a proven dead end** (wrong-frame gravity, naive decay). Redo it.
  `libsurvive` (Collabora, IMU-capable, Linux-friendly, reads Tundra calibration) was vendored as the
  intended restart point — never built on.

### Pillar B — Display (get pixels onto the panels without SteamVR)
- **Monitor-mode is EDID policy, not hardware.** The MCU writes DisplayID-2.0 EDIDs from its own
  `src/edid.h` into VXR RAM at boot. A FATP EDID profile already makes the Beyond enumerate as a
  **plain desktop monitor**. HID cmd `'d'` (`0x64`) switches EDID/refresh (75/90/72 Hz) live (~5s, resets VXR).
- **Proven desktop-monitor unlock exists** (`extended-mode-display`, ships, v1.0.3): EDID-native +
  NVAPI direct-mode **DSC present-test (DSC 1.1, 4 slices, 8bpp)** then release → Windows treats it
  as a monitor. EDID manufacturer = **"BIG"** (`DM_VENDOR_ID=0x2709`) — the direct-mode match key.
- Modes seen: **3840×1920 extended** (1920²/eye), **5088×2544 direct** (2544²/eye). 75 Hz validated, 90 Hz "use at own risk."
- Panel bring-up vocabulary all on HID: panel power, per-eye MIPI DCS display-on (`0x29`),
  **persistence/duty (`0x3FF`=100% … `0x066`=10%)** ← low-persistence lever, proximity disable, LED, fan.
- `BigscreenVR/mmi_test` holds a D3D12 direct-mode presenter (not yet cloned).
- **Caveat: the proven path is Windows + NVIDIA only** (NVAPI). Linux / AMD / Intel = unproven.

### Pillar C — Distortion correction (replace SteamVR's warp)
- The Beyond is a stock lighthouse HMD; SteamVR's closed driver implements `ComputeDistortion()` from a
  **single Valve-format JSON in the Tundra flash** (zlib, ~2KB), cached at
  `Steam\config\lighthouse\<serial>\config.json`, dumpable via `lighthouse_console.exe downloadconfig`
  (no base stations needed to read).
- **Model:** per-color-channel radial polynomial in r² (3 coeffs + center, NDC space) +
  `intrinsics` (fx≈1.422 → ~70°/eye) + `grow_for_undistort` 0.6 + `eye_to_head` rotation-only canting
  (≈ ±6.17° yaw, −5° pitch). Variants: DPOLY3 (EVT/DVT) → POLY3 (production) → DPOLY3_SCALED
  (BS2, per-channel chromatic-aberration scale). Evaluator matches Monado's Vive formula.
- **Reimplementation is ~50 lines of shader** per the recipe in `calibration-distortion.md §8`.
- **Mura correction: not applicable** — per Bigscreen, mura correction is not part of the Beyond's
  display/optical stack. Ignore `mura.mc`; nothing to re-apply when SteamVR is bypassed.
- Per-unit data: `eye_to_head` (camera-measured pitch, from VAP station) + IPD. BS1 IPD is a hardware
  SKU in serial[3:5] (55–72 mm, no 70). BS2 flashes 64.0 default + adjustable.

---

## 4. Firmware scope — likely ZERO for a v1 3DOF Windows PoC

The headline simplification from the research: a 3DOF Windows PoC may need **no new firmware at all**.
- IMU: read existing Tundra HID. No MCU/Tundra firmware change.
- Display: existing MCU EDID + host-side NVAPI unlock. No VXR/MCU firmware change.
- Distortion: host shader. No firmware change.

Firmware levers exist if later needed (all first-party, documented, recoverable over USB):
- **MCU app** (`35BD:4004`, `.beyondfw`, SHA-512, CRC-gated boot, strong recovery — bad flash just traps
  in bootloader). Safe to iterate. Bootloader replacement NOT needed.
- **VXR7200 fullrom** (HID→I2C, dual-bank fallback; 9 stock blobs in `beyond_synaptics`, opaque, from a
  Synaptics gen tool — no source). Custom video modes possible (branch `nofio_72hz` shows the recipe).
- **ET FPGA** (Gowin source available, USB-DFU). Only relevant if repurposed for sensing.
- **No tooling exists to flash the Tundra SiP** in any repo. Treat Tundra firmware as off-limits.

---

## 5. Linkbox / cable

- The cable carries 4 DP lanes + AUX + USB2.0 + VBUS + CC. **No PD controller in the headset.**
- HPD is signaled to the linkbox by switching a **CC pulldown 5.1k→1.0k** — proprietary, handshake-free.
- **Linkbox-less** therefore needs only a small host-side adapter: break out DP pins + 5V + a CC-sense→HPD
  circuit. No PD negotiation to emulate on that side.
- **True USB-C-DP-alt-mode-alone** (host USB-C → headset, no adapter) would require adding a PD sink —
  i.e. hardware. Out of scope under "no hardware changes" unless a dongle is allowed.

---

## 6. Platform / runtime — the big fork (unresolved, to grill)

Three ways to stand this up; not mutually exclusive over time:
1. **SteamVR-based PoC** — Beyond already runs as a native lighthouse HMD. Add an IMU-only pose driver so
   it tracks 3DOF without base stations; reuse SteamVR's distortion/mura for free. Fastest first light.
   Tension with the "no lighthouses / SteamVR optional" goal, but SteamVR ≠ lighthouses.
2. **Standalone host compositor** — own IMU fusion + own warp + own present (via `extended-mode-display`
   path). Max control, required for "SteamVR not needed," most work. Windows+NVIDIA first.
3. **Monado (OpenXR)** — open-source, Linux+Windows, has Vive-style distortion + IMU drivers to extend.
   Best fit for the Linux + "anything with DP" ambitions; steeper ramp.

---

## 7. Critical open risks (verify early, before committing a path)

1. **RESOLVED (S1 PASS, 2026-06-10 — `spikes/s1-imu-no-steam/FINDINGS.md`):** the Tundra streams IMU
   **unconditionally** — 993.8 Hz unique samples via plain `ReadFile`, SteamVR never run since boot, no
   wake/feature report needed. Reports are a **sliding 3-sample window** (dedupe by timecode+seq);
   timecode = 48 MHz clock, wraps ~89.5 s; 4096 LSB/g accel re-confirmed by measurement.
2. **Yaw drift.** 3DOF from gyro+accel has no absolute heading. Is there a magnetometer in the Tundra
   (sibling `tundra-mag-plate`, `resilient-imu` hint at mag work)? If not, yaw drifts → needs recenter UX
   or a mag source. *S1 datapoint: no mag report IDs on MI_00 — only `0x20`. v1 design assumes no mag
   (recenter hotkey owns yaw).*
3. **IMU gyro scale unverified.** Accel scale measured; gyro 0.001 rad/s/LSB only plausible. Calibrate.
4. **Display unlock is NVIDIA-only today.** AMD/Intel/Linux desktop-monitor path unproven.
   *S2 datapoints (2026-06-10): own-process direct-mode present PROVEN on Windows+NVIDIA via NDA
   NVAPI DirectMode (75 Hz native, zero errors). `VK_NV_acquire_winrt_display` is dead on consumer
   Windows (specialized displays edition-gated, absent on Win11 Pro). Beyond modes exposed in the
   DM pool: 5088×2544@75 + 3840×1920@90 × 5 formats; DSC driver-managed.*
5. **90 Hz / native-res direct mode** flagged "use at own risk"; burn-in is real (a 10-min timeout was
   deliberately added). Low-persistence + safety matter.

---

## 8. Reuse vs redo — quick ledger

**Reuse:** Tundra HID IMU protocol facts + debug logs (`openvr-resilient`); vendored `libsurvive`;
`extended-mode-display` HID bring-up + NVAPI unlock + EDID switch; full `35BD:0101` opcode map
(`hmdutility`, `bey-closer-t1`); distortion model + config-dump path + warp recipe (`calibration-distortion`);
`mmi_test` presenter.
**Redo:** all IMU fusion/orientation math; all device-I/O architecture; the host app; Linux support;
distortion shader (port the model, don't inherit predecessor code).
**Off-limits / hardware:** Tundra firmware; USB-C-alone (needs PD sink); 6DOF from existing cameras
(inward-facing).

---

*See also: per-repo files `openvr-resilient.md`, `openvr-host-tools.md`, `firmware-update-chain.md`,
`beyond-synaptics.md`, `hmdutility.md`, `extended-mode-display.md`, `calibration-distortion.md`, `eye-tracking.md`.*
