• 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.

Hootswitch, a (work-in-progress) Apple Desktop Bus switch

saybur

Well-known member
Over the past few weeks I've been working on something to share peripherals between multiple old Macs (keyboards/mice/whatever). Here's what I've come up with:

hootswitch.jpg

This supports five ADB buses (4 computers and 1 set of peripherals) via a Pico W. I've got (very) basic ADB keyboard and mouse sharing working at this point. The code is janky and needs lots of refinement, this is definitely not ready for general use. That said I'm pretty happy with what I've come up with so far, and I wanted to share my progress and get thoughts from others with more ADB experience than I have.

Unlike period ADB switches this is 100% emulated, all traffic flows through the RP2040 on the Pico. This should make it immune to issues with ADB devices dropping off the bus, the firmware continues to respond to Macs on inactive ports and it can handle systems going online and offline while the switch is active. I've also tried to make it easy to add new types of devices in the future. The PIO units on the RP2040 are doing a lot of the heavy lifting so this design has free CPU time to do fancy things; I'm hoping to (eventually) add Bluetooth device and remote-control functionality via WiFi, for example.

This project is free and open: firmware is GPL and hardware is CERN-OHL-S. Just be aware that as of now this is really experimental and there will likely be large changes made during future development. Source is here:

https://github.com/saybur/hootswitch

Thanks for reading! Feedback is welcome :)
 

demik

Well-known member
Niiice. Is this barebones or are you running some kind of RTOS ?

Also I see your wife has made another great art. Is the buzzer hooting ?

Edit : you also need to put a quadrature in port so I can daisy chain my stuff :p
 

saybur

Well-known member
Thank you both!

This is just running on the bare Pico SDK. I don't have experience with an RTOS and I wasn't 100% sure if it would be a good match or not with this project. In retrospect that might have been a good thing to figure out before I wrote a bunch of code lol.

And sadly no, right now the buzzer just makes a little 'bzzt' noise on switching. A "hoot hoot" when switching would be much more on brand! :D

For add-ons there is a I2C/UART port exposed with both 0.1" headers and a JST for Qwiic connectors. No software support yet but that might be a way to add more stuff (or potentially some kind of crazy daisy-chaining if you really want more than 4 computers).
 

Byte Knight

Well-known member
Very cool! I have multiple vintage Macs on my desk and would love to be able to share a keyboard and mouse with them but have never been able to find a decent ADB switcher. I'm assuming this would work with the IIgs too?
 

saybur

Well-known member
I'll need to test it with my IIgs but yup, the goal is to support it. Others with more ADB knowledge can chime in but AFAIK the bus implementation on that system is fairly similar to a Mac. The PIO units on the RP2040 let you keep pretty much 100% in-spec on stuff like bit timing; the delays between command/data are the only spot that might cause trouble.

Sounds like we're in the same boat, my desk also has too many Macs to keep a keyboard and mouse out for each one. Switching cables gets old after a while!
 

saybur

Well-known member
For @demik your question got me thinking and I went ahead and dove into the FreeRTOS documentation. That was definitely the approach I should have taken to begin with. I've got a test branch on Github that breaks the polling superloop into tasks and it is working just fine. Based on the experience so far that's the direction I'm going to take the rest of the project, it should simplify future development and let me move more stuff out of the interrupt handlers.

Anyway, thank you for the inquiry, it led to a good learning experience!
 

Arbee

Well-known member
The IIgs ADB timings are a little off spec, but not by much. If you're as permissive as Apple documentation says to be it should work fine.
 

demik

Well-known member
For @demik your question got me thinking and I went ahead and dove into the FreeRTOS documentation. That was definitely the approach I should have taken to begin with. I've got a test branch on Github that breaks the polling superloop into tasks and it is working just fine. Based on the experience so far that's the direction I'm going to take the rest of the project, it should simplify future development and let me move more stuff out of the interrupt handlers.

FreeRTOS is nice if you want to add features such as Wifi. The downside is that your peripheral needs to be top notch with the timings, you can't really do active loops like with bare bone coding, mostly because you can be scheduled at any time

I'm assuming the PIOs can do that just fine ?
 

Daniël

Well-known member
Very, very cool project. I've long waited for an ADB switch project like this, as the "proper" KVM switches for ADB are very thin on the ground, and the switchboxes being... well, not great, given you're effectively hotplugging ADB when switching, which you're very much not meant to do.

I do wonder about adding video switching to it. Perhaps it's easiest to have it control an existing KVM product that provides VGA for video in and out, and just use that part of the KVM and nothing else.

