Cidco MailStation as a Z80 Development Platform

The Cidco MailStation is a series of dedicated e-mail terminals sold in the 2000s as simple, standalone devices for people to use to send and receive e-mail over dialup modem. While their POP3 e-mail functionality is of little use today, the hardware is a neat Z80 development platform that integrates a 320x128 LCD, full QWERTY keyboard, and an internal modem.

After purchasing one (ok, four) on eBay some months ago, I've learned enough about the platform to write my own software that allows it to be a terminal for accessing BBSes via its modem or as a terminal for a Unix machine connected over parallel cable.

mailstation on desk showing main menu


I've been tinkering with old computers in the past few years, but the BASIC-interpreter-hooked-up-to-a-TV or the single-board-6502 never really appealed to me. This is probably because I skipped that generation of computing growing up, with my first computers being full IBM-compatible PCs.

The MailStation has a Z80 processor which is small and easy to program, but it also comes with an integrated LCD and keyboard in a small footprint that can optionally be powered by three AA batteries. Since the Z80 is also used in TI calculators and a bunch of old computers like the TRS-80, there are many resources available for learning Z80 assembly. The instruction set is small and easy to understand, especially while reading disassembled code from the MailStation's factory ROM.

While the MailStation is now twenty years old, I had never heard of them before last year. Fortunately, some very smart and friendly people learned and shared a lot about these devices a decade ago by reverse engineering the firmware and doing various hardware modifications. MailStation devices are still appearing on eBay for $5-$35 today.

Most of the information I learned came from Jeff's MailStation page and the now-quiet Yahoo! group which was active from 2004-2012. Unfortunately Yahoo! Groups no longer makes available any of the files that members uploaded which included a lot of utilities and documentation, though I have archived the public e-mail messages from the group in mbox format for easy searching.

Hardware Specifications

The MailStation was sold in a few different models over the years starting with the Mivo 100, which is what I have:

  • Z80 processor which can operate at 8, 10, or 12 MHz
  • 128 KB static RAM (8 bankable pages)
  • 1 MB flash memory (64 bankable pages of OS code, referred to as "codeflash")
  • 512 KB flash memory (32 bankable pages of user data such as downloaded e-mails, referred to as "dataflash")
  • Rockwell RCV336DPFSP 33.6kbps modem with caller ID
  • Bidirectional parallel port
  • 320x128 monochrome LCD
  • Real-time clock
  • 72-key QWERTY keyboard
  • "New Mail" LED

Because the Z80 is an 8-bit processor and can only access 64 KB of address space (0x0000 - 0xffff), the additional pages of RAM, flash memory, and I/O devices are banked into one of two slots at 0x4000 and 0x8000 at any given time. The first 16 KB of address space always corresponds to the first page of the 1 MB of OS code ("codeflash") and the last 16 KB is always the first page of the 128 KB of RAM.

Unfortunately since the first 16 KB is not RAM, it is not an easy target for porting the CP/M operating system. A hardware modification can be done to bank in a page of RAM for the first 16 KB of memory and reportedly a CP/M BIOS has been written to work in this configuration. I have concentrated my efforts on running code without any hardware modifications.

Loading Custom Code

When used as an e-mail terminal, the Mailstation could download specially formatted and authenticated "Clipmail" e-mails that would allow the settings on the device to be changed, such as the user's e-mail password or the dialup number.

Cidco partnered with Yahoo! for Mailstation users to receive Yahoo! content in the form of small applications that were downloaded to the devices through Clipmail. These were simple single-screen applications (mostly just a full-screen bitmap) that showed TV listings, horoscopes, weather, etc. Cidco would send out Clipmail e-mails and when each Mailstation automatically dialed up overnight and fetched them via POP3, there would be new Yahoo! content waiting for the user the next day.

Old Mailstations purchased off of eBay will sometimes have these old applications with TV listings and weather data frozen in time, providing a snapshot of life in the mid-2000s.

These applications are each stored in a separate page of dataflash and presented to the user under a Yahoo! menu, or on some devices, through an Extras menu. Up to five applications can be stored at a time.

"Loader" and "FlashLoader" are custom applications that I loaded

The easiest way to load arbitrary code onto the Mailstation is by acting as one of those Yahoo! applications and writing the program code to the dataflash chip where it will automatically show up in this Yahoo! menu.

As luck would have it, the Mailstation ROM contains a built-in hex editor that can view or edit any data on the dataflash through a secret menu. By holding down Fn+Shift+T when pressing the Power button, the Diagnostic Menu can be accessed:

Pressing Shift+F5 (the right-most grey button under the screen) will open the hex editor and pressing g will prompt for an address. By entering 710304x as the address (the x must be typed but will not be shown) it enables write-mode, which can then be accessed by pressing s.

In case you thought the g710304x label in these pictures was my password…

Once in write mode, raw Z80 opcodes can be entered, composing an executable program. If it follows a particular layout, it will be made available as an application under the Yahoo/Extras menu complete with name and icon.

Of course, hand-typing hex digits can be tedious and error-prone, so an easier way to load custom code is by bootstrapping with a loader program (the binary of which is just 97 bytes to type in). When run from the Yahoo! menu, this loader application will just wait for new code to be sent over the parallel port, copy it into RAM, and then execute it. The documentation for this loader program goes into more detail about how apps are structured on the flash.

