USB Serial Boy

USB Serial Boy

by ferris

This week the idiots at work and I were talking about debugging the Virtual Boy emulator, and the discussion led to hardware rigs. This sucked, because I realized that with stuff I had laying around my apartment already, that I could build something quite useful.

You see, the Virtual Boy has a link port, as Nintendo was planning on making multiplayer games for the system. Though no such cable ever actually came out, all VB's were manufactured with this port.

The link port is built to facilitate shit-simple bidirectional serial communication between two VB units, and is nearly identical to the Gameboy link port. One unit (designated master) pulls the command line low, indicating a transfer will take place. Another unit (slave) sees this. master clocks 8 bits of data serially with a clock line, both units simultaneously send and receive data bit signals on their crossed, matching tx and rx lines. After that, an interrupt can be raised, or the software can monitor the whole process via a "transfer active" bit in its link port control register. Another couple lines are also available to sync the displays of the two units (this is I think the only way in which this hardware actually differs from the Gameboy hardware).

With this simple port, it should be entirely possible to build a basic transfer setup and design a simple protocol to use over it. And unfortunately for me, I already had a couple 5v-compatible teensy boards laying around, for exactly these kinds of use cases...

So Thursday I got to work. I started by trying (and failing) to open the Virtual Boy's case up to check out the port's insides and see if there would be nice contact points to solder to (since I don't really have the equipment to manufacture the custom headers needed for a proper external cable). I didn't get very far, as I had the right screw bit, but the screw holes were a bit too small for it to fit into.

However, I was able to get the teensy up and running, and even got its C USB serial example up and running, which was really easy, and was also a perfect starting point for what I wanted to build myself.

Friday I bought a drill and some other tools, and Friday evening I got to work again. This time I was successful in opening the unit and soldering some breadboard wires to the backside of the serial connector. From there, I put the teensy on a breadboard and figured out how I would wire it all up, and got everything connected.

Getting initial communication was pretty tedious, as I didn't have all the communication details right in my head. There was also a problem with some of the register definition code I grabbed for the link port reg's on the VB rom's end, since they weren't marking the control reg as volatile, which meant that my wait loops weren't actually exiting. But after some trial and error and reading up on open-collector outputs, I got a byte read from the VB!

Saturday I extended this to also write bytes at the same time (the protocol is full duplex), and I moved all the higher-level protocol bits into Rust, so that we would always send and receive single bytes through the teensy. This made it easy to proceed to the next part: extending the simple byte transfer to a multibyte packet protocol. I got this working in Rust without too much pain actually, but it was very slow (~190 bytes/second!!).

The issue here was in the USB connection. Running a fully synchronous protocol with handshaking each byte has a massive amount of overhead over USB. So, I had to buffer everything over that connection. Fortunately, the full protocol was already worked out at this point, so I really just had to move the byte-level packet protocol details into the teensy, and add a second simple protocol to write out/read in entire packets over USB. This took a few hours as there were a lot of details to get right, but eventually I got that working too! With just changing these details I reached ~4kb/s (over 20x speedup!), and with some more timing tweaks and better buffered I/O, have now reached up to 8kb/s, with varying degrees of stability.

At this point this is almost done; there are still some details remaining that mostly have to do with timeouts and perhaps doing some of the protocol asynchronously on the Virtual Boy using interrupts, so that when things get out of sync/fail randomly, I can at least drop the transfer and be able to start it again. Currently it sometimes happens that we have to restart some hardware units that are out of sync and stuck mid-transfer, which can be pretty annoying.

The end goal here though is to be able to do things like send over test code to the VB and run it without having to restart. I expect to be able to do entire test suites with this against real h/w without restarting the device or reflashing the ROM - pretty cool stuff! But that will also involve some more interesting bits like a custom ROM format for that environment, and some other stuff.. but I love this shit, so yeah, will be very fun :)

Last Edited on Mon Nov 27 2017 03:59:58 GMT-0500 (EST)