#include <stdbool.h>
#include <stdio.h>
#include <time.h>
+#include <unistd.h>
static long const pulsewidth = 250000000; /* nanoseconds */
displayed.tm_min -= 60;
}
displayed.tm_hour %= 12;
- printf(" (%02d:%02d:%02d)\n",
+ printf(" (%d:%02d:%02d)\n",
displayed.tm_hour, displayed.tm_min, displayed.tm_sec);
fflush(stdout);
}
static void
-init()
+init(int argc, char **argv)
{
struct timespec ts;
+ int opt;
tzset();
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
if (localtime_r(&ts.tv_sec, &displayed) == NULL)
err(1, "localtime_r");
displayed.tm_sec = (displayed.tm_sec >= 30) ? 30 : 0;
+ while ((opt = getopt(argc, argv, "s:")) != -1) {
+ switch (opt) {
+ case 's':
+ if (sscanf(optarg, "%d:%d:%d", &displayed.tm_hour,
+ &displayed.tm_min, &displayed.tm_sec) != 3)
+ errx(1, "usage");
+ break;
+ }
+ }
+}
+
+enum need_adjust { STOP, TICK, ADVANCE };
+
+static enum need_adjust
+need_adjust(struct tm const *now)
+{
+ long diff;
+
+ diff = now->tm_sec - displayed.tm_sec +
+ 60 * (now->tm_min - displayed.tm_min) +
+ 3600 * (now->tm_hour - displayed.tm_hour);
+ if (diff < 0) diff += 3600 * 12;
+ diff %= 3600 * 12;
+ printf("diff = %ld\n", diff);
+ if (diff < 30 || diff >= (10 * 3600)) return STOP;
+ if (diff < 60) return TICK;
+ if (diff < (10 * 3600)) return ADVANCE;
+}
+
+static void
+ts_advance(struct timespec *tp, long nsec)
+{
+
+ tp->tv_nsec += nsec;
+ if (tp->tv_nsec >= 1000000000) tp->tv_sec++;
}
-
static void
run()
{
struct timespec ts;
struct tm tm;
+ int tick;
while (true) {
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
err(1, "clock_gettime");
+ ts_advance(&ts, pulsewidth);
if (localtime_r(&ts.tv_sec, &tm) == NULL)
err(1, "localtime_r");
- /* Round down to the last 30 s. */
+ tick = 30;
+ switch (need_adjust(&tm)) {
+ case ADVANCE:
+ tick = 2;
+ /* FALLTHROUGH */
+ case TICK:
+ pulse();
+ /* FALLTHROUGH */
+ case STOP:
+ /* nothing */ ;
+ }
+ /* Round down to the last tick. */
ts.tv_nsec = 0;
- ts.tv_sec -= tm.tm_sec % 30;
+ ts.tv_sec -= tm.tm_sec % tick;
/* Choose when next tick will be. */
ts.tv_nsec = 1000000000 - pulsewidth;
- ts.tv_sec += 29;
+ ts.tv_sec += tick - 1;
if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL)
!= 0)
err(1, "clock_nanosleep");
- pulse();
}
}
main(int argc, char **argv)
{
- init();
+ init(argc, argv);
run();
return 0;
}