To send code from another computer through the parallel port, a LapLink cable (I'm using a Belkin F3D508-10) must be used along with a sending program.

Unfortunately the cross-section of computers that are fast and comfortable enough to do development and compilation, and old enough to have a real parallel port is not very large these days. In my case I am running OpenBSD on an HP OmniBook 800CT that just acts as a proxy, listening on a TCP port for data and then sending anything it receives over its parallel port in the custom format the MailStation expects. This allows me to edit and compile code on my main laptop and send it over the network with nc to the OmniBook, where it then gets uploaded to the Mailstation and executed.

Perhaps someone more skilled than me can program some USB device like an Arduino to emulate an LPT port to make it easier to transfer code.

Update (2020-03-31): Apparently I am more skilled than I was last year and have finally made a USB loader.

Update (2021-04-30): I've also made a WiFi device for the MailStation called WiFiStation that can load code over the network.

Once a program has been tested by this dynamic loading, it can eventually be written to the dataflash itself to show up in the Yahoo! menu as a standalone application. Add three AA batteries and you can have a completely portable Z80 computer running your own applications.

Development Environment

I am developing on my OpenBSD laptop writing C and Z80 assembly in Vim. I compile code with SDCC and then upload to the Mailstation over parallel port as described above (with make upload).

SDCC provides a small Z80-specific C library implementing things like printf, but device-specific code had to be written to implement putchar and getchar to interface with the Mailstation's custom LCD and keyboard.

Most of the original code fragments I found for the MailStation on the Yahoo! Group were written to compile with the Kingswood AS80 assembler for DOS/Windows, so I have rewritten everything I used to assemble with SDCC's asz80 assembler. Additionally, all of the host-side tools like the program to send code to the MailStation were written to run on Windows, so I have written new tools that run on OpenBSD (which could probably run on Linux quite easily).

Since much of the information available for the MailStation is scattered across hundreds of mailing list posts and defunct forums, I've tried to assemble much of it, along with my tools, in a central repository that will hopefully not get lost to time and Yahoo! acquisitions.

Update: An SDL-based emulator for the MailStation was being developed back in 2010 and has resumed development under new developers.

MailStation Firmware

The OS that runs the MailStation is fairly easy to use given its target audience, and rather performant, especially given its slow CPU clock speed.

Some members of the Yahoo! Group were focused on reverse engineering that firmware code to map out all of the built-in functions and understand how it works, in order to write custom applications that acted like the built-in utilities. I'm not sure exactly what tools they were using a decade ago to disassemble the firmware, but it makes for some tricky reading.

It's relatively easy to read disassembled Z80 code and understand what it does, but it's much harder to understand why it's doing what it is, especially with the MailStation's memory layout.

The first 16 KB page of firmware code from the codeflash chip is located at 0x0000 with each additional 16 KB page able to be swapped into slot 8 (0x8000) at any time. However, each 16 KB page of dataflash can also be swapped into this region. This can make it difficult to follow when reading since each page (after the first) is written as if it is located at 0x8000 and this code often swaps in a new page at the same location it's being run from. So code running at, say 0x8123, will call a function in the permanent first page which will swap in a new 16 KB page of code at 0x8000, execute a function in that space, then swap the old page back in and return to 0x8123.

While I was working on this over the past few months, Ghidra was released and included Z80 CPU support, which has been fairly helpful in turning assembly functions into pseudo-C code to better understand what's going on.

Eventually I hit enough roadblocks trying to understand and use the built-in firmware functions that I decided to re-implement most of what I needed myself. However, I still need to read the firmware code quite often to figure out how to interface with particular hardware or try to figure out what some existing variable in memory is for.

Creating msTERM

My goal for the MailStation was to write a terminal program allowing me to dial into BBSes and make full use of the MailStation's internal modem. This required writing a custom putchar that could handle absolute cursor positioning and attributes (underline, reverse, etc.), a getchar routine to read from the keyboard that could handle using Caps Lock as a Control key, an ANSI escape code parser, and eventually a custom interrupt service routine (ISR) to communicate with the modem.

I also modified the 5x8 Spleen font to add many of the 437 code page characters used by many BBSes and ANSI art for drawing shapes and shading.

Before I figured out how to properly communicate with the modem, I made msTERM able to communicate bi-directionally over its parallel port using the LapLink cable. On the host side, a small program interfaces between getty and its parallel port using specific routines for sending a byte in 3 pieces, which specific functions in the firmware of the MailStation expect. This allowed me to login to my OpenBSD laptop from the MailStation and then telnet to the Level 29 BBS:

Communicating with the Modem

After weeks of reverse engineering the MailStation firmware's code and reading the modem chip documentation, I realized that the built-in interrupt service routine (ISR) of the MailStation firmware was responding to the modem before my program could get a chance to, so I had to implement my own ISR to take over all interrupt handling. Since I couldn't easily change the firmware code without reflashing, I used the Z80's interrupt mode 2 to have it call my own ISR while msTERM is running.

This finally allowed me to communicate with the modem and issue AT commands like normal. Fortunately there is great documentation available for the modem chip that made this pretty easy once I had the ISR working.

At this point I've got most of the modem functionality working and can use it to dial into BBSes, though it drops data on faster connections because my putchar routine is too slow to draw lots of text on the LCD. This is because I'm using a font that is not 8 pixels wide (to get a bigger terminal) but the LCD has to be addressed in columns of 8 pixels wide, so drawing one character usually requires reading the characters around it and redrawing halves of them to redraw a column on the LCD.

msTERM Release

I've released the code to msTERM and am continuing to improve things. I recently added the ability to read the MailStation's RTC to display the current time on the status bar, and am blinking the New Mail light when the modem passes data, like an external modem.

If you're interested in playing with one of these devices, pick one up on eBay and reach out. I'd love to get help with msTERM or help anyone else wanting to write a BASIC interpreter or something fun.

Update (2021-04-30): I've abstracted code from my msTERM project to a small example project that should make it easier to get started writing your own programs for the MailStation. I've also created a WiFi adapter for the MailStation called WiFiStation that makes it easier to upload code and get the MailStation talking to the internet.

Questions or comments?
Please feel free to contact me.