Counting seconds

Discussion of issues related specifically to writing code for native mode devices. This includes ZBasic code as well as assembly language code and C code, both inline and standalone.
Post Reply
meenbombs
Posts: 35
Joined: 20 November 2008, 15:54 PM

Counting seconds

Post by meenbombs »

I am trying to keep track of the seconds since the micro is powered up. This is the code I am using but for some reason it just rolls from 299 or 300 to about 45. I would expect it to continue counting for the 8 or 10 hours the product runs but no such luck.

dim hour as byte
dim minute as byte
dim second as single
dim seconds as single

call gettime(hour, minute, second)
seconds = Csng(hour *3600) + Csng(minute*60) +Csng(second)

Thanks in advance
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Counting seconds

Post by dkinzer »

meenbombs wrote:[...] for some reason it just rolls from 299 or 300 to about 45.
The problem is that the program is doing exactly what you told it to rather than what you intended. The issue is that each data type has a fundamental limit on the values that it can represent. As a programmer, you have to be aware of how those limitations relate to what you're tying to do.

Consider, for example, the part of your equation that says CSng(hours * 3600). The 'hours' variable is a byte that can hold values up to 255 but the maximum value that will be placed in that variable by the GetTime() call is 59 so that is OK. However, when you multiply that byte value by 3600 the result, for every possible value of 'hour' except zero, is too large to be represented in a Byte variable. The code is perfectly legal but useless.

The way to correct the problem is to convert the 'hours' value to a larger data type before multiplying by 3600. Which type you should use depends on a careful analysis of the range of expected values. Since the largest expected value of 'hours' is 59, the largest expected value of the result after multiplying by 3600 is 212,400. Since this value is too large to represent in an UnsignedInteger type, you'll have to use the UnsignedLong type. The code fragment then becomes: CSng(CULng(hours) * 3600). You'll need to apply the same kind of analysis to the remaining terms.

As a side note, there is a much simpler way to accomplish your objective. The value returned by Register.RTCTick() gives the number of RTC ticks that have occurred since midnight. On most ZX devices, there are 512 RTC ticks per second. You can convert this value to "seconds since midnight" thusly:

Code: Select all

CSng(Register.RTCTick) / CSng(Register.RTCTickFrequency)
If you only need an integral number of seconds, the following code produces a value rounded to the nearest second:

Code: Select all

(Register.RTCTick + CLng(Register.RTCTickFrequency \ 2)) \ CLng(Register.RTCTickFrequency)
If you don't need a rounded value, you can drop the middle term; the result will then be truncated (rounded down) to the nearest integral value.
- Don Kinzer
meenbombs
Posts: 35
Joined: 20 November 2008, 15:54 PM

Post by meenbombs »

I incorrectly assumed because "seconds" was a single it would be limited to 3.4e+38 and the equation feeding the "seconds" value would assume that limit. I feel dumber every time I post. Thanks for the tune up.
Post Reply