ikjordan / picozx81

ZX81 emulator for Raspberry Pi Pico
GNU General Public License v2.0
37 stars 2 forks source link

A Sinclair ZX81 and ZX80 Emulator for the Raspberry Pi Pico

Contents

Features

Both the RP2040 and RP2350A is supported

Examples

Installed in a reproduction case

The following images are taken with permission from a thread on SinclairZXWorld and show how user computergui has used picozx81 together with a case created by user Spinnetti to create a replica ZX80

3d printed ZX81 USB keyboard, USB joystick and LCD

The left image shows a system with a 3d printed ZX81 case being used as a USB keyboard. A usb hub allows control via the keyboard and a joystick. The high resolution version of Galaxians is displayed on screen

The right image shows the emulator running MaxDemo, which generates a 320 by 240 display, exactly filling the 2.8 inch Waveshare LCD

HDMI/DVI Output

To the left SplinterGU SInvaders can be seen on a TV connected over HDMI. Sound can also be played over HDMI

To the right can be seen a status page, illustrating some of the configurable options for the emulator

LCD Displays with Cytron Maker Board

Cytron Maker Pi Pico with Waveshare 2.0" LCD (ST7789V controller) displaying the 25thanni full screen demo

Cytron Maker Pi Pico with Generic 3.2" LCD (ILI9341 controller) displaying the 25thanni full screen demo

Dedicated hardware

PICOZX with VGA and LCD output running 3D Monster Maze

Pictures supplied by zzapmort

PICOZX in a Spectrum case

A ZX81 disguised as a Spectrum!

Chroma 80 and Chroma 81 Emulation

ColourAttrModeTest and HiRes ZX-Galaxians

Quick Start

The fastest way to get started is to:

  1. Write data onto a Micro SD Card
  2. Install the pre-built binary onto your Pico
  3. Connect your board to a keyboard and start exploring

Populate the SD Card

  1. Click here to download a zip file containing files and directories to copy to an empty micro SD card
  2. unzip the file into the root directory of an empty micro SD Card
  3. Insert the micro SD Card into your boards micro SD card slot

Load the pre-build binary onto the Pico

Click on the uf2 name corresponding to your board in the table below to download the latest version

RP2040

Board uf2 name
Pimoroni DVI picozx81_dvi_rp2040.uf2
Pimoroni VGA picozx81_vga_rp2040.uf2
Olimex PICO DVI picozx81_olimexpc_rp2040.uf2
PicoMiteVGA picozx81_picomitevga_rp2040.uf2
Olimex PICO DVI with HDMI Sound picozx81_olimexpc_hdmi_sound_rp2040.uf2
Pimoroni DVI with HDMI Sound picozx81_dvi_hdmi_sound_rp2040.uf2
Waveshare PiZero with HDMI Sound picozx81_wspizero_hdmi_sound_rp2040.uf2
Waveshare 2.8 LCD picozx81_lcdws28_rp2040.uf2
Cytron Maker + 320x240 LCD picozx81_lcdmaker_rp2040.uf2
Cytron Maker + VGA 222 CSYNC picozx81_vgamaker222c_rp2040.uf2
PICOZX picozx81_picozx_rp2040.uf2
PICOZX with LCD picozx81_picozx_lcd_rp2040.uf2
PICOZX for ZX-Spectrum case picozx81_picozxreal_rp2040.uf2

RP2350

Board uf2 name
Pimoroni DVI picozx81_dvi_rp2350.uf2
Pimoroni VGA picozx81_vga_rp2350.uf2
Olimex PICO DVI picozx81_olimexpc_rp2350.uf2
PicoMiteVGA picozx81_picomitevga_rp2350.uf2
Olimex PICO DVI with HDMI Sound picozx81_olimexpc_hdmi_sound_rp2350.uf2
Pimoroni DVI with HDMI Sound picozx81_dvi_hdmi_sound_rp2350.uf2
Waveshare 2.8 LCD picozx81_lcdws28_rp2350.uf2
  1. Connect your Board to your display using a VGA or HDMI cable, as appropriate for your board
  2. Connect the Pico to your PC using a USB cable, whilst pressing the BOOTSEL button on the Pico. Use the micro USB connector on the Pico, not the micro USB cable on your board
  3. The Pico should appear on the PC as a USB drive
  4. Drag the uf2 file that you downloaded onto the USB drive
  5. The file will be loaded onto the Pico, which will then reboot. You should see the familiar K prompt appear on your display

    Connect to a keyboard

  6. Remove the USB cable from the Pico. Plug a USB keyboard into the Pico. You will need an OTG adaptor cable to do this
  7. Plug a micro USB power supply into the USB connector on your board. You can also power your board directly from your PC using a micro USB cable
  8. You now have an emulated ZX81 with a working keyboard and display

    Next Steps

    Read on for more information. The Applications Tested section contains links to free downloads of some of the most iconic ZX80 and ZX81 software

