Subject: [E3-hacking] E2 keyboard/PS2

From: Matt Evans <[email-masked]>
Date: Sun, 8 Jan 2006 13:48:49 +0000

Hi all,

Have been tinkering with the E2 again and have got the keyboard going.

I think this is documented somewhere else but just for clarity the  
pinout, looking into the socket on the board, is:
_____------_____
|  1  2  3  4  |
+--------------+

1 (wire red)	PS2CLK
2 (wire green)	PS2DATA
3 (wire black)	Ground
4 (wire blue)	+5V power (switched!)

It's a PS2-like port - not quite a proper PS2 port in that the PS2CLK  
is an input only ;(  This precludes the E2 sending data to the PS2  
device. (Which is annoying since I want to drive a synaptics trackpad  
from it, and that requires outputting some configuration.)  This is  
fine for the supplied keyboard which requires no initialisation.

So the connections are:

PS2CLK drives pin 185 (input) on the LH79531, INTR4.  This is  
inverted (i.e. the usual PS2 idle state (high) appears 0).  The  
PS2CLK input floats low - which is weird - and the keyboard appears  
to have an internal pullup.  If you want to attach a different PS2  
device be sure you pull this pin high with, say, a 10K resistor.

PS2DATA drives pin 12 (input) on the LH79531, PIO[70].  This is also  
inverted.
The PS2DATA line is also drivable (as an 'output') by setting pin 203  
high.  (203 high = pull down PS2DATA, low = no pull-down.)

The power is switched on by an output from the CPLD, pin 23.  This is  
accessible using bit 0 of register 0 of the CPLD - writing '1' to  
'0xa0002000' will power up the keyboard.

I'm not sure why PS2DATA can be pulled low yet PS2CLK cannot - I  
don't think any sensible output (in PS2 terms) is achievable without  
CLK being driven.  I'll probably add my own pulldown at some point to  
get proper PS2 behaviour for my trackpad...

It's probably easier to illustrate this with some code, a routine to  
initialise what's required and a routine to read the data:

setupPS2Port:
         // 1. Set pin in/outness
         //    a: 203 output, set to 0 please (don't pull down DATA)  
PIO[2] (Fn 2)
         ldr    r0, =PIOA
         ldr    r1, [r0, #0x10]
         orr    r1, r1, #4
         str    r1, [r0, #0x10]
         ldr    r1, [r0, #0x14]
         bic    r1, r1, #4
         str    r1, [r0, #0x14]  // mux2:mux1 = 01 = fn2
         // 203 is PIO[2] now
         // Make sure output low:
         mov    r1, #4
         str    r1, [r0, #0x0c]  // Clear register
         ldr    r1, [r0, #0x04]  // control reg
         orr    r1, r1, #4
         str    r1, [r0, #0x04]  // Set as output

         //    b: 12 input (DATA) PIO[70] (Fn 2)
         ldr    r0, =PIOE
         ldr    r1, [r0, #0x10]
         orr    r1, r1, #4       // 12 = bit 2
         str    r1, [r0, #0x10]  // mux1 = 01 = fn2
         // 12 is PIO[70] now
         // Make sure output low:
         ldr    r1, [r0, #0x04]  // control reg
         bic    r1, r1, #4
         str    r1, [r0, #0x04]  // Set as input

         //    c: 185 input (CLK) INTR[4] ooh
         ldr    r0, =PIOF
         ldr    r1, [r0, #0x10]
         bic    r1, r1, #4       // 185 = bit 2
         str    r1, [r0, #0x10]
         ldr    r1, [r0, #0x14]
         orr    r1, r1, #4
         str    r1, [r0, #0x14]  // mux2:mux1 = 10 = fn3

         // intr type config:
         ldr    r0, =INTC
         mov    r1, #0
         str    r1, [r0, #0x200]
         mov    r1, #1<<4
         str    r1, [r0, #0x204] // INTR4 is high level triggered  
(for now)

         // Clear INTR4:
         mov    r1, #1<<4
         str    r1, [r0, #0x208]

         // 2. Power up the keyboard
         ldr    r0, =0xa0002000
         mov    r1, #1
         strb   r1, [r0, #1]

         // data input is inverted
         // clk input also inverted; but also it seems to need a pullup!
	mov    pc, r14

	// A dumb routine to read a byte from the PS2 port.  This isn't  
especially optimal, and obviously
	// a better scheme would be to use the CLK input as an IRQ input.
ps2_read:
         stmfd  r13!, {r1-r12, r14}
         ldr    r12, =PIOE
         ldr    r11, =INTC

         mov    r0, #0
         mov    r2, #11
         mov    r3, #1
ps2_read_loop:
         // Wait for CLK to pulse low (for us, high...)
1:      ldr    r1, [r11, #0x004]
         tst    r1, #0x10
         beq    1b

         // Sample the DATA line:
         ldr    r1, [r12, #0]
         and    r1, r1, #4
         eor    r1, r1, #4  // Data's inverted
         mov    r1, r1, lsl#(31-2)
         orr    r0, r1, r0, lsr#1

         // Wait for CLK to go high again (low)
2:      ldr    r1, [r11, #0x004]
         tst    r1, #0x10
         bne    2b

         subs   r2, r2, #1
         bgt    ps2_read_loop

         // data is at bits 29-22:
         mov    r0, r0, lsr#22
         and    r0, r0, #0xff

         ldmfd  r13!, {r1-r12, pc}

-----------

Very usefully, the scancodes are documented at: http://82.152.113.94/ 
misc/Amstrad_Emailer_Pinouts.txt

Cheers,

Matt

PS:  If anyone cares, I went to a Tesco Extra super-mega-hyper-store  
in Altrincham, Manchester, yesterday and there were about 15 E2s on  
the shelves at £14.97 each - apparently also at several other south  
Manchester Tescos.  I don't know if this is a national thing.