• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

TashKM: ADB Daisy-Chained Keyboard/Mouse Controller

tashtari

PIC Whisperer
This project isn't as oven-ready as TashTalk, but at this point I've got enough of it working that I think it deserves a forum post...

Introducing... TashKM!

...This is how brands are built. =) Anyway...

Elevator Pitch

It's an ADB peripheral which appears to the computer as an extended keyboard and a basic 100 cpi mouse, and up to 16 of them can be daisy-chained together and controlled by a single host.

The vision here is to make your classic macs full citizens of your extended desktop using Barrier KVM (formerly known as Synergy until it went from open source to for-pay). The macs have their own monitors, but they, along with any other computer on your desk, share a single keyboard and a single mouse pointer, which moves seamlessly between monitors as though all were part of the same multi-monitor setup on one machine, and keyboard keystrokes are sent to whichever machine currently possesses the mouse pointer.


Project Status

Firmware working and passing basic tests, though not rigorously tested. Integration with Barrier KVM still in the idea phase.


Caveats

The daisy-chain functionality splits the PIC's UART, the receiver taking commands from the host or the previous unit and the transmitter relaying commands to the next unit if their destination is further down the chain, and so is unidirectional. The ADB implementation depends on a decent degree of intelligence on the host's side, especially with regard to the mouse - I may want to change that to a graphics tablet, but this will require more experimentation.


What's Next

Looking into how to integrate this with Barrier, for one thing, developing less breadboard-y hardware for it, for another.


Code



The remaining parts of this project start to get into areas with which I'm less familiar than PIC firmware, so if anyone finds this compelling and wants to pitch in, by all means let me know...
 
Last edited:

tashtari

PIC Whisperer
Project Update:

I've been thinking.

A lot of my hopes for this were pegged on two things: (1) being able to imitate an ADB device with absolute positioning, and (2) being able to imitate the protocol used by Barrier KVM. Both of these have proven a bit more problematic than I'd anticipated. As far as I can tell, there is no native support for an absolutely-positioned ADB device - all devices with absolute positioning that I've been able to find require drivers (some context in this thread). Barrier KVM's protocol is undocumented and is not meant to be interfaced with by anything other than Barrier itself.

So... in view of the circumstances, I'm going to shift my vision a little. Instead of interfacing to Barrier, I'm now shooting for being able to control a daisy chain of ADB macs using a single USB keyboard and mouse plugged into a Raspberry Pi, in much the way one would with a conventional KVM switch. With this arrangement, the requirement to use relative mouse movement will not present a problem and it will be compatible with all ADB macs with no software required.

Firmware to accomplish this is done and tested, and instead of 16, it now supports as many as 64 macs, a frankly ridiculous number. Remaining work is in the software for the RPi and turning the chip into a full-fledged hardware device. I'm thinking of using PyGame for the software, in full-screen mode it should give direct control over the mouse and keyboard...