Use

First Time

Configuring the Emulator

The capabilities of the emulator are set using configuration files stored on the SD Card

Configuration Files

Configuration attributes (described in the following sections) are set via config.ini files. When a program is loaded the emulation configuration is read, and set for the program before it is run. The order for configuring an item for a given program (e.g. prog.p) is as follows:

  1. Search for config.ini in the directory that contains prog.p
  2. If it exists, configure items specified in a [prog.p] section
  3. If it exists, configure items not yet specified, that exist in a [default] section
  4. Search for config.ini in the root directory
  5. If it exists, configure items not yet specified, that exist in a [default] section
  6. Configure any items not yet specified with the default values given above

Note: All entries in a config.ini file are case insensitive

Main Attributes

The following can be configured: Item Description Default Value Notes
Computer Selects ZX81, ZX81x2, ZX80-4K or ZX80-8K ZX81 ZX80-4K selects ZX80 with the original 4kB ROM. ZX80-8K selects a ZX80 that has been upgraded with an 8K ROM. ZX81x2 selects a ZX81 with the "Big Bang" ROM for faster BASIC
Memory In kB. Starting at 0x4000 16 1, 2, 3, 4, 16, 32 and 48 allowed
WRX Selects if RAM supports Hi-res graphics Off Automatically set to on if Memory is 2kB or less
LowRAM Selects if RAM populated between 0x2000 and 0x3fff Off Typically used in conjunction with WRX to create a hires display file in low memory, can also be used for UDG graphics emulation if WRX off
M1NOT Allows machine code to be executed between 0x8000 and 0xbfff Off Memory must be set to 32 or 48
ExtendFile Enables the loading and saving of memory blocks for the ZX81, using ZXpand+ syntax On See Loading and Saving Memory Blocks
Centre When enabled the usual 32 by 24 character display is centred on screen On When in 640 by 480 mode, set to Off for some programs that require the full 320 by 240 pixel display (e.g. QS Defenda or MaxDemo)
FrameSync Synchronises screen updates to the start of the display frame. Option to synchronise frame pairs for programs that display interlaced images Off On reduces "tearing" in programs with horizontal scrolling, at the expense of a possible small lag. Interlaced reduces flickering in programs that display interlaced images
CHR128 Enables emulation of a 128 character user defined graphics board (CHR$128) in Low memory. Off When enabled LowRAM is forced to On, WRX and QSUDG are forced to off
QSUDG Enables emulation of the QS user defined graphics board Off Memory automatically limited to 16 when selected
Sound Selects sound card type (if any) None Valid options are QUICKSILVA, ZONX, TV, CHROMA and NONE or OFF
ACB Enables ACB stereo if sound card enabled Off
NTSC Enables emulation of NTSC (60Hz display refresh) Off As for the "real" ZX81, SLOW mode is slower when NTSC is selected
VTOL Specifies the tolerance in lines of the emulated TV display detecting vertical sync 25 See notes below

