0                GOTO MAIN                  ;***** An Unusual Clock *****
1                NOP                        ;uses 12 LED's in hour positions
2                NOP                        ;anodes to RB0-RB7,RA0-RA3 thru 1K
3                NOP                        ;MCLR and RA4 to +5 thru 10K
4                NOP                        ;RA4 to gnd thru NO SPST pushbutton
5                NOP                        ;4Mhz crystal with 33pf caps to gnd
6                NOP                        ;***** initilization routine *****
7    INIT        CLRF HIHOUR                ;top 4 bits of hour position
8                CLRF LOHOUR                ;lo 8 bits of hour position
9                INCF LOHOUR,f              ;put a 1 in lowest position
10               CLRF HIMIN5                ;top 4 bits of minutes5 position
11               CLRF LOMIN5                ;low 8 bits of minutes5 position
12               INCF LOMIN5,f              ;put a 1 in lowest position
13               MOVLW $06                  ;cycles of blanking for dim
14               MOVWF DIM                  
15               CLRF FLASH                 
16               CLRF SECONDS               ;holds seconds count 0 - 59
17               CLRF MINUTES               ;hold minutes count 0 - 4
18               CLRF PORTA                 ;all outputs low
19               CLRF PORTB                 
20               BSF STATUS,RP0             ;change to page 1
21               MOVLW $10                  
22               MOVWF TRISA                ;all but PA4 are outputs
23               CLRF TRISB                 ;all outputs on port B
24               MOVLW $03                  
25               MOVWF OPTION               ;assign prescaler (1:16) to TMR0
26               BCF STATUS,RP0             ;back to page 0
27               RETURN                     
28               NOP                        ;***** the main program *****
29   MAIN        CALL INIT                  ;set up ports etc.
30   MAINLOOP    CALL CLOCK                 ;update clock every second
31   UPDATE      CALL SHOW                  ;update display about 244 times/sec
32   WAIT        BTFSS INTCON,T0IF          ;check for high clock flag
33               GOTO WAIT                  ;not yet, try again
34               CLRF INTCON                ;clear the clock flag
35               CALL CHKSW                 ;check for switch pressed
36               DECFSZ TICKS,f             ;second up yet?
37               GOTO UPDATE                ;no, display and wait for flag
38               GOTO MAINLOOP              ;yes, advance clock
39               NOP                        ;*****  advance clock routine *****
40   CLOCK       MOVLW $F4                  ; reset tick with seconds value 
41               MOVWF TICKS                ;(244 decimal)
42               INCF SECONDS,f             ;bump seconds
43               MOVLW $3C                  ;check for rollover to minutes
44               SUBWF SECONDS,W            ;(60 decimal)
45               BTFSS STATUS,Z             ;skip if zero
46               RETURN                     ;we are done this time
47               CLRF SECONDS               ;reset seconds to zero
48               INCF MINUTES,f             ;bump minutes
49               MOVLW $FC                  ;overide ticks with min value
50               MOVWF TICKS                ;(252 decimal)
51               MOVLW $05                  ;have 5 minutes gone by?
52               SUBWF MINUTES,W            
53               BTFSS STATUS,Z             ;if zero must reset minutes
54               RETURN                     
55               CLRF MINUTES               ;reset minutes (count 5 again)
56               MOVLW $F6                  ;overide ticks with 5 min value
57               MOVWF TICKS                ;(246 decimal)
58               CALL NEXTMIN5              ;move position pointer 1 to left
59               BTFSS LOMIN5,0             ;roll into lowest bit?
60               RETURN                     ;no
61               CALL NEXTHOUR              ;yes, hour position one to left
62               MOVLW $F6                  ;overide ticks with hour value
63               MOVWF TICKS                ;(246 decimal)
64               RETURN                     ;finished update of clock
65               NOP                        ;***** advance hour position *****
66   NEXTHOUR    BCF STATUS,C               ;clear the carry bit
67               BTFSC HIHOUR,3             ;check if at 11 o'clock
68               BSF STATUS,C               ;yes roll a 1 in from carry
69               RLF LOHOUR,f               ;roll low hour 1 to left
70               RLF HIHOUR,f               ;and then hihour
71               RETURN                     
72               NOP                        ;***** advance 5 min position *****
73   NEXTMIN5    BCF STATUS,C               ;prepare to roll 0 in
74               BTFSC HIMIN5,3             ;setting at top position?
75               BSF STATUS,C               ;yes, roll a 1 into lowest position
76               RLF LOMIN5,f               ;roll low 8 bits left
77               RLF HIMIN5,f               ;then high 4 bits
78               RETURN                     
79               NOP                        ;***** update the display *****
80   SHOW        MOVLW $00                  ;assume bits are off this cycle
81               DECFSZ DIM,f               ;time to switch?
82               GOTO OVERDIM               ;not yet
83               MOVLW $06                  ;yes, reset dim
84               MOVWF DIM                  
85               MOVLW $FF                  ;one cycle of on
86   OVERDIM     MOVWF SETUPB               ;into low setup
87               MOVWF SETUPA               ;and hi setup
88               MOVF LOMIN5,W              ;min5 position to minute pos
89               MOVWF LOMINUTE             
90               MOVF HIMIN5,W              
91               MOVWF HIMINUTE             
92               MOVF MINUTES,W             ;transfer minutes into mincnt
93               MOVWF MINCNT               
94               BTFSC STATUS,Z             ;is minutes zero?
95               GOTO BLNKMIN               ;yes skip the rotation
96   MINLEFT     CALL NEXTMIN               ;rotate left one place
97               DECFSZ MINCNT,f            ;dec count, is it zero?
98               GOTO MINLEFT               ;no, rotate left again
99   BLNKMIN     COMF LOMINUTE,W            ;blank the minutes position
100              ANDWF SETUPB,f             
101              COMF HIMINUTE,W            
102              ANDWF SETUPA,f             
103              DECFSZ FLASHCNT,f          ;count down for flash change
104              GOTO CKFLASH               
105              MOVLW $C8                  ;reset flash count
106              MOVWF FLASHCNT             
107              COMF FLASH,f               ;flip, all zeros - all ones
108  CKFLASH     MOVF FLASH,f               ;check flash for zero
109              BTFSS STATUS,Z             ;if yes want 0 in min5 bit
110              GOTO SETBITHI              ;no, want a 1 in min5 bit
111              COMF LOMIN5,W              ;blank out 5 minute bit
112              ANDWF SETUPB,f             
113              COMF HIMIN5,W              ;in case it is in hi byte
114              ANDWF SETUPA,f             
115              GOTO ADDHOUR               
116  SETBITHI    MOVF LOMIN5,W              
117              IORWF SETUPB,f             
118              MOVF HIMIN5,W              
119              IORWF SETUPA,f             
120  ADDHOUR     MOVF LOHOUR,W              ;now override with the hour bit
121              IORWF SETUPB,W             ;(always set)
122              MOVWF PORTB                ;and move result to port B
123              MOVF HIHOUR,W              ;likewise for the hi byte
124              IORWF SETUPA,W             
125              MOVWF PORTA                ;into port A
126              RETURN                     
127              NOP                        ;***** delay routine *****
128  DELAY       MOVLW $18                  ;(24) approx. 100ms delay
129              MOVWF TICKS                
130  DEL1        BTFSS INTCON,T0IF          ;wait for TMR0 to roll over
131              GOTO DEL1                  
132              CLRF INTCON                
133              DECFSZ TICKS,f             
134              GOTO DEL1                  
135              RETURN                     
136              NOP                        ;***** advance min postion *****
137  NEXTMIN     BCF STATUS,C               ;prepare to roll in 0
138              BTFSC HIMINUTE,3           ;reach upper limit?
139              BSF STATUS,C               ;yes, roll 1 in low
140              RLF LOMINUTE,f             ;low 8 bits
141              RLF HIMINUTE,f             ;then hi 4 bits
142              RETURN                     
143              NOP                        ;***** set time routine *****
144  CHKSW       BTFSC PORTA,4              ;is switch pressed?
145              RETURN                     ;no, back to main program
146  SHOWHOUR    MOVF LOHOUR,W              ;load low byte of hour
147              MOVWF PORTB                ;into display
148              MOVF HIHOUR,W              ;also hi byte
149              MOVWF PORTA                
150              MOVLW $0A                  ;1 sec delay
151              MOVWF COUNT                
152  WAIT1       CALL DELAY                 
153              BTFSC PORTA,4              ;switch still pressed?
154              GOTO WAITPRESS             ;no, wait for next press
155              DECFSZ COUNT,f             ;yes continue count down
156              GOTO WAIT1                 
157              CALL NEXTHOUR              ;increment hour after 1 sec
158              GOTO SHOWHOUR              ;and display it
159  WAITPRESS   MOVLW $14                  ;2 second delay
160              MOVWF COUNT                ;to wait for keypress
161              CLRF SECONDS               ;restart with no seconds
162              CLRF MINUTES               ;and also no minutes
163  WAIT2       CALL DELAY                 
164              BTFSS PORTA,4              ;skip as long as switch up
165              GOTO SHOWMIN5              ;key pressed, set 5 minute position
166              DECFSZ COUNT,f             ;count up?
167              GOTO WAIT2                 ;no, continue countdown
168              RETURN                     ;after 2 sec no press
169  SHOWMIN5    MOVF LOMIN5,W              ;put min5 position on display
170              MOVWF PORTB                
171              MOVF HIMIN5,W              
172              MOVWF PORTA                
173              MOVLW $0A                  ;1 sec delay
174              MOVWF COUNT                
175  WAIT3       CALL DELAY                 
176              BTFSC PORTA,4              ;switch up?
177              RETURN                     ;yes, we are finished
178              DECFSZ COUNT,f             ;continue countdown?
179              GOTO WAIT3                 ;yes
180              CALL NEXTMIN5              ;next 5 minute position
181              GOTO SHOWMIN5              ;display it