As for the hardware, some questions remain. Mainly, how to get away from the restriction that all the macs in the chain have to be powered on in order for the transceiver to relay a command down the line? Is there a way that a device can get power from further up the line until its host is powered on? How to avoid bridging the 5V rails of all the macs together (that can't be good)? These questions have answers, I'm sure, but I'll have to get advice from someone more inclined toward electrical engineering than myself...
 

saybur

Well-known member
I've used optocouplers to do this type of thing before, which also has the nice benefit of isolating the system grounds. That might be overkill: ADB being open-collector, you could also try some tricks with transistors and pull-up resistors.

Hopefully not too self-promotional (and Java may not be your thing) but I've done something similar with computer control to an ADB interface peripheral: the software for that might be what you need, with some tweaking for TashKM's UART commands. That's here:


Though it is geared more toward being a windowed application on a desktop. It wouldn't be too tricky to modify it to go full-screen and grab the mouse on startup.
 

tashtari

PIC Whisperer
Thanks for the link. Thinking on it more, I suspect it's jumping ahead for me to be thinking too much about the control side at this stage. There are still problems to be solved on the circuit side. On further reflection, relying on the individual macs to power the thing is a major disadvantage since you can't use the power key to turn a mac on, and you can't talk to macs further down the chain than a powered-off mac. It'd be better all around to have the whole chain powered at one end.

Optocouplers was what I had been thinking about originally (along the lines of what you have to do to interface a microcontroller to MIDI), and it'd be nice to isolate the system grounds, even if it is technically overkill. Would need four of them, I think, two in each direction: on the mac side, one each to sense the ADB line and the +5V rail, and on the microcontroller side, one each to drive the ADB and the power-key lines. Nicely symmetrical. I should be able to marry stock open-collector circuits with stock optoisolator circuits for that... worth experimenting with.

And for interconnection between nodes on the chain, I could use USB cables, of which everyone's got a ton lying around... not carrying actual USB in this case, but each bringing +5V and ground from the host through to the next, and using its shielded twisted pair of data lines to carry the UART line shifted to differential RS422 levels.

Just crazy enough to work?
 

tashtari

PIC Whisperer
circuit.png
Microcontroller pins:
2: ADB sense (pulled high within microcontroller, pin pulled low when ADB is high)
3: ADB drive (when driven high, pull ADB low)
4: Mac +5V rail sense (pulled high within microcontroller, pin pulled low when +5V rail is up)
5: PWR (ADB powerup pin) drive
6: UART RX
7: UART TX

This is what I have in mind. I'm not sure about the bit with the transistor, though - I'm trying to sense the state of the ADB on pin 2 of the microcontroller, but I didn't figure it was a good idea to try and drive the opto's LED directly from it. (Also, I'm not sure what transistor I should use.) If anyone looking can offer some advice, I'd be most appreciative. =)
 

Scott Squires

Well-known member
Disclaimer: I'm not an EE and don't have a thorough understanding of transistors. I also struggle with selecting transistors. With that said, I tend to default to the garden variety 2N7002 signal mosfet (2N7000 if you want through-hole) for this type of application (low side switch). Gate connected to ADB, drain connected to VO2630 and source connected to ground.
 

tashtari

PIC Whisperer
the garden variety 2N7002 signal mosfet (2N7000 if you want through-hole)
I'm glad you suggested this, because this is also the direction that me and my limited circuitry skills were going... here's my latest schematic:
circuit.png
This also reflects my realization that you can't pull PWR low with an optoisolator when the +5V rail isn't powered yet, so am using a relay instead - a magnetoisolator, if you like.
 

tashtari

PIC Whisperer
So I built this circuit and discovered it drew 60 mA from the host's +5V at rest... which feels like too much, especially since the intention is that a person will chain together potentially a lot of these, and potentially from the +5V rail of an RPi.
ADB being open-collector, you could also try some tricks with transistors and pull-up resistors
Maybe this is the way to go and I should give up on opto- (and magneto-) isolation. This is my attempt at that...

circuit-transistors.png
ADBS = ADB sense
ADBD = ADB drive
5VS = +5V sense
PWRD = PWR drive
Both sense lines are pulled high inside the PIC. If I understand the theory correctly, this should isolate the power supplies but not ground. I hear this puts me at risk for a ground loop, but I'm not sure I know what the implications of that are...
 

demik

Well-known member
So I built this circuit and discovered it drew 60 mA from the host's +5V at rest... which feels like too much, especially since the intention is that a person will chain together potentially a lot of these, and potentially from the +5V rail of an RPi.
Both sense lines are pulled high inside the PIC. If I understand the theory correctly, this should isolate the power supplies but not ground. I hear this puts me at risk for a ground loop, but I'm not sure I know what the implications of that are...

60 mA is ok on the host side. The Optométries that you are using are easting like 15 mA per circuit + something like 5mA for the other end. It's really reasonable with the PIC running.

I would keep that circuit to avoir ground loop and weird stuff, because we are talking plugging things on things with dodgy PSUs on both sides !
 

gsteemso

Well-known member
I haven't sat down and analyzed your proposed circuit. I doubt I really know enough to check your work to any meaningful extent. That said, if I were to undertake a similar project, I'd probably have started with the technique used in LocalTalk & PhoneNet dongles: a tiny little transformer.

With a winding ratio of 1:1, you get the same voltages on the output as on the input (a "matching transformer"); it isn't done to get a different signal level. The reason it's useful is that the two sides are completely electrically isolated -- with only passive components!

That's very different from an optoisolator IC, which would require a full-blown electronic board (if only a very simple one) - with its own power rails and everything. It's a lot harder to ignore one of those if it happens to be powered down in the midst of your daisy chain.

Just my $0.02.

Edit: A transformer faithfully conveys signal _edges_, but is a lot less useful if you need to track a signal's _level_. Still, when the application is suited, it's a very tidy approach.
 

tashtari

PIC Whisperer
The transformer is an interesting thought that I hadn't considered, though the edges-not-levels restriction does add some complications. I think there would have to be a microcontroller on each side of the transformer. The mac side would need one since ADB isn't edge-based and something would have to translate an edge-based protocol into ADB's open-collector protocol, and the non-mac side would need one because the mac side wouldn't be powered all the time and we need to be able to ground the pesky PWR line. That restriction really makes things complicated. Assuming the microcontrollers can drive/sense the transformer directly, without driver/receiver ICs, net change, we'd be down two optoisolators and up one microcontroller... that could be good for host-side power consumption, since the microcontroller is less power-hungry than the opto. Firmware-wise, though, the mac side would have to bitbang two protocols at the same time, which could get tricky, since neither the UART nor the SSP has the capacity to speak in edges without external components...
 

gsteemso

Well-known member
Well, _ground_ is always connected AFAIK. It's only the V+ supply that might be absent depending on the powered-on-ness of the Mac.

Edit: On machines with soft (keyboard) power-on, the ground & power lines are always powered far enough to tell whether that button has been pressed. That particular part doesn't need isolating; no matter what technique you employ, they pretty much _can't_ be.
 

gsteemso

Well-known member
Further thoughts:

- Your original "magnetoisolator" should work just fine for the power-on function; if it isn't broken don't fix it.

- Why would you need to speak two different protocols at once on the Mac? It's not complicated to convert edges to levels; a simple set/reset flip-flop on each side is all you should need. From the software point of view, you shouldn't even be able to tell it's there.
 

tashtari

PIC Whisperer
I've been thinking about this again. I kind of lost interest in the project after running into the twin walls of interfacing with Barrier and the power consumption of my circuit, but I think I'm ready to regroup. Here's what I'm thinking.

Ditch Barrier. I loved the idea of moving one mouse pointer between multiple macs, but ultimately I don't feel that integration with Barrier is realistic. The interface will be that of a traditional KM switch, with buttons and/or keystrokes changing which machine the one keyboard and mouse are connected to.

Ditch remote power-on. I'm sad to see it go, but ultimately this makes the system more complex, more power-hungry, and more expensive, and it's not worth it to save users the necessity of reaching for the power button. Transceivers will rely on host power.

Ditch the daisy chain. While this approach had the advantage of making addressing free, it brought with it the problem of what to do when a machine in the chain is powered off, and with that complicating issues of isolation and power consumption. The transceivers will use a bus topology.

Along the lines of what @gsteemso suggested, a transformer should be where the isolation comes from. Specifically, the transceivers will share an RS422/485-type bus from which every one is isolated by a transformer. The bus protocol will be simpler, similar to LIN, but electrically, the bus will be identical to LocalTalk. In fact, it will use the inner pair of a phone cable for cabling so that users can use the same physical network for TashKM and for PhoneNet.

Since they're host-powered, each transceiver will consist of a microcontroller, an RS485 transceiver, and a 1:1 isolation transformer, with an ADB mini-DIN-4 connector on one end and a dual 6P4C connector on the other. Future expansion can include transceivers that speak other protocols such as PS/2 and the Plus/512/128 keyboard and quadrature mouse.

The controller can be an RPi or it can be a dedicated piece of hardware that the user plugs a keyboard and mouse into - maybe an ADB one, even, for users who really like their AEKs and want to use them for everything...

The biggest question this leaves is how to handle addressing. Maybe there needs to be a one-time handshake between the controller and a transceiver which uses a pushbutton on the transceiver. It'd be a headache, but a one-time headache. Something more automatic would be nice, though.

That's what I'm thinking of. Any suggestions, comments, complaints, compliments? =)
 

tashtari

PIC Whisperer
...No, I forgot. Using a transformer LocalTalk style means the protocol has to speak in terms of inversions, not in terms of marks and spaces. The PIC can do this (as TashTalk proves) but it takes all its CPU time to do it. I need something the UART or SSP can do largely on its own, isolated, with two wires. Bleah. Drawing board time again.
 
Last edited:

cheesestraws

Well-known member
One hack you could attempt is to use the UART to do a kind of 1b/2b encoding where each actual bit you want to transmit is represented by two bits on the line such that there's always a transition at the start. If you do that reasonably fast and have, say, an external differential driver, that might be enough?

You could do "supermarket own brand manchester encoding" that way, and we know that's happy with magnetic isolation, because 10mbit Ethernet uses it :)
 

buserror

Active member
I don't know if this help, or not, but I wrote a replacement to Synergy a few years ago. Didn't try to replace it /all/ just make something lighweight that worked between my mac and linux box. I haven't used it in a while now as I converted to Linux for the desktop these days, but I used it for /many/ years.
 
Top