BMOW title
Floppy Emu banner

Archive for the 'Retro USB' 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.

Be the first to comment! 

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.

 
USB to ADB

USB keyboards and mice with a classic ADB-based Macintosh or Apple IIgs. Set the jumpers as shown on the Retro USB board’s diagram to select USB-to-ADB conversion mode. Use an ADB cable to connect the board’s ADB port to the computer’s ADB port.

A single USB peripheral can be connected directly to the Retro USB board’s USB-A port, or a standard USB hub can be used to connect multiple peripherals at once. When in this mode, Retro USB supports one USB keyboard and one USB mouse, as well as any number of ADB keyboards and mice, all used simultaneously.

Standard bus-powered USB hubs are recommended. Externally powered USB hubs (with their own independent power supply) are not recommended, because they can backfeed power into Retro USB even when it’s off, causing problems.

Power Key

Original ADB keyboards had a power key – a square or rectangular key with a triangle logo that could be used to turn on some later models of Macintosh computers. Retro USB has two substitutes for the power key. There’s a small button on the board that will function as the power key, even when the board is off. And when Retro USB is provided standby power from an auxiliary source, the PRINT SCREEN key on a USB keyboard will also function as the power key. To provide standby power, connect the Retro USB board’s USB-B port to a standard USB charger.

 
 
ADB to USB

ADB keyboards and mice with a modern USB-based computer. Set the jumpers as shown on the Retro USB board’s diagram to select ADB-to-USB conversion mode. Use a USB-B-Mini cable to connect the board’s USB-B port to the computer’s USB port.

A single ADB peripheral can be connected directly to the Retro USB board’s ADB port, or multiple peripherals can be daisy-chained, using the ADB pass-through connector found on all Apple ADB keyboards. When in this mode, Retro USB supports one ADB keyboard and one ADB mouse, as well as any number of USB keyboards and mice, all used simultaneously.

The ADB peripherals will appear as standard HID input devices to modern Windows, OSX, and Linux computers. No special drivers or other software are needed.

 
Firmware Updates

Retro USB firmware can be updated to fix bugs and add new features. Disconnect all power from the board, and set the board’s jumpers to select USB-to-ADB mode. Download the firmware.hex file from the Retro USB web page, and copy the file to a USB flash drive. Plug the flash drive directly into the board’s USB-A port – do not use a hub. Hold the board’s power key button while you connect the power and turn on the board. Continue to hold the button for a few seconds, until the A and B status LEDs begin blinking rapidly. The update process takes about 10 seconds. When finished, the LEDs will blink slowly together, once per second. You can now press the power button a second time to exit the firmware update and return to normal input conversion mode.

 
LED Status Codes

The A and B LEDs on the Retro USB board display status and error information. (The A LED is labeled RUN on some boards). During normal use, the A LED will blink rapidly while B remains off. During a firmware update, both LEDs are used to indicate status:

slow alternating blinks of A, then B (1 blink/sec) – bootloader is searching for a firmware file
fast alternating blinks of A, then B (8 blinks/sec) – bootloader is updating the firmware
slow synchronized blinks of A and B together (1 blink/sec) – bootloader finished successfully

If B blinks several times while A remains off, it indicates a bootloader error:

2 blinks – no valid firmware exists on chip, can’t start main Retro USB program
3 blinks – no firmware files found on USB drive
4 blinks – error in firmware file (checksum mismatch or illegal data)
5 blinks – error while updating firmware in chip memory

 
Help Commands

You can interact directly with Retro USB by typing help commands on an attached ADB or USB keyboard. Open an empty text document or command prompt on your computer. Retro USB will “type” its responses to your commands, so they appear on the screen.

Control-Shift-Capslock-V – Displays the firmware version number

Control-Shift-Capslock-C – Enters keydump mode. While in this mode, the USB key code is displayed for each key that you press, along with the corresponding ADB key code it’s mapped to (or vice-versa). This can be helpful for troubleshooting key mapping problems.

Control-Shift-Capslock-D – Exits keydump mode.

Read 16 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 

Older Posts »