Notes:

  1. The "real" QS UDG board had a manual switch to enable / disable. In the emulator, if QSUDG is selected, it is assumed to be switched on after the first write to the memory mapped address range (0x8400 to 0x87ff)
  2. To emulate other standard UDG graphics cards that reside between 0x2000 and 0x3fff set LowRAM to On and WRX to Off. This setting is needed to run e.g. Galaxians with user defined graphics. If emulation of CHR128 UDG graphics is required set CHR128 to On. This setting is needed to run e.g. zedgragon
  3. If NTSC is set to On and Centre is set to Off then a black vsync bar will be seen at the bottom of the display for programs that generate a typical 192 line display
  4. A higher tolerance value set for VTOL results in faster screen stabilisation. As for a real TV, a low tolerance level results in vertical sync being lost for some programs, such as QS Defenda and Nova2005. Set the value to 15 to emulate a TV that struggles to maintain vertical lock. Run the Flicker program to see the effects of PAUSE on lock
  5. The "Big Bang" ROM can double the speed of BASIC programs
  6. The Waveshare LCD 2.8 board has no sound capabilities
  7. The TV sound option emulates the sound generated through the TV speaker by VSYNC pulses. The CHROMA sound option emulates the sound generated through the TV speaker by the Chroma interface when VSYNC pulses are not frame synchronised

Joystick

In addition a USB joystick,and on some boards a 9-pin joystick, can be configured to generated key presses

Item Description Default Value
Left Keypress when joystick moved left 5
Right Keypress when joystick moved right 8
Up Keypress when joystick moved up 7
Down Keypress when joystick moved down 6
Button Keypress when joystick button pressed 0

Notes: ENTER and SPACE can be used to represent the New Line and Space keys, respectively

Extra configuration options

Eight extra options apply across all programs and can only be set in the [default] section of the config.ini file in the root directory of the SD Card Item Description Default Value
FiveSevenSix Enables the generation of a 720x576p display @ 50Hz On , or 720x576p display @ 50.65Hz Match. If set to Off a 640x480 display @ 60Hz is produced Off
Dir Sets the initial default directory to load and save programs /
Load Specifies the name of a program to load automatically on boot in the directory given by Dir ""
DoubleShift Enables the generation of function key presses on a 40 key ZX80 or ZX81 keyboard. See here On
AllFiles When set, all files are initially displayed when the Load Menu is selected. When off only files with extensions .p, .o, .81, .80 and .p81 are initially displayed Off
MenuBorder Enables a border area (in characters) for the Load and Pause menus, useful when using a display with overscan. Range 0 to 2 1
LoadUsingROM Runs the Sinclair ROM routines to load a file in real-time. Authentic loading visual and audio effects are emulated OFF
SaveUsingROM Runs the Sinclair ROM routines to save a file in real-time. Authentic saving visual and audio effects are emulated OFF
NinePinJoystick When set to on Enables reading a 9 pin joystick, if supported in hardware Off
VGA When set to on enables VGA output for the PICOZX + LCD board off

Notes:

  1. By default the European ZX81 generates frames slightly faster than 50Hz (50.65 Hz). Setting FiveSevenSix to Match enables a display mode slightly faster than the 50Hz TV standard, so that better synchronisation between the frame generates by the emulator and frames sent to the monitor can be achieved. If there are issues with a TV or monitor locking to 50.65 Hz, then FiveSevenSix can be set to On to generate an exact 50 Hz frame rate
  2. The LCD supported displays all have a fixed 320 by 240 resolution. FiveSevenSix therefore only sets the framerate for these displays (50 Hz, 50.65 Hz or 60 Hz)
  3. Due to the low speed of the ZX8x cassette interface, files can take many minutes to load and save when LoadUsingROM and SaveUsingROM is enabled

Examples

Examples of the config.ini files used to test the programs listed in this section can be found here

Editing config.ini

The config.ini file cannot be edited within the emulator. Modify the config.ini file using another computer.

After replacing the SD Card into the emulator, the Pico must be restarted, either via a Power cycle, or by pressing the run / reset button on the board, before any edits will be visible to the emulator

Need for reset of emulated machine

The emulated machine is always reset if any of the following options are changed:

Computer Memory LowRAM M1NOT QSUDG CHR128 LoadUsingROM SaveUsingROM

Note: Changing the virtual sound card, or the FrameSync or NTSC settings, does not trigger a reset

File Storage

Program and configuration files are stored on a micro SD-Card. Directories are supported. File and directory names should only contain characters that exist in the ZX81 character set. File and directory names can be a mixture of upper and lower case, but are used case insensitive. Therefore, all file and child directory names in a given directory must differ by more than just case

Function key menu

