Computers Overview
Commodore PET
Sinclair ZX80
Sinclair ZX81
BBC Micro
Sinclair Spectrum
Memotech MTX
    About
    Library
    Manuals
    Options
    Photos
    Projects
      CFX
      Hardware Hacks
      Legacy (1980s)
      MAGROM
      MTXPlus+
      PAL Reader
      PC Keyboard I/F
          Design
          Firmware
      Programmers
      ReMemotech
      ReMemorizer
      SDX
      SFX
    Repairs
    Software
    Tools
    User Groups
    Video Wall
Memotech CP/M
Atari ST
PDAs
DEC 3000 AXP
OpenVMS
Raspberry Pi

 

 
 
 

The Memotech MTX Series

MTX PC Keyboard Interface

 

 

Propeller Logic Description  [Courtesy of Bill Brendling]

[Also available as Bill's Open Document format file]

 

The Propeller chip is a fast 32 bit micro-controller, designed for hardware interfacing, with eight largely independent cores, called "Cogs" in Propeller speak. It can be programmed in assembler, a high level language designed specifically for the chip called "Spin", or in a number of other languages such as C. In designing software for the Propeller it is typical for each cog to be dedicated to a specific task, such as controlling a piece of hardware, and for the cogs to cooperate to implement the entire functionality.

The keyboard interface uses a 6MHz crystal which is multiplied internally by 16, to give a 96MHz clock. This is slightly over-clocking (although fairly common), the Propeller was originally designed for a 5MHz crystal, and 80MHz internal clock. Each of the Propeller cogs can execute one assembler instruction in typically 4 internal clocks. At 96MHz clock, this gives the Propeller, when using all eight cores, the capability of executing 192 instructions per microsecond. For the keyboard interface, the cogs are used as follows:

Master Cog

The propeller always starts by executing code written in Spin on the first cog. This may be a major part of the software, or it may just be initialisation code. In this case it initialises some addresses in memory and then starts a cog for sending diagnostic messages to the programming interface. After outputting an initial diagnostic signature message, the master cog reads the position of the keyboard type jumper. What happens next depends upon the type of keyboard selected.

 

PS/2 Keyboard

If a PS/2 keyboard is selected, five additional cogs are started (giving seven used in total), running:

  • PS/2 interface
  • Key matrix mapping
  • MTX interface (2 cogs)
  • Key map reprogramming  

The function of these cogs are described below.

For the PS/2 keyboard, it would be possible for the master cog to stop at this point. However, for diagnostic purposes it continues to run, and sends key events and remap diagnostics to the diagnostics cog.

 

USB Keyboard

If a USB keyboard is selected, then six additional cogs are started (using all eight of the Propeller cogs), running:

  •  USB driver (2 cogs)
  • Key matrix mapping
  • MTX interface (2 cogs)
  • Key map reprogramming

The USB driver cogs only provide a low level interface to the keyboard. Routines on the master cog use this interface to enumerate and configure the keyboard. The master cog next flashes the keyboard LEDs in sequence (this helps to differentiate USB mode from PS/2 mode which flashes all three LEDs simultaneously).

Having completed keyboard initialisation, the master cog starts a loop, repeatedly polling the keyboard for key status. Any change (a key pressed or released) causes a key event code (7 bit USB key number, plus 8th bit to identify key press or release) to be placed in a first-in, first-out (FIFO) buffer for processing by the key matrix mapping cog. The key event code is also sent to the diagnostic output cog.

The master cog loop also checks the state of the keyboard lock bits (maintained by the mapping cog), and if these have changed, uses the USB driver to update the keyboard LEDs.

 

PS/2 Keyboard Driver

Much of the code was borrowed from the Propeller Object Exchange. When a key is pressed or released on a PS/2 keyboard, the keyboard sends 1-3 bytes of serial data over clock and data lines to the Propeller. The PS/2 driver cog receives this data and turns it into a one byte event code, with 7 bits identifying the key, and one bit to indicate key press or release. The key codes used are the same as those for USB keys. These event codes are queued in the key event FIFO.

This cog performs two other functions:

  • On startup of the cog, it first sends a reset command to the keyboard, so that it is in a known state. This causes the three keyboard LEDs to flash simultaneously. The auto-repeat rate on the PS/2 keyboard is then set to the slowest possible. I would have turned auto-repeat off if that was an option. Note, on the MTX the keys will still auto-repeat, but that is functionality built into the MTX ROM, not the PS/2 keyboard repeat.
  • This cog also checks the state of the keyboard lock bits (maintained by the mapping cog), and if these have changed, updates the keyboard LEDs.

 

USB Driver

The USB driver came from the Parallax forums (http://forums.parallax.com/discussion/121321).

The original version was produced by Scanlime (https://scanlime.org/2010/04/its-alive-bit-banging-full-speed-usb-host-for-the-propeller/). This version supported full speed (12MHz) USB devices only. This version requires the Propeller to be clocked at 96MHz.

The code was subsequently modified by Saucy Solition (https://github.com/SaucySoliton/propeller-usb-host) to also support low speed devices (1.5MHz), and to work with an 80MHz Propeller clock.

The version used for the keyboard interface has been modified slightly from the latter source:

  •  Operation with a 96MHz clock has been re-instated (with conditional compilation options).
  • The restriction on which propeller pins can be used for the USB interface has been relaxed, although in the end no advantage was taken of this.
  • A small amount of diagnostic code was cleaned up.
  • Despite these modifications, the author cannot claim anything like full understanding of the operation of this code.

As mentioned earlier, this code provides a low level interface, which in principle can support many types of USB device. Details of the keyboard implementation were copied from (http://forums.parallax.com/discussion/167592/propeller-ansi-vt-100-terminal-with-vga-and-usb-keyboard-support).

Without the efforts of the above referenced authors, who’s work was shamelessly borrowed, USB support would not have been possible.

 

Key Matrix Mapping Cog

This cog retrieves key events from the FIFO buffer, and updates an in-memory model of the MTX keyboard accordingly. The Propeller code implements eight different mappings between PC keyboard keys and MTX keys, depending upon the state of the shift keys, and scroll-lock and num-lock flags:

  • For many keys (such as the letter keys), the translation from PC to MTX key is the same for all eight mappings.
  • For some keys (such as the “9” key) the shifted character (open bracket for the “9” key) is on a different key on the MTX keyboard (MTX key “8” for open bracket). So a different translation is used depending upon whether or not shift is down.
  • A few symbols (such as equals) have different shift states on the PC and MTX keyboards. Because of the way the MTX scans the keyboard, it is not possible to modify the shift state for individual key presses. Therefore, Andy Key defined (originally for MEMU, see here) alternate keys to press to produce these symbols. By default the Propeller uses the same translations. However, if scroll-lock is selected, most of these symbols are translated to one of the three key matrix positions which don’t have a key on the MTX keyboard. The enhanced ROM in the MTX+ then translates these additional locations to the correct symbols. It is possible to load additional drivers on an unmodified MTX which will also translate these additional locations.
  • To maximise usability for games, Andy Key defined for MEMU a mapping for the numeric keypad keys which preserved physical layout. By default the Propeller follows this mapping. However, this results in the shifted keys producing digits other than those displayed on the PC keys. Turning on the num-lock bit, changes the mapping so that shifted keypad keys produces the digits as displayed. Because Andy’s mapping uses the keypad num-lock key for the MTX “Page”/”7” key, the PC “F12” key is used (by default) to toggle the num-lock bit.
  • Engaging both scroll-lock and num-lock combines the effect of the two previously described mappings.

It is possible to change any of the mappings, either permanently by changing the mapping tables in the Propeller ROM, or temporarily by re-programming from the MTX as described below.

The translated MTX key has to be remembered so that the correct MTX key can be released on receiving the corresponding key release event.

As well as mapping PC key events to the MTX keyboard matrix, this cog also maps keys to toggle the scroll-lock and num-lock bits, and to generate an MTX reset.

 

MTX Interface

The MTX Z80 writes the drive lines with one instruction, and reads the sense lines with the very next instruction. With a real keyboard the sense lines update instantly (or at least at the speed of light). The Propeller is significantly faster than the Z80 but updating the sense lines is still a challenge. Earlier versions of the keyboard interface assumed that only one drive line is active at any one time. This is always true for the MTX ROM, but may not be true for all games that implement their own keyboard decoding. The Propeller code used a binary search to identify the active drive line. This enabled the required keyboard row to be selected using only three tests.

Tony Brewer made a number of observations on MEMORUM:

  • That it was common, at least on the Spectrum to have multiple sense lines active at the same time, to enable rapid detection of a key press.
  • By unrolling the loop it was possible to process multiple sense lines more rapidly than I had appreciated.
  • By outputting logic ones for the active keys, rather than logic zeros, it was possible to use the Propeller hardware to combine results from multiple cogs. The Propeller needs output buffers anyway to go from 3.3v logic to 5v logic, and these buffers can be inverting to turn the active ones into active zeros that the MTX expects.

As a result of these comments, the MTX interface now uses two cogs, one of which samples the lower four drive lines and outputs the corresponding sense bits, the other cog sampling the upper four drive lines.

 

Key Map Reprogramming Cog

As described in the section on the “Key Matrix Mapping Cog”, the Propeller firmware has eight different key mappings built in to provide different compromises for the differences between PC and MTX key layouts. However others may have different preferences, for example Martin wanted the unshifted keypad to produce numbers. Therefore this cog provides the ability to temporarily update the mappings from the MTX. To do this the MTX has to first disable keyboard scanning, so that this is not sending any bytes to the keyboard drive port. It also has to ignore the values on the sense lines while reprogramming is in progress.

 To enable reprogramming, the MTX writes the following four bytes to the scan line port (port 0x05): 0xF0, 0x0F, 0x55, 0xAA. Once enabled, any byte sent to the scan line port with less than two zero bits will disable reprogramming. Typically 0xFF will be used to complete the programming sequence.

Once programming is enabled, a sequence of four bytes is used to update a map position:

Byte Bit Pattern Meaning
1 0101dddd dddd = 0 – 7:   MTX drive line number
             F:         Dead key            
             E:         Lock key
             D:        Reset key
2 0100ssss For an MTX key:
    ssss =   0 – 9:   MTX sense line number
For a dead key:
    ssss =   F (by convention, although actual value is ignored)
For a lock key:
    ssss =   1:         Num lock            
    ssss =   4:         Scroll lock
For a reset key:
    ssss =   1:         Left reset
    ssss =   2:         Right reset
    ssss =   3:         Combined reset (single key will reset MTX)
3 001nktxx n =       0:         Mapping with num-lock off
            1:         Mapping with num-lock on
k =       0:         Mapping with scroll-lock off
            1:         Mapping with scroll lock on
t =        0:         Mapping with shift key up
            1:         Mapping with shift key down
xx =     Top two bits of PC key code
4 00oxxxx xxxxx =           Bottom five bits of PC key code
This byte also writes the new value to the appropriate keyboard mapping table.

If updating multiple mappings, the first three bytes only have to be resent if they have changed from the previous value, This means that the amount of data to be sent can be reduced by:

  •  Updating multiple keys with the same drive line
  • Updating multiple keys with the same sense line
  • Updating keys in the same map, and the adjacent PC key codes (same top two bits)

The following table lists the key event codes used in the Propeller, and are needed for bytes 3 and 4 of the key map reprogramming. These are standard USB key codes, except for 0x64 to 0x6b which have been added to define the various shift keys.

Code Key Code Key
0x04 Keyboard a and A 0x38 Keyboard / and ?
0x05 Keyboard b and B 0x39 Keyboard Caps Lock
0x06 Keyboard c and C 0x3a Keyboard F1
0x07 Keyboard d and D 0x3b Keyboard F2
0x08 Keyboard e and E 0x3c Keyboard F3
0x09 Keyboard f and F 0x3d Keyboard F4
0x0a Keyboard g and G 0x3e Keyboard F5
0x0b Keyboard h and H 0x3f Keyboard F6
0x0c Keyboard i and I 0x40 Keyboard F7
0x0d Keyboard j and J 0x41 Keyboard F8
0x0e Keyboard k and K 0x42 Keyboard F9
0x0f Keyboard l and L 0x43 Keyboard F10
0x10 Keyboard m and M 0x44 Keyboard F11
0x11 Keyboard n and N 0x45 Keyboard F12
0x12 Keyboard o and O 0x46 Keyboard Print Screen
0x13 Keyboard p and P 0x47 Keyboard Scroll Lock
0x14 Keyboard q and Q 0x48 Keyboard Pause
0x15 Keyboard r and R 0x49 Keyboard Insert
0x16 Keyboard s and S 0x4a Keyboard Home
0x17 Keyboard t and T 0x4b Keyboard Page Up
0x18 Keyboard u and U 0x4c Keyboard Delete Forward
0x19 Keyboard v and V 0x4d Keyboard End
0x1a Keyboard w and W 0x4e Keyboard Page Down
0x1b Keyboard x and X 0x4f Keyboard Right Arrow
0x1c Keyboard y and Y 0x50 Keyboard Left Arrow
0x1d Keyboard z and Z 0x51 Keyboard Down Arrow
0x1e Keyboard 1 and ! 0x52 Keyboard Up Arrow
0x1f Keyboard 2 and " 0x53 Keyboard Num Lock and Clear
0x20 Keyboard 3 and £ 0x54 Keypad /
0x21 Keyboard 4 and $ 0x55 Keypad *
0x22 Keyboard 5 and % 0x56 Keypad -
0x23 Keyboard 6 and ^ 0x57 Keypad +
0x24 Keyboard 7 and & 0x58 Keypad Enter
0x25 Keyboard 8 and * 0x59 Keypad 1 and End
0x26 Keyboard 9 and ( 0x5a Keypad 2 and Down Arrow
0x27 Keyboard 0 and ) 0x5b Keypad 3 and Page Down
0x28 Keyboard Return (Enter) 0x5c Keypad 4 and Left Arrow
0x29 Keyboard Escape 0x5d Keypad 5
0x2a Keyboard Delete (Backspace) 0x5e Keypad 6 and Right Arrow
0x2b Keyboard Tab 0x5f Keypad 7 and Home
0x2c Keyboard Spacebar 0x60 Keypad 8 and Up Arrow
0x2d Keyboard - and _ 0x61 Keypad 9 and Page Up
0x2e Keyboard = and + 0x62 Keypad 0 and Insert
0x2f Keyboard [ and { 0x63 Keypad . and Delete
0x30 Keyboard ] and } 0x64 Left Control
0x31 Keyboard \ and | 0x65 Left Shift
0x32 Keyboard # and ~ 0x66 Left Alt
0x33 Keyboard ; and : 0x67 Left Meta
0x34 Keyboard ' and " 0x68 Right Control
0x35 Keyboard ` and ~ 0x69 Right Shift
0x36 Keyboard , and < 0x6a Right Alt
0x37 Keyboard . and > 0x6b Right Meta

 

Diagnostic Cog

This cog outputs diagnostic messages in serial format at 115,200 baud, 8 bits, no parity, 1 stop bit. The output is 3.3v TTL on pin 39 (I/O bit 30) of the propeller, which is connected to the programming connector.

The output consists of:

  • Firmware identification string, including version number.
  • Keyboard type message (USB or PS/2).
  • Cog initiation messages.
  • USB configuration messages (if appropriate)
  • Two digit key event codes, as per table above, with high bit set for key release.
  • Eight digit diagnostic codes from the remap cog.

This cog a standard Parallax Propeller object, accessed from driver routines running on the main code. It is also capable of receiving incoming serial characters from the programming connector, although this feature is not currently used.

 

Firmware Distribution

Any upgrades to the Propeller application program will be available below. If there are any updates to the hardware, a new PCB will probably be required, firmware updates will likely be specific to the hardware version that they are designed to run on.

The Source file archive contains the Parallax Spin language source code, the source files must be compiled into a binary file that is loaded from the EEPROM when the Propeller is powered on or reset. The Propeller Tool includes software for programming in Spin and Assembly but the easiest method of compiling the source files for the MTX PCB application is to use the Open Source compiler, OpenSpin. It is a command line tool, with pre-built binaries for Windows, Linux and Raspberry PI available from Github.

Parallax Propeller 
Version By Zip PCB Description
         
180610 WB 1.0 Modified key mapping, added dynamic remapping
180504 WB 1.0 Optimisation of drive line decoding (suggested by Tony Brewer)
(Chips U3 & U4 must be inverting buffers, e.g., 7406, 7416)
(All future release will be written for inverting buffers)
180429 WB 1.0 Initial release supporting USB and PS/2 keyboards
(Chips U3 & U4 must be non-inverting buffers, e.g. 7407, 7417)
         
         
MTX "BASIC" ROM (ROM 'B') (Optional)
1.0 MA 1.0 Enables "Scroll Lock" mode without CP/M or SDX  
         

Software

The optional programs below allow MTX users with disk based systems to utilise the "Scroll Lock" mode without needing to modify the MTX ROMs.

Ver.  Host  Zip PCB Description
1.0 CP/M 1.0 Initial release - enables "Scroll Lock" for CP/M (.com)
1.0 SDX 1.0 Initial release - enables "Scroll Lock" for non-CP/M SDX (.run)
1.0 Tape 1.0 Initial release - enables "Scroll Lock" for "tape" users CP/M (.wav)
(Currently not tested on real hardware)
         

 

 

 

 

mailto: Webmaster

 Terms & Conditions