Saturday, January 7, 2012

The 6502 based homebrew computer, the design and first prototype.

I finally found some time to scan my loose notes and drawings of my 6502 based 8-bit general purpose computer design, which I call MKHBC-8-R1 (to those curious what that stands for I explain: M.K. - my name initials, Home Brew Computers, 8-bit, Revision 1) and therefore I can start publishing my progress of me actually building the prototype (and at some future time hopefully a working final model) and sharing the experience with Internet community.

In my design I used standard and simple solutions whenever possible. I aimed at the project to result in a retro-style 80-s era computing experience mixed a bit with modern technology. I wanted a system to be scalable, expandable with possibility to interface with modern technology (PC computers, flash memory cards, IDE interface etc.). At the same time I wanted a taste of the 70-s/80-s computing era, the one can experience using computers like Apple I, II or Commodore 64. I wanted to use electronic chips from that era whenever possible or close replacements if available. I used standard 74LS series for address decoding and glue logic. I aim to use specialized high integration chips from the era for interfacing, video and sound capabilities (like Motorola 6847 video chip or Commodore's SID for sound, MOS 6522 for interfacing, Motorola 6850 for serial communication etc.). I want the system to be modular, so I'd be able to build and test it module by module and then assemble the tested prototype on the permanent board and move to the next module.
I think of 2 different design variants for my system:
1) A single board computer with buffered expansion bus for I/O devices. CPU, interrupt controller, address decoding and I/O decoding circuits plus EPROM and base RAM memory would be fixed on the motherboard. The expansion cards would be plugged into expansion bus sockets. The cards would consist of various peripheral devices, like video cards, sound cards, serial/parallel ports cards, expanded banked RAM cards, IDE interface card etc. that could be added gradually to the system over time.
2) Computer system organized around high load capacity passive bus with minimum common circuitry on mother board, to which expansion cards would be connected. Each expansion card would have its address/data/control lines buffered and each must provide its own on board 5V regulator and address decoding logic. CPU card would be just one of the expansion modules. CPU card would have its own clock and interrupt controller circuitry (bus would have to have dedicated lines for all external interrupts that CPU card can serve).
I did not decide just yet which variant I'd use. My revision 1 computer of which I built my 1st prototype is based on design #1 above. E.g: I have common I/O address decoding logic in it, which is not compliant with requirements of design #2 (each expansion card should provide its own address decoding logic). I think design #2 is pretty cool and more universal/expandable. At some time I could decide to use different CPU card (I have Motorola 6809 CPU in my drawer, another pretty cool CPU from the era, just waiting to come alive). However design #1 seems much easier to achieve and with less amount of IC-s.

I built a minimalist working prototype of my design on 2 bread boards.
The big bread board consists of the following circuits:
- 7805 5V voltage regulator.
- Some LED-s for testing outputs.
- CPU clock with frequency dividing circuitry.
- CPU: Rockwell 6502AP, capable of running with frequency up to 2 MHz.
- Reset circuit.
- Address decoding logic (EPROM, RAM, I/O).
- EPROM (2 x 8 kB).
- Base RAM (32 kB, no banked 128 kB RAM yet).
In this prototype I did not buffer any lines of the CPU. They go directly to the bus and address decoding logic.
The smaller bread board consists UART circuitry (Motorola 6850 with Tx/Rx clock, frequency dividing circuit and MAX232 RS232 adapter chip).
The system is connected to a PC computer running Hyper Terminal Private Edition, terminal mode is ANSI, the baud rate is 9600.

Software:
After I build my prototype, I wanted to run simple test program that would prove that my CPU, address decoding circuitry and I/O select circuitry works (that was before I built UART board). I wrote this little code bit, short enough to present directly here:

; This simple code tests the I/O decoding
; (and in intermediate way, memory decoding)
; circuits of my homebrew 6502 computer MKHBC-8-R1
; (revision 1, CPU + ROM + IO decoder).
; Prototype HW consists of clock generator, CPU,
; I/O and ROM decoder and I/O specific device
; addresses decoding and RAM.
; RAM is currently the base 32 kB ($0000 - $7FFF)
; enabled with A15 from uP bus with no upper 128kB
; banked memory nor video memory decoder yet implemented.
; 3 LEDs are connected to IO device decoder outputs
; IO0, IO1 and IO2. By sending memory write requests
; to them in a loop with delay we can observe LEDs
; going on and off sequentially.

.segment "CODE"

IOSTART = $C000

IO0 = IOSTART
IO1 = IO0+256
IO2 = IO1+256
IO3 = IO2+256
IO4 = IO3+256
IO5 = IO4+256
IO6 = IO5+256
IO7 = IO6+256

