
;*******************************
;4x4 Keypad.asm
;4x4 keypad connected to 4 devices
;  22-7-2013 
;*******************************


	list	p=12F629
	radix	dec
	include	"p12f629.inc"
	
		errorlevel	-302	; Dont complain about BANK 1 Registers during assembly

	__CONFIG	_MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT  ;Internal osc.

;_MCLRE_OFF  - master clear must be off for gp3 to work as input pin 

;****************************************************************
; variables - names and files
;****************************************************************

		Cblock  20h
temp1		    ;used in delays
temp2			;used in delays
temp3			;used in delays
temp4           ;used to generate key value
temp16          ;16 keys
flashes		    ;LED flashes to indicate key number
loops 
SwFlags      

        endc

;****************************************************************
;Equates
;****************************************************************
status		equ	0x03
rp1			equ	0x06
rp0			equ	0x05
GPIO 		equ 0x05
			

status		equ	03h
option_reg	equ 81h


		; bits on GPIO
				
pin7		equ	0	;GP0  LED - flashes to indicate key number
pin6	 	equ	1	;GP1  Relay
pin5		equ	2	;GP2  Piezo Buzzer 
pin4		equ	3	;GP3  not used
pin3		equ	4	;GP4  Motor
pin2		equ	5	;GP5  4x4 Keypad switches   
 

		;bits
				
rp0			equ	5			;bit 5 of the status register



;****************************************************************
;Beginning of program
;****************************************************************
		org		0x00
		nop
		nop
		nop
		nop
		nop			
SetUp	bsf		status, rp0 	;Bank 1			
       	movlw	b'11001000'		;Set TRIS GP0,1,2,4,5 out   GP3 not used
		movwf	TRISIO	
		bcf		status, rp0		;bank 0
		movlw   07h         	;turn off Comparator ports
        movwf   CMCON       	;must be placed in bank 0  
		clrf 	GPIO       		;Clear GPIO of junk	- turn off all devices		
		movlw	4Fh             ;start of GPR's
		movwf	fsr
		call    NoKey           ;see if a switch is pressed
		btfss   SwFlags,1       ;test bit1 for switch pressed
		goto    SetUp2          ;load 50h to 5Fh from EEPROM
		call    GenKeyvalue     ;to see if key16 is pressed before start-up.
		movlw   0CFh             ;Put a value into W and perform SUBWF
		subwf   loops,1         ;Carry flag is CLEAR if W is greater than file value 
        btfsc   03,c            ;Test carry flag 
		goto    SetUp2		
		movlw   .16
		movwf   temp16          ;for 16 keys
		
		call    NoKey           ;test bit1 for switch pressed - ----
		btfsc   SwFlags,1       ;detect no key pressed for debounce	
		goto    $-2             ;
		bsf     gpio,0          ;Key not pressed - flash LED briefly
		call    _10mS
		bcf     gpio,0
		call    _10mS
		
		call    NoKey           ;test bit1 for switch pressed 
		btfss   SwFlags,1       ;detect key pressed for debounce	
		goto    $-2
			
		call    GenKeyvalue     ;Key pressed  - get number of loops 
					
    	incf	fsr,f	        ;fsr starts at file 50h   Store 16 key-values
		movf    loops,w         ;move number of loops into w
		movwf	indf	        ;put loops into file 50h to 5Fh
		decfsz	temp16,f
		goto    $-.15
		
		call    toEEPROM        ;put 16 values into EEPROM
		
		bsf     gpio,0          ;added
		call    _500mS
		bcf     gpio,0
		call    _500mS
		goto    $-4            ;keeps flashing - turn off project        
		
		 

         ;load files 50h to 5Fh with key values from EEPROM
         

SetUp2  
		bsf		status,rp0	;select bank1	
		clrf	eeadr		;start EEPROM at location 0				
		bcf		status,rp0	;select bank0		
		movlw   .16
		movwf   temp16      ;for 16 keys
		movlw	4Fh         ;start of GPR's
		movwf	fsr
		incf	fsr,f	    ;fsr starts at file 50h	
		bsf		status,rp0										
		bsf		EECON1,0	;starts EEPROM read operation storing result in EEDATA						
		movf	EEDATA,w	;move read data into w
		bcf		status,rp0				
		movwf	indf	    ;put EEPROM data into file 50h to 5Fh
		bsf		status,rp0	;select bank1	
		incf	eeadr,1						
		bcf		status,rp0	;select bank0
		decfsz	temp16,f
		goto	$-.10
		goto    Main		
		

