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. So, I first designing my own computer that lead to the following specs:

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 computer, and a Z80 CTC (Counter/Timer Channels) that I can program it to generate the serial clock and other stuff, like an interrupt generator to make a simple software timer.

The magic of having everything work together is made by several logic gates: the 74xx series is a family of ICs that help doing almost everything, from address deconding to buffers, from logic gates to flip-flops and so on.


Firmware & BASIC

I derived the bootloader from the one that Grant Searle developed for his Z80 computer, doing the required changes due to the fact that he used another serial interface and so he didn't set his Z80 to work on interrupt mode 2. The BASIC is the Nascom BASIC, developed by Microsoft for the Nascom computers at the end of the '70s, adapted by Grant to work for his machine and expanded by me with new statements, new features (like a software timer) and long error messages. This is a good version of the interpreter since it's been developed to work on terminal systems such as the Nascom systems, and good enough because it had a lot of interesting features, like the one to IN/OUT data to/from peripheral chips.

Clock

The clock is given by a 7.37MHz crystal oscillator whose signal is halved to get the primary clock of 3.68MHz. This clock is halved again to get the input serial clock of the Z80 SIO so that it is fed with a nice 1.84MHz signal: this value is mandatory because it is used to generate a lot of baud rates (bps are fractions of this frequency).

The TMS9918A has its own quartz, since it needs a precise clock signal of 10.738635MHz: the VDP then divides it by 2 to get the pixel clock (5.3MHz) and then by 3 (3.58MHz) to get the video color signal and the color burst reference used to generate the composite video output signal. I could have used the COMCLOCK output pin of the TMS9918A that outputs the latter clock (i.e., this was the way of working of MSX computers and others) but I wanted the 3.68MHz frequency for the system clock to get correct timings for the serial interface.

Interrupts

In my system the Z80 is configured to handle interrupts in mode 2, meaning that the peripheral chips are set up to send the addresses of interrupt vectors to the CPU so that every single module of each peripheral chip can call for a specific portion of code. This is done, i.e., for the incoming chars over the serial, or for one of the timers of the Z80 CTC that is used to increments a 100ths of second counter, and so on.

Serial interface

The LM80C can be connected to a remote computer via a simple serial-to-USB converter (I used an FTDI232 module) and communicate at a speed of 19,200bps. By using a terminal emulator you can interact with the LM80C on a Windows/Linux/Mac computer.

Video chip

Despite I live in a PAL-system country, I chose the TMS9918A, an NTSC-system device, as the video chip. I did so because the TMS9918A is the only chip from the TMS99xx family that generates a composite signal that can be directly sent to a TV set. Since almost every modern LED TV can handle PAL & NTSC signals, I don't need a TV interface as I had to use if I chose the TMS9929 (this variant outputs a pseudo-component PAL signal), used on the European MSX computers.

Audio chip

At the moment this component isn't connected yet. I chose the YM219F , a legal replica of the GI AY-3-8910 made by Yamaha, because it was widely used and it is still available as a vintage spare part. There are also some 100% compatible clones still manufactured by some manufacturers like the WF19054. So, you shouldn't have any difficult to find such a chip. The YM219F/AY-3-8910 is a state machine with several internal registers that can be interfaced to a common CPU with a data bus and some extra lines. It can generate 3 voices with volume, frequency, pitch and envelope control; it also has a white noise generator whose output can be mixed with any of the 3 channels. The AY-3-8910 also has 2 input/output ports that can be used to interface the chip with external devices like a keyboard or a couple of joysticks.


Compiling

To compile the firmware I recently switched to SJASMPlus because it's multi-platform (Win/MacOS/Linux) & it supports macros, file inclusion and assembler directives. The command to compile an ASM file is the following:

./sjasmplus --lst --lstlab LM80C-firmware-r3.18.asm

 This instructs the assembler to generate a binary file and a list file that includes the label listings with source code and machine language code. This list file is very useful if you need to do some debug because you can see how the program was compiled, where your code jumps, etc. 


Firmware programming

The best solution to flash the firmware for the system is to use an EEPROM chip. This kind of non-volatile memory is essentially an PROM (Programmable Read-Only Memory) that it is "E"rasable, meaning that it can be erased and written several times (usually, 10,000/100,000 times: this value can vary). Moreover, despite the classic EPROM chips that need an UV-eraser, this kind of memory is "E"lectrically erasable meaning that it can be erased with just a simple voltage signals sent by the internal logic circuitry. To flash the firmware on these chips you need a programmer, a device that must be connected to a host computer and driven by some software. Since I wanted to maintain the cost of my system as low as possible, I built an EEPROM programmer using an Arduino/Genuino UNO and few 74xx chips. Then I uploaded a modified version of the TommyPROM firmware that I adapted to work with 74595 shift registers. To flash a firmware, you need a terminal emulator that can send files using the XMODEM protocol, the one supported by TommyPROM programmer. On a Mac you can use the "Serial" app from DecisiveTacticts, that is shareware software; alternatively, you can use TeraTerm on Windows systems, that is freely available. For Linux I didn't find any terminal emulator that worked correctly.


2021 UPDATE: 64K model

The new year came with a big news. I developed a bigger version of the computer, named LM80C 64K Color Computer. As you can understand, the main difference is the memory amount: in fact, the RAM grew from 32K to 64K, using a bank switching mechanism that move the firmware from ROM to RAM during the boot, levang about 43K for BASIC programs. Another improvement is the adoption of the same mechanism to get 2x 16K VRAM banks available to the VDP, and the initial support for a Compact Flash as a mass storage device, eliminating the need for additional hardware to have the SD card accessible from the computer.

UPDATE 2019/06/01: home computer functionalities

In the last weeks I've worked hard and modified the firmware of the LM80C computer to a point that now it acts like an home computer of the '80s. The computer now gets input chars and prints them on the video. Due to the fact that the TMS9918A has its own video RAM (VRAM) separated by the main memory of the system, I've written a routine that intercepts the output chars that the BASIC echoes to the host computer through the serial line and prints them on the screen. The visualization is made by sending the single chars directly to the TMS9918A that stores them into the VRAM into the area used for the video buffer. The code keeps track of the cursor position, too: since the TMS9918A doesn't have hardware support for a cursor I've had to provide a method to store the cursor's coordinates and print a special character that represents the position where the actual char will be printed. I've published two videos: in the first one you can see some sprites management made by simple BASIC commands. The second one show the scrolling capabilities of the computer with a newer firmware.


UPDATE 2019/12/07: added built-in keyboard support

After adding the keyboard of an old Commodore 16 computer I bought on internet, the LM80C was finally raised to the dignity of Home Computer. Now the user can interact with it without the need of a remote computer anymore.

More details, UPDATED CODE and schematics can be found on my personal blog and on my Github page.