USB connection – it works!

Done:

  • write a clean joystick interface: 4 axes with 16-bit precision, 12 buttons (no PS3 button yet), and a hat (d-pad). This uses the excellent LUFA framework from Dean Camera.
  • configure an interrupt for the serial reception (great tutorial from Dean Camera)
  • write a RS232-capable emu process (docs).
  • write a new Sixemugui

Sixemugui layout:

Results:

  • 2ms update period = 500Hz update frequency (same as my G500 mouse) – not sure the PS3 can drive a usb device at that speed – not sure running as fast is relevant considering the Linux latency
  • measured worst latency between a usb packet received by the PC from a peripheral (like a mouse) and the usb packet received by the device the joystick is connected to (for easiness, the PC – should be the PS3) is about 4.7ms, average latency is about 3.6ms

Notes:

  • It’s probably better to avoid connecting both the mouse and the USB to serial device to the same usb bus.
  • A kernel with realtime capabilities could probably lower the worst latency.
  • It’s not good to work at a frequency higher than the mouse frequency (no mouse report in the last period => stick is set to the center => jerky movements).
  • The dead zone doesn’t seem to be is proportional to the max absolute axis value.
  • The report period is probably not constant without a realtime kernel (2ms is probably too low considering the Linux latency).
  • For performance reasons, emu & emuclient could be merged in a single process.

Next tasks:

  • build a package

USB connection

Some time ago I announced my intention to work on a usb connection that can replace the bluetooth connection (it’s well known that the ps3 is compatible with some joysticks that comply with the USB HID specification).

Why do I want a usb connection?

  • better precision for sticks (better than 8-bit precision)
  • higher update frequency (better than 100Hz)
  • good solution for a native windows controller
  • challenge 😉

What hardware can be used?

This usb connection requires a system with 2 usb ports, one for the PC, and the other for the PS3. My first though was to use a VNC2, which is a programmable device with 2 usb ports. But the development tools are windows only 🙁

Widely distributed, available, and cheap devices with usb capabilities are the at90usb* boards (Teensy++, bumble-b, AvrUsbKey…). These only have a single usb port, which is not enough. But it’s possible to talk to these boards with other means like a UART (RS232, AKA serial connection).

USB to RS232 TTL devices are very easy to find and are very cheap (a few $/€). The theoretical maximum baud rate reachable with these devices is 1 Mbit/s = 125 Kbytes/s = 125 bytes/ms, which seems fast enough. As a comparison, the sixaxis sends about 64 bytes to the PS3 each 10ms.

Another good point for this at90usb + RS232 solution is that I already have all the hardware parts, as you can see in the following picture:

  • Red outlined, the USB to RS232 TTL chip (FT232RL from FTDI). It’s on an arduino board, which is not required at all.
  • Blue outlined, the bumble-b (at90usb162).
  • Green outlined, the push-buttons required by the bumble-b to enter into dfu mode (other usb boards generally have on board push-buttons).

The RS232 connection requires as low as 3 wires (Gnd, Rx and Tx). Rx and Tx wires are crossed.

The Rx and Tx connectors of the arduino are for the AVR chip (which is absent on my board), and are crossed with the FT232RL. That’s why the arduino Rx pin is the FT232RL Tx, and the arduino Tx pin is the FT232RL Rx. I obviously fall into the trap 🙂

First experiments:

  • The ps3 seems to handle 16-bit axes.
  • The at90usb162 can report its joystick state each 1ms (but not sure the ps3 can work as fast).
  • The practical max baud rate of the RS232 connection is about 85 bytes/ms bidirectional (instead of the 125 bytes/ms theoretical max baud rate).
  • There seems to be no transmission error for the RS232 connection (I won’t handle errors in a first time).

Next tasks:

  • write a clean joystick interface
  • write a RS232-capable emu process

What’s next?

Version 0.20 is bringing many new stuffs and I hope its quality is good. I was thinking to code more things for this release, but it would have even more delayed the release date. Issues 66, 68 and 70 (enhancements, not bugs) will probably be fixed in the next release.

There also are a few things I want to work on.

  • Translation tables

I already studied the stick position to rotation speed relation some time ago (link). Measuring rotation speed for each stick position is quite painful, and I’m thinking to design a tool to automate it. I want this to work with a cheap video capture card (about 10$).
Why do I want to study rotation speed? I want to add some translation tables (there will be one different translation table for each game) so that a 1:1 translation can be achieved. A 1:1 translation means that if you double your mouse speed, your rotation speed will double. This aims to produce a better PC-feel.

Following chart gives the rotation speed vs stick position measured for COD:MW2:


It’s obviously not 1:1, especially for positions lower than 50.

Following table (values do not correspond to the above chart) shows how to perform a 1:1 translation:

1:1 translation
position speed 1:1 speed 1:1 position
1 0 8 7
32 91 140 57
64 295 480 85
96 589 720 108
128 960 960 128

All stick positions are required. Speed unit is °/s.

First column is the stick position.
Second column is the measured rotation speed.
Third column is the speed that we would expect with a 1:1 position to rotation speed translation (position*max speed/max position).
Fourth column is the translation of the position to perform a 1:1 translation. Look for the expected speed in the 2nd column (closest value) and look what position it is in the first column, this gives the 1:1 position.

The translation looks like this:

This position to position translation may introduce a loss of precision. It probably would be better to have a direct speed to position translation.
  • Better precision for the right analog stick

8-bit precision allows 256 stick positions. 10-bit precision allows 1024 stick positions. More positions give a finer control. As a comparison, a high-end mouse reports x and y values with a 16 bit precision.

The official sixaxis page tells that analog sticks and l2/r2 buttons have a 10-bit precision. This is wrong: stick and button positions are reported with a 8-bit only precision. Only motion sensing controls have a 10-bit precision. This is lame because many people are saying that the Xbox360 pad is technically lower than the Sixaxis (8-bit precision vs 10-bit precision), which is absolutely wrong.

We can’t change the precision of the sixaxis emulator, but it is probably possible to build a usb gamepad interface that has a precision higher than 8-bit for the right stick.