Ver Fonte

Enable raw IMU in every emulated gyro mode (#308)

Steam can leave the controller's persisted IMU_MODE off, which suppresses
the RF motion samples. Only Switch Pro re-enabled it, and only on RF
link-up, so switching modes with the controller already connected (or
using DS5/DS4/PS3/DirectInput/SInput) left gyro reporting zeros.

Write raw accel + gyro for every mode that reports motion, on reconnect,
on a mode switch, and every 5 s as a keepalive.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
FakeGiraffe93 há 1 semana atrás
pai
commit
99c874ecd4
1 ficheiros alterados com 41 adições e 13 exclusões
  1. 41 13
      OpenPuck/haptics.cpp

+ 41 - 13
OpenPuck/haptics.cpp

@@ -651,6 +651,29 @@ void hapticInit()
 		g_hapticBlockUntil[s] = 0;
 	}
 }
+// Emulated modes that report motion from the controller's RF IMU samples.
+static const uint32_t IMU_KEEP_MS = 5000;
+static bool modeWantsImu(uint8_t m)
+{
+	return m == MODE_SW_PRO || m == MODE_PS5 || m == MODE_PS5_GAME ||
+	       m == MODE_HIDGYRO || m == MODE_DS4_GAME || m == MODE_PS3 ||
+	       m == MODE_DINPUT || m == MODE_SINPUT;
+}
+// Steam can leave the controller's persisted IMU mode off, and it survives across pucks. Every emulated
+// gyro mode needs the raw RF samples that setting suppresses, so write raw accel + gyro for this slot.
+static void imuForceRaw(int slot)
+{
+	static const uint8_t RAW_IMU[] = {
+		SETTING_IMU_MODE,
+		SETTING_GYRO_MODE_SEND_RAW_ACCEL |
+			SETTING_GYRO_MODE_SEND_RAW_GYRO,
+		0x00
+	};
+	if (!modeWantsImu(g_usbMode))
+		return;
+	relayEnqueue(IBEX_CMD_SET_SETTINGS_VALUES, RAW_IMU, sizeof RAW_IMU,
+		     false, (uint8_t)slot);
+}
 // Schedule the clearing re-init for ONE slot. Called on the reliable first-reply signal from rf_link and
 // again from hapticTask's link-up edge detector. Strictly per-slot: only the reconnected controller gets
 // re-inits / its pending haptics scrubbed -- the other controllers hear nothing about it.
@@ -664,19 +687,7 @@ void hapticOnReconnect(int slot)
 	g_rumble80Ms[slot] = 0;
 	// Scrub haptics queued before the link came up (stale across the reconnect) -- this slot only.
 	hapticCancelPendingOn(slot);
-	if (g_usbMode == MODE_SW_PRO) {
-		static const uint8_t RAW_IMU[] = {
-			SETTING_IMU_MODE,
-			SETTING_GYRO_MODE_SEND_RAW_ACCEL |
-				SETTING_GYRO_MODE_SEND_RAW_GYRO,
-			0x00
-		};
-
-		// Steam can leave the controller's persisted IMU mode off. Switch
-		// Pro reports require the raw RF samples that setting suppresses.
-		relayEnqueue(IBEX_CMD_SET_SETTINGS_VALUES, RAW_IMU,
-			     sizeof RAW_IMU, false, (uint8_t)slot);
-	}
+	imuForceRaw(slot);
 	// NO automatic haptic re-init. hapticReinit lands 0x81 (CLEAR DIGITAL MAPPINGS -- rid < 0x87 so it
 	// EXECUTES even on legacy framing). 0x81 is NON-IDEMPOTENT (ibex FUN_0001f554): EVERY call re-runs the
 	// lizard-disable event + func_0x0001bbf0 (a hardware peripheral re-arm unique to the 0x81 path) -- so
@@ -807,6 +818,23 @@ void hapticTask()
 			}
 		} // !modeIsPuck
 	}
+	// Re-assert the raw IMU mode on a mode switch (the link stays up, so hapticOnReconnect never fires)
+	// and periodically, in case Steam or the controller turned it back off while we were connected.
+	{
+		static uint8_t lastMode = 0xFF;
+		static unsigned long lastImu[NSLOT] = { 0 };
+		bool modeChanged = (g_usbMode != lastMode);
+		lastMode = g_usbMode;
+		for (int s = 0; s < NSLOT; s++) {
+			if (!g_slot[s].used || !hapticLinkUp(s))
+				continue;
+			if (!modeChanged &&
+			    (uint32_t)(millis() - lastImu[s]) < IMU_KEEP_MS)
+				continue;
+			lastImu[s] = millis();
+			imuForceRaw(s);
+		}
+	}
 	// Per-slot link-edge detect (backup for hapticOnReconnect in rf_link).
 	static bool wasHapticLinkUp[NSLOT] = { 0 };
 	for (int s = 0; s < NSLOT; s++) {