Glitches are sometimes more interesting than the programs in which they arise. Sometimes they help to have fun or even learn something new. This time, thanks to the glitch, I learned how to make a mouse.
Experimental set
On Thursday evening, I was debugging a small program for the controller: the state of the analog joysticks was sent from the debugging board over the UART to the PC. Computers rarely equip COM ports now, so I worked through a USB-COM adapter. I was trying to understand why the data bar in the Comport Toolkit comes out uneven when my thoughts were roughly interrupted by the Blue Screen of Death.
Outset
After the reset, the mouse cursor suddenly went berserk. With unprecedented persistence, he crawled into the lower left corner of the screen! I saw this behavior for the first time and for some time did not know what to think. To my shame, not controlling the cursor, I could not even log in to Windows (because I do not know the hot keys, and the tab on the win7 welcome screen does not work).
After pulling out all the devices from the computer and pressing reset several times, I pacified the cursor and was able to login. Consistently sticking devices back, I found that the USB-COM adapter was the cause of the mouse rampage (it turns out that the cursor in the lower left corner also clicked). Having decided that the adapter can be buried, I went home.
Who is guilty
The next day (Friday), I showed my colleagues a crazy adapter. During the demonstration, the following thing became clear: if you disable the debugging board (which honestly sent data from the joysticks in an endless loop all this time), the “mouse effect” disappeared.
')
It means that it was either in the data that the board sent out, either in a specific Windows or in combination of all this with a USB-COM adapter. I checked these assumptions by connecting the board to another computer through an adapter (the effect persisted) and without an adapter into the hardware COM port (the effect persisted). Consequently, it was the board itself.
When the board was connected to another computer, the pop-up message “Microsoft Ballpoint Trackball Discovered” appeared!
But how is this possible ?!
Googling trackball name I only learned that a similar problem arose with the ancient DSL modems or specific devices that used the COM port. But just to locate the problem and cure it (disabling the "trackball" in the device manager) was somehow not interesting.
The more general request “Microsoft serial mouse protocol” revealed a completely amazing (for me) thing: it turns out that in order for the device to be recognized as Microsoft Serial Mouse, it is enough to send the letter 'M' (0x4D) when the DTR pin at the COM port changes the state [1] !
Details
The mouse protocol (for the Microsoft serial mouse) looks like this. Each packet consists of three bytes (but only 7 data bits are used):
6 bits
5 bits
4 bits
3 bits
2 bits
1 bit
0 bit
Byte 1
one
Lb
RB
Y7
Y6
X7
X6
Byte 2
0
X5
X4
X3
X2
X1
X0
Byte 3
0
Y5
Y4
Y3
Y2
Y1
X0
Here:
LB and RB - the state of the left and right buttons, respectively (1 means "pressed")
X7..X0 and Y7..Y0 - increments in two coordinates (one sign byte for each coordinate)
Such a mouse works at a speed of 1200 bps, uses 7 bits of data in each byte (that is, the most significant bit is ignored), one stop bit.
Lyrical digression
There was a full-fledged COM connector on my debug board, but I used only RX and TX pins and did not monitor DTR status. Apparently, the continuous stream of data from the board just fell in time with jerking a pin. In addition, the Microsoft serial mouse runs at 1200 bps (and I am at 9600), and with a 7-bit data packet. Apparently, the stars took the correct position that evening!
Another Google session (out of pure curiosity) led me to the document “Plug and Play. External COM Device specification ", dated February 1995, in which the algorithm of the mouse operation was found [2] :
Echo DTR to DSR, always, in hardware. On Power-up (from DTR = 1 and TXD = Mark)
If RTS = 0, wait (forever) for RTS = 1
If RTS = 1, go send COM ID (eg Table 3)
Go be a mouse
If RTS = 0, go back to state 2
Hidden text
This indicates the expectation of the unit at the RTS pin, not the DTR, but to understand where the truth is, I was not very interested, because I still could not track these pins. But now I understand about how Plug and Play works - two pins in the port are simply short-circuited when the device is connected to them. This triggers the interrupt request, the device is polled and off and it's gone.
Unfortunately, there was no trackball identifier listed there. If, in the ComPort Toolkit, we first “open” the COM port and then connect the board to it, the “mouse effect” did not occur. After listening to what the board sends, I saw something like the following:
"KkKkKkkkkkj FF.Ĺ’ĂŽckkkkkj". I could not find the trackball ID in this porridge (separate letters k or j did not work).
Go be a mouse
A test reference of a line of two hundred letters M at a speed of 1200 bps led to the desired result - the board was defined as a Microsoft serial mouse! I quickly threw in a function for packing the coordinates, and now the cursor obediently crawls to the desired angle!
staticvoidformPacket(bool leftClick, bool rightClick, int8_t x, int8_t y){ packet[0] = 0; packet[1] = 0; packet[2] = 0; // packet[0] |= (1<<6) | (leftClick<<5) | (rightClick<<4); // high y packet[0] |= ((y>>6) & 0x3) << 2; // high x packet[0] |= ((x>>6) & 0x3); packet[1] = x & 0x1F; packet[2] = y & 0x1F; }
Replacing the “initialization sequence” with the trackball showed that the package of the trackball is exactly the same, which is why my interest in the trackball faded completely.
Flaws and shoals
In order for such a “mouse” to be detected, I have to turn off the USB-COM adapter with my hands, turn it on and press the reset button on the board.
For some reason I didn’t click.
Negative increments work crookedly, a movement of -1 looks approximately like +30 (in amplitude, everything is fine with direction).
Result
Because of the jamb with a negative increment, I did not bathe with an honest recalculation of the joystick tilt as an increment in the coordinate and made the joystick just three positions on each axis. The increment in the positive direction I picked up so that it roughly coincides with -1.
I was not able to come up with any other use for such a “mouse”, but perhaps someone will come in handy.