;/******************************************************************************/
;/  PC Keyboard decoder															/
;/																				/
;/  Designed and written by Daryl Rictor (c)2004								/ 
;/******************************************************************************/
;
; All standard keys and control keys are decoded to 7 bit (bit 7=0) standard ASCII.
; Control key note: It is being assumed that if you hold down the ctrl key,
; you are going to press an alpha key (A-Z) with it (except break key defined below.)
; If you press another key, its ascii code's lower 5 bits will be send as a control
; code.  For example, Ctrl-1 sends $11, Ctrl-; sends $2B (Esc), Ctrl-F1 sends $01.
;
; The following non-standard keys are decoded with bit 7=1, bit 6=0 if not shifted,
; bit 6=1 if shifted, and bits 0-5 identify the key.
; 
; Function key translation:  
;              ASCII / Shifted ASCII
;            F1 - 81 / C1
;            F2 - 82 / C2
;            F3 - 83 / C3
;            F4 - 84 / C4
;            F5 - 85 / C5
;            F6 - 86 / C6
;            F7 - 87 / C7
;            F8 - 88 / C8
;            F9 - 89 / C9
;           F10 - 8A / CA
;           F11 - 8B / CB
;           F12 - 8C / CC
;
; The Print screen and Pause/Break keys are decoded as:
;                ASCII  Shifted ASCII
;    Ctrl-Break - 02       02  (Ctrl-B) (can be changed to AE/EE)(non-repeating key)  
;     Pause/Brk - 03       03  (Ctrl-C) (can change to 8E/CE)(non-repeating key)
;      Scrl Lck - 8D       CD  
;        PrtScn - 8F       CF
;
; The Alt key is decoded as a hold down (like shift and ctrl) but does not
; alter the ASCII code of the key(s) that follow.  Rather, it sends
; a Alt key-down code and a seperate Alt key-up code.  The user program
; will have to keep track of it if they want to use Alt keys. 
;
;      Alt down - A0
;        Alt up - E0
;
; Example byte stream of the Alt-F1 sequence:  A0 81 E0.  If Alt is held down longer
; than the repeat delay, a series of A0's will preceeed the 81 E0.
; i.e. A0 A0 A0 A0 A0 A0 81 E0.
;
; The special windows keys are decoded as follows:
;                           ASCII    Shifted ASCII
;        Left Menu Key -      A1          E1 
;       Right Menu Key -      A2          E2
;     Right option Key -      A3          E3
;            Power Key -      A4          E4  
;            Sleep Key -      A5          E5
;             Wake Key -      A6          E6
;
;
; The following "cursor" keys ignore the shift key and return their special key code 
; when numlock is off or their direct labeled key is pressed.  When numlock is on, the digits
; are returned reguardless of shift key state.        
; keypad(NumLck off) or Direct - ASCII    Keypad(NumLck on) ASCII
;          Keypad 0        Ins - 90                 30
;          Keypad .        Del - 7F                 2E
;          Keypad 7       Home - 97                 37
;          Keypad 1        End - 91                 31
;          Keypad 9       PgUp - 99                 39
;          Keypad 3       PgDn - 93                 33
;          Keypad 8    UpArrow - 98                 38
;          Keypad 2    DnArrow - 92                 32
;          Keypad 4    LfArrow - 94                 34
;          Keypad 6    RtArrow - 96                 36 
;          Keypad 5    (blank) - 95                 35
;
;******************************************************************************
; include ATtiny26 definitions & program specific definitions and macros
;******************************************************************************
.include  "tn26def.inc"
;
;  Define Registers and Port Pins
;
;   Acc = R00, R01 (results of multiply command)
.def  Acc		=	R00			;\ math accumulator
.def  Acch		=	R01			;/ 

.def J			=   R16			; temp data storage
.def K			= 	R17         ; IRQ temp data storage
.def special	=	R18			; hold status flags
.def byte		=   R19			; byte to tx/rx
.def lastbyte	=   R20			; last byte sent (incase of error)
.def parity		=   R21			; parity value rcvd
.def pcnt		=	R22			; parity generator
.def cntr		=  	R23			; bit counter
;
; special register bit defs (for test opcode)
;
.equ SCRLLOCK	=	0			; 01
.equ NUMLOCK	=	1			; 02
.equ CAPSLOCK	=	2			; 04
.equ CONTROL	=	3			; 08
.equ SHIFT		=	4			; 10
.equ EXT		=	5			; 20
.equ EXTSH		=	6			; 40  
.equ RLSE		=   7			; 80  key release code

