Mouse

From SNESdev Wiki
Revision as of 19:59, 29 May 2022 by Rainwarrior (talk | contribs) (→‎References: index the dev manual documentation too)
Jump to navigationJump to search

The Super NES Mouse (SNS-016) is a peripheral for the Super NES that was originally bundled with Mario Paint. The Hyper Click Retro Style Mouse by Hyperkin is an optical mouse mostly compatible with software for the Super NES Mouse, with some behavior quirks.

Unlike the standard controller which returns 16 bits of data, the Super NES mouse returns 32 bits. All 32 bits can be read manually via $4016 as on the NES, but an alternative is to let the SNES do its automatic controller reading to get the first 16 bits, and then read the last 16 bits manually.

Report

The report is divided functionally into four bytes. The most significant bit is delivered first:

76543210  First byte
++++++++- Always zero: 00000000

76543210  Second byte
||||++++- Signature: 0001
||++----- Current sensitivity (0: low; 1: medium; 2: high)
|+------- Left button (1: pressed)
+-------- Right button (1: pressed)

76543210  Third byte
|+++++++- Vertical displacement since last read
+-------- Direction (1: up; 0: down)

76543210  Fourth byte
|+++++++- Horizontal displacement since last read
+-------- Direction (1: left; 0: right)

After the fourth byte, subsequent bits will read as all 1, though the Hyperkin clone mouse instead reads a single 1 then all 0s. [1]

The Hyper Click mouse will not give a stable report if it is read too fast. Between each read and the next, there should be at least 180 master cycles. Between the 2nd and 3rd byte (16th and 17th bit) of the report should be at least 336 master cycles. Reading faster than this will result in corrupted values.[2].

Automatic read

Official documents recommend reading the first 2 bytes with the automatic read system, and then reading the remaining 16 bits through the serial interface. Alternatively it can be read entirely through the serial interface.

Through the automatic read, the second byte of the mouse report will be the low byte of 16-bit automatic report.

    .a8
    ; wait for automatic read to finish
:
    lda a:$4212
    and #1
    bne :-
    ;
    ; Note: after the end of auto-read, a delay should be placed here to accomodate
    ;       the hyperkin mouse. This might be a good time to check the signature byte,
    ;       or do other mouse-related logic.
    ;
    ; now read the remaining serial report
    ldy #16
:
    lda a:$4017 ; mouse in second controller port
    lsr
    rol a:mouseread_x
    rol a:mouseread_y
    nop ; extra delay to match mouse.x65 timing (might need extra in fastrom for hyperkin?)
    dey
    bne :-
    rts

Motion

Motion of the mouse is given as a displacement since the last mouse read, delivered in the third and fourth bytes of the report.

The displacements are in sign-and-magnitude, not two's complement. For example, $05 represents five mickeys (movement units) in one direction and $85 represents five mickeys in the other. To convert these to two's complement, use negation:

  ; Convert to two's complement
  lda third_byte
  bpl :+
  eor #$7F
  sec
  adc #$00
:
  sta y_velocity

  lda fourth_byte
  bpl :+
  eor #$7F
  sec
  adc #$00
:
  sta x_velocity

When the magnitude of motion is 0, the reported sign will repeat the last used sign value for that coordinate.

Sensitivity

The mouse can be set to low, medium, or high sensitivity.

On the original SNES mouse this can be changed by sending a clock while the latch ($4016.d0) is turned on. The latch is controlled by writing to $4016, and the clock is sent by reading the serial port (either $4016 or $4017).

    .a8
    lda #1
    sta $4016
    lda $4016 ; mouse in first port
    stz $4016

Note that this cannot be done while an automatic read is active. Either test $4212 before proceeding, or otherwise guarantee that an automatic read is not occurring at the same time.

Some revisions of the mouse's microcontroller power up in an unknown state and may return useless values before the sensitivity is changed for the first time.[3]

The Hyper Click mouse will not cycle its sensitivity this way. Instead it has a manual button on the underside that must be pressed by the user to cycle sensitivity. It will always report 0 for sensitivity, regardless of its manual setting. For this reason, it is not advised to use the software sensitivity cycling to automatically detect the presence of a mouse.[4]

On the original SNES mouse, sensitivity setting 0 responds linearly to motion, at a rate of 50 counts per inch[5]. Values range from 0 to 63, but values higher than 25 are increasingly difficult to produce. [6]

Sensitivity settings 1 and 2 appear to remap the equivalent setting 0 values 0-7 to a table, and clamping at the highest value. (Rarely, however, other values may be seen in settings 1 and 2.)

Sensitivity Value
0 0 1 2 3 4 5 6 7 8 9 ...
1 0 1 2 3 8 10 12 21 21 21 ...
2 0 1 4 9 12 20 24 28 28 28 ...

The Hyper Click's two manually selected sensitivities both scale linearly with motion speed. Low sensitivity produces 0-31, and high sensitivity produces 0-63. The magnitude of the result is not dependent on the rate of polling, so it appears to report the current speed rather than the distance travelled since the last poll. The maximum value (31/63) at either sensitivity appears to correspond roughly to a speed of 8 inches per second. (This mouse should be used on a surface with a visible texture.)[7]

Other notes

Some documents about interfacing with the mouse recommend reading the first 16 bits at one speed, delaying a while, and reading the other 16 bits at another speed, following logic analyzer traces from a Super NES console. However, this is simply a result of Mario Paint using the automatic controller reading feature, and the authentic mouse will give a correct report when read at any reasonable speed. For example, a program could read 8 bits, wait a couple thousand cycles, and then read the other 24. The Hyper Click needs a delay after the first 16 bits, though not nearly as much as these documents recommend.

References

  1. forum post: Hyperkin SNES mouse investigation
  2. forum post: Hyperkin mouse reads have a speed limit
  3. Martin Korth. "Fullsnes: SNES Controllers Mouse Two Button Mouse".
  4. forum post: Hyperkin SNES Mouse cannot software-cycle sensitivity
  5. FullSNES - Nocash SNES Mouse documentation
  6. forum post: SNES Mouse sensitivity measurements
  7. forum post: Hyperkin Mouse sensitivity measurements