LM80C Color Computer

A Z80 homebrew computer with 32KB SRAM & 32KB ROM, TMS9918A VDP (video) and AY-3-8910 PSG (audio)

Similar projects worth following
This is a full working 8-bits computer based on the Z80 processor with BASIC interpreter, TMS9918A for video and AY-3-8910 for sound.

I always desired to build my own 8-bits computers. Back in the '80s I was a Commodore 16 user, and a lot of friends of mine had C64 and MSX computers. They had sprites and sound, I only had 121 colors. Now I want to build my own system, to bridge that gap. 

I looked around, started studying projects of other homebrew enthusiasts and eventually made my choices:

  • CPU: I chose a Zilog Z80 because it has a lot of registers, it has I/O features, it can set the stack anywhere into the RAM, it can handle interrupts in different ways.
  • RAM: 32KB of SRAM. I think that, at the moment, this amount of memory is enough to do some good programming.
  • ROM: 32 KB of EEPROM. I chose an EEPROM chip because I can easily burn my firmware with an Arduino board connected to my computer. Also, 32KB are enough to store a BASIC interpreter and some other stuff.
  • VIDEO: TMS9918A. I wanted a video chip that was able to render a colorful image, with a good image size, easy to interface and that had support for hardware sprites. 
  • AUDIO: AY-3-8910 (or its variant from Yamaha, the YM219F). It features 3 voices with environment and white noise. It also has 2 input/output ports, that were used to read the keyboard or the joystick ports.
  • I/O
    • parallel I/O: a Z80 PIO that, at the moment, only drives some LEDs
    • serial I/O: a Z80 SIO/0, used to interface with a computer through a serial connection (FT232 serial/USB converter)
    • timer/counter: a Z80 CTC used to generate the serial clock and to increment a software timer counter

