Making arcade controls: Arduino Leonardo code
Published
I recently got it into my head that I wanted to build an arcade control panel from parts. Specifically, an 8 way digital joystick and a bunch of buttons. How it'll look when finished isn't important at the moment. It's enough now to say that there'll be a joystick, six regular buttons, and two buttons for start and select use.
I decided to use an Arduino Leonardo to accept inputs from the buttons and stick. The Leonardo presents itself as a keyboard to the machine you plug it into, which is perfect for this. The only thing I needed to do is to initialize the pins on the Arduino as inputs with inline resistance, and bind them to the desired keys.
Usually when a programmer thinks "the only thing I need to do", what follows is
three or four times as much effort as predicted. I was surprised this time that
the effort required was so low, particularly given that I've not written any
C/C++ in years. In addition to functions for setting key states, keyboard.h
provides a bunch of useful constants for special keys.
#include <Keyboard.h>
// MAMEish. An array of pin-key pairs.
struct { int pin; int key; } pinkeys[] = {
{ 2, KEY_LEFT_ARROW },
{ 3, KEY_UP_ARROW },
{ 4, KEY_RIGHT_ARROW },
{ 5, KEY_DOWN_ARROW },
{ 6, KEY_LEFT_CTRL }, // Fire 1
{ 7, KEY_LEFT_ALT }, // Fire 2
{ 8, ' ' }, // Fire 3
{ 9, 'a' }, // Fire 4
{ 10, 's' }, // Fire 5
{ 11, 'q' }, // Fire 6
{ A0, '1' }, // start
{ A1, KEY_ESC } // select
};
void setup() {
// Set all used pins to handle input
// from arcade buttons.
for (auto const &pinkey : pinkeys) {
pinMode(pinkey.pin, INPUT_PULLUP);
}
// Initialize keyboard.
Keyboard.begin();
}
void loop() {
// For each pin-key pair, check the
// state of the pin and set the
// associated key state to match.
for (auto const &pinkey : pinkeys) {
if (digitalRead(pinkey.pin) == LOW) {
Keyboard.press(pinkey.key);
} else {
Keyboard.release(pinkey.key);
}
}
}
Since the Arduino is programmed in a dialect of recent C++, range-based for
loops are available, as is type inference with auto
. This meant I could use an
array of instances of an anonymous structure to express the pin-key pairs. Not a
sizeof
in sight!