# Phase 7: Configuration - Context

**Gathered:** 2026-03-22
**Status:** Ready for planning

<domain>
## Phase Boundary

Internal developer tunables via `steamvr.vrsettings` for the Bigscreen team. No user-facing configuration — `user_trim` is already configurable via the Beyond Utility app and stored in headset flash. Report rate, log verbosity, and moving average length are the only settings, read on driver startup.

</domain>

<decisions>
## Implementation Decisions

### Settings scope
- **No user-facing configuration** — user_trim is stored in headset flash, configurable via Beyond Utility (external app). End users do not interact with steamvr.vrsettings.
- Three internal/dev tunables only:
  1. `report_rate_ms` — HID report rate (currently hardcoded 200ms in DeviceProvider::Init)
  2. `log_verbosity` — 0=normal (state transitions + errors), 1=verbose (raw samples, algorithm values per frame)
  3. `moving_avg_length` — Override the 8-sample moving average length for tuning responsiveness vs. stability
- Threshold and hysteresis are NOT configurable — they come from headset flash and are correct as-is

### Settings section and naming
- Section name: `driver_BeyondProximity` (standard SteamVR convention: `driver_{driver_name}`)
- Key naming: `snake_case` — `report_rate_ms`, `log_verbosity`, `moving_avg_length`
- All settings have sensible defaults so the driver works with no vrsettings section present

### Settings vs flash
- No changes to Phase 4's calibration read from flash — it's already correct
- user_trim, threshold, hysteresis remain flash-only
- No priority/override logic needed between vrsettings and flash

### Runtime behavior
- Settings read once in `DeviceProvider::Init()` — startup only
- No runtime reload — user edits steamvr.vrsettings, restarts SteamVR
- No pipe reload command, no live watch

### Log verbosity
- Two levels: 0=normal (state transitions + errors only), 1=verbose (raw samples, algorithm values per frame)
- Default: 0 (normal)

### Claude's Discretion
- Default value for moving_avg_length (currently 8 in ProximityAlgorithm)
- VRSettings error handling (missing section, missing keys — fall back to defaults silently)
- How verbose mode actually logs (e.g., DriverLog format strings, frequency of raw sample logging)
- Whether moving_avg_length requires ProximityAlgorithm API changes or just parameterizing the existing constant

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### SteamVR VRSettings API pattern
- `extern/openvr/samples/drivers/drivers/simplehmd/src/hmd_device_driver.cpp` lines 12-47 — Example of reading settings from steamvr.vrsettings: section naming, GetString/GetInt32 calls
- `extern/openvr/headers/openvr_driver.h` — `IVRSettings` interface: `GetInt32()`, `GetFloat()`, `GetBool()`, `GetString()`

### Current hardcoded values to extract
- `src/driver/device_provider.cpp` line 34 — `StartReading(0x35BD, 0x0101, 200)` — report_rate_ms hardcoded to 200
- `src/hid/proximity_algorithm.h` line 33 — `static constexpr int kAverageLength = 8` — moving average length hardcoded to 8

### Integration points
- `src/driver/device_provider.cpp` — `DeviceProvider::Init()` reads VRSettings, passes values to HidDevice and ProximityAlgorithm
- `src/hid/hid_device.h` — `StartReading()` already accepts `rateMs` parameter
- `src/hid/proximity_algorithm.h` — `kAverageLength` needs to become configurable (constructor param or Reset param)

### Project requirements
- `.planning/REQUIREMENTS.md` — CONF-01, CONF-02, CONF-03 (note: scope reduced from original requirements — no user-facing settings)

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `vr::VRSettings()` — Available in driver context after `VR_INIT_SERVER_DRIVER_CONTEXT`. Standard API for reading steamvr.vrsettings.
- `HidDevice::StartReading(vid, pid, rateMs)` — Already accepts report rate as parameter. Just need to pass VRSettings value instead of hardcoded 200.
- `DriverLog()` — Existing logging wrapper. Verbose mode adds conditional logging calls guarded by verbosity level.

### Established Patterns
- `VRSettings()->GetInt32(section, key)` returns value directly (no out-param for non-string types)
- Sample drivers read settings in constructor or Init, store in member variables
- All settings have defaults in code — steamvr.vrsettings section is optional

### Integration Points
- `DeviceProvider::Init()` — Primary: read all three settings from VRSettings, pass to subsystems
- `ProximityAlgorithm` — Needs constructor or Reset param for average length (currently compile-time constant)
- `HidDevice::ReaderThreadFunc()` — Verbose logging would go here (raw sample values)
- `DeviceProvider::RunFrame()` — Verbose logging for algorithm output on every frame

</code_context>

<specifics>
## Specific Ideas

- user_trim is NOT a driver concern — it's managed by Beyond Utility and stored in headset flash. The driver already reads it correctly from flash in Phase 4.
- These settings are for the Bigscreen development team only — not documented for end users.
- The driver must work correctly with no `driver_BeyondProximity` section in steamvr.vrsettings at all (all defaults).

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope

</deferred>

---

*Phase: 07-configuration*
*Context gathered: 2026-03-22*