;********************
;* Delays 			*
;********************

_uS     movlw   7h
        movwf   temp1
		decfsz 	temp1,f
        goto 	$-1			
		retlw 	00
		
		
		
_10mS	movlw	0Ah
		movwf	temp2
_10		nop
		decfsz 	temp1,f
		goto 	_10
		decfsz 	temp2,f
		goto 	_10	
		retlw 	00		
		


_100mS	movlw	.100
		movwf	temp2
_100	nop
		decfsz 	temp1,f
		goto 	_100
		decfsz 	temp2,f
		goto 	_100	
		retlw 	00	
		
		

		
_500mS	movlw   5			
		movwf   temp3
		call	_100mS		
		decfsz  temp3,1
		goto    $-2
		retlw   00

;****************************
;* Sub Routines 			*
;****************************
	
	
Device1
		movlw 	01h
        xorwf   gpio,1  ;XOR 01 with gpio, lowest line (GP0) 
        retlw   00      ;toggles line gpio,0
	
Device2
		movlw 	02h
        xorwf   gpio,1  ;XOR 01 with gpio, lowest line (GP1) 
        retlw   00    ;toggles line gpio,1

Device3
		movlw 	04h
        xorwf   gpio,1  ;XOR 01 with gpio, lowest line (GP2) 
        retlw   00    ;toggles line gpio,2

Device4
		movlw 	10h
        xorwf   gpio,1  ;XOR 01 with gpio, lowest line (GP4) 
        retlw   00    ;toggles line gpio,4

	
	
  
        ;detect key16 at start-up to generate key-loops for storage in EEPROM
	    ;this sub-routine also detects a pressed-key and
	    ;returns with a value in "loops"
			
GenKeyvalue				
		clrf    loops      	
		bsf		status, rp0 	;Bank 1	    	
		bcf 	TRISIO,5	    ;clear bit GPIO,5 as output to charge cap.
		bcf		status, rp0		;bank 0
		bsf		gpio,5			;make pin2 HIGH to charge cap. 
		call	_10mS           ;charge cap	
		call	_10mS           ;charge cap	
		call	_10mS           ;charge cap	
			
		bsf		status, rp0 	;Bank 1			
       	bsf 	TRISIO,5	   	;set TRIS GP0,5 to detect discharged cap		
		bcf		status, rp0		;bank 0	
		movf    gpio,w
		movwf   temp3
		clrf    gpio            ;turn off outputs while detecting		
		call	_uS		
		incf    loops,1
		btfsc   gpio,5
		goto	$-3  
		movf    temp3,w
		movwf   gpio            ;re-instate output port         
		retlw   00              ;return with value in loops
	
	
	;Key_Yes returns SwFlags,7 when file 50h to 5Fh is correct key 
	;temp4 will already contain file 50h to 5Fh
	;GenKeyvalue  generates current loops value and compares with
	;files 50h to 5Fh
		
		
Key_Yes		
		bcf     SwFlags,7
		call    GenKeyvalue     ;value of key in loops
		movf    loops,w         ;put loops into w
		xorwf   temp4,w
		btfsc   03,z
		goto    bb              ;key found
		incf    temp4,f         ;try one value higher
		movf    loops,w         ;put loops into w again
		xorwf   temp4,w
		btfsc   03,z
		goto    bb 
		decf    temp4,f         ;try one value lower
		decf    temp4,f  
		movf    loops,w         ;put loops into w again
		xorwf   temp4,w
		btfss   03,z
		retlw   00              ;key not found		
bb		bsf     SwFlags,7
        retlw   00


		
		
		
		
	;NoKey - detect no key pressed 
	
	
NoKey	bcf     SwFlags,1
		bsf		status, rp0 	;Bank 1	 (see if switch is pressed)      	
		bcf 	TRISIO,5	    ;clear bit GPIO,5 as output to charge cap.
		bcf		status, rp0		;bank 0
		bsf		gpio,5			;make pin2 HIGH to charge cap. 
		call	_10mS           ;charge cap		
		bsf		status, rp0 	;Bank 1			
       	bsf 	TRISIO,5	   	;set TRIS GP0,5 to detect discharged cap		
		bcf		status, rp0		;bank 0					
		call	_10mS		
		btfsc   gpio,5
        retlw	00				;no switch pressed
        bsf     SwFlags,1
	    retlw	00	            ;key pressed - bsf SwFlags,1
		
		
		;ShowKey shows the key value via LED flashes
