aboutsummaryrefslogtreecommitdiffstats
path: root/src/pipe/register.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pipe/register.rs')
-rw-r--r--src/pipe/register.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/pipe/register.rs b/src/pipe/register.rs
new file mode 100644
index 0000000..555b70a
--- /dev/null
+++ b/src/pipe/register.rs
@@ -0,0 +1,95 @@
+//! Generic register access.
+
+use core::marker::PhantomData;
+use vcell::VolatileCell;
+
+pub trait Readable {}
+pub trait Writable {}
+
+pub struct Register<T, Reg> {
+ value: VolatileCell<T>,
+ _marker: PhantomData<Reg>,
+}
+
+impl<T, Reg> From<T> for Register<T, Reg> {
+ fn from(v: T) -> Self {
+ Self {
+ value: VolatileCell::new(v),
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<T, Reg> Register<T, Reg>
+where
+ Self: Readable,
+ T: Copy,
+{
+ pub fn read(&self) -> R<T, Self> {
+ R {
+ bits: self.value.get(),
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<T, Reg> Register<T, Reg>
+where
+ Self: Readable + Writable,
+ T: Copy,
+{
+ pub fn write<F>(&self, f: F)
+ where
+ F: FnOnce(&mut W<T, Self>) -> &mut W<T, Self>,
+ {
+ let mut w = W {
+ bits: self.value.get(),
+ _marker: PhantomData,
+ };
+ self.value.set(f(&mut w).bits);
+ }
+
+ pub fn modify<F>(&self, f: F)
+ where
+ F: FnOnce(T, &mut W<T, Self>) -> &mut W<T, Self>,
+ {
+ let mut w = W {
+ bits: self.value.get(),
+ _marker: PhantomData,
+ };
+ self.value.set(f(w.bits, &mut w).bits);
+ }
+}
+
+pub struct R<T, Reg> {
+ pub bits: T,
+ _marker: PhantomData<Reg>,
+}
+
+impl<T, Reg> R<T, Reg>
+where
+ T: Copy,
+{
+ pub fn new(bits: T) -> Self {
+ Self {
+ bits,
+ _marker: PhantomData,
+ }
+ }
+
+ pub fn bits(&self) -> T {
+ self.bits
+ }
+}
+
+pub struct W<T, Reg> {
+ pub bits: T,
+ _marker: PhantomData<Reg>,
+}
+
+impl<T, Reg> W<T, Reg> {
+ pub unsafe fn bits(&mut self, bits: T) -> &mut Self {
+ self.bits = bits;
+ self
+ }
+}