Introduction

When I started playing Star Citizen [1] (SC) I found the key combinations required during “flight” overwhelming. I saw this problem as something that could be overcome by designing a physical “control panel” which would have the most important functions mapped to a dedicated button.

Note: I only outline setting up the SC “flight” functionality as I primarily use keyboard and mouse for other parts of the game such as First-Person Shooting (FPS).

Joysticks

The first thing I decided was that I wanted my flight control to be a HOSAS (Hands On Stick And Stick) rather than the perhaps more common HOTAS (Hand On Throttle And Stick) setup. My rationale is that the game is primarily space based and the additional axes that the dual sticks afford, provide fine control of all three “strafing” directions as well as all three rotational “Pitch, Roll and Yaw” rotations.

Having decided on the HOSAS setup, the next question was which joysticks I wanted to use. I decided upon two Thrustmaster T.16000m joysticks. The factors that decided this choice were:

  • they are very affordable,
  • they are quite easily sourced,
  • they can be configured as left or right handed, and
  • they are very accurate.

My Dual T.16000m Layout

Control Panel Development

Hardware

The first step in designing the control panel was to determine how many buttons I wanted to implement. I settled at around 60 after deciding which SC functions would be mapped to the panel itself, the buttons on the sticks, neither or both.

My Control Panel Layout

Next, I chose the type of buttons and the enclosure I wanted and ordered those. Whilst I was waiting I started thinking about how to drive it. For this, I chose the Arduino as the micro-controller platform as I’ve used them previously, they are simple, and they work straight out of the box.

The specific Arduino I chose was an “eBay knockoff” of the 5V/16MHz Pro Micro [4]. This is based on the Leonardo range of Arduinos which allow Human Interface Device (HID) emulation as the micro-controller itself (ATmega32u4) has built-in USB communication, which eliminates the need for a secondary processor.

The only limitation with Arduinos for a project like this is that they provide limited general purpose Input/Output (GPIO or I/O) pins. There are many workarounds including wiring the buttons in a matrix to and cyclically read them by row. This would’ve added complexity so the workaround I chose for this was to use external devices to add more, as this reduced the complexity of the Arduino software and the hardware required to support the switches.

The Microchip MCP23017 IC [2] is a 16-bit I/O expander with an I2C serial control interface. It works in a similar manner to a standard parallel to serial shift register. The differences (and the reasons I chose these chips) are as follows:

  • Multiple chips can be used on the serial bus and each adds 16 additional I/O pins;
  • The 16 I/O pins include pull-up resistors meaning that discrete resistors for each button weren’t needed; and,
  • Adafruit’s MCP23017 Library makes interfacing with these pins as easy as it is with the built-in Arduino pins.

Control Panel Driver Board

I have used four MCP23017 ICs giving me 64 additional I/O pins, sacrificing only 2 of the Arduino GPIO pins for I2C serial communication with the chips.

With sufficient I/O pins available (and my buttons and enclosure in-hand), I assembled amd wired it all up.

Control Panel Wiring

Firmware

I am providing basic examples of how to use the libraries in this section.

Here is a bare-basic example of how to use the MCP23017 Library [3]:

#include <Wire.h>
#include "Adafruit_MCP23017.h"

// Create a MCP23017 object
Adafruit_MCP23017 myMCP;

void setup() {
  // Setup the MCP with address 0
  myMCP.begin(0);
  // Sets pin 0 of the MCP 
  // to be an input with pull-up resistor
  myMCP.pinMode(0, INPUT); 
  myMCP.pullUp(0, HIGH);
}

void loop() {
  // Reads the current state of pin 0 on the MCP
  bool currentInputState = myMCP.digitalRead(0)
  // Do something with it...
}

Initially, the Arduino HID emulation was limited to Keyboard and Mouse functionality but MHeironimus has developed the HID Joystick Library.

At the time I am writing this, the release version of the Joystick Library is v1.0.1 which allows multiple or single joysticks with a maximum or 32 buttons to be emulated by the Arduino. I wanted to emulate only one joystick but I wanted at least 60 buttons. Luckily, the library has a (currently Beta) version 2.0 which allows the number of buttons to be specified.

