Journal #6564

Posted 14 years ago2010-05-13 16:05:03 UTC
The Perfect Clock: The code behind it

A few days ago, I posted the theoretical point of view of a perfect PIC clock. Today, I'll present you with a few code snippets. TWHL could really, really use [code] or [ pre ] tags, and I don't mean just for this.

*Remember to define variable names - i.e seconds equ 0x25

I'll start easy. This is the interrupt routine. There's nothing special in it.
;*******************
Interrupt:

	call	Clock_step
	bcf	INTCON, T0IF	;Clear interrupt flag to be able to return
	retfie
The above code is called on each timed interrupt - every 8.192ms. Now you need to make something useful of that. The following is only a 122-interrupt second, just to show context.

;*******************
Clock_step:
	incf	tick
	movfw	tick
	sublw	D'122'		;Count 122 cycles, add 1 second
	btfss	STATUS,Z
	goto	Clock_end

	clrf	tick		;I have 1 second, reset int counter.
	call	Seconds_inc	;Increment seconds counter
	movfw	seconds
	btfss	STATUS,Z	;On seconds=0, increment minutes
	goto	Clock_end

	call	Minutes_inc	;Increment minutes counter
	movfw	minutes
	btfss	STATUS,Z	;On minutes=0, increment hours
	goto	Clock_end

	call	Hours_inc	;Increment hours counter
	;--snip-- you get the idea.

Clock_end:
	return

;*******************
Seconds_inc:
	incf	seconds
	movfw	seconds
	sublw	D'60'
	btfsc	STATUS,Z
	clrf	seconds		;Reset on 60 seconds
	return

Minutes_inc:
	;--snip-- again, you get the idea.
Remember, this is only the imprecise clock, only to show the concept. Now you'll need to adjust for 122 and 123 cycles and all that shizzle I mentioned in the other journal.

To do this, I have allocated a tick_wait variable, to store whether my next cycle should be 122 or 123 interrupts long. I have also allocated adj_s to count 14-second cycles, and adj_c, to count 64 14-second cycles.

We must make a few changes to the code above.

;*******************
Clock_step:
	incf	tick
	movfw	tick
	[b]subwf	tick_wait,w[/b]	;Instead of 122, check against tick_wait
	btfss	STATUS,Z
	goto	Clock_end

	clrf	tick		;I have 1 second, reset int counter.
	[b]call	Tick_adj[/b]	;Check if next cycle counts 122 o 123

	call	Seconds_inc	;Increment seconds counter
	;--snip-- same as previous sample.

Clock_end:
	return
;*******************
Seconds_inc:
	;--snip-- same as previous sample.

;*******************
; NEW CODE BELOW
;*******************
Tick_adj:
	incf	adj_s
	movfw	adj_s
	sublw	D'14'
	btfss	STATUS,Z	;If 14, I'm done with 14s cycle
	goto	tick_adj2	;Otherwise, check if it's 13
	clrf	adj_s		;reset 14s cycle
	movlw	D'122'
	movwf	tick_wait
	goto	tick_adj_end

tick_adj2
	movfw	adj_s
	sublw	D'13'
	btfss	STATUS,Z	;If 13, it's adjust time
	goto	tick_adj_end	;if not 13 either, nothing to do

	incf	adj_c
	movfw	adj_c
	sublw	D'64'
	btfsc	STATUS,Z
	goto	tick_adj_end	;if this is the 64th adj cycle, ignore it

	incf	tick_wait	;14th second is next, lasts 123
	movfw	adj_c
	sublw	D'65'		;Check if 65
	btfsc	STATUS,Z
	clrf	adj_c		;If 65, reset count

tick_adj_end:
	return
As you can see, the code has grown quite a bit. But here we have our (theoretically) perfect clock.

I had to revise this code before posting, as the code I've written has functions to decrement seconds, minutes, and hours (so there's no need to wrap around incrementing if you missed 1 minute) as well as date keeping and alarm. What I posted here is only a fraction of it, but feel free to use this code in any clocks you intend to make.

By the way, since I still haven't built it, I'm not sure how to store years. Therefore I risk being subject to either the year 2256 bug (returns to 2000) or the year 2999 (returns to 2000 too). It could also be in 9999, but it'd be wishful thinking to expect it not to break before that :P

I hope you have found this an educational experience :)

Edit: Wow, [ pre ] works! Although only sometimes. WTF?
Edit2: I just found out why. Dude, at least let it respect tabs.
Edit3: No, I was wrong. It appears to be random. TWHL BACKEND NO WORKIE!

4 Comments

Commented 14 years ago2010-05-13 17:04:51 UTC Comment #61935
Pb is a bad programmer.
Commented 14 years ago2010-05-13 22:45:20 UTC Comment #61936
So that's assembly?
Code looks nice and simple too :) always a plus.
Commented 14 years ago2010-05-14 00:07:33 UTC Comment #61938
Sure. Although it would look better if it were rendered properly, it's not as contorted as some may think ;)
Commented 14 years ago2010-05-16 19:09:48 UTC Comment #61937
hahaha nice work wish i knew what i was looking at!

)

You must log in to post a comment. You can login or register a new account.