; Routine to read a standard 3x4 matrix keypad using

; only 4 wires. Result is output the number on port A.

; Mike Rigby-Jones 30/11/98 (mrjones@nortelnetworks.com)



; Port B is altered by loading the port register with 0x00

; and changing the TRIS register.  Making a bit an output will

; force the bit to go low.  The inputs are pulled high by the

; internal weak pullups

;

;       SET            READBACK       KEY

; RB3 RB2 RB1 RB0  RB3 RB2 RB1 RB0  

;  1   1   1   0    1   1   0   0      *

;                   1   0   0   0      0

;                   1   0   1   0      #

;  1   1   0   1    1   1   0   0      7

;                   1   0   0   1      8

;                   1   0   0   0      9

;  1   0   1   1    1   0   0   0      4

;                   1   0   0   1      5

;                   1   0   1   0      6

;  0   1   1   1    0   1   0   0      1

;                   0   0   0   1      2

;                   0   0   1   0      3



	list	p=16f84

	include	<p16f84.inc>



keys	equ	0x10		; current state of row

count  	equ	0x11		; counter

keycode	equ	0x12		; number of button pressed

	

	org	0

	goto	start

	

	org	5		; avoid interupt vector

start:	bsf	STATUS,RP0	; change to bank 1

	bcf	OPTION_REG,NOT_RBPU	; enable pull ups on port b

	clrf	TRISA		; all outputs on port a

	movlw	0x0f

	movwf	TRISB		; RB0 to RB3 inputs

	bcf	STATUS,RP0	; change back to bank 0

	clrf	PORTA		; set all outputs low

	clrf	PORTB	



main:	call	scan		; scan keyboard 

	movf	keycode,W	; put keycode into w

	xorlw	0xff		; is the returned number 255?

	btfsc	STATUS,F	; if so then no key pushed

	goto	main		; scan again

	movf	keycode,W	; put key number back into w

	movwf	PORTA		; output result on port a



keyoff:	call	scan		; wait for user to release key

	movf	keycode,W	; put key number into w

	xorlw	0xff		; is the returned number 255?

	btfss	STATUS,Z

	goto	keyoff		; no, keep scanning keyboard

	goto	main		; yes, start again



scan:	movlw	0xff

	movwf	keycode		; default to 0xff if no key pushed

	movlw	B'00001110'

	bsf	STATUS,RP0	; bank 1

	movwf	TRISB		; turn B0 to an output (low)

	bcf	STATUS,RP0	; bank 0

	movf	PORTB,W		; get port b state

	andlw	0x0f		; mask lower nibble

	movwf	keys		; save result

	xorlw	B'00001110'	; check for no change

	btfsc	STATUS,Z

	goto	row2		; try next row

	call	getbit		; find position of first set bit

	call	table1		; translate to a key number

	movwf	keycode		; save result

	return



row2:	movlw	B'00001101'

	bsf	STATUS,RP0	; bank 1

	movwf	TRISB		; turn B1 to an output (low)

	bcf	STATUS,RP0	; bank 0

	movf	PORTB,W		; get port b state

	andlw	0x0f		; mask lower nibble

	movwf	keys		; save result

	xorlw	B'00001101'	; check for no change

	btfsc	STATUS,Z

	goto	row3		; try next row

	call	getbit		; find position of first set bit

	call	table2		; translate to a key number

	movwf	keycode		; save result

	return



row3:	movlw	B'00001011'

	bsf	STATUS,RP0	; bank 1

	movwf	TRISB		; turn B2 to an output (low)

	bcf	STATUS,RP0	; bank 0

	movf	PORTB,W		; get port b state

	andlw	0x0f		; mask lower nibble

	movwf	keys		; save result

	xorlw	B'00001011'	; check for no change

	btfsc	STATUS,Z

	goto	row4		; try next row

	call	getbit		; find position of first set bit

	call	table3		; translate to a key number

	movwf	keycode		; save result

	return



row4:	movlw	B'00000111'

	bsf	STATUS,RP0	; bank 1

	movwf	TRISB		; turn B3 to an output (low)

	bcf	STATUS,RP0	; bank 0

	movf	PORTB,W		; get port b state

	andlw	0x0f		; mask lower nibble

	movwf	keys		; save result

	xorlw	B'00000111'	; check for no change

	btfsc	STATUS,Z

	return

	call	getbit		; find position of first set bit

	call	table4		; translate to a key number

	movwf	keycode		; save result

	return



getbit:	clrf	count		; initialise counter

loop:	btfsc	keys,0		; test bit zero		

	goto	found

	incf	count,F		; add 1 to count

	rrf	keys,F		; move to next bit

	goto	loop		; try again

found:	movf	keys,W		; put count into w for lookup table

	return



table1:	addwf	PCL,F		; lookup table to convert number returned...

	retlw	0xff		; dummy

	retlw	0x0b		; #

	retlw	0x0a		; *

	retlw	0x00		; 0



table2:	addwf	PCL,F

	retlw	0x08		; 8

	retlw	0xff		; dummy

	retlw	0x07		; 7

	retlw	0x09		; 9



table3:	addwf	PCL,F	

	retlw	0x05		; 5

	retlw	0x06		; 6

	retlw	0xff		; dummy

	retlw	0x04		; 4



table4:	addwf	PCL,F	

	retlw	0x02		; 2

	retlw	0x03		; 3

	retlw	0x01		; 1



	end