Why did I choose the Z80? Initially, I chose the Motorola 6809, then the 6502 but both of them had PROs and CONs. The 6502 has very few registers and it doens't support I/O instructions so every peripheral chip must be mapped into RAM, leading to complex address decoding systems. The 6809 is similar to the 6502 but it has some more registers, it has I/O instructions and a lot of addressing modes but it wasn't very used at its time so there aren't a lot of resources available. So I decided to use the Z80, because it's still manufactured by Zilog, it has a lot of peripheral chips specifically made for it (so that it's easy to interface each other), it can use I/O ports, it has a lot of registers, and so on.

The RAM and ROM are at the moment of 32 KB each: I think that this is a good amount of space, both for user programs and for firmware too. Maybe in the future I could implement a system to deactivate the system ROM and add another 32KB SRAM chip, to let the user to load very big programs (the same thing was done by engineers for the C64, where the ROM could be disabled, showing up the underlying RAM).

Video section. I only had few options. I discarded the MOS VIC-II from Commodore because it's very expensive online and it was developed to work with a 65xx processor. I also discarder the 6845 because it was just a video signal generator. I also discarded solutions based on moderm microcontrollers: I could have used an Atmel MCU and program it to geneate a VGA signal but I wanted to use only solutions that were available at that time. So I chose the TMS9918A, that is still available on Ebay at a resonable price, it's easy to interface since it only needs few lines between the CPU and itself and since it can generate an image of 256x192 pixels with 15 colors and 32 sprites.

For the audio section the choise was easy, the AY-3-8910: widely available, easy to interface, good to use as an I/O periphery too, and cheap. There is also the YM2149F: this is (almost) the same chip manufactured by Yamaha under license by GI. So that I could choose the one I was able to find first.

The I/O is the reachest part of the computer. Since Zilog made a lot of peripheral chips and since all of these chips are still in production, you can find parallel & serial interfaces very easily. I decided to add a Z80 PIO (Parallel Input/Output)  to drive 8 LEDs via an ULM2803, then a Z80 SIO (Serial Input/Ouput) to connect the system to my primary...

Read more »

Schematics and Arduino code to realize the EEPROM programmer used to burn the firmware for the LM80C computer.

Zip Archive - 1.15 MB - 05/01/2019 at 09:23


This archive contains both the firmware source and the schematics of the computer at the current stage: PIO, SIO, CTC, TMS9918A fully working

Zip Archive - 203.68 kB - 04/29/2019 at 21:08


  • 1 × Zilog Z80B CPU Possible product code: Zilog Z86C0006PEG (Z80 CPU in CMOS, 6MHz)
  • 1 × Zilog Z80 PIO Possible product code: Zilog Z84C2006PEG (Z80 PIO in CMOS, 6MHz)
  • 1 × Zilog Z80 SIO/0 Possible product code: Zilog Z80C4006PEC (Z80 SIO/0 in CMOS, 6MHz)
  • 1 × Zilog Z80 CTC Possible product code: Zilog Z84C3006PEG (Z80 CTC in CMOS, 6MHz)
  • 1 × GI AY-3-8910 or Yamaha YM2149F

View all 9 components

  • New firmware R3.13.4

    Leonardo Miliani6 days ago 0 comments

    Just a minor change in firmware:

    • Fixed a bug into the drawing line algorithm that crashed the system when there was a gap of 1 pixel between the starting and ending points;
    • redefined chars 105,106, and 252 in 6x8

    Grab it at

  • New maintenance releases for firmware R3.13

    Leonardo Miliani06/14/2020 at 16:05 0 comments

    In the last days I've released some maintenance releases for the firmware R3.13, primarily to fix some little bugs. This is the cumulative changelog:

    • 3.13.3: fixed a bug with function keys that lead to get a syntax error or a non-function behaviour when pressed them while system was in direct mode and print-on-screen not active, i.e. in a graphics mode 2 & 3.
    • 3.13.2: revised code of GPRINT command to avoid an error that emerged when the statement was called with an arguments line too long.
    • 3.13.1: fixed a race condition that could lead the interrupt service routine access the PSG reg #7 (mixer) together with some BASIC statements (i.e., SOUND), resulting in wrong values being stored into the mixer.

    Please update to the latest release grabbing the firmware from here.

  • New firmware releases R3.12 & R3.13

    Leonardo Miliani05/30/2020 at 15:07 0 comments

    New releases for the LM80C Color Computer firmware.

    In the last days I've released the R3.12 and R3.13 files. They contain a lot of bug fixes and enhancements. Here is the cumulative changelog:

    • - New style for "£" char;
    • fixed a bug into the automatic shutting down manager of SOUND that didn't de-activate the audio channel into the PSG mixer after a tone had finished its period of reproduction;
    • new INSTR statement, returning the position of the first occurrence of one string within another;
    • changed the behavior of INKEY statement: now the minimum delay interval is set to 10 hundredths of a second. If a shorter interval is being passed, it will be automatically set to 10 (this is because values under 10 could lead to faulty readings);
    • fixed a severe bug originated by a wrong design error of the final PCB: ports A & B of the PSG were inverted into the schematic, same for the definition of the ports into the code;
    • fixed a bug into the SOUND statement that accepted the third argument when generating a noise, even the syntax shouldn't accept it.

    Please grab the latest revisions from my Github repo.

  • LM80C: a new PCB, a new case

    Leonardo Miliani05/20/2020 at 08:21 0 comments

    Finally… I did it! I made the PCB, working for several weeks designing lines and placing components with KiCAD, to get the final board that you can see in the picture below:

    After I received I spent a couple of days by soldering the components, and another day by checking the connections… and eventually I found a couple of issues. Careful, not design errors, just my missings when I reported the prototype circuit into the schematic. I left a pull-up resistor (that I soldered on the back face of the PCB) and I inverted the connections of the I/O ports A & B of the PSG (this has been easy to fix: I just inverted the references of such ports into the code).

    I also encountered a little problem with the capacitors’ capacitance of the VDP crystal that lead to a B/W image: I ordered a different component from a differend seller but I forgot to re-evaluate their value (changed them and fixed the issue). Lastly, I discovered that the AY-3-8910 I bought from Chine a couple of months ago was, most likely, a fake/faulty chip and got no sound nor keyboard scanning. Replaced it with the YM2149F I was using on my prototype and everything went fine.

    Here is the assembled PCB:

    (The socket with no chip on the right, near the UART/USB converter, will be used in a future step to access to an SD card to be used as a mass storage).

    I also encapsulated my computer into a case of the time, because I wanted that the feeling of using a real 8-bit computers of the ’80s was full. To get it, I used the C16 case that I got together with the keyboard. This is the final result:

    Looks impressive, isn’t it? It seems a real C16, even it’s my LM80C! The next step is to make some adaptations to let the internal connectors go out properly (I missed some holes for just a couple of cm…) and then I have to put the status LEDs onto the top part of the case. And, of course, change the name of the label on the left…

  • New firmware R3.11

    Leonardo Miliani05/12/2020 at 13:56 0 comments

    Hello everybody. During these days I spent a lot of time working on the firmware of my LM80C computer trying to add features and fixing little bugs within the code. This is the new R3.11 release of the firmware:

    • Changed the way TMR() reads the real time counter so that now continue readings won't slow down the clock itself anymore: this was due to the fact the at each reading I disabled/re-enabled interrupts because I read 2 single bytes from the memory while now I'm reading a single word at a time, so I don't need to disable INTs anymore;
    • I also changed the frequency of the keyboard reading. Since this task was very heavy (more than 1,500 clock cycles), instead of doing it each time the interrupt service routine is called (100 times a second), I just execute it 50 times a second, lightening the jobs of the CPU.

    Please, grab it from my Github repo:

  • New firmware R3.10

    Leonardo Miliani05/08/2020 at 16:05 0 comments

    Another firmware release for the joy of everyone. The new R3.10 is out:

    •  Added GPRINT command to print text and ASCII chars in screen 2 as they would in text modes;
    • fixed a bug that lead to unpredictable behaviors when a line longer than 88 chars was received from the serial port: now the interpeter simply drops exceeding chars.

    GPRINT is a very interesting command since it let printing text and ASCII chars in screen 2 (the graphic mode) with different colors for each character, acting as an high resolution multicolor mode:

    Download the R3.10 release from GitHub:

  • New firmware R3.9

    Leonardo Miliani05/02/2020 at 09:47 0 comments

    Another good release for the LM80C Color Computer. The new firmware R3.9 is out!

    • Added POINT function to get the status of a pixel in G2 mode (set or reset);
    • Relocated CTC interrupt vectors to a jump table into RAM so that now the user can configure the CTC  channel interrupts to jump to custom routines (included the routine attached to channel 3 that supervises several critical system routines);
    • now SERIAL has default arguments for data, parity, and stop bits if not passed;
    • changed FN key 5 function;

    Grab it as usual at

  • New firmware R3.8

    Leonardo Miliani04/30/2020 at 16:22 0 comments

    Some minor bug fixes and improvements:

    - Fixed a bug in FN key codes that lead to the activation of the wrong FN keys;
    - introduced support for NMI custom routines (suggested by nippur72) with NMI statement;
    - fixed a bug that lead to un-wanted behaviors when graphic chars were parsed in direct mode.

    Grab the code from my Github repo:

  • New firmware R3.7

    Leonardo Miliani04/29/2020 at 20:39 0 comments

    Lot of improvements on the road:

    • Added HELP command to automatically list the line where a program error has occurred;
    • added modulo operator '%' to make modulus operations between integers (returns the remainder of an integer division);
    • added integer division operator '#' (return the integer part of a division);
    • added support for function keys into firmware;
    • added KEY command to manage function keys: it is now possible to print the current functions and assign new functions to the keys;
    • revised PAUSE code: it is now possible to break the delay with the "RUN STOP" key;
    • better error management when in graphic modes: now if an error occurs in G2 and G3 modes, the BASIC interpreter returns into G1 mode; same behavior if an error occurs in direct mode while in graphics modes;
    • pressing the "RUN STOP" key in direct mode while in graphic modes leads the interpreter to return to G1 mode.

    Grab the new ROM file here:

  • New firmware R3.6

    Leonardo Miliani04/19/2020 at 13:13 0 comments

    Another release for the LM80C firmware. This one sets improvements in several parts of the code:

    • Minor improvements in LIST code:
      • when a line terminates at the right side of the video the code won't send a "carriage return" code anymore (an empty line was inserted, before);
      • printing a list on the serial when the computer is in graphics mode now lets the list to get carriage returns after the end of each line (the list was printed in a row, before).
    • Fixed a bug in sound management: automatic cutting down of a tone on a channel wrongly altered the whole sound mixer.
    • Added management of noise from PSG: now it is possible to generate noise for each of the 3 channels, mixing the noise with tones, too.
    • Fixed some timing issues in VDP access that lead to graphic glitches in graphic mode 2
    • Code improvements

    The new code is available at my GitHub repo:

View all 35 project logs

  • 1
    Z80 chips

    Choose CMOS versions of the Z80 family chips: they usually have a "C" in the middle of the produc's code, i.e. Z84C006PEG for the Z80 CPU.

    Also, choose 4MHz- or, better, 6MHz-compliant chips. You can see the different models by looking at the last number of the product's code, i.e. Z84C006PEG is 6MHz tolerant.

  • 2
    74HCTxx family

    Choose chips of the 74HCTxx family. The "HCT" indicates a type of circuitry that is 74LS-compatible (the "LS" series was the original 74 family). The chips of the HCT series are compatible with the LS ones, because they have the same logic levels (despite the HC series, that don't). Since the LS series is difficult to find, I suggest to use chips of the HCT series.

  • 3
    TMS9918 Vs. TMS9918A

    Pay attention when you buy the video chip. The "A" letter at the far right of the name of the chip indicates a newer variant of the chip that Texas Instruments released to add support for bitmap graphics. The TMS9918 only supports graphics 1 (tiles) mode, text mode and muticolor mode, while TMS9918A adds the bitmap support, in graphics 2. 

View all 4 instructions

Enjoy this project?



Leonardo Leoni wrote 05/30/2020 at 16:17 point

Hi, your project is great, there are several z80 system but yours is really complete. It deserves a nice case and a dedicated keyboard. Congrats

  Are you sure? yes | no

Leonardo Miliani wrote 02/28/2020 at 17:10 point

Hello. To draw the schematics I used a lib with footprints and symbols for the Z80 peripherals, VPD, PSG, and other ICs partially developed by me, so I would have to release both schematics and lib, but to do this I have to make some order in the files. Please keep patience, I think that I will release them soon.... I hope...

  Are you sure? yes | no

bmxpie wrote 02/20/2020 at 22:01 point

Ciao Leonardo,

molto interessante il tuo progetto LM80C, ma...è troppo avere gli schemi su files per Kicad?



  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

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