This is a long technical post. There’s probably only one reason to read it: you have a Lexitron with a broken keyboard. I’m not going to polish it much, but I leave it here just for you!
I spent a lot of time creating a teensy replacement for the microcontroller in the keyboard. One of the great challenges was to work out the key codes sent from the keyboard to the 8085. This was very time-consuming and there were some that I never really cracked.
With the arrival of working keyboards, I could just swap out the original for one of the working units. Buuut the teensy solution actually provides a mechanism to move data from a modern PC to the Lexitron and that’s handy. Also, I guess I’d like to just close the loop!
I can now sniff the communication between the 8085 and the keyboard microcontroller. Because the keyboard appears to be just another device on the 8085 bus the data is transmitted as a parallel byte. This would be easy to sniff with a logic analyser, but not so easy with an oscilloscope. I thought my Analogue Discovery 2 might be sufficient for this task.


Two Different Keyboard Types
One of the VT202 units uses the same Cortron Keyboard as the VT1303. The other uses a Digitran keyboard which looks quite different but seems to be entirely compatible with the Cortron. The Digitran sound is not as loud.
Revisit Operation
Keyboard Pinout
Pin | Name | Function |
1 | +5V | |
2 | +5V | |
3 | GND | |
4 | GND | |
5 | NC | |
6 | GND | |
7 | Strobe_L | This line indicates activity on the keyboard. It is asserted for 5us when a key is pressed and for 10us when a key is released. The strobe is not asserted when a front panel switch is changed. It is not asserted when the shift key is pressed. It is asserted for spec shift. |
8 | D5 | |
9 | D6 | |
10 | GND | |
11 | D7 | |
12 | D4 | |
13 | Kbd_Read_L | This line causes the keyboard to put data on to the 8085 bus. The read occurs about 100us after the strobe is asserted. A0 is low. Scan code? A second read occurs about 8us after the first. A0 is high. Switch state? This strobe is asserted a couple of times every 10ms (approx.) |
14 | Screen On | This also appears in the status register. |
15 | A0 | This selects the data that is read by the 8085 – either the keycode or the status of the front panel switches. |
16 | Kbd_Write_L | This strobe is asserted about 5us after Read is asserted in response to the Strobe. This strobe is asserted every 10ms (approx.) |
17 | Reset? | |
18 | GND | |
19 | D3 | |
20 | D2 | |
21 | D1 | |
22 | D0 | |
23 | -15V | |
24 | -15V | |
25 | +15V | |
26 | +15V |
Character Register
Bits 6:0 = Character number
Bit 7 = Shift
Status Register:
Bits 1:0 = Print Spacing
Bit 2 = Pitch
Bit 3 = Screen Spacing
Bit 4 = Not used (input pulled up)
Bit 5 = Key pressed
Bit 6 = Screen On/Off
Bit 7 = Autorepeat (although it doesn’t seem to be used)
Command Register:
Bit 0 = Key click
Bit 1 = Type Through LED
Bit 2 = Select LED
Bit 3 = Continuous Typing LED
Bit 4 = Write LED state (Bits 1, 2 & 3)
Bit 5 = Acknowledge
Bit 6 = Bell (Not supressed by volume control)? Under CP/M this is sent when Select is pressed. Select causes an alarm chime (not volume controlled).
Bit 7 = Unknown
Adjustable volume applies to key strokes. Alarms have a fixed volume.
Word Processing Program Behaviour
Periodic
Once every 10ms or so the program reads the status register and writes the Command Register.
Keystroke
When a key is hit the keyboard alerts the uP by asserting Strobe_L for 5us. The program responds by reading the character, reading the status register, and then writing 32 to the Command Register. This seems to be an acknowledgement. If there is a LED change or sound then that will be sent a few milliseconds later.
The key release is also acknowledged with a command write which can update the LED state and sound a bell but I think does neither.
The unit only autorepeats on space, backspace, dash, underline, and full stop. This auto repeat is convoluted. It involves resending a specific character after the wait time has elapsed. This triggers the software to autorepeat. It looks like the bit 6 of the status word is set at the same time. This is set by an output from the microcontroller (Pin 29). Although the original keyboard does this it does no appear necessary.
Character | Original Output | Autorepeat Output |
Space | 80 | 112 |
Dash | 103 | 119 |
Underline | 231 | 247 |
Full stop | 26 | 122 |
Backspace | 110 | 126 |
I can’t see any obvious pattern in these numbers. They just are.
CP/M Behaviour
Periodic
Once every 10ms or so the program reads the status register.
Keystroke
When a key is hit the keyboard alerts the uP by asserting Strobe_L for 5us. The program responds by reading the status register, reading the character, and then writing the Command Register – it can acknowledge, set LEDs, or make a sound.
The key release is also acknowledged but the LED data is not repeated. There is no periodic write The key release is also acknowledged with a command write which can update the LED state and sound a bell but I think does neither.
CP/M autorepeats on most keys but not Spec Shift or Sel. It initiates a beep on each auto repeated character.
CP/M politely ignores the autorepeat shenanigans that the keyboard does for the word processing program.
In CP/M lots of keys are defined as function keys that can be changed using the config program. The config can also control auto repeat and key click.
Select is a caps lock key.
My Current Keyboard Code
The current routine that I have for sending a character to the 8085 sets up the character and then takes then asserts the strobe (indirectly) for 1ms. It then sets up another character (usually zero).
The real thing asserts the strobe for 5 or 10us. Both the key register and the status register are read within about 100us of the strobe. The Command Register is then written. This may be the trigger to clear the key but maybe not. I previously concluded that the key needed to be nulled but I’m not sure why it does.
My implementation autorepeats on all keys except “mode” keys like Spec Shift and Margin Set. The actual unit does not autorepeat, although the software does under some circumstances.
I’ve treated Spec Shift and Margin Set as special cases because they are used in combination with other keys. Certainly, autorepeat doesn’t apply. CP/M treats Margin Set as a normal function key.
This means that the effect of these keys is application specific. Eg in CP/M the Spec Shift key is used to create control keys eg Ctrl-C to do a soft boot. In the word processing program it has no effect on the letter c. Spec Shift does not beep.
Shift really is different. No key code is sent with just the shift key, and the character that is sent is modified if a shift key is pressed. When shift is pressed the most significant bit is set. This applies to all keys including Spec Shift and Margin Set.
The various reads and writes change a little with CP/M. CP/M still reads the front panel switches but I have no idea what it does with the state. Similarly, the LEDs have no apparent function.
Under CP/M Select behaves like a caps lock. The shift is done in software.
Observations


