;**********************************************************************
;   This file contains an example of how to set up a PIC16F874 to     *
;   use Timer 0 with interrupts.  Port B bit 0 will be used to output *
;   a high value at the start of a pulse-measuring sequence.  The goal*  
;   is to make it high for 750 us on a PIC with a 10 MHz crystal      *
;   oscillator.  The main program will make the pulse hight; the      *
;   interrupt service routine will make it low when it gets control.  *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:	    TMR0Exampl.asm                                    *
;    Date:          February 13, 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

TMR0_PRESCALER EQU	B'00000111'	; Designates the prescaler bits of OPTION_REG
TMR0_PRESCALER_INIT EQU D'2'		; Divide the crystal oscillator frequency by
								; 2^(2+1)=8 to yield a 3.2 us interval
								; between Timer 0 clock ticks (400 ns
								; instruction period)
TMR0_INIT	EQU D'234'			; 234 clock ticks yields 748.8 us, close to
								; the desired 750 us.
								
TRISB_mask equ B'00000000'	; Make RB0/INT an output pin
OutputBit	equ 0			; Points to bit 0 of Port B, the output bit


;**********************************************************************
		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,T0IF			; Check for an RB0/INT interrupt
		call	handle_TMR0


		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
	
	; Initialize Port B
	bcf		STATUS,RP1	; Select Bank 1
	bsf		STATUS,RP0	
	movlw	TRISB_mask
	movwf	TRISB
	
	; Initialize options for Timer 0
	bcf		OPTION_REG,T0CS		; Choose the oscillator input to Timer 0
	bcf		OPTION_REG,PSA		; Assign prescaler to Timer 0
	movlw	~TMR0_PRESCALER		; Clear prescaler bits
	andwf	OPTION_REG,F
	movlw	TMR0_PRESCALER_INIT	; Load prescaler setting
	iorwf	OPTION_REG,F

	bcf		STATUS,RP0	; Select Bank 0 again
	
	; Enable Timer 0 Interrupts
	bsf	INTCON,T0IE	; Enable Timer 0 interrupts
	bcf	INTCON,T0IF	; Clear the interrupt flag initially
	; Enable interrupts generally
	bsf	INTCON,GIE

loop	; This is the repetitive part of the program.
	; The normal, mundane task is to watch Port B, bit OutputBit.
	; When it becomes a 0 (under interrupt service routine
	; control), make it a 1 again and repeat
	bsf	PORTB,OutputBit
	movlw	-TMR0_INIT
	movwf	TMR0
WaitForLowOutput
	btfsc	PORTB,OutputBit
	goto	WaitForLowOutput
	goto	loop
	
; This is the interrupt service routine for the Timer 0 interrupt
; It should clear the OutputBit of Port B and return
handle_TMR0
	bcf		PORTB,OutputBit
	
end_of_handle_handle_TMR0
	bcf	INTCON,T0IF	; Clear the interrupt flag to avoid
						; recursive interrupts
	return
		END                       ; directive 'end of program'


