In this post, I run CP/M on the RC2014
While browsing around Grant Searle’s website looking at his Z80 projects one day, I stumbled upon his CP/M project and it sounded like a great idea to reproduce this on the RC2014.
CP/M is a disk operating system that was popular from the 1970s to the 1980s. It was particularly popular on 8-bit microprocessor platforms such as the 8080 and the Z80. There were also variants for the 8086 processor. People who grew up with MSDOS, but never experienced CP/M, will probably feel that DOS resembles CP/M in many ways.
By running CP/M on our RC2014, we can get access to a wide variety of software — from programming languages (Basic, Forth, C) to games like Zork. Access to a disk allows permanent store of programs and data.
RC2014 Modifications required
To run CP/M on the RC2014, it’s going to take several modifications:
- Replace the default 68B50 serial board with a SIO board
- Replace the individual RAM and ROM boards with a banked RAM/ROM board
- Add a CompactFlash board
The CompactFlash and SIO serial board have been discussed in prior blog posts, so the board that I will introduce in this post is the banked RAM/ROM board.
Why we need the Banked RAM/ROM board
The default RC2014 used a single ROM and a single RAM chip. The ROM occupied addresses 0000h to 2000h (8KB) and the RAM occupied addresses 8000h to FFFFh (32KB). This was perfect for the BASIC interpreter since we could easily fit the interpreter into 8KB of ROM, and 32KB was plenty of space for holding out BASIC program. For CP/M there are two issues:
- 32KB of RAM is more restrictive than we’d like
- CP/M wants locates operating system data at 0h and programs at 100h, which is smack in the middle of the RC2014’s default ROM.
So the approach that we’re going to use is to boot from ROM (still at 0000h), load the CP/M BIOS and runtime into high RAM at E1600h and D000h respectively, jump into high RAM to continue executing, and finally replace the low ROM with a second RAM chip. We boot off ROM, but we end up in a state where we have all 64K of address space occupied by RAM.
Design of the Banked RAM/ROM board
The basis for this came from Grant Searle’s CPM project, though I have made a few modifications. I wanted it to be easily possible to switch back to ROM under program control, and to bank switch in additional RAM chips if we wanted to. Here is my schematic:
There are a total of two RAM chips, IC1 and IC2. IC2 is always active and is addressed from 8000h to FFFFh. IC1 is only active after it has been bank switched in and is active from 0000h to 7FFFh. We could have lowered the chip count by using a single 64KB RAM chip and playing a few different tricks with the addressing, but I already had 62256 32KB RAM chips, and decided to optimize keeping my inventory simple.
IC5 is a 64KB EPROM. It’s also addressed a 0000h. There are some jumpers to the A14 and A15 pins of the EPROM that allow us to map in a 16KB chunk out of the 64KB EPROM. This allows us an easy way for us to store four different programs in the ROM and select which one by moving jumpers about. Spencer did the same thing with the RC2014’s 64 KB ROM board.
So the trick, and the purpose of the other four ICs, is to be able to selectively switch between the EPROM, IC5, and the low RAM chip, IC1. We start with a 74HCT238E 3-to-8 decoder (NOTE: a 74HCT138 might also work and simplify inventory requirements; need to try this). This sets a port that can be used to control the bank switching. The addressing is a little bit different that my other 74HCT138-based boards in that I spaced the addressing ranges 8h apart. You can put the bank-select port at 0h, 8h, 10h, 18h, 20h, 28h, 30h, or 38h. I did this to maintain compatibility with Grant Searle’s CP/M design, which places the bank switch address at 38h.
Writing to the bank select port clocks D0 and D1 into a pair of flipflops on a 74HC84N. The RC2014’s RESET pin is connected to the clear pin of the flipflops, so that a reset will always reset the flipflops back to zero. This allows us to write any of four values — 0, 1, 2, or 3 — to the flipflops and will serve as our bank select. The default is zero.
The output of these flipflops is used as the input to a 74HCT139N dual 2-to-4 decoder. When A15 is high, it will cause the 74HCT139 to assert low one of four outputs based on the value it’s currently receiving from the flipflops. Output 0 is connected to the ROM. Output 1 is connected to the RAM. Outputs 2 and 3 are connected to a header to allow additional RAM chips to be added at a later date.
The second half of the 74HCT139N is wired up to function as an inverter. I needed an inverter to invert A15 so that it could drive the IC2 from 8000h to FFFFFh. Rather than add a 7404 of inverter for this purpose, I figured out how to repurpose the unused half of the 74HC139.
To make a long story short:
- On reset, the EPROM (IC5) is selected
- If you write a 0 to the bank select port, the EPROM (IC5) is selected
- If you write a 1 to the bank select port, the LOW RAM (IC1) is selected
- If you write a 2 to the bank select port, pin 1 of JP3 is selected, to support an external RAM chip
- If you write a 3 to the bank select port, pin 2 of JP3 is selected, to support an external RAM chip
Here’s how the CP/M boot sequence works:
- The ROM loads the CP/M runtime and BIOS into RAM at D000h and E600h respectively. The entrypoint to start CP/M is at FFFEh.
- The ROM then jumps to RAM at address FFFEh
- The CPM bios writes 1 to port 38h. This causes the ROM to be deselected and the low RAM to be selected in it’s place. This selection remains in effect until the board is reset (or some program writes a different value to port 38h).
- We’re now running entirely in 64KB RAM. The ROM is completely out of the picture.
Here is a picture of the completed RAM/ROM board
For the other necessary boards (SIO, CompactFlash), see my other blog posts.
Modifications to CP/M
I made a few modifications to Grant Searle’s CP/M monitor, BIOS, and other support tools.
- I put the compactlflash at port E0h instead of at port 10h. I like keeping the 00h-79h range free for peripherals like IO boards and such.
- I put the SIO/2 at port 80h instead of port 0h. This is for the same reason as above.
- I significantly increased the size of the serial receive buffer. Flow control isn’t working for me, and XMODEM transfers were overflowing the buffer at its original size.
- Optionally, I have support for my CTC board at 90h. This is a work in progress and it to allow baud rates other than 115,200.
- I modified the bootstrap procedure that loads download.com and the format tool to load from 8100h instead of 4100h.
Installing CP/M on the RC2014
I followed the instructions on Grant Searle’s page, and things went amazingly well and trouble free
- Hardware Configuration for RC2014
- SIO/2, CompactFlash, and Banked RAM/ROM board installed
- Monitor ROM installed
- Format the Flash Card
- Boot to monitor
- paste form64.hex into monitor
- type “G8100”
- (note: assumes smbaker’s changes that relocate from64 from 4100h to 8100h)
- Install CP/M
- Boot to monitor
- paste cpm22.hex
- paste cbios64.hex
- paste putsys.hex
- type “G8100”
- (note: assumes smbaker’s changes that relocate putsys from 4100h to 8100h)
- Boot into CP/M the very first time
- Boot into monitor
- Press “X” (boot to CPM)
- Press “Y” (confirm boot)
- You’re now staring at the A> prompt
- Install Download.com
- Press RC2014 reboot button while CPM is running. This will boot to the monitor.
- Paste down8100.hex
- (note: assumes smbaker’s change that relocates download.hex from 4100h to 8100h)
- Type “GFFE8”. This will cause the monitor ROM to bank switch, and automatically copy down8100.hex from 8100h to 100h
- You should be starting at the A> prompt again
- Type “SAVE 2 DOWNLOAD.COM”
- This will cause the program that is currently located at 100h to be saved to disk under the name “DOWNLOAD.COM”
At this point, you have a minimally functional CP/M system, with a single program called DOWNLOAD.COM that you can use to download other programs into the RC2014. Grant Searle’s page has links to a bundle of useful tools (LOAD, SUBMIT, DISPLAY, PIP, STAT, DDT, DUMP, ED, ASM). I recommend installing all of these, as they are pretty useful.
I also found it very handy to install XMODEM, since my terminal program has a built-in XMODEM client. I found some XMODEM source in a google thread at https://groups.google.com/forum/#!topic/comp.os.cpm/-oI2ydzFrC8. There were a few issues I had to fix in this XMODEM program to get it to work on my CP/M RC2014. These are documented in patches/xmodem.patch in my RC2014 github repo. The two primary issues I ran into were a stack overrun which forced me to relocate where xmodem was storing its stack, and a call to RXTIMR that was causing the receive routine to prematurely terminate.
Once XMODEM is installed, it’s a simple matter to upload additional software like this:
- type this: “xmodem filename.ext /r /x0”
- initiate an xmodem upload in your terminal
The /R instructs xmodem to operate in receive mode. The /X0 tells it to transfer using the CP/M console.
CP/M Software Resources
There are several sites with useful resources on the web. At RetroArchive you can find Zork 1-3, a variety of programming languages including Microsoft Basic, etc. Note that some of this appears to be commercial software (for example, Turbo Pascal) so I haven’t provided direct links here. Note that there is both -86 software and -80 software on this site. For a Z80, you’ll want the -80 software.
cpm.z80.de is another resource, and has programming languages, tools, emulators, etc. There seems to be a lot more -86 software here than -80 software though.
Bill of Materials
- pcboard, Osh-Park
- 40-pin right handle 0.100″ male header
- 2×8 pin 0.100″ male header
- (3) 1×3 pin 0.100″ male header
- (2) 62256 static RAM
- EPROM, 27C512 suggested, others may work
- (5) 0.1uF capacitor
- IC sockets as desired (probably smart to at least socket the EPROM)
RAM/ROM PCBoard Ordering
As usual there’s an Osh Park link for ordering the banked RAM/ROM board:
As with all the other boards, I don’t make any money from this. I’ve just made the boards available on Osh Park for anyone else who wants them.
To order the other boards (SIO, CompactFlash), see my other blog posts.
Congratulations, I’ve been following your blogs on the RC2014 since I stumbled across them after looking at Grant Serles pages. I made his FPGA version, but have more fun with the RC2014. I’ve got the 5 slot backplane and a working RC2014. I’m building my own CF card interface to plug into it. My plan until this morning!! was to have
as I have built the clock onto the CF Card board. I use Veroboard for prototypes rather than PCB, but I’m impressed with your boards. Well done.
I’ve just ordered an 8 slot backplace as I want to build an I/O board using the Z80PIO and also get my original RadioShack Sound Chip SPO256A-AL2 chip working.
Your latest CPM board is where I have been heading and I am impressed and very grateful for the work you are doing. Your blog makes very interesting reading.
What timescales do you get with OSHPark? I have ordered some of your boards (SIO and SP0256) about a month ago, but not got any replies or updates?
Years ago in a previous life, I used to work for Digital (DEC ) in the UK and one of the things I did there was to rewrite the BIOS for their VT180 CP/M machine to support their new RX50 floppy drives, so CP/M is in my blood.
Paul Bigwood G3WYW
I would say the average wait I get from Osh Park from submitting my order to shipping is around 2 weeks. I would definitely inquire with them if you’ve been waiting for a month, as I don’t think I’ve ever had an order from them take so long. Usually you get a number of emails, starting with “Order Received”, then “Assigned to Panel”, then “Sent to Fab”, a week or two goes by, then “Received from Fab”, and finally “Shipped”.
Good luck with your RC2014 project!
OK thanks, I’ll email them for an update. I discovered today that the board layouts (*.brd) are on their website, so I’ve downloaded them and can view fine on Eagle. Checking local UK prototype sources to see if they are any easier.
Have you thought of doing an intelligent parallel printer port with Centronics interface using a Z80PIO?
Got the boards from OSHPark last week, and the RAM/ROM board is built as is the SIO card with Clock and CF card nearly completed. Currently investigating software for the ROM card. As I understand your Github, I need to download the stuff from Grants site ( already done) and move these to my Raspberry Pi, and also download your .sh files to apply the mods to those. This will create a hex file to blow into a rom to boot. I have decided to skip building the CTC card for the present and have jumpered the SIO card so both COMPorts run at 115200Baud. Havent investigated the impact on the code of NOT having the CTC card installed.
Have I got that right so far?
Best Regards and Thanks again for a great design.
Both COM ports at 115200 baud will be fine. If you want to be able to use the ROM monitor with the second serial port, then you might need to adjust the code in the monitor that configures the second serial port (the divisor gets set differently when using the CTC). The first serial port will work regardless, since I never used it with the CTC.
There are a few additional steps that you need to perform to patch the code. I haven’t documented them anywhere — I’ll see if I can get the time this week. Basically, I created some patches against Grant Searle’s CPM code using the Linux “diff” tool. These patches changed some IO port addresses, moved some things to 8100h, etc. You have to run the Linux “patch” tool to apply those patches to Searle’s code, which will result in my modified code. Then you assemble that and generate the ROMs.
My .sh files used an assembler called “zasm” and I also had to patch a bug in that and compile it. Something to do with hex files being output at the wrong address.
To exit “mbasic” type “system”.
CP/M is working great!
I am truly amazed with the work and also G Searal. The download.com program is a very handy tool. I know need to figure out how to convert a Z80 program in to hex and use the download.com tool to write the new files on to the Compact flash card.
I am trying to rebuild the monitor ROM that is used to load the CP/M code and then boot CP/M. I would like to use an SIO/2 board for serial I/O and a CF card at 10H (not E0H). Whilst I can modify Grant Searle’s original monitor.asm code, you seem to have made some good improvements to the code for the serial ports. If possible, please can you add your version of monitor.asm to your RC2014 GitHub repository.
Got a question regarding schematic and pcb layout programs you use?
Are these done with Eagle pcb design?
Great blogs. Just starting out on the floppy disc boards. Got cpm/m running on CF card fine. Now adding a floppy will enable me to xfer all the stuff I have on them.
I use EasyEDA to fab my PCB’s. Are you okay with sending the Gerber’s for a board to EasyEDA for fab?
I’m guessing that the 74HC84N mentioned on paragraph 5 of the ‘Design of the Banked RAM/ROM Board’ section is supposed to be 74HCT74N, given the BOM & Schematic? 🙂
This has been a super interesting read and really helpful, indeed! It’s always a pleasure reading about the design of your projects.