The emulator has several menus that can be selected through function key presses. To keep the look and feel of the ZX8x computers the menus are in black and white and, dependent on the computer type being emulated, use either the ZX81 or ZX80 font

The original ZX80/ZX81 40 key keyboard does not have function keys. A "double shift" mechanism can be used instead. The mechanism is as follows:

  1. Shift is pressed without another key
  2. Shift is released, without another key being pressed
  3. Within one second shift is pressed again
  4. Shift is released, without another key being pressed
  5. To generate a function key, within one second, a numeric key in the range 1 to 8 is pressed without shift being pressed. If 0 is pressed Escape is generated

This mechanism is enabled by default. To disable it set DoubleShift to Off in the configuration file

F1 - Reset

Hard resets the emulator. It is equivalent to removing and reconnecting the power

F2 - Load

A menu displaying directories and files that can be loaded is displayed, using the ZX81 font. Any sound that is playing is paused. Directory names are prepended by < and appended by > e.g. <NAME>

If the name of a file or directory is too long to display in full it is truncated with the last characters as + (file) and +> (directory)

Press Escape to remove the keyboard display. The keyboard is also removed if another menu is selected

If a ZX8x 40 key keyboard is being used and DoubleShift is enabled, the menu can be removed by pressing and releasing shift twice and then pressing 0 within one second of releasing shift

F6 - Modify

Allows some values to be modified "on the fly" to see the impact of the changes without having to edit the config files. Select the item to modify using the up and down keys. The 7 key also generates up and the 6 key also generates down. Change the value of an item using the left and right keys. The 5 key also generates left and the 8 key also generates right

The changes are not written back to the config files, so will be lost when the emulator is rebooted. Exit by pressing Enter to see the effect of the changes. Press Escape to exit without changes

F7 - Restart

Allows some values to be modified to see the impact of the changes without having to edit the config files. Changing these values will result in the emulated machine being reset and returning to the K prompt. Select the item to modify using the up and down keys. The 7 key also generates up and the 6 key also generates down. Change the value of an item using the left and right keys. The 5 key also generates left and the 8 key also generates right

The changes are not written back to the config files, so will be lost when the emulator is rebooted. Exit by pressing Enter to action the changes. Press Escape to exit without changes

F8 - Reboot

Allows the impact of changes to display resolution and frequency to be seen without editing config files. If a change is made and the menu is then exited by pressing Enter the Pico will reboot and use the new display mode. The changes are not written back to the main config files, so any changes will be lost on subsequent reboots.

On the LCD builds the display resolution is fixed and only the frequency can be changed

Loading and saving options

The emulator supports loading .p, .81, .o, .80 and .p81 files from micro SD Card. It can save in .p and .o format. Files to be loaded should only contain characters that are in the ZX81 or ZX80 character set

Load

There are 3 ways to load files:

1. Via the F2 menu

The user can navigate the SD card directory and select a file to load. The emulator is configured to the settings specified for the file in the config.ini files, reset and the new file loaded

2. Via LOAD "" (ZX81) or LOAD (ZX80)

If the user enters the LOAD command without specifying a file name the SD Card directory menu is displayed and a file to load can be selected. The emulator is configured to the settings specified for the file in the config.ini files. Unlike for option 1, the emulator is only reset if the configuration differs. This, for example, allows for RAMTOP to be manually set before loading a program

3. Via LOAD "program-name" (ZX81 only)

If a file name is specified, then .p is appended and an attempt is made to load the file from the current directory. The configuration for the file is read. A reset is performed only if required by a configuration change. This allows for multiple parts of an application to be loaded e.g. HiRes Chess or QS games that include character definitions.

If the supplied filename, with .p appended, does not exist, then the LOAD fails with error D. This is similar to a "real" ZX81, where if a named file is not on a tape, the computer will attempt to load until the user aborts by pressing BREAK, generating error D

Save

ZX81

To save a program the SAVE "Filename" command is used. If "Filename" has no extension then .p is appended to the supplied file name. The file is saved in the current directory. If a file of the specified name already exists, it is overwritten

ZX80

To save a program the SAVE command is used. SAVE does not take a file name, so mechanisms are provided to supply a file name. When SAVE is executed the emulator scans the program for a REM statement of the form:

