home   |   primer index   |   1. Intro: Why 6502?   |   2. addr decode   |   3. mem map req.s   |   4. IRQ/NMI conx   |   5. 74 families & timing   |   6. clk gen   |   7. RST   |   8. mystery pins   |   9. AC performance construction   |   10. exp bus & interfaces   |   11. get more on a board   |   12. WW Q&A   |   13. custom PCBs   |   14. I/O ICs   |   15. displays   |   16. getting 65xx parts   |   17. project steps   |   18. program-writing   |   19. debugging   |   20. pgm tips   |   21. workbench equip   |   22. circuit potpourri


6502 PRIMER: Building your own 6502 computer


I/O ICs

There are dozens if not hundreds of I/O (input/output) ICs that can be used on the 6502 bus, but the two most common ones you'll find used by hobbyists are the 6522 VIA (Versatile Interface Adapter) and 6551 ACIA (Asynchronous Communications Interface Adapter).

The 6522 VIA has:

With a little creativity, you'll find dozens of uses for these.  For example, one of the synchronous serial port's modes allows 9-level D/A conversion, which is quite adequate for DTMF generation and even non-critical speech playback.  The 6522 does have a bug in one of the serial modes, shifting in under control of an external shift clock, which makes it lose bits if you don't use a flip-flop so the external clock edges are presented to CB1 only on the rising edge of Φ2, keeping them away from the troublesome falling edge.  The bug does not affect most users, and there is a way around it anyway (as shown in the link), but it would be nice if WDC would fix it.  I do like WDC's 65c22 above the other brands because when the pins are input mode, they present a CMOS load instead of LSTTL.  This has been very valuable sometimes.  The output drivers of the 65c22 (ie, CMOS) from all manufacturers are much stronger than those of the NMOS, despite the overconservative datasheets.  In my own experiments, WDC's can even pull up with 19mA to 4.2V.

The 6551 ACIA has everything you need for a complete RS-232 (TIA-232) link except a crystal and the line drivers and receivers.  It includes the baud rate generator (unlike the 6850 which lacks it) and five handshake lines: RTS, CTS, DSR, DTR, and DCD.  My RS-232 primer tells about it.  You might not think you have any use for an "antique" RS-232 serial port connection, but UARTs (including this ACIA) are used even for interfacing to some modern displays, including this tiny VGA interface that just came up on the forum.  RS-232 is still used in industrial environments where they need a longer range than you can get with other things like USB which are more oriented toward consumer electronics and are more "black box" and not as hobbyist-friendly.  The ACIA can also be used for RS-422 and RS-485 which use different line drivers and receivers but may use the same communications protocol.

In the end of the section "Construction: Avoiding AC-Performance Problems," I tell about expansion buses and synchronous-serial interfaces.  The MAX3100 is a 14-pin UART that interfaces to the processor through SPI.  I've tried it and like it so I will probably use that one in the future.  It has 8-byte transmit and receive buffers and takes less board space than the 6551.  Part of its design is specifically to also be IrDA-capable (for infrared communications).  The MAX3110E is the same thing with line drivers and receivers built in, and it doesn't need any support parts like the popular MAX232 line driver/receiver IC does.

The 65SPI I/O IC, designed and sold by Daryl Rictor, provides direct and complete SPI support in a 65-family IC.  There's a ton of I/O ICs on the market that interface by SPI, and his 65SPI IC is a great way to interface to a lot of them at once.  For example if you want to try USB later, Maxim has USB ICs that take care of all the internal details and interface through SPI and require very few parts.

For detailed information on how to use these and others, consult the data sheets available on 6502.org's data sheet page.  There have been many different 65-family I/O ICs, but the ones listed above are being made today in higher speeds (14MHz or more).  Older ones I am aware of are the

There are lots of non-65-family I/O ICs you can connect to the 6502's buses, but they may require slightly more logic, for example if they have RD and WR inputs.  The simple circuit for deriving those two signals is shown near the end of the Clock Generation section.

You can also use something like 74HCxxx output latches (as output ICs) and input buffers (as input ICs) on the bus, but it's more work and gets you less return on investment.  I started out that way on my first home-made computer, and although it worked, it was a huge amount of labor to build and wasn't really useful for anything.

If you have questions or problems, post them to the forum (preferable) or E-mail me directly at wilsonmines@dslextreme.com .  I check the E-mail several times a day and respond quickly.

My main workbench computer uses the first VIA for:

connected this way:

VIA1 connections

If you can read that, congratulations.  It's from my 3x5" mini ring binder.  Since the page is so full, some of the info I would like to have here is on other pages.  I tried to make this more clear but it was just taking way too much time.  The main thing I wanted to show however is how the printer, LCD, and keypad are connected.

The last list above was also given in the section "Expansion Buses and Interfaces," but without the diagram.  My next one will make more efficient use of the VIAs, allowing more to be connected.

Many of the tips in my "Tip of the Day" topic on the 6502.org forum are about the 6522 and 6551.


Here's a little extra info on the 1.8432MHz input for the 6551 ACIA, typically used for RS-232, for which I have a primer here.  (Note that the 1.8432MHz is separate from the Φ2 rate.  The 6551 still needs a Φ2 signal from the processor, and its frequency does not need to be related at all to the 1.8432MHz used to get the data rates.)  The 6551 also allows connecting a crystal directly to the XTAL1 input and XTAL2 output pins (pins 6 & 7 of a DIP, respectively) as shown in the following diagram (but don't try an RC timebase—it won't be accurate enough).

