It's never been easier to create adaptive controls to play video games. For gamers with particular needs not met by standard gaming controllers, the Microsoft Xbox Adaptive Controller (XAC) is a fantastic option for managing alternative inputs.

In this guide, we'll learn how to build our own interconnections between large buttons, foot pedals, analog joysticks, and limit switches and the XAC's button inputs.

XAC is designed to work with the Xbox One series of consoles and Windows 10. However, many people have sucessfully used it on other systems by adding a wireless controller adapter to translate between standards.
The basic switch inputs in this guide do not require any soldering, but as you build more complex XAC projects, some soldering skills can come in handy!

Assistive Technology Resources

There are many great resources out there for people to learn more about AT for gamers. Here are a few:

If you're interested in helping build adaptive controllers, AT Makers can help you get connected with people in your areas. They've also got great guides on building adaptive connectors and switch testers.

The support of Bill Binko of AT Makers, and Bryce Johnson of Microsoft Devices have been incredibly helpful in creating this guide! Thanks guys!

If you're just learning about XAC, here are a couple of good videos to watch:

Parts

You'll need to a Microsoft Xbox Adaptive Controller as well as an Xbox One or Window's 10 PC to use this guide. Additionally, here are some of the switches, buttons, joysticks, pedals, wiring, connectors, and supplies you can use to create your own inputs:

1 x Mini Analog Joystick
10K Potentiometers
1 x Foot switch
momentary button, bare wires
1 x Small Arcade Joystick
with four switches
1 x Magnetic contact switch
door sensor/reed switch
1 x Micro Switch w/Wire
Three Terminals

You can also have a look at our many, many other buttons!

Tools

Here are some useful tools for use when making adaptive tech inputs:

Angled shot of a Digital Multimeter - Model 9205B+.
This massive multimeter has everything but the kitchen sink included. It's a great addition to any workbench or toolbox.  It's low cost, simple to use, and has a big clear...
$17.50
In Stock
Open case of Precision screwdriver set.
Break seals! Void warranties! With this handy screwdriver set at your hands, all hardware you touch will open up and reveal their secret innards.This set contains 6...
$7.95
In Stock
Red and black multi-size wire stripplers, closed
These are the finest wire strippers we have used, and if you have to do a lot of wiring, you will agree! They have soft rounded grips - very comfortable to use, and precision ground...
$17.50
In Stock

If you're new to the Xbox Adaptive Controller, have a look at these resources:

If you need to dive into deeper details, check out these Xbox Adaptive Controller Input Specifications. These are incredibly helpful in detailing the pinouts and voltages for all of the ports, particularly the analog ports for joystick control.

The XAC works just like a standard Xbox controller in terms of wireless connection with the Xbox, however it only sports a few of the typical buttons -- D-pad (6) , A button, B button, menu (3), Xbox button (1), menu button (3), and view button (2).

hacks_07dfa2ea-c90e-47e7-86e2-ccc75307726e.png
https://support.xbox.com/en-US/xbox-one/controllers/get-to-know-adaptive-controller

All of the missing inputs, along with the ones already physically present, can be controlled by external devices plugged into the 3.5mm jacks along the back of the XAC.

For example, you can see here that the Y, X, B, and A buttons are all represented as 3.5mm jacks, where you can plug in four larger buttons if needed.

Thanks to the Copilot Mode, you can use a standard Xbox controller in tandem with the XAC, so two users can work together as a single player, or one use can use both if that suits their needs.

Next, we'll look at the standards used with these jacks so you can interface your own digital buttons, switches, and analog devices with them.

The XAC can also use HID joystick devices plugged into the USB ports on either side -- we won't be covering this in this guide.

Digital Input Standard

The 3.5mm inputs jacks on the XAC allow you to connect any type of switch that can open and close a circuit between the internal Ground and a 1.8V pin that is internally read on the device. These pins have internal-pull up resistors, so you can think of them just like you do any switch used in a microcontroller project.

These jacks are a standard stereo audio-type jack, and have Tip, Ring, Sleeve (TRS) connections. However, only Tip and Sleeve contacts are used.

So, in order to press a button on a digital input port, we simply need to ground the tip to the sleeve.

Represented another way, we can see that the Tip and Sleeve wires coming from a typical stereo cable can be shorted via a switch or button to create the connection that signal a button press.

Analog Input Standard

There are four jacks on the XAC that can accept variable resistance analog inputs, such as potentiometers -- X1, X2, LT, and RT. These map to the left thumb stick, right thumb stick, left trigger, and right trigger.

