PS/2 keyboards...

Programming the 6502 microprocessor and its relatives in assembly and other languages.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

PS/2 keyboards...

Post by barnacle »

I'd just like to rant and ask - what were they thinking? :mrgreen:

Getting raw data from the keyboard is trivial (and I note that the recently purchased second hand Dell keyboard that I'm playing with both works at 3.3v and 5v, and takes so little current that it doesn't show on my power supply) but converting the output into something useful is, um, a non-trivial activity...

It probably doesn't help that I don't want to limit myself to the normal typing block - I also want to implement ctrl, alt, and ctrl-alt combinations for letters and ctrl and alt for numbers (though I'm not sure I'll ever use the latter) and definitely want the function keys and caps lock. Oh, and a pound sign '£', what with being English and all. Which isn't an ascii codepoint anyway, but lives on shift-3 on a UK keyboard.

So I've had to redefine (cough, 'extend') the ascii set to use eight bits:

Code: Select all

// control codes including cr, lf, tab etc
#define K_NULL		0x00
#define K_CTL_A		0x01
<...> 
#define K_CTL_Z   	0x1a
#define K_ESC		0x1b
#define K_POUND		0x1f		// £ sign

// standard ascii 
#define K_SPACE		0x20
<...> 
#define K_DEL		0x7f

// alt letters
//					0x80
#define K_ALT_A		0x81
<...>
#define K_ALT_Z		0x9a

// control numbers
#define K_CTL_0		0xa0
<...>
#define K_CTL_9		0xa9

// alt numbers
#define K_ALT_0		0xb0
<...>
#define K_ALT_9		0xb9

// ctrl-alt letters
//					0xc0
#define K_CTRALT_A	0xc1
<...>
#define K_CTRALT_Z	0xda

// cursor keys
#define K_LEFT		0xe0
#define K_RIGHT		0xe1
#define K_UPARROW	0xe2
#define K_DOWN		0xe3
#define K_PAGEUP	0xe4
#define K_PAGEDOWN	0xe5
#define K_HOME		0xe6
#define K_END		0xe7
#define K_INSERT		0xe8
#define K_DELETE	0xe9

// function keys
//					0xf0
#define K_F1		0xf1
<...>
#define K_F12	0xfc
Code is as yet incomplete; it's in C to run on an STM arm chip which will act as an SPI slave to a 65c02 and also provide serial interfaces. The combination of press and release and oddball (unnecessary) extension codes makes it interesting.

Neil
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: PS/2 keyboards...

Post by Yuri »

barnacle wrote:
I'd just like to rant and ask - what were they thinking? :mrgreen:
Might not want to ask. :mrgreen:

I've wondered about this myself. 7-bits could transmit some 128 scan codes with a make/break bit. Most keyboards don't have that many keys, yet, keys like Home, End, etc needed an "extended" scan code..... IDK why.
Quote:
It probably doesn't help that I don't want to limit myself to the normal typing block - I also want to implement ctrl, alt, and ctrl-alt combinations for letters and ctrl and alt for numbers (though I'm not sure I'll ever use the latter) and definitely want the function keys and caps lock. Oh, and a pound sign '£', what with being English and all. Which isn't an ascii codepoint anyway, but lives on shift-3 on a UK keyboard.

So I've had to redefine (cough, 'extend') the ascii set to use eight bits:
...
Code is as yet incomplete; it's in C to run on an STM arm chip which will act as an SPI slave to a 65c02 and also provide serial interfaces. The combination of press and release and oddball (unnecessary) extension codes makes it interesting.

Neil
Most of the time I've just processed the scan codes on the CPU itself. (Though that was for x86 based OSes I've tinkered with)

For 65xxx setups I've considered throwing the work onto a PIC16F871 where I can use it's own internal memory as a ring buffer, and raise an interrupt when there's data available.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

That's the plan with an STM32L073, largely because I've got a box full of the damn things :mrgreen:

Nice that it can handle up to five serial ports as well, with internal buffering, though I'm only planning for one.

