;*********************************************************
; THIS PROGRAM SCANS THE KEYPAD AND RETURNS WITH
; THE KEY PRESS IN THE 'KEY_PRESSED' REGISTER FOR PORTABILITY!
; RUN SCAN_PAD_ON TO SET UP AN INTERRUPT FOR THE PAD
; OR RUN SCAN_PAD_OFF TO DISABLE THE INTERRUPT.
; IN YOUR INTERRUPT SERVICE ROUTINE, CHECK FOR A PORT
; CHANGE ON RB4-RB7 AND THEN CALL KEY_HIT_INT TO
; SEE WHICH KEY WAS HIT!!
;*********************************************************
SCAN_PAD_ON:
MOVLW B'11111111' ;MAKE PORTB
TRIS PORTB
;ALL INPUTS
BSF STATUS,RP0
;SWITCH TO BANK 1
BCF OPTREG,RBPU ;ENABLE WEAK PULLUPS
BCF STATUS,RP0
;SWITCH TO BANK 0
BCF INTCON,RBIF ;CLEAR
INTERRUPT FLAG
BSF INTCON,GIE
;ENABLE GLOBAL INTERRUPTS
BSF INTCON,RBIE ;AND THE ONE WE NEED
RETURN
SCAN_PAD_OFF:
BSF STATUS,RP0
;SWITCH TO BANK 1
BSF OPTREG,RBPU ;DISABLE WEAK PULLUPS
BCF STATUS,RP0
;SWITCH TO BANK 0
BCF INTCON,RBIE ;DISABLE
INTERRUPT
RETURN
;********************************************************
; IF A KEY IS HIT, YOUR PROGRAM GETS TO HERE
;********************************************************
;********************************************************
; RB4 RB5 RB6 RB7
; COL1 COL2 COL3 COL4
; B0 ROW1 1 2 3 <
;
; B1 ROW2 4 5 6 >
;
; B2 ROW3 7 8 9 Y
;
; B3 ROW4 * 0 # N
;
;********************************************************
KEY_HIT_INT:
movfw cnt
;get the cnt value
movwf temp_cnt ;save it
movfw cnt2
;get the cnt value
movwf temp_cnt2 ;save it
movfw cnt3
;get the cnt value
movwf temp_cnt3 ;save it
movfw cnt4
;get the cnt value
movwf temp_cnt4 ;save it
MOVFW PORTB ;MOVE PORTB VALUE TO W REG
;(THIS ENDS THE MISMATCH CONDITION)
MOVLW .250
;DEBOUNCE DELAY TIME
CALL MDELAY ;DEBOUNCE DELAY
call read_again ;check for a reasonable key press
BTFSS TEMP_KEY2,4 ;WAS IT ON RB4?
GOTO COLUMN1 ;IT WAS ON COLUMN 1
BTFSS TEMP_KEY2,5 ;WAS IT ON RB5?
GOTO COLUMN2 ;IT WAS ON COLUMN 2
BTFSS TEMP_KEY2,6 ;WAS IT ON RB6?
GOTO COLUMN3 ;IT WAS ON COLUMN 3
BTFSS TEMP_KEY2,7 ;WAS IT ON RB7?
GOTO COLUMN4 ;IT WAS ON COLUMN 4
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
;RETURN FROM THE INTERRUPT
COLUMN1:
CLRF TEMP_KEY ;SET KEY VALUE TO 0
MOVLW B'11101111' ;SET THE COLUMN VALUE (RB4)
MOVWF COL
;INTO COL REGISTER
CALL KEY_PRESS ;GO SEE WHICH ROW IT IS ON
CALL KEY_DOWN? ;MAKE SURE THE KEY IS RELEASED
MOVWF KEY_PRESSED ;MOVE THE KEY PRESSED TO FILE REG
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
COLUMN2:
MOVLW .4
;OFFSET VALUE FOR KEY
MOVWF TEMP_KEY ;STORE IN TEMP_KEY
MOVLW B'11011111' ;SET THE COLUMN VALUE (RB5)
MOVWF COL
;INTO COL REGISTER
CALL KEY_PRESS ;GO SEE WHICH ROW IT IS ON
CALL KEY_DOWN? ;MAKE SURE THE KEY IS RELEASED
MOVWF KEY_PRESSED ;MOVE THE KEY PRESSED TO FILE REG
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
COLUMN3:
MOVLW .8
;OFFSET VALUE FOR KEY
MOVWF TEMP_KEY ;STORE IN TEMP_KEY
MOVLW B'10111111' ;SET THE COLUMN VALUE (RB6)
MOVWF COL
;INTO COL REGISTER
CALL KEY_PRESS ;GO SEE WHICH ROW IT IS ON
CALL KEY_DOWN? ;MAKE SURE THE KEY IS RELEASED
MOVWF KEY_PRESSED ;MOVE THE KEY PRESSED TO FILE REG
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
COLUMN4:
MOVLW .12
;OFFSET VALUE FOR KEY
MOVWF TEMP_KEY ;STORE IN TEMP_KEY
MOVLW B'01111111' ;SET THE COLUMN VALUE (RB7)
MOVWF COL
;INTO COL REGISTER
CALL KEY_PRESS ;GO SEE WHICH ROW IT IS ON
CALL KEY_DOWN? ;MAKE SURE THE KEY IS RELEASED
MOVWF KEY_PRESSED ;MOVE THE KEY PRESSED TO FILE REG
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
KEY_PRESS:
MOVFW COL
;GET THE COLUMN VALUE
TRIS PORTB
;MAKE THE COLUMN AN OUTPUT
COMF COL,0
;INVERT THE COL REGISTER
MOVWF PORTB ;MAKE THE LINE HIGH ON YOUR COLUMN
call read_again ;check the port for valid data
BTFSC temp_key2,0 ;WAS IT ON ROW 1?
GOTO KEY
;YEP
INCF TEMP_KEY,1 ;INCREMENT KEY VALUE
BTFSC temp_key2,1 ,1 ;WAS IT ON ROW 2?
GOTO KEY
;YEP
INCF TEMP_KEY,1 ;INCREMENT KEY VALUE
BTFSC temp_key2,2 ;WAS IT ON ROW 3?
GOTO KEY
;YEP
INCF TEMP_KEY,1 ;INCREMENT KEY VALUE
BTFSC temp_key2,3 ;WAS IT ON ROW 4?
GOTO KEY
;YEP
BCF INTCON,RBIF ;CLEAR THE INTERRUPT FLAG
call finnish_pad ;
RETFIE
;RETURN FROM INTERRUPT
KEY:
MOVFW TEMP_KEY
;CALL OUT THE VALUE OF THE KEY
ADDWF PCL
;ADD IT TO THE PROGRAM COUNTER
RETDATA "147*2580369#<>YN" ;RETURNS WITH THE KEY PRESSED
;**************************************************************
; THIS CHECKS FOR A KEY DOWN!!
;**************************************************************
KEY_DOWN?:
MOVWF TEMP_KEY ;STORE THE KEY PRESS
CHECK_AGAIN:
MOVLW B'11110000' ;CHECK IF BACK TO NORMAL
SUBWF PORTB,W ; '' '' ''
BTFSS STATUS,Z ;CHECK IF ZERO
GOTO CHECK_AGAIN ;IF NOT THEN LOOP AGAIN
MOVLW B'11111111' ;RESTORE THE KEYPAD TRIS REGISTER
TRIS PORTB
; '' '' ''
MOVFW TEMP_KEY ;RESTORE THE KEY PRESS
RETURN
;************************************************************
; This routine checks the pad for a valid key press
;************************************************************
read_AGAIN:
MOVFW PORTB
;MOVE PORTB VALUE TO W REG
MOVWF TEMP_KEY2 ;SAVE THE PORT READING
MOVLW .250
;DELAY TIME
CALL MDELAY
;DELAY
MOVLW .250
;DELAY TIME
CALL MDELAY
;DELAY
MOVLW .250
;DELAY TIME
CALL MDELAY
;DELAY
MOVFW PORTB
;READ PORT AGAIN
SUBWF TEMP_KEY2,W ;SEE IF IT WAS THE SAME AS A MOMENT AGO
SKPZ
;SKIP NEXT INSTRUCTION IF ZERO
GOTO read_AGAIN ;LOOP UNTIL A BETTER READING IS PRESENT
return
;*****************************************************
; this restores the counters
;******************************************************
finnish_pad:
movfw temp_cnt ;get the cnt value
movwf cnt
;resore it
movfw temp_cnt2 ;get the cnt value
movwf cnt2
;resore it
movfw temp_cnt3 ;get the cnt value
movwf cnt3
;resore it
movfw temp_cnt4 ;get the cnt value
movwf cnt4
;resore it
return
;return