;    Y pair = R28,29
;    Z pair = R30,31
;
;  Y pair used as output buffer to host
;  Z pair used to convert scan codes to ASCII codes

;PORT A pin defs (Host data bus)

;PORT B pin defs

.set  kbclk     =   PB3			; bi directional
.set  kbdat     =   PB4			; bi directional
.set  datardy   =   PB5			; output to host (Data RDY)
.set  dataack   =   PB6			; input from host (Data Ack)
.set  rstpin	=   PB7			; input (Reset)

;******************************************************************************
; Code Begins at 0x000
; System IRQ jump table from 0x0000 - 0x0012
;******************************************************************************
	rjmp 	RESET 				; Reset Handler
	rjmp	EXT_INT0 			; IRQ0 Handler
	rjmp 	EXT_IOPINS 			; IRQ1 Handler
	rjmp 	TIM1_COMPA 			; Timer1 CompareA Handler
	rjmp 	TIM1_COMPB 			; Timer1 CompareB Handler
	rjmp 	TIM1_OVF1 			; Timer1 Overflow1 Handler
	rjmp 	TIM0_OVF0 			; Timer0 Overflow0 Handler
	rjmp 	USI_STRT 			; USI start
	rjmp	USI_OVF				; USI overflow
	rjmp 	EE_RDY	 			; EEPROM Ready Handler
	rjmp 	ANA_COMP 			; Analog Comparator Handler
	rjmp	ADC_COMP			; Analog-digital conversion complete
	
;******************************************************************************
; unused IRQ vector's point to software reset code
;******************************************************************************

EXT_INT0:
EXT_IOPINS:
TIM1_COMPA:
TIM1_COMPB:
TIM1_OVF1:
TIM0_OVF0:
USI_STRT:
USI_OVF:
EE_RDY:
ANA_COMP:
ADC_COMP:

;******************************************************************************
; Program Starts here on Reset
;******************************************************************************
RESET:							; first line executed after reset 
	CLI							; disable interupts

;******************************************************************************
; Initialize the I/O Ports
;******************************************************************************
; port A pins (Host data bus - outputs)
	ldi		J, 0x00				; data 0
	out		porta, J			; set port a outputs to 0
	LDI		J, 0xFF				; pins 0 - 7 of port A
	out		ddra, J				; set DDRA pins 0 - 7 to outputs

; port B pins (KB I/O, Host handshake, SPKR)
	LDI		J, 1<<datardy		; pin 5 is output, rest inputs
	out		ddrb, J				; set DDRB 
	out		portb, J			; drop all pullups on Port B, set datardy high (active low)

;******************************************************************************
; Initialize System Resources
;******************************************************************************
	ldi		J, 0xDF				; top of SRAM
	out		SP, J				; init Stack Pointer

;******************************************************************************
; Initialize Program
;******************************************************************************
	rcall	initkbd

;******************************************************************************
; Main Loop
;******************************************************************************
MAIN:
	rcall	KBINPUT				; get a kb code

	out		porta, J			; yes, send data direct to host port
	cbi		portb, datardy		; tell host data ready (active low)

loop1:
	sbic	pinb, dataack		; 
	rjmp	loop1				; wait for host drop ack signal

	sbi		portb, datardy		; raise our data ready strobe (inactive)		

loop2:
	sbis	pinb, dataack		; wait for host to raise its ack line
	rjmp	loop2				;
	rjmp	main				; get another kb code
		
;******************************************************************************
; Subroutines
;******************************************************************************
INITKBD:
    ldi   	J, 1<<NUMLOCK  		; init - num lock on, all other off
    mov		special, J          ; 
init1:
    ldi     J, 0xff        		; keybrd reset
    rcall   send       			; reset keyboard
    rcall   get         	    ; 
	cpi   	J, 0xFA             ; ack?
    brne    init1	            ; resend reset cmd
	rcall	get             	; 
	cpi   	J, 0xAA             ; reset ok
	brne   	init1           	; resend reset cmd        

SETLEDS:
	ldi   	J, 0xED             ; Set the keybrd LED's from kbleds variable
    rcall	send            	; 
    rcall	get             	;
	cpi		J, 0xFA    	        ; ack?
    brne   	setleds            	; resend led cmd        
    mov   	J, special        	; 
    andi    J, 0x07             ; ensure bits 3-7 are 0
    rcall	send            	; 
	ret