Key hit

Close up of subsequent reads and write.

With the autorepeat:

The regular status read (word processor software):

Revised Keyboard Code
The keyboard code has been substantially reworked based on the observations that were possible using the logic analyser function of the Analogue Discovery 2.
- Autorepeat has been removed except to the extent required by the word processing program.
- Each key press and release is transferred to the 8085.
- The timings have been changed to better match the real keyboard.
- Only one key is checked and processed on each pass of the main loop so that commands are less likely to be missed.
- All sounds are generated only at the request of the 8085. There are no automatically generated sounds.
- An additional signal was discovered that is set when a command is written and is cleared when the command has been read.
- A few missing key codes were found.
Things like Spec Shift, Set Margin, and Select now work as advertised (as far as I can tell).
The code works on the VT1303 and the VT202. It works with the word processing programs and with both the VT1303 CP/M and the VT202 CP/M.
Mapping
The transmitted codes can be read straight off the data lines (see waveform pics above).


Circuitry
https://www.pjrc.com/store/teensypp.html
The mapping from the microcontroller to the teensy are shown in this table:
uC Pin Nr | uC Pin Name | Teensy Pin Nr | Signal Name | Comment |
1 | T0 | |||
2 | XTAL1 | |||
3 | XTAL2 | |||
4 | RESET_L | |||
5 | SS | |||
6 | INT_L | D4 | uC_New_Command | |
7 | EA | |||
8 | RD_L | |||
9 | PSEN_L | |||
10 | WR_L | |||
11 | ALE | |||
12 | DB0 | C0 | DB0 | Data bus for the keyboard. |
13 | DB1 | C1 | DB1 | |
14 | DB2 | C2 | DB2 | |
15 | DB3 | C3 | DB3 | |
16 | DB4 | C4 | DB4 | |
17 | DB5 | C5 | DB5 | |
18 | DB6 | C6 | DB6 | |
19 | DB7 | C7 | DB7 | |
20 | VSS | GND | ||
21 | P20 | F6 | LED_TypeThru | |
22 | P21 | F5 | LED_Unused | |
23 | P22 | F4 | LED_Select | |
24 | P23 | |||
25 | PROG | |||
26 | VDD | |||
27 | P10 | B0 | Column0 | Keyboard Column |
28 | P11 | B1 | Column1 | |
29 | P12 | B2 | Column2 | Also drives a status register input to indicate that the current key has been pressed. |
30 | P13 | B3 | Column3 | Also indicates when an autorepeat could be started. |
31 | P14 | B4 | Row0 | Keyboard Row |
32 | P15 | B5 | Row1 | |
33 | P16 | B6 | Row2 | |
34 | P17 | B7 | Pulser | This creates an opportunity for a pulse at E7 |
35 | P24 | F3 | LED_ContType | |
36 | P25 | D3 | uC_Rd_L | Enables command register so it can be read via Port C. |
37 | P26 | D2 | uC_GotOne_Loud_L | Loud Beep for Alarms |
38 | P27 | D1 | uC_GotOne_Adj_L | Adjustable beep for key presses |
39 | T1 | E7 | uC_Sense | Senses when a key is down |
40 | VCC | +5V |

