;******************************************************************
; (C) K8LH 2-Digit Up/Dn Counter, Isochronous Loop Example v2 *
;******************************************************************
processor PIC16F88
include "p16f88.inc"
errorlevel -302
__CONFIG _CONFIG1, _LVP_OFF&_WDT_OFF&_INTRC_IO&_MCLR_OFF
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
number equ 0x20 ; packed BCD, 0x00..0x99
swlatch equ 0x21 ; switch state latch variable
swflags equ 0x22 ; switch flag bits
DelayHi equ 0x23 ; DelayCy() subsystem variable
#define Dn 3 ; RA3
#define Up 2 ; RA2
;******************************************************************
;
; K8LH DelayCy() subsystem macro generates four instructions
;
radix dec
clock equ 8 ; clock frequency in Megahertz
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf DelayHi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
;
; init hardware and program variables
;
org 0x000
Init
bsf STATUS,RP0 ; bank 1 |B1
movlw b'01110000' ; |B1
movwf OSCCON ; select 8-MHz INTOSC clock |B1
Stable btfss OSCCON,IOFS ; INTOSC Freq Stable bit set? |B1
goto Stable ; no, branch, else |B1
clrf ANSEL ; setup PORT A for digital I/O |B1
movlw b'00001100' ; |B1
movwf TRISA ; RA3-RA2 inputs, others outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
movlw b'00000001' ; digit select bits (RA1-RA0) |B0
movwf PORTA ; select the 'ones' display |B0
clrf swlatch ; clear switch state latch |B0
clrf swflags ; clear switch flags |B0
clrf number ; number = 00 |B0
;
; isochronous 8 msec program loop (62.5 Hz display refresh rate)
;
Display
clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
xorlw b'00000011' ; flip digit select bits |B0
movwf PORTA ; |B0
swapf number,W ; W = tens in right nybble |B0
btfss PORTA,1 ; 10's display? yes, skip, else |B0
movf number,W ; W = ones in right nybble |B0
call segtbl ; get segment data |B0
movwf PORTB ; display new digit |B0
Buttons
comf PORTA,W ; sample active low switches |B0
andlw b'00001100' ; on RA3 and RA2 pins |B0
xorwf swlatch,W ; changes (press or release) |B0
xorwf swlatch,F ; update switch state latch |B0
andwf swlatch,W ; filter out "new release" bits |B0
movwf swflags ; save any "new press" bits |B0
CountUp
movf number,W ; |B0
addlw 7 ; increment + bcd adjust? |B0
skpdc ; yes, skip, else |B0
addlw -6 ; increment only |B0
btfsc swflags,Up ; Up press? no, skip, else |B0
movwf number ; update 'number' |B0
movf number,W ; |B0
xorlw 0xA0 ; upper limit 99? |B0
skpnz ; no, skip, else |B0
clrf number ; reset to 00 (rollover mode) |B0 <-
CountDn
movf number,W ; lower limit 00? |B0
skpnz ; no, skip, else |B0
movlw 0xA0 ; reset to 99 (rollover mode) |B0 <-
addlw -1 ; decrement only? |B0
skpdc ; yes, skip, else |B0
addlw -6 ; decrement + bcd adjust |B0
btfsc swflags,Dn ; Dn press? no, skip, else |B0
movwf number ; update 'number' |B0
DelayCy(8*msecs-41) ; precise 8 msec loop timing |B0
goto Display ; loop |B0
;
; segment data table (caveat, non-boundary tolerant)
;
segtbl
andlw 0x0F ; strip off upper nybble |B0
addwf PCL,F ; |B0
retlw b'00111111' ; "0" -|-|F|E|D|C|B|A |B0
retlw b'00000110' ; "1" -|-|-|-|-|C|B|- |B0
retlw b'01011011' ; "2" -|G|-|E|D|-|B|A |B0
retlw b'01001111' ; "3" -|G|-|-|D|C|B|A |B0
retlw b'01100110' ; "4" -|G|F|-|-|C|B|- |B0
retlw b'01101101' ; "5" -|G|F|-|D|C|-|A |B0
retlw b'01111101' ; "6" -|G|F|E|D|C|-|A |B0
retlw b'00000111' ; "7" -|-|-|-|-|C|B|A |B0
retlw b'01111111' ; "8" -|G|F|E|D|C|B|A |B0
retlw b'01101111' ; "9" -|G|F|-|D|C|B|A |B0
;
; K8LH DelayCy() subsystem 16-bit timing subroutine
;
nop ; entry for (delay-11)%5 == 4 |B0
nop ; entry for (delay-11)%5 == 3 |B0
nop ; entry for (delay-11)%5 == 2 |B0
nop ; entry for (delay-11)%5 == 1 |B0
uDelay addlw -1 ; subtract "loop" cycle time |B0
skpc ; borrow? no, skip, else |B0
decfsz DelayHi,F ; done? yes, skip, else |B0
goto uDelay ; do another loop |B0
return ; |B0
end