All the ZX-Keyboard expansions available have at least two disadvantages: the connection with a flatcable (of limited possible length) and the trouble of having to type in long sequences of frequently used commands like, for example, when you quickly want to display the value of RAMTOP. It would be nice to have an interface: connect it to the back of a ZX, buy an AT keyboard and you're done. Shortly before finishing this AT keyboard project, Peter Liebert-Adelt pointed out to me that in the mean time the ZX fans in the USA weren't sleeping either. Over there, they built almost the same thing using TTL ICs. The circuit used is very interesting, however it needs a XT Keyboard, which is not easy to get these days. Also, I recently discovered Wilf Rigter's solution using a PIC processor.

The ZX81 AT-Keyboard Interface works with a normal PC-AT keyboard. When I examined two different AT keyboards I noticed that one of these contained a 80C49 and a few small ICs, while the other one had a custom IC and almost no other parts. However, the connection to the keyboard is always the same: a 4-wire cable that is used for supplying power and connecting a clock and data line.

When a key is pressed, the clock and data lines change from high signals to a pulse sequence which is always 12 bits long. In this the main difference lies with a XT keyboard: it uses 8 bits instead. The more detailed theory of data transfer involved has never really interested me, it's not important that it should be 11 bits and one stopbit. The serial data is now read with a microcontroller and decoded. Every normal key is encoded in a 12 bit code, while some special keys result in multiple codes of 12 bits each. When a key is released the keyboard always sends two codes: one code for "key released" and a second code corresponding with the key that was released, with a 2ms pause between these two codes. For example, for the shift key it must be carefully evaluated: while shift is pressed down and several keys are pressed after each other while holding shift down, the keyboard starts with sending only one "shift" code and this must be remembered until the code "Shift key released" is sent.

The interface in turn receives the serial data from the keyboard, translates it into a 7 bit code and a single bit for "shift" (more than 64 keys aren't really needed in our case) and relays the key to the ZX81 by means of an EPROM (IC3), which contains the ZX-matrix.

Overview of the Keycodes

This matrix-EPROM is quite a complicated matter, when keeping in mind the ZX81 matrix key scanning procedure. (eg. described in the the book "kleinen Hardwarebuch" by A. Deckers) For scanning the ZX-keyboard, one of the 8 address lines A8-A15 is pulled low and the I/O port $FE is read, where only D0 ... D4 are evaluated. That makes it possible to locate each of the 40 seperate ZX81 keys. These 8 seperate address lines, of which only one is active at a time, can be encoded into 3 lines. In this process, the LS240 IC has two tasks: to buffer signals in order to reduce bus load on the Z80 and to invert the logic signals. Without the LS240, germanium diodes would be needed and the load on the address lines would also be relatively high. A LS148 would have been ideal(would save the diodes and an LS240), but I didn't have one of those available at the time. So finally we have 3+8 inputs which result in 5 outputs that need to be encoded in a specific manner.
So how does the entire circuit work? Let's assume that the "Q" key is pressed. This means that the microcontroller outputs "10". In the ZX81 keyboard matrix the "Q" connects A10 with D0. The ZX81 knows that when it reads D0=low while A10=low, the "Q" key is pressed. So the output to the ZX81 must be $FE. (D0=low) The matrix-EPROM can be viewed as devided into 8 blocks of 256 bytes each. One block represents a matrix address line of the ZX81. When A10=low, the 3rd block -counted from A8- is valid. So the EPROM inputs are: A0...A7="10", A8=A9=high, A10=low. At this address (778) the matrix EPROM should contain the value $FE.When shift is pressed, bit 7 of the microcontroller (A7 of the matrix EPROM) will be high which results in a +128 shift of the matrix EPROM addresses. In order to make the ZX81 also register the shift, the upper 128 bytes of the A8 EPROM block must always have bit0=low. (address 128 through 255) A key that is scanned with A8 but also has shift pressed is encoded by setting two bits low.

With this Matrix-EPROM any key of the AT keyboard can be transformed. For example, the code for the "Del" key can be relayed to the ZX81 as "Shift+0". The same applies to the keys ,;.:+-*/ etc. This way, these keys can be used directly, without needing to press "shift". Every AT keyboards has an extra numerical key block - these keys can also be transformed resulting in much easier input of numbers.

For the translation of the 12 bit AT keyboard codes into the 7 eprom bits, a second code table is used in the program of the microcontroller. This allows us to make smart use of a feature of the 8048: banking. Using the keys F11 and F12, these banks can be switched and the keyboard layout can be completely altered. The program is the same for all banks, only the code table area is different. Most frequently, an alternative cursor key layout is needed because many ZX81 programs evaluate the 5, 6, 7, 8 cursor keys differently. Some require shift to be pressed first and some work without shift.

Because in our case there is an 'intelligent being' between the AT keyboard and the ZX, we can even attribute entire key sequences to a single AT key: the microcontroller can simply process a "keyboard macro". That's why I have attributed the annoying keyboard commands that I most frequently need to the function keys, which includes the nerve-killing PRINT PEEK 16389+ ... This matter is solved with a relatively simple straight-forward software solution, but it works. Programming fans can also consider for themselves if it would be possible to store such a keyboard macro in the microcontroller's RAM which could result in user-programmable function keys. It's also possible to use a 2732 as the matrix EPROM. In that case, a switch would allow to choose from two different keyboard layouts, (eg. Spectrum or Power3000) in case the F11 and F12 options are already used.

Finally a few things needed for building this project: (explanations in certain documents are in German)
Documented Listing (scans) 245 kB
Binary file of the program-EPROM IC2 2 kB
Binary file of the matrix-EPROM IC3 2 kB
Sourcecode 13 kB
Circuit Diagram 52 kB
Picture of the finished board 31 kB

07/01 Kai Fischer