In order to read dual potentiometers and provide ground and reference voltages, these ports require the use of a four-pole TRRS plug. This is what is commonly found on mobile phone earbuds that include a microphone.

This is how the connections are used:

  • Tip = wiper output from potentiometer 1 for X axis
  • Ring 1 = wiper output from potentiometer 2 for Y axis
  • Ring 2 = Ground
  • Sleeve = 3.3V reference voltage

Here you can see two potentiometers from a typical analog joystick connected to the proper poles of the TRRS jack. Note, one potentiometer is inverted to provide the proper orientation of signal values as used on most joysticks. This isn't of too much concern however, as values can be remapped in software configuration on the game console.

Now that we understand how the inputs work, let's wire up some components!

Interfacing buttons and switches to the XAC's 3.5mm digital input jacks is incredibly easy to do! We only need a way to connect a given button or switch to a 3.5mm mono or stereo cable.

Terminal Block Jack to Cable Plug

The simplest way to connect most buttons and switches is through a 3.5mm stereo audio jack terminal block. Once you connect it to your button, then you can simply run any 3.5mm stereo cable between it and the chosen port on the XAC.

hacks_2791-01.jpg

hacks_2791-00.jpg

Here we see the connections needed:

  • N.O. switch to Adapter L (which will contact plug Tip)
  • Common switch to Adapter Gnd (which will contact plug Sleeve)

Optionally, to keep compliance with other adaptive technology devices other than the XAC that use 3.5mm TR mono jacks, it's a good idea to short the Adapter R contact to GND. This isn't necessary for the XAC, but good practice.

Switch to Terminal Block

Here's an example of connecting a large arcade button to the terminal block, using quick connect wires. This is a nice, secure connection that requires no soldering.

Quick Connect Wire to Terminal

 

Use a small screwdriver to bend in the two metal crimp ends a little bit so they can be pulled from the plastic connector housing, we won't be using it.

 

Unscrew the terminal block screws to open the terminals fully, then insert the blue wire into the GND terminal and the white wire into the L terminal.

 

Screw down the terminal screws moderately tight.

Quick Connect Crimp Connectors to Switch

 

Now, slide the white wire crimp terminal connector to the N.O. spade terminal of the switch.

 

Connect the blue wire to the Common connector

3.5mm Cable

 

Plug one end of a TRS 3.5mm stereo cable into the adapter

This button is now ready to be plugged into any of the digital input ports on the XAC and used just like any Xbox controller button!

We'll give it a nice home by re-using a cardboard box as a button housing.

Box Prep

 

Decide where the button will go, then trace the inside of the plastic button shaft nut.

 

Cut out the hole with a hobby knife.

 

Insert the button and push down a bit to make marks with the registration shafts, then poke those holes out with a small screwdriver.

 

Insert the button, then thread on the nut from the inside of the box.

Add Switch and Wire

 

Place the switch into the shaft and twist to lock into place.

 

Add a small hole in the back of the box for the cable.

 

Plug the cable in through the box and into the adapter.

 

Add strain relief with a zip tie.

The button and box are ready to go, time to plug it in and test it out!

Here, we're plugging it in to the X button jack on the XAC.

You can use this method with any type of switch or button. Here are a few other examples.

Light Touch Limit Switch

The switch shown takes very little pressure to activate, which may make it good for adapting to chin or mouth activation (with appropriate adaptation) as well as light pressure activation from other sources.

Foot Pedal

The Adafruit foot pedal has a good activation switch inside and can be easily wired to a TRS plug.

To use the footswitch as a normally open, momentary switch, simply connect the white wire to the Adapter GND terminal and the red wire to Adapter L. You can leave the black wire unconnected.

If you have a reason to use it as normally closed, so that a button is pressed constantly unless you tap the switch, use the black wire in the L terminal and ignore the red wire.

Hefty On Off Switch

This one is unique in that it is not a momentary switch, but instead latches in the on or off position. This may be useful for cases where the player wants to "hold" a button for long periods of time, such as an accelerator pedal in a driving game, and doesn't plan to "feather" the throttle too much.

Open the case with the thumb screw and remove the top.

 

Wire from the Adapter L and GND positions to two terminals across each other in the switch.

 

Tuck in the wires neatly so the don't impeded the button mechanisms, and place the adapter in the case cutout (remove plastic plug first).

 

Close the case and replace the thumb screw.

 

Plug in a 3.5mm stereo cable.