So we have an 8048 talking to an STM arm talking to a 65C02. The eighties called - they want their processors back!

Neil

p.s. The windows event loop throws (threw? I'm not current with anything 64-bit) keypresses and releases onto the event chain and lets the application sort out what it needs, but it does some pre-processing of the data so the application never sees the extended code or the release code, just a defined key code. I'm not planning on telling the 6502 when a key is released, but I am leaving an option to return raw data on request.
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: PS/2 keyboards...

Post by Yuri »

barnacle wrote:
p.s. The windows event loop throws (threw? I'm not current with anything 64-bit) keypresses and releases onto the event chain and lets the application sort out what it needs, but it does some pre-processing of the data so the application never sees the extended code or the release code, just a defined key code.
To some extent. (Win32 API is still the under pins Win64, so not much has changed there)

I know with DirectX you can get a lot more detail about the make/break codes. But I recall looking through the Quake 2 source code way back in the day, and as I recall, Carmack just used the normal Win32 key events; so apparently they were "good enough".
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: PS/2 keyboards...

Post by BigDumbDinosaur »

barnacle wrote:
I'd just like to rant and ask - what were they thinking? :mrgreen:

Probably a design-by-committee process got involved.  You have to consider the origins of the keyboard design.  IBM is/was full of committees.  :shock:

Quote:
Oh, and a pound sign '£', what with being English and all...

...says the guy in Germany, where they use euros.  :D
x86?  We ain't got no x86.  We don't NEED no stinking x86!
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

BigDumbDinosaur wrote:


Quote:
Oh, and a pound sign '£', what with being English and all...

...says the guy in Germany, where they use euros.  :D
Yup! Left off the ä, ö, ü, and ß, too... UTF-8 is not in my immediate plans. I just feel that if I have a £ key, it ought to do something.

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

barnacle wrote:
Getting raw data from the keyboard is trivial
Even more trivial when you plug the data wire into the correct pin on the Nucleo... :roll:

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

Encouraging. The majority of the keyboard is producing something useful, and in the majority of cases the right something. I still need to sort out the 0xe0 prefixed keys, and for some reason the numeric key pad is all over the place - probably my lookup table is incorrect.

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

There must be a more elegant way to handle shift and capslock... capslock has to shift the alpha characters only, unless shift is active, but the number keys have to respond to shift but ignore capslock.

Shift is true when the shift key is held; capslock is toggled whenever it's pressed. Ukupper and uklower are tables where the scancode indexes the desired keyboard mapping.

Code: Select all

					// shift affects all keys; shift lock only alpha
					if (shift)
					{
						if (!shiftlock)
						{
							ret = ukupper[scancode];
						}
						else
						{
							ret = uklower[scancode];
							if (!isalpha(ret))
							{
								ret = ukupper[scancode];
							}
						}
					}
					else
					{
						if (!shiftlock)
						{
							ret = uklower[scancode];
						}
						else
						{
							ret = ukupper[scancode];
							if (!isalpha(ret))
							{
								ret = uklower[scancode];
							}
						}
					}
That works, but it feels ugly...

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

So here's a mostly complete keyboard driver to translate PS/2 keycodes - including function keys and cursor controls into a modified ascii output on key press ( key release is ignored except for the control, shift, alt etc keys which are handled internally).

A few odd keys are ignored and some may cause immediately following keys to be ignored - particularly print-screen, scroll-lock, and pause-break. This is for my Compaq keyboard - UK 104 layout; it's obvious where to change the keyboard mapping.

0x00-0x1a: ctrl-A to ctrl-Z
0x1b: ESC
0x1c: ctrl-TAB
0x1d: alt-TAB
0x1e: shift-TAB (for text editors)
0x1f: UK Pound
0x20-0x7f: normal ascii characters
0x81-0x9a: alt-A to alt-Z
0xa1-0xba: ctrl-alt-A to ctrl-alt-Z
Cursor keys:
0xe0: left
0xe1: right
0xe2: up
0xe3: down
0xe4: page up
0xe5: page down
0xe6: home
0xe7: end
0xe8: insert
And the function keys: 0xf1-0xfc.

There is no number lock; I prefer it as a number pad all the time but it's easy enough to add.

For what it's worth, the interrupt routine to grab the next bit is five lines of code and the test for completion another five...

Neil
Attachments
keycodes.c.zip
(1.68 KiB) Downloaded 46 times
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: PS/2 keyboards...

Post by Yuri »

barnacle wrote:
There must be a more elegant way to handle shift and capslock... capslock has to shift the alpha characters only, unless shift is active, but the number keys have to respond to shift but ignore capslock.

Shift is true when the shift key is held; capslock is toggled whenever it's pressed. Ukupper and uklower are tables where the scancode indexes the desired keyboard mapping.

Code: Select all

					// shift affects all keys; shift lock only alpha
					if (shift)
					{
						if (!shiftlock)
						{
							ret = ukupper[scancode];
						}
						else
						{
							ret = uklower[scancode];
							if (!isalpha(ret))
							{
								ret = ukupper[scancode];
							}
						}
					}
					else
					{
						if (!shiftlock)
						{
							ret = uklower[scancode];
						}
						else
						{
							ret = ukupper[scancode];
							if (!isalpha(ret))
							{
								ret = uklower[scancode];
							}
						}
					}
That works, but it feels ugly...

Neil
Maybe something like so?

Code: Select all

int ret = uklower[scancode];
ret = (isalpha(ret) && (shift ^ shiftlock)) | (!isalpha(ret) && shift) ? ukupper[scancode] : ret;
(Haven't tried this logic myself, but I think that might be closer to what you're looking for)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

Yuri wrote:
Maybe something like so?

Code: Select all

int ret = uklower[scancode];
ret = (isalpha(ret) && (shift ^ shiftlock)) | (!isalpha(ret) && shift) ? ukupper[scancode] : ret;
Thanks Yuri, much tidier. Needs a || in the middle instead of a | but that's what I couldn't get my head round. (I only have a small execution stack in my head and it kept overflowing :mrgreen: )

I've also modified the alt/ctrl logic so that alt-alpha is now the more logical 0xc0-0xdf and ctrl-alt-alpha 0x80-0x9f.

Neil
Attachments
keycodes.c.zip
(1.67 KiB) Downloaded 46 times
jgharston
Posts: 181
Joined: 22 Feb 2004

Re: PS/2 keyboards...

Post by jgharston »

barnacle wrote:
So here's a mostly complete keyboard driver to translate PS/2 keycodes - including function keys and cursor controls into a modified ascii output on key press ( key release is ignored except for the control, shift, alt etc keys which are handled internally).
...
0x00-0x1a: ctrl-A to ctrl-Z
0x1b: ESC
0x1c: ctrl-TAB
0x1d: alt-TAB
0x1e: shift-TAB (for text editors)
0x1f: UK Pound
So what does Ctrl-\ give? And Ctrl-] Ctrl-^ Ctrl-_

I use 0x80+n for function keys and 0xC0+n for editing keys with Shift,Ctrl,Alt encoded in b6-b5-b4, allowing 0xD5=Shift-TAB, 0xE5=Ctrl-TAB, 0xF5=Alt-TAB.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: PS/2 keyboards...

Post by barnacle »

It shouldn't give anything. I only applied the control and tab modifiers to alpha keys. Also, shift is ignored if control or alt are active.

Neil
jgharston
Posts: 181
Joined: 22 Feb 2004

Re: PS/2 keyboards...

Post by jgharston »

I've also just noticed you've got: 0xe0: left, 0xe1: right, 0xe2: up, 0xe3: down.
Cursor controls are ordered 8,9,10,11 left,right,down,up so it's always useful to order input cursor controls the same, ie:
base+0:left, base+1:right, base+2:down, base+3:up, similarly:
base+0:home, base+1:end, base+2:pgdn, base+3:pgup

Eg, my code has &C8-&CF as home,end,pgdn,pgup,left,right,down,up
(quickly checks docs... make sure I'm not talking rubbish :) )
Post Reply