First of all, have a look at your Beaglebone Black board. So many GPIO ports waiting idlely for some arcade fun! One of the advantages of the Beaglebone Black board over boards like the Raspberry Pi is that lots of GPIO ports are available, more than we need actually if we want to go the simple way: 1 button - 1 GPIO. And as a total beginner in electronics, I wanted to go the simple way!
I wanted to provide a 2-player arcade system (2x 4-way controllers), with enough buttons to emulate up to the Playstation generation (2x 8 action buttons, 2x start buttons), 1 button to "add coins into the slot", and 1 "exit button". 28 "buttons".
Setting up the GPIOs
We have to tell the Beaglebone Black that we will use 28 GPIOs as inputs, activating their internal "pulldown" resistors. This is done by setting a specific device-tree overlay, that tells the system how to configure its ports.
This is explained better than I could by Derek Molloy: http://derekmolloy.ie/gpios-on-the-beaglebone-black-using-device-tree-overlays/. Go check his work, it's great. He doesn't know it, but he deserves a large part of the credit in my Pixbox project! My controller setup is just an application of this tutorial and the related ones.
These documents he made are essential for building your setup: https://github.com/derekmolloy/boneDeviceTree/tree/master/docs
Print them, everything you will ever need is inside.
Anyway, here is the GPIO setup I ended up using:
Button | GPIO | Key event emitted |
---|---|---|
Escape (leave game) | P8_8 | Escape |
Insert coin | P9_15 | 5 |
1P Joystick Up | P8_10 | Up arrow |
1P Joystick Left | P8_14 | Left arrow |
1P Joystick Right | P9_16 | Right arrow |
1P Joystick Down | P8_12 | Down arrow |
1P Start | P8_7 | 1 |
1P Action 1 | P8_9 | A |
1P Action 2 | P8_13 | S |
1P Action 3 | P8_17 | D |
1P Action 4 | P8_26 | Q |
1P Action 5 | P8_11 | W |
1P Action 6 | P8_15 | E |
1P Action 7 | P8_19 | Z |
1P Action 8 | P9_26 | X |
2P Joystick Up | P9_27 | I |
2P Joystick Left | P9_23 | J |
2P Joystick Right | P9_27 | L |
2P Joystick Down | P9_21 | K |
2P Start | P9_11 | 2 |
2P Action 1 | P9_13 | F |
2P Action 2 | P9_14 | G |
2P Action 3 | P9_18 | H |
2P Action 4 | P9_24 | B |
2P Action 5 | P9_12 | T |
2P Action 6 | P9_16 | Y |
2P Action 7 | P9_22 | V |
2P Action 8 | P9_30 | R |
export SLOTS=/sys/devices/bone_capemgr.9/slots
export PINS=/sys/kernel/debug/pinctrl/44e10800.pinmux/pins
echo PixBox > $SLOTS
Of course, you can (and I believe you should) make this automatic by adding this into an executable script in /etc/profile.d.
Plugging the buttons and testing
Joysticks and buttons are basically the same thing: microswitches. They have two pins each, and the electric current passes when the user presses the button/direction.
If you have a look at my device tree overlay definition, you will notice that I set up my GPIOs with a pull-up resistor. Basically, this means that my GPIOs are, by default, in a "high" state (1). Connecting them to the ground sets them in "low" state (0).
All I had to do was linking one pin of my microswitches to the proper GPIO, the other to the ground, adding a "strong" resistor in-between.
I made my first experiments with a basic switch, a 10k resistor and a breadboard. Just plug one pin of your switch to your GPIO (say P8_8, "escape" button in my setup). The other one to the resistor, and the resistor to the ground of you board (P8_1 or P8_2).If you have a look at my device tree overlay definition, you will notice that I set up my GPIOs with a pull-up resistor. Basically, this means that my GPIOs are, by default, in a "high" state (1). Connecting them to the ground sets them in "low" state (0).
All I had to do was linking one pin of my microswitches to the proper GPIO, the other to the ground, adding a "strong" resistor in-between.
For testing purposes, you will want to expose the GPIO as a special file. Go check the documents from Derek Molly, look for P8_8, and you will see that P8_8 is GPIO #67. Now, on your Beaglebone, write the value "67" to /sys/class/gpio/export and what the magic happen:
root@beaglebone:~# cd /sys/class/gpio
root@beaglebone:/sys/class/gpio# ls
export gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport
root@beaglebone:/sys/class/gpio# echo 67 > export
root@beaglebone:/sys/class/gpio# ls
export gpio67 gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport
After you write this value, a gpio67 folder appears. Check its "value" file: root@beaglebone:/sys/class/gpio# cat gpio67/value
1
"1" means "high" state.Toggle your switch, and check the value:
root@beaglebone:/sys/class/gpio# cat gpio67/value
0
Well done, you are one step closer to having your arcade controller!From button events to keyboard events
In practice, we do not want to poll the status of the gpio[whatever]/value files. This does work, but is quite slow. We can do better than that! Actually, GPIO values are stored in specific addresses in memory, and we can access them programmatically.
Ethan Hayon (https://github.com/ehayon/BeagleBone-GPIO) did a great job providing C primitives to configure the GPIOs and access their values, and my implementation (https://github.com/alban-rochel/pixbox-controls/tree/master/service) largely relies on his code.
My code is basically polling the proper addresses, and emitting keyboard events when their states changes. To emit keyboard events, I used the uinput Linux subsystem, check it out! Very simple to use.
The only "smart" thing I did was adding a "debounce" period. "Bouncing" is what happens when you toggle the state of a switch: within a very short amount of time, the electric state may be unstable and oscillate between "high" and "low" values. You definitely don't want these to appear as button presses. So, after each state change (button press or depress), I ignore the button for a very short duration.
And that's it! Feel free to use this piece of code, all you have to do for your specific project is to change the "ADD_BUTTON" calls: the first argument is the key emitted, the second the GPIO, and the third one a debug string.
Actual building of the controller
I used the protocape from Adafruit to solder all my resistors and wires: not much to say about this, it is cheap and easy to use: https://www.adafruit.com/products/572
As for the arcade components, I ordered them on http://www.starcab.net/ . Standard 28mm buttons, Sanwa sticks, everything works (and feels) great!
No comments:
Post a Comment