;
;
;
HIGHLOW:
	sbis	pinb, kbclk			
    rjmp	highlow		        ; wait while clk low
hl1: 
    sbic 	pinb, kbclk
	rjmp	hl1             	; wait while clk is high
	clc							; clear Carry bit
	sbic	pinb, kbdat			; is data hi
	sec							; yes. set Carry bit
	ret							; exit with Carry = data input bit 
;
; Flush the keyboard buffer 
;
FLUSH:
	ldi   	J, 0xf4             ; flush buffer (fall through to Send command)
;
; send a byte to the keyboard from J
;
SEND:
    mov		byte, J				; byte to send into Byte
	mov		lastbyte, J			; copy to lastbyte also in case of send error
	sbi		ddrb, kbclk			; clk & dat as outputs
	ldi		J, 0x21				; 33 dec * 3 clks = 99uS
sendw:							;
    dec     J                 	; 
	brne   sendw 	          	; 100uS delay
	ldi		parity, 0x00		; parity counter
	ldi		cntr, 0x08			; bit counter 
	sbi		ddrb, kbdat			; set data low
	cbi		ddrb, kbclk			; set clk input
	rcall	highlow         	; wait for clock transition from kb and read data
send1:
	lsr   	byte              	; get lsb first
    brcs  	mark            	; 
	sbi		ddrb, kbdat			; set data line low
    rjmp    next            	; 
mark:
	cbi		ddrb, kbdat			; set data line high
    inc     parity				; inc parity counter
next:
	rcall	highlow         	; 
    dec  	cntr			    ; bit counter
    brne    send1   			; send 8 data bits

	mov		J, parity
    andi   	J, 0x01   	        ; get odd or even
    brne   	pclr            	; if odd, send 0
	cbi		ddrb, kbdat			; set data bit high
	rjmp	ack					; ack
pclr:
	sbi		ddrb, kbdat			; set data bit low
ack:
	rcall	highlow         	; 
	cbi		ddrb, kbclk			; set clk & data to input
	cbi		ddrb, kbdat			;	
	rcall	highlow         	; wait for ack from keyboard
    brcs   	initkbd            	; VERY RUDE error handler - re-init the keyboard
send2:
	sbis	pinb, kbclk			; wait for clk to go high
	rjmp	send2				;
	rjmp	disable				; done
;
; Error sends a resend command and then gets the code again
;
error:
	ldi		J, 0xFE             ; resend cmd
	rcall	send            	; 
;
; KBGET waits for one scancode from the keyboard, save in byte
;
GET:
	ldi		byte, 0x00    		; clear scankey holder
	ldi		parity, 0x00		; clear parity holder
	ldi		pcnt, 0x00			; clear parity counter
	ldi		cntr, 0x08			; bit counter 
	cbi		ddrb, kbdat
	cbi		ddrb, kbclk			; set clk to input (change if port bits change)
get1:
	sbic	pinb, kbclk
	rjmp	get1	            ; wait while clk is high

	sbic	pinb, kbdat			; get start bit, if 1, false start bit, do again 
	rjmp	get1
get2:
    rcall	highlow         	; wait for clk to return high then go low again
    ror		byte  				; save bit to byte holder
    brpl    get3            	; 
    inc		pcnt				; add 1 to parity counter
get3:
    dec   	cntr				; dec bit counter
    brne   	get2            	; get next bit if bit count > 0 
	rcall	highlow         	; wait for parity bit
	brcc	get4				; if parity bit 0 do nothing
    inc   	parity            	; if 1, set parity to 1        
get4:
	mov 	J, pcnt				; get parity count
	eor   	J, parity           ; compare with parity bit
    andi   	J, 0x01             ; mask bit 1 only
    breq   	error           	; bad parity
	rcall	highlow         	; wait for stop bit
	brcc	error           	; 0=bad stop bit 
	cpi		byte, 0x00			; is byte rcv'd =0?
	breq   	get             	; no data, do again
	rcall	disable             ; 
	mov		J, byte				; 
	ret							; 
;
; disable keyboard from sending
;
disable:						; disable kb from sending more data
	sbi		ddrb, kbclk			; clk = 0 (change if port bits change)
    ret		                    ; 
;
; get scancode and convert it to an character code
;
kbinput:
	rcall	get					; get a scancode (returned in byte)
	sbrc	special, rlse		; was a release code pending?
	rjmp	Rlsproc				; yes - process this key
	sbrc	special, ext		; was extended code entered?
	rjmp	Extproc				; yes, do further tests
	cpi		byte, 0x12			; no, is it the L shift key? 
	breq	shftky
	cpi		byte, 0x59			; is it the R shift key? 
	breq	shftky				; 
