8

The Macintosh 128k, 512k, and Plus use a DE-09 Serial port for the mouse. Is there some proprietary data-transfer method? Or is any DE-09 Serial mouse compatible?

Furthermore: has anyone documented this data-transfer protocol?

Edit: the reason I ask is because I'd like to build a custom mouse-input system (and eventually keyboard), perhaps over bluetooth. I am brainstorming a raspberry pi → Macintosh. Please comment with any insight.

  • 4
    I don't know the wiring offhand but it's definitely just a plain quadrature mouse input — no serial communications and therefore no protocol in that sense. – Tommy Jul 27 at 16:59
  • @Tommy I saw that term "quadrature" on the mouse's Wikipedia, but I don't understand what it is. Do you have a reference that will put it in beginner-friendly terms? – Michael Austin Jul 27 at 17:04
  • I'll find a pinout and write it up as an answer later this morning if nobody beats me to it. I just finished writing a Macintosh emulator, so I have a bunch of appropriate documents waiting on my computer. – Tommy Jul 27 at 17:06
  • @Tommy wow that would be great! Sounds like a cool project. Feel free to put a GitHub link here if you want :) – Michael Austin Jul 27 at 17:07
  • Schematic of an Apple quadrature mouse port with crude drawing of what someone believes the mouse to do: applefritter.com/comment/73859#comment-73859 there does not appear to be a difference between internals of early Mac/Lisa/AppleII type solutions. – Chris Stratton Jul 27 at 17:40
19

The pre-ADB Macintoshes use a simple quadrature-encoded mouse input, no formal serial protocol.

Quadrature encoding is a simple, physical process, that lends itself to a convenient cheat if you're synthesising input. Picture a cog, with an optical sensor pointing through the grooves. If you observed the digital output of that sensor, you'd be able to tell how fast the cog is turning, which is half the problem solved.

(Disclaimer: it's not really a cog, but that's an easy image)

What a quadrature encoder does is it uses two sensors, half a groove apart. Then if the cog is turning one way you'd expect to see the time-ordered input:

sensor 1 on, sensor 2 on, sensor 1 off, sensor 2 off, sensor 1 on, etc

But if it's turning the other way, you'd instead see:

sensor 2 on, sensor 1 on, sensor 2 off, sensor 1 off, sensor 2 on, etc

Which the Macintosh (and most other similar computers) collapse into a simple process:

  • every time sensor 1 changes state, observe the the mouse has moved by one pixel;
  • if sensor 2 has the same value as sensor 1 when sensor 1 has just changed, that's one pixel left; otherwise it's one pixel right.

(for appropriate values of 'left' and 'right', of course)

This is specifically embodied in the Macintosh by having inputs 'X1' and 'Y1' wired up to its serial controller chip, the SCC, to generate interrupts anytime they transition, and having inputs 'X2' and 'Y2' wired up as inputs to the 6522 VIA, which the processor manually polls upon receiving the X1 or Y1 interrupt.

So the shortcut I currently take in my emulator is very straightforward:

  • keep a couple of values representing "x offset not yet communicated" and "y offset not yet communicated", into which modern-style instantaneous mouse delta reports are accumulated;
  • when motion is outstanding, toggle X1 and Y1 at a fixed frequency that's close to the maximum rate the Macintosh can process the relevant interrupts at; and
  • upon each toggling, set X2 and Y2 as either the same value as X1 or Y1, if motion is leftward and downward, or the opposite value, if motion is rightward or upward.

That's a cheat coupled to the known software implementation of mouse input reading — really X2 and Y2 should mutate in between changes to X1 and Y1, rather than in lockstep with them. I will banish it from my emulator at some point, but it definitely works.

I unscientifically arrived at a figure of toggling X1/Y1 every 1,250 cycles relative to the internal 7,833,600 Hz clock. Obviously you don't have access to that clock, but that implies that ~6266 Hz is not too fast for handling mouse input. My thinking here was that since I'm receiving mouse pointer movements of multiple pixels atomically, feeding them to the emulated Macintosh "as close to atomically as possible" is technically as accurate as the available information, even if it's nothing like how someone would move a real mouse.

On the pinout, per here:

  • pin 5 is X1, the one that indicates velocity of x movement;
  • pin 4 is X2, the one that — through comparison to X1 — indicates direction of x movement;
  • pin 9 is Y1, for velocity of y movement;
  • pin 8 is Y2, for direction of y movement exactly as per x.

Otherwise it looks line pins 1 and 3 are grounds, for the chassis and electronics respectively, pin 2 is +5v, pin 7 is for the button, and 6 isn't connected to anything.

EDIT:

So, in case it's any help, this is all there is to the virtual mouse electronics in the current version of my emulator. It accepts multiple buttons because I'm sure I'll reuse it for other machines. The actual stuff of feeding the SCC and 6522 isn't in that file, naturally, it's Macintosh-specific wiring outside of the mouse itself.

EXAMPLE:

One-dimensional pseudocode:

int x_delta;

func add_x_motion(int number_of_pixels) {
    x_delta += number_of_pixels;
}

// update() is called by a timer roughly 6,000 times/second; 
// the timer needn't be very precise.
func update() {
    // Do nothing if no pixels are left to communicate.
    if(!x_delta) return;

    // Toggle x1 (/pin 5) to indicate a single pixel's movement.
    toggle_x1_output();

    // Set x2 (/ pin 4) to the same level as x1 to indicate motion
    // to the left. Set it to the opposite level to indicate motion
    // to the right. And then reduce `x_delta` appropriately.
    if(x_delta < 0) {
       set_x2_output(get_x1_output());
       ++ x_delta;
    } else {
       set_x2_output(!get_x1_output());
       -- x_delta;
    }
}
  • And, as an aside: the keyboard is an actual serial protocol, responding to queries with properly enumerated key up and key down events. But probably still not a great hassle. Pleasantly enough, the clock for serial keyboard communications in both directions is provided by the keyboard itself, so you can probably even be a bit irregular, and it's pretty slow at just 100 kHz. – Tommy Jul 27 at 18:00
  • 4
    Actually, that "quadrature" principle is how all mechanical mice worked. The only question is, at which end of the mouse cord were the quadrature signals decoded. In most mice, the decoder was in the body of the mouse itself, and then some serial protocol was used to send the data to the computer. – Solomon Slow Jul 27 at 18:12
  • I didn't mean to imply otherwise; @SolomonSlow is 100% correct. I literally meant that the physical input on a pre-ADB Macintosh is for raw quadrature input. – Tommy Jul 27 at 18:15
  • 1
    P.S., The very first optical mice I ever saw also appeared to work in a similar way. They only worked on a special pad that was made of shiny aluminum with a fine pattern of colored stripes running in one direction, and different colored stripes at a 90 degree angle. I assume that a pair of photo detectors must have generated a quadrature signal for one axis by watching one of the two colors, while another pair watched for the other color. The mice in question were attached to Sun-1 Workstations. – Solomon Slow Jul 27 at 18:29
  • 1
    @SolomonSlow the two sensors were definitely linked to the different orientations of the mouse pad somehow. That had the side effect that mouse movement was relative to the pad, not to the direction the mouse was pointing in, at least for small amounts of deviation. On of the tricks we used to play on newbie Sun users was to turn the pad through 90 degrees and see how long it took them to figure out why the mouse wasn't working. – alephzero Jul 27 at 18:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.