Note: Arduino IDE 1.6.6 (or above) is required for this library.

Here is a bare-basic example of how to use the HID Joystick Library [5]:

#include <Joystick.h>

// Create a Joystick object
Joystick_ myJoystick;

void setup() {
  // Setup the Joystick
  myJoystick.begin();
}

void loop() {
  // State of the button (read something)...
  bool buttonState = true;
  // Report the first (0) button state to buttonState
  myJoystick.setButton(0, buttonState);
}

My Arduino firmware is available here. When loaded, the Arduino is listed as a standard USB Game Controller in Windows (run command: joy.cpl). The standard utility shows only the first 32 buttons. To see more, I had success with Pointy’s Joystick Test [6].

PC Software

At this point three controllers were visible to the computer; two T.16000m joysticks and the control panel. There were multiple limitations to simply mapping these three controllers directly:

  1. A maximum of 50 buttons are allowed per joystick in SC which means that not all buttons on the control panel could be used.
  2. Only one button can be mapped to each function.
  3. Any custom button functions must be implemented on the Arduino, requiring all actions be mapped to an Arduino “joystick button”.

To remove these limitations, multiple options exist. The solution I chose is one I discovered on the SC forums. WhiteMagic’s Joystick Gremlin was developed to utilize “virtual joysticks” which can be linked to the physical joysticks in many ways.

vJoy

Once configured, vJoy is a set and forget tool. It creates the virtual joysticks and unless troubleshooting or changing the vJoy parameters, there is little evidence that it is even installed. I set it up as follows:

  1. Install vJoy [8].
  2. Launch to configuration interface and create 2 virtual joysticks (1 tab each).
  3. For each joystick, allocate:
    • 3 axis (X, Y, Z)
    • 3 rotations (Rx, Ry, Rz)
    • Slider
    • Hat
    • 50 buttons (maximum allowed in SC)
  4. Activate vJoy.

vJoy also include a utility to monitor the states of the vJoy joysticks. This is found in the start menu as Monitor vJoy.

The virtual joysticks were now shown in the list of USB game controllers.

Joystick Gremlin

