BMOW title
Floppy Emu banner

Archive for the 'USB Wombat' Category

Retro 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 conversation 

First 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 conversation 

Retro 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 conversation 

RetroUSB 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 conversation 

Retro 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.
Read 3 comments and join the conversation 

USB-to-ADB is not Dead

Long-time readers of this blog may remember a USB-to-ADB converter project that never made it past the concept stage. I wrote a series of posts about it last year, and made some decent progress with ADB emulation and USB host support. I ordered parts to build a second-generation prototype, but when they arrived, I let them sit on my desk collecting dust for 12 months. Until today.

The goal is to build a simple and reliable device for using modern USB peripherals with a vintage Macintosh or Apple IIgs computer. These classic machines normally use ADB peripherals, the Apple Desktop Bus. Last year I called this project “USB-to-ADB”, but that seemed to confuse many people into thinking it was for using ADB keyboards on a modern computer. In the hope of avoiding confusion, I’ve tentatively decided to rename this effort “Retro USB”. I welcome suggestions for better and less ambiguous names, especially names that somehow suggest a Mac and Apple II tie-in.

Today’s effort was about catching up to where I’d been a year ago. Using a breadboard and a bare PIC32MX230F256B, I assembled something more-or-less equivalent to the PIC32 USB Starter Kit board I’d used previously, and got it working. I also added an LCD screen for displaying diagnostic messages. Nothing terribly exciting yet, but it took me quite a long time just to get the PIC software installed, and learn how to wire up everything by hand for an LED blinker example.

PICs don’t seem to get much love in the hobby electronics world, so for those who didn’t read last year’s project posts, I’ll remind you how I ended up selecting the PIC32MX. To convert a USB keyboard and mouse to ADB, I need a microcontroller with USB Host support (uncommon, most only have USB Device support) and the ability to work with a USB hub, so a keyboard and mouse can be used simultaneously. This second requirement proved to be the more difficult one to meet, and the PIC32 series was the only one I found that had published sample code for accessing multiple USB devices through a HUB. In theory any microcontroller with USB Host could do it, since it’s “just software”, but I’m not interested in going deep into the bowels of writing my own USB stack.

I ran into a minor problem with the crystal oscillator. My example program worked fine with the PIC’s internal RC oscillator, but I couldn’t get it to work reliably with an external crystal and capacitors, as shown in the data sheet. It sort of worked sometimes, but was very flakey. I know crystal oscillator circuits are very sensitive to stray capacitance, and my breadboard circuits with their long component leads and loopy wires everywhere were probably too problematic. When I replaced the crystal circuit with an external clock in a can-type package, running at the same speed, it worked fine. I’m 95% sure this was just a breadboard problem, and if I reproduce the same crystal circuit on a well-designed PCB it will work fine.

It shouldn’t take me much longer to finish restoring the functionality I had with the old prototype, then I can finally begin the long-delayed work of stitching together the USB and ADB pieces of this project.

Read 5 comments and join the conversation 

« Newer PostsOlder Posts »