After having success making a single-board, Z80-based computer that can turn on a LED, you may wish to make a computer with slightly enhanced output capabilities. To this end, this second project will connect an industry-standard graphical LCD screen to the Z80, and allow you to draw things on it. Although this project is still pretty simple and doesn't draw anything more than three bars on the display, the beauty of it is that you can draw anything you want, simply by re-programming the ROM chip. Just as with more complicated and modern computers, the hardware is just a framework, from which you can do just about anything imaginable through software.
Although much (most) of the wiring involved in this project duplicates what was already done in the first Z80 project, the text for those parts of the assembly will be repeated here; For the sake of completeness, this project does not assume that you have done and understood the first project, so you can take this project alone and begin with it if you so wish.
As you put this project together, you will need some way to hold the parts together and connect them, while keeping everything (including the wires) in place so they don't flop around. That's what the breadboard is for. Get the biggest breadboard you can find; Trust me, when you start building projects like this, you'll be glad for the extra space eventually. For this project, I recommend you put the CPU in the center, and the ROM and the VIA on either side of the CPU. This is because the ROM does not have any connections to the VIA, but the CPU has plenty of connections to both of them; This way, you will reduce how much you have to extend your wiring. Similarly, the LCD connects only to the VIA, so put it on the opposite side of the VIA from the CPU.
The industry-standard pin-numbering scheme for DIPs is to place pin 1 in the upper-left corner, and begin moving down, until you reach the half-way pin in the lower-left corner. From there, move to the right side and move back up, ending up with the highest-numbered pin in the upper-right corner. For example, on a 40-pin chip, pin 1 is in the upper-left corner, pin 20 is in the lower-left corner, pin 21 is in the lower-right corner, and pin 40 is in the upper-right corner. Note that this requires knowing which side is "up" on the chip; Most chips are manufactured with a small orienting notch carved into one side. This notch is meant to be at the top in all pin diagrams.
Let's start with the centerpiece of the computer, the CPU. As has been mentioned, for this project we're using the classic Z80 CPU. This CPU is an amazing little piece of work, and it was well ahead of its time. It's very easy to work with, for several reasons. First of all, it has an I/O request pin, meaning it doesn't require the use of memory-mapped I/O. (If you don't know what that means, be thankful.) It has an extremely easy-to-remember NOP opcode (all zeros!), and it doesn't use any dynamic registers (which will be elaborated upon a little later). The pinout for this CPU is as follows:
1: A11 2: A12 3: A13 4: A14 5: A15 6: CLK 7: D4 8: D3 9: D5 10: D6 11: Vcc (+5V) 12: D2 13: D7 14: D0 15: D1 16: /INT 17: /NMI 18: /HALT 19: /MREQ 20: /IORQ 21: /RD 22: /WR 23: /BUSAK 24: /WAIT 25: /BUSRQ 26: /RESET 27: /M1 28: /RFSH 29: Vss (Ground) 30: A0 31: A1 32: A2 33: A3 34: A4 35: A5 36: A6 37: A7 38: A8 39: A9 40: A10
Let's get all those weirdly-named control pins (the ones from 16 to 28) out of the way first. All of these pins are active-low, which is normally indicated by a line over the pin name. However, as there's no way to put a line over text in a plain ASCII text file, the convention in text is the signify active-low with a slash before the pin name, which is the convention used here. What does active-low mean? It simply means that the pin's function is active when it is receiving a low voltage. (This is as opposed to the norm, active-high, which is on when it receives a high voltage.)
Of all these control pins, only 5 are inputs to the Z80. The rest are outputs, meaning they can be ignored for now as they are not crucial to the functionality of the CPU itself. The five input control pins are: INT, NMI, WAIT, BUSRQ, and RESET. The good news is that we don't need to worry about what any of these pins do right now, so just connect them all directly to the high side of your power supply (to disable them), EXCEPT for RESET, which we do need to concern ourselves with. We'll come back to reset a little later.
Pin 11 is the positive 5 volts of your power supply, and pin 29 is the ground (negative) end, so connect these two pins to your power supply so the CPU has power.
The CLK pin is an interesting beast. Every CPU chip has a clock pin, and this pin is simply a trigger for the CPU: Every time the clock input pulses, the CPU performs a cycle (which basically means it runs an instruction). That's right, the speed of the CPU is externally-controlled. You can run the CPU as fast or as slow as you want to, simply by changing how fast the CLK pin pulses up and down, although if you make it too high, the CPU will stop being able to keep up and may overheat from trying too hard. This is why every CPU in the world has a hertz rating, which is how fast it can handle clock pulses before it stops working reliably. You can go under this speed by simply lowering your clock pulse, but you can't go much over it without risking damage to the CPU.
The clock input can be a little difficult to generate if you're not familiar with analog electronics. Because the timing of it is so precise, you cannot simply manually cycle the clock by flipping it from low to high with a switch. Doing this will make a split-second instability during each transition, because whenever you press or release a hand-operated switch, the circuit state does not go instantly from low to high, or high to low; Rather, it fluctuates between them for just a fraction of a second. Although it doesn't seem like a long time to you, the clock input of a CPU is so sensitive that trying to pulse it by hand will make the CPU crash instantly. (This behaviour of switches is called "switch bounce", and is an inescapable fact of life when working with switches in electronics.)
So what must you do with this clock input? You need to supply it with a good clean square wave, which is an electric signal which rises and falls instantly (or pretty close to instantly). This creates a waveform which looks like a series of three-sided squares or rectangles, hence its name:
ÚÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄ
The creation of square-wave clock signals is a whole world of a topic unto itself. As such, it is out of the scope of this file; For now, a very quick cook-book recipe for making a square wave suitable for use with a CPU like the Z80 is as follows:
Take a 4093 chip, which is a Schmitt trigger NAND gate logic chip. (If you don't know exactly what that means, don't worry about it.) Power it up by connecting its pin 14 to +5 volts and pin 7 to ground. Connect pin 1 to ground through a capacitor, and also connect pin 1 directly to pin 2. Lastly, connect pin 1 to pin 3 through a resistor, and then pin 3 becomes your clock output; Connect pin 3 to the clock input on your CPU (which is pin 6 in the case of the Z80).
You can change the speed of the clock by changing the values for the resistor and capacitor. For a tiny tutorial circuit like this, I found that using a 62,000-ohm resistor and a 10 microfarad capacitor worked well at creating a very slow square wave of about one pulse a second, which would mean that the CPU is running at 1 hertz, or one millionth of a megahertz. Later on, if you want things to run a little faster, you can change the capacitor to a lower farad rating (0.1 microfarads will run fairly quickly), or change the resistor to a lower ohm level (1,000 to 5,000 ohms will also be pretty fast), but this is a good start so you can see exactly what is going on and what the CPU is doing, in slow-motion.
It is worth noting that the Z80 is the only major computer CPU in the history of microelectronics that does not use any dynamic registers. Dynamic registers function much like dynamic RAM (DRAM) in that they must be constantly refreshed, or they lose their contents. Virtually every other CPU that was widely used, from the 6502 to the 80x86 family, uses these dynamic registers, and so they have a minimum clock speed which must be maintained for them, or their dynamic registers will lose their contents. The Z80 is so stable that it can actually be stopped at a standstill and still not lose its data. In fact, you can even set up a circuit to hand-clock it with a push-button switch. (If you do so, however, you must connect the button to the clock input pin through some stabilizing circuitry so that it produces a clean rise and fall, instead of a ragged, unsteady rise and fall.)
The usual way of making a clock input for a CPU is with a quartz crystal oscillator. However, because of the Z80's ability to run at any speed, it is possible to use this method with a 4093 chip. With any other CPU, it would be difficult to make a proper clock circuit with the 4093 because it's hard to make one fast enough. We're using the 4093 to make the Z80's clock circuit because it lets us slow things way down to 1 hertz or even less, so we can watch what's happening. It would be more complicated to make a pulse this slow with a crystal, since none of them are made at that speed. Although you could always step the speed down using some kind of counter circuit which outputs one pulse for every few thousand (or million) pulses it receives, the 4093 is much easier to use, and we have the ability to use it, so why not? If you move onto other CPUs, you may have to use other means to make the clock input, however.
For the 4093 timer circuit of pin 1 to ground through capacitor, pin 1 directly to pin 2, and resistor between pin 1 and 3 (or 2 and 3), 3 becomes the clock output, and frequency is as follows:
F = 1 / (R X C)
...R is in meg-ohms and C is in micro-farads. F is in hertz.
Example: Using a 100 kilo-ohm resistor (0.1 meg-ohm) and a 1 microfarad cap:
1 / (0.1 X 1) = 10
Thus, the frequency would be 10 hertz. Using a 1 kilo-ohm resistor (0.001 meg-ohm) and a 1 microfarad cap, we would have:
1 / (0.001 X 1) = 1000
And using a 1 kilo-ohm resistor (0.001 meg-ohm) and a 0.001 microfarad cap:
1 / (0.001 X 0.001) = 1,000,000
That pretty much leaves us with the A and D pins of the CPU, which constitute the address bus and the data bus, respectively. We'll get to those in the appropriate sections of the parts describing the other chips in this project.
And now we return to that RESET pin. Like any CPU, the Z80 must be reset when it is first powered on. This is because as the power is first coming on, it goes through a transition state where the power is not quite fully on yet. This kind of marginal voltage confuses digital electronics, and so all CPUs must be immediately reset after they're turned on to clear them out and re-start them with the now-fully-established power. Desktop computers have built-in circuits which automatically reset the CPU when the power comes on, but for this project, we can stand to keep things simple by manually resetting the CPU with a button. Some would argue that resetting the CPU with a button creates the same variation problems that crop up when you try to clock-pulse the CPU with a button; However, this worked for me. Resetting the CPU with a button seems to work well enough. For this, I recommend one of those tiny push-button switches, the kind which are meant to be mounted on a printed circuit board. You can get them to fit on a breadboard too; They take up very little space and they work quite well. Use a momentary, normally-open push-button switch. (The "momentary" part means that it only takes effect when you push it, as opposed to a toggle switch, which flips back and forth each time you push it. The "normally-open" part means that it is not connected when it's not pushed.)
Begin by connecting the button to the Z80's RESET pin, and connecting the other side of the button to ground. This way, when you push the button, the RESET pin will go to ground, and since it is active-low, pushing the button will reset the CPU. But this leaves us with another interesting electronic problem: When we let go of the button, the RESET pin needs to go high. How can we make it do this? We could certainly just connect it directly to the high end of the power supply, but then when we pushed the button... Well, you can hopefully guess what would happen. We'd be connecting the two sides of the power supply directly together, which would result in a short-circuit. To deal with this problem, we'll use what is technically called a "pull-up resistor", a resistor used to keep something high when it will sometimes be connected directly to ground. Run a 3,000-ohm resistor from the Z80's RESET pin to the positive end of the power supply. Now, normally the resistor will keep the pin high, so the CPU does not reset. But when we push the button, the button provides a direct path to ground, and that direct path is stronger than the path to the high voltage (because there's a 3K-ohm resistor in the way), so we can reset the CPU without fear of it getting confused or short-circuiting.
As an afterthought, you may want to take a moment to add a capacitor to your CPU. This should simply be a capacitor connected directly between the positive and negative sides of the power supply, connected as close to the CPU as possible; This adds some stability to digital ICs, and generally you should have one on any CPU you use. (This is called a "decoupling capacitor".) The capacitor should be fast (i.e. have a low farad rating, somewhere from 0.1 to 4.7 microfarads), and it should prefereably be ceramic, although I used a mylar one.
For that added touch to your computer, you can add a reset IC, which is an ultra-simple IC which resets your CPU for you automatically. Essentially, a reset IC is a chip with three pins, two of which are simply connected to the power supply, and the third of which is a reset output. If for any reason the power wavers or is otherwise not appropriate for powering digital electronics (such as when the power supply is first powering up when you turn it on), the reset IC sends a reset signal out; When the power stabilizes, it releases the reset signal. It really is that simple. These reset ICs are very cheap and they eliminate the one step that you need to do to get your computer working (besides plugging it in). If you don't use such a device then you just need to reset the system manually with a switch every time you turn it on.
You are now finished wiring your Z80 CPU chip.
(For my earlier quick-start guide to the Z80, click here.)
For this project, we're using a 2865 EEPROM chip, which is an 8-bit, 8-kilobyte, 28-pin ROM chip that can be easily programmed and re-programmed without special chip-erasing-and-burning hardware. It's also fairly inexpensive (mine was $5), making it a good choice for a small hobby project. The pinout for the 2865 is as follows:
1: READY/BUSY 2: A12 3: A7 4: A8 5: A5 6: A4 7: A3 8: A2 9: A1 10: A0 11: D1 12: D2 13: D3 14: Vss (Ground) 15: D4 16: D5 17: D6 18: D7 19: D8 20: /CE (Chip Enable) 21: A10 22: /OE (Output Enable) 23: A11 24: A9 25: A6 26: N.C. (Not Connected) 27: /WE (Write Enable) 28: Vcc (+5 Volts)
The very first thing you need to do with the ROM chip, before you can actually incorporate it into your circuit, is program it. This project uses a "much" larger program than the first project, which simply turned on a LED. This project will create a simple pattern on the LCD, which requires a fair bit of programming. The program is as follows:
0000000000000: 00111110 (3E) ;LD A,#FF 0000000000001: 11111111 (FF) 0000000000010: 11010011 (D3) ;OUT (#02),A 0000000000011: 00000010 (02) 0000000000100: 11010011 (D3) ;OUT (#03),A 0000000000101: 00000011 (03) 0000000000110: 00111110 (3E) ;LD A,#06 0000000000111: 00000110 (06) 0000000001000: 11010011 (D3) ;OUT (#00),A 0000000001001: 00000000 (00) 0000000001010: 00111110 (3E) ;LD A,#3F 0000000001011: 00111111 (3F) 0000000001100: 11010011 (D3) ;OUT (#01),A 0000000001101: 00000001 (01) 0000000001110: 00111110 (3E) ;LD A,#07 0000000001111: 00000111 (07) 0000000010000: 11010011 (D3) ;OUT (#00),A 0000000010001: 00000000 (00) 0000000010010: 00111110 (3E) ;LD A,#06 0000000010011: 00000110 (06) 0000000010100: 11010011 (D3) ;OUT (#00),A 0000000010101: 00000000 (00) 0000000010110: 00111110 (3E) ;LD A,#0E 0000000010111: 00001110 (0E) 0000000011000: 11010011 (D3) ;OUT (#00),A 0000000011001: 00000000 (00) 0000000011010: 00111110 (3E) ;LD A,#B7 0000000011011: 10110111 (B7) 0000000011100: 11010011 (D3) ;OUT (#01),A 0000000011101: 00000001 (01) 0000000011110: 00111110 (3E) ;LD A,#0F (This is address 001E) 0000000011111: 00001111 (0F) 0000000100000: 11010011 (D3) ;OUT (#00),A 0000000100001: 00000000 (00) 0000000100010: 00111110 (3E) ;LD A,#0E 0000000100011: 00001110 (0E) 0000000100100: 11010011 (D3) ;OUT (#00),A 0000000100101: 00000000 (00) 0000000100110: 11000011 (C3) ;JP #001E 0000000100111: 00011110 (1E) 0000000101000: 00000000 (00)
(The first number is the byte address on the chip, the second number is the actual data value that should be in that memory cell. The third number, in parentheses, is the hexadecimal value of the data byte, and the text after some of those bytes is just the assembly-language instructions, placed there for easy reference.) Remember that in this kind of binary work, bit numbers are read from right to left, so in the first byte (which is 00111110), pin D1 on the ROM chip should correspond to 0, D2 should correspond to 1, etc. (In other words, D2 should NOT be 0, and D7 should NOT be 1, which is how it would be if the pins were numbered from left to right.) It is beyond the scope of this file to detail how to program an EEPROM chip; If you have one and don't know how, read my separate electronics writeup, How to program an EEPROM.
Below, the code is reproduced in Z80 assembly language. Here you can see exactly what the code is doing.
;Make all VIA's pins be outputs by loading 11111111 into the accumulator, and ;then putting that on ports 2 and 3 (DDRB and DDRA) LD A,#FF ;00111110 11111111 or 3E FF OUT (#02),A ;11010011 00000010 or D3 02 OUT (#03),A ;11010011 00000011 or D3 03 ;Put D/I low for instruction ;Put 6h into accumulator, then put accumulator onto port 0, which is ORB LD A,#06 ;00111110 00000110 or 3E 06 ;Change the above line to LD A,#00 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 ;D/I should now be low ;Put 3Fh (00111111b) into the accumulator, which is the "turn LCD on" command LD A,#3F ;00111110 00111111 or 3E 3F ;Stick the accumulator onto port 1, which is ORA OUT (#01),A ;11010011 00000001 or D3 01 ;Toggle the LCD's Enable pin to make the command take effect LD A,#07 ;00111110 00000111 or 3E 07 ;Change the above line to LD A,#01 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 LD A,#06 ;00111110 00000110 or 3E 06 ;Change the above line to LD A,#00 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 ;LCD's Enable pin has now been toggled, and the LCD should be on ;Put D/I high for data LD A,#0E ;00111110 00001110 or 3E 0E ;Change the above line to LD A,#08 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 ;D/I is now high ;Store 10110111 (B7h) (pixel pattern) in the accumulator LD A,#B7 ;00111110 10110111 or 3E B7 ;Put it in ORA OUT (#01),A ;11010011 00000001 or D3 01 ;Toggle LCD's Enable LD A,#0F ;00111110 00001111, So that D/I and Enable are high at the same time ;Change the above line to LD A,#09 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 LD A,#0E ;00111110 00001110, So that Enable goes low, but D/I remains high ;Change the above line to LD A,#08 if your LCD uses active-low CS pins OUT (#00),A ;11010011 00000000 or D3 00 ;Keep toggling Enable infinitely JP #001E ;11000011 00011110 00000000 or C3 1E 00
After the chip is programmed, you can drop it onto your circuit board. Begin by powering it up (connecting it appropriately to your power supply via pins 28 and 14). Keep pin 27 (Write Enable) high, since that pin is only used to write to the ROM, and you do not want to overwrite this program that you worked so hard to get into it in the first place. Keep pin 20 (Chip Enable) low so that the chip is enabled (because CE is active-low).
Connect the ROM's data bus to the CPU's data bus. This is basically a matter of simple name-matching with wires, EXCEPT for one small anomaly: The ROM's data bus pins are numbered beginning with 1, while the Z80 CPU's data bus is numbered beginning with 0, resulting in an off-by-one difference for each pin mating. Below is a table indicating where each pin on the CPU should meet each pin on the ROM (the CPU's pin is on the left, the ROM's pin is on the right):
D0 --- D1 D1 --- D2 D2 --- D3 D3 --- D4 D4 --- D5 D5 --- D6 D6 --- D7 D7 --- D8
Normally you'd connect the ROM's address bus pins to the CPU in exactly the same way. However, because the program we're using only goes up to memory address 101000, we're actually only using the bottom six address bus pins. Therefore, you can simply connect all of the ROM's address bus pins from A6 to A12 directly to ground (since they will always be low, or 0), and then just connect A0 to A5 directly to the corresponding CPU pins. (Inexplicably, while the 2865 numbers its D pins beginning with 1, the A pins begin with 0 just as they do on the Z80, so you can match the names directly.)
Now all that's left on the 2865 is the OE (Output Enable) pin, which, when activated, makes the ROM spit out whatever is in the selected memory address. This pin can be connected directly to the MREQ pin on the CPU, since the CPU uses that pin to tell memory when it wants to access it. The Z80's MREQ pin is active-low, and so is the 2865's OE pin, so you can just run a wire directly between them without any conversion.
You are now finished wiring your 2865 ROM chip.
If you really want to cut down on the number of obscure parts you're using for this project, you can certainly omit the I/O chip and create your own I/O circuitry. All it really is is a buffer of the data bus, so you can set up some kind of glue logic that latches the data bus and maintains it on some other wires, but the I/O chip we're using is a fairly simple beast, and it will make things a lot easier on you later when you want multiple peripherals. Trust me, it's worth getting an I/O chip and learning to use it, it will make your life easier.
I'm a fan of the 6522 VIA (Versatile Interface Adapter) chip. It's simply and logically designed, yet quite powerful. It's fairly readily available and very cheap. The biggest irony of this project is that even though the 6522 was designed to work with the 6502 CPU, I interfaced it with one of the 6502's biggest competitors, the Z80. (The Z80 family has an I/O chip of its own, the Z80-PIO; However, as I said, I'm a fan of the 6522.)
The 6522's pinout is as follows:
1: Vss (Ground) 2: PA0 3: PA1 4: PA2 5: PA3 6: PA4 7: PA5 8: PA6 9: PA7 10: PB0 11: PB1 12: PB2 13: PB3 14: PB4 15: PB5 16: PB6 17: PB7 18: CB1 (Control for Port B) 19: CB2 (Control for Port B) 20: Vcc (+5V) 21: IRQ (Active-low; Output to the CPU, not an input to the VIA) 22: R/W (High = read, low = write) 23: CS2 (Chip Select 1; Active-low) 24: CS1 (Chip Select 2; Active-high) 25: CLK2 (Enable) 26: D7 27: D6 28: D5 29: D4 30: D3 31: D2 32: D1 33: D0 34: RES (Reset; active-low) 35: RS3 (Register Select 3) 36: RS2 (Register Select 2) 37: RS1 (Register Select 1) 38: RS0 (Register Select 0) 39: CA2 (Control for Port A) 40: CA1 (Control for Port A)
Ignore the CA and CB pins for this project; We won't be using them at all.
Begin by powering up the VIA by connecting pins 20 and 1 to your power supply as appropriate.
The RS pins on the VIA are normally connected to a CPU's address bus, and that's exactly what we're going to do here. Connect RS0 on the VIA to A0 on the Z80, RS1 on the VIA to A1 on the Z80, RS2 on the VIA to A2 on the Z80, and RS3 on the VIA to A3 on the Z80. Similarly, connect all the D pins to each other; This is just a matter of pin-name-matching, once again.
For the 6522 to work, both CS (Chip Select) pins must be active. The trick here is that CS1 is active-high and CS2 is active-low; So tie CS1 to the high side of your power supply and CS2 to the low side. Also tie R/W to the low side (which signals a write to the VIA), because for this project, we're always writing to the VIA, never reading from it.
The CLK2 pin is a bit of a problem here. (This is the only point where interfacing the 6522 to a CPU other than the 6502 becomes problematic.) You see, this pin is meant to be directly connected to a clock output on the CPU. However, the Z80 does not have the appropriate clock output; The 6502 does. Luckily, the function of this pin is very simple: It just enables the 6522. We can easily substitute the Z80's "I/O Request" (IORQ) pin, which is the pin used by the Z80 to tell the I/O chip that it needs to access I/O. There's just one other problem here: The Z80's IORQ pin is active-low, and the 6522's CLK2 pin is active-high. If you directly connect them, the result will be the opposite of what you want. The solution is simple: Connect them through a NOT gate.
There are all kinds of ways you can invert the signal, but the simplest way that I could think of (and thus, the method I used) was to connect them with a 7404 chip, which is a NOT gate logic chip. So get a 7404 (nearly any variety, such as 74F04, 74C04, 74LS04, etc. should work) and bring it to your project board. Begin, as usual, by powering it up, which in this case means connecting its pin 14 to +5 volts, and its pin 7 to ground. Now you can connect the Z80's IORQ pin to any input on the 7404. (It has 6 inputs, I used the one on pin 13 because that was the one closest to my Z80.) Then connect the corresponding output on the 7404 (which, if you're using pin 13 for an input (like I did), is pin 12) to CLK2 on the 6522. That's all you need to do as far as CLK2 goes.
Almost done! The 6522 has a reset pin, just like the CPU. Add a reset button to it, just like the CPU; Connect the pin to ground through the button, and add a 3,000-ohm pull-up resistor so the pin normally stays high.
Now all that's left is those PA and PB pins. Those pins are the actual I/O buses, the two I/O buses that are built into the 6522. For this project, we're using most of these pins; However, they are covered below in the section on the LCD.
You are now finished wiring your 6522 I/O chip.
(For my earlier introduction to the 6522, click here.)
For this project, I used a 128 X 64 pixel graphical LCD display based on the Samsung KS0108 chip, which seems to be the standard chip for controlling small graphical LCD displays like this. Using a character-based LCD would have probably been easier to implement, and would certainly be easier to program, but you can only display text with one, which is dinky.
The pinout for this display is as follows:
1: Vss (Ground) 2: Vdd (+5V) 3: V0 (Contrast adjust) 4: RS (or D/I) (0 = instruction, 1 = data) 5: R/W (0 = Write to LCD, 1 = read from LCD) 6: E (Enable) 7: DB0 8: DB1 9: DB2 10: DB3 11: DB4 12: DB5 13: DB6 14: DB7 15: CS1 (Chip select 1; Selects left side of screen) 16: CS2 (Chip select 2; Selects right side of screen) 17: RST (Reset; Active-low) 18: Vee (-8V OUTPUT) 19: A (Backlight anode) (Positive connection) 20: K (Backlight cathode) (Negative connection)
Begin, as usual, by powering up the display; Connect pins 1 and 2 to your power supply. You will also need to set up pin 3 to control the LCD's contrast. Do this by connecting one side of your trimming resistor to +5 volts and the other side to Vee on the LCD (which is a negative voltage output). Then connect the wiper (center connection) on the trimmer resistor to pin 3, which is V0, the contrast adjust. Now when the LCD is turned on, you can adjust its contrast by adjusting the trimmer resistor.
For this project, I connected the data bus of the LCD (pins 7 to 14) to I/O bus A on the VIA, so just connect them directly. (DB0 on the LCD goes to PA0 on the VIA, DB1 goes to PA1 on the VIA, etc.) Enable on the LCD goes to PB0 on the VIA. CS1 and CS2 on the LCD go to PB1 and PB2 on the VIA, respectively. RS (also known as D/I) on the LCD goes to PB3 on the VIA. Although you can use basically any pins on the VIA that you like to control these LCD pins, the ROM program given on this page is for this configuration; If you change one, you'll have to change the other to accomodate for that.
I didn't connect R/W on the LCD to the VIA, but rather I left it tied to ground, since it can stay low (as we're always writing to the LCD, never reading from it). If you later want to change this, you can connect it to a spare I/O bus pin on the VIA and control it through that.
The RESET pin is the same story as with the CPU and the VIA; Hook up a pull-up resistor and a momentary button to short it to ground so it resets when you push the button.
You can leave the two backlight pins alone; They just exist to turn on the built-in backlight on the LCD which brightens it up a bit, but if you're using this LCD in a well-lit location, you don't need to do anything with them.
(For my earlier introduction to KS0108-based LCDs, click here.)
You are now finished wiring your LCD.
Congratulations! You are also finished assembling your single-board computer.
Begin by powering up your power supply. Hold down all three reset buttons for a few seconds, then release them. (The 6522 VIA and the LCD display both reset almost instantly, but the CPU's reset line must be held low for a few clock cycles in order for it to reset properly, so hold down its button for perhaps 10 seconds.) After this, all that's left is to simply watch the LCD. After a few moments, it should suddenly turn on, and after that, a pattern of straight horizontal bars should begin slowly extending across it. If this happens, congratulations! You have successfully built, programmed, and operated a scratch-made computer with an LCD!