The source code and some artwork files are available from my local download or from github.com/larsi-org/MAME-Interface
I decided to build only a single player controller with just one joystick and a few buttons. After a whole day of on-line "research" I decided to have 6 play buttons (instead of 8), 2 Player1 control buttons, and 4 system control buttons. I use the following mapping:
# | Function | Keyboard Code | Teensy Pin | Teensy Port |
---|---|---|---|---|
1 | Player1 Up | Up | 0 | PB0 |
2 | Player1 Down | Down | 1 | PB1 |
3 | Player1 Left | Left | 2 | PB2 |
4 | Player1 Right | Right | 3 | PB3 |
5 | Player1 Button1 | L-Ctrl | 4 | PB7 |
6 | Player1 Button2 | L-Alt | 5 | PD0 |
7 | Player1 Button3 | Space | 6 | PD1 |
8 | Player1 Button4 | L-Shift | 7 | PD2 |
9 | Player1 Button5 | Z | 12 | PD7 |
10 | Player1 Button6 | X | 13 | PB4 |
11 | Player1 Start | 1 | 14 | PB5 |
12 | Player1 Coin | 5 | 15 | PB6 |
13 | Pause | P | 16 | PF7 |
14 | UI Select | Enter | 17 | PF6 |
15 | UI Cancel | Esc | 18 | PF5 |
16 | Config Menu | Tab | 19 | PF4 |
That means I have a total of 16 inputs. I want to use some buttons multiple times - Button1 is used again under the 6 buttons (as a fake 7th button for NeoGeo games) and Button1 and Button2 are also on the left and right for Pinball games. So I need a total 9 play buttons which are all red. The control buttons are all white with the exception of the Player1 Start button, which has a special symbol.
There are many great sites where you can buy all kinds of buttons and joysticks, like Ultimarc, ArcadeShop.de, Suzo-Happ, or X-Arcade. I decided to use SparkFun's Short Handle Arcade Joystick and Suzo-Happ's Competition Pushbutton for the play buttons and the regular Pushbutton for the control buttons.
The next step was to find an enclosure for the button, the joystick, and the electronics. I wanted something better than a plastic box, maybe something a little more steampunk... After looking around I settled for getting a "Vintage Wooden Lap Desk" on eBay. The slightly slanted surface is perfect. I applied my layout by printing it out and marking the center holes with a pushpin. After this I started with a small drill and went up a few steps until I had drilled all holes with a ¼" drill. The last step was to drill with a 1 1/8 " drill, which was more difficult than I anticipated. I had to recharge the drill a few times and unfortunately the holes were not as clean as I had hoped. Basically I had scratched the top surface badly.
![]() |
![]() |
![]() |
To hide my mistakes from the last drilling and to label the button I decided to decoupage some paper on top of the wood (check out the download section). I had to cleanup the wooden surface and glue the mask over it. The next day I sealed the surface and I repeated the sealing process the next two days.
I thought about just using the popular I-PAC 2 or the easy to use Arcade Controller. After reading about the V-USB project and related sub projects (like Tinkerlog's Tupperware Arcade Controls) I wanted to to design my own. But then I found this great little board called Teensy. You can buy it from adafruit for $20. It works perfectly well with the Arduino interface, but you have to download the Teensyduino patch for your Arduino version and the Teensyloader. Here is a really nice tutorial and here is my source for the MAME system (check out the download section):
#define REPEATRATE 100 // milliseconds const byte pin_P1_UP = 0; const byte pin_P1_DOWN = 1; const byte pin_P1_LEFT = 2; const byte pin_P1_RIGHT = 3; const byte pin_P1_B1 = 4; const byte pin_P1_B2 = 5; const byte pin_P1_B3 = 6; const byte pin_P1_B4 = 7; const byte pin_P1_B5 = 12; const byte pin_P1_B6 = 13; const byte pin_P1_START = 14; const byte pin_P1_COIN = 15; const byte pin_PAUSE = 16; const byte pin_SELECT = 17; const byte pin_CANCEL = 18; const byte pin_CONFIG = 19; const byte pin_LEDOutput = 11; //Variables for the states of the MAME buttons byte buttons[] = { pin_P1_UP, pin_P1_DOWN, pin_P1_LEFT, pin_P1_RIGHT, pin_P1_B1, pin_P1_B2, pin_P1_B3, pin_P1_B4, pin_P1_B5, pin_P1_B6, pin_P1_START, pin_P1_COIN, pin_PAUSE, pin_SELECT, pin_CANCEL, pin_CONFIG }; byte keys[] = { KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_A, KEY_S, KEY_D, KEY_Z, KEY_X, KEY_C, KEY_1, KEY_5, KEY_P, KEY_ENTER, KEY_ESC, KEY_TAB }; #define NUMBUTTONS sizeof(buttons) void setup() { //Setup the pin modes. pinMode( pin_LEDOutput, OUTPUT ); //Special for the Teensy is the INPUT_PULLUP //It enables a pullup resitor on the pin. for (byte i = 0; i < NUMBUTTONS; i++) { pinMode(buttons[i], INPUT_PULLUP); } } void loop() { // //debugging the start button... digitalWrite ( pin_LEDOutput, digitalRead(pin_P1_START)); //Progess the MAME controller buttons to send keystrokes. fcnProcessButtons(); } //Function to process the buttons from the SNES controller void fcnProcessButtons() { static long currentkey = 0; byte nothingpressed = 1; // run through all the buttons for (byte i = 0; i < NUMBUTTONS; i++) { // are any of them pressed? if (! digitalRead(buttons[i])) { nothingpressed = 0; // at least one button is pressed! // if its a new button, release the old one, and press the new one if (currentkey != keys[i]) { Keyboard.set_key1(0); Keyboard.send_now(); Keyboard.set_key1(keys[i]); currentkey = keys[i]; Keyboard.send_now(); } else { // the same button is pressed, so repeat! Keyboard.set_key1(keys[i]); Keyboard.send_now(); delay(REPEATRATE); } } } if (nothingpressed) { // release all keys Keyboard.set_key1(0); Keyboard.send_now(); } }
First I thought of a very simple and solderless method to wire up all the buttons. I bought a 100 pack of female .187 solderless terminals and 2 × 40 pin male break away header. I removed the plastic part of terminals and cut up the headers so that I have 2 pin connectors. Both parts can be crimped together with some pliers.
This did work, but sometimes the connection got loose, so I decided to just solder the 2 pin connectors directly to the switches. I have 15 buttons and 1 joystick (4 buttons) and I need 2 of these connectors for each buttons, which means I had to solder 38 connectors.
![]() |
![]() |
The buttons can be connected to the controller board with dual-female jumper wire. Because I have 2 pins, I can easily daisy chain all button grounds to just a single ground to the controller board.
![]() |
![]() |
I can also daisy chain the triple button B1 and the double button B2 and connect the rest with dual-female jumper wire. I used some 4 pin to 4 × 1 pin cables that allowed me to connect the the buttons in groups of 4 to the controller board.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
I learnt a lot. About woodwork, decoupage, PCBs, and electronics. I spent 12 hours and a total of $100 on this controller. I think next time I might just get a X-Arcade Dual for $130... Or maybe not |