A first project: Buffered I/O
The design
There are other designs for control applications for the GameBoy. Most just hook up some circuits to the
systembus and then hope for glory. But glory is not based on luck. It's based on preparation, consideration
and design.
The design goals for this GameBoy extension were as follows:
The buffer sections.
A central processor unit cannot drive a lot of inputs. Each input gate absorbs some current and if there are
too many inputs paralelled, the CPU cannot pump enough electrons into the circuits. The result is that the CPU
lowers it's output voltage, which will result in the loss of logic levels. What you end up with, is a system
that behaves well in 99.999% of the cases, but that will let you down just when you need it. Remember that the
CPU carries out millions of instructions per second, so a 10 ppm chance of system error will halt the system
within a minute. Which is not acceptable.
So we introduce the concept of buffering all relevant signals. The advantage is, that now the CPU only sees
one load and the buffer (who can easily drive up to 20 loads) takes care of the rest.
The addressbus is unidirectional. It needs to deliver an address to the rest of the system and it is "output
only". So the best choice would have been to use a set of 74HC541 buffers. But for the ease of purchasing
materials I decided in using bidirectional buffers, which were fixed in direction. The reason will be clear in
a few moments.
The databus needs to deliver data to the peripherals, but it also needs to access the I/O and memory
locations. So the databus buffers need to be bidirectional. The well known 74HC245 buffer is used for this.
The HC245 is a very strong buffer. So when the buffer is sending data back to the GBC mainboard, it will
easily overpower the CPU, so it is only allowed to function if asked to.
That's why the HC245 has a direction control input which is tied to the /RD control line. And to prevent the
245 from disrupting memory accesses in higher memory, the 245 is enabled ONLY when the A15 line is LOW.
In order to make the purchase of parts easier, I chose for the 245 instead of the 541. The latter is also not available everywhere and hence it can be more expensive.
The control lines are buffered by means of a 74HC243, which is half of a 245. It is set to function as output only.
I/O space
Since the GameBoy CPU does not have I/O instructions and related /IORQ pins, we need to find another way to
access the outside world. The solution is easy: we go memory mapped. In the old days, when the Z80 was still
young, there were two schools of thought for processors. One was the Intel family that used different address
spaces for memory and I/O devices. The other was the Motorola section that saw everything as memory. Both
schools have their own advantages.
We are not interested in the advantages of one or the other: we just are faced with the lack of separate address spaces. So we go memory mapped. The trick is to decode one section of memory and assign it a unique signal. In a way, we make our own IORQ signal. This is done with the 74HC30 (8 input NAND) and double 74HC32 (2 input OR) gates. The output of HC30 is LOW only when all inputs are HIGH at the same time.
In the circuit drawing on the left, you see how it's done in this interface. The /IO signal is our proprietary
/IORQ signal and the /CE signal is the chip enable of the ROM device.
The three gates respond to the address range characterized by 0011.1111.11xx.xxxx or in hexadecimal 3FC0
through 3FFF, which is the last part of the lower 16 KB memory. If addresslines are in this range, the /IO
signal is valid.
The ROM must respond to all memory accesses in our range: 0000 to 7FFF. Except for the IO range. This is accomplished by the U2C and U3A in the drawing on the left.
I/O selector circuit
We need to decode the IO range a little further. As can be seen to the left, a 74HC154 chip is used for this.
This is a 4 to 16 decoder. It takes 4 address lines as input. It puts a logical zero on the addressed output
pin. So when the input lines are '1010', output /Y10 is LOW and all other pins are HIGH. The outputs are
labeled 'IOCSxx' as an acronym for
I/O port Chip Select nr xx.
Most I/O chips have 4 internal registers so they need two address lines to function properly. In total we have reserved 6 address lines for our I/O space. So there are four remaining (A02 through A05) and these are fed into the HC154.
I chose to do the decoding on this mainboard and not send all the buffered address lines to all other expansion boards. Now each board can just pick one or more ChipSelects from the set of 15 and do what's needed. This is easier and better for the circuit since there are not much high speed switching signal lines on the expansion connector.
The chip may only activate one of it's outputs when we really are INSIDE the I/O space, so we use the /IO
signal (described above) to enable the HC154.
We end up with a decoder that enables us to connect 16 intelligent I/O devices to the GBC. Each device may use
four addresses. One address is preconfigured (see below) and the other fifteen outputs are brought out to the
40 pin expansion connector.
Memory bank controller MBC-F
I made my own memory bank controller, the MBC-F (the F is for Fruttenboel). The reason is easy: why make
things difficult by removing an MBC-1 from a game cart? The MBC-1 is clearly more sophisticated than my MBC-F,
but mine is easier to make and fully transparent. The circuit drawing is on the left, as you undoubtly have
seen.
The MBC-F is built around a 74HC259 chip. It has 8 individually addressable bits. One bit is addressed by
putting the correct number on the address input lines A0, A1 and A2. We do that with databits 0, 1 and 2. This
makes it easy to access consecutive output bits by simply incrementing the value in the accumulator.
The chip has a /CLR input. If this gets LOW at any time, all output pins are reset to ZERO. That's why the pin
is connected to the /RESET line on the GBC edge connector.
The value stored in bit 7 of the databus is copied to the addressed output pin, when the /Enable input is strobed. This only happens when two conditions are met:
IF A14 = 0 THEN
B16 := 0;
B17 := 0;
B18 := 0;
B19 := 0
ELSE
B16 := A16;
B17 := A17;
B18 := A18;
B19 := A19
END
The WE pin is there to prevent accidental writes to the ROM memory device. Otherwise run-away programs could
easily overwrite large portions of the softare we put there to stay forever. The WE pin must be "1" to enable
the Write signal for the ROM device.
The CLEAR line is an additional line to reset the 82C55 chip. I chose to use a seperate line for this, instead of an inverted /RESET signal since the 8255 is a strange beast and sometimes it canb be handy to just simply reset the lot and start reprogramming it from scratch.
The status LED is a general purpose signal that can be used at will. I am now thinking of incorporating it in a timer routine so that it blinks once every two seconds.
The eighth pin can be used for anything you want. It is brought out to the 40 pin expansion connceor.
Alternative MBC-F
Below the 259 is a so called 'wired or' constructed. In this case, I need 5 OR gates whereas the 74HC32
package contains only 4. So either I install another HC32 and waste 3 gates, or I use a wired OR circuit.
Wired OR truth table
/MBC /WR pin 14
---- ---- ------
0 0 0
0 1 1
1 0 1
1 1 1
The diode will only let a "1" pass. A "0" is blocked. The resistor is a kind of pre-charge or bias for the
output.
This circuit is an alternative design for the MBC-F. It's function is identical. Construction may be easier, but this 257 is 7 cents more expensive... The 257 is a quad 2 to 1 multiplexer. Depending on the A/B selector, the A or B inputs are connected with the corresponding Y output. I omitted the flashing LED and the extra output in this drawing.
Memory device
The memory device I put in the drawing is a 28C010. This is an EEPROM device of 128 KB. EEPROM stands for
Electrically Erasable Programmable Read Only Memory. It can be programmed byte for byte if enabled by hardware
(the WE and /WR signals). In most cases however the device acts as a ROM.
For the memory hungry among us: you can also connect other memory devices like a big EPROM or a more modern FLASH device. I want to go for the EEPROM or FLASH device to start with. EPROM's are nice but they cannot be altered in system.
The drawing on the left tells it all. The first 14 address lines A00 .. A13 are just taken from the address bus that happens to have a bus stop there. On the other side, the data bus is connected to the ROM device (D0 .. D7). Easy.
ROM address line A14 is not accessible from the system address bus. Therefore we made one ourselves in our MBC-F. The same goes for ROM address line A15. ROM address lines A16 and A17 would not even be available for us, if we wanted it, on a normal Z80 system. So, again, we made our own.
The Bxx address lines are the BankSwitch selectors. For this 'small' EEPROM, B19 is not necessary, but for a 29F020 Flash device (which has an upward compatible pinout) it is indispensible.
Power supply
Above is a circuit drawing for a simple yet efficient power supply for this entire project. I will give a short explanation for those of us who are new to the sybject.
On the left is the transformer, in this case one that transforms the 230 Volts from the mains to 7.5 Volts.
The transformer is a 16 VA type, meaning that the product of maximum Voltage and Current is 16. In our case,
this means 7.5 Volts at 2.1 A on the secondary side.
Since the transformer is one with two separate windings (the only kind I have in stock), we need to parallel
the both of them. Now we have single voltage and double current (one winding would be 1.1 A max).
The parallelled windings are connected to a full bridge rectifier which converts the AC from the powerline
into DC.
This DC voltage is yet a series of half sinus waves (all values above the horizontal axis) and we need a flat
line elevated around 10 Volts above the ground level. With the aid of the big electrolytical capacitor (10,000
uF) we achieve this. The small 100 nF capacitor is used to get rid of high frequency noise.
This flattened out voltage which is still far from good enough to feed into a microprocessor, is fed into a
7805 style voltage regulator. This is a three pin device that just does all we want. It converts the raw 9
Volts DC into a very constant +5 Volts. If the 7805 is shorted, it will limit the current to a safe value in
order not to selfdestruct.
If, on the other hand, the 7805 gets too hot, it will start to pulsate the output voltage, again in order not
to selfdestruct.
There are many kinds of 7805's depending on the letter between the '8' and the '0'. A 78S05 is capable of producing 5 Volts at 2 Ampere's. This wonderful chip will cost you around EUR 0,35.
Some math. We feed 9 Volts at 1.5 Ampere into the 78S05. We get out 5 Volts at 1.5 A, so we loose something.
In fact, we loose (9 - 5) * 1.5 = 6 Watts (under full load).
The package of the 78S05 is too small to get rid of all that heat. So we need to attach it to a so called
heatsink (picture on the left). This particular one has a thermal resistance of 3.5 Kelvin per Watt (K/W). If
we pump 6 Watts into this heatsink, it will rise it's temperature for 6 * 3.5 = 21 Kelvin. So at
roomtemperature, the heatsink will get a temperature of around 40 degrees centigrade.
This kind of heatsink will set you back around EUR 3. You might have an old Pentium processor heatsink in your
junkbox. You can use that as well, if there is a fan on top of the heatsink. Power the fan with the RAW 9
Volts (i.e. the power before the 78S05!).
The heat resistance of a heatsink is in most cases determined in still air. If you mount a fan on a 10 K/W
heatsink, the resistance may well drop to less than 2 K/W. So any Pentium heatsink with a fan on top will be
big enough to remove the excess power from the voltage regulator. Do not use a heatsink for processors above
the Pentium II. These heatsinks have thermal resistances of much less than 1 K/W so it's a bit of a pity to
use these monsters for such a small dissipation application.
You can mount the 78S05 on the heatsink by drilling a 2.5 mm hole in it and then screwing an M3 bolt right
into the heatsink material. It's aluminium, so no need to cut threads in it with a threadcuttertool. Apply
some thermal grease on the bottom of the 78S05 and screw it tight to the heatsink. Make sure the heatsink
doesn't touch any other metal part or you might get a short circuit.
This text is just an explanation to get started. If you are interested in this topic, please buy the book 'The art of electronics' by Horowitz and Hill.
Expansion connector
On the left, we see the kind of connector that is to be used for the various applications. A 34 pin boxed
header and the mating plug are used on the extender board. The interconnections between the buffer board and
the various I/O stations will be made with 40 pin boxed headers.
These boxed headers are available in several forms:
pin function pin function
--- ------------------ --- ------------------
1 +5 Volts 2 +5 Volts
3 CLK 4 /WR
5 /RD 6 /CS
7 Ground 8 Ground
9 Sound in 10 /RESET
11 A00 12 A01
13 I/O range 0 14 I/O range 1
15 I/O range 2 16 I/O range 3
17 I/O range 4 18 I/O range 5
19 I/O range 6 20 I/O range 7
21 I/O range 8 22 I/O range 9
23 I/O range 10 24 I/O range 11
25 I/O range 12 26 I/O range 13
27 I/O range 14 28 Ground
29 D0 30 D1
31 D2 32 D3
33 D4 34 D5
35 D6 36 D7
37 Clear 38 Bit 7 of HC259
39 Ground 40 Ground
Page created January 2006,
Page equipped with GoogleBuster technology