ShowKey		
		bsf     gpio,0          ;
		call    _500mS
		bcf     gpio,0
		call    _500mS
		decfsz  flashes,1
		goto    $-5            ;
		goto    Main
		
		
		;TestKeys is a test routine that flashes the key number
		
TestKeys

        clrf    loops
        clrf    flashes
        movlw	50h             ;start of GPR's
		movwf 	fsr
aa     	incf    flashes,1
		call    GenKeyvalue     ;value of key in loops
		movf    indf,w          ;put contents of 50h into w
		movwf   temp4
		xorwf   loops,w
		btfsc   03,z
		goto    ShowKey	        ;flashes = 1
		decf    temp4,f          ;try one value less
		movf    temp4,w
		xorwf   loops,w
		btfsc   03,z
		goto    ShowKey	        ;flashes = 1
		incf    temp4,f          ;try one value higher
		incf    temp4,f 
		movf    temp4,w
		xorwf   loops,w
		btfsc   03,z
		goto    ShowKey
		incf    fsr		
		movlw   16
		xorwf   flashes,w
		btfsc   03,z
		goto    aa
		retlw   00
			
		    
		
		;after 16 keys  . . . .
		;put number of loops in 50h to 5Fh into EEPROM	
				
		
toEEPROM
		bsf		status,rp0	;select bank1	
		clrf	eeadr		;start EEPROM at location 0				
		bcf		status,rp0	;select bank0		
		movlw   .16
		movwf   temp16      ;for 16 keys
		movlw	4Fh         ;start of GPR's
		movwf	fsr
		incf	fsr,f	    ;fsr starts at file 50h
		movf	indf,w	    ;retreive data in file 50h to5Fh
		bsf		status,rp0	;select bank1	
		movwf	eedata		; 
		bcf		status,rp0	;select bank0
		call 	write
		bsf		status,rp0	;select bank1	
		incf	eeadr,1						
		bcf		status,rp0	;select bank0
		decfsz	temp16,f
		goto	$-10
		retlw   00
		
		
write	bsf		status,rp0	;select bank1	
		bsf		eecon1,wren	;enable write		
		movlw	55h 		;unlock codes
		movwf	eecon2
		movlw	0aah
		movwf	eecon2
		bsf		eecon1,wr	;write begins
		bcf		status,rp0	;select bank0		
writeA	btfss	pir1,eeif	;wait for write to complete
		goto	writeA
		bcf		pir1,eeif
		bsf		status,rp0	;select bank1
		bcf		eecon1,wren	;disable other writes
		bcf		status,rp0	;select bank0					
		retlw	00			
		
	

;************************************
;* Main 							*
;************************************

Main	
		call    NoKey           ;test SwFlags,1 for switch pressed 
		btfss   SwFlags,1       ;detect key pressed for debounce	
		goto    $-2				;key not pressed
			
		movf    50h,w           ;is key 1 pressed?
		movwf   temp4	        ;set-up temp4 for Key_Yes 
		call    Key_Yes
		btfsc   SwFlags,7 
		call    Device1			;LED	
				
		
		movf    51h,w           ;is key 2 pressed?
		movwf   temp4	        ;set-up temp4 for Key_Yes 
		call    Key_Yes
		btfsc   SwFlags,7 
		call    Device2			;globe	
		
		
		movf    52h,w           ;is key 3 pressed?
		movwf   temp4	        ;set-up temp4 for Key_Yes 
		call    Key_Yes
		btfsc   SwFlags,7 
		call    Device3			;piezo buzzer	
	
		movf    53h,w           ;is key 4 pressed?
		movwf   temp4	        ;set-up temp4 for Key_Yes 
		call    Key_Yes
		btfsc   SwFlags,7 
		call    Device4			;motor	
		call    NoKey           ;test bit1 for switch pressed 
		btfsc   SwFlags,1       ;detect key pressed for debounce	
		goto    $-2				;key  pressed		
		
	    goto    Main            
	      
	   	    
		
;****************************************************************
;*EEPROM     						*
;****************************************************************
								
		org		2100h	;16 locations 00 to 0F		
							
					
							
		END
		
		