Subposition precision, 1:1 translation

This post explains a mechanism for the mouse to stick translation, that allows to reach a better precision and that is required to perform a 1:1 translation.

If you don’t want to read some math, then skip this post ๐Ÿ™‚

All values are considered positive so as to simplify the explanation.

Each 10 ms, the sixaxis emulator processes all pending events.
All mouse motion events are merged and as a result, a single mouse event is processed.
This mouse event contains cumulated x and y deltas: (dx1, dy1).

This motion vector is then translated into a stick position according to the following formula:
  (1) pos1 = dz1 + mul * pow(mv1, exp)
pos1 = desired stick position (real)
dz1 = deadzone (real, function of dx1, dy1 and the deadzone shape)
mv1 = mouse value (integer), dx1 or dy1
mul = multiplier (real, constant)
exp = exponent (real, constant)

The result pos1 is a real. But the final stick position has to be an integer.
What emuclient was doing previously is rounding pos1 to the nearest integer.
This obviously results into a lower or higher speed than the desired one.
A much more precise solution to tackle this real to integer conversion is to truncate pos1, and compute a mouse vector remainder to be added next iteration.

The mouse event that corresponds to the applied stick position is: (dx2, dy2).
dx2 and dy2 are reals.
  (2) pos2 = dz1 + mul * pow(mv2, exp)
pos2 = applied stick position (truncate(pos1), integer)
dz1 = deadzone (same value, the angle is considered to be the same)
mv2 = mouse value (real), dx2 or dy2
mul = multiplier (real, constant)
exp = exponent (real, constant)

Note: norm(mv1) >= norm(mv2)
  (3) vrem = mv1 - mv2
vrem = mouse vector remainder
mv1 is known.
mv2 is computed from (2):
  (4) mv2 = pow[(pos2 - dz1)/mul, 1/exp]
mv2 can be replaced in (3):
  (5) vrem = mv1 - pow[(pos2 - dz1)/mul, 1/exp]
Conclusion:

  • (5) gives the mouse vector remainder that has to be added the next iteration
  • this emulates a subposition precision

Notes:

  • this is useful with 8-bit precision for stick axes as the speed difference between two neighbor stick positions is high
  • this is useless with 16-bit precision for stick axes

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

Version 0.21 released

Warning: the configuration writer of the mouse calibration mode is not working (issue 82) ๐Ÿ™

If you are upgrading from v0.15 or lower, read this post first: link.

New configuration example installed in the /etc/emuclient folder:

  • CallOfDuty:BlackOpsG500i.xml (with stick intensity control)

Improvements:

  • the calibration mode automatically saves the configuration
  • stick intensity control for button-to-stick mapping
  • macros are fixed
  • emuclient is started automatically
  • the last used config file is auto-selected
  • a (big) memory leak is fixed

All corrected issues:

Download links:

New sixemuconf layout:


It’s now possible to have a better control over a stick with 4 keys or buttons (for ex WASD) and at least 1 modifier key or button (for ex a wheel, which is in fact 2 buttons).

The original idea was to enable to reach mid-positions. This was proposed by KillerBug (see issue 73).

The solution I coded enables to reach more positions of the 8 directions that can be generated with 4 buttons. Up to 127 positions for each direction = up to 1016 positions!

Example:

– dead zone = 31 (null-movement positions = black zone)
– shape = circle
– steps = 3 (number of positions for each direction)

The circle radiuses are 127, 95, 63.
Each red dot is a position we can reach with 4 direction buttons (ex WASD) + at least 1 modifier button (ex wheel).
With shape = rectangle, the red dots are aligned as squares.

Enjoy!!

Ubuntu 11.04

Ubuntu 11.04 is out! Some important changes for the sixaxis emulator:

  • the bluez version is now 4.91

The Ubuntu 10.10 bluez version (4.69) seems to cause some connection problems in some undefined cases.

  • the middle mouse button emulation is now off by default

This “feature” can cause a 50ms lag for left and right mouse buttons.

Download link.

And now, fake sixaxis…

Bouvrie, a reader of this blog, reported issues getting the sixaxis emulator to work.

The connection isn’t successful, even with a dongle that has a chip know to work (CSR bluecore4).

The result of our investigation – see issue 74 – is that the sixaxis doesn’t give the right ps3 bdaddr (bluetooth device address). It always gives the same wrong bdaddr.

Obviously, with a wrong ps3 bdaddr, the sixaxis emulator can’t connect to the ps3.

The reason why this sixaxis doesn’t give the right baddr is simple: it’s a fake one ๐Ÿ™

Yet another fake CSR dongle…

The whole series of posts about cheap ebay dongles: link.

It seems ebay is really not a good option to find a CSR bluecore4 dongle. As a reminder, these dongles can have their bdaddr (bluetooth device address) changed, and 99% of them work with the sixaxis emulator. As far as I remember, only 1 or 2 users reported a non-working CSR BC4 dongle.

After having tried 2 sellers and only having received 2 out of 7 non-fake dongles, I decided to try another seller. But this time, I asked before buying, so as to make sure I will get what I am paying for. The answer to my question “Is there really a CSR BC4 chip inside your dongles?” was a clear “YES”. Fine, I decided to buy 5.

After 3 weeks I finally received my order. First test, plug it to my PC, see what kind of bluecore revision it is. No revision, not good at all. Try to change the bdaddr. No error for the command, but the bdaddr is not changed. Finally, unplug it, open it, and look at the chip manufacturer: Conwise. Obviously not CSR…

Lesson learnt: don’t buy these cheap ebay dongles, even if it’s advertised as a BC4 (CSR+EDR) dongle!

A good advice I could give is to borrow every dongle you can borrow, and test it. Last solution: get a dongle from a local store.