6551 crystal direct connections

Different manufacturers may have slightly different recommendations.  You can check their data sheets if you really want to do it their way, but the above diagram will probably work with most of them.  WDC recommends a 1M resistor across the crystal to bias the XTAL1 input.

If you have more than one 6551, you can connect the XTAL2 output of the first one to the XTAL1 input of subsequent ones as shown here:
two 6551's on one crystal

If you prefer to use a standard 1.8432MHz crystal oscillator can, just connect its output to the to the XTAL1 inputs (pin 6 of the DIP) of your 6551(s).

The 6551 does not necessarily have to run on this crystal frequency.  MIDI (Musical Instrument Digital Interface) for example, runs at 31.25 kbps.  To get that, connect a 500kHz square wave to the XTAL1 input.  Then in software, set the ACIA to use the clock ÷16 for the transmit baud rate generator, and set the receive clock to be the same as the transmit clock.  So where do you get the 500kHz?  One easy way to get it is from PB7 of one of your 6522 VIAs.  Here's what I have on my workbench computer, showing the DIP-switch clock options for ACIA #2.  This is actually one of the 3x5" pages in my mini ring binder:

ACIA2 connections, showing input clock choices

The code to set it up for MIDI would be as follows:


     LDA  VIA_DDRB
     ORA  #80H		 ; Make VIA PB7 an output for outputting
     STA  VIA_DDRB	 ; the square wave from timer 1 (T1).

     LDA  VIA_ACR
     ORA  #C0H		 ; Free-run T1 with output on PB7.
     STA  VIA_ACR	 ; (Don't enable T1 interrupts though.)

     LDA  #3
     STA  VIA_T1CL	 ; Write 3 to T1CL for 5MHz Φ2.  0 if 2MHz.
     LDA  #0
     STA  VIA_T1CH	 ; Write 0 to T1CH.  (Do T1CL first.)

     STA  ACIA_STAT_REG	 ; (Software reset of ACIA)
     LDA  #1011B
     STA  ACIA_COMM_REG	 ; No parity or echo, TX & RX enabled, no IRQ.
     LDA  # 10010000B	 ; 2 stop bits, 8 data bits, RX clk=TX clk,
     STA  ACIA_CTRL_REG	 ; TX clk=1/16 of XTAL1 input frequency.

For the 65c02, it can be shortened by three lines by using TSB and STZ, or by four lines if your I/O is in ZP and you start with SMB7 above.

You can also have the receive clock and transmit clock different, with the transmit clock on the XTAL1 input and the receive clock on the RxC input (pin 5 of the DIP).  The diagram above shows this too.

Similar to the above, you can get much higher data rates out of the ACIA, still under software control—it's just that it won't be from the 1.8432MHz crystal and the ACIA's own baud-rate generator.  Instead, use the VIA's T1 in free-run mode toggling PB7 on every timeout with no further attention from the processor, and select the rate by writing to T1CL and T1CH as shown in the code above.  The ACIA data sheet says the ACIA is good to 125kbps, and I suspect that that's rather conservative.  115200 is a standard bit rate, and you can get it by running the system on a Φ2 rate of 7.3728MHz (which is a standard crystal & oscillator frequency) and storing 0 in T1CL and T1CH.  Then you can also get all the other standard speeds by writing different values to T1.


Writing    0 to T1 gives 115200 bps.  (These apply to a Φ2 rate of 7.3728MHz.)
Writing    2 to T1 gives  57600 bps.
Writing    4 to T1 gives  38400 bps.
Writing    6 to T1 gives  28800 bps.
Writing  $0A to T1 gives  19200 bps.
Writing  $0E to T1 gives  14400 bps.
Writing  $16 to T1 gives   9600 bps.
Writing  $2E to T1 gives   4800 bps.
Writing  $5E to T1 gives   2400 bps.
Writing  $BE to T1 gives   1200 bps.
Writing $2FE to T1 gives    300 bps.  (The 2 goes in the VIA's T1CH.)

The bit rates shown here are exact.  With adjusted T1 values, it would also work to run Φ2 twice as high, at 14.7456MHz which is another standard crystal & oscillator frequency.  Other Φ2 rates would work too; but to hit the standard RS-232 bit rates exactly (or at least with an acceptable error of about 1% or less), you'll have to work around the poor granularity caused by the big jumps in PB7 output frequency that result from single-step adjustments in T1 value when it's near 0.


I might mention here a potential problem that's relatively simple to prevent but may be difficult to troubleshoot.  When servicing 6551 ACIA interupts for simultaneous transmission and reception, remember that reading the status register clears the interrupt, but the interrupt could have been caused by both TX register empty and RX register full at the same time.  If your ISR ends before finding all the interrupt causes, it may, for example, find the receive register full, service that, and then exit thinking it's done, when in actuality the transmit register emptied before you read the status register and it's waiting for the next byte.  Now the IRQ line is false and the issue will never be addressed, and transmission will come to a halt.  If more than one thing in the same IC could need service, make sure the ISR doesn't stop before the whole job is done.  This is from my tip #14 in my "Tip of the Day" column.


Note that there are lots of I/O interfacing ideas on the "potpourri" page, and I will keep adding more as time permits.  It includes links to code to work the various circuits.


Custom PCBs <--Previous   |   Next--> Displays

last updated May 2, 2017