This project demonstrates how to run a CP/M emulator on a tiny board. If you prefer a genuine CP/M experience on a small device, consider the eZ80-based eZ-Tiny computer.
IntroductionRunCPM is a Z80 CP/M emulator that supports many platforms. Setting up and running the emulator is particularly easy on Linux and macOS. For instance, you can build and run a CP/M computer using something as inexpensive as a Raspberry Pi Zero, an old display, and a keyboard.
But what if we could run a CP/M computer on an even tinier board?
There is a fork of RunCPM called RunCPM_RPi_Pico, designed specifically to run CP/M emulation on a Raspberry Pi Pico:
While this setup is compact and functions well, we can take it a step further by eliminating jumper wires and pin headers. By using a board that integrates both the RP2040 MCU and a microSD socket—such as the Adafruit Feather RP2040 Adalogger—we simplify the build. There is also an STM32F4-based Adafruit Feather with a microSD socket. The STM32F4 operates at 200 MHz, compared to the 133 MHz of the RP2040, but RunCPM_RPi_Pico is specifically designed for the RP2040, not the STM32F4.
Setting Up the Adalogger- Clone the RunCPM_RPi_Pico repository.
- Choose a version directory, for example
v6_7
. - Unzip one of the archives—for example
GL20241103_Binary_Source_RunCPM_v6_7_Pico2_275Mhz.zip
. - In the newly created directory, find the Arduino sketch of RunCPM, for example
RunCPM_v6_7_Pico2_275Mhz_03112024.ino
. - Open the sketch in the Arduino IDE.
- Ensure that the board is recognized in the IDE as "Adafruit Feather RP2040 Adalogger". You may need to first install the board support package as explained here.
- Upload the sketch to the board. If the Output log indicates that the upload process is taking a long time or continually searching for RP2040 devices, press the board’s Boot and Reset buttons (holding down Boot while pressing Reset) to exit the loop.
- In the Arduino IDE’s Serial Monitor, set the baud rate to 115200.
- Make sure you see the CP/M Emulator greeting in the Serial Monitor (press the Reset button on the board if needed). Normally, it looks like this:
- You'll notice that the last line starts with "CPU-Clock" and lacks any mention of the microSD card. Let's address this issue.
- First, note that the SD card in the Adalogger communicates via
SPI1
, notSPI
. Also, the MISO and SS/CS pins are different from those used in the Raspberry Pi Pico version. - Replace this snippet in the sketch:
SPI.setRX(16); // MISO
SPI.setCS(17); // Card Select
SPI.setSCK(18); // Clock
SPI.setTX(19); // MOSI
With this one (see https://learn.adafruit.com/adafruit-feather-rp2040-adalogger/pinouts#microsd-card-slot-3174751 for details):
SPI1.setRX(20); // MISO
SPI1.setCS(23); // Card Select
SPI1.setSCK(18); // Clock
SPI1.setTX(19); // MOSI
- About a dozen lines below, replace
#define SS 17
with#define SS 23
. - In this line
#define SD_CONFIG SdSpiConfig(SS, DEDICATED_SPI, SD_SCK_MHZ(SDMHZ), &SPI) // self-selecting the Mhz
replace &SPI
with &SPI1
).
- Add these lines
#undef LED
#define LED 13
after
// Raspberry Pi Pico(2) - normal (LED = GPIO25)
#include "hardware/pico/pico_sd_spi.h"
- Replace the line
_puts(" running on Raspberry Pi [\e[1mPico-2\e[0m]\r\n");
with
_puts(" running on Raspberry Pi [\e[1mRP2040 Adalogger\e[0m]\r\n");
- Upload the updated sketch to the board.
- Copy the contents of the
SDCARD
directory to your microSD. - Insert the microSD into the Adalogger and press Reset. You should see a CP/M prompt,
A0>
, which indicates disk driveA
, user0
. - The Serial Monitor is not the most convenient tool for interacting with the board; using TeraTerm provides a better experience.
If you want a more realistic Z80 experience:
- In
globals.h
, comment out the line#define CCP_DR
and uncomment the line#define CCP_Z80
. Also inglobals.h
, comment out the line#define TPASIZE 64
and uncomment the line#define TPASIZE 60
. - Copy the file
CCP-Z80.60K
to (the top directory of) the microSD. - In the directory
/A/0
of the microSD, copy the fileABDOS.Z60
toABDOS.SYS
.
Comments