Installation
Download the latest release of JoystickXL that corresponds to the version of CircuitPython you’re running. (i.e.
joystick_xl_x.x.x_cp8for CircuitPython 8.x)Extract the files from the downloaded .zip archive.
Copy the
joystick_xlfolder to thelibfolder on your device’sCIRCUITPYdrive.
See also
For additional information on installing libraries, see Adafruit’s Welcome to CircuitPython Guide.
USB HID Configuration
In order to use JoystickXL you have to initialize a custom USB HID device in
the boot.py file on your CircuitPython board.
If boot.py does not currently exist in the root folder on your board’s
CIRCUITPY drive, you can create it using the standard example below:
"""JoystickXL standard boot.py."""
import usb_hid # type: ignore (this is a CircuitPython built-in)
from joystick_xl.hid import create_joystick
# This will enable all of the standard CircuitPython USB HID devices along with a
# USB HID joystick.
usb_hid.enable(
(
usb_hid.Device.KEYBOARD,
usb_hid.Device.MOUSE,
usb_hid.Device.CONSUMER_CONTROL,
create_joystick(axes=8, buttons=128, hats=4),
)
)
This enables JoystickXL along with CircuitPython’s other standard USB HID
devices. The axes, buttons and hats parameters are all set to
maximum values here, but can be lowered if you know you’re going to be
using fewer inputs.
Alternatively, if you’re not using any other CircuitPython USB-HID devices
and don’t want them to appear on the host, you can enable the joystick
device by itself as shown below. (The usb_hid.enable() function always
expects a tuple - even when it is only given a single device.)
"""JoystickXL minimal boot.py."""
import usb_hid # type: ignore (this is a CircuitPython built-in)
from joystick_xl.hid import create_joystick
# This will enable a joystick USB HID device. All other standard CircuitPython USB HID
# devices (keyboard, mouse, consumer control) will be disabled.
usb_hid.enable((create_joystick(axes=8, buttons=128, hats=4),))
Note
Once you’re finished creating or modifying boot.py you will have to
hard reset your CircuitPython board by pressing its reset button or
disconnecting it from power for the changes to take effect.
Once you have boot.py set up correctly (and have hard rest your board!),
you’re ready to start working with JoystickXL! Before you dive into hardware
design and coding, though, you should read over the section on
Verifying Compatibility below.
See also
For more information about customizing USB devices in CircuitPython, you can refer to this excellent guide on Adafruit’s learning system.
Verifying Compatibility
Not all platforms/games/applications support joystick devices with high input counts. Before you spend any time writing code or building hardware for a custom controller, you should make sure the software that you want to use it with is compatible.
Fortunately, JoystickXL has a built-in testing module that can be run right from the CircuitPython Serial Console/REPL to verify compatibility with an operating system, game or application - no input wiring or code.py required!
See also
See Adafruit’s Connecting to the Serial Console and The REPL guides for more information about connecting to - and interacting with - your board.
Assuming you
have set up boot.py as described in the USB HID Configuration section
above, just enter the following two commands at the >>> prompt in the
CircuitPython REPL to fire up the JoystickXL test console:
Adafruit CircuitPython 7.0.0-alpha.5 on 2021-07-21; Adafruit Trinket M0 with samd21e18
>>> from joystick_xl.tools import TestConsole
>>> TestConsole()
When the test console loads up, you will be greeted with the following:
JoystickXL - Test Console
Using 1-based indexing.
Button Clicks = 0.25s
Test Button = board.D2
Enter command (? for list)
:
From here, you can manually activate any axis, button or hat switch and see the
results on the host device. To see a list of available commands, type ? at
the prompt and press enter. The available commands are:
a: Axis commands[i]u: Move axisifrom idle to its maximum value and back. (ex.a1u)[i]d: Move axisifrom idle to its minimum value and back. (ex.a4d)t: Test all configured axes by simulating movement on them one at a time. (ex.at)
b: Button commands[i]: Click buttoni. (ex.b12)t: Test all configured buttons by simulating clicking them one at a time. (ex.bt)
h: Hat Commands[i]u: Click hat switchi’sUPbutton. (ex.h1u)[i]d: Click hat switchi’sDOWNbutton. (ex.h3d)[i]l: Click hat switchi’sLEFTbutton. (ex.h0l)[i]r: Click hat switchi’sRIGHTbutton. (ex.h2r)[i]ul: Click hat switchi’sUP+LEFTbutton. (ex.h1ul)[i]ur: Click hat switchi’sUP+RIGHTbutton. (ex.h3ur)[i]dl: Click hat switchi’sDOWN+LEFTbutton. (ex.h0dl)[i]dr: Click hat switchi’sDOWN+RIGHTbutton. (ex.h2dr)t: Test all configured hat switches by clicking each position one at a time. (ex.ht)
t= Test all configured axes, buttons and hats by cycling through their states one at a time.0= Switch to 0-based indexing1= Switch to 1-based indexingp[t]= Set button press time. (ex.p150= 1.5 second button presses)q= Quit the test console
Note
By default, the test console uses 1-based indexing, which means that
the first axis is 1, first button is 1, and so on. If your host
device or test application uses 0-based indexing (the first input is
0), you can switch the test console to use the same numbering scheme
with the 0 and 1 commands.
If you’re using a joystick test application (one that shows all of the
available inputs and their current states), you can use the t command
to automatically cycle through all available inputs and make sure they register
in the test app. You can also test individual input types with their
corresponding test commands, at, bt and ht.
To test compatibility with a particular game you should be able to go to
that game’s input configuration settings, select your JoystickXL device
(likely labelled CircuitPython HID) and attempt to assign inputs to
functions. Ideally, the game uses a click to assign system where you
select the desired function, then move/click the input you want to assign to
it. If so, you can use the corresponding test console command (ex. a2u,
b7, h3d, etc.) to trigger the desired input and make sure it registers
in-game.
Warning
Make sure you start the JoystickXL test console before you start the application you want to test it with on your host. If you start the application on the host first, it may not detect the joystick.
If the application you are trying to test has to be in-focus to capture
joystick events it will not capture events generated from the test console
because your serial terminal will be in-focus while you are typing in it.
For cases like these, the test console provides a single digital input - by
default on pin D2 (GP2 on RP2040-based devices) - which will repeat
the last typed command when activated. You can either hook up an actual
button, or just short the pin to ground to trigger commands as needed. In
the game example above, you would enter the desired command in the test
console and press enter, then switch to the game and use the button input to
trigger that command while the game is in focus. If needed, the button pin
can also be changed when the test console is started as follows:
Adafruit CircuitPython 7.0.0-alpha.5 on 2021-07-21; Adafruit Trinket M0 with samd21e18
>>> import board
>>> from joystick_xl.tools import TestConsole
>>> TestConsole(button_pin = board.D7)
See also
Joystick Testing Applications
(Windows) Pointy’s Joystick Test Application (requires the Microsoft DirectX End-User Runtimes)
(Browser-based) gamepad-tester.com (Works with up to 6 axes, 32 buttons and 1 hat switch.)
(Linux) jstest (Part of the
joystickpackage - works with up to 7 axes, 80 buttons, no hat switches)
What Next?
With your configuration in boot.py complete, and compatibility with your
desired host application confirmed, you’re ready to start building and coding!
The building part is up to your skills and imagination (and beyond the scope of this documentation). Adafruit has some excellent CircuitPython-specific guides that can help with the wiring part:
For Buttons/Hat Switches - CircuitPython Digital In & Out
For Axes - CircuitPython Analog In
(Don’t worry so much about the code parts in those guides - JoystickXL handles configuration and processing for standard analog/digital inputs for you - although it doesn’t hurt to know what’s going on under the hood!)
Adafruit also carries some excellent button, switch, rocker, and axis hardware in their store.
The coding part is where JoystickXL comes in. Check out the Examples section to see how it’s done. Reading through the first couple of examples should give you a pretty good sense of how to get started. If your custom controller has no more than 24 buttons, you may be able to use the More Inputs example as-is!
If you need to dig deeper into JoystickXL’s inner workings, check out the API documentation.
Good luck, have fun, and happy coding!