Thank you for reminding me Ralph... I thought if I stayed nice and quiet and kept my head down the problem will go away...

To achieve the answer is easy... to write it up so you all know how we get to it is what I wasn’t looking forward to doing... ah well, here goes an hour out of my life... and as always I draw your attention to the fact that there are many ways to get to the result - this is just one that’s simple and easy to grasp...

1. Firstly let’s stand back and look at the big picture and try to understand it...

The problem is that we have linear seconds represented as a 32 bit number which in theory we can’t handle. What we need to achieve is linear DAYS, with the remainder in the form of HOURS, MINUTES and SECONDS. That remainder of HOURS, MINUTES and SECONDS we can display as our REAL-TIME CLOCK component, whilst the linear DAYS we can then simply add to a reference point (ie a PIC version of a JULIAN DATE) to give us our YEAR, MONTH and DAY.

There are two further problems here... not too obvious but pretty serious if you think about it, and that is (a) We can’t take significant time to calculate the result (after all it’s a clock and really you’d like to see the seconds ticking by and still have time to do something else), and (b) We can’t use up serious amount of codespace (what’s the point of using the equivalent of floats and then not having any space left in your PIC).

Here’s our known limitations so far... We can’t have numbers bigger than 16-bits (65535), and we can’t have a divisor bigger than 15 bits (32767) if we decide to use DIV32 which is the only large calibre weapon in our maths arsenal. We could embed Microchips 32-bit Assembler routines but that will burn codespace and anyway, that’s cheating, quite apart from the fact that as soon we write a single line of Assembler, half the readers of this forum will immediately drop-out through lack of understanding or interest.

2. How do we reduce the numbers to something manageable?

What we ideally want to do is divide our 32-Bit number by 86400 (the number of seconds in a day). Well, the divisor is already 17 bits, and that’s two bits more than DIV32 can handle... looks on the surface like we’re losing this one - but are we?

Let’s analyse those 32 bits... what have we got?

The lower 16 bits are seconds from zero, up to 65535. The upper 16 bits are multiples of 65536 seconds. If we load the two upper bytes as a word, then each count represents 65536 seconds. What is 65536 seconds? It is 18 HOURS, 12 MINUTES and 16 SECONDS. Knowing this, we can simply explode our most significant word into multiples of HOURS, MINUTES and SECONDS...

3. Let’s program...

ByteA var BYTE
ByteB var BYTE
ByteC var BYTE
ByteD var BYTE
DAYS var WORD
HOURS var BYTE
MINUTES var BYTE
SECONDS var BYTE
TempA var WORD
TempB var WORD
TempHOURS var WORD
TempMINUTES var WORD
TempSECONDS var WORD

Now assume we’ve read our 32-Bit number from the RTC into variables ByteA, ByteB, ByteC and ByteD where ByteA holds our Most Significant Bits, and ByteD holds the Least Significant Bits.

TempA.Highbyte=ByteA
TempA.Lowbyte=ByteB
TempB=TempA*18
DAYS=DIV32 24
HOURS=R2
TempB=TempA*12
TempHOURS=DIV32 60
MINUTES=R2
TempB=TempA*16
TempMINUTES=DIV32 60
SECONDS=R2

This now completely resolves our most significant byte:-

DAYS holds our resolved days.
HOURS and TempHOURS together hold the Hours quotient
MINUTES and TempMINUTES together hold the Minutes quotient
SECONDS holds the Seconds quotient

Now for our least Significant 16 Bits...

TempA.Highbyte=ByteC
TempA.Lowbyte=ByteD
TempHOURS=TempHOURS+(TempA/3600)+HOURS
TempA=TempA//3600
TempMINUTES=TempMINUTES+(TempA/60)+MINUTES
TempA=TempA//60
TempSECONDS=TempA+SECONDS

And finally, let’s resolve the issue in it's entirity...

TempMINUTES=TempMINUTES+(TempSECONDS/60)
SECONDS=TempSECONDS//60
TempHOURS=TempHOURS+(TempMINUTES/60)
MINUTES=TempMINUTES//60
DAYS=DAYS+(TempHOURS/24)
HOURS=TempHOURS//24

So at the end of this, we have DAYS (a word variable which can be used to offset our Reference Point), HOURS, MINUTES and SECONDS, the latter all being BYTE variables. The only clever thing we have used, is a little known system variable called R2 which holds the remainder from a DIV32 execution. Before anyone asks that they've never hear of R2, that little golden nugget on this forum was brought to you by Darrel Taylor in the Code Examples section. Bet nobody's paid attention!

4. Let’s work through a random example…

10154 days, 18 Hours, 48 Minutes and 52 seconds… is 877373332 Seconds, which equates to the 32 bit number… $344BA794… (assuming my math serves me correctly)…
Code:
	'
	'	Software Defines
	'	----------------
	ByteA var BYTE
	ByteB var BYTE
	ByteC var BYTE
	ByteD var BYTE
	DAYS var WORD
	HOURS var BYTE
	MINUTES var BYTE
	SECONDS var BYTE
	TempA var WORD
	TempB var WORD
	TempHOURS var WORD
	TempMINUTES var WORD
	TempSECONDS var WORD

	'
	'	Enter Test Data
	'	---------------
	ByteA=$34
	ByteB=$4B
	ByteC=$A7
	ByteD=$94

	'
	'	Calculate and Display
	'	---------------------
Loop:
	Gosub CalculateLinearDAYS
	LCDOut $FE,$01,"Days=",#DAYS
	LCDOut $FE,$C0,"Time=",DEC2 HOURS,":",DEC2 MINUTES,":",DEC2 SECONDS
	Pause 1000
	Goto Loop
	
	'
	'	Calculate Linear DAYS
	'	---------------------
CalculateLinearDAYS:
	TempA.Highbyte=ByteA
	TempA.Lowbyte=ByteB
	TempB=TempA*18
	DAYS=DIV32 24
	HOURS=R2
	TempB=TempA*12
	TempHOURS=DIV32 60
	MINUTES=R2
	TempB=TempA*16
	TempMINUTES=DIV32 60
	SECONDS=R2
	'
	TempA.Highbyte=ByteC
	TempA.Lowbyte=ByteD
	TempHOURS=TempHOURS+(TempA/3600)+HOURS
	TempA=TempA//3600
	TempMINUTES=TempMINUTES+(TempA/60)+MINUTES
	TempA=TempA//60
	TempSECONDS=TempA+SECONDS
	'
	TempMINUTES=TempMINUTES+(TempSECONDS/60)
	SECONDS=TempSECONDS//60
	TempHOURS=TempHOURS+(TempMINUTES/60)
	MINUTES=TempMINUTES//60
	DAYS=DAYS+(TempHOURS/24)
	HOURS=TempHOURS//24
	Return

	End
Does it work? As if you need to ask!

Now… having got this to work, your hour is up, and JULIAN DATE routines is another story…

Melanie