REM SAVE "filename"

If such a REM is found the file is saved with the name filename with .o appended if not supplied

Note: The SAVE in the REM is the keyword. Enter it first then use the cursor keys to insert the REM in front of it

If no REM statement of the required format is found, then a save screen will be displayed to allow a filename to be entered. The ZX80 keyboard image is automatically displayed to make it easier to enter non alphanumeric characters. The cursor keys (SHIFT 5 and SHIFT 8) and Rubout (SHIFT 0) can be used. Press ENTER to exit the screen and use the filename, .o is appended if not supplied. Press Esc or SHIFT 1 to leave the screen without setting a filename

The program is saved to the current directory. If no valid file name is supplied a default filename of "zx80prog.o" is used. Any existing file with the same name is overwritten

Loading and Saving Memory Blocks

When emulating a ZX81, extensions are provided to LOAD and SAVE to support the loading and saving of memory blocks. The syntax is similar to that used by ZXpand

Note: There are differences in failure modes and error reporting compared to the ZXpand. Also .p is not appended when loading and saving memory blocks

The extensions are enabled by default. Set the ExtendFile config option to Off to disable the extensions

Load

LOAD "filename;nnnnn"

where nnnnn represents a decimal number specifying the target address

Failure Modes

Note:

where:

Using the ROM routines

The LoadUsingROM and SaveUsingROM configuration options allow the ROM code to be executed. This emulates the loading and saving of program files (but not data blocks) in the same time that it would take on a real ZX80/ZX81

Picozx81 generates realistic load and save sounds and graphics for the 8K ROM. The 4K ROM generates sounds and graphics when saving, which picozx81 emulates. The 4K ROM does not generate a load screen. Picozx81 will show a black screen when the 4K ROM is loading a program

The save sounds generated for both the 4K and 8K ROMs have been recorded as wav files and then successfully loaded into the EightyOne emulator

The ROM is used for program loading if either the filename is specified on the command line, e.g. LOAD "FILENAME.P" or (for the ZX81) an empty filename is supplied e.g. LOAD "". If a file extension exists (.p, .o etc) then it must be supplied. Directories can be specified as part of the filename e.g. LOAD "SUBDIR/FILENAME.P"

Limitations

The config file is read prior to loading. If the configuration file requires the emulator to be reconfigured so that it requires a reboot (e.g. the computer type or memory size changes) then the ROM will not be used for loading, and the file will be loaded immediately, as if LoadUsingROM was set to OFF. The ROM is also not used for loading if the file to be loaded is selected by pressing F2

When loading, picozx81 will read a .p, .o or .p81 file and generate values which the ROM reads through IN statements
Note: A program cannot be loaded directly from a wav file

Applications Tested

Testing the emulator has been a great way to experience some classic ZX81 games and demos, including many that stretch the ZX81 and ZX80 well beyond what Sinclair may have originally expected. The following have been successfully tested:

ZX81

Low res

Programs with limitations or artefacts

  1. Clone this repository (i.e. picozx81), including submodules

    git clone --recursive https://github.com/ikjordan/picozx81.git

  2. create a build directory, move to that directory and build using CMake. By default an executable compatible with the Pimoroni vga board and a rp2040 will be created. This will be named picozx81_vga_rp2040.uf2

    mkdir build
    cd build
    cmake -DCMAKE_BUILD_TYPE=Release ..
    make

  3. To build for other boards with a RP2040, pass the board type as part of the cmake command. e.g.

