;**************************************************************************
; 4bit.ASM
;
; This is a simple 4 bit counter, writing the result to PORTB...
;
;**************************************************************************

        LIST      P=16F84, R=DEC
        __FUSES   _XT_OSC &  _WDT_OFF & _CP_OFF & _PWRTE_ON
        include   "P16F84.inc"

;--------------------------------------------------------------------------
; Variables
;--------------------------------------------------------------------------

Ram             EQU     h'0C'

Count           EQU     Ram+0
timer_local     EQU     Ram+1



;--------------------------------------------------------------------------
; Program Code
;--------------------------------------------------------------------------

                ORG     0               ;reset vector
Start           call    Init            ;Initialise hardware

Reset           clrf    Count           ;Reset Count
Loop            movfw   Count           ;Move Count into W
                movwf   PORTB           ;Write W to PORTB

                call    Wait1Second     ;Call the 1 second subroutine

                incf    Count,f         ;Count = Count + 1

                movlw   d'16'           ;W = 16
                xorwf   Count,w         ;W = 16 XOR Count
                btfss   STATUS,Z        ;Check the Z flag in the STATUS register
                                        ;Is it set?
                goto    Loop            ; No, so Count <> 16 - keep counting
                goto    Reset           ; Yes, so Count = 16 - reset counter



;--------------------------------------------------------------------------
; Subroutines
;--------------------------------------------------------------------------

;*****Init - set up all ports, make unused ports outputs

Init            clrf    PORTA           ;all of porta low
                clrf    PORTB           ;all of portb low

                bsf     STATUS, RP0     ;change to bank1
                clrf    TRISA           ;all of porta outputs
                clrf    TRISB           ;all of portb outputs
                bcf     STATUS, RP0     ;back to bank0

                return


;*****Timing routines - general purpose delays (4MHz clock)

Wait1ms         movlw   d'250'          ;initial value - tweak if req.
                nop
loop1ms         addlw   d'255'          ;dec w
                btfss   STATUS, Z       ;Zero flag set?
                goto    loop1ms         ;No, keep looping
                return                  ;1ms done

WaitNms         movwf   timer_local     ;timer_local=w
loopNms         movlw   d'248'          ;revised value due to extras
                call    loop1ms         ;248*2+2=994
                goto    $+1             ;+2
                decfsz  timer_local,f   ;dec loop variable - is it Zero?
                goto    loopNms         ;No, keep looping
                return                  ;Nms none

Wait1Second     movlw   d'250'          ;250mS
                call    WaitNms         ;
                movlw   d'250'          ;250mS
                call    WaitNms         ;
                movlw   d'250'          ;250mS
                call    WaitNms         ;
                movlw   d'250'          ;250mS
                goto    WaitNms         ;


                END                     ;Stop assembling here

