A RetroPie (or similar) controller for £5?!

I recently found myself in Poundland seeing what a humble pound coin could get me, aside from the usual cables, chargers and similar accessories I buy… seriously, they work fine and are only £1/£2, not to mention their chargers are far better than cheap ones you’d find on ebay! Check out this video from bigclivedotcom on the subject.

As I was browsing, I happened upon the £5(!) electronics/games section. There were a few XBOX360 games and such, but what caught my eye was this;

I forgot to take a photo at the shop

It is a Gioteck ‘Turbo Controller’ for the Nintendo Classic Mini. It looks basically like a NES controller with turbo buttons. Considering my RetroPie setup at home, but having no idea of the protocol/connector it used, I decided it was worth the sacrifice of £5 to find out if I could make it work. You can also get these controllers from the likes of argos/ebay (for £5.99, the horror!).

I got it home, opened it up and saw the Nintendo ‘nunchuck‘ style plug on the (surprisingly long) cable. This was a good start and I figured that it probably uses the same protocol as the Nunchuck or the Wii Classic Controllers and similar that use the same plug. Both of these use the I2C protocol and there are various libraries out there to allow them to be use with Arduino’s and compatible micro-controllers.

I was hoping there would be something similar for the Raspberry Pi, given it has an I2C bus built in, but unfortunately the only information I could find was on drivers for the Wii controller with a Nunchuck or Classic Controller connected to it, connected to the Raspberry Pi over bluetooth, which was no use to me as I don’t own a Wii controller.

So I decided to write my own ‘driver’ for it (more of a daemon actually!) and here is how I did it;

First thing I had to do was crack it open to see if I could find the pinout. Mercifully it was printed right on the board, along with several test points I plan to investigate later. I2C devices generally use four wires VIN (Power, 3.3v) GND (Ground), SDA (Data) and SCL/CLK (Clock).

In this case, VIN is red, GND is black, SDA is green and CLK is white.

Controller PCB with connections labeled

Given that this experiment was so cheap, I simply cut off the nunchuck style plug to expose the wires and I then attached my own pin sockets/plug for easy connection to a Raspberry Pi or other devices.

Controller with new Raspberry Pi compatible plug

Adding the plug made it very easy to connect and disconnect it from the various raspberry Pi’s I used for testing, namely a Raspberry Pi 3 I use to run RetroPie in my lounge room, and a Raspberry Pi 0W that I used for headless testing/development.

Connected to the Raspberry Pi

If you didn’t want cut it up, you can get you could grab a ‘Nunchucky‘ from adafruit and solder wires and an appropriate plug to that, or scavenge sockets from a broken system.

Once I had the new plug on it, I connected it to an Arduino nano to do some testing. I initially tried the WiiClassicController library to see if it used the same protocol as the Nunchuck/Classic Controller and luckily for me, it did. So now I had to work out a way to get that data into a useable form on the Raspberry Pi using its I2C bus.

Ideally you would write a kernel module in C for this, but given my very limited knowledge of C and desire to get it running quickly I had to pick something else. I am most comfortable with Java so my my first attempt was to write a simple app that used the PI4J and Robot libraries to take the data from the I2C bus and turn it in to keyboard commands. This was very quick and easy to write, but unfortunately was a failure as Robot on linux requires X11 to be running for it to work, and RetroPie does not use X11.

I looked around, and a good way to achieve keyboard emulation at a lower level was with the ioctl call, and there happens to be an wrapper for it in NodeJS. I am not brilliant with JS but I have written node app’s before and figured it was going to be easier than learning C (which I do want to do at some stage!)

My first attempt was using the virtual-input library, but nothing I did would make it work with the Raspberry Pi. I could get it work fine on an ubuntu VM to send keystrokes, but never on the Pi.I saw that it was used in another project, node-virtual-gamepad which is a really cool project. So I tried it and it and worked fine on the Pi.

I then had a look through the source to see if I could extract its virtual keyboard code for use in my own project and after much wrangling, I got it to work! I used evtest to detect the virtual keyboard codes as they were sent by the virtual keyboard code.

evtest running

The next thing to do was integrate the keyboard code with the I2C library to come up with some sort of daemon that would interpret the commands sent from the controller over I2C into keypresses on the virtual keyboard, thus controlling the game.

