;** Dragonfly Clock HH:MM.SS uses the 32768Hz crystal with flashing colon
list p=16F886
include <p16F886.inc>
__CONFIG _CONFIG1, _DEBUG_ON & _WDT_OFF & _LVP_OFF & _INTOSCIO
errorlevel -302,-305
cblock 0x20
Digit:6
Jiffy ; 1/256 second timebase
HalfSec
Minutes
Hours
DigSel ; which digit 0-5 (left to right)
Tens
Ones
endc
#define Rst4022 PORTC,5
#define Clk4022 PORTC,2
org 0
nop
goto Init
org 4
goto _512
_Seg addwf PCL
dt b'00111111' ; "0"
dt b'00000110' ; "1"
dt b'10011011' ; "2"
dt b'10001111' ; "3"
dt b'10100110' ; "4"
dt b'10101101' ; "5"
dt b'10111101' ; "6"
dt b'00000111' ; "7"
dt b'10111111' ; "8"
dt b'10101111' ; "9"
_512 incfsz Jiffy ; 1/512 second refresh clock
goto _DoDisp
_Sec incf HalfSec ; .5 second increments
movlw .119
subwf HalfSec,w
bnc _UpSec
clrf HalfSec ; zero the half seconds
_Min incf Minutes ; 0-59 minutes
movlw .59
subwf Minutes,w
bnc _UpMin
clrf Minutes
_Hrs incf Hours
movlw .23
subwf Hours,w
skpnc
clrf Hours ; 0-23 hours
_UpHrs movlw Digit
addlw .1
movwf FSR
incf Hours,w ; 1-24 hours
call _DecBCD
decf Tens,w
skpnz
clrf Digit ; blank lead digit (tens of hours)
_UpMin movlw Digit ; point to seconds (ones)
addlw .3
movwf FSR ;
movfw Minutes
call _DecBCD
btfsc Digit+2,7 ; digit 3 dp / G transpose
bsf Digit+2,6
bcf Digit+2,7
_UpSec movlw Digit ; point to seconds (ones)
addlw .5
movwf FSR ;
clrc ; make sure carry is clear
rrf HalfSec,W ;
call _DecBCD
btfsc Digit+5,7 ; digit 6 dp / G transpose
bsf Digit+5,6
bcf Digit+5,7
_Colon bsf Digit+3,6 ; turn on digit 4 colon
bcf Digit+1,6
bcf Digit+2,7
btfsc HalfSec,0
goto _DoDisp
bsf Digit+1,6
bsf Digit+2,7
;*** refresh each digit 512 times per second
_DoDisp clrf PORTB ; blank display ABCDEF
movlw b'00111111'
andwf PORTA ; blank display dp G
incf DigSel ; increment to 6 then reset
movlw .6 ; W = 6 (number of digits)
subwf DigSel,w ; is DigSel < 6
bnc _disp ; yes then proceed normally
_reset bsf Rst4022 ; no then reset the 4022 counter (1)
clrf DigSel ; clear the digit count
bcf Rst4022 ; enable the 4022 counter
_disp bsf Clk4022 ; 4022 latch on rising edge
movlw Digit
addwf DigSel,w
movwf FSR ; point to display charater
movfw INDF
movwf PORTB
andlw b'11000000' ; mask off low six bits
iorwf PORTA ; segment G on (normal)
bcf Clk4022
bcf PIR1,CCP1IF ; clear the interrupt flag
retfie
;*** Decimal to BCD enter with byte 0-99 returns Ones
_DecBCD movwf Ones
clrf Tens
_10s incf Tens
movlw .10 ; load the constant 10
subwf Ones,f ; subtract 10 and save result
bc _10s ; check if answer negative
movlw .10
addwf Ones,w ; W = Ones + 10
call _Seg ; get the
movwf INDF ; save ones to display
decf FSR ; next digit Tens (left)
decf Tens,W ; W = Tens -1
call _Seg ; convert to seven segment
movwf INDF ; save tens to display
return
Init movlw b'00001011' ; osc on, sync,
movwf T1CON ; enable external OSC on TMR1
movlw low(.64-1) ; 32768 / 512
movwf CCPR1L
movlw high(.64-1)
movwf CCPR1H
movlw b'00001011' ; special CCP timer compare & reset
movwf CCP1CON
banksel ANSEL ;B3
clrf ANSEL ;B3 all ports digital
banksel TRISA ;B1
movlw b'00011111'
movwf TRISA ;B1 LED1
movlw b'11000000'
movwf TRISB
movlw b'11011011'
movwf TRISC
bsf PIE1,CCP1IE ;B1 enable CCP1 interupt
bcf STATUS, RP0 ;B0
movlw b'11111011' ; clock low and reset high
movwf PORTC ; 4022 clock low & Reset high
clrf DigSel
movlw .119 ; cause clock to overflow on reset
movwf HalfSec
movlw .59
movwf Minutes
movlw .10 ; start the clock at 11:59:59
movwf Hours
movlw b'11000000' ; Enable GIE PIE
movwf INTCON
bcf Rst4022 ; enable the 4022
Loop goto $
end