Qubyte Codes

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!