;**********************************************************************
;   This file is a sample showing how to do interrupt processing on   *
;   the PIC16F874.                                                    *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:       testinterrupts.asm                               *
;    Date:           17 February 2004                                 *
;    File Version:   1                                                *
;                                                                     *
;    Author:        CDR Charles B. Cameron                            *
;    Company:       United States Naval Academy                       *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files required:                                                  *
;                                                                     *
;                  p16f874.inc                                        *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;       This program sets up Timer 2 to generate an interrupt every   *
;       40 us.  The ISR counts four such interrupts and toggles       *
;       Bit 0 of Port B.  Since this bit toggles every 160 us, the    *
;       period is twice this, or 320 us, making a frequency of        *
;       3.125 kHz for Bit 0.  All these times are dependent on the    *
;       crystal oscillator running at 4 MHz.                          *
;**********************************************************************


    list      p=16f874,b=4        ; list directive to define processor
    #include <p16f874.inc>        ; processor specific variable definitions
    
    __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF

; Turn code protection off, watch dog timer off,
; brown-out reset disabled, power-up timer enabled, HS oscillator mode selected,
; flash program memory write disabled, low-voltage in-circuit serial programming
; disabled, and data EE memory code protection off.


;***** VARIABLE DEFINITIONS
w_temp            equ     0x20        ; variable used for context saving 
status_temp       equ     0x21        ; variable used for context saving
Timer2Count       equ     0x22        ; used to count Timer 2 interrupts

; With the postscaler = 5, prescaler = 1, and PR2 = 8, we get
; 5 x 1 x 8 = 40 instruction cycles, or 40 us, between interrupts
T2CON_Init        equ     B'00100000' ; 1:5 Postscale, TM2OFF, Prescaler = 1
PR2_Init          equ     D'8'        ; TMR2 rolls over after 8 increments

PIE1_Init         equ     B'00000010' ; Mask pointing to the TMR2IE bit of PIE1
INTCON_Init       equ     B'11000000' ; Mask pointing to GIE and PEIE of INTCON
LEDToggleBit      equ     B'00000001' ; Mask for toggling bit 0 of PORTB
TRISB_Init        equ     B'00000000' ; Make all bits of PORT B output bits
Timer2MagicNumber equ     D'4'        ; We'll count 4 Timer 2 interrupts.
                                      ; This represents 160 us between occasions
                                      ; when Port B Bit 0 is toggled, giving a
                                      ; period of 320 us in all, or a frequency
                                      ; of 3.125 kHz.



;**********************************************************************
        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


        ; Check for TMR2 interrupt
        btfsc    PIE1,TMR2IF
        call    Handle_Timer2
        

        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

; Initialize Timer 2
    ; Initialize TMR2
        clrf     TMR2
    ; Initialize T2CON
        movlw    T2CON_Init
        movwf    T2CON
    ; Initialize PR2
        bsf      STATUS,RP0    ; Bank 1
        movlw    PR2_Init
        movwf    PR2
    ; Initialize PIE1
        movlw    PIE1_Init
        iorwf    PIE1,F
        bcf      STATUS,RP0    ; Bank 0-
    ; Initialize INTCON
        movlw    INTCON_Init
        iorwf    INTCON,F
    ; Start Timer 2
        bsf      T2CON,TMR2ON
        
; Initialize the Port B direction bits
        bsf      STATUS,RP0    ; Bank 1
        movlw    TRISB_Init
        movwf    TRISB
        bcf      STATUS,RP0    ; Bank 0
        
loop
    ; This loop doesn't do anything.  The main point of
    ; this program is to illustrate interrupt processing.
    goto    loop

Handle_Timer2
    ; Increment counter of timer 2 interrupts
        incf    Timer2Count,F
    ; Have we reached the magic number yet?
        movlw    Timer2MagicNumber
        subwf    Timer2Count,W
        btfss    STATUS,Z
        goto     EndOfTimer2        ; No
    ; Reinitialize Timer2Count      ; Yes
        clrf     Timer2Count
    ; Toggle output bit
        movlw    LEDToggleBit
        xorwf    PORTB,F
    
EndOfTimer2
    ; Clear Timer 2 interrupts so that another Timer 2 
    ; interval can ensue
        bcf      PIR1,TMR2IF
        return

    END                       ; directive 'end of program'

