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.14 with Flood Fill

    Leonardo Miliani10/20/2020 at 17:36 0 comments

    Hello everybody. Nice release, today, for the LM80C Color Computer. The new firmware R3.14 comes with an interesting feature: the flood fill algorithm, to fill connected areas in graphic mode!

    Here's a little video to show the new PAINT command in action:

    Grab and burn the new firmware from the official Github repo.

  • New firmware R3.13.8

    Leonardo Miliani10/01/2020 at 14:33 0 comments

    Another firmware release, to fix a minor bug and to implement a new feature:

    • Fixed a little bug in COLOR statement: it didn't store the foreground color set by the user;
    • Now PLOT, CIRCLE, and DRAW statements accept color "0" to draw pixels with background color, i.e. reset pixels that are on;
    • Code cleaning

    Every single ROM is available ready-to-be-flashed on my Github repo.

  • New firmware R3.13.7

    Leonardo Miliani10/01/2020 at 14:30 0 comments

    New firmware release 3.13.7:

    • Fixed a bug into the new cursor management routine: now the cursor won't appear during PRINTing anymore;
    • Fixed a bug into the comma tabulation: now the max. allowed number of columns is   calculated dinamically, according to the screen width

    The new firmware is available from my GitHub repo, as usual.

  • New firmware R3.13.6

    Leonardo Miliani09/10/2020 at 15:58 0 comments

    Another minor release for the LM80C firmware. Let me introduce you the new 3.13.6:

    • Changed the cursor management routine: now the cursor is visible when being moved.
    • Now when the computer is software reset, the NMI is disabled before restart.
    • When printing with "comma" separator, 10 spaces are introduced  between items.

    As usual, the new firmware is available from my Github repo.

  • LM80C Color Computer 64K

    Leonardo Miliani08/30/2020 at 09:44 0 comments

    Hello everybody. After a while I’m back with interesting news! I’m glad to introduce you the LM80C Color Computer 64K. This is the V2 release of my homebrew computer built around the Zilog Z80 CPU. A lot of things are changed since V1 hardware, most importantly the main RAM, increased to 64K.

    LM80C 64K on video

    LM80C 64K

    Since the Z80 can address only 64K of memory, to be able to address the 32K ROM and the 64K RAM a trick has been used. Other computers of the past, like the C64 for example, had 64K of RAM but to let the computer be user-friendly the developers adopted bank switching mechanisms to disable the ROM or the RAM or to switch between them in particular conditions: on the C64, if the user tried to wrote in a memoery area used by the system, the operating system disabled the ROM, wrote on the underlying RAM, then re-enabled the ROM. I decided to solve the problem using a different approach: instead of jump between RAM and ROM according to the situation, I simply copied the whole ROM contents into the RAM.

    When the user powers up the computer, the usual check to see if it’s a cold or warm start is performed. For a cold start, the bootloader copies the firmware from the first bank of 32K memory (occupied at startup by a ROM  chip) into the second bank (from $8000). Then, jumps into the RAM continuing to execute the switching code, that disables the ROM bank and enables another 32K RAM bank. Now, it copies the whole firmware again on the first bank (from $0000) and then resume the original boot code. The bank switching is performed using a PIO line, so with just a simple OUT instruction. I also want to disappoint who thinks that the operation is too slow: by using the LDIR instrucion of the Z80, the double transfer (from ROM to RAM, and then from RAM to ROM) only takes 0.2 seconds!

    In this way, the BASIC interpreter can access all the memory left free (about 44K). If the user need the whole amount of memory RAM (64K) for his/her needs, he/she just has to write a little loader in a portion of the RAM and simply overwrite the original firmware.

    But that is not the only change. Now the VDP can benefit of 2x 16K VRAM banks to store 2 different video buffers and a serial switch to isolate the serial port in case the computer hasn’t opened the serial line yet. The trick is the same used for the ROM/RAM switching: a PIO line wired up to an address pin of the VRAM chip.

    Lastly, I’ve added a 4066 Switch to isolate the SIO pins when the serial line is not used or is disabled for any special event (i.e. buffer overrun).

    Here are the complet set of features of the new hardware:

    • CPU: Zilog Z80@3.68 MHz
    • Main memory:
      • 32K ROM with LM80C BASIC (an extended version of Microsoft BASIC 4.7) with special instructions to manage graphics and sound
      • 64K SRAM, of which 44K available under BASIC
    • Graphics:
      • VDP TMS9918A
      • 32K VRAM (2x 16K banks)
      • 256×192@15 colors
      • 32 sprites (monoc.)
    • Sound:
      • YM2149F (or AY-3-8910)
      • 3 analog channels
      • 8 octaves
      • 2×8-bit ports (used to read an external keyboard)
    • I/O:
      • Z80 SIO (2x serial ports with software-programmable bps)
      • Z80 PIO (2x 8-bit parallel ports – of which one is used to set up the system peripherals)
      • Z80 CTC (timer/counter, used to provide serial clock and system tick mechanism)

    LM80C 64K protoboard

    LM80C 64K protoboard

    Here is a little video of the power up of the system:

    Code and schematics will come soon on my Github repo.

  • New firmware R3.13.5

    Leonardo Miliani08/29/2020 at 15:59 0 comments

    Another minor release, now the firmware comes to version R3.13.5:

    • Minor code revisions into BASIC interpreter
    • Fixed a buf into the comma-separated printing code that lead to wrong alignment of the text

    Grab it, as usual, here:

  • New firmware R3.13.4

    Leonardo Miliani07/04/2020 at 17:28 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…

View all 41 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?



mar-sim wrote 08/18/2020 at 08:20 point

Ciao Leonardo,

il progetto mi piace molto, ma non è che per caso hai un PCB disponibile? Che così mi evito gli sbattimenti delle generazione dei file, la stampa etc etc... se si fammi sapere quanto e come ti posso pagare.



  Are you sure? yes | no

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