; 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 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