Board CMake uf2 name
Pimoroni DVI cmake -DPICO_BOARD=dviboard .. picozx81_dvi_rp2040.uf2
PicoMiteVGA cmake -DPICO_BOARD=picomitevgaboard .. picozx81_picomitevga_rp2040.uf2
Olimex PICO DVI cmake -DPICO_BOARD=olimexpcboard .. picozx81_olimexpc_rp2040.uf2
Pimoroni VGA cmake -DPICO_BOARD=vgaboard .. picozx81_vga.uf2
Custom 332 VGA (similar to MCUME) cmake -DPICO_BOARD=vga332board .. picozx81_vga332_rp2040.uf2
Cytron Maker based 222 VGA with CSYNC (similar to PICOZX) cmake -DPICO_BOARD=vgamaker222cboard .. picozx81_vgamaker222c_rp2040.uf2
PICOZX without LCD cmake -DPICO_BOARD=picozxboard .. picozx81_picozx_rp2040.uf2
PICOZX with LCD cmake -DPICOZX_LCD=ON -DPICO_BOARD=picozxboard .. picozx81_picozx_lcd_rp2040.uf2
PICOZX in Spectrum case cmake -DPICO_BOARD=picozxrealboard .. picozx81_picozxreal_rp2040.uf2
Pimoroni DVI with HDMI sound cmake -DHDMI_SOUND=ON -DPICO_BOARD=dviboard .. picozx81_dvi_hdmi_sound_rp2040.uf2
Olimex PICO DVI with HDMI sound cmake -DHDMI_SOUND=ON -DPICO_BOARD=olimexpcboard .. picozx81_olimexpc_hdmi_sound_rp2040.uf2
Wavesare PiZero with HDMI sound cmake -DHDMI_SOUND=ON -DPICO_BOARD=wspizeroboard .. picozx81_wspizero_hdmi_sound_rp2040.uf2
Waveshare Pico-ResTouch-LCD-2.8 cmake -DPICO_BOARD=lcdws28board .. picozx81_lcdws28_rp2040.uf2
Cytron Maker cmake -DPICO_BOARD=lcdmakerboard .. picozx81_lcdmaker_rp2040.uf2
  1. Upload the uf2 file to the Pico
  2. Populate a micro SD Card with files you wish to run. Optionally add config.ini files to the SD Card. See here for examples of config files

Notes:

Extra Information

General

Cytron Maker

Use of LCD displays

The Maker board can be used with a range of 320 by 240 LCDs, controlled over the SPI bus, with controllers from either the ILI9341 or ST7789 families. The boards are configured using entries in the default section of the config file

The LCD should be connected to the Maker board as follows: Function Name Pico GPIO Pin
Backlight BL 4
Chip Select CS 5
Clock CLK 6
Data In DIN or MOSI 7
Reset RST 8
Data / Command Selection DC 9
VCC 3.3V 3V3 (OUT)
GND Ground Any Ground Pin

Touchscreen functionality is not supported. Any pins used for the touchscreen do not need to be connected

LCD Configuration Options

All options are set in the [default] section of the config.ini file in the root directory of the SD Card. Item Description Default Value
LCDInvertColour Inverts the colour of the display. i.e. changes white to black and black to white False
LCDReflect Defines the horizontal scan direction. Use if the K prompt is displayed on the right hand side of the display False
LCDBGR Set to true if blue displays as red and red displays as blue False
LCDRotate Rotates the display through 180 degrees False
LCDSkipFrame Displays every other frame, to reduce bandwidth False

e.g. to set LCDReflect to true, add the following to the [default] section of the configuration file: LCDReflect = True

Notes:

  1. If the configuration appears correct for a display, but no image appears, or the image is not stable, it could be that the display cannot support the SPI bus speed required to display every frame, or that cross talk is occurring between the wires connecting the display. In this case set LCDFrameSkip = True
  2. It is recommended to use the Cytron maker board with the Pico pre-soldered, as this version can support higher bus speeds. If the version with a socket for a Pico is used, then the LCD display may not function correctly unless LCDFrameSkip is set to True
  3. If LCDFrameSkip equals True, then if FrameSync is set to Interlaced it will be interpreted as On

Configuration of Tested LCDs

Display Controller Invert Colour Reflect Frame Skip BGR
Waveshare 2" LCD ST7789V True False True False
Waveshare 2.4" LCD ILI9341 False False False True
Waveshare 2.8" LCD ST7789 True True False False
Generic 3.2" LCD ILI9341 False False False True

Example config.ini settings for these LCDs can be seen here. Uncomment the lines in the section matching the LCD you wish to use

Rotating the display on the Waveshare Pico-ResTouch-LCD-2.8

By default the display for the Waveshare Pico-ResTouch-LCD-2.8 is configured rotated, so that the usb connection and SD Card is at the bottom of the display. To undo the rotation, so that usb connection and SD Card is at the top, set LCDRotate = False in the default section of the config file

