//! Generic register access. use core::marker::PhantomData; use vcell::VolatileCell; pub trait Readable {} pub trait Writable {} pub struct Register { value: VolatileCell, _marker: PhantomData, } impl From for Register { fn from(v: T) -> Self { Self { value: VolatileCell::new(v), _marker: PhantomData, } } } impl Register where Self: Readable, T: Copy, { pub fn read(&self) -> R { R { bits: self.value.get(), _marker: PhantomData, } } } impl Register where Self: Readable + Writable, T: Copy, { pub fn write(&self, f: F) where F: FnOnce(&mut W) -> &mut W, { let mut w = W { bits: self.value.get(), _marker: PhantomData, }; self.value.set(f(&mut w).bits); } pub fn modify(&self, f: F) where F: FnOnce(T, &mut W) -> &mut W, { let mut w = W { bits: self.value.get(), _marker: PhantomData, }; self.value.set(f(w.bits, &mut w).bits); } } pub struct R { pub bits: T, _marker: PhantomData, } impl R where T: Copy, { pub fn new(bits: T) -> Self { Self { bits, _marker: PhantomData, } } pub fn bits(&self) -> T { self.bits } } pub struct W { pub bits: T, _marker: PhantomData, } impl W { pub unsafe fn bits(&mut self, bits: T) -> &mut Self { self.bits = bits; self } }