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!


Feel like sharing or responding?

Comments or corrections? Toot to me or skeet me!

This blog supports webmentions. If your blog supports webmentions and you've linked to this post, then a mention will have been dispatched to me. These are viewed and published manually, so please allow some time. If you would like to manually send me a webmention, please submit the URL to it here:

Edit page.