A Little Diversion
The XtraScreenHacks screensaver collection for X11 has an interesting, if unusual, clock: the Berlin Clock, or “berlinuhr.” Based on the Set Theory Clock, it has four counting rows: five hours, single hours, five minutes, and single minutes, plus a single flashing second indicator on top.
As an independent study, I wanted to create a text-based version of the Berlin Clock, to learn a little ncurses programming, plus the ability to handle a terminal window resize.
A resize is always possible in X11, but it’s possible on a text console as well. The following sequence will resize a terminal in a text console:
- Start a “screen” session.
- Inside the session, start “vi”.
- Detach from the “screen” session.
- Start “splitvt”.
- Rejoin the “screen” session.
Since the “screen” session re-connects to a terminal (actually, a pseudo-TTY) that has a different $LINES or $COLUMNS, “vi” running inside it gets a resize event, that is, a SIGWINCH.
Rather than jumping into the project head-first, I put down some notes specifying the look of the display, the expectations of its behavior, and the concepts I needed to research. I did a few forays into obtaining and parsing the time, creating and displaying a window using ncurses, and using color. These tests are available in the GitHub repository.
Once I was satisfied that all the concepts were in place, I copied “berlinuhr-sigwinch.c” to “berlinuhr-final.c”. In that version, I did one last bit of research (using color in ncurses), and then made the necessary changes to turn a textual proof-of-concept clock into a Berlin Clock. A few macros for color management, and one more macro to eliminate one more repetitive sequence, and I had a working Berlin Clock, bouncing somewhat incorrectly around my screen. That is, it never reached the top or left edges, but it did “scrape” against the bottom and right edges before reversing direction. But, at least it worked without crashing anything.
The “scraping” problem was fixed once I adjusted the origin locations for ncurses objects stdscr and uhrwindow. By “adjusted,” I mean “try this, no, that didn’t work, okay, try this, woops….” It does work now, and if I need to, I can look at the code and see how screen and window origins are figured.
The final task was to hide the cursor as the window marched around the screen.
A bone-headed goof
Even as I was typing this blog entry, I realized there was something wrong with the “lit/unlit” testing. For integer tests, the condition (i+1>n) is the same as (i>=n). So I’ll let you see it in the commit history, as an example of “what was I thinking?”. The GNU GCC compiler’s optimizer actually produces identical object code with this change. Woohoo!
The final result
Even with that goof, and fixing it, the final version is something I’m proud of. It isn’t on the same level as my BCM2708 microsecond timer reader, but it’s still a cool little visual toy.
I developed this on Slackware 14.1(-current), all packages installed. If you aren’t using Slackware, and want to build this program, you may need to install your distribution’s ncurses-dev or ncurses-headers package.
If you want to build this text version of berlinuhr, you can find the code here. It isn’t perfect, and it doesn’t use the latest C idioms, but it works.
Horology (the study of time-keeping) has fascinated me ever since my family had a Rolling Ball Clock in the early 1980’s. It uses a similar alternative time display, with minutes on the first row, 5-minute intervals on the second row, and hours on the third row. 1:00AM and 1:00PM were noisy affairs, with all the mobile ball bearings getting dumped into the reservoir of uncounted minutes.
Another representation of time is French Revoluionary Time (also called “decimal time”). It was inspired by the metric system, with base units of milli-days. One day is 86,400 traditional seconds, so one unit (or “beat”) is 86.4 seconds, or 1 minute 26.4 seconds. Swatch tried to revive this concept in the late 1990’s, as people all over the world connected to the Internet, but such a ham-fisted attempt to change a deeply-rooted aspect of human culture failed. No surprise there.
For an excellent overview of measuring the “small units” of time, I refer the reader to Marrison’s The Evolution of the Quartz Crystal Clock (PDF), published in July 1948 in the Bell Systems Technical Journal.
There’s also the time-eating Corpus Clock, built specifically to portray the inconsistent human perception of time.
Horology also includes the study of calendars, keeping track of times longer than a day. Some cultures use the solar (agricultural) seasons, some use the lunar phases, and some look at the larger schedule of eclipses.
And then there’s the classic quote from Tom West, who had struggled to defeat a nanosecond-level timing flaw in Data General’s 32-bit Eagle processor in the late 1970’s. He finally became so frustrated with the issue that he resigned, leaving this note on his basement terminal: “I’m going to a commune in Vermont and will deal with no unit of time shorter than a season.” (Quoted in The Soul of a New Machine by Tracy Kidder, 1981.)