(PS2 Protocol) PS2 mouse movement packet bad/odd data, multiple mice

Status
Not open for further replies.

zelfor

Member
Hoping somebody can help point me in the right direction.....
Note: Code Attached

I'm working with a Teensy 3.1, the latest Teensyduino, the latest Arduino, and am using a self-rewritten version of the Arduino PS2 Mouse library to interface with several PS2 mice.
I built an adaptor for PS2 connectors, and have the mice directly connected to the Teensy 3.1, powered off 5v from VUSB. Level shifting is not needed for IO as 3.3v is logic high for 5v systems.
I know my implementation of the protocol is correct as I receive correct responses(specific acks, data) to commands.

The following applies to 3 entirely different PS2 mice I've tried (2 ball, 1 optical)...

When moving, particularly in a negative direction, I'm receiving odd data packets. The movement bytes, representing ticks of movement in x/y will, very often, be far larger than they should and/or in the wrong direction.

The following is my data conversion code, adapted from a linux driver:

Code:
int xDelta = ((byte_status & 0x10) ? 0xFFFFFF00 : 0) | byte_x;
int yDelta = ((byte_status & 0x20) ? 0xFFFFFF00 : 0) | byte_y;

I've tried different equations and algorithms, several adapted from linux drivers, and most output the same results as the above code.

I've spent the last two days fiddling with my code trying to figure this out and I've run out of ideas.

While the PS2 protocol is fairly simple, troubleshooting seems very esoteric. I'd appreciate it if anyone could help give me some insight as to what's going on.

I've formatted my data out as x/y columns with coding for sign bits and overflow (s = sign bit, o = overflow bit, v = ?Delta value).

Moving west I receive odd data:

Code:
x=s0o0v245  Y=s0o0v255
X=s0o0v245  Y=s0o0v0
X=s1o0v-11  Y=s0o0v0
X=s0o0v246  Y=s0o0v255
X=s0o0v0    Y=s0o0v255
X=s1o0v-11  Y=s0o0v0
X=s1o0v-256 Y=s0o0v0
X=s1o0v-256 Y=s0o0v0
X=s1o0v-7   Y=s0o0v0

  • (s)ign bits are mostly correct, but some oddities
  • (v)alues are partially correct given the sign


Moving south-west I received odd data:

Code:
x=s0o0v246  Y=s0o0v0
X=s0o0v246  Y=s0o0v228
X=s0o0v245  Y=s0o0v0
X=s0o0v0    Y=s0o0v231
X=s0o0v0    Y=s0o0v231
X=s0o0v0    Y=s0o0v231
X=s0o0v246  Y=s0o0v231
X=s0o0v243  Y=s0o0v231
X=s0o0v0    Y=s0o0v0
X=s0o0v243  Y=s0o0v231
X=s0o0v0    Y=s0o0v231
X=s0o0v0    Y=s0o0v231
X=s0o0v243  Y=s0o0v232
X=s0o0v243  Y=s0o0v231
X=s0o0v243  Y=s0o0v232

  • (s)ign bits should be 1, not 0
  • (v)alues should be negative, not massive positive values


Moving north-west I received good data:

Code:
x=s0o0v0    Y=s0o0v9
X=s0o0v0    Y=s0o0v9
X=s0o0v9    Y=s0o0v10
X=s0o0v10   Y=s0o0v10
X=s0o0v9    Y=s0o0v9
X=s0o0v10   Y=s0o0v10
X=s0o0v10   Y=s0o0v0
X=s0o0v10   Y=s0o0v10
X=s0o0v0    Y=s0o0v12
X=s0o0v10   Y=s0o0v0

  • (s)ign bits are correct
  • (v)alues are correct and of the correct magnitude.
 

Attachments

  • PS2Rodent.cpp
    4.1 KB · Views: 137
  • PS2Rodent.h
    3.3 KB · Views: 160
  • PS2test.ino
    1,015 bytes · Views: 128
Last edited:
I'm not familiar with the PS2 protocol and I'm on mobile at the moment so haven't got a chance to read into it, but the representation of negative numbers in binary, results in what would appear to be, very large positive numbers. In terms of the binary, there is no way to differentiate what is a large positive number or a small negative number.

Eg
9 = 00001001
-9 = 11110111 = 247

Therefore, you have to ensure that you keep some sort of record that that number is 'signed' or 'unsigned' and such is the importance of variable declaration in your programming.

Somewhere along the lines, either in the protocol or your own code, I'm willing to bet this signed/unsigned business isn't being handled properly (possibly a signed integer being cast to unsigned?).
 
The PS2 mouse returns a 3 byte movement data packet.
The relative movement ( since last report ) is represented by 9-bit, 2's compliment integers.
Bytes #2 and #3 represent the 8 least significant bits for x/y respectively. Byte #1 contains the most significant bits ( sign bits ) for 9 bit 2's compliment integers, stored in bits 0x10 and 0x20 for that byte.

The code...
Code:
int xDelta = ((byte_status & 0x10) ? 0xFFFFFF00 : 0) | byte_x;
int yDelta = ((byte_status & 0x20) ? 0xFFFFFF00 : 0) | byte_y;
...determines the sign of the 9th bit, and assigns the remaining 8 bits to an appropriately constructed 2's complimented integer for the returned data's sign.

One of the oddities, for example, is in the westward moving data in the OP. The first line is...
Code:
x=s0o0v245  Y=s0o0v255

Which indicates X is a positive (sign bit 0) integer, but is reporting an improbable result.
First, the movement is in the wrong direction (should be a negative).
Second, even if there were movement in the positive direction, the reported value is highly unlikely. A value of +80 is what I might get when moving the mouse very quickly in the positive direction. A value of 245 is astronomical in comparison.

Later data in the westward data there are expected results such as...
Code:
...
X=s1o0v-11  Y=s0o0v0
...
... showing appropriate movement in the negative direction ( sign bit 1 on x ), and an appropriate value for a moderate movement rate (-11)

Further on, another oddity shows up...
Code:
...
X=s1o0v-256 Y=s0o0v0
...
...This shows the appropriate sign bit on X (1), but is also reporting an improbably large movement value.

Movements in positive directions alwaysso far report correct movement values (below going North-East)...
Code:
x=s0o0v0	Y=s0o0v10
X=s0o0v0	Y=s0o0v0
X=s0o0v0	Y=s0o0v10
X=s0o0v5	Y=s0o0v10
X=s0o0v5	Y=s0o0v9
X=s0o0v5	Y=s0o0v9
X=s0o0v0	Y=s0o0v0
X=s0o0v3	Y=s0o0v0
X=s0o0v3	Y=s0o0v6

I'm 99.9% certain my byte conversion code is correct..
  • negative movement will, some portion of the time, return values of expected sign and magnitude
  • positive movement has always had values of correct sign and magnitude
  • multiple implementations of byte-conversion code product the same results (my own and from linux system drivers)
... so I am very puzzled as to why the mouse is reporting such odd results.
 
Well, I decided to take a new approach given the output issues I was having from PS2 mice.

I've now got a USB mouse, connected to a raspberry PI, connected via I2C to my Teensy3.1, connected to my PC and emulating a joystick given mouse events.
 
I'm having the the same problem and haven't been able to figure it out. But I tried the exact same on an Arduino Uno and didn't have the issue anymore. But I'd like to use a Teensy for my project. Does anyone have any ideas what I could try? Thanks.
 
Status
Not open for further replies.
Back
Top