Mon, 9 Dec 2019

Maccabeam™ Part 4: A Typical Code Problem

— SjG @ 8:43 pm

Part 1: Simulating candle-light with pseudo-random sequences
Part 2: Some physical structure
Part 3: When Exactly is Hanukkah?

The build is coming together.

One discovery was a sneaky bug in the date conversion code. originally, the code had used standard C library for doing some time manipulations. These functions like mktime are used to convert from a structure containing year, month, day, hour, minute, and second to a single large number of seconds. Similarly, there’s gmtime which does the reverse. One nice thing about these functions is that you can use them for arithmetic, e.g., pass mktime all the regular values but a negative value for the hour, then convert back with gmtime to get the computed time. If you want to do the arithmetic yourself, you have to handle all of the boundaries (e.g., if you’ve rolled back into the past hour … or day … etc.)

Under the hood, mktime is doing something like what was described in the last posting about date conversions: it computes a number of seconds from the epoch given the year, month, day, hour etc. The epoch is an arbitrarily defined date and time standard. In most C / Unix environments, it’s the midnight of 1 January 1970 (e.g., the 0th second of 1970). The gmtime function does the reverse, converting a number of seconds from that epoch into a date and time.

I use this feature when computing sunrise and sunset times. Paul Schylter’s suntime.c returns a number of hours and/or minutes to each event. If the sun has already risen on the day you’re computing, for example, you’ll get a negative hour and or minute for sunrise. If the sunrise has not yet happened, the values are positive. I assembling times by adding those offsets to the current hour and minute, and passing the values to mktime. I didn’t have to worry whether the value was still the same hour or day, because mktime sorts it all out for me.

Somewhere along the line, however, I switched from the standard C library for time to using Paul Stoffregen’s Time Library. I did this because it integrates nicely with the GPS. What I neglected was that in C’s standard library, the components of the time structure are integers but in Paul’s library they are unsigned 8-bit integers.

For simple 8-bit integers, the highest-order bit is used for the sign of the number. In other words, a binary value of 00000011 would represent 3, and 10000011 would represent -3. That way, an 8-bit integer can represent values from -127 to 127. An unsigned 8-bit integer, however, uses the highest-order bit like any other bit, so 00000011 would still represent 3, but 10000011 would represent 131!

All this to say, my trick of passing possibly-negative hours or minutes into the equivalent of mktime was not doing what I had thought! When I thought I was computing the time of sunrise that was 7 hours earlier by passing hour - 7, I was actually computing the time as hour + 135. It turns out that tweaking Paul’s library to supports signed integers was simple.

The moral of this particular story is pay attention when changing C libraries.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.