;**********************************************************************
;   This file contains an example of how to set up a PIC16F874 to     *
;   handle interrupts.  Port B bit 0 (the RB0/INT bit) will be used   *
;   by an external circuit to request attention from the PIC.  When   *  
;   a falling edge arrives on that pin, an interrupt will be          *
;   and the PIC will stop doing its main task, instead invoking the   *
;   interrupt service routine.                                        *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:	    SampleISR.asm                                     *
;    Date:          February 10, 2006                                 *
;    File Version:  1                                                 *
;                                                                     *
;    Author:        CDR Charles B. Cameron                            *
;    Company:       United States Naval Academy                       *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files required: p16f874.asm                                      *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:         None                                              *
;                                                                     *
;**********************************************************************


	list      p=16f874            ; list directive to define processor
	#include <p16f874.inc>        ; processor specific variable definitions
	
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF

; '__CONFIG' directive is used to embed configuration data within .asm file.
; Watch dog timer is disabled.

;***** VARIABLE DEFINITIONS
w_temp        EQU     0x20        ; variable used for context saving 
status_temp   EQU     0x21        ; variable used for context saving

a_init	equ	D'9'	; Initial value for variable a
a		equ H'22'	; Storage for variable a
bb_init	equ	D'252'	; Initial value for variable bb
bb		equ H'23'	; Storage for variable bb

TRISB_mask equ B'00000001'	; Make RB0/INT an input pin
OPTION_REG_mask equ B'01000000' ; This mask indicates the INTEDG bit
								; of OPTION_REG.  We'll clear this bit
								; to force interrupts on falling edge
								; of RB0/INT.


;**********************************************************************
		ORG     0x000             ; processor reset vector
		clrf    PCLATH            ; ensure page bits are cleared
  		goto    main              ; go to beginning of program


		ORG     0x004             ; interrupt vector location
		movwf   w_temp            ; save off current W register contents
		movf	STATUS,w          ; move status register into W register
		bcf     STATUS,RP0        ; ensure file register bank set to 0
		movwf	status_temp       ; save off contents of STATUS register


; isr code can go here or be located as a call subroutine elsewhere
		btfsc	INTCON,INTF		; Check for an RB0/INT interrupt
		call	handle_INT


		bcf     STATUS,RP0        ; ensure file register bank set to 0
		movf    status_temp,w     ; retrieve copy of STATUS register
		movwf	STATUS            ; restore pre-isr STATUS register contents
		swapf   w_temp,f
		swapf   w_temp,w          ; restore pre-isr W register contents
		retfie                    ; return from interrupt



main

; Initialization
	movlw	a_init	; Initialize a
	movwf	a
	movlw	bb_init	; Initialize bb
	movwf	bb
	
	; Initialize Port B
	bcf		STATUS,RP1	; Select Bank 1
	bsf		STATUS,RP0	
	movlw	TRISB_mask
	movwf	TRISB
	; Use the OPTION_REG_mask to clear the INTEDG bit
	movlw	~OPTION_REG_mask
	andwf	OPTION_REG,F
	bcf		STATUS,RP0	; Select Bank 0 again
	
	; Enable the RB0/INT Interrupt
	bsf	INTCON,INTE
	; Enable interrupts
	bsf	INTCON,GIE

loop	; This is the repetitive part of the program.
	; The normal, mundane task is to decrement variable a
	; Whenever it reaches 0, re-initialize it using a_init
	decfsz	a,F
	goto	loop
	;Re-initialize a whenever it reaches 0
	movlw	a_init	; Initialize a
	movwf	a
	goto	loop
	
; This is the interrupt service routine for the RB0/INT interrupt
; It should increment variable bb.  When the variable reaches 0,
; it should re-initialize it using bb_init. 
handle_INT
	incfsz	bb,F
	goto end_of_handle_INT
	movlw	bb_init
	movwf	bb
	
end_of_handle_INT
	bcf	INTCON,INTF	; Clear the interrupt flag to avoid
					; recursive interrupts
	return
		END                       ; directive 'end of program'


