Merge #120

120: Add example that periodically shows the current clock ticks. r=torfmaster a=gendx

This example sets a periodic timer, and reads the current clock ticks every time it fires. This can be helpful to debug when the system ticks wrap around.

Co-authored-by: Guillaume Endignoux <guillaumee@google.com>
Co-authored-by: torfmaster <briefe@kebes.de>
diff --git a/examples/hello.rs b/examples/hello.rs
deleted file mode 100644
index 3cbaf2f..0000000
--- a/examples/hello.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![no_std]
-
-use core::fmt::Write;
-use libtock::result::TockResult;
-use libtock::timer::Duration;
-use libtock::Drivers;
-
-#[libtock::main]
-async fn main() -> TockResult<()> {
-    let Drivers {
-        console_driver,
-        timer_context,
-        ..
-    } = libtock::retrieve_drivers()?;
-    let mut console = console_driver.create_console();
-    let mut driver = timer_context.create_timer_driver();
-    let timer_driver = driver.activate()?;
-
-    for i in 0.. {
-        writeln!(console, "Hello world! {}", i)?;
-        timer_driver.sleep(Duration::from_ms(500)).await?;
-    }
-
-    Ok(())
-}
diff --git a/examples/timer.rs b/examples/timer.rs
new file mode 100644
index 0000000..9ed0112
--- /dev/null
+++ b/examples/timer.rs
@@ -0,0 +1,85 @@
+#![no_std]
+/**
+ * This example shows a repeated timer combined with reading and displaying the current time in
+ * clock ticks.
+ **/
+use core::fmt::Write;
+use libtock::console::Console;
+use libtock::result::TockResult;
+use libtock::timer::DriverContext;
+use libtock::timer::Duration;
+use libtock::Drivers;
+
+const DELAY_MS: usize = 500;
+
+#[libtock::main]
+async fn main() -> TockResult<()> {
+    let Drivers {
+        mut timer_context,
+        console_driver,
+        ..
+    } = libtock::retrieve_drivers()?;
+    let mut console = console_driver.create_console();
+
+    let mut previous_ticks = None;
+
+    for i in 0.. {
+        print_now(&mut console, &mut timer_context, &mut previous_ticks, i)?;
+        let mut driver = timer_context.create_timer_driver();
+        let timer_driver = driver.activate()?;
+
+        timer_driver.sleep(Duration::from_ms(DELAY_MS)).await?;
+    }
+
+    Ok(())
+}
+
+fn print_now(
+    console: &mut Console,
+    timer_context: &mut DriverContext,
+    previous_ticks: &mut Option<isize>,
+    i: usize,
+) -> TockResult<()> {
+    let mut timer_with_callback = timer_context.with_callback(|_, _| {});
+    let timer = timer_with_callback.init()?;
+    let current_clock = timer.get_current_clock()?;
+    let ticks = current_clock.num_ticks();
+    let frequency = timer.clock_frequency().hz();
+    writeln!(
+        console,
+        "[{}] Waited roughly {}. Now is {} = {:#010x} ticks ({:?} ticks since last time at {} Hz)",
+        i,
+        PrettyTime::from_ms(i * DELAY_MS),
+        PrettyTime::from_ms(current_clock.ms_f64() as usize),
+        ticks,
+        previous_ticks.map(|previous| ticks - previous),
+        frequency
+    )?;
+    *previous_ticks = Some(ticks);
+    Ok(())
+}
+
+struct PrettyTime {
+    mins: usize,
+    secs: usize,
+    ms: usize,
+}
+
+impl PrettyTime {
+    fn from_ms(ms: usize) -> PrettyTime {
+        PrettyTime {
+            ms: ms % 1000,
+            secs: (ms / 1000) % 60,
+            mins: ms / (60 * 1000),
+        }
+    }
+}
+
+impl core::fmt::Display for PrettyTime {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        if self.mins != 0 {
+            write!(f, "{}m", self.mins)?
+        }
+        write!(f, "{}.{:03}s", self.secs, self.ms)
+    }
+}