How to Build the Home Micro HM1000
Table of Contents
1 Parts
- 1x 14.31818MHz crystal oscillator.
- 1x ATmega328p.
- 1x DIP32 Flash chip, at least 64 kilobit. For example, Microchip SST39F010A.
- 1x DIP32 SRAM chip, at least 512 kilobit. For example, Alliance AS6C1008.
- 1x WDC 65C02S or 65C816S.
- 1x 74HC08 quad 2-input AND gate.
- 1x 74HC10 triple 3-input NAND gate.
- 1x 74HC138 3-to-8 line demultiplexer; inverting.
- 1x 74HC139 dual 2-to-4 line decoder/demultiplexer.
- 2x 74HC161 presettable synchronous 4-bit binary counter.
- 1x 74HC166 8-bit parallel-in/serial-out shift register.
- 3x 74HC541 octal buffer/line driver; 3-state.
- 1x 74HC299 8-bit universal shift register; tri-state.
- 1x 74HC574 octal D-type flip-flop; positive edge-trigger; tri-state.
- 5x 1K ohm resistor.
- 2x 10K ohm resistor.
- 1x 100 microfarad capacitor.
- 8x 0.047 microfarad capacitor.
- VGA port.
- A power switch.
- 5V power supply.
You will also need something to build it on and some way to connect the components. The computer can be built on a breadboard (it fits on a 3220 tie-point board) or using wire-wrap. Printed circuit board would also be possible, but no PCB layout is available yet.
A number of parts contain flash memory that must be programmed. For this, an appropriate programming circuit is required. The recommended way to go about this is to use a Raspberry Pi with GPIO headers. The software tools in the Home Micro project can use the Raspberry Pi's GPIO pins along with simple circuits to program the Flash chip for the ROM and the I2C EEPROMs used as cartridges. The AVRDUDE utility (http://www.nongnu.org/avrdude/) can be used to program the AVR microcontroller with a simple circuit connected to a Raspberry Pi.
- To program the ROM, you can use
- The circuit at ./design/rom-programmer.txt.
- The program in ../tools/memory/writerom.c.
- To program cartridges, you can use
- The circuit at ./design/cartridge-programmer.txt.
- The program in ../tools/cartridge/writecart.c.
1.1 Substitutions
In many cases, other parts can be substituted for the ones listed above. For example, you should be able to use AHC logic instead of HC without any problems. HCT probably also works fine. The parts list shows HC parts because those tend to be easiest to obtain.
For the RAM, make sure that the data lines are high impedance when ce# is high.
For the CPU, you need a 6502 with a bus enable pin. Other variants can be made to work, but you will have to add logic to stop the CPU from driving the address and data buses when bus enable is low. The CPU also needs to be able to run at 1.79MHz. Using the 65C816S allows for the possibility of later reusing it in a more advanced, even 16-bit computer.
Instead of an ATmega328p, you can use an ATmega328 (without the p).
Instead of '574s you can use '374s. They do the same thing, but the pinout is different, so be sure to wire them correctly.
No particularly stringent requirements are put on the diodes connecting to the keyboard. This means that, instead of 1N4148, many other types of diode could be used. Probably the most important thing to pay attention to is the forward voltage drop. If this exceeds 1.3V, the diode cannot pull its anode low enough to read as a logic 0, so you need a diode with a forward voltage drop that's comfortably below 1.3V.
2 How to Read the Instructions
The wiring tables shown in the instructions have tables that show what to connect each pin to. Pin numbers are shown in the first column, along with a pin name as it may be found in the component's datasheet. Due to different manufacturers using different pin names, not all names necessarily match those in your components' datasheets exactly. Moreover, although many components used have standard pinouts, in other cases, different components that perform the same function may have different pinouts. Generally, the text will point out cases where the pinout shown in the table may not match the pinout of your actual component.
Connections are shown in the second column. Connections to signals that already exist when the component is added are shown as regular text. Italics indicate connections that will be made later. These are usually signals that are provided by the component, which will be connected once components that require them are inserted. There are also a number of special signal names. A table may look like:
Pin | Connection |
---|---|
1 (reset#) | high |
2 (s) | low |
3 (a) | siga |
4 (gnd) | GND |
5 (b) | NC |
6 (y) | sigb |
7 (oe#) | low |
8 (vcc) | Vcc |
This shows a hypothetical component with 8 pins. The way to read the connections is:
- Vcc
- This is the supply voltage (+5V). Data sheets may also refer to it as Vdd.
- GND
- This is the ground (0V). Data sheets may also refer to it as Vss.
- high
- This pin should be connected to a logic high value. The easiest way to do so is to connect it to Vcc.
- low
- This pin should be connected to a logic low value. The easiest way to do so is to connect it to GND.
- NC
- No connect. This pin should be left unconnected.
- siga (regular text)
- Connect this pin to the existing siga signal. Generally, the instructions will provide a source of that signal within parentheses. Note that, in some cases, the pin number a signal is provided on may vary based on the exact component used. For example, the 74HC374 and 74HC574 provide the same signals, but on different pins. Therefore, double-check that you are using the correct pins for the components you're actually using.
- sigb (italics)
- This pin will be connected later. We will refer to the signal it provides as sigb.
3 Instructions
3.1 VGA Signal
Insert the crystal oscillator. Consult the data sheet for correct wiring. Commonly, crystal oscillators come in dual in-line packages that are the size of a DIP8 or DIP14, but have only 4 leads. Generally you will wire one pin to Vcc, one pin to GND, and one pin will be your output. The remaining pin may be no connect or it may be an enable/disable pin.
You can check that everything is working right on the oscilloscope. You should have a waveform that oscillates at 14.31818MHz or something very close to it, with a minimum of less than 1.6V and a maximum of at least 3.3V. It may look more like a sawtooth wave than like a square wave. If so, that's ok - as long as the frequency is correct and it reaches the required voltages.
Insert the ATmega328p. Wire it as follows:
Pin | Connection |
---|---|
1 (reset#) | High |
2 (pd0) | va0 |
3 (pd1) | va1 |
4 (pd2) | va2 |
5 (pd3) | va3 |
6 (pd4) | va4 |
7 (vcc) | Vcc |
8 (gnd) | GND |
9 (pb6/xtal1) | clk14 (output from the oscillator) |
10 (pb7) | NC |
11 (pd5) | va5 |
12 (pd6) | va6 |
13 (pd7) | va7 |
14 (pb0) | va8 |
15 (pb1) | va9 |
16 (pb2) | va10 |
17 (pb3) | va11 |
18 (pb4) | va12 |
19 (pb5) | NC |
20 (avcc) | High |
21 (aref) | High |
22 (gnd) | GND |
23 (pc0) | NC |
24 (pc1) | NC |
25 (pc2) | vrdy |
26 (pc3) | video active |
27 (pc4) | hsync |
28 (pc5) | vsync |
If all is well, pin 28 (pc5) should output a signal that stays high for 16.656ms, then goes low for 0.064ms, for a frequency of about 59.8Hz. This is the vsync signal. Pin 27 (pc4) should output a signal that stays high for 27.937us, then goes low for 0.629us. This is the hsync signal. Don't worry if the oscilloscope displays slightly different values. If you're getting the signals and your crystal has the right frequency, the signals should be right.
Add the VGA port. For the numbering, if the wide side of the port is up, pin 1 is in the top right, pin 5 in the top left, pin 6 in the middle right, pin 10 in the middle left, pin 11 in the bottom right, and pin 15 in the bottom left:
\----------------------/ \ 5 4 3 2 1 / \ 10 9 8 7 6 / \ 15 14 13 12 11 / \--------------/
Wire it as follows:
Pin | Connection |
---|---|
1 (red) | red (1K ohm resistor) |
2 (green) | green (1K ohm resistor) |
3 (blue) | blue (1K ohm resistor) |
4 (id2) | NC |
5 (gnd) | GND |
6 (rgnd) | GND |
7 (ggnd) | GND |
8 (bgnd) | GND |
9 (key) | NC |
10 (sgnd) | GND |
11 (id0) | NC |
12 (id1/sda) | NC |
13 (hsync) | hsync (ATmega328p pin 27) |
14 (vsync) | vsync (ATmega328p pin 28) |
15 (id3/scl) | NC |
Of course, we don't actually have red, green, and blue yet. You can temporarily add 1K ohm resistors to pins 1, 2, and 3, and connect those resistors to pin 26 of the ATmega328p.
When you connect the circuit to a VGA monitor and power it on, the monitor should be able to synchronize to the signal. If you connected the red, green, and blue signals as described above, the monitor should display a grey rectangle.
3.2 Pixels
Add a 74HC161. This will be used to divide the 14.318MHz clk14 signal to lower frequencies. Wire it as follows:
Pin | Connection |
---|---|
1 (mr#) | pin 25 (pc2) of the ATmega328p |
2 (cp#) | clk14 (output of the oscillator) |
3 (d0) | high |
4 (d1) | high |
5 (d2) | high |
6 (d3) | high |
7 (cep) | high |
8 (gnd) | GND |
9 (pe#) | high |
10 (cet) | high |
11 (q3) | NC |
12 (q2) | clk1 (1.79MHz) |
13 (q1) | clk3 (3.58MHz) |
14 (q0) | clk7 (7.16MHz) |
15 (tc) | NC |
16 (vcc) | Vcc |
Add a 74HC08 to create a signal that goes high when video active and clk3 are both high. We will later use the same '08 to generate the ram# and oe# signals.
Pin | Connection |
---|---|
1 (1a) | video active (pin 26 of the ATmega328p) |
2 (1b) | clk3 (pin 13 of the clock divider) |
3 (1y) | activeclk3 |
4 (2a) | a0 |
5 (2b) | clk3 (pin 13 of the clock divider) |
6 (2y) | clk3a0 |
7 (gnd) | GND |
8 (3y) | ram# (connect to the RAM's ce#) |
9 (3a) | a15 (pin 9 of the 74HC10) |
10 (3b) | a14 (pin 10 of the 74HC10) |
11 (4y) | connect to RAM's oe# |
12 (4a) | connect to pin 12 of the '10 |
13 (4b) | clk1 (pin 12 of the clock divider) |
14 (vcc) | Vcc |
We will use a 74HC139 as a load pulse generator. This will generate the ldpix# signal to load pixel data every 8 pixels, and the ldkbrow signal to latch keyboard row data. Wire it as follows:
Pin | Connection |
---|---|
1 (1e#) | rwb (pin 13 of the '10) |
2 (1a0) | io2# |
3 (1a1) | io4# |
4 (1y0#) | NC |
5 (1y1#) | ldsercr |
6 (1y2#) | ldkbrow |
7 (1y3#) | NC |
8 (gnd) | GND |
9 (2y3#) | ldpix# |
10 (2y2#) | NC |
11 (2y1#) | NC |
12 (2y0#) | NC |
13 (2a1) | activeclk3 (pin 3 of the '08) |
14 (2a0) | clk7 (pin 14 of the clock divider) |
15 (2e#) | clk1 (pin 12 of the clock divider) |
16 (vcc) | Vcc |
Connect a 74HC166 shift register. This will be used to shift the pixel data out one bit at a time.
Pin | Connection |
---|---|
1 (ds) | low |
2 (d0) | d0 |
3 (d1) | d1 |
4 (d2) | d2 |
5 (d3) | d3 |
6 (ce#) | low |
7 (cp) | clk14 (oscillator output) |
8 (gnd) | GND |
9 (mr#) | high |
10 (d4) | d4 |
11 (d5) | d5 |
12 (d6) | d6 |
13 (q7) | pixel output |
14 (d7) | d7 |
15 (pe#) | ldpix# (pin 9 of the load pulse generator) |
16 (vcc) | Vcc |
If you made the temporary connection between the ATmega328p and the red, green, and blue lines, remove it now.
Connect each of red, green, and blue to a 1K ohm resistor, and connect those resistors to pin 13 (q7) of the '166.
If you create a bit pattern on the d0..d7 pins of the '166 by temporarily wiring some of the pins low and others high, turning on the power should display the bit pattern, repeated every 8 pixels.
3.3 Memory
The ATmega328p generates addresses to read pixel data from. Let's use those addresses to control the image we display.
To prevent the ATmega328p from accessing memory at the same time as the CPU, we run the address lines from the ATmega through two 74HC541 buffers. The first handles the lower 8 bits of the address, and is wired as follows:
Pin | Connection |
---|---|
1 (oe1#) | low |
2 (a0) | va0 (ATMega328p pin 2 / pd0) |
3 (a1) | va1 (ATMega328p pin 3 / pd1) |
4 (a2) | va2 (ATMega328p pin 4 / pd2) |
5 (a3) | va3 (ATMega328p pin 5 / pd3) |
6 (a4) | va4 (ATMega328p pin 6 / pd4) |
7 (a5) | va5 (ATMega328p pin 11 / pd5) |
8 (a6) | va6 (ATMega328p pin 12 / pd6) |
9 (a7) | va7 (ATMega328p pin 13 / pd7) |
10 (gnd) | GND |
11 (b7) | a7 |
12 (b6) | a6 |
13 (b5) | a5 |
14 (b4) | a4 |
15 (b3) | a3 |
16 (b2) | a2 |
17 (b1) | a1 |
18 (b0) | a0 |
19 (oe2#) | clk1 (pin 12 of the clock divider) |
20 (vcc) | Vcc |
The second one handles the upper 8 bits of the address and is wired like so:
Pin | Connection |
---|---|
1 (oe1#) | low |
2 (a0) | va8 (ATMega328p pin 14 / pb0) |
3 (a1) | va9 (ATMega328p pin 15 / pb1) |
4 (a2) | va10 (ATMega328p pin 16 / pb2) |
5 (a3) | va11 (ATMega328p pin 17 / pb3) |
6 (a4) | va12 (ATMega328p pin 18 / pb4) |
7 (a5) | high |
8 (a6) | low |
9 (a7) | low |
10 (gnd) | GND |
11 (b7) | a15 |
12 (b6) | a14 |
13 (b5) | a13 |
14 (b4) | a12 |
15 (b3) | a11 |
16 (b2) | a10 |
17 (b1) | a9 |
18 (b0) | a8 |
19 (oe2#) | clk1 (pin 12 of the clock divider) |
20 (vcc) | Vcc |
The pinout for the RAM chip shown here is for the Alliance AS6C2008. Other SRAM chips should have similar pinouts. Check your datasheet to make sure. Note that the address pins in the datasheet of the chip do not match the address bit numbers on the bus. This is ok, as long as every bus address maps to a unique and valid address on the chip.
Pin | Connection |
---|---|
1 (a17) | low |
2 (a16) | low |
3 (a14) | a0 (lower address buffer pin 18) |
4 (a12) | a1 (lower address buffer pin 17) |
5 (a7) | a2 (lower address buffer pin 16) |
6 (a6) | a3 (lower address buffer pin 15) |
7 (a5) | a4 (lower address buffer pin 14) |
8 (a4) | a5 (lower address buffer pin 13) |
9 (a3) | a6 (lower address buffer pin 12) |
10 (a2) | a7 (lower address buffer pin 11) |
11 (a1) | a8 (upper address buffer pin 18) |
12 (a0) | a9 (upper address buffer pin 17) |
13 (d0) | d0 ('166 pin 2) |
14 (d1) | d1 ('166 pin 3) |
15 (d2) | d2 ('166 pin 4) |
16 (gnd) | GND |
17 (d3) | d3 ('166 pin 5) |
18 (d4) | d4 ('166 pin 10) |
19 (d5) | d5 ('166 pin 11) |
20 (d6) | d6 ('166 pin 12) |
21 (d7) | d7 ('166 pin 14) |
22 (ce#) | ram# |
23 (a10) | a15 (upper address buffer pin 11) |
24 (oe#) | oe# |
25 (a11) | a14 (upper address buffer pin 12) |
26 (a9) | a13 (upper address buffer pin 13) |
27 (a8) | a12 (upper address buffer pin 14) |
28 (a13) | a11 (upper address buffer pin 15) |
29 (we#) | w# |
30 (ce2) | high |
31 (a15) | a10 (upper address buffer pin 16) |
32 (vcc) | Vcc |
On the AS6C4008, pin 1 is a18 and pin 30 is a17. Wiring it the same way as an AS6C2008 should work.
On the AS6C1008, pin 1 is no connect instead of a17 and you should leave it unconnected.
To test, you can temporarily wire we# high, oe# low, and ce# low. This gives you a circuit that reads an image from memory and displays it. Of course, there is no way to control what is in that memory, so the image you see will be random. It may change when you turn the power off and back on. However, it should not change while the machine is powered on. Undo the temporary wiring after testing.
Add the ROM chip. Consult the datasheet for the proper wiring. The wiring in the table below is for the Microchip SST39SF0{1,2,4}0. The references to pin numbers on the RAM chip correspond to those on the AS6C2008, and may differ if you are using a different RAM chip.
Pin | Connection |
---|---|
1 (a18) | low |
2 (a16) | low |
3 (a15) | low |
4 (a12) | a12 (pin 27 of the RAM) |
5 (a7) | a7 (pin 10 of the RAM) |
6 (a6) | a6 (pin 9 of the RAM) |
7 (a5) | a5 (pin 8 of the RAM) |
8 (a4) | a4 (pin 7 of the RAM) |
9 (a3) | a3 (pin 6 of the RAM) |
10 (a2) | a2 (pin 5 of the RAM) |
11 (a1) | a1 (pin 4 of the RAM) |
12 (a0) | a0 (pin 3 of the RAM) |
13 (d0) | d0 (pin 13 of the RAM) |
14 (d1) | d1 (pin 14 of the RAM) |
15 (d2) | d2 (pin 15 of the RAM) |
16 (gnd) | GND |
17 (d3) | d3 (pin 17 of the RAM) |
18 (d4) | d4 (pin 18 of the RAM) |
19 (d5) | d5 (pin 19 of the RAM) |
20 (d6) | d6 (pin 20 of the RAM) |
21 (d7) | d7 (pin 21 of the RAM) |
22 (ce#) | rom# |
23 (a10) | a10 (pin 31 of the RAM) |
24 (oe#) | r# |
25 (a11) | a11 (pin 28 of the RAM) |
26 (a9) | a9 (pin 12 of the RAM) |
27 (a8) | a8 (pin 11 of the RAM) |
28 (a13) | low |
29 (a14) | low |
30 (a17) | low |
31 (we#) | high |
32 (vdd) | Vcc |
To test, you can temporarily wire the ROM's ce# and oe# low (make sure the RAM chip isn't also driving the data bus, e.g. by removing it or temporarily wiring its ce# high). This causes the video circuit to read from ROM. The displayed image should look like some random noise, some white blocks (corresponding to the memory value $ff), and part of the display should show the machine's character set. If you power the machine off and power it back on, you should see the same pixels as before. After testing, undo the temporary wiring.
3.4 CPU
Consult your CPU's data sheet for the proper wiring. Wiring for the 65C816S is shown below. This assumes the ROM chip pinout of the SST39SF0{1,2,4}0; if your ROM chip is different, adjust the ROM chip pin numbers accordingly.
Note that pins a13, a14, and a15 (pins 23, 24, and 25) connect to the RAM chip rather than to the ROM chip, because we don't use those address lines when addressing ROM.
Pin | Connection |
---|---|
1 (vpb) | NC |
2 (rdy) | 10K ohm pull-up resistor |
3 (abort) | 10K ohm pull-up resistor |
4 (irq) | high |
5 (mlb) | NC |
6 (nmib) | high |
7 (vpa) | NC |
8 (vdd) | Vcc |
9 (a0) | a0 (pin 12 of the ROM chip) |
10 (a1) | a1 (pin 11 of the ROM chip) |
11 (a2) | a2 (pin 10 of the ROM chip) |
12 (a3) | a3 (pin 9 of the ROM chip) |
13 (a4) | a4 (pin 8 of the ROM chip) |
14 (a5) | a5 (pin 7 of the ROM chip) |
15 (a6) | a6 (pin 6 of the ROM chip) |
16 (a7) | a7 (pin 5 of the ROM chip) |
17 (a8) | a8 (pin 27 of the ROM chip) |
18 (a9) | a9 (pin 26 of the ROM chip) |
19 (a10) | a10 (pin 23 of the ROM chip) |
20 (a11) | a11 (pin 25 of the ROM chip) |
21 (vss) | GND |
22 (a12) | a12 (pin 4 of the ROM chip) |
23 (a13) | a13 (pin 26 of the RAM chip) |
24 (a14) | a14 (pin 25 of the RAM chip) |
25 (a15) | a15 (pin 23 of the RAM chip) |
26 (d7) | d7 (pin 21 of the ROM chip) |
27 (d6) | d6 (pin 20 of the ROM chip) |
28 (d5) | d5 (pin 19 of the ROM chip) |
29 (d4) | d4 (pin 18 of the ROM chip) |
30 (d3) | d3 (pin 17 of the ROM chip) |
31 (d2) | d2 (pin 15 of the ROM chip) |
32 (d1) | d1 (pin 14 of the ROM chip) |
33 (d0) | d0 (pin 13 of the ROM chip) |
34 (rwb) | 10K ohm pull-up resistor |
35 (e) | NC |
36 (be) | connect to pin 37 (phi2) |
37 (phi2) | clk1 (pin 12 of the clock divider) |
38 (mx) | NC |
39 (vda) | NC |
40 (resb) | reset# (pin 25 of the ATmega328p) |
When using the 65C02S, pin 3 is an output and should be left unconnected.
3.5 Glue Logic
The address decoder is a circuit that uses the address on the bus to decide if we're accessing RAM, ROM, or I/O. This will be built using a 74HC10 and the 74HC08 that was added earlier. Wire the 74HC10 like so:
Pin | Connection |
---|---|
1 (1a) | high |
2 (1b) | high |
3 (2a) | clk3 (pin 13 of the clock divider) |
4 (2b) | clk1 (pin 12 of the clock divider) |
5 (2c) | connect to pin 12 (1y/r#) |
6 (2y) | w#. connect to RAM's we# |
7 (gnd) | GND |
8 (3y) | rom# (connect to ROM's ce#) |
9 (3a) | a15 (pin 25 of the CPU) |
10 (3b) | a14 (pin 24 of the CPU) |
11 (3c) | a13 (pin 23 of the CPU) |
12 (1y) | r#. connect to ROM's oe# |
13 (1c) | pin 34 (rwb) of the CPU |
14 (vcc) | Vcc |
Add the remaining connections on pins 8 through 13 of the 74HC08:
Pin | Connection |
---|---|
1 (1a) | video active (pin 26 of the ATmega328p) |
2 (1b) | clk3 (pin 13 of the clock divider) |
3 (1y) | activeclk3 |
4 (2a) | low |
5 (2b) | low |
6 (2y) | NC |
7 (gnd) | GND |
8 (3y) | ram# (connect to the RAM's ce#) |
9 (3a) | a15 (pin 9 of the 74HC10) |
10 (3b) | a14 (pin 10 of the 74HC10) |
11 (4y) | connect to RAM's oe# |
12 (4a) | connect to pin 12 of the '10 |
13 (4b) | clk1 (pin 12 of the clock divider)/ |
14 (vcc) | Vcc |
At this point, you should have a computer that can execute boot code from ROM and read from and write to RAM. The memory check should show there are 48 kilobytes of addressable RAM.
3.6 I/O
So far, addresses $0000..$bfff map to RAM and addresses $e000..$ffff map to ROM. We will use $d000..$dfff for I/O, reserving $c000..$cfff for future use. I/O devices each get an address. We decode those addresses with 74HC138. Wiring is shown below.
Pin | Connection |
---|---|
1 (a0) | a1 (pin 11 of the CPU) |
2 (a1) | a2 (pin 10 of the CPU) |
3 (a2) | a3 (pin 9 of the CPU) |
4 (e1#) | a13 (pin 11 of the 74HC10) |
5 (e2#) | clk3a0 |
6 (e3) | ram# (pin 8 of 74HC08) |
7 (y7#) | NC |
8 (gnd) | GND |
9 (y6#) | NC |
10 (y5#) | NC |
11 (y4#) | NC |
12 (y3#) | NC |
13 (y2#) | io4# |
14 (y1#) | io2# |
15 (y0#) | NC |
16 (vcc) | Vcc |
The effect of this is that we have I/O addresses 0 through 7 at $d000 through $d007. The rest of the $c000..$dfff range should not be used. The way we built it, it contains copies of I/O addresses 0 through 7, but future versions of the computer may use those addresses for other purposes.
To implement the serial protocol for reading from and writing to cartridges, add a 74HC161 pre-settable counter. Wiring is shown in the table below.
Pin | Connection |
---|---|
1 (mr#) | high |
2 (cp) | ldsercr (pin 5 of the load pulse generator) |
3 (d0) | d4 (pin 29 of the CPU) |
4 (d1) | d5 (pin 28 of the CPU) |
5 (d2) | d6 (pin 27 of the CPU) |
6 (d3) | d7 (pin 26 of the CPU) |
7 (cep) | low |
8 (gnd) | GND |
9 (pe#) | low |
10 (cet) | low |
11 (q3) | sda |
12 (q2) | scl |
13 (q1) | NC |
14 (q0) | NC |
15 (tc) | NC |
16 (vcc) | Vcc |
To receive bits from the cartridge wire a 74HC299 universal shift register like this:
Pin | Connection |
---|---|
1 (s0) | high |
2 (oe1#) | io4# (pin 13 of the I/O selector) |
3 (oe2#) | oe# (pin 11 of the '08) |
4 (i/o6) | d6 (pin 5 of the serial control register) |
5 (i/o4) | d4 (pin 29 of the CPU) |
6 (i/o2) | d2 (pin 31 of the CPU) |
7 (i/o0) | d0 (pin 33 of the CPU) |
8 (q0) | NC |
9 (mr#) | high |
10 (gnd) | GND |
11 (dsr) | sda from cartridge |
12 (cp) | scl from cartridge |
13 (i/o1) | d1 (pin 32 of the CPU) |
14 (i/o3) | d3 (pin 30 of the CPU) |
15 (i/o5) | d5 (pin 28 of the CPU) |
16 (i/o7) | d7 (pin 6 of the serial control register) |
17 (q7) | NC |
18 (dsl) | low |
19 (s1) | low |
20 (vcc) | Vcc |
Next, add the wiring for the cartridge. The cartridge is a DIP8 with the following pinout:
Pin | Connection |
---|---|
1 (a0) | low |
2 (a1) | low |
3 (a2) | low |
4 (gnd) | GND |
5 (sda) | connect to sda via 1K resistor and directly to '299 pin 18 |
6 (scl) | connect to scl via 1K resistor |
7 (wp) | low |
8 (vcc) | Vcc |
At this point, booting the computer without a cartridge inserted should result in a "insert cartridge" diagnostic. Booting the computer with a cartridge inserted should load and run the program on the cartridge.
3.7 Keyboard
The keyboard works by selecting a row by writing to an I/O register, then reading which columns are active in that row from another I/O register. We implement the row register using a 74HC574 flip-flop, wired as show below:
Pin | Connection |
---|---|
1 (oe#) | low |
2 (d0) | d0 (pin 7 of the '299) |
3 (d1) | d1 (pin 13 of the '299) |
4 (d2) | d2 (pin 6 of the '299) |
5 (d3) | d3 (pin 14 of the '299) |
6 (d4) | d4 (pin 5 of the '299) |
7 (d5) | d5 (pin 15 of the '299) |
8 (d6) | d6 (pin 4 of the '299) |
9 (d7) | d7 (pin 16 of the '299) |
10 (gnd) | GND |
11 (cp) | ldkbrow (pin 6 of the load pulse generator) |
12 (y7) | kbdrow7# |
13 (y6) | kbdrow6# |
14 (y5) | kbdrow5# |
15 (y4) | kbdrow4# |
16 (y3) | kbdrow3# |
17 (y2) | kbdrow2# |
18 (y1) | kbdrow1# |
19 (y0) | kbdrow0# |
20 (vcc) | Vcc |
Here is the wiring for the keyboard column buffer, a 74HC541:
Pin | Connection |
---|---|
1 (oe1#) | io2# (pin 13 of the I/O selector) |
2 (a0) | kbcol0# |
3 (a1) | kbcol1# |
4 (a2) | kbcol2# |
5 (a3) | kbcol3# |
6 (a4) | kbcol4# |
7 (a5) | kbcol5# |
8 (a6) | kbcol6# |
9 (a7) | kbcol7# |
10 (gnd) | GND |
11 (b7) | d7 (pin 9 of the keyboard row register) |
12 (b6) | d6 (pin 8 of the keyboard row register) |
13 (b5) | d5 (pin 7 of the keyboard row register) |
14 (b4) | d4 (pin 6 of the keyboard row register) |
15 (b3) | d3 (pin 5 of the keyboard row register) |
16 (b2) | d2 (pin 4 of the keyboard row register) |
17 (b1) | d1 (pin 3 of the keyboard row register) |
18 (b0) | d0 (pin 2 of the keyboard row register) |
19 (oe2#) | oe# (pin 11 of the '08) |
20 (vcc) | Vcc |
There are two possibilities for connecting the keyboard row register and keyboard column buffer to an actual keyboard. The recommended way is to use a PS/2 keyboard. Alternatively, you can make your own keyboard. Both of these options are described in more detail in the keyboard design document.
Once the keyboard is connected, the computer should be able to detect key presses. You can check this with the testkeys program from the source code repository.
If you have made it this far, congratulations! You have built a working microcomputer.