SendRumble less frequently to reduce input lag

I was using two Joycons as a single controller. One (often right, sometimes
both, sometimes left) of the Joycons seems to have random lags.
This patch reliably removes the lag for me.

Potentially fixes #32.

More context:

I first excluded the possibility that the Bluetooth connection is lagging,
because when I click the "locate" button, both Joycons can rumble
immediately without lag.

Reading the existing issues seems to suggest something was wrong with
threading. When I tried moving both Joycons' "Poll" to a single thread,
by calling both ReceiveRaw() and other.ReceiveRaw() in a single Joycon
Poll thread, and removing "lock { ...}"s), lag still exists.

I then suspected the I/O loop is too busy so the code does not have time
to consume events in time. By adding some debug prints, I was able to
confirm that at the time the code receives an event (after hid_read),
it was already too late. However, it is strange that a) hid_read almost
always returns immediately, b) a single "poll" still takes a few
milliseconds. Finally, I found "SendRumble" is the culprit causing
the majority of the few milliseconds delay. Therefore the patch.

The 5 seconds is not a scientific choice. It works for me. I don't have
a USB controller to test it right now.
This commit is contained in:
Jun Wu 2019-02-02 01:26:49 -08:00
parent edd72be31a
commit 85f77cb91c

View file

@ -452,8 +452,16 @@ namespace BetterJoyForCemu {
private Thread PollThreadObj; // pro times out over time randomly if it was USB and then bluetooth?? private Thread PollThreadObj; // pro times out over time randomly if it was USB and then bluetooth??
private void Poll() { private void Poll() {
int attempts = 0; int attempts = 0;
Stopwatch watch = new Stopwatch();
watch.Start();
while (!stop_polling & state > state_.NO_JOYCONS) { while (!stop_polling & state > state_.NO_JOYCONS) {
SendRumble(rumble_obj.GetData()); // Needed for EVERYTHING to not time out. Never remove pls if (watch.ElapsedMilliseconds >= 5000) {
// Send a no-op operation as heartbeat to keep connection alive.
// Do not send this too frequently, otherwise I/O would be too heavy and cause lag.
// Needed for both BLUETOOTH and USB to not time out. Never remove pls
SendRumble(rumble_obj.GetData());
watch.Restart();
}
int a = ReceiveRaw(); int a = ReceiveRaw();
if (a > 0) { if (a > 0) {