Emulating the DMD 5620 Terminal

Back in the early 1980s, before GUIs were commonplace, Rob Pike and Bart Locanthi Jr. at AT&T Bell Labs created a bitmapped windowing system for use with UNIX. Originally, they called the system “jerq”, a play on the name of the Three Rivers PERQ computer. When the technology started to get showed around outside of the lab, however, they changed its name to “Blit”, from the name of the “bit blit” operation.

Here’s a small demo of the system in action, circa 1982.

The windowing system was a combination of hardware and software. The hardware was a terminal built around a Motorola 68000, with an 800 by 1024 pixel 1-bit bitmapped display in portrait mode, a keyboard, and a mouse. The software was hosted on a UNIX computer and would be uploaded to the terminal’s memory on demand, where it executed on the terminal’s CPU itself.

Later still, AT&T and the Teletype Corporation teamed up to commercialize the system. They reimplemented the hardware and based it on a Western Electric WE32100 CPU. They named it the DMD 5620 (DMD for “Dot-Mapped Display”).

0115_dmd5620.jpg

Software emulators for the earlier 68000 Blit already exist, both in C and in JavaScript. But the DMD 5620, the version that saw some commercial success outside of bell labs, has never been emulated.

Because I’m such a fan of emulation, and because I worked so long and hard on the AT&T 3B2/400 Emulator, and because 3B2s often ran DMD 5620 terminals in commercial environments, I knew I had to remedy the situation.

Getting Started

Unlike the 3B2/400, the DMD 5620 is extraordinarily well documented. Not only that, but the source code for the ROM is available, as is the source code for the driver and application software on the UNIX side. Many thanks go to Eric Smith for his DMD 5620 FAQ and Software archive, without which this project wouldn’t have been possible. It made writing the emulator a weeks-long project instead of a years-long project.

The Architecture

I decided not to use a framework like SIMH to build the DMD 5620 emulator, so I could start fresh. I also wanted to take the opportunity to use my favorite new language, Rust. I knew I wanted the emulator to be fully cross platform, so I split the work into two parts: A Rust back end that could be compiled as a library on Windows, Linux, and macOS; and a front end written in JavaScript that could be built as an ElectronJS desktop application (or in the future, potentially deployed to a webpage backed by a WASM library. But that’s an exercise for a future me…)

The Back End

Naturally, I worked on the Rust back end first, starting with the very tedious work of porting my WE32100 CPU core from the 3B2/400 emulator to the new DMD 5620 emulator. It gave me a chance to rethink some things, and also add unit tests where I didn’t have them before (SIMH does not support any unit testing framework, which I thik is a shame). After the CPU core was implemented, I added the other peripherals one by one, emulating them as I went, until I could boot the ROM successfully.

Lucky for me, the DMD 5620 as a system is pretty simple. There’s a ROM, a RAM, a DUART, some non-volatile memory, a couple of status registers, and an optional parallel I/O interface that I’ve chosen not to implement. Fairly easy-peasy. The biggest pain is the 2681 DUART, which is very complex. I was able to crib most of the architecture for this from the 3B2/400 emulator, though, since the 3B2/400 uses the same model of DUART for its console I/O.

If you’re interested in looking at the back end, I’ve published it here on GitHub, and it is available here as a Rust crate.

The Front End

Finally, it was time to stick a front end on it so I could see whether it was trying to talk to me after it booted.

The first front end I built was just an experiment, written in Rust, and not meant to be cross platform. It uses the Piston rust library to draw to an OpenGL window, but otherwise has no interesting features.

The second front end, the one I’ve actually published on GitHub, uses JavaScript for the drawing, and Neon Bindings as a Rust-to-JavaScript bridge. It’s packaged as an ElectronJS app because ElectronJS apps can be built and deployed to all the major platforms, which was an essential goal.

Actually drawing the bit-mapped display is pretty easy. The DMD 5620 exposes a 100KB window of its RAM as video memory, so really all I had to do was iterate over this block of memory, reading it bit by bit, and draw a green pixel if the bit was set, or a black pixel if the bit was not set. Still, it took me a few tries to get it right, because I’m a doofus. In the end, though, I could see the DMD 5620 booting, echoing some status messages to the screen, presenting a cursor, and then waiting for input.

Input handling in the JavaScript front end is accomplihed with keydown, keyup, mousemove, mousedown, and mouseup events. These are fed into the back end as either keyboard UART receive events, mouse button UART events, or memory updates (the DMD 5620 writes the current mouse X and Y position to a pair of registers in memory).

Finally, there has to be a way to communicate with a host. My first implementation is Telnet, which can be used to connect the terminal emulator to a 3B2/400 emulator on the same host, or on a different host. It may be a little counter-intuitive, but the front end is actually responsible for handling the Telnet protocol. The back end is totally agnostic about where characters come from, it doesn’t care. This means I can plug in different character sources, say direct serial interface.

With all the elements put together, it’s a fairly usable system!

0115_dmd5620_layers_sm.png

Odds and Ends

The main pain point so far has been working with the JavaScript ecosystem, which has hitherto been an enigma to me. I’ve found ElectronJS to be somewhat painful to work with because, although it is indeed cross platform, there are many caveats. The primary issue is in recompiling native NodeJS modules across platforms, which took some trial and error to get working correctly. In fact, I still haven’t produced a Linux app bundle yet, because the build keeps failing in ways I don’t quite understand.

In general, it feels like JavaScript and NodeJS modules are a lot more brittle and error-prone than the code I’m used to working with. This may just be something of a blanket statement based on limited experience. I hope so.

Conclusion

I’m happy with how this project progressed. The bulk of the time spent on it was porting the CPU core, which was tedious and error prone (thank goodness for unit tests). The rest of the time seems to have breezed by, thanks to good documentation and a simple system.