Arduino Leonardo Cartridge Reader
Extracting the data of a P2000T SLOT1 cartridge is a simple matter of connecting to the cartridge and reading the internal ROM chips, very much in the same manner as the P2000T machine itself would do it. Obviously, we would like to do this in a non-invasive manner, i.e., without opening and/or damaging the original cartridge.
This page discusses a cartridge reader solution using the Arduino Leonardo. Another option is to use the P2000T adapter plate together with the PICO SST39SF0x0 Programmer.
To this aim, an Arduino Leonardo HAT (HAT stands for "hardware attached on top") is developed that can be nicely inserted into the sockets on the Arduino as shown in Figure 1. On mounts the cartridge onto the socket and uses a simple Python script (explained below) to read from the cartridge.
In Figure 2, the schematic of the cartridge reader is shown. As the Arduino Leonardo does not
have enough pins for both the address as well as the data lines on the cartridge, we have to use
some additional logic chips. One could use for example shift registers, but here we have opted for
4040 chip as an efficient counter to set the values on the address lines.
4040 chip sets the first 12 address lines and the Arduino Leonardo is responsible for the
A12 line as well as the
CARSEL2 signals. These latter three lines effectively
set the internal
A13 lines on the ROM chips. The details of this mapping can be found
CRES lines correspond to the clock and reset lines of the
4040 chip, the former
resulting in the chip counting up and the latter resetting the address lines. Finally,
connected to the data lines on the cartridge.
Preparing the Arduino Leonardo
To allow the Arduino Leonardo to interface with the cartridge, first some firmware has to be written
to the cartridge. The firmware can be found in the Github repository.
Download the repository and open
arduino/cartridge_reader_firmware/cartridge_reader_firmware.ino using the Arduino IDE. (see Figure 3)
Ensure that the correct board is set via
Tools > Board > Arduino Leonardo. Next, test that firmware compiles by clicking
Sketch > Verify/Compile (shortcut: CTRL + R). If everything compiles, you can upload the firmware to the Arduino by
Sketch > Upload (shortcut: CTRL + U). Your Arduino is now ready to receive instructions.
Reading from a cartridge
To extract the data from the cartridge, mount the cartridge such as shown in Figure 4.
Ensure that the front side of the cartridge is facing away from the
4040 chip. In other words,
the front side of the cartridge is on the same side as the
ANALOG IN pins of the
The Arduino Leonardo communicates with your computer over its serial port. It receives 8-byte command words after which a certain operation is conducted. A number of Python scripts are provided in the repository to show how the interfacing works. It is recommended to run the Python scripts from an IDE environment such as Spyder. Spyder can be easily installed as part of the Anaconda package which is essentially a complete and bundled Python environment.
Before reading any cartridges, it is important to first test that your cartridge reader is properly working. To this aim, two important tests need to be executed as explained below.
Testing the interface
To test the interface, open
scripts/serialtest.py and execute it. What the script does is automatically find
the COM port to which the Arduino Leonardo is connected, open that port and send the command
READINFO to the Arduino. The response should be an echo of the command followed by a string
identifying the firmware (typically something like
P2k0_V1.0.0_____). The result of the test should
look as follows:
Ran 1 test in 0.018s
Testing reading from cartridges
The next test is actual reading from a cartridge. For this test, you need to have a (copy of) the
BASICNL v1.1 ROM. Mount this cartridge into the cartridge reader and open the file
scripts/comparison_test.py. Similar to
serialtest.py, this test first tries to find the
PORT to which the Arduino Leonardo is connected, after which it opens the port and verifies
READINFO command can be executed. If this works, the program will read the complete
cartridge by reading 4 times
0x1000 (4kb) of data. Effectively, the scripts sends the commands
RB003000, each invoking a read operation wherein
bytes are read starting at the address designated in the command. After echoing the command back,
the data follows as a binary stream. These binary streams are collected and combined into a
large bytearray. Finally, a MD5 checksum is generated of this bytestream and verified whether
this checksum matches the one of the BASICNL v1.1 ROM cartridge.
The result of this test should look as follows:
Reading bank 0
Reading bank 1
Reading bank 2
Reading bank 3
Ran 1 test in 1.159s
Reading data and storing result
If the previously explained two tests gave satisfactory results, you are ready to actually read
from a P2000T SLOT1 cartridge. For this purpose, the Python script
scripts/readrom.py has been
designed. Similar to the previous two scripts, this script opens an interface to the Arduino Leonardo,
executes the read operations and collects the result. The collected bytestreams are stored
in a file called
rom.bin which can be found in the same folder as where the
Below, example output is provided when executing this script for the BASICNL v1.1 ROM. To get a first impression on the content of the ROM, the first 256 bytes are printed in hexadecimal notation.
Reading bank 0
Reading bank 1
Reading bank 2
Reading bank 3
First 256 bytes read:
5E FB 0F 00 80 52 6F 62 52 6F 62 38 33 02 00 00
C3 66 1F C3 E6 60 C3 C4 1F 1C 86 8D 50 48 49 4C
49 50 53 20 43 41 53 53 45 54 54 45 20 42 41 53
49 43 04 03 02 83 56 65 72 73 69 65 20 31 2E 31
86 4E 4C 04 05 02 86 00 C9 00 C3 C0 60 C3 3A 19
C3 D0 60 C3 48 15 C3 5A 1F C3 4F 17 C3 E2 16 C3
C3 60 C3 18 19 C3 53 1D C9 00 00 C9 00 00 C3 63
24 C3 F3 14 C3 2C 15 C3 30 13 CD 30 13 D0 CD 3E
11 3E 50 18 CE 2A B3 60 EB 2A AD 60 19 F5 7C 87
87 84 67 7D 6C 26 05 29 29 29 29 22 B1 60 85 6F
30 01 24 F1 C9 CB 3E 38 03 23 77 C9 CB 3E 5F 23
56 38 16 1D 15 2A AF 60 7D BA D8 7C BB D8 7B 32
B4 63 EB 22 B3 60 C3 3E 11 B7 C8 AF 6F 4F 14 1D
28 01 0C F3 A9 D8 D8 D3 50 43 2D 20 01 15 28 04
10 F8 18 F0 FB 3E 07 18 10 3A B4 60 3C 32 BD 60
3E 03 01 3E 0D E1 01 3E 1D 32 BC 60 C9 21 BC 60
All source files, i.e. the PCB design, the Arduino Leonardo firmware and the casing, can be found in this Github repository.