- Notifications
You must be signed in to change notification settings - Fork1
Arduino-based USB rotary controller for arcade Arkanoid, Tempest, etc.
License
carlosefr/spinner-mouse
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
If you ever tried to play the arcade version ofArkanoid on an emulator, you may have found the game impossibly hard. And by that I meanimpossible. That's because the game was designed to be played with a rotary controller (called a "spinner" or "dial"), not a joystick. With a spinner, you're directly moving the paddle – spaceship – not pushing it.
In most arcade emulators –lr-fbneo andlr-mame2003-plus are my current choices – you can use a mouse instead. As the MS-DOS version of Arkanoid could also be played with a mouse, that makes it a perfectly cromulent thing to do. But a mouse forces you to play sitting at a desk, which I'd rather avoid.
TheNES version of Arkanoid shipped withits own spinner controller commonly called the "Vaus" controller, and its simple (and cheap) design inspired me to build my own version that presents itself as an USB mouse – something that any Arduino-like board based on theATmega32U4 microcontrollercan easily do.
And if I could use it to play some otherspinner-based games, the better. So I added an extra button, and the option to connect a pedal that I had lying around from my MIDI keyboard (for up to three buttons total).
The main input is a smoothincremental rotary encoder commonly used for volume control in audio amplifiers. It costs a fraction of the kind of encoders arcade cabinet enthusiasts would use, which made me fear it might not have enough resolution, but it turned out just fine. Thisspecific encoder has two pulse pins with 24 steps per turn for a final resolution of 96 steps withquadrature encoding.
Theprimary button (yellow) is an arcade-style microswitch and thesecondary button (red) is a generic doorbell push-button. Both are wired to connect to ground when pressed (active-low), in order to use the ATmega's internal pull-up resistors and minimize the number of external components, and are debounced in hardware using 100nF capacitors across their pins, to minimize code complexity.
The (optional)pedal is of the type commonly used as a sustain pedal with music keyboards. Internally, it's just a spring-loaded push-button configured in either a normally-open or normally-closed way. It connects using anaudio jack which includes a normally-closed sense switch that opens on insertion. As before, both of these switches use the ATmega's internal pull-up resistors and get debounced using 100nF capacitors.
An external (blue)LED provides some minimal feedback about the controller's operation. As blue LEDs are usually pretty powerful, and harsh, sources of light, it is dimmed to a reasonable level using PWM.
Having the mouse move one pixel for each encoder pulse is generally too slow, so there's amulti-turn potentiometer to adjust the speed without having to reflash the firmware. There's also a2-way DIP-switch block to disable mouse events while testing, and switch between X-axis and Y-axis motion. Both of these adjustments can be done through holes drilled in the back of the case. I didn't bother adding debouncing capacitors for these switches.
By default, the primary button maps to theleft mouse button, while the secondary button maps to theright mouse button. When a pedal is connected, mappings are shifted so the pedal becomes the left mouse button, the primary button becomes the right mouse button, and the secondary button becomes themiddle mouse button.
The firmware can handle the pedal being connected/disconnected at any time. It also autodetects if the pedal switch is normally-closed or normally-open (the pedal I have can be configured either way).
By default the rotary input moves the mouse pointer as fast as configured using the internal multi-turn potentiometer – from 1 to 50 steps at a time. If the primary button is kept pressed when connecting the controller, it entersslow speed mode and will always move at 20% of the configured speed. This is useful for emulators such as MAME that have their own sensitivity adjustments.
You may be wondering why slow speed mode is 20% of the configured speed and not the maximum precision of 96 steps per turn (1 mouse step per encoder pulse): it allows for better use of MAME's dial sensitivity range, which only goes up to 255%.
Besides providing some debug output when buttons are pressed and so on, it's also possible to switch controller speed modes by writing to the serial port. Specifically:
s
switches to slow speed mode;n
switches to normal speed mode (whatever's set through the multi-turn potentiometer);w
swaps the left/right mouse buttons (some games have their main function on the secondary button);r
switches to the default settings (slow/normal speed depending on whether the primary button was kept pressed at connect time);+
increases the speed by 5%;-
decreases the speed by 5%;c
shows the current settings.
See theretropie
directory in this repo for theruncommand scripts that I'm using withRetroPie to dynamically switch speed modes depending on the emulator being started.
In my case I have the multi-turn potentiometer set for a speed of 22 by default, which I find confortable for Arkanoid running underlr-fbneo on a 1680x1050 display. I prefer to run other games underlr-mame2003-plus to be able to adjust the sensitivity (the controller must be in slow speed mode for best results, see above).
As different games used spinners withdifferent resolutions, the specific sensitivity settings for each game will also be different. Even games where the original spinner had a much higher resolution seem to work fine (e.g. Arkanoid's spinner had a resolution of 486 steps per turn).
The following two lists include the components that I used for my build, with links to the specific parts I bought. Since I ordered most of them from a nearby portuguese store, most of the linked pages are in portuguese, but should still be useful to figure out what to buy elsewhere if you wish to build your own.
The first list is the minimum needed to support games that only use one button (e.g.Arkanoid,Super Sprint/Championship Sprint,Hot Rod) as well as games that use two buttons (e.g.Tempest,Badlands). That should cover most cases.
If you'd rather use a pedal on racing games, or play a game that needs the third button (e.g.APB), then you'll also need the additional components in the second list.
- 1xATmega32U4 USB-C module (5V/16MHz)
- 1xright-angle USB-C to USB-A cable
- 1xincremental rotary encoder (24 pulse / 360°, smooth rotation) +knob (31x17mm)
- 1xarcade push-button (32x30mm, microswitch)
- 1xsmall push-button (12.7mm, SPST-NO)
- 1xminiature push-button (6mm, SPST-NO, through-hole)
- 1x 3.5mm LED
- 1x 1KΩ resistor (to current-limit the LED)
- 2x 10nF poliester capacitor (to debounce the rotary encoder pulse pins)
- 2x 100nF poliester capacitor (to debounce the arcade and small push-buttons)
- 1x10KΩ multi-turn potentiometer
- 1x2-way DIP-switch
- 1xprototyping circuit board (72x47mm, perforated)
- 1xproject case (145x80x34mm, ABS plastic)
The miniature push-button is not needed if you choose another ATmega32U4-based module board with a built-in reset switch.
- 1xmusic keyboard sustain pedal (momentary switch)
- 1xmale 3.5mm to female 6.3mm jack adapter cable
- 1xfemale 3.5mm jack with sense switch (mono, panel-mount)
- 2x 100nF poliester capacitor (to debounce the pedal and jack sense switch)
All of the following dependencies are available for installation from within theArduino IDE:
- Paul Stoffregen'sEncoder library
- Arduino'sMouse library
- Sparkfun AVR Boards support files
Caveat: Make sure you select the proper board variant from the "Tools > Processor" menu. The board I have is 5V/16MHz and theSparkfun AVR Boards support files default to 3.3V/8MHz. This had me jump throughsome hoops to revive the board after an initial firmware upload under this wrong configuration.
The artwork was printed with a normal inkjet printer on matte photographic paper and protected with transparent tape. It looks pretty good up close. Thesource file is inPixelmator Pro format.
Having an adequate game controller can be crucial for these old games – it can be the difference between frustration and fun.
At first I built this controller just for Arkanoid, until I figured that I could use another button for the "superzapper" inTempest. The pedal was added because driving, accelerating, and using the siren inAPB felt awkward. Shifting the accelerator away from my hands was enough to make that game fun for me (abeit still hard).
-- Carlos Rodrigues, 2024
About
Arduino-based USB rotary controller for arcade Arkanoid, Tempest, etc.