DEVICE PIC16C711,PROTECT_OFF,WDT_OFF,HS_OSC,PWRT_ON ; io pins oddeven equ RA.0 ; odd/even pin from LM1881 MBIT equ 1 ; button to set seconds HBIT equ 2 ; button to set hours mbut equ RA.MBIT hbut equ RA.HBIT gate equ RB.6 ; operates mux VPORT equ RB ; port directions DIR_A equ 0111b ; ra0-2 inputs DIR_B equ 0 ; all outputs ; port map BUTTONPORT equ RA BUTTONMASK equ 0110b ; general purpose registers count equ 0ch line equ 0dh vline equ 0eh field equ 0fh flag equ 10h.0 row equ 11h hpix equ 12h mpix equ 13h spix equ 14h h10 equ 15h h01 equ 16h m10 equ 17h m01 equ 18h s10 equ 19h s01 equ 1ah t0 equ 1bh tick equ 1ch buttondown equ 1dh buttonlast equ 1eh ; constants ACTIVELO equ 30 ; index of first line containing digits ACTIVEHI equ 40 ; index of last line containing digits TICKADJ equ -60 ; 60 fields per second S01ADJ equ -10 ; tens of seconds S10ADJ equ -6 ; 6x10seconds per minute M01ADJ equ -10 ; tens of minutes M10ADJ equ -6 ; 6x10minutes per hour H01ADJ equ -10 ; tens of hours ; ; reset vector ; org 0 jmp Start ; ; CharTable ; ; pixel lookup for digits 0 thru 9 ; CharTable jmp PC+W ; 1 ; skipped cycle for jmp ; 2 retw 111b ;0 ; 3... retw 101b retw 101b retw 101b retw 111b retw 001b ;1 retw 001b retw 001b retw 001b retw 001b retw 111b ;2 retw 001b retw 111b retw 100b retw 111b retw 111b ;3 retw 001b retw 111b retw 001b retw 111b retw 101b ;4 retw 101b retw 111b retw 001b retw 001b retw 111b ; 5 retw 100b retw 111b retw 001b retw 111b retw 111b ; 6 retw 100b retw 111b retw 101b retw 111b retw 111b ; 7 retw 001b retw 001b retw 001b retw 001b retw 111b ; 8 retw 101b retw 111b retw 101b retw 111b retw 111b ; 9 retw 101b retw 111b retw 001b retw 111b ; skipped cycle after ret ; 4 ; ; Start ; ; program begins here after reset ; Start setb RP0 mov ADCON1,#3 ; set all RA inputs to digital clr OPTION mov TRISA,#DIR_A mov TRISB,#DIR_B clrb RP0 ; start at 00:00:00 clr h10 clr h01 clr m10 clr m01 clr s10 clr s01 ;; start out passing the video clrb gate ; ; Resynch -- waits for falling edge on oddeven pin ; ; used when chip resets or video signal is lost ; Resynch jnb oddeven,Resynch :loop1 jb oddeven,:loop1 ; init field counter on the way in clr field not field ; ; Retrace: top of screen ; ; executed at the end of each field, 59.94 times a second. ; Retrace nop ; 0! Retrace1 ; invert field not field ; 1 ; detect button status mov W,BUTTONPORT ; 2 peek at button port and W,#BUTTONMASK ; 3 isolate button pins xor W,#BUTTONMASK ; 4 invert (lines are active low) mov t0,W ; 5 save to t0 mov buttondown,W ; 6 save to buttondown xor W,buttonlast ; 7 buttondown gets bits on for... and buttondown,W ; 8 newly pushed buttons mov W,t0 ; 9 buttonlast gets new current status mov buttonlast,W ; 10 (automatic 1/30 sec debounce) ; if both buttons are held, force a resynch to get ; time display in the right part of the frame. ; note: this also allows user to hide the time temporarily mov W,#BUTTONMASK ; 11 xor W,buttonlast ; 12 snz ; 13 jmp Resynch ; 14 ; if hour button is pressed, zero ticks ; to protect against multiple carries. ; (hours incremented later) snb buttondown.HBIT ; 15 clr tick ; 16 ; if minute button is pressed, zero seconds ; for aesthetic reasons and zero ticks to ; protect against multiple carries. ; (minutes incremented later) snb buttondown.MBIT ; 17 clr s01 ; 18 snb buttondown.MBIT ; 19 clr s10 ; 20 snb buttondown.MBIT ; 21 clr tick ; 22 ; adjust numbers for proper digit carries ; before adding anything mov W,#TICKADJ ; 23 add tick,W ; 24 mov W,#S01ADJ ; 25 add s01,W ; 26 mov W,#S10ADJ ; 27 add s10,W ; 28 mov W,#M01ADJ ; 29 add m01,W ; 30 mov W,#M10ADJ ; 31 add m10,W ; 32 mov W,#H01ADJ ; 33 add h01,W ; 34 ; always add a tick. this won't carry if ; a button was just pushed, since tick ; is cleared at that time. inc tick ; 35 snz ; 36 inc s01 ; 37 snz ; 38 inc s10 ; 39 snz ; 40 inc m01 ; 41 snz ; 42 inc m10 ; 43 snz ; 44 inc h01 ; 45 snz ; 46 inc h10 ; 47 ; timebase correction: every minute, add 4 ticks ; (again, this cannot carry if a button was just ; pushed.) mov W,#TICKADJ+4 ; 48 test s10 ; 49 snz ; 50 mov tick,W ; 51 ; if the minute button was pushed, add one ; minute, but don't roll to hours. ; in the event that a button was pushed, ; no other carries will have happened. mov W,#0 ; 52 snb buttondown.MBIT ; 53 mov W,#1 ; 54 add m01,W ; 55 snc ; 56 inc m10 ; 57 ; if the hour button was pushed, ; nothing else will have carried. ; add one hour. mov W,#0 ; 58 snb buttondown.HBIT ; 59 mov W,#1 ; 60 add h01,W ; 61 snc ; 62 inc h10 ; 63 ; adjust numbers back 6*4 = 24 cycles, ; cycles 64 thru 87 mov W,#TICKADJ ; 64 test tick sz sub tick,W mov W,#S01ADJ test s01 sz sub s01,W mov W,#S10ADJ test s10 sz sub s10,W mov W,#M01ADJ test m01 sz sub m01,W mov W,#M10ADJ test m10 sz sub m10,W mov W,#H01ADJ test h01 sz sub h01,W ; 87 ; daily fix: 24:00:00 is really 00:00:00 setb flag ; 88 mov W,#2 ; 89 xor W,h10 ; 90 sz ; 91 clrb flag ; 92 mov W,#4 ; 93 xor W,h01 ; 94 sz ; 95 clrb flag ; 96 snb flag ; 97 clr h10 ; 98 snb flag ; 99 clr h01 ; 100 ; prepare loop counters ; vertical interval has 20 more lines after this one. mov W,#20 ; 101 mov vline,W ; 102 ; field 0 has 242 remaining lines, for 263 total ; field 1 has 241 remaining lines, 262 total mov W,#241 ; 103 mov line,W ; 104 sb field.0 ; 105 inc line ; 106 ; waste rest of line mov W,#49 ; 107 mov count,W ; 108 :rloop decsz count ; 253 (last) jmp :rloop ; 254 nop ; 255 ; fallthru ; ; VLines ; ; wait out lines 2 thru 21 (unused) ; VLines mov W,#84 ; 0! mov count,W ; 1 :rloop decsz count ; 251 (last) jmp :rloop ; 252 decsz vline ; 253 jmp VLines ; 254 ; skipped cycle ; 255 ; fallthru nop ; 255 ; fallthru ; ; HLine ; ; normal scan lines counted here ; those holding digit pixels are "active" ; HLine setb flag ; 0! assume this line is active mov W,#ACTIVELO ; 1 subwf line,0 ; 2 w = line - w sc ; 3 skip if no borrow clrb flag ; 4 borrow means line not in range mov W,#ACTIVEHI ; 5 subwf line,0 ; 6 snc ; 7 skip if borrow clrb flag ; 8 no borrow means line out of range sb flag ; 9 jmp BlankLine ; 10 ; if jump taken ; 11 ; fallthru means this line is in the active range ; ; ActiveLine ; ; plot pixels as appropriate ; ActiveLine ; get row, then look up pixels ; row = 4 - (line - ACTIVELO)/2 mov W,#ACTIVELO ; 11 subwf line,0 ; 12 mov row,W ; 13 clc ; 14 rr row ; 15 mov W,#4 ; 16 sub row,W ; 17 not row ; 18 inc row ; 19 ; compute this row of pixels ; 87 cycles, from 20 thru 106 mov W,h10 ; 20 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable mov hpix,W swapf hpix,1 mov W,h01 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable or hpix,W mov W,m10 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable mov mpix,W swapf mpix,1 mov W,m01 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable or mpix,W mov W,s10 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable mov spix,W swapf spix,1 mov W,s01 mov t0,W add t0,W add t0,W add t0,W add W,t0 add W,row call CharTable or spix,W ; 106 ; wait until it's time to display the pixels mov W,#27 ; 107 mov count,W ; 108 :aloop decsz count ; 187 (last) jmp :aloop ; 188 ; show all pixels mov W,hpix ; 189 mov VPORT,W ; 190! rl VPORT ; 191 rl VPORT ; 192 rl VPORT ; 193 rl VPORT ; 194 rl VPORT ; 195 rl VPORT ; 196 clrb gate ; 197 mov W,mpix ; 198 mov VPORT,W ; 199 rl VPORT ; 200 rl VPORT ; 201 rl VPORT ; 202 rl VPORT ; 203 rl VPORT ; 204 rl VPORT ; 205 clrb gate ; 206 mov W,spix ; 207 mov VPORT,W ; 208 rl VPORT ; 209 rl VPORT ; 210 rl VPORT ; 211 rl VPORT ; 212 rl VPORT ; 213 rl VPORT ; 214 clrb gate ; 215 ; kill time until the end of the line mov W,#11 ; 216 mov count,W ; 217 :aloop1 decsz count ; 248 (last) jmp :aloop1 ; 249 nop ; 250 jmp HLineMerge ; 251 ; skipped cycle ; 252 ; ; BlankLine ; ; just wait this one out ; BlankLine mov W,#80 ; 12 mov count,W ; 13 :yawnloop decsz count ; 251 jmp :yawnloop ; 252 ; fall through to HLineMerge ; ; HLineMerge ; ; both active and blank lines end here. ; HLineMerge decsz line ; 253 jmp HLine ; 254 ; if jump taken ; 255 jmp Retrace1 ; 255 ;; skipped cycle ; 0!