exttst:							;***** do not add test above this line without changing Extproc code!
	cpi		byte, 0x14			; is it the ctrl key? 
	breq	ctrlky				; 
	cpi		byte, 0x58			; is it the capslock? 
	breq	caplky				; 
	cpi		byte, 0x77			; is it the numlock key? 
	breq	numlky				; no, test code under 128
	cpi		byte, 0x7E			; scroll Lock key?
	breq    scrlky				; yes
	cpi		byte, 0x7F			; is it < 0x80
	brcs    lookup				; yes, do direct conversion to ASCII
	cpi		byte, 0x83			; is it the F7 key?
	breq	F7ky				; 
	cpi		byte, 0xE0			; is it the E0 code
	breq	extky				; 
	cpi		byte, 0xE1			; is it pause/break?
	breq	brkky				; 
	cpi		byte, 0xF0			; is it the key release code?
	brne	kbinput				; no, ignore and get next key
	sbr		special, 1<<rlse	;
	rjmp	kbinput				; get next key

lookup:
	ldi		ZH, 0x06			; set page base for index table (pre *2)
	mov		ZL, byte			; set code to index
	lsl		ZL					; *2 for lookup in word table unshifted byte
	sbrc	special, shift
	sbr		ZL, 1				; set shifted byte in word table	
	sbrc	special, extsh
	sbr		ZL, 1				; set shifted byte in word table	
	cpi		byte, 0x78			; is it F11?
	breq	lookup1				; yes, just get it
	cpi		byte, 0x7E			; is it scroll lock?
	breq	lookup1				; yes, just get it
	cpi		byte, 0x69			; test for numpad?
	brcs	lookup1				; not numpad
	sbrs	special, numlock	; test for numlock off
	sbr		ZL, 1				; if off, get shifted code from table
lookup1:
	lpm		J, Z				; lookup the ASCII code from the scan code
	sbrc	special, control	; is control key active?
	andi	J, 0x1F				; mask out control key codes from 0x00-0x1F
	sbrc	special, rlse		; is this a release code?
	andi	J, 0x00				; clear it out
	sbrs	special, capslock	; is capslock set
	rjmp	final				; no
	cpi		J, 0x61				; <"A"
	brcs	final
	cpi		J, 0x7B				; >"Z"+1
	brcc	final
	andi	J, 0xDF				; set letter to CAPS
final:
	cpi		J, 0x00				; is it zero?
	brne	final1
	rjmp	kbinput				; resulted in 0x00, ignore and get next byte
final1:
	ret							; done. exit with ASCII in J
	
shftky:
	sbr		special, 1<<shift	; set shift bit
	rjmp	kbinput
ctrlky:
	sbr		special, 1<<control	; set control bit
	rjmp	kbinput
caplky:
	ldi		J, 1<<capslock
	eor		special, J			; toggle the capslock
	rcall	setleds				; update the LED's
	rjmp	kbinput
numlky:	
	ldi		J, 1<<numlock
	eor		special, J			; toggle the numlock
	rcall	setleds				; update the LED's
	rjmp	kbinput
scrlky:	
	ldi		J, 1<<scrllock
	eor		special, J			; toggle the scroll-lock
	rcall	setleds				; update the LED's
	rjmp	lookup				; send scroll lock code
F7ky:	
	ldi		byte, 0x02			; yes F7, set scancode to modified F7 code 0x02
	rjmp	lookup				; process it
extky:
	sbr		special, 1<<ext		; set the extend flag in the flag reg
	rjmp	kbinput				; get next key
brkky:
	rcall	get					; yes - Pause break pressed
	rcall	get
	rcall	get
	rcall	get
	rcall	get
	rcall	get
	rcall	get					; flush the next 7 keycodes (all part of brk)
	ldi		J, 0x03				; set Pause/break code
	ret							; return it
ctrlbrk:
	ldi		J, 0x02				; set Control- Pause/break code
	ret							; return it
Extshky:
	sbr		special, 1<<extsh	; set ext shift bit
	rjmp	kbinput				; get next code
Prtscnky:
	cbr		special, 1<<extsh	; turn off ext shift flag
	ldi		byte, 0x0F			; yes, set new scan code for PrtScrn
	rjmp	lookup				; and process it