Joystick Gremlin allows mapping of joystick controls to the virtual joysticks’ controls. This mapping can take many forms. Step 2 below describes the types of mapping possible with this tool.

  1. Install Joystick Gremlin [7].
  2. Assign the buttons/axes/sliders/hats of each physical controller (accessible by tabs) to vJoy or keyboard actions. This can be done in various ways:
    • Remap: physical action (eg: button press) is cloned to the virtual action (eg: vJoy button press, keyboard button press, etc.
    • Macro: physical action triggers a pre-programmed sequence of virtual actions.
    • Custom Modules: allow a vast array of options by writing code which performs virtual actions using various triggers including physical actions and time cycles. These modules are limited only by your familiarity with python code (see my modules for examples).
  3. Activate Joystick Gremlin (or trigger activation by focus on Star Citizen.

Extensive documentation on the use of Joystick Gremlin is available on WhiteMagic’s project page.

My Joystick Gremlin configuration (.xml) and and custom modules (.py) are available here and need to be placed in the directory:
%userprofile%\Joystick Gremlin\
Note: These files are created for Joystick Gremlin v5 which is pre-release at the time of writing. Thanks for all of your help WhiteMagic!

SC Joystick Mapper

To map the virtual joysticks (vJoy 1 & 2) to SC keybindings, SC Joystick Mapper [9] can be helpful. It creates an XML file which can be imported into the game.

My SC keybinding (.xml) is available here, and needs to be placed in the directory:
StarCitizen\CitizenClient\USER\Controls\Mappings\

The keymapping is loaded by navigating in the menu to: Options, Keybinding, Advanced Controls Customization. Under Control Profiles, select the keymapping and chose the controllers to load.

Joystick ID Fixer

I created a script which will fix the joystick IDs in all of the configuration files if they change in Windows. It is available here. It’s process is as follows:

  1. Identify all of the joysticks connected by Name.
  2. Resolve which stick is which by the user pulling the left trigger.
  3. Resolve which vJoy is which by checking the button count (made vJoy 2 have 49 buttons, vJoy 1 still has 50).
  4. Check that Joystick Gremlin XML is setup for the correct Windows IDs for the sticks and the control panel.
  5. Check that the Joystick Gremlin modules are setup for the correct Windows IDs for the sticks and the control panel.
  6. Check that the Star Citizen keybinding XML is setup for the correct Windows IDs for the vJoy controllers.
  7. Correct any incorrect IDs in the above files and report it.

Finished Panel

The end result is that I can now utilise all of the functions that the ships provide in Star Citizen with the added bonus of some specialised custom functions.

Finished Panel

Mapping Matrix

I have reworked the spreadsheet I used to keep track of the various functions whilst I was developing this project. It traces each button through it’s various representations from physical button all the way to the key binding it controls in SC. I also includes the type of mapping I’ve used for each within Joystick Gremlin. It is available here.

Lastly, in case you are wondering, my in game moniker is danricho, and if you’ve read this far you are probably already a Star Citizen, but if not use this referral code: STAR-7Y4C-Z2BN and get 5000 free in game credits (and a bonus for me too!).

See you ‘round the ‘verse!

F.A.Q.s

I got many questions when I shared this on Reddit. I’m adding some that I got a few times here. I will only reference the original person who asked it. Thanks for your feedback, everyone!

Q (TankBoyKen): How did you do the labeling?
A: I printed the reverse of the design (mirrored horizontally) onto a sheet of “over head transparency”. I then cut each section including the holes for the buttons on my wife’s paper-craft cutter (this could be done by hand). The sections are placed print down onto the top of the panel and held there by the switches. Placing it face down protects the printing and also “un-mirrors?” the design.

Q (elixin77): Since you are using a hosas set up, wouldn’t the panel be a reach in order to hit a button, especially when you need two hands on both sticks at the same time?
A: I’ve tried to use the buttons on the sticks for the functions I use most while both hands are required for flight. For example, at the moment I have hat up and hat down on my right stick to cycle friendlies and hostiles. Joystick Gremlin allows me to map any number of control inputs to the same function, so I can also map the panel buttons.

Q (Cowbellius): Do you feel it is a little early for me to be putting together a physical control panel when we’re missing so many mechanics (and therefore important buttons)?
A: I had that in mind when I designed the layout of the switches (mostly) on a grid. If needed, I will be able to rearrange (and regroup) functions by reprinting the labels. Off hand I can think of at least one that I will want to add when it’s available… “Reliant Vertical/Horizontal mode toggle” or whatever form that takes!

Q (ASF_Memnoch): Any lighting? I love to play in the dark and would need lit buttons or a small LED on a gooseneck.
A: I have a couple of goosenecked LEDs on my bench (from a cheap LED book light) for that exact reason! It’s still something I’m deciding on as I generally have enough light around me to see the panel.

Q (Solidus_ty): Do you have a link to the switches and buttons that you used?
A: Everything I used is quite common, but here is a quick parts list with where I sourced them:
- Enclosure from Hammond Manufacturing
- Buttons and toggle switches from Futurlec
- Arduino “Pro Micro” clone from eBay - ensure it is ATmega32u4 powered
- MCP23017 from eBay (widely available inc. Futurlec)
- Proto-board from Sure Electronics
- 0.1” 8-way screw terminals from eBay
- Wiring and other miscellany from my random parts box(es)

Q (Obsidianpick9999): Do you have the circuit diagram for that? I want to build something similar so it would be useful to see some examples like yours.
A: I have drawn up the control board ciruit below:

Control Panel Driver Board Circuit Diagram

Reference List

[1] Star Citizen by Cloud Imperium Games
[2] MCP23017 datasheet by Microchip
[3] MCP23017 Arduino Library by Adafruit
[4] 5V/16MHz Pro Micro product page by Sparkfun
[5] HID Joystick Arduino Library by MHeironimus
[6] Pointy’s Joystick Test by Pointy
[7] Joystick Gremlin by WhiteMagic
[8] vJoy by Shaul Eizikovich
[9] SC Joystick Mapper by SCToolsfactory