Saturday, November 29, 2014

ERIC-1: Homebrew Computer

Everyone seems to be building their 6502-based 80s esque computers nowadays, and it seems to be a lot of fun. Well, I don't want to miss the party, so I've recently started building one of my own. I've now been working on the thing for a few nights and here's what I've got so far....

Behold the mighty ERIC-1 running at whopping 2 Mhz! 

As you can see I'm building this on a breadboard, but the plan is to build the final version on a PCB that I'll be etching myself. But before I can do that I need to settle on a few features.

The general design is quite simple. There's is the 6502 CPU, 64 KB of SRAM (actually I'm using a 128 KB SRAM chip but the 6502 can only address 64 KB) and a coprocessor. The coprocessor is an ATMega1284P microcontroller that has several purposes: first it generates the necessary reset and clock signals for the 6502. It also contains the ROM image and implements the I/O interface for the system. Later I'm planning to use it to generate composite video and maybe sound.

Reset and Clock Signals

The 6502 seems to be very picky about the quality of the reset and clock signals. I found out the hard way that simply connecting a button to the reset line is not enough, like with e.g. AVR microcontrollers. The reset signal must be clean, rise quickly and be properly debounced. Also the clock signal can only be stopped in high state although modern versions of the 6502 do not have this restriction. I wanted to be able to switch between different clock frequencies easily and switch between free run and single step modes on the fly. The ATMega1284P can handle these tasks and more easily.

Shared Memory

The only way to implement I/O with a 6502 is to use memory mapping. This means that the I/O devices usually sit on the address and data bus of the 6502 and the 6502 simply reads and writes certain addresses corresponding to the I/O devices. Usually this is implemented with some sort of address decoding logic which generates chip select signals for devices based on the status of the address lines.

I wanted to try a different approach. In ERIC-1 the 6502 and the coprocessor share the same 64 kilobytes of memory. Naturally both devices cannot access the memory at the same time, so the coprocessor acts as the bus master. Since the coprocessor also generates the clock signal for the 6502, it can simply halt the 6502 when it needs to access the memory. When the 6502 is halted it still drives the address bus so I'm using 74HC541 buffers to detach the CPU from the bus. The buffers are controlled by a single output pin of the coprocessor.

But what about the data bus? In case the CPU is halted during a write cycle, the 6502 is driving the data lines. Trying to update the SRAM at the same time will cause bus contention when both the coprocessor and 6502 are trying to write data to the bus. A simple fix for this is to halt the CPU only during read cycles, e.g. when 6502's R/W is high. This means the coprocessor may have to wait a few clock cycles longer when it wants to access the bus, but overall this seems like a good solution.

Here is the code fragment from the AVR firmware that I'm using to halt the CPU:


Any computer needs some memory non-volatile memory (memory that keeps its state even when powered off) so that it knows what to do when it boots up. Usually in 6502 systems there is a separate ROM chip that contains the boot up routines of the computer. The ROM chip is mapped to upper part of the 64 KB address space, because when the 6502 wakes up it first reads the starting address from $FFFC - $FFFD (6502 is little endian, so the lo byte of the address is stored first, then the hi byte). This reset vector points to the machine code routine (in ROM) that should be executed first.

Since the coprocessor of ERIC-1 has full access to the SRAM, I decided to use the upper part of SRAM as ROM. The ROM code is stored in microcontroller's flash memory. At startup the coprocessor holds the 6502 in reset while the ROM image is copied to the SRAM chip.

What can it do?

To test the computer that I've built so far, I made a simple ROM routine that… you guessed it, blinks a LED! Here is the ROM routine, hand assembled in the coprocessor firmware:

The coprocessor firmware holds the 6502 in reset, copies this piece of code to SRAM, starts generating the clock signal. Every thousand clock cycles of so it halts the 6502, reads the byte at address $10 and turn the LED on/off based on the value read: if the value is below 128 the LED is on, otherwise it's off. The ROM routine therefore has a delay loop (the X registers counts from 255 to 0), otherwise the blinking would be way too fast to notice with the naked eye.

Now that I have the basic setup working, I'm going to add more I/O. I'll probably start working on the video generation next. Until that time!


p.s. ERIC-1?? Some of you may remember an obscure 6502 based computer, the Oric from the 80s. It was not a hugely popular computer, and in fact I've never even seen one, but I thought it would cool to nickname my computer to remind of a real 6502 system. Or it could just be acronym for "Extraordinarily Robust Integrated Computer" :)  

Monday, November 24, 2014

Driving a RGB LED with Arduino Uno

Here's a simple way to drive a RGB LED with Arduino Uno. The microcontroller generates a multiplexed PWM signal in software. The PWM is generated in an interrupt routine so the main program and LED update frequency are completely independent. The only requirements is that main program does not use hardware timer 1.

Components required: one common cathode RGB LED, one 330 ohm resistor.