Soldered Wire Connections

In cases where you want a soldered connection, you can use the 3.5mm stereo pigtail cable instead. It has pre-tinned wires to solder to your buttons and switches.

Use a multimeter in continuity mode to determine which wires are tip and sleeve, then solder those to the NO and GND of your button or switch.

 

In this case, the red and white wires are tip and sleeve, and we'll ignore the copper non-insulated wire (it can be trimmed or bridged to sleeve).

Analog inputs are a bit more complex than digital. They require either one or two variable resistors to be used as triggers or thumb sticks, respectively.

Let's add a joystick to the X1 or X2 ports, which can control the two thumb sticks. This joystick is really just a pair of potentiometers, one for the X-axis that is controlled by horizontal movement of the stick, and the other for Y-axis motion achieved through vertical motion of the stick. It's capable of mixing those motions to partial values of both potentiometers simultaneously for smooth motion, and has a spring return to bring it to center when you let go.

From our previous look at the XAC Standards we saw that we'll use this following connection schematic:

Again, note how we're reversing the direction of the second potentiometer to mimic the value behavior of a typical joystick.

Wiring

We'll first connect the ground and reference voltage tabs of the pots so we only need four, not six wires.

Next, we'll use four long lengths of silicone sheathed stranded wire. These are color coded for ease of explanation in this guide, however, they are unruly and could get tangled easily, so you would want to use some wire loom to neaten them, or get some appropriate four-conductor wire for your own use. (Old USB cables can be a very good source for this once you cut off their ends!)

Strip some insulation from the four wires.

 

Add some heat shrink tubing to each wire.

 

Solder the black, green, and red wire's as shown.

 

Solder the blue wire only to the other potentiometer.

 

Heat the shrink tubing.

Add Terminal Adapter

Now, screw in the four wires as shown. Ignore the markings on the adapter, those refer to the expected use as a stereo + microphone adapter, not a joystick for the XAC!

Plug in the joystick to X1 or X2 on your Xbox Adaptive Controller and you're ready to play!

Note, you should be able to use a similar wiring scheme to adapt a PSP thumbstick like this one.

As you can imagine, every gamer with assistive tech needs will want potentially unique solutions, so this is just a small set of possible controls you can build, and some of the fundamental techniques for getting started.

USB Inputs

As mentioned previously, this guide does not go into USB HID joysticks, but there is some work being done by Bill at AT Makers and our own Dan Halbert to bring CircuitPython HID joystick drivers into use with the XAC and Circuit Playground Express boards. Stay tuned!

The Xbox Adaptive Controller (XAC) has two USB ports on the side for use with USB joysticks -- these are designed to allow alternative hardware to replace the left and right thumbsticks of a typical gaming controller. Rather than be constrained by the commercially available USB joysticks, you can use the TRRS Trinkey to design custom solutions.

In this example, a typical X/Y dual potentiometer joystick breakout is read by two analog pins on the TRRS Trinkey. The Trinkey is running CircuitPython and emulating an XAC-compatible HID gamepad. You can substitute your own analog inputs, such as joystick/thumbstick modules, soft potentiometers, and more, as well as adjust the code to meet your needs.

Angled Shot of the Adafruit TRRS Trinkey.
It's half USB Key, half TRRS breakout... it's the Adafruit TRRS Trinkey specifically designed for Assistive Technology hackers and...
$9.95
In Stock
2-Axis Joystick Thumbstick with breakout board
This mini-kit makes it easy to mount a PSP/Xbox-like thumb joystick to your project. The thumbstick is an analog joystick - more accurate and sensitive than just 'directional'...
$5.95
In Stock
Angled shot of a A/V and RCA (Composite Video, Audio) Cable for Raspberry Pi.
This A/V RCA Cable for Raspberry Pi is a great way to turn your Pi 3, 2, A+ or B+'s output into a full on composite video and audio device.  Simply connect the cable to your...
$4.95
In Stock
Angled shot showing dual potentiometers
Sometimes a simple analog control device can be the perfect tactile solution for your project, but they can be surprisingly hard to come by. Luckily we've found a low-cost,...
$19.95
In Stock
Top shot of a feather, a humidity sensor, a potentiometer and an I2C quad board mounted on to the grid.
With most of our dev boards, sensors and feathers now sporting plug-and-play stemma QT ports it can be very fast to...
$4.95
In Stock

Assembly

Wiring