KPdivky:
	ldi		J, 0x2F				; yes, set ASCII code for /
	ret							; and send it to host
Rlsalt:
	ldi		J, 0xE0				; alt Rls ASCII Code
	ret
Rlsshft:
	cbr		special, 1<<shift	; drop shift mode
rlsextsh:
	cbr		special, 1<<extsh	; clear ext shift register bit
	rjmp	kbinput				; get next key
rlsctrl:
	cbr		special, 1<<control	; drop control mode
	rjmp	kbinput				; get next key

Extproc:
	cbr		special, 1<<ext		; turn off ext flag
	cpi		byte, 0x12			; was the E012 code entered?
	breq	Extshky
	cpi		byte, 0x7C			; was it E07C - Print Screen?
	breq	Prtscnky
	cpi		byte, 0x4A			; was it KP /?
	breq	KPdivky	
	cpi		byte, 0xF0			; is it a rlse code?
	breq	Extrls				; 
	cpi		byte, 0x7E			; is it the ctrl-brk key?
	breq	Ctrlbrk				;
	cpi		byte, 0x68			; test for cursor/movement keys (E069 - E07D)
	brcc	extp1				; do lookup
	rjmp	Exttst				; 
Extp1:
	rjmp	lookup

Extrls:
	rcall   get					; get next code
	cpi		byte, 0x12			; was it ext shift?
	breq	rlsextsh			; 
;	rjmp	Rlsproc				; test for alt & ctrl releases
Rlsproc:
	cbr		special, 1<<rlse	; yes - reset flag
	cpi		byte, 0x11			; was alt released?
	breq	Rlsalt
	cpi		byte, 0x12			; left shift
	breq	Rlsshft
	cpi		byte, 0x59			; right shift
	breq	Rlsshft
	cpi		byte, 0x14			; control key
	breq	rlsctrl				; 
	rjmp	kbinput				; don't care about the rest, get next key
