Archive for the 'USB Wombat' Category
Retro USB Firmware Update v0.1.5
Firmware version 0.1.5 is now available from the Retro USB page. This version adds a few small improvements:
- LED A now illuminates when there’s a working ADB or USB connection to the host computer. LED B blinks when there’s keyboard or mouse activity.
- F13 now functions as an ADB power key in standby mode, just like PRINT SCREEN. Some USB keyboards don’t have a PRINT SCREEN key, some don’t have F13, so you can’t please everybody.
- Special ADB keycodes for the right-side shift, control, and alt keys are no longer sent unless the host computer specifically requests them. This fixes some weirdness with these keys on the Apple IIGS at the BASIC prompt.
Retro USB is an input converter for USB and ADB keyboards and mice. It works in two directions, connecting modern USB peripherals to a classic ADB-based Macintosh or Apple IIgs computer, or ADB peripherals to a USB-based computer running Windows, OSX, or Linux. The foreign keyboards and mice behave exactly like native peripherals, requiring no special software or drivers – just plug it in and go.
Read 2 comments and join the conversationRetro USB – On Sale Now
Retro USB is available for sale now – visit the BMOW shop to be the first kid on your block to get one! Retro USB is an input converter for USB and ADB keyboards and mice. It works in two directions, connecting modern USB peripherals to a classic ADB-based Macintosh or Apple IIgs computer, or ADB peripherals to a USB-based computer running Windows, OSX, or Linux. The foreign keyboards and mice behave exactly like native peripherals, requiring no special software or drivers – just plug it in and go.
Now you can finally use an optical mouse with your vintage Macintosh, or amaze your coworkers with an antique Apple Extended Keyboard on your work machine.
The last month of development has been a marathon, but I’m very excited to finally release this product whose first concept was outlined here over a year ago. Aside from a very long period of hibernation between concept and implementation, the final result turned out very similar to how I imagined it in those first concept posts.
Compatibility
The Retro USB hardware is compatible with all Apple computers, keyboards, and mice using a mini DIN 4-pin ADB connector, including most early Macintosh computers and the Apple IIgs. It is also compatible with standard USB keyboards and mice with a USB-A connector. When in ADB-to-USB conversion mode, it works under Windows, OSX, Linux, or any other operating system that supports USB HID input peripherals.
Read 19 comments and join the conversationFirst Hardware
Retro USB boards are here. They look pretty! And they actually work – minus some small fixes I had to apply.
I was in the midst of typing up a description about how my test board didn’t work, and feeling sorry for myself, when I remembered the issue with the external crystal that occurred with the breadboard prototype a few weeks ago. I couldn’t get the crystal to work reliably on the breadboard, so I substituted an external “can oscillator” for testing. That required changing some configuration bits for the PIC32’s clock source – bits that I forgot to change back once I had the real PCB. After I made that change, everything was good.
I’ll be very happy to retire the breadboard, with its delicate wiring that’s thrown off by the smallest bump, and switch over to a nice sturdy PCB for further development. Although within the first 10 minutes of use I already identified a long list of things I want to change about the PCB. For example, I located the serial port and ICSP headers too close to each other, so the PICKit3 programmer blocks the serial port. Doh! And a couple of the components I selected (like U3 in the photo) are way too tiny, and a real pain to solder. SOT-363 sounds fine when it’s some acronym, but perspective changes when you see it’s a 6-pin chip that’s the size of a sesame seed. I had to get a 10x loupe magnifier just to read the markings on the chip. But on the whole, the board seems completely usable, even though it makes some assembly and programming tasks slightly awkward. I think it’s a pretty good first attempt.
Read 9 comments and join the conversationRetro USB in Reverse
This Retro USB conversion stuff is getting interesting. Last week I showed off my first working prototype of USB to ADB input conversion. After another week of tinkering, I’ve now got the reverse conversion working as well. I can use my early 80’s keyboard and mouse on my 21st century Windows desktop machine! It’s awesome, in a totally useless kind of way.
As entertaining as this is, I’m not sure it makes sense to include this feature in the final Retro USB design. While it’s not conceptually difficult to do the conversion in reverse, it complicates the software and hardware for a feature that’s basically just a novelty. It means a USB-B port would be required, along with some way of switching between it and the USB-A port that’s safe and idiot-proof. It also means the ADB port would either be a source of power, or a peripheral that needs to be supplied power. It’s not a huge problem, but it’s lots of extra fiddly bits to design and include in the hardware. I’m thinking it may be better to keep things simple and focus exclusively on USB-to-ADB, which would help keep the cost down too. Or maybe I could find a way to offer ADB-to-USB as an extra option for those who really want it.
Read 4 comments and join the conversationRetroUSB Happy Progress
Good news from my RetroUSB project! I finally have a working proof-of-concept, connecting a modern USB keyboard and mouse to a classic 1980s Macintosh SE computer. A microcontroller and small pile of related components perform the necessary conversion between USB and ADB, acting as a USB host and translating the input events into the Apple Desktop Bus protocol used by the Macintosh. It’s still a long way from being a finished design, but the hardest part is done, and I’ve proven that this approach can work.
Reading and writing ADB bus traffic is implemented entirely in software, checking and setting I/O pin values using hard-coded delays. The USB side of the converter uses the built-in USB functionality of the PIC32MX microcontroller. In order to avoid impacting the hard-coded delays in the ADB routines, interrupts are disabled whenever listening for or responding to ADB bus commands. These periods where interrupts are disabled can last for several milliseconds, and at first they caused major problems for USB communication, which I detailed in my previous post.
With the help of a logic analyzer, I eventually determined that the problem was caused by sending USB packets too late during the USB frame, so that they weren’t finished before the end of the frame. This was a side-effect of re-enabling interrupts midway through a USB frame, causing the PIC to start sending packets even though the 1 millisecond USB frame was almost over. Fortunately the PIC has a USB setting to handle this: U1SOF, the start-of-frame threshold. If the number of bit times remaining in the current USB frame is less than U1SOF, no new USB tokens will be started until after the next SOF has been transmitted. Through experimentation, I found that doubling or tripling the default U1SOF value eliminated the USB errors I was experiencing. Here’s a figure from the datasheet:
So the basic functions of a USB to ADB converter are now working, as you can see in the video. I can simulate multiple ADB keyboards and mice, complete with ADB collision detection and address remapping. And I can read up to eight USB keyboards and mice at the same time, directly connected or through a USB hub. I can also log traffic and statistics over the serial port for debugging. Now there are a million smaller details to address:
Brownouts. The ADB bus directly powers the whole collection of hardware, including the USB hub, keyboard, and mouse. It draws about 120 mA from the Macintosh SE, which is well within the 500 mA spec. Yet I measured the 5V line drooping as low as 4.3V, and the 3.3V supply for the PIC drooping as low as 2.6V. Sometimes the PIC’s supply voltage gets low enough to trigger a brownout reset. I’m not sure what’s going on here. Maybe my breadboard wires and hand-soldered ADB connector have a few ohms of resistance, causing a voltage drop.
Mouse Sensitivity. Initially the USB mouse was super sensitive, and only a tiny movement was needed to send the Mac’s mouse pointer all the way across the screen. I’m now dividing the mouse movement vectors by 4, but that makes motion less smooth.
Mouse Axis Mapping. An Amazon Basics brand optical mouse works fine, but a Dynex brand mouse appears to have its movement axes mapped weirdly. X and Y axis movements are combined and reported on the wheel axis, while wheel movements are reported on the X axis. This must be a software bug in the HID report parser.
Keypress Handling. I’m not truly handling USB keypresses properly, because a single USB key event is being translated into two separate down and up events for ADB. At present, it won’t correctly recognize when you press and hold a key.
Double Keypresses. Sometimes when I press a key once, it will be reported twice. Probably due to the dodgy keypress handling.
Power Button. Real ADB keyboards have a power button used to turn on the computer. This is a physical switch that completes a circuit between a dedicated ADB pin and ground. I’ll have to add a hardware button to my breadboard somewhere to act as the power switch.
Read 12 comments and join the conversationRetro USB – So Close, So Far
The mess on my desk is growing. In my attempt to use USB keyboards and mice with an old ADB-equipped Macintosh, I’ve got something that’s tantalizingly close to working. On the ADB side, I can simulate an ADB keyboard and mouse, complete with ADB collision detection and address remapping. It works great on the Macintosh, when I write a routine to generate fake input data. On the USB side, I can read a USB keyboard and mouse at the same time, through a hub. I can log all the collected data over the serial port. And I can do all of this from within the same program running on my PIC32MX230. Just not all at once.
Each interface seems to work fine by itself, but things go poorly when they’re combined. The USB-related interrupts introduce timing errors into my software bit-banged ADB implementation, so that ADB no longer works. Or if I disable interrupts during ADB activity, so the bit-banged ADB timing isn’t affected, then USB breaks in strange and subtle ways. USB devices will just stop reporting status after a short while, or attach/detach events will get missed, or the program will sporadically reboot itself. This is the problem of multi-tasking two interfaces that I anticipated last year while planning this project, and now here it is.
USB Mysteries
I know very little about how USB works “under the hood”, and would prefer to keep it that way, but it seems I’ll need to do a deep dive into the USB stack code. The multi-tasking interface failure is disappointing, because I’d almost convinced myself that the USB Host implementation should be able to tolerate occasional disabling of interrupts for the 5-10ms needed to handle an ADB transaction. Yes, USB activity is supposed to happen every 1ms, so 5-10ms with disabled interrupts would mean a lot of missed USB windows. But as the USB host, I initiate all USB activity, and ultimately I should get to determine when USB activity happens, whether that’s every 1ms or not. I was a bit surprised that it didn’t work, and even more surprised that it sometimes causes the program to reset. Maybe a buffer overrun somewhere causing a crash, or an intentional error handling mechanism somewhere in the USB stack?
I used a logic analyzer to observe that there’s still USB activity on the bus every 1ms, whether interrupts are disabled or not. That much must be performed in the PIC32’s USB peripheral, without any dependency on interrupts. But when interrupts are disabled, the USB traffic seems to consist entirely of 2.59 microsecond bursts that I’m guessing are the SOF (start of frame) packet and nothing else. With the ADB side disabled, I see occasional longer bursts of USB activity up to 126 microseconds mixed in with the shorter SOF-only packets. I assume these are the HID requests and reports, which seem to come every 10ms regardless of whether I request them more often.
I was able to partially debug what’s happening when input devices stop reporting status. The program appears to get stuck in a state where it requested an HID report, and is waiting forever for the reply. I’m not sure what caused that, or why there isn’t some timeout or error-detection in the USB stack. Perhaps there is, at a lower level of the USB stack that I haven’t yet examined, but then I need to understand why it’s apparently not working. Maybe I can fix this with some timeout-and-reset code, but there’s also the deeper problem lurking of the sporadic random reboots when multitasking ADB and USB. That scares me.
Trivia
Some interesting little discoveries I’ve made while troubleshooting:
- The circuit draws 106 mA from the Macintosh’s ADB port, with my hardware plus an unpowered USB hub, one keyboard, and one mouse. That’s well within the 500 mA limit, and even within the lower 200 mA of the Powerbook computers.
- The axis data from my USB mouse is all backwards and confused. It’s something like Y axis movements reported on the X axis, and the wheel and X axis movements combined on the wheel axis. This probably means there’s a bug somewhere in the HID Report Descriptor parser in the USB stack. As I understand it, that’s the code responsible for understanding what format the report data will be delivered in.
- The USB mouse will detach and reattach itself every 30 seconds, if I don’t request an HID input report from it. As long as I request periodic input reports from it, it stays attached. In contrast, my keyboard is happy to sit there forever on the USB bus without me ever requesting an input report from it.