COUNT = $0800
DELAY = $FFFF

.ORG $E000


NMIJUMP:

    jmp    NMIPROC
   
RESJUMP:

    jmp RESPROC
   
IRQJUMP:

    jmp IRQPROC

NMIPROC:
   
    rti   

IRQPROC:

    rti

RESPROC:

    cld
mainloop:
    lda #<DELAY
    sta COUNT
    lda #>DELAY
    sta COUNT+1
loop1:
    sta IO0
    dec COUNT
    bne loop1
    lda #<DELAY
    sta COUNT
    dec COUNT+1
    bne loop1
    lda #<DELAY
    sta COUNT
    lda #>DELAY
    sta COUNT+1
loop2:
    sta IO1
    dec COUNT
    bne loop2
    lda #<DELAY
    sta COUNT
    dec COUNT+1
    bne loop2
    lda #<DELAY
    sta COUNT
    lda #>DELAY
    sta COUNT+1
loop3:
    sta IO2
    dec COUNT
    bne loop3
    lda #<DELAY
    sta COUNT
    dec COUNT+1
    bne loop3
    jmp mainloop

.segment "VECT"

.ORG    $FFFA

.BYTE    <NMIJUMP, >NMIJUMP
.BYTE    <RESJUMP, >RESJUMP
.BYTE    <IRQJUMP, >IRQJUMP

Assembled with ca65, burned to EPROM and booted the system....and it worked!

Next, I did research on the Internet for the software that I could either use directly to test more advanced features of my design (like UART, serial communication) or which I could adapt with not too much effort for my purpose (apparently patience is not my virtue, I wanted to see some results now!). When I found this great project by Scott Chidester (thanks Scott!), I knew I was at home. After a little tweaking (different I/O space addresses and different compilation tools) the software assembled and worked splendidly on my prototype computer. The archive also contains code of Tiny Basic interpreter, that I found on Tom Pittman's web page, which I ported to my platform. There are also some BASIC programs to run on that interpreter.
The issue of uploading programs directly to RAM of my computer was solved by using Hyper Terminals feature called Send Text File and a short program I wrote in C, which is available in software archive I posted, called bin2hex. This program basically converts binary image generated by ca65 assembler/linker into plain text file which consists series of write memory statements that can be understood by Scott Chidester's M.O.S. system that I used in my computer. Such text file can be then send over the terminal session, resulting in physically writing data directly to RAM and automatically execute the program.
There are few tweaks needed to be done in terminal software setup for the programs to upload correctly with Sent Text File feature:
1) When uploading binary programs to M.O.S. with write statements (like the ones generated with bin2hex), at 9600 baud, the speed at which hyper terminal throws the text at the session may be a little too fast, resulting in errors or hang up of the session. To adjust, go to session properties, select tab Settings, click button ASCII Setup and enter custom values to fields Line delay and Character delay. Line delay is the delay time (in milliseconds) that hyper terminal will apply after new line/line feed is sent to the session. Character delay is the delay applied after each character sent to session accordingly. For sending programs to M.O.S. at 9600 baud, I used Line delay 2, Character delay 1 and it worked fine.
2) For uploading data with Send Text File feature to other programs than M.O.S., above properties may require adjusting. E.g: for Tiny Basic, I use Character delay 2 and Line delay 300. Why so big? Well, even though this significantly extends the loading times, it is necessary, because of the way Tiny Basic works. The short times may work for short BASIC programs. However for long BASIC programs, with many lines, each next line entered to memory takes more time for interpreter to process. I noticed that while loading long BASIC programs (like tiny adventure), that errors/skipping started to happen near the 60% of the upload progress. By extending Line delay I give interpreter more time to enter the line into RAM before I start sending data for next line.

And now some pictures:

Figure 1: The big bread board, CPU, address decoding and memory circuitry.

Figure 2: The small bread board, UART circuitry.
Figure 3: Connected to the MKHBC-8-R1 with terminal emulator.
Figure 4:  Time to upload hex code of Tiny Basic, which I ported to my platform.

Figure 5: Tiny Basic is uploading to RAM via Hyper Terminal using Send Text File feature.

Figure 6: Tiny Basic finished upload. Time to execute.


Figure 7: Tiny Basic booted OK.

Figure 8: Well, let's play some game!

Figure 9: BASIC program is uploading.

Figure 10: BASIC game running.

This is it for today. I hope this project will give me lots of fun in coming months or even years and hopefully will inspire other enthusiasts to take on the quest of building their own computer. I am now living the dream I had since I was in elementary school. Because I was born at wrong time and at wrong place, I could not pursue all of my passions at the time.
Next time I will write something about my Commodore 64 experience.

Thanks for reading.