One of the advantages of building a ZX81 from a kit was that you got a schematic with the manual, and you gained some insight into how the machine worked as you put it together.
It was evident, for example, that the computer was missing some memory from 8K to 16K — an area transparent to the BASIC operating system. An expansion to a 16K ROM was probably intended at some point. In any event, the gap has been filled, and overfilled, by the many manufacturers of peripherals for the computer.
This article, possibly one of a series if the response is favorable, describes a very simple way to page or select from several devices using the 8K-16K region. This method is not sophisticated and serves as an easy introduction to I/O control.
The apparent simplicity of the ZX81 design conceals a complicated operating system. Some features of this system make I/O less useful than it could be in any other “normal” Z80 system. For example, the use of NMI (nonmaskable interrupt) in the display routine precludes its use in I/O control. Similarly, the use of I/O addresses by the system is extravagant. Fortunately there are some addresses left and if necessary indirect addressing is possible. (This means that, although the lower half of the address bus is normally used to decode one of 256 I/O ports, the higher half of the address bus can also be used.) For example, OUT C,r places the contents of [register] B on A8-A15, the contents of C on A0-A7, and the contents of register r on the data bus D0-D7.
The addresses used by the system can be found by searching the ROM for IN and OUT instructions, I/O addresses are used in keyboard servicing, TV display routines, printer input and output latching, and in cassette LOADing and SAVEing
Addresses monopolized by the system are:
- Any address with A0 low, e.g. FE
- Any address with Al low, e.g. FD
- Any address with A2 low, e.g. FB and the address FF
The final hindrance to I/O operation is the absence in the ZX/TS1000 BASIC of any IN or OUT command. Machine language subroutines must be used.
You may well wonder then, why not memory map the I/O and avoid all these problems. Then, for example, the BASIC commands PEEK and POKE can be used to service the port. Well of course you can – particularly if you haven’t already got a full complement of memory (64K). The same kind of circuit can be constructed.
HARDWARE PROJECTS
Building hardware projects can become addictive — it is very satisfying to see something you build actually work, and in many respects the ZX/TS makes it easy — most of the Z80 CPU signals are available at the edge connector.
This project is based on a RADIO-SHACK 276-161 experimenter’s IC board ($2.95). With a wire-wrap edge connector and a small pc extender board, this makes an economical and reusable plug-in board for the ZX81/TS1000. Wire-wrap is recommended — it’s easy to undo and is often more reliable than soldering. The wire-wrap sockets you accumulate can be used over and over again with care. Although wire-wrap can be done with a manual step-by-step tool, something like a “Just-Wrap” daisy-chaining wire wrap tool by OK eases the burden considerably.
With such a tool, a project like the one described can be put together in less than an hour. The socket-wrap ID’s by OK are useful if you’re not used to looking at IC’s from underneath. The Radio Shack experimenter’s board stands up behind the ZX81 as shown in Figure 1. With the connector to the computer mounted flush to the board, and soldered or glued in place, there is plenty of room behind the board for the 3-level wire-wrap sockets. Be sure not to mount any components or sockets below the 16th row of holes from the bottom (the 0-0 line). Solder the pc edge connector in place between the wire-wrap pins of the socket after you have made connections to the pins.
To complete the prototype board, solder a 10 uF, tantalum capacitor between the +5V power supply pin and ground. Discrete components like LEDs, resistors, capacitors, etc. can be mounted on their own wire-wrap pins or on DIP headers and plugged into sockets.
THE CIRCUIT
The schematic for the paging control is shown in Figure 2. Note that no data lines are used — the device select signals are derived from decoding the address lines alone. A0, Al, A2 are high and A7 low to avoid system conflicts. These lines, with the IORQ and the WR signals are used to generate a positive-going pulse which enables the 74LS175 latch. The four remaining address lines are used as inputs to the 74LS42 This decoder ensures that only one device is selected at a time. If you are confident enough and only have four devices from which to select, then the LS42 decoder can be omitted — connect the address lines A3-A6 directly to the LS175 latch.
The choice of a 74LS175 latch allows an automatic reset on power-up. The outputs from the latch are arranged so that the default, or reset, condition is that for which only device number 1 is enabled. Upon power-up or reset you should observe LED1 on and all others off. When you test the board do so first without any peripherals attached.
The routine to select a particular device is simple enough;
211 OUT
N address (7, 15, 23, 0r 31)
201 RETurn
The routine can be placed in a REM statement. For example, the first line in a program: 1 REM PEEK # TAN (# = space).
The device can be selected by: POKE 16515, (7, 15, 23, or 31). And the routine executed by: RAND USR 16514
It remains, of course, to incorporate a device select signal (active low) in the selection of a particular peripheral device. Most peripherals are memory-mapped and are enabled by the MREQ control signal with some combination of RD or WR. If this is the case then the device select signal and MREQ can be gated together through a 74LS32 OR gate.