;This program demonstrates the wake-up on Keystroke feature of the
;PIC16C71. Port B pins RB4 - RB7 can be configured as inputs with internal
;pull up resistors, also the interrupt associated with the change on input
;on RB4 - RB7 can be set up to wake the chip from sleep. If the 
;global interrupt is enabled just before sleep, the program will vector to
;the interrupt vector (0004). If not the chip will continue execution
;just after the next instruction following sleep.
;In this example code, the port B is initalized to input 4 push-buttons at
;RB4 - RB7. RB0 - RB3 are configured to drive LEDs corresponding to
;which push-button is hit (LED on RB0 when RB4 is hit and so on).
;Sleep is executed. When any keys is hit, the processor wakes
;up and jumps to the interrupt vector. The corresponding LED is 
;turned on and after the key is released, the whole process is repeated.
;
;
;       Program:          WAKEUP.ASM 
;       Revision Date:   
;                         1-16-97      Compatibility with MPASMWIN 1.40
;
;******************************************************************************
;
	LIST P=16C71
;
z       equ     2
RBPU    equ     7
temp    equ     10h
OptionReg  equ     1h
F       EQU     1
;
	include "p16c71.inc"
;
	org     0
	goto    start
;
	org     4
	goto    ServiceInterrupt
;
;
start
	call    InitPortB       ;initalize port B
loop
;        sleep                   ;sleep till key is hit
	nop
	goto    loop
;
ServiceInterrupt
	btfsc   INTCON,RBIF     ;change on rb int?
	goto    ServiceWakup    ;yes then service
	bcf     INTCON,T0IE     ;clear TMR0 int mask
	bcf     INTCON,T0IF     ;clear flag
	return
;
;This routine checks which keys is hit and lights up the
;corresponding LED associated with it. eg. RB0's LED when
;RB4's key is pressed. Finally it waits till all keys have 
;been released before returning form the service routine.
ServiceWakup
	bcf     INTCON,RBIE     ;clear mask
	comf    PORTB,W        ;read PORTB
	bcf     INTCON,RBIF     ;clear flag
	call    delay16         ;do de-bounce for 16mSecs
	comf    PORTB,W        ;read port B again
	andlw   B'11110000'     ;mask outputs
	movwf   temp            ;save in temp
	swapf   temp,W          ;switch low and high
	movwf   PORTB          ;send as outputs.
	call    KeyRelease      ;check for key release
	retfie
;
;This sub-routine, waits till all key have been released
;In order to save power, the chip is in sleep mode till
;all keys are released.
KeyRelease
	call    delay16         ;do debounce
	comf    PORTB,W        ;read PORTB
	bcf     INTCON,RBIF     ;clear flag
	bsf     INTCON,RBIE     ;enable mask
	andlw   B'11110000'     ;clear outputs
	btfsc   STATUS,z        ;key still pressed?
	return                  ;no then return
	sleep                   ;else save power
	bcf     INTCON,RBIE     ;on wake up clear mask
	comf    PORTB,W
	bcf     INTCON,RBIF     ;clear flag
	goto    KeyRelease      ;try again
;
;
;This sub-routine, initializes PortB.
InitPortB
	bsf     STATUS,RP0      ;select bank 1
	movlw   B'00000011'     ;Port_A digital I/O
	movwf   ADCON1          ;               /
	movlw   0               ;
	movwf   PORTA          ;set port a as outputs
	movlw   B'11110000'     ;RB0-RB3 outputs
	movwf   PORTB          ;RB4-RB7 inputs
	bcf     OptionReg,RBPU  ;enable pull up
	bcf     STATUS,RP0      ;select page 0
	clrf    PORTB          ;init port B
	clrf    PORTA          ;make port a all low
	bsf     PORTA,0        ;make first bit high
	bcf     INTCON,RBIE     ;disable mask
	movf    PORTB,W        ;read port
	bcf     INTCON,RBIF     ;clear flag
	bsf     INTCON,RBIE     ;enable mask
	retfie                  ;enable global and return
;
;delay16 waits for approx 16.4mSecs using TMR0 interrupts
;fosc speed is 4Mhz.
delay16
	bsf     STATUS,RP0      ;select page 1
	movlw   B'00000111'     ;fosc/256 --> TMR0
	movwf   OptionReg       ;       /
	bcf     STATUS,RP0      ;select page 0
	clrf    TMR0
	bcf     INTCON,T0IF     ;clear flag
	bsf     INTCON,T0IE     ;enable mask
CheckAgain
	btfss   INTCON,T0IF     ;timer overflowed?
	goto    CheckAgain      ;no check again
	bcf     INTCON,T0IE     ;else clear mask
	bcf     INTCON,T0IF     ;clear flag
	return
;
	end



	