There was also code for emulating joysticks/gamepads which I do plan to build in to the daemon, so that you can choose to emulate a keyboard or gamepad depending on your needs. But the first order of business was to get it working as a virtual keyboard.

Once I had both portions working, both I2C reading and virtual keyboard, i was able to combine them to build the daemon that will run in the background and interpret the data from the controller in to keyboard presses to control the Raspberry Pi.

Testing it out with a bit of Mario

The code and is available on my github here, along with instructions on how to setup and use it. If you want more detail on how I built it, read on.

Once I had both the virtual keyboard and I2C code working combining them was relatively straightforward, but there were a few gotchas.

  1. As I learned from the Arduino library, the gamepad sends data in ‘packets’ of 6 bytes
  2. When there is no buttons pressed, the result always begins with a 0x0 (0) with the packet looking like this (decimal);
    [ 0, 0, 128, 128, 255, 255 ]
  3. The gamepad sends a ‘heartbeat’ packet of 6x 0xFF (255) byte values every ~8 seconds and a randomly times packet that begins with 0x1 (1), these look like this (decimal);
    [ 1, 0, 164, 32, 1, 1 ]
    [ 255, 255, 255, 255, 255, 255 ]
  4. In the linux event subsystem when a key is pressed a 1 is sent and it will remain pressed until a 0 is sent for the same key, you can send multiple 1’s and 0’s at once
  5. All 8 buttons are handed by the last two bytes in the array (5 and 6) and some buttons when pressed together send a new code if they are on the same byte. I had to test and map these out.
  6. I needed to ensure that 2 buttons can be pressed at a time in order for the controller to be useful

Below is a table of the keys to their ‘bytes’ that I am using to detect keypresses;

Button Position Hex Dec
D-pad Up Byte 5 0xFE 254
D-pad Down Byte 4 0xBF 191
D-pad Left Byte 5 0xF3 253
D-pad Right Byte 4 0x7F 127
Start Byte 4 0xEF 239
Select Byte 4 0xFB 251
A Byte 5 0xEF 239
B Byte 5 0xBF 191

Given that some buttons share the same byte (such as A&B) they give different results if pressed at the same time. Below is a table of the ‘Combination’ bytes and positions;

Combination Position Hex Dec
A & D-pad Up Byte 5  0xEE 238
B & D-pad Up Byte 5 0xBE 190
Select & Start Byte 4 0xEB 235
A & D-pad Left Byte 5 0xED 237
B & D-pad Left Byte 5 0xBD 189
D-pad Up & D-pad Left Byte 5 0xFC 252
D-pad Down & D-pad Right Byte 4 0x3F 63
 D-pad Down & Start Byte 4 0xBB 187
 D-pad Down & Select Byte 4 0xAF 175
 D-pad Right & Select Byte 4 0x6F 111
 D-pad Right & Start Byte 4 0x7B 123
 A & B Byte 5 0xAF 175

Once I had this information, the code itself is fairly simple.

It polls the controller every 10ms (this can be changed) for the 6 byte array. From that I build JSON object containing each button and its state (0 or 1). I then check this against the last iteration to see if its changed to detect a change in state of a button, if its changed I then set the key high or low using the virtual keyboard library, at the end of the iteration i pass the current button states in to the ‘old’ iteration variable and start again. Only if the key has changed from one iteration to the next do I send a key event to change its state in the events subsystem.

The daemon is designed to be run in the background upon boot of the system to register events from the controller and pass them to the virtual keyboard. I also noted that the controller can be connected and disconnected while the daemon is running with no ill effects.

Let me know if you found this useful or interesting, or if you have any suggestions on improving it!

Supercharging a cheap GPS Tracker – Part 1: Hardware

Recently my motorcycle was stolen, which is not an experience I would like to repeat. Motorcycle crime in London is quite prevalent, and unfortunately, I didn’t secure the bike as well as I should have.

Luckily I was able to find and recover it with minimal damage, as it was dumped quite close to my home.

I decided I needed to beef up security, so aside from a chain and disk lock, I also wanted an alarm and a GPS tracker.

Having a look on amazon, I came across the ‘XCSOURCE Vehicle Tracker‘ for £14.99. This seemed very cheap for a GPS tracker, as I’d seen them advertised for hundreds of pounds in other places, but for £14.99, what do I really have to lose?

