An ADB version (for keyboards or mice or both) should be possible. I have firmware dumps from a couple of real Apple ADB keyboards that I'd like to get to eventually. They used an i8048, for the record, at least in the non-extended keyboards. ADB mice typically used a tiny surface-mount microcontroller that's significantly harder to get the code out of.
Either this or ADB should be possible to make work on the 8-bit micro of your choice; Apple themselves shipped ADB running on at least 4 distinct microcontroller families and a 6502 or Z80 shouldn't have a problem as long as you count cycles carefully.
I started messing around with the mouse on the same board, and I was able to control the mouse well enough via simple serial commands, so I've sent off another PCB revision to try to get 2 PS2 ports, a DB9, and the RJ11 all on one board to get both mouse and keyboard working in one setup.
As for ADB, it's entirely reasonable, but I'm just plodding along with one thing at a time for now.
Everything is async driven by a timer interrupt firing at ~10uS, mainly because that's an easy multiple for the keyboard clock.
The length of the movement cycle and how many cycles there are is determined before when a mouse movement request is received, and then everything is counted down by the timer. The interrupt cycle is the same thing shifted in time by 50% of the length of the movement cycle. Direction is determined by which direction the interrupt cycle is shifted.
I just have a single function that is called for both X and Y axes.
FWIW, the quadrature signal needs to be relatively slow, since every cycle generates at least one interrupt. When I tested it out just throwing out a continuous ~20uS cycle, the Plus gets very unhappy servicing all those interrupts. Right now I'm using a ~100uS cycle for a constant rate of movement, and I'm using USART serial input for diagnostics, and sending the cycle count, axis, and direction. I anticipate needing to play with finding a good function to vary both the cycle length and cycle count based on the PS2 mouse movement counts. The 100uS cycle length is probably on the fast side, but it's something that generates observable results for the moment.
Can you elaborate on that a bit? I understand the timer thing. But I dont quite know how it goes from there.
"Direction is determined by which direction the interrupt cycle is shifted."
Not clicking to me.
So one timer fires 10us, then the next timer fires at 10us? then the first timer fires again at 10us? So I assume every time the timer fires that it toggles the I/O pin state. From high to low, fire again, from low to high, fire again, from high to low, every 10us? So i assume you keep track of every interrupt trigger to know when to stop the interrupt. (number of counts/moves).
But again the part that confuses the crap out of me is how do you set which timer fires first. Obviously you have to have direction control, and that confuses me.
But then how do you know to keep the two different interrupts exactly 10us apart? They are going to fire randomly at thier own counts, with 2 individual timers, which means the phase relationship between the 2 signals wont stay the same.
From what I understand on quadrature, the two signals are always 90 degrees apart from one another, correct? I look at signals in phase. and which signal starts first determines direction? So if signal 2 lags signal 1 by 90deg, it moves one way. but if signal 1 lags by signal 2 90deg, it moves the other way?
Also, 100uS, is that the entire period of a single pulse? or half the period? if its full then that means that one signal is going to lag the other by 50us, correct?
New PCBs arrived, and I now have the software working with both mouse and keyboard on the same board.
Now that I've got the mouse totally working, I can explain what I'm doing.
I was trying to generate the 2 sine waves out of phase for each axis, shifting for direction. Then I realized it's soooo much simpler than that. X1 and Y1 are ORd for interrupt, and the state of X2 and Y2 are used to determine direction along with whether the interrupt is a rising or falling edge. So, the sine waves are totally unnecessary.
I now have a timer and toggle the lines from that. Depending on whether I want to go right or left, and the current state of X1, I set X2 to the appropriate value. The table of values & directions is in IM: Volume III and Guide to the Macintosh Family Hardware (I used the latter). Then once X2 is in the right position, toggle X1 to generate the interrupt and move the mouse.
To convert the PS2 mouse movement to these signals, I'm basically just taking the movement count in each axis I get back from the PS2 mouse, and that count is the number of X1/Y1 interrupts generated. It takes longer to send that data to the Mac than for the PS2 mouse to send it to the adapter, so there is a possibility of dropping subsequent movements. I process them, so I get button presses, but I drop the movement if I'm still sending a movement to the Mac. The same thing happens with a physical mouse, if you move the rotary encoders faster than the Mac can process the interrupts, the movement is lost.
It seems to actually be working fairly well at the moment, although I get some oddness occasionally when mashing both the keyboard and the mouse simultaneously. I haven't had any problems with normal use though, so that's nice.
I've tested it both with a Plus and System 6 and a 512k-no-e with System 0.97/Finder 1.0, and both the keyboard and mouse work fine. I've also tested it with a KVM with no problems. It works with either keyboard or mouse plugged in, or both.
New PCBs are on the way that have PS2 mouse/keyboard, the mac rj interface, and an adb connector on them, as well as a slight fix of the DB9 connector for pre-ADB mice. The idea is to have a jumper to choose ADB or pre-ADB conversion.
There is a question on the pre-ADB keyboard connector though. The standard keyboard cable is straight through, while more easily obtainable telephone handset cables are swapped. The pre-ADB connector is currently wired for a standard keyboard cable. Would it make more sense to swap the pins, so the easier to obtain handset cables work? I guess I could also bulk order cable and ends and provide straight through cables if needed.
Using the wrong cable is bad, since it will swap +5V and ground.
What I would do, is make jumpers to select reverse or streight-through. This way, you can use original mac cables, or phone cables.
You could always install a clamp diode that prevents the mac from burning up the keyboard. Keep in mind, the mac powers the keyboard, not the other way around. So you dont send 5V down the line at all.
You can in fact, leave your 5V line on the phone-jack open circuit if your board is powered externally. If this is the route you wanna take, then put a clamp diode in the phone jack and a fuse., So if its backwards, the macs 5V will be clamped against ground and pop the fuse via conduction on the clamp.
Hmm, interesting idea. The mac's 5V is already left unconnected. That would leave 3 connections that would need to be swapped to switch back and forth. 3 jumpers seems a bit cumbersome for that, but a 3PDT switch would be fairly convenient. Something like this.
But that switch only has 2 outputs. It has 3 poles on each side yes, but each side only has a single output.
So its like a 3 to 1 multiplex.
You know what would work, is a CD4053 or a MAX4619.
it has 3 channels, and contains an A/B select input. So, A would contain streight-through for all 3 signals, B would contain reverse of all 3 signals. And streight-through or reverse is selectable in either software, or a single jumper.
Option 2: You could ground pins 1 and 4 through a series blocking diode, so no matter which way it was plugged in, it cant hurt anything as current wont flow. Then pins 2 and 3 could be used through a mechanical switching method, Or through the CD4053 which could be CPU auto-select. Set one way, No ack signal from mac, flop the mux and try again. automatically Maybe even an LED to indicate its operating in reverse mode.
New PCBs arrived, with both rj11 and adb connectors!
I put a jumper on it to select between ADB and pre-ADB, but ended up not using it. Instead, it's outputting to both interfaces simultaneously. As a result, you can use one set of PS2 keyboard/mouse to control both a Plus and an SE, as seen in this video: http://users.mac68k.info/~bbraun/adb1.mp4
The mouse moves at different rates between the two interfaces, mostly having to do with encoding of the relative mouse movements.
Currently the ADB keyboard only does the usual keyup/keydown events. I haven't implemented the adb 'register 2', which allows getting the current state of any meta keys (the meta key events are reported normally, this is for software polling), and getting/setting the keyboard LED states.