--- a
+++ b/src/chrono.cpp
@@ -0,0 +1,211 @@
+#ifndef TEST_CHRONO
+/* Copyright (C) 2014 J.F.Dockes
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+// Measure and display time intervals.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <iostream>
+
+#include "chrono.h"
+
+using namespace std;
+
+////////////////////
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 1
+#endif
+
+#define MILLIS(TS1, TS2)                                \
+    ((long long)((TS2).tv_sec - (TS1).tv_sec) * 1000LL +  \
+     ((TS2).tv_nsec - (TS1).tv_nsec) / 1000000)
+
+#define MICROS(TS1, TS2)                                        \
+    ((long long)((TS2).tv_sec - (TS1).tv_sec) * 1000000LL +       \
+     ((TS2).tv_nsec - (TS1).tv_nsec) / 1000)
+
+#define SECONDS(TS1, TS2)                             \
+    (float((TS2).tv_sec - (TS1).tv_sec) +             \
+     float((TS2).tv_nsec - (TS1).tv_nsec) * 1e-9)
+
+// We use gettimeofday instead of clock_gettime for now and get only
+// uS resolution, because clock_gettime is more configuration trouble
+// than it's worth
+static void gettime(int, Chrono::TimeSpec *ts)
+{
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    ts->tv_sec = tv.tv_sec;
+    ts->tv_nsec = tv.tv_usec * 1000;
+}
+///// End system interface (used to be much more complicated in the 199xs...)
+
+Chrono::TimeSpec Chrono::o_now;
+
+void Chrono::refnow()
+{
+    gettime(CLOCK_REALTIME, &o_now);
+}
+
+long long Chrono::amicros() const
+{
+    TimeSpec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 0;
+    return MICROS(ts, m_orig);
+}
+
+Chrono::Chrono()
+{
+    restart();
+}
+
+// Reset and return value before rest in milliseconds
+long Chrono::restart()
+{
+    TimeSpec now;
+    gettime(CLOCK_REALTIME, &now);
+    long ret = MILLIS(m_orig, now);
+    m_orig = now;
+    return ret;
+}
+long Chrono::urestart()
+{
+    TimeSpec now;
+    gettime(CLOCK_REALTIME, &now);
+    long ret = MICROS(m_orig, now);
+    m_orig = now;
+    return ret;
+}
+
+// Get current timer value, milliseconds
+long Chrono::millis(bool frozen)
+{
+    if (frozen) {
+        return MILLIS(m_orig, o_now);
+    } else {
+        TimeSpec now;
+        gettime(CLOCK_REALTIME, &now);
+        return MILLIS(m_orig, now);
+    }
+}
+
+//
+long Chrono::micros(bool frozen)
+{
+    if (frozen) {
+        return MICROS(m_orig, o_now);
+    } else {
+        TimeSpec now;
+        gettime(CLOCK_REALTIME, &now);
+        return MICROS(m_orig, now);
+    }
+}
+
+float Chrono::secs(bool frozen)
+{
+    if (frozen) {
+        return SECONDS(m_orig, o_now);
+    } else {
+        TimeSpec now;
+        gettime(CLOCK_REALTIME, &now);
+        return SECONDS(m_orig, now);
+    }
+}
+
+#else
+
+///////////////////// test driver
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+#include "chrono.h"
+
+using namespace std;
+
+static char *thisprog;
+static void
+Usage(void)
+{
+    fprintf(stderr, "Usage : %s \n", thisprog);
+    exit(1);
+}
+
+Chrono achrono;
+Chrono rchrono;
+
+void
+showsecs(long msecs)
+{
+    fprintf(stderr, "%3.5f S", ((float)msecs) / 1000.0);
+}
+
+void
+sigint(int sig)
+{
+    signal(SIGINT, sigint);
+    signal(SIGQUIT, sigint);
+
+    fprintf(stderr, "Absolute interval: ");
+    showsecs(achrono.millis());
+    fprintf(stderr, ". Relative interval: ");
+    showsecs(rchrono.restart());
+    cerr <<  " Abs micros: " << rchrono.amicros() <<
+        " Relabs micros: " << rchrono.amicros() - 1430477861905884LL
+         << endl;
+    fprintf(stderr, ".\n");
+    if (sig == SIGQUIT) {
+        exit(0);
+    }
+}
+
+int main(int argc, char **argv)
+{
+
+    thisprog = argv[0];
+    argc--;
+    argv++;
+
+    if (argc != 0) {
+        Usage();
+    }
+
+    for (int i = 0; i < 50000000; i++);
+    fprintf(stderr, "Start secs: %.2f\n", achrono.secs());
+
+
+    fprintf(stderr, "Type ^C for intermediate result, ^\\ to stop\n");
+    signal(SIGINT, sigint);
+    signal(SIGQUIT, sigint);
+    achrono.restart();
+    rchrono.restart();
+    while (1) {
+        pause();
+    }
+}
+
+#endif /*TEST_CHRONO*/