A portable CP/M machine

Some time ago I found FabGL, which is a fantastic library implementing a VGA controller and a PS/2 keyboard controller for the ESP32. It means you can use Arduino IDE to create a sketch that talks directly to a real VGA display and a real PS/2 keyboard. For VGA,  Red, Green and Blue signals and Hsync and Vsymc signals are handled by the library, the only thing you need to provide is a DAC made with three resistors (I chose the 8 color mode). The keyboard interface also requires a few resistors for handling CLOCK and DATA signals.

In my case, the main software running on the ESP32 sketch is a Z80 emulator. The emulator, in turn, runs my CZ80 Basic ROM, which I adapted from NASCOM Basic. The ROM is stored in a const array in memory for faster access.

This is how the setup() function initializes FabGL:

// PS/2
PS2Controller.begin(PS2Preset::KeyboardPort0);

// VGA (GPIO 22 to Red, GPIO 21 to Green, GPIO 17 to Blue, GPIO 16 to HSync and GPIO 4 to VSync)
DisplayController.begin(GPIO_NUM_22, GPIO_NUM_21, GPIO_NUM_17, GPIO_NUM_16, GPIO_NUM_4); 
DisplayController.setResolution(VGA_640x240_60Hz);

// Terminal
Terminal.begin(&DisplayController);
Terminal.connectLocally();
Terminal.loadFont(&fabgl::FONT_8x8);
Terminal.setBackgroundColor(Color::White);
Terminal.setForegroundColor(Color::Black);
Terminal.clear();
Terminal.enableCursor(true);

The machine  also emulates two 250KB floppy disks and one 8MB hard disk. The first floppy image is read-only and also stored in flash memory (the ESP32 has lots of flash memory, so I could spare some). This image is bootable and contains a copy of CP/M 2.2 with a a few utilities. I chose the common CP/M floppy format using 77 tracks of 26 sectors each, but with no sector interleaving. The disk images are created with a simple tool written in C.

The second floppy image and the hard disk image are stored on a SD card and are writable. The emulator looks for files named disk1.dsk and hd.dsk on the SD card root and maps them during startup.

CP/M (BIOS, BDOS, CCP) was compiled from source. I used version 1.8 of this z80asm assembler. It is much smaller and much easier to setup than z88dk, but it uses a different syntax. I found the original Digital Research CP/M source code here. The other utilities distributed with CP/M were found here (in binary form).

The Basic interpreter was also compiled from source. It is a custom version I have been using for some years now and has its origins on the NASCOM Basic source listing. A similar version can be found here (but of course without my changes). I had to change the source code a lot because of the different syntax used by the assembler.

I also adapted a version of BBC Basic for CP/M so that it can run on my emulated machine. Again, I adapted the source code for my purposes.

I am preparing a source code distribution of everything, but I am still unsure about some aspects of licensing, mainly because it uses code from Digital Research. There are alternative versions of CP/M that do not use code from DR, but I have not tested them yet.

For now, here is a picture of my test board (with copious amounts of hot glue, naturally):

board1
ESP32 Dev Kit, Micro SD breakout board below it, power jack on the left
board2
VGA connector on the left, PS/2 connector on the right

I have selected to display black text over white background using a 8×8 bitmap font (as seen on the initialization code above). Picture quality is quite good (the white blob at the bottom is a defect of the monitor screen):

cz80

In this session, the computer starts at the Basic interpreter prompt. Then I ran the command “BOOT”, which loads the first sector of the first floppy drive into memory and jumps to it. The boot sector is the first stage of the CP/M boot process, which loads BDOS and then starts CCP. Once in CP/M, I typed a “DIR” command to show the contents of drive A.

This project shares a lot of ideas and code with the hardware implementation of my CZ80 computer. Here hardware is emulated by an ESP32 and the display uses VGA. The real CZ80 will run on actual Z80 and will use composite video for display, but the Basic interpreter is mostly the same (as you can see in the “CZ80 BASIC” prompt above).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s