Messy 80

A Z80 single board computer, just because.

Similar projects worth following
I started building this Z80 computer a couple of years ago with the help of the book "Build Your Own Z80 Computer" by Steve Ciarcia.
My goal was learn a little about digital circuits. At first it was built on a breadboard before been left on a shelf right up until recently. There is now a circuit board and a simple monitor has been written for it.
There are way better Z80 SBCs out there but I still would like to share the experience of building this computer

The Messy80 has 32kb of EEPROM and 32kb of RAM, 8 interupts  and 8 separate outputs to select external IO interfaces with up to 32 addresses each.

The board has header that expose the necessary input/outputs to expand the functionality of the Messy80.

On board there is a 16C550 UART and a UART to USB chip which is used as the standard interface.

The monitor program is written for zasm.

This is what the serial monitor looks like right now:

I am currently using cool-retro-term and picocom for added effect.

Memory layout:

0x00000x7FFFROM, Monitor
0x80000x83FFRAM, Reserved for monitor
0x84000xFFFFRAM, For whatever, as long as it doesn't collide with the stack*

* The stack is set up at 0xFFFF and grows downwards.


Start building circuits on the breadboard to interface with the Messy80

Connect a CF-card to the bus and write a simple flat filesystem.


Messy80 schematic

Adobe Portable Document Format - 172.16 kB - 03/20/2018 at 16:34


  • 1 × Z84C00-06 CPU
  • 1 × AT28C256 Memory ICs / EEPROMs
  • 1 × 74LS04 Inverter
  • 1 × 74LS32 OR Gate
  • 1 × 74LS00 NAND Gates

View all 15 components

  • First C program for the Messy80

    Oliver.D03/21/2018 at 23:42 0 comments

    I just got SDCC to compile a Hello World program for the Messy80. Writing a putchar function to get printf working was a little more tricky than I thought. I had to have a look at the list file produced by SDCC to figure out how to get the function parameter.

    #include <stdio.h>
    #define UART_LINE_STATUS               0x05
    #define UART_LINE_STATUS_THRE        0x05
    #define UART_TX_BUFF                0x00
    putchar (char c)
    Needed for printf
    void putchar (char c)
    _wait_tx_ready:        // Wait until uart is ready to send
        jr Z,_wait_tx_ready
        // Get the parameter (char c) from the stack
        // There must be a better way of doing this
        // This is insane :[
        pop DE
        dec sp        // Looks like SDCC saves some space by using inc
                // when pushing 8bit values onto the stack
        pop AF
        // Put everything back the way it was.
        push AF
        inc sp
        push DE
        out (UART_TX_BUFF),A     // At long last, send the byte
    void main(void)
        printf("Hello world!\r\n");

     One thing is for sure, now that the C compiler is set up. writing C programs feels like cheating in comparison to using assembler.


    I really should have read the SDCC manual a little more. There is a section called "Z80/Z180 intrinsic named address spaces" that explains how write to input/output registers.

    This is what the new putchar function looks like.

    #define UART_LINE_STATUS_THRE        0x05
    __sfr __at 0x00 UART_TX_BUFF;
    __sfr __at 0x05 UART_LINE_STATUS;
    void putchar (char c)
        while( (UART_LINE_STATUS & (1 << UART_LINE_STATUS_THRE)) == 0 );
        UART_TX_BUFF = c;

    Having a look at the list file is also quite enlightening  as to how the function can be implemented in assembler

         in    a,(_UART_LINE_STATUS)
         and    a, #0x20
         jr    Z,00101$
         ld    hl, #2+0
         add    hl, sp
         ld    a, (hl)
         out    (_UART_TX_BUFF),a

    Much nicer than what I've done above.

  • Just added a dump command to the messymonitor

    Oliver.D03/20/2018 at 10:04 0 comments

  • Writing and loading programs for the Messy80

    Oliver.D03/19/2018 at 10:29 0 comments

    This will be a description of the steps taken to write and run programs.

    1. Program is written in assembler starting at address 0x8400

    ; ---------------------------------------------------------------------;
    ; Print out Hello World!!!                                             ;
    ; ---------------------------------------------------------------------;
    #include "labels.ass"
    #target     rom                 ; declare target file format
    #code       $8400,$4000        ; declare main code segment
        ld       HL, str_hello_world
        call     print_string
        call     new_line
    str_hello_world     defm    "Hello World!"+$80

     2. Before assembling the program a script gets the symbols used in the monitor so that routines such as 'print_string' can be used. The symbols are saved into labels.ass

    zasm conveniently can produces a log file with all the symbols defined.

    3. The program is assembled with zasm.

    4. Yet another script is called that reads the bin file and outputs commands for the monitor that will write the program to the RAM. The commands saved into a text file.

    This is what it looks like:

    wa 8400,21
    wa 8401,0A
    wa 8402,84
    wa 8403,CD
    wa 8404,E8
    wa 8405,03
    wa 8406,CD
    wa 8407,BF
    wa 8408,03
    wa 8409,C9
    wa 840A,48
    wa 840B,65
    wa 840C,6C
    wa 840D,6C
    wa 840E,6F
    wa 840F,20
    wa 8410,57
    wa 8411,6F
    wa 8412,72
    wa 8413,6C
    wa 8414,64
    wa 8415,A1

    5. 'Picocom' and 'ascii-xfr' are used to send the commands to the monitor.

    6. Finally address 0x8400 is called.

    This is the result in the serial monitor:

    *** file: -s -l 10 /home/oliver/workspace/z80/messy80/programs/hello_world/hello_world.txt
    $ ascii-xfr -s -l 10 /home/oliver/workspace/z80/messy80/programs/hello_world/hello_world.txt
    ASCII upload of "/home/oliver/workspace/z80/messy80/programs/hello_world/hello_world.txt"
    Line delay: 10 ms, character delay 0 ms
    wa 8400,21
    #wa 8401,0A
    #wa 8402,84
    #wa 8403,CD
    #wa 8404,F8
    #wa 8405,03
    #wa 8406,CD
    #wa 8407,CF
    #wa 8408,03
    #wa 8409,C9
    #wa 840A,48
    #wa 840B,65
    #wa 840C,6C
    #wa 840D,6C
    #wa 840E,6F
    #wa 840F,20
    #wa 8410,57
    #wa 8411,6F
    #wa 8412,72
    #wa 8413,6C
    #wa 8414,64
    #wa 8415,A1
    *** exit status: 0
    #ca 8400
    Hello World!
    Successfuly returned

  • Experiences ordering PCBs

    Oliver.D03/15/2018 at 01:09 0 comments

    The Messy80 is just the second printed circuit board I have ever ordered. I got it from JLCPCB. When I received it the silkscreen was missing. As I ordered it I tried to follow their instruction as well as I could. What is interesting is that JLCPCBs online preview did show the silkscreen.

    I have decided that before ordering the second revision of the Messy80 I will order a smaller board first, so I made a small adapter so that I can easily connect the Messy80 with ribbon cable to a breadboard. 

    I have renamed the gerbers so that they follow the suggested naming patterns here:

    Only the future will tell whether the silkscreen will show up this time.

View all 4 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates