There is an odd fault you occasionally see on the ZX Spectrum where all of the keys work, but some key combinations do not. The usual one to test is SHIFT + A, which should generate the STOP keyword, but that does not register. A on it's own works. SHIFT + most of things work, just not SHIFT + A and a few others.
In some case, it can be down to the Z80, but it is often the ULA. Changing either can fix the issue, but that's not ideal. There is a fix, which usually works, which involved changing the pullup resistor on the column from 10K down to 6K8 or 4K7.
What is going on here?
This is one of those cases where the digital electronics are affected by their analogue properties. The basic circuit for the keyboard can be seen by looking at a single key:
When the key switch is not pressed, the column input is pulled high via the 10K resistor and reads as a 1. During scanning, the address line is used to select the row. When scanning the other rows, A10 will be high, so if the switch is pressed, the diode will prevent any current flowing and the column will read a 1 again. If this switch is pressed and this row is being scanning, A10 will be low, the diode will conduct and pull the column input low and a 0 will be read.
See a previous post on the whole range of 5x8 keyboards used by Sinclair and others in the 1980s
It is difficult to visualise what is going on inside a ULA, so to better demonstrate this, I am going to look at the ZX80 / Jupiter Ace implementation. These use discrete logic chip, the input being read by a 365/367 input buffer. With that, I can show both the input value being read and the logic output that is generated.
On these traces, blue is the trigger, the pulse which causes the keyboard input to be read. Green is the keyboard input, and yellow is the logic output. You can ignore the yellow trace either side of the trigger as that is ROM read cycles.
And that works fine most of the time. You can see the switch is pressed and when sampled, the output is interpreted as a logic 0.
When there are no key pressed, it is likewise clear that it is a logic 1. (again ignore the yellow trace either side, I just picked one where the ROM reads were low to show the change)
It is less clear cut when the key is not pressed, but another key in the same row is pressed. Rather than being pulled straight back to 5V, the input takes a while to recover. The input capacitance of the gate comes into play. It is usually only 5-10pF, but with a 10K resistor, that is a time constant in the 10s to 100s of nS, which can be important when the sample pulse is less than 800nS.
Even more so when two other keys in the same column are pressed. The trace only just gets past half way back to 5V before the scan is complete.
The above traces are using 74LS logic, where the logic threshold for a 1 is over 2.0V.
With 74HC logic, this is raised to 3.3V, and you can see the interpretation is very different.
The input signal only passes the logic threshold to be read as a logic 1 right at the end of the read cycle.
And with two switches on the same column pressed, it doesn't even register at all.
I think what is happening here is not that it is failing to read the SHIFT + A keys as being pressed, but that it reading all the keys in the row as being pressed. When they all appear to be pressed, it aborts the read.
During the development of the Minstrel 4D, the first prototype suffered from this problem. Here it was SHIFT + 1 that was not working. This was a little odd, since the schematic was the same as the Ace and the Minstrel 4th. Neither of which suffered from this issue. I guess it's more of the analogue influence, and the extra length of the traces in the keyboard matrix are enough to cross the line.
Reducing the pullup resistor value
There are a few ways to deal with this. In the Spectrum world, the solution seems to be putting a 10K resistor in parallel to drop the resistance to about 5K, or a 22K in parallel to bring it or about 6K8. Or just swapping out the resistor for a 4K7 or 6K8 resistor. Either way, reduce the value of the pullup resistor to reduce the RC time constant and speed up the recovery.
I hit this issue in the design of the Minstrel 3. The ZX80 design actually used 47K pullup resistors and 74LS gates, and that had worked fine on the Minstrel 2. For the Minstrel 3, I had moved to 74HC logic and found that some SHIFT + key combinations did not work. Reducing the values to 10K (as used on the Spectrum) resolved the problem in that case. (the first run of Minstrel 3 PCBs have the pullups marked 47K, and are probably worth at least £1M each now)
Use 74LS logic
This is a simple option, switch the gates doing the reading over to 74LS logic with their lower logic threshold. 74HCT logic may also be an option, but 74LS has the extra benefit that it does reduce bus contention when used with an external keyboard - see the previous post on issues with those:
An alternative is to drive the row lines via a buffer, rather than using the address lines directly. This is used on the external keyboards I reverse engineered in the above post. I imagine the effect is multiplied due to the longer cables.
This also adds the option is disabling the drive to the rows when they are not being scanned. That would probably help EMC (if that is important to you).
It would be neat if the buffer and 8 diodes could be replaced with a single octal open drain buffer. I think the 74x641 will do the job. This is an open drain bus transceiver, it is only needed to work on one direction, but should in theory do the job.
The high numbered 74 series is usually where all the esoteric stuff lives, so it's not a great part to use when supply issues are commonplace, but I will see if I can get some to give it a go.(I couldn't. I didn't.)
I did consider making a suitable buffer using a 16V8 GAL, but adding programmed parts to a kit is never a popular move. Two 74LS07 chips would be another alternative.
The Harlequin ZX Spectrum clone went for a row of PNP transistors. That does the job quite neatly if you can find the 'E line' packaged versions that fit in line.
They line up quite neatly in that package.
For the Minstrel 4D, the best option was to change the buffer IC from a 74H3265 to a 74LS365. That solved the SHIFT+1 combination not responding, and also gave additional protection against RC2014 bus cards that write to the same address.
The Minstrel 4D kits are shipping now, you can order one from The Future Was 8 bit
More info in a previous post:
Sell My Retro
PCBs for the Minstrel 2, 3 and 4th, as well as Mini PET and other projects, and keyboards for all the above, can be found at my Sell My Retro store:
You can support me via Patreon, and get access to advance previews of posts like this, and behind the scenes updates. These are often in more detail than I can fit in here. This also includes access to my Patreon only Discord server for even more regular updates.