aos/common/control_loop/Timing=>aos/common/util/phased_loop
diff --git a/aos/common/util/phased_loop.cc b/aos/common/util/phased_loop.cc
new file mode 100644
index 0000000..4b9dcdb
--- /dev/null
+++ b/aos/common/util/phased_loop.cc
@@ -0,0 +1,20 @@
+#include "aos/common/util/phased_loop.h"
+
+#include <string.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace time {
+
+void PhasedLoopXMS(int ms, int offset) {
+ // TODO(brians): Tests!
+ const Time frequency = Time::InMS(ms);
+ SleepUntil((Time::Now() / static_cast<int32_t>(frequency.ToNSec())) *
+ static_cast<int32_t>(frequency.ToNSec()) +
+ frequency + Time::InUS(offset));
+}
+
+} // namespace timing
+} // namespace aos
diff --git a/aos/common/util/phased_loop.h b/aos/common/util/phased_loop.h
new file mode 100644
index 0000000..d231449
--- /dev/null
+++ b/aos/common/util/phased_loop.h
@@ -0,0 +1,19 @@
+#ifndef AOS_COMMON_UTIL_PHASED_LOOP_H_
+#define AOS_COMMON_UTIL_PHASED_LOOP_H_
+
+#include <time.h>
+#include <string>
+
+namespace aos {
+namespace time {
+
+// Will not be accurate if ms isn't a factor of 1000.
+// offset is in us.
+void PhasedLoopXMS(int ms, int offset);
+// offset is in us.
+inline void PhasedLoop10MS(int offset) { PhasedLoopXMS(10, offset); }
+
+} // namespace time
+} // namespace aos
+
+#endif // AOS_COMMON_UTIL_PHASED_LOOP_H_
diff --git a/aos/common/util/util.gyp b/aos/common/util/util.gyp
index 6dd2aa2..682db82 100644
--- a/aos/common/util/util.gyp
+++ b/aos/common/util/util.gyp
@@ -8,6 +8,17 @@
],
},
{
+ 'target_name': 'phased_loop',
+ 'type': 'static_library',
+ 'sources': [
+ 'phased_loop.cc',
+ ],
+ 'dependencies': [
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/common/common.gyp:time',
+ ],
+ },
+ {
'target_name': 'log_interval',
'type': 'static_library',
'sources': [