calibrator: exact center in must be exact center out
The legacy joystick math left the output unchanged when the raw sample was exactly 0 - a case a jittering pot never produces, so on real hardware the hold was invisible. vRIO's pad deadzone produces it constantly: every release of the bench gamepad shapes the residual to exactly 0.0 and holds it there, one sample per 55 ms poll. The calibrator held the last in-motion output against that stream indefinitely, so the virtual pad froze off-center at whatever the stick commanded the instant before release. Flown, that read as a Descent 3 pod drifting on yaw and pitch with the stick centered, stopping only when the release was slow enough to land an intermediate sample inside the +/-5 band. It survived a full day of suspects - the game's deadzone, its axis map, its focus handling, com0com, the serial protocol - because every layer below the calibrator was correct: the freeze was visible in joy.cpl itself, and the game's own control trace showed heading latched at -0.38 while the wire carried perfect zeros. Same divergence from the legacy port, same reasoning, as the throttle detent fix above it: zero means centered, not "no information". Both axes; regression tests pin the fast-release case and center stability across repeated zero polls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -200,7 +200,19 @@ public sealed class AxisCalibrator
|
||||
// 16838 (not 16383) and a +2 nudge are deliberate legacy anti-snap tweaks.
|
||||
_joystickXLast = lJx > 0 ? 16838 - ((lJx + 2) * sRightRate) : AxisOutputs.Center;
|
||||
}
|
||||
// lJx == 0 leaves _joystickXLast unchanged (legacy behavior).
|
||||
else
|
||||
{
|
||||
// Deliberate divergence from the legacy port, same reasoning as the
|
||||
// throttle detent above: the legacy held the previous output on a raw
|
||||
// of exactly 0. A real pot jitters and never rests at exact 0, so the
|
||||
// hold was invisible on hardware - but vRIO's pad deadzone emits
|
||||
// sustained exact zeros on release, and the hold latched the last
|
||||
// in-motion output indefinitely: the ship kept turning at whatever
|
||||
// rate the stick commanded the instant before release (bench
|
||||
// 2026-08-01, Descent 3 drifting on yaw/pitch with the stick
|
||||
// centered). Exact center in must be exact center out.
|
||||
_joystickXLast = AxisOutputs.Center;
|
||||
}
|
||||
|
||||
return _config.InvertX ? AxisOutputs.Max - _joystickXLast : _joystickXLast;
|
||||
}
|
||||
@@ -223,7 +235,12 @@ public sealed class AxisCalibrator
|
||||
lJy -= DeadzoneJoystick;
|
||||
_joystickYLast = lJy > 0 ? AxisOutputs.Center - (lJy * sDownRate) : AxisOutputs.Center;
|
||||
}
|
||||
// lJy == 0 leaves _joystickYLast unchanged (legacy behavior).
|
||||
else
|
||||
{
|
||||
// Exact 0 centers rather than holding the previous output - see the
|
||||
// matching branch in JoystickX for the full story.
|
||||
_joystickYLast = AxisOutputs.Center;
|
||||
}
|
||||
|
||||
return _config.InvertY ? AxisOutputs.Max - _joystickYLast : _joystickYLast;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user