Closed CavemanJoe closed 7 months ago
Sounds like you tried every angle and you’ve gotten much further than others in trying to use guilikit joysticks on this device. The general recommendation has been to just stick with the original joystick or get the rg353m hall sticks instead. As far as I can tell, joystick calibration is just not possible on this platform at this time. Good luck.
Yikes, you weren't kidding, I've been at this all day. Guide follows for anyone seeking to do the same, IDK if you wanna put this in the wiki or whatevs:
Phew. Right, I've been cranking away at this problem all day and I've got good news and bad, the good news is that you CAN calibrate and correct issues with Hall-effect joysticks from within ArkOS. The bad news: it's a massive pain in the arse.
My left stick was favouring left to the point of drifting while centered, my right was weak in the north, and they were both oversensitive. Here's how I fixed it.
All of this is done over SSH, so enable remote services and get ssh'd in. First, install joystick stuff with sudo apt-get install joystick - that gives diagnostic and calibration front-ends for both old and new Linux joystick interfaces (aye there are two and they both suck). The old one is made up of jstest (tests joysticks), jscal (calibrates joysticks, albeit to no effect at all within arkOS that I've found, guess it uses the newer interface) and jscal-store (supposed to store calibration data so it doesn't get wiped after a reboot - but instead it just kills the joypad dead lol). The new one involves evtest (shows inputs badly) and evdev-joystick (modifies calibration).
The gamepad, made up of the D-pad, ABXY, select, start, shoulder buttons and two analogue sticks are on /dev/input/event4. The function button, volume keys, power, headphone jack sensor and touchscreen are on different devices, number 4's our lad. So we go:
evdev-joystick --showcal /dev/input/event4
and it shows us four joystick axes, with default minimum and maximum values of -1800 and 1800 respectively. We also have a flatness (which is supposed to correspond to the stick's deadzone, but it doesn't seem to have any effect in this environment) and fuzz (which does... something. You can tell it's doing something all right. If you search, you'll find folk wondering aloud what it does and cursing the man page). Because the most common fault is drift at centre position, and we've got no deadzone adjustment, we're in for a lot of trial and error adjusting the minimum and maximum values.
Start off by seeing just how far outta whack your sticks are, by running
evtest /dev/input/event4
and giving them a good wiggle. Write down the maximum and minimum numbers on each axis. Gonna guess they're pretty far off from 1800. It'd be reasonable to think that what you're supposed to do here is take those maxes and mins and plug them into evdev-joystick - I tried that and oh boy no that is not the solution At All, that gives you incredibly neurotic joysticks. Instead we're just using those numbers to get a rough idea of the adjustments we'll want to make.
Assuming we're trying to correct a drift-from-centre problem, and our deadzone adjustment does nothing at all, what we want to do is widen the gap between the minimum and maximum. Work on one stick at a time, one axis at a time.
Axis 0: Left stick, -L, +R Axis 1: Left stick, -U, +D Axis 3: Right stick, -L, +R Axis 4: Right stick, -U +D
Example: return the X-axis of the left stick to default out-of-the-box calibration:
evdev-joystick --evdev /dev/input/event4 --axis 0 --minimum -1800 --maximum 1800 --deadzone 16 --fuzz 16
Example: desensitize the X-axis of the left stick:
evdev-joystick --evdev /dev/input/event4 --axis 0 --minimum -2000 --maximum 2000 --deadzone 16 --fuzz 16
Example: my left stick drifts right and we want to shift its "centre mark" to the right to compensate:
evdev-joystick --evdev /dev/input/event4 --axis 0 --minimum -1900 --maximum 2100 --deadzone 16 --fuzz 16
Here's the kicker: in between making any of these adjustments, you've gotta reload the joystick config. For example, enter a game, or restart emulationstation - but don't reboot the console, because you'll lose all your adjustments lol. I recommend OpenRCT2 from PortMaster as a good cursor test. So the procedure is to SSH an adjustment, open OpenRCT2, start a game (so you can move the cursor with the left stick and pan the camera with the right), make another adjustment, quit OpenRCT2, see if you can move through menus, make another adjustment if you want, load OpenRCT2 again... and just keep doing that, all day, until it's close enough to perfect that you can live with it. Min and max adjustments need a context change to take effect but fuzz takes effect immediately so play with that a bit I guess.
This will need a LOT of fiddling and testing. It will take a LONG time. Make big coarse adjustments shifting two or three hundred at a go so you can see the effects quickly, and then make increasingly fine adjustments as you go on.
Once you've got things more or less square, you'll wanna do
evdev-joystick --showcal /dev/input/event4
and note down all your values, because they'll be erased when you reboot the console. Now we'll make an udev rule to apply them when you turn the console on.
Shut down, pop out your SD card, stick it in your computer and go to /etc/udev/rules.d/ - you'll have to do this as root. Create a new file; mine's called 30-gulikit-calibration.rules and it looks like this:
ACTION=="add", KERNEL=="input4", ATTRS{phys}=="retrogame_joypad/input0", / RUN+="/usr/bin/evdev-joystick --evdev /dev/input/event4 --axis 0 --minimum -1600 --maximum 2000 --deadzone 400 --fuzz 20", / RUN+="/usr/bin/evdev-joystick --evdev /dev/input/event4 --axis 1 --minimum -1800 --maximum 1800 --deadzone 16 --fuzz 16", / RUN+="/usr/bin/evdev-joystick --evdev /dev/input/event4 --axis 3 --minimum -2000 --maximum 1900 --deadzone 100 --fuzz 10", / RUN+="/usr/bin/evdev-joystick --evdev /dev/input/event4 --axis 4 --minimum -1900 --maximum 2000 --deadzone 50 --fuzz 16"
Fill out your maximums and minimums and fuzzes as appropriate. As you can see, my left stick Y axis was fine, but everything else needed adjustment. I filled out the deadzone numbers for funsies in case that ever starts working.
Once you've got udev rules in place, you won't be able to recalibrate and test on the fly any more, you'll be stuck with modifying your rules file and rebooting between every adjustment. So it's a long, tedious process full of trial and error and iteration and it's a massive pain in the arse, but YES, it is possible to put Hall effect sticks in an RG353V and calibrate them under ArkOS.
Oh wow. It's a process indeed. I wonder if just making these values default for guilikit sticks would do it then?
I don't think Gulikit works to tolerances fine enough that we could do a one-size-fits-all config, hell I've got two radically different sticks in the same package here. They just rely on the Switch having a calibration menu.
I'm real interested in why that deadzone adjustment isn't having any effect. I think if we get to the bottom of that, this'll become much easier.
So it started to drift in OpenRCT2 again lol.
2 days of fiddling later, more critical info:
It seems nothing on this system uses the old joydev API, everything works on the new evdev API, so on the one hand at least there's only one set of calibration to do, but on the other we have to do it with the new API whose calibration tooling still sucks.
That leaves the mystery of why the --deadzone option seems to have no effect at all, and the answer to that question is the dumbest possible answer: the decision of whether or not to listen to the joystick API's idea of where the deadzones should be, is left entirely to software. Yup, you can set up your deadzones at the driver level and the software can just ignore it.
So, to correct stick drift in OpenRCT2 specifically, the entry is in /ports/openrct2/openrct2.gptk, towards the bottom is deadzone set to a thousand, I set mine to 4k and it still drifted because Gulikit sticks suck lol so I whacked it all the way up to 8k.
So I guess we need both a calibration program AND a way for PortMaster/GPtoKB to either take its deadzone considerations from the evdev joystick API or have all the various .gptk files in the ports folder take their deadzone values from some other file somewhere?
Way to complicated for this device imo. Just best to stick the stock sticks or use the hall sticks from the 353m.
Just replaced my knackered stock RG353V joysticks with Gulikit hall effect sticks. These new ones are really sensitive and don't seem to have any dead zone at all, which causes occasional camera drift in OpenRCT2. I spend some time going through various emulators and ports to determine that the problem is deeper than retroarch; moving through menus in EmulationStation also suffers, the right stick needs to be pushed all the way upwards to move up through the menu but it only needs the vaguest of taps to move downwards, in Playstation games I can hit the top left diagonal no problem but the top right doesn't seem to work, that kind of thing - it needs calibrated, is the headline, it needs calibrated at driver level.
So I furtle around the wiki and the setup menu, don't see anything related to joystick calibration, I figure right there's gotta be some driver-level stuff I can do via SSH, so I SSH in and I try and launch jstest/jscal, they're not there, I install them (via the "joystick" meta-package), run "jstest --normal /dev/input/js0", the values coming back off the sticks are all outta whack as expected.
I run "jscal -c /dev/input/js0", run through calibration, rerun jstest and get more reasonable numbers, but EmulationStation is still responding in the same sluggish way to certain directions. I figure it'll want a reboot, so I reboot it, no change, I remember that I didn't use jscal-store to save the calibration data so I run through the whole thing again. I save the calibration data with "jscal-store /dev/input/js0" and get a permissions error, so I do the same again as root, and EmulationStation immediately stops responding to any joystick or button input whatsoever. I reboot via SSH, same behaviour. Except now I can't SSH in anymore because I can't enable remote services without use of the D-pad.
After a bit of headscratching I pop out the SD card, put it in my PC, remove var/lib/joystick/joystick.state and am able to once again control EmulationStation enough to get SSH enabled. I run through all the above steps once again, but this time I still have SSH access, and I can see that running jstest on /dev/input/js0 shows that no new joystick events are being registered.
Volume keys still work as expected in EmulationStation, as does the F+Power shortcut to graceful shutdown.
I get the idea to run evtest on retrogame_joypad, and run through the whole thing again, and confirm that after storing calibration data, even evtest shows no response to joystick or buttons.
At this point I scratch my head some more, chuck some cash in the bucket and decide to ask you to save my dumb ass from myself.
A joystick calibration menu would be GREAT - or if not that, if you could just kinda point me where I need to go to calibrate these things that won't lock up the whole joypad. This isn't an urgent bug yet, but given that these devices shouldn't ever need to be upgraded (why buy a new retro console to play the same old SNES games) and all joysticks eventually wear out, it'll probably become more urgent as time goes by and more people need to put in new sticks.
All the best,
~Dan