]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/main_time.c
Refactor main into separate files
[~andy/csm213a-hw] / hw2 / main_time.c
diff --git a/hw2/main_time.c b/hw2/main_time.c
new file mode 100644 (file)
index 0000000..e022c6a
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdint.h>
+
+#include "serial_irq.h"
+#include "main_time.h"
+
+/*******************
+ * Timer functions *
+ *******************/
+
+uint64_t time_last_local; // timestamp at last time sync
+uint64_t time_last_world; // offset at last time sync
+
+/* Initialization */
+void time_init(void)
+{
+       // nothing for now
+}
+
+/**
+ * Generate time stamp for an async event:
+ *   time:  drift compensated wall-clock time
+ *   stamp: event timestamp from PIT Module
+ */
+uint64_t time_to_world(uint64_t local)
+{
+       uint64_t elapsed = local - time_last_local;
+       return time_last_world + elapsed;
+}
+
+uint64_t time_to_local(uint64_t world)
+{
+       uint64_t elapsed = world - time_last_world;
+       return time_last_local + elapsed;
+}
+
+/**
+ * Synchronize the timer internal state with updates
+ * from an external time sync message.
+ *   local: our internal timestamp for the event
+ *   world: reference timestamp from the other device
+ */
+void time_ext_init(uint64_t local, uint64_t world)
+{
+       sirq_printf("initialize clocks: %d -> %d\r\n",
+                       (int)(local/NSEC_PER_SEC),
+                       (int)(world/NSEC_PER_SEC));
+
+       time_last_local = local;
+       time_last_world = world;
+}
+
+/**
+ * Synchronize the timer internal state with updates
+ * from an external time sync message.
+ *   local: our internal timestamp for the event
+ *   world: reference timestamp from the other device
+ */
+void time_ext_sync(uint64_t local, uint64_t world)
+{
+       uint64_t guess = time_to_world(local);
+
+       time_last_local = local;
+       time_last_world = (guess/2) + (world/2);
+       //time_last_world = (guess * 3 / 4) + (world * 1 / 4);
+       //time_last_world =
+       //      (guess - (        guess / 2)) +
+       //      (world - (world - world / 2));
+       //time_last_world =
+       //      (guess - (guess - guess / 4)) +
+       //      (world - (        world / 4));
+
+       world = time_last_world;
+
+//#ifdef VERBOSE
+#if 1
+       uint64_t error = world > guess ? world - guess :
+                        guess > world ? guess - world : 0;
+       int      ahead = guess > world;
+       sirq_printf("syncing clocks: %6d=%d.%04u -> %d.%04u (err: %s%ld.%09lu)\r\n",
+                       (int)((local / NSEC_PER_SEC)),
+                       (int)((guess / NSEC_PER_SEC)),
+                       (int)((guess % NSEC_PER_SEC)/(NSEC_PER_SEC/10000)),
+                       (int)((world / NSEC_PER_SEC)),
+                       (int)((world % NSEC_PER_SEC)/(NSEC_PER_SEC/10000)),
+                       ahead ? "-" : " ",
+                       (int32_t )(error / (int64_t)NSEC_PER_SEC),
+                       (uint32_t)(error % (int64_t)NSEC_PER_SEC));
+#endif
+//#endif
+}
+
+void time_printf(const char *label, uint64_t local)
+{
+       uint64_t world = time_to_world(local);
+       sirq_printf("%s -- %d.%09u -> %d.%09u\r\n",
+                       label,
+                       (int)(local / NSEC_PER_SEC),
+                       (int)(local % NSEC_PER_SEC),
+                       (int)(world / NSEC_PER_SEC),
+                       (int)(world % NSEC_PER_SEC));
+}