;
;
;
.cseg
.org	0x300
scancode:
;               norm    shift     scancode
	 .db		$00,	$00		; 00 no key pressed	
	 .db		$89,	$C9		; 01 F9	
	 .db		$87,	$C7		; 02 relocated F7	
	 .db		$85,	$C5		; 03 F5	
	 .db		$83,	$C3		; 04 F3	
	 .db		$81,	$C1		; 05 F1	
	 .db		$82,	$C2		; 06 F2	
	 .db		$8C,	$CC		; 07 F12	
	 .db		$00,	$00		; 08	
	 .db		$8A,	$CA		; 09 F10	
	 .db		$88,	$C8		; 0A F8	
	 .db		$86,	$C6		; 0B F6	
	 .db		$84,	$C4		; 0C F4	
	 .db		$09,	$09		; 0D tab	
	 .db		$60,	$7E		; 0E `~	
	 .db		$8F,	$CF		; 0F relocated Print Screen key	
	 .db		$03,	$03		; 10 relocated Pause/Break key	
	 .db		$A0,	$A0		; 11 left alt (right alt too)	
	 .db		$00,	$00		; 12 left shift	
	 .db		$00,	$00		; 13 
	 .db		$00,	$00		; 14 left ctrl (right ctrl too)	
	 .db		$71,	$51		; 15 qQ	
	 .db		$31,	$21		; 16 1!	
	 .db		$00,	$00		; 17	
	 .db		$00,	$00		; 18	
	 .db		$00,	$00		; 19	
	 .db		$7A,	$5A		; 1A zZ	
	 .db		$73,	$53		; 1B sS	
	 .db		$61,	$41		; 1C aA	
	 .db		$77,	$57		; 1D wW	
	 .db		$32,	$40		; 1E 2@	
	 .db		$A1,	$E1		; 1F Windows 98 menu key (left side)	
	 .db		$00,	$00		; 20 	
	 .db		$63,	$43		; 21 cC	
	 .db		$78,	$58		; 22 xX	
	 .db		$64,	$44		; 23 dD	
	 .db		$65,	$45		; 24 eE	
	 .db		$34,	$24		; 25 4$	
	 .db		$33,	$23		; 26 3#	
	 .db		$A2,	$E2		; 27 Windows 98 menu key (right side)	
	 .db		$00,	$00		; 28	
	 .db		$20,	$20		; 29 space	
	 .db		$76,	$56		; 2A vV	
	 .db		$66,	$46		; 2B fF	
	 .db		$74,	$54		; 2C tT	
	 .db		$72,	$52		; 2D rR	
	 .db		$35,	$25		; 2E 5%	
	 .db		$A3,	$E3		; 2F Windows 98 option key (right click, right side)	
	 .db		$00,	$00		; 30	
	 .db		$6E,	$4E		; 31 nN	
	 .db		$62,	$42		; 32 bB	
	 .db		$68,	$48		; 33 hH	
	 .db		$67,	$47		; 34 gG	
	 .db		$79,	$59		; 35 yY	
	 .db		$36,	$5E		; 36 6^	
	 .db		$A4,	$E4		; 37 Power Key 	
	 .db		$00,	$00		; 38	
	 .db		$00,	$00		; 39	
	 .db		$6D,	$4D		; 3A mM	
	 .db		$6A,	$4A		; 3B jJ	
	 .db		$75,	$55		; 3C uU	
	 .db		$37,	$26		; 3D 7&	
	 .db		$38,	$2A		; 3E 8*	
	 .db		$A5,	$E5		; 3F Sleep Key	
	 .db		$00,	$00		; 40	
	 .db		$2C,	$3C		; 41 ,<	
	 .db		$6B,	$4B		; 42 kK	
	 .db		$69,	$49		; 43 iI	
	 .db		$6F,	$4F		; 44 oO	
	 .db		$30,	$29		; 45 0)	
	 .db		$39,	$28		; 46 9(	
	 .db		$00,	$00		; 47	
	 .db		$00,	$00		; 48	
	 .db		$2E,	$3E		; 49 .>	
	 .db		$2F,	$3F		; 4A /?	
	 .db		$6C,	$4C		; 4B lL	
	 .db		$3B,	$3A		; 4C ;:	
	 .db		$70,	$50		; 4D pP	
	 .db		$2D,	$5F		; 4E -_	
	 .db		$00,	$00		; 4F	
	 .db		$00,	$00		; 50	
	 .db		$00,	$00		; 51	
	 .db		$27,	$22		; 52 '"	
	 .db		$00,	$00		; 53	
	 .db		$5B,	$7B		; 54 [{	
	 .db		$3D,	$2B		; 55 =+	
	 .db		$00,	$00		; 56	
	 .db		$00,	$00		; 57	
	 .db		$00,	$00		; 58 caps	
	 .db		$00,	$00		; 59 r shift	
	 .db		$0D,	$0D		; 5A <Enter>	
	 .db		$5D,	$7D		; 5B ]}	
	 .db		$00,	$00		; 5C	
	 .db		$5C,	$7C		; 5D \|	
	 .db		$A6,	$E6		; 5E Wake Key	
	 .db		$00,	$00		; 5F	
	 .db		$00,	$00		; 60	
	 .db		$00,	$00		; 61	
	 .db		$00,	$00		; 62	
	 .db		$00,	$00		; 63	
	 .db		$00,	$00		; 64	
	 .db		$00,	$00		; 65	
	 .db		$08,	$08		; 66 bkspace	
	 .db		$00,	$00		; 67	
	 .db		$00,	$00		; 68	
	 .db		$31,	$91		; 69 kp 1 {End}
	 .db		$2f,	$2f		; 6A kp / converted from E04A in code	
	 .db		$34,	$94		; 6B kp 4 {Left}	
	 .db		$37,	$97		; 6C kp 7 {Home}	
	 .db		$00,	$00		; 6D	
	 .db		$00,	$00		; 6E	
	 .db		$00,	$00		; 6F	
	 .db		$30,	$90		; 70 kp 0 {Ins}	
	 .db		$2E,	$7F		; 71 kp . {Del}	
	 .db		$32,	$92		; 72 kp 2 {Down}	
	 .db		$35,	$95		; 73 kp 5	
	 .db		$36,	$96		; 74 kp 6 {Right}	
	 .db		$38,	$98		; 75 kp 8 {Up}	
	 .db		$1B,	$1B		; 76 esc	
	 .db		$00,	$00		; 77 num lock	
	 .db		$8B,	$CB		; 78 F11	
	 .db		$2B,	$2B		; 79 kp +	
	 .db		$33,	$93		; 7A kp 3 {PgDn}	
	 .db		$2D,	$2D		; 7B kp -	
	 .db		$2A,	$2A		; 7C kp *	
	 .db		$39,	$99		; 7D kp 9 {PgUp}	
	 .db		$8D,	$CD		; 7E scroll lock	
	 .db		$00,	$00		; 7F
;
; End of Program
;
