Skip to content

Arduino-based USB rotary controller for arcade Arkanoid, Tempest, etc.

License

Notifications You must be signed in to change notification settings

carlosefr/spinner-mouse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spinner Mouse Game Controller

If you ever tried to play the arcade version of Arkanoid on an emulator, you may have found the game impossibly hard. And by that I mean impossible. 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 and lr-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.

The NES version of Arkanoid shipped with its 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 the ATmega32U4 microcontroller can easily do.

And if I could use it to play some other spinner-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).

Hardware Features

External

The main input is a smooth incremental 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. This specific encoder has two pulse pins with 24 steps per turn for a final resolution of 96 steps with quadrature encoding.

The primary button (yellow) is an arcade-style microswitch and the secondary 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 an audio 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.

Internal

Having the mouse move one pixel for each encoder pulse is generally too slow, so there's a multi-turn potentiometer to adjust the speed without having to reflash the firmware. There's also a 2-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.

Modes of Operation

Mouse Button Mapping

By default, the primary button maps to the left mouse button, while the secondary button maps to the right 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 the middle 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).

Mouse Movement

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 enters slow 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 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%.

Serial Port

Besides providing some debug output when buttons are pressed and so on, it's also possible to switch controller modes by writing to the serial port. Specifically:

  • s switches to slow mode;
  • n switches to normal mode (whatever's set through the multi-turn potentiometer);
  • r switches to the default mode (slow/normal 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 mode.

See the retropie directory in this repo for the runcommand scripts that I'm using with RetroPie to dynamically switch modes depending on the emulator being started.

Sensitivity Settings (in Emulators)

In my case I have the multi-turn potentiometer set for a speed of 22 by default, which I find confortable for Arkanoid running under lr-fbneo on a 1680x1050 display. I prefer to run other games under lr-mame2003-plus to be able to adjust the sensitivity (the controller must be in slow mode for best results, see above).

As different games used spinners with different 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).

Parts List

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.

The miniature push-button is not needed if you choose another ATmega32U4-based module board with a built-in reset switch.

Software Dependencies

All of the following dependencies are available for installation from within the Arduino IDE:

Caveat: Make sure you select the proper board variant from the "Tools > Processor" menu. The board I have is 5V/16MHz and the Sparkfun AVR Boards support files default to 3.3V/8MHz. This had me jump through some hoops to revive the board after an initial firmware upload under this wrong configuration.

Artwork

The artwork was printed with a normal inkjet printer on matte photographic paper and protected with transparent tape. It looks pretty good up close. The source file is in Pixelmator Pro format.

Final Words

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" in Tempest. The pedal was added because driving, accelerating, and using the siren in APB 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.

Topics

Resources

License

Stars

Watchers

Forks