Using 9 pin "Atari" joysticks

With boards with connectors supplied for enough free GPIO pins it is possible to attach a 9 pin connector and then plug-in and use "in period" 9-pin joysticks

Supported Boards

The lcdmaker, vgamaker222c, picomitevga, pizero and picozx builds support the connection of a 9-pin joystick connector

Obtaining a 9-pin interface

Solderless 9-Pin connectors can be sourced from e.g. ebay or amazon

Connections

pin number 1 2 3 4 6 8
lcdmaker GP20 GP21 GP22 GP26 GP27 Ground
vgamaker222c GP20 GP21 GP22 GP26 GP27 Ground
picomitevga GP3 GP4 GP5 GP22 GP26 Ground
pizero GP11 GP12 GP10 GP15 GP13 Ground

The picozx board has a 9-pin joystick port connector built in

Enabling the joystick

To enable the nine pin joystick set NinePinJoystick to On in the [default] section of the config.ini file in the root directory

It is not necessary to create a NinePinJoystick entry to use the joystick port on the picozx board

Developer Notes

Acknowledgements

One intention of this project was to show what can be quickly achieved by leveraging other open source projects. The following excellent Open source projects have been used for source code and inspiration:

Thanks to Paul Farrow for information on the Chroma expansion boards and the .p81 file format

Use with an original ZX80/ZX81 keyboard

There are not enough unused GPIO pins on the Pimoroni demo boards to allow the direct connection of a ZX80/81 keyboard, but it can be done by using another Pico to convert the ZX80/81 keyboard into a USB keyboard. It may seem excessive to use a whole Pico as a keyboard controller, but they are cheap and there is enough space to put the Pimoroni board, plus another Pico, plus a small USB hub into a ZX80 or ZX81 case

Code to convert a ZX8x keyboard to USB can be found at ZX81_USB_KBD. This code has been used to successfully connect a ZX81 keyboard to this emulator. If the keyboard is the only peripheral, then it can be plugged straight into the USB port of the Pico on the emulator board with the power connected to the USB power socket of the Pimoroni board. If other USB peripherals (such as another keyboard, or a USB joystick) also need to be connected then the ZX80/81 keyboard can be connected via a USB hub

To access the function menus from a ZX80/81 keyboard the doubleshift configuration option must be enabled

The picozx board does support keyboard and joystick. This is achieved by using every available GPIO pin, and using VGA222 with CSYNC, together with mono audio

Performance and constraints

In an ideal world the latest versions of the excellent sz81 or EightyOne emulators would have been ported. An initial port showed that they are too processor intensive for an (overclocked) ARM M0+. An earlier version of sz81 (2.1.8) was used as a basis, with some Z80 timing corrections and back porting of the 207 tstate counter code from the latest sz81 (2.3.12). See here for a list of applications tested

The initial port from sz81 2.3.12 onto the Pico ran at approximately 10% of real time speed. Use of the Z80 emulator originally written for xz80 by Ian Collier, plus optimisation of the ZX81 memory access, display and plot routines allows the emulator to run at 100% of real time speed. The display of a full 320 by 240 image in real time (e.g. Maxhrg) uses approximately 83% of the available RP2040 CPU clock cycles with sound disabled and 87% with Zonx sound enabled when picozx81 is running with a 640x460 display and ZX81 hardware emulation. Figures are much lower for the RP2350 (56.5% without sound, 59% with sound)

ZX80 hardware emulation takes more CPU. Emulating an idle ZX80 with Zonx sound enabled takes approximately 94% of a 252 MHz RP2040 based Pico. Due to the nature of the ZX80 hardware display emulation, the CPU load drops, both in B&W and Chroma, when a ZX80 program is running. The CPU load is much lower on a RP2350 based Pico. An idle ZX80 with Zonx sound enabled takes approximately 65% of a 252 MHz RP2350 based Pico

The 640x480 display mode uses an overclock to 252MHz. The 720x576 display mode uses an overclock to 270MHz

Corrections to the tstate timings were made for ld a,n; ld c,n; ld e,n; ld l,n; set n,(hl); res n,(hl);

Possible Future Developments

This emulator offers the following over MCUME: