Now Playing Tracks

WiiMotes as lightguns in Mame on Linux

Lightguns were the last thing on my list to configure for my arcade machine. This is an attempt at documenting how to get WiiMotes to work in a Modern version of Mame on Linux. I’m using XUbuntu, but it should work on most things.

Important information I figured out along the way:
-http://spritesmods.com/?art=wiimote-mamegun - This had most of the information. Unfortunately it is out of date. His MAME patch has since been merged into MAME and his instructions for the MAME part are wrong. I’ve stolen much from there to document it in one place. If part isn’t clear, see his guide up until the Mame setup.
-Bluetooth pairing with the WiiMotes does work using the present BlueZ stack (provided you have a non -TM labeled WiiMote) but it isn’t automatic when you turn on the WiiMotes. I couldn’t figure out how to force the pairing even when the devices were trusted.
-XWiiMote is getting there but doesn’t support IR yet when I was testing it. Stick to WMInput with cwiid like this guide shows.

I’m going to setup two WiiMotes so that MAME sees two light guns. I’m using a bluetooth dongle for this and an IR Source.

IR Source choices:
-Candles
-IR LEDs,
-Wireless Sensor Bar
-Modified wired bar, many of the old style wire bars run off 5V. If your’s does, you can take off the end and solder on a USB connection (Pin 1 and 4 on USB, center two are data). Power the sensor over a USB port on your mame box! Careful the LEDs will only light with the wires in one direction. You can find snap on USB ends around the internet. I tied a knot in my wire before installing the end to function as strain relief.

Step 1) Get WiiMotes working as Mice.
apt-get install bluetooth wminput lswm evtest

You’ll need to load a module in the kernel
sudo modprove uinput

You won’t want to do this at each boot so tell Linux to load the module. 

sudo nano /etc/modules

On the last line add: 

uinput

Save

Try to connect a WiiMote (You’ll want to disconnect it from the Wii, red button on console while it is on). Press 1+2 on the WiiMotes (possibly need the red button on back of WiiMote) and run:

lswm

You can do this one at a time or have both flashing when you start lswm. It’s going to list out the address of the WiiMotes it has detected. Copy them down.

Let’s test one without the IR source. Run the following after pressing the 1+2 buttons:

sudo wmimput ONEofTHEaddressesHERE

Tilt the WiiMote and your mouse should move on screen.

Edit the config file to use IR:

sudo nano /etc/cwiid/wminput/ir_ptr

On these lines: “Plugin.ir_ptr.X = ~ABS_X” (and the Y line), remove the tilde and save. They should look like “Plugin.ir_ptr.X = ABS_X”. You can add custom mappings here for each button if you like. Documentation is abundant online. I’m going to use the stock settings.

Run wminput with this profile:

sudo wminput -c ir_ptr ONEofTHEaddressesHERE

Setup the WiiMote scripts to run at boot. Once you pair your WiiMote (pressing 1+2) they will start functioning as a mouse.
Download this file: http://www.novaslp.net/download/wiimote/wiimote (Modified from Sprites for 2 WiiMotes). You’ll need to modify two lines near the top that read WM_BDADDR1 and WM_BDADDR2. Switch them to be the two addresses of your WiiMotes that you got from LSWM
Place it in: /etc/init.d using cp.

chmod 755 /etc/init.d/wiimote
cd /etc/init.d
sudo update-rc.d wiimote defaults 80 20

If you aren’t on a Debian distro, make sure this gets run at startup after bluetooth starts. This runs wminput with IR source flags as a daemon in the background.

Reboot. When you start back up, press 1+2 on the WiiMotes and see if they function as mice.

Step 2) Make X server recognize them as named devices.
X already can take the input and use them as Mice but it has internal names. We need to specify names for them so that we can tell Mame what they are called. We’ll do this by modifying the Xorg.conf. If you are on a modern version of X, you may not have one. We can generate one though! I found documentation here: http://ubuntuforums.org/showthread.php?t=2123353

First figure out what ID uinput gave your WiiMotes. Connect them (press 1+2) and then check out /dev/input/

cd /dev/input
ls

It’s probably the last two objects but just to be sure, use evtest to check them out.

evtest /dev/input/eventX

Once we know which two are WiiMotes, we need to tell X about them. 
Press CTRL-ALT-F1 and login

sudo service lightdm stop

(This kills XWindows on XUbuntu, If you are on plain Ubuntu sub gdm for lightdm)

sudo Xorg -configure

Edit the newly (sudo nano xorg.conf.new) generated file and add the following:

Section "InputDevice"
	Identifier "WiiMote0"
	Driver "evdev"
	Option "Device" "/dev/input/event4"
	Option "SendCoreEvents" "True"
EndSection

Section "InputDevice"
	Identifier "WiiMote1"
	Driver "evdev"
	Option "Device" "/dev/input/event5"
	Option "SendCoreEvents" "True"
EndSection

Change the devices to the devices you discovered using evtest. WiiMote0 and WiiMote1 are going to be the names we tell Mame to use.
Add these devices to the server layout section of the X config also.

	InputDevice    "WiiMote0"
	InputDevice    "WiiMote1"

You can see my completed Xorg.conf here: http://www.novaslp.net/download/wiimote/xorg.conf

Yours should look similar, but most likely not exactly the same.
Save and copy the file to where it needs to be:

sudo cp xorg.conf.net /etc/X11/xorg.conf

Restart X or reboot to restart it.

sudo service lightdm start

For me, X would crash/quit when I’d log in. If this happens to you make sure that your users .Xauthority file isn’t owned by root.

ls -la ~/.Xauthority

If it is owned by root, run the following:

chown usernamehere:usernamehere ~/.Xauthority

Assuming X started, your WiiMotes should still function as Mice.

Step 3) Configure Mame
Edit your mame.ini (mine sits in /home/username/.mame)

nano ~/.mame/mame.ini

Under core input options, switch the following to be set like this:

joystick 1
lightgun 1
offscreen_reload 1

For games that use Offscreen reload, point to the lower right site of the screen and pull the trigger to reload.

Mame will detect these as WiiMotes but sets them up as joysticks. This is okay but we’ll need to tell it that we don’t have a deadzone otherwise the WiiMote will stall around mid screen.
Add a line to the Mame.ini:

joystick_deadzone 0

Find the core input enable options and tell it the following device settings

trackball_device mouse
lightgun_device lightgun
mouse_device mouse

After that add two lines to tell mame which lightgun is which.

lightgun_index1   WiiMote0
lightgun_index2   WiiMote1

Save this file. Start mame and enter the controls setup for player 1 and 2 (Default is tab key)

Clear all the lightgun controls except the X and Y positions. 
Lightgun X Analog for player 1 should read Joy 1 A0 Nintendo WiiMote and Lightgun Y Analog for player 1 should read Joy 1 A1 Nintendo WiiMote. If it has any extra settings, clear the setting by pressing Delete then hit Enter to set a new mapping. Move your WiiMote up/down and left/right to set the respective axis. I also cleared settings for Axis increments and decrement.

I also set default button B to be fire (Mame button 1) and button A (Mame button 2) to be alternate reload.

Try a light gun game. Inside the games you’ll be able to access the Tab menu and set controls specific for that game. Here is where you’ll be able to adjust sensitivity and enable it to show a positional cursor.

If you want to set these in the default config file for mame instead of through the UI, my settings for the AXIS were:

JOYCODE_1_XAXIS
JOYCODE_1_YAXIS

If everything here worked you should see silky smooth movement of a cursor in light gun games on Mame. Congrats!

Let me know if you have any problems with this configuration!

BeagleBone GPIO input methods

I’ve been utilizing /sys/kernel/debug/gpio to get pin state on the Beagle for some time. It was a slow solution but I really enjoy simplistic things. I didn’t want to install another library.

Tonight while commuting, I became frustrated with the slowness. I spent a bit of time trying to come up with a better solution. I ended up using Adafruit’s GPIO library. It works, but isn’t ideal.

The library supports “events” which is closer to where I wanted to be. I can set an event on a pin and watch for high, low, or “both” states. The events can be polled and the call to do so is non-blocking. I don’t need to continuously poll a file or run a series of commands to see if a change has occurred. It is doing all of this work behind the scene in a much more efficient manner than I was.

The library stops a little short though of what I’d like. I’d love to have multiple events on a pin and it doesn’t look like I can do that. I can tell it to alert me when pin GPIO1_13 does something, but I can’t get a different event to trigger when it goes high, or when it goes low.

My workflow became:
Event triggers
Read Pin state

I can get around the second step if I know the previous pin state. The pins are either on or off so any event would signal a change. I still need to read the pin state at start to verify that my view of the pin states matches reality.

I’ve found come up with two solutions that feel a little better. I haven’t successfully implemented either yet.

PRU solution:
PRUs are my new hammer. My thought is to have the PRU watch the pin state. When it changes, the ASM alters memory shared between the PRU and the host. The host script runs and looks for changes. This moves the heavy lifting of the polling to the PRU. The CPU is just in a tight loop, not doing much and possibly sleeping between loops.

Device Tree:
I’m not familiar enough with the device tree files to get this working properly. I started to play around with it but got stuck. If I revisit later this week, I’ll update this. My thought was to have the pins generate keyboard events in Linux. This appears to be feasible. This eliminates my need for an intermediate script that reads events. Most of the software I wish to use can trigger off keystrokes on it’s own.

Thoughts? Do you have a better solution? I really dislike using many third party libraries to accomplish simple things like this.

Internet Speedometer

A project that Jon and I wrote for Radioshack’s weekend project series just went live! It features my PRU/Tri-Color LED driver that was previously documented here! Build this device to have a visual representation of your Internet connection speed.

PureData - Networking with PD, a quick introduction.

PureData is an amazing software based synthesizer language. It is a branch (kinda) of Max/MSP. If you aren’t familiar with what PureData is, go check out the website. It’s okay, I’ll wait.

The documentation for PureData (PD) is hit or miss. I assume if you have been working with it for a while that it makes sense. Sometimes they leave out important things. Today I’ll touch on networking. I eventually found someone detailing my issue but it took a while.

PD can be interfaced with keyboards, files, hardware midi devices and network programs very easily. If you want two PD patches to talk to each other on different machines, networking is common. PD includes two objects to very easily do this over TCP and UDP. They are [netsend] and [netreceive]. Making them talk within PD is pretty simple see here.

Have a different program or language that you want to talk to PD? That is where my adventure began. Connecting to my PD patch was very simple. I used python and using the socket library established a connection to a TCP port on [netreceive]. Off the left most output I added a [print msg] object. I sent messages from python and waited. And waited some more. And waited more. I tried sending another message. Nothing was printed on PDs console. Changed logging level, no luck. Tried sending various combinations of end line characters, no. Tried to disconnect, no.

Eventually I setup a server in Python had PD connect to it and send me a message. Sure enough PD was sending an end-line character ‘;’. I couldn’t find it anywhere in the documentation at the time. Adding a ; to the end of each message made it pop right into PD.

If you are just getting started with PD check out [route] which you can use as a case statement and break apart different messages. Also note that the outputs of route work as both (bang) and [X] boxes. You can trigger either from a change in output based on what the downstream objects expect.

In my next PureData post, I’ll cover undocumented requirements when you are trying to read from a file!

The Tea Party (band) on 89.7 Windsor!

I was just telling a good friend earlier this weekend that I was disappointed I hadn’t heard The Tea Party (the band, not the political group) on the radio since moving to Ann Arbor.

I assumed with my proximity to Canada, I would. I occasionally caught 89.7’s Canadian hour on Sunday nights and still had not heard them.

I spent a large portion of my teens listening to The Tea Party and trying to import their albums. I discovered them from a fellow gamer that hung in The True Lodge on Battle.Net.

This evening I went for a drive and heard The Tea Party. They are hosting an entire hour of the Sunday evening Canadian X-Ports show. I was so excited that I even came home and hooked up an antenna to my tuner. Still listening now.

This is an amazing way to finish a weekend! Thanks 89x! I’m hoping to hear “Heaven Coming Down”!

We make Tumblr themes