It seemed to have the basic features I wanted, with real time tracking, SMS capability and TCP/IP reporting (e.g sending data to a tracking service). I did notice that in the pictures there were many unpopulated pads for other functions, so I thought maybe I could do more with it than advertised.

Turns out my hunch was correct, it was very easy to expand the capabilities of the device, as well as get the data in to a tracking service!

Initial Setup

You will need a SIM card in order for this device to work, the device uses the 2G (GPRS) network, so make sure the provider you choose still has a 2G network.

In the UK, ee, O2 and Vodafone all provide 2G networks. Three does NOT.

I purchased a sim from giffgaff as they use O2’s network and are very cheap. I pay £5/month and get 100mb of data and 500 texts. The device tends to use ~50mb of data per month and ~100 texts, but of course YMMV.

If you just want to use the SMS functionality, all you need to do is pop the sim card in and connect up the device, however there is some configuration required if you wish to use it with a tracking service (which I will cover in my next post)

It is a good idea to change the password for the device, the default is 123456. You can do this by sending password<oldpassword> <newpassword> (e.g “password123456 111111”) to the device vis SMS.

Hardware Modifications

As shown in the pictures on amazon, you need to open it up to put in the SIM card. You can also see that there are several pads on the board that are unpopulated. This particular GPS tracker (often known as a GT06/GT02) had quite a few more features than listed, and these can be accessed by simply soldering wires to the pads.

I removed the standard wiring, and soldered in new wiring to the following pads

  1. ACC – This is for sensing if the vehicle is on, connect it to power that is switched by the ignition
  2. OIL – This is used for disabling the vehicle remotely (which i’m not currently using)
  3. MIC+ and MIC- These are used for an optional microphone (you can call the device and hear what is going on in the vehicle, no use on a bike but probably handy on a car)
  4. + and – on the back of the device – This is for a speaker (you can yell at the person who is stealing your vehicle!)
  5. VBATT and GND – This is for your backup battery (more details on that below)
  6. GPSTX and GPSRX – This is for the data stream coming from the onboard GPS (more details on that below)
  7. TX and RX – This is for the data coming from the device itself (more details on that below)

With that done, you should have something like this.

 

Once you’ve done that, you can re-assemble the device. With the original wiring removed, the new wires have no issues fitting through the opening for them at the end.

Battery Backup

Probably one of the most useful things you can enable the battery backup. Not only will this help to prevent the GPS tracker from draining your vehicles main battery, it also has a feature that it sends an SMS to you with the devices location as soon as it detects a power cut. So even if thieves find the main wiring and cut it, it will keep transmitting location, as long as the backup battery remains connected/charged.

If you get ahold of a battery mobile phone charger, they normally contain a 18650 3.7v cell, you can use one of these (or any other 3.7v battery really) as backup for the GPS.

Alternatively, you can buy a pair of 18650s here for £10.49 if you don’t have some laying around.

A word of caution though, soldering to batteries is not ideal, you may be better suited either getting a hold of batteries with tabs/wires, or using a holder. If you must solder, be very quick about it as heat is bad for these batteries.

Once you’ve got your battery, you simply connect it to the wires you soldered to the VBATT and GND pads earlier, I have a plug on either end of mine so I can remove it easily if required

Serial Output

You can gain access to both the device’s serial output, as well as the GPS module’s serial output from the pads on the board, the serial output is useful for debugging, as it reports overall status (e.g battery, GPS, GPRS, etc) every few seconds.

The GPS output is useful if you need data from the GPS for another purpose e.g a custom navigation, digital dashboard, etc.

The pins ‘GPSRX and GPSTX’ on the back side of the board are for the GPS signal and the ‘TX’ and ‘RX’ near the USB port are for the console. Remember for serial to work you also need a ground, the power ground (‘GND’ at the bottom of the board with the other pads) works fine here. The serial voltage is +5v (so be careful when using it with 3.3v devices like raspberry pi’s). The GPS operates at 9600bps, 8-n-1 and outputs standard NMEA sentences. The console operates at 9600bps, 8-n-1 and outputs text.

Next Steps

Once all this is done, find somewhere inconspicuous to mount the device on your bike or car, and connect all of the lines you wish to use (+12v, ACC, backup battery, etc)

In part two, I will detailing how you can use this in conjunction with software called traccar for logging and tracking of your vehicle, which really unleashes the potential of this device!