diff --git a/Cargo.toml b/Cargo.toml
index 569e620866a74fd9b59202d38b428211e728320a..e6bd14d1571cee648ee428acb1714b457127fc6d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,15 +1,21 @@
 [package]
 authors = [
 	"Jorge Aparicio <japaricious@gmail.com>",
-	"Jonathan 'theJPster' Pallant <github@thejpster.org.uk>"
+	"Jonathan 'theJPster' Pallant <github@thejpster.org.uk>",
+	"Per Lindgren <per.lindgren@ltu.se>"
 ]
+
 description = "Volatile access to memory mapped hardware registers"
 documentation = "https://docs.rs/volatile-register"
 keywords = ["no-std", "volatile", "register"]
 license = "MIT OR Apache-2.0"
 name = "volatile-register"
 repository = "https://github.com/japaric/volatile-register"
-version = "0.2.0"
+version = "0.3.0"
 
 [dependencies]
 vcell = "0.1.0"
+
+[features]
+debug-fmt = []
+#default = ["debug-fmt"]
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 21393850b7ddd7cac6ebad2238d8bd29b7b36dbf..b5cffc8e00f025580e1417574adf4e22832a4687 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,20 +27,47 @@
 
 #![deny(missing_docs)]
 #![no_std]
+#![feature(specialization)]
 
 extern crate vcell;
 
+#[cfg(feature = "debug-fmt")]
+use core::fmt;
+#[cfg(feature = "debug-fmt")]
+use core::fmt::{Debug, UpperHex};
 use vcell::VolatileCell;
 
 /// Read-Only register
 pub struct RO<T>
-    where T: Copy
+where
+    T: Copy,
 {
     register: VolatileCell<T>,
 }
 
+#[cfg(feature = "debug-fmt")]
+impl<T> fmt::Debug for RO<T>
+where
+    T: Copy + Debug,
+{
+    default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.read())
+    }
+}
+
+#[cfg(feature = "debug-fmt")]
+impl<T> fmt::Debug for RO<T>
+where
+    T: Copy + Debug + UpperHex,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:#X}", self.read())
+    }
+}
+
 impl<T> RO<T>
-    where T: Copy
+where
+    T: Copy,
 {
     /// Reads the value of the register
     #[inline(always)]
@@ -49,22 +76,45 @@ impl<T> RO<T>
     }
 }
 
+#[cfg(feature = "debug-fmt")]
+impl<T> fmt::Debug for RW<T>
+where
+    T: Copy + Debug,
+{
+    default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.read())
+    }
+}
+
+#[cfg(feature = "debug-fmt")]
+impl<T> fmt::Debug for RW<T>
+where
+    T: Copy + Debug + UpperHex,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:#X}", self.read())
+    }
+}
+
 /// Read-Write register
 pub struct RW<T>
-    where T: Copy
+where
+    T: Copy,
 {
     register: VolatileCell<T>,
 }
 
 impl<T> RW<T>
-    where T: Copy
+where
+    T: Copy,
 {
     /// Performs a read-modify-write operation
     ///
     /// NOTE: `unsafe` because writes to a register are side effectful
     #[inline(always)]
     pub unsafe fn modify<F>(&self, f: F)
-        where F: FnOnce(T) -> T
+    where
+        F: FnOnce(T) -> T,
     {
         self.register.set(f(self.register.get()));
     }
@@ -86,13 +136,25 @@ impl<T> RW<T>
 
 /// Write-Only register
 pub struct WO<T>
-    where T: Copy
+where
+    T: Copy,
 {
     register: VolatileCell<T>,
 }
 
+#[cfg(feature = "debug-fmt")]
+impl<T> fmt::Debug for WO<T>
+where
+    T: Copy + Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "- write only -") // TODO: perhaps self.register.get()
+    }
+}
+
 impl<T> WO<T>
-    where T: Copy
+where
+    T: Copy,
 {
     /// Writes `value` into the register
     ///