Any of the four TRRS pins of the TRRS Trinkey can be assigned as digital in/out or analog in. We'll set the TIP and RING_1 as analog inputs to read the two joystick pots, and RING_2 and SLEEVE as ground and Vcc respectively. 

Cable Wiring

Use a multimeter's continuity tester to check the wire mapping of your TRRS cable (I used a TRRS to AV cable with the RCA jacks cut off, although you can also buy them pre-cut usually sold as "replacement 3.5mm TRRS cables"), then solder the following:

  • Cable TIP to Xout
  • Cable RING_1 to Yout
  • Cable RING_2 to GND
  • Cable SLEEVE to Vcc

Plug In Joystick

Plug in the joystick to the TRRS Trinkey.

CircuitPython Usage

To use with CircuitPython, you need to first install the xac_gamepad library and XACsettings.py into the lib folder onto your CIRCUITPY drive. Then you need to update code.py with the example script, and save the boot.py onto the root of the CIRCUITPY drive.

Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and files in a zip file. Extract the contents of the zip file, and copy the entire lib folder and the code.py and boot.py files to your CIRCUITPY drive.

CIRCUITPY
# SPDX-FileCopyrightText: 2024 by John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# adapted from Bill Binko's Chording Switches code
'''
Xbox Adaptive Controller USB port joystick
Use a two axis joystick, or combo of pots, soft pots, etc.
wired to TRRS 3.mm plug:
 Tip = X
 Ring 1 = Y
 Ring 2 = GND
 Sleeve = VCC
'''
import time
import array
import board
import analogio
import digitalio
#Custom version of Gamepad compatible w/the XBox Adaptive Controller (XAC)
import xac_gamepad
# pylint: disable=wildcard-import, unused-wildcard-import
from XACsettings import *

time.sleep(1.0)
gp = xac_gamepad.XACGamepad()

class RollingAverage:
    def __init__(self, size):
        self.size=size
        # pylint: disable=c-extension-no-member
        self.buffer = array.array('d')
        for _ in range(size):
            self.buffer.append(0.0)
        self.pos = 0
    def addValue(self,val):
        self.buffer[self.pos] = val
        self.pos = (self.pos + 1) % self.size
    def average(self):
        return sum(self.buffer) / self.size

# Two analog inputs for TIP and RING_1
hor = analogio.AnalogIn(board.TIP)
vert = analogio.AnalogIn(board.RING_1)

# RING_2 as ground
ground = digitalio.DigitalInOut(board.RING_2)
ground.direction=digitalio.Direction.OUTPUT
ground.value = False

# SLEEVE as VCC (3.3V)
vcc = digitalio.DigitalInOut(board.SLEEVE)
vcc.direction=digitalio.Direction.OUTPUT
vcc.value = True

def range_map(value, in_min, in_max, out_min, out_max):
    # pylint: disable=line-too-long
    return int(max(out_min,min(out_max,(value - in_min) * (out_max - out_min) // (in_max - in_min) + out_min)))

# These two are how much we should smooth the joystick - higher numbers smooth more but add lag
VERT_AVG_COUNT=3
HOR_AVG_COUNT=3
#We need two Rolling Average Objects to smooth our values
xAvg = RollingAverage(HOR_AVG_COUNT)
yAvg = RollingAverage(VERT_AVG_COUNT)

gp.reset_all()


while True:
    x = range_map(hor.value, 540, 65000, 0, 255)
    y = range_map(vert.value, 65000, 540, 0, 255)

    #Calculate the rolling average for the X and Y
    lastXAvg = xAvg.average()
    lastYAvg = yAvg.average()

    #We know x and y, so do some smoothing
    xAvg.addValue(x)
    yAvg.addValue(y)
    #We need to send integers so calculate the average and truncate it
    newX = int(xAvg.average())
    newY = int(yAvg.average())

    #We only call move_joysticks if one of the values has changed from last time
    if (newX != lastXAvg or newY != lastYAvg):
        gp.move_joysticks(x=newX,y=newY)
        # print(hor.value, vert.value)  # print debug raw values
        # print((newX, newY,))  # print debug remapped, averaged values
    #Sleep to avoid overwhelming the XAC
    time.sleep(0.05)

Use It

Once you've coded the TRRS Trinkey you can plug it into either USB A port on the XAC and use it for gameplay on your Xbox or Windows machine. It will show up as either thumbstick in-game. Build a second one for the other stick if you like.

You can see it in action here:

This guide was first published on Jan 11, 2019. It was last updated on Jun 16, 2024.