Mini Pinball
Make an awesomely playable mini pinball, out of an Android tablet, real arcade buttons, some wood and some software!
There are some very good Android pinball applications. But I do not like to play using the touchscreen (I always end up hitting the home or menu icons).
I just needed real buttons, so I built this cabinet. The result is really reactive, and give full justice to these amazing pinball simulators!
There are some very good Android pinball applications. But I do not like to play using the touchscreen (I always end up hitting the home or menu icons).
I just needed real buttons, so I built this cabinet. The result is really reactive, and give full justice to these amazing pinball simulators!
Technical Considerations
Before undertaking the job of building a cabinet, it is necessary to check that all conditions are met.
Events principle
The principle I chose is to simulate finger touches. This will insure a perfect compatibility with all pinball applications (and not only the seldom ones supporting an external keyboard).
The buttons are connected to an USB keyboard controller. The SHIFT keys are detected and converted to touch events.
Tablet connectors
The tablet must have USB host capability, with an USB (or USB-on-the-go) connector. BTW, Android well supports external USB peripherals such as hard drives, keyboards, mice, hubs, etc.
Alternatively, Bluetooth keyboard may work, but I bet that the lag will badly impact the reactivity.
Also, an Arduino with an USB host controller, and directly connected to pinball buttons, may work. It would require ADK support.
Rooting
In order to read and send raw events, the application requires the tablet to be permanently rooted.
IT IS VERY DANGEROUS TO USE A ROOTED TABLET, as malware could virtually access anything, including your personal data and online accounts. Do not run apps requiring rooting, except if you know exactly what they're doing.
Evaluate!
Anyway, make a test before undertaking the project.
Events principle
The principle I chose is to simulate finger touches. This will insure a perfect compatibility with all pinball applications (and not only the seldom ones supporting an external keyboard).
The buttons are connected to an USB keyboard controller. The SHIFT keys are detected and converted to touch events.
Tablet connectors
The tablet must have USB host capability, with an USB (or USB-on-the-go) connector. BTW, Android well supports external USB peripherals such as hard drives, keyboards, mice, hubs, etc.
Alternatively, Bluetooth keyboard may work, but I bet that the lag will badly impact the reactivity.
Also, an Arduino with an USB host controller, and directly connected to pinball buttons, may work. It would require ADK support.
Rooting
In order to read and send raw events, the application requires the tablet to be permanently rooted.
IT IS VERY DANGEROUS TO USE A ROOTED TABLET, as malware could virtually access anything, including your personal data and online accounts. Do not run apps requiring rooting, except if you know exactly what they're doing.
Evaluate!
Anyway, make a test before undertaking the project.
The Software Architecture
Studies
Before ending up with the current design, a few studies have been made:
(*) see http://www.mjmwired.net/kernel/Documentation/input/multi-touch-protocol.txt
Architecture
The final architecture is based on a daemon, that is, a small standalone program (written in C and hence very fast) communicating with a Java service.
The diagram in this step is an UML class diagram, showing the principal classes and entities, and their relations.
pinball_buttons_mapper (aka the daemon) - this is the standalone C program, actually doing all the "real" job: it waits for keyboard events, and generates multitouch events (simulating finger touches on the screen). It reads all its parameters from the compact settings file. The daemon is started by the Java app as root, because it needs such permissions to read/write events directly from /dev/input/eventN device drivers from the underlying Linux OS. The demon is not able to determine the devices to use, screen size and orientation, etc, so it reads these parameters from the settings.cnf file, that was prepared by the Java part. The daemon is able to detect that the settings file has changed and to re-read it automatically.
SettingsActivity - this is the main screen that is shown when starting the program. It lets you set all parameters, and stores them as preferences. It also (re)starts the service, and calls the CompactSettings upon settings changes.
CompactSettings (aka settings.cnf) - writes a copy of the settings, in a very compact format that the daemon can easily read. The settings are in XML, but the compact copy is very much simpler.
TheService - this is Java code running in background, even when no screen of the app is visible. It makes an icon always visible in the Android notification area, and cares for (re) starting the daemon (its role is merely to monitor the daemon, and call the settings screen).
Mapper - this is a Java class designed to install the daemon, and (re)start it.
BroadcastReceiver - this is needed to make the app automatically start when the tablet boots.
Logs - provides a screen showing debug logs, useful when developing the software.
UncaughtExceptionHandler - normally, when a Java apps encounters a bug leading to a creash, it stops. This handler instead displays some technical information (the stack trace) to help locating the problem without a debugger attached via a PC.
Compiling and building
The Java part was developed under Eclipse. The daemon is cross-compiled, and stored into the Java app as a raw resource.
To build all, run the build_all.sh script. Its final product is the APK file in bin/. The build script works under Linux and Mac OSX, and requires the Android SDK to be installed, as well as the C cross-compiler (arm-linux-gnueabi-gcc). To develop the Java part, and if build_all.sh was run once before in order to compile the C daemon, everything can be done from within Eclipse as usual.
The archive for source code can be found in step 10.
Before ending up with the current design, a few studies have been made:
- Reading raw keyboard events from the PC, using adb and getevent.
- Generating multitouch events (*) from a small program written in C.
- Doing the above from Java (requiring only rooting, but no daemon). This proved slightly too slow and introduced a noticeable lag, so I opted for a daemon written in C, and configured by a Java app.
(*) see http://www.mjmwired.net/kernel/Documentation/input/multi-touch-protocol.txt
Architecture
The final architecture is based on a daemon, that is, a small standalone program (written in C and hence very fast) communicating with a Java service.
The diagram in this step is an UML class diagram, showing the principal classes and entities, and their relations.
pinball_buttons_mapper (aka the daemon) - this is the standalone C program, actually doing all the "real" job: it waits for keyboard events, and generates multitouch events (simulating finger touches on the screen). It reads all its parameters from the compact settings file. The daemon is started by the Java app as root, because it needs such permissions to read/write events directly from /dev/input/eventN device drivers from the underlying Linux OS. The demon is not able to determine the devices to use, screen size and orientation, etc, so it reads these parameters from the settings.cnf file, that was prepared by the Java part. The daemon is able to detect that the settings file has changed and to re-read it automatically.
SettingsActivity - this is the main screen that is shown when starting the program. It lets you set all parameters, and stores them as preferences. It also (re)starts the service, and calls the CompactSettings upon settings changes.
CompactSettings (aka settings.cnf) - writes a copy of the settings, in a very compact format that the daemon can easily read. The settings are in XML, but the compact copy is very much simpler.
TheService - this is Java code running in background, even when no screen of the app is visible. It makes an icon always visible in the Android notification area, and cares for (re) starting the daemon (its role is merely to monitor the daemon, and call the settings screen).
Mapper - this is a Java class designed to install the daemon, and (re)start it.
BroadcastReceiver - this is needed to make the app automatically start when the tablet boots.
Logs - provides a screen showing debug logs, useful when developing the software.
UncaughtExceptionHandler - normally, when a Java apps encounters a bug leading to a creash, it stops. This handler instead displays some technical information (the stack trace) to help locating the problem without a debugger attached via a PC.
Compiling and building
The Java part was developed under Eclipse. The daemon is cross-compiled, and stored into the Java app as a raw resource.
To build all, run the build_all.sh script. Its final product is the APK file in bin/. The build script works under Linux and Mac OSX, and requires the Android SDK to be installed, as well as the C cross-compiler (arm-linux-gnueabi-gcc). To develop the Java part, and if build_all.sh was run once before in order to compile the C daemon, everything can be done from within Eclipse as usual.
The archive for source code can be found in step 10.
Scavenging the Keyboard
My USB keyboard controller has, additionally, an USB hub, which is very convenient for connecting a second (unscavenged) keyboard.
With an ohmmeter, I found the tracks to the both shift keys. Then I removed the keyboard membrane, and soldered two arcade buttons in place of the shift keys.
With an ohmmeter, I found the tracks to the both shift keys. Then I removed the keyboard membrane, and soldered two arcade buttons in place of the shift keys.
Building the Cabinet
The cabinet is custom built for the tablet I dedicate to this project. The tablet can be easily detached from it, so it is still usable for any other purposes.
I will not describe the making of the cabinet in much details; you are seasoned makers and crafters!
I just made a cardboard model to evaluate the size, angles, the handling, etc, then made drawings with a 2D sketching program.
I will not describe the making of the cabinet in much details; you are seasoned makers and crafters!
I just made a cardboard model to evaluate the size, angles, the handling, etc, then made drawings with a 2D sketching program.
Artwork
Artwork is an important aspect of pinballs.
As a fan of BTTF, I located some related pictures and printed them on printable A4 sticker sheets, then laminated them.
I applied some spray glue on the cabinet to improve the adhesion force, then affixed the sheets.
Finally, I installed the legs, with the help of a spacing tool made of Lego.
As a fan of BTTF, I located some related pictures and printed them on printable A4 sticker sheets, then laminated them.
I applied some spray glue on the cabinet to improve the adhesion force, then affixed the sheets.
Finally, I installed the legs, with the help of a spacing tool made of Lego.
PinballButtons Application Setup
Installation of the PinballButtons application
I will make my app available on the Google Play Store, but in the mean time you can do the following:
Once the Pinball Buttons app is installed, you can bring its screen by clicking its icon in the notification area. Or clicking its icon on the apps list or on the desktop.
Then set the parameters as shown in the 4 screen shots.
I will make my app available on the Google Play Store, but in the mean time you can do the following:
- Download, from step 10, the PinballButtons-rNNN-apk.zip file
- Extract it. It contains one file, PinballButtons.apk: copy it on a flash SD card.
- Insert the card in your tablet.
- On the tablet, start a file manager, locate the apk file and install it.
Once the Pinball Buttons app is installed, you can bring its screen by clicking its icon in the notification area. Or clicking its icon on the apps list or on the desktop.
Then set the parameters as shown in the 4 screen shots.
More Tablet Settings
Forcing the screen orientation
Given the slight slant, my tablet orientation wans changing all the time. To freeze the orientation, use for instance Set Orientation app.
Settings: Seeing finger touches
A very practical system setting is Developer Options -> Show Touches. For each finger touch on the screen, this displays a spot.
Our simulated touches produced by the Pinball Buttons app will be visible, if all works as expected.
Given the slight slant, my tablet orientation wans changing all the time. To freeze the orientation, use for instance Set Orientation app.
Settings: Seeing finger touches
A very practical system setting is Developer Options -> Show Touches. For each finger touch on the screen, this displays a spot.
Our simulated touches produced by the Pinball Buttons app will be visible, if all works as expected.
Pinball Apps! Pinball Apps!
There are many cools 2D and 3D pinball apps.
- 2D: Pinball Deluxe and Pinball Classic,
- 3D: The king of apps: Pinball Arcade. Simulates many famous tables. Fast! Realistic! Fun!!!
Enjoy!
Many advanced pinball maneuver are possible.
With the Pinball Arcade app, you can play a huge collection of legacy tables, with the same feel as before. I tried Black Knight, Black Hole, etc. with the same feel as decades ago!
With the Pinball Arcade app, you can play a huge collection of legacy tables, with the same feel as before. I tried Black Knight, Black Hole, etc. with the same feel as decades ago!
Downloads and Updates
This steps provides these download files:
- PinballButtons-rNNN-src.zip -- archive containing the project source files -- Use this to study/modify the project (see step 2).
- PinballButtons-rNNN-apk.zip -- archive containing the APK file, i.e. the Android app install package -- Use this to install the app (see step 6).
- Initial release (Apr 29, 2013)
- r343 (May 16, 2013) - Fixed issue found by mwheeler3: releasing buttons generated improper touchscreen events.