That does raise the question on how to convert it to DE15 (RGBHV is easy enough, but not sure how to handle the sense lines, and DDC if the KVM is smartypants and using it for detecting whether anything's plugged in), without using a bunch of DE15 -> VGA DIP adapters on the inputs, and VGA -> DE15 on the output.

But that's for later, just an ADB switch is still very excellent to have :)
 

saybur

Well-known member
I'm assuming the PIOs can do that just fine ?
They're quite good at asynchronous processing. All the direct ADB line handling is done in interrupt time; I was paranoid about excessive ISRs from the get-go, so most of the interrupt stuff is just PIO/DMA setup or dumping raw data from a PIO into a custom queue for later interpretation, originally done in the superloop, but it now has a dedicated higher-priority task with FreeRTOS in the mix. It should be resilient (within reason) to heavier CPU loads from WiFi or the like.

Honestly, I was expecting a steeper learning curve with FreeRTOS but it really isn't too bad. If anyone is hesitant about adding it to their project, if you've previously had experience with threads in higher-level languages most of the concepts translate over really well. FreeRTOS seems to be quite good about doing what it needs to do and then getting out of your way. It's pretty neat.

Very, very cool project.
Thank you!

I do wonder about adding video switching to it
I've been thinking about that too. I need to do a second board spin to fix some problems anyway, and I was considering adding some kind of stacking setup to let a "shield" PCB easily get to the I2C and power pins. That would let a separate project come along and add a video board with it's own controller chip.

@bigmessowires did some really great writeups recently on the specifics of Mac video and how to deal with the peculiarities of the sense lines and composite sync on some models. The kind of active logic approach he ended up using might be a good match here too.

Overall though I want to keep focusing on the ADB part, I agree that it isn't well served by existing switches. I'd be happy to coordinate if someone wants to tacke the video part though! :D
 

saybur

Well-known member
More progress on the firmware, which is feeling much more complete for basic keyboards and mice. Still some bugfixes needed but it's at a stage where I can now use it for daily driving.

I put together a little video of the switch in action. It can hopefully show off things better than a long written description.

 

Callan

Well-known member
This is a super cool project! I've been wanting to have some sort of kvm for a while for my different machines. It looks like you've got the 'K' part sussed. I'm definetly down for building one once your happy with the finished product.
Thanks!!!
 

Torbar

Well-known member
This looks awesome. Threw in some boards into my most recent PCB order, looking forward to playing around with this!
 

saybur

Well-known member
Thanks both for your comments, and great to hear about your order. Let me know how it goes once those show up, any feedback/suggestions for changes would be welcome.
 

CircuitBored

Well-known member
This is really nifty, well done!

One thing I'm curious about is the possibility of dynamically switching machines based on cursor movement. If you know the resolution of each machine, could you program this gizmo to switch whenever the cursor is moved a certain distance in a certain direction? I seem to recall from @tashtari's prior investigations that the Mac doesn't support absolute cursor positioning in any meaningful way but perhaps you could still achieve a similar result just using relative positioning and some good approximation. I don't really know anything meaningful about how cursor moves are communicated over ADB but this concept has been bouncing around in my head for a while.
 

zigzagjoe

Well-known member
This is really nifty, well done!

One thing I'm curious about is the possibility of dynamically switching machines based on cursor movement. If you know the resolution of each machine, could you program this gizmo to switch whenever the cursor is moved a certain distance in a certain direction? I seem to recall from @tashtari's prior investigations that the Mac doesn't support absolute cursor positioning in any meaningful way but perhaps you could still achieve a similar result just using relative positioning and some good approximation. I don't really know anything meaningful about how cursor moves are communicated over ADB but this concept has been bouncing around in my head for a while.
Unfortunately, using relative positioning, if you were to move the mouse against a boundary (ie. the edge of the screen) you start to become off.
 

saybur

Well-known member
Appreciate the kind comments 🙂

Yeah, that seems right. The communication for mice is only mouse->computer so AFAIK there isn't a way to notice the pointer running off the screen without a supplemental driver. If a app/driver could be written, on the Hootswitch side it would be easy to add a device plugin that responds to a Listen 1 (or whatever) when the mouse entered a magic zone, and call the computer_switch() function to move the active computer to a different port.

As for the absolute positioning thing, I've already been dipping my toes into Mac application development (nothing specific to drivers yet). I've been pondering how hard it would be to write a generic absolute-positioning driver, something that I could deploy here for WiFi control and tashtari/others could potentially use elsewhere with other custom ADB projects. There is an open source Qemu virtio driver implementing a tablet that might provide an existing structure to build on: https://github.com/elliotnunn/classicvirtio

Curious if @Arbee or others with emulator dev experience could chime in with how applicable they think that code would be to a real-device driver?
 

tashtari

PIC Whisperer
I've been pondering how hard it would be to write a generic absolute-positioning driver, something that I could deploy here for WiFi control and tashtari/others could potentially use elsewhere with other custom ADB projects.
I would love this. TashKM has been stalled for a long time on the nonexistence of a way to do absolute positioning... though, honestly, it seems you're doing or plan to do most of what I was planning to do anyway, so I'm happy to leave this one to you.
 
Top