PadRIO: publish stick X in the WIRE sign -- the left/right inversion fix

User-reported: glass left/right inverted.  Closed with live sign algebra:
the joystick-group wire push was traced end to end (new env-gated
BT_CTRLMAP_LOG push trace + record mode-mask in the install log) --
measured wire stickX=-1 -> turnDemand=-1, the SAME demand the
user-verified dev D-key-RIGHT produces (stickX=+1 -> turnDemand=-1 via the
bridge's negate-once, cb82d8c).  The mapper interprets the authentic RIO
WIRE convention: stick right = NEGATIVE JoystickX (the vRIO/RIOJoy
calibration convention).  PadRIO now publishes X negated (all sources --
keyboard deflect, pad LX, panel -- uniformly); Y stays screen-sign;
L4PADFLIP still flips both.  Also: PadRIO honors BT_KEY_NOFOCUS=1 (the
btinput harness override) for automation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-18 19:38:53 -05:00
co-authored by Claude Fable 5
parent 1e6f5fd347
commit 22d7a0e3b7
2 changed files with 45 additions and 1 deletions
+20
View File
@@ -1523,6 +1523,25 @@ void
stick.x = rioPointer->JoystickX;
stick.y = rioPointer->JoystickY;
//
// BT_CTRLMAP_LOG=1: periodic trace of the wire stick reaching the
// joystick-group push (stick-path diagnosis).
//
{
static const int s_stickLog =
(getenv("BT_CTRLMAP_LOG") != 0 && *getenv("BT_CTRLMAP_LOG") != '0');
static unsigned long s_lastStickLog = 0;
unsigned long stick_now = timeGetTime();
if (s_stickLog && stick_now - s_lastStickLog >= 1000)
{
s_lastStickLog = stick_now;
DEBUG_STREAM << "[ctrlmap] push stick x=" << stick.x
<< " y=" << stick.y
<< " mode 0x" << std::hex << (unsigned)mode_mask
<< std::dec << "\n" << std::flush;
}
}
Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]);
joystickGroup[LBE4ControlsManager::JoystickPhysical].Update(
&stick, mode_mask
@@ -2200,6 +2219,7 @@ void
<< " subsys " << mapping->subsystemID
<< " group " << (int)mapping->controlsGroup
<< " elem " << element
<< " mask 0x" << std::hex << (unsigned)mode_mask << std::dec
<< " attrID " << (int)mapping->attributeID
<< " -> +0x" << std::hex
<< (attribute ? (int)((char*)attribute - (char*)subsystem) : -1)
+25 -1
View File
@@ -59,6 +59,20 @@ static float
static int
ProcessHasFocus()
{
//
// BT_KEY_NOFOCUS=1: automation harnesses read keys without focus
// (the same override the btinput binding engine honors).
//
static int s_noFocus = -1;
if (s_noFocus < 0)
{
const char *value = getenv("BT_KEY_NOFOCUS");
s_noFocus = (value != 0 && *value == '1') ? 1 : 0;
}
if (s_noFocus)
{
return 1;
}
HWND foreground = GetForegroundWindow();
if (foreground == NULL)
{
@@ -418,10 +432,20 @@ void
if (channelValue[c] > 1.0f) channelValue[c] = 1.0f;
}
//
// PORT SIGN (user-reported inversion, closed with live sign algebra
// 2026-07-18): the mapper interprets the WIRE convention -- stick
// right = NEGATIVE JoystickX (the real RIO hardware / vRIO calibration
// convention; the keyboard bridge compensates by negating once,
// cb82d8c). Measured: wire stickX=-1 -> turnDemand=-1 = the same
// demand the user-verified D-key-RIGHT produces -- so screen-sign
// publish was inverted. X therefore publishes NEGATED; Y stays
// screen-sign. L4PADFLIP still flips both on top.
//
float stick_sign = flipStickAxes ? -1.0f : 1.0f;
Throttle = (Scalar)channelValue[PadBindingProfile::ChannelThrottle];
JoystickX = (Scalar)(stick_sign *
channelValue[PadBindingProfile::ChannelJoystickX]);
-channelValue[PadBindingProfile::ChannelJoystickX]);
JoystickY = (Scalar)(stick_sign *
channelValue[PadBindingProfile::ChannelJoystickY]);
LeftPedal = (Scalar)channelValue[PadBindingProfile::ChannelLeftPedal];