I’m still chugging away slowly on this USB to ADB input translator concept, using a PIC32 starter kit. First the good news: the ADB end of things is pretty much finished. I’ve designed a demo that creates a phantom mouse on a Mac SE, and when I hold a button on the starter kit, it moves the mouse around in lazy circles. It also coexists happily with other real ADB peripherals, remapping itself if necessary to avoid ADB address conflicts, and asserting the SRQ signal as necessary when it needs attention to report new mouse movement data. So that part is looking good.
Now for the bad news: the USB side is looking to be much more difficult than I expected. I’m struggling to create even a simple demo of reading from a USB mouse, let alone dealing properly with keyboards or USB hubs. Microchip only provides a single USB Host example project for the starter kit, which writes a file to an attached USB storage device. It works, but it doesn’t tell me much about how to handle a mouse or keyboard, and all of the USB specifics are in a separate pre-compiled library.
My search for a simple USB example is made harder by the fact that most PIC example code was designed for older Microchip compilers, and needs modification to get it working with the latest XC32 and MPLAB X. I found this example by Suwa-Koubou, who modified Microchip’s USB library to add support for multiple, cascadable hubs. It includes a simple example program that displays messages when USB devices are attached and detached, as well as examples of dumping input data from a mouse, keyboard, and joystick. Sounds great! But it was designed for the older MPLAB 8 and C32 compiler.
I spent a few hours trying to update and port this example project, but I ran into several problems while trying to update it. Something about the interrupt declaration mechanism has changed (shadow registers?), and it was designed for a different model of PIC32. I updated the code as I thought was needed, but the modified example doesn’t work. It never logs any attach/detach events, and doesn’t really do anything at all, except once when it crashed after I attached a USB keyboard. So more work is needed there.
Assuming I can eventually get the code working for reading from a USB mouse and keyboard, through a hub, I’m still worried about how to multitask the USB and ADB interfaces. My understanding of the USB Host implementation is shaky, but I think some events are handled by interrupts, while other activity requires periodically calling USBTasks() from the main loop, every 1 ms or so. Both of those present potential problems for the ADB interface, which bit-bangs the ADB protocol using a purely software-based implementation. ADB transactions can take about 3 ms, plus a few milliseconds more waiting for an attention or reset signal. If I don’t call USBTasks() during that period, it may starve the USB Host controller and cause errors. But if I insert periodic calls to USBTasks() inside the ADB code, it may cause ADB timing errors depending on how longUSBTasks() takes to return. Similarly, if a USB interrupt fires in the middle of an ADB transaction, and it takes more than a few microseconds to complete, it may cause timing errors for any ADB transaction that was in progress. Hmm…