use core::{cmp, convert, marker, ops};
pub trait RegisterValue : Copy + Clone +
ops::BitAnd<Output=Self> +
ops::BitAndAssign +
ops::BitOr<Output=Self> +
ops::BitOrAssign +
ops::BitXor<Output=Self> +
ops::BitXorAssign +
ops::Not<Output=Self> +
cmp::PartialEq + cmp::Eq +
cmp::PartialOrd + cmp::Ord +
convert::From<u8> {
}
pub trait Register : Sized {
type T: RegisterValue;
type RegisterBits = RegisterBits<Self>;
const ADDRESS: *mut Self::T;
#[inline(always)]
fn write<V>(value: V) where V: Into<Self::T> {
unsafe {
core::ptr::write_volatile(Self::ADDRESS, value.into());
}
}
#[inline(always)]
fn read() -> Self::T {
unsafe { core::ptr::read_volatile(Self::ADDRESS) }
}
fn set(bits: RegisterBits<Self>) {
Self::set_mask_raw(bits.mask);
}
#[inline(always)]
fn set_mask_raw(mask: Self::T) {
unsafe {
core::ptr::write_volatile(Self::ADDRESS, core::ptr::read_volatile(Self::ADDRESS) | mask);
}
}
fn unset(bits: RegisterBits<Self>) {
Self::unset_mask_raw(bits.mask);
}
#[inline(always)]
fn unset_mask_raw(mask: Self::T) {
unsafe {
core::ptr::write_volatile(Self::ADDRESS, core::ptr::read_volatile(Self::ADDRESS) & !mask)
}
}
fn toggle(mask: RegisterBits<Self>) {
Self::toggle_raw(mask.mask);
}
#[inline(always)]
fn toggle_raw(mask: Self::T) {
unsafe {
core::ptr::write_volatile(Self::ADDRESS, core::ptr::read_volatile(Self::ADDRESS) ^ mask)
}
}
fn is_set(bits: RegisterBits<Self>) -> bool {
Self::is_mask_set_raw(bits.mask)
}
#[inline(always)]
fn is_mask_set_raw(mask: Self::T) -> bool {
unsafe {
(core::ptr::read_volatile(Self::ADDRESS) & mask) == mask
}
}
fn is_clear(mask: RegisterBits<Self>) -> bool {
Self::is_clear_raw(mask.mask)
}
#[inline(always)]
fn is_clear_raw(mask: Self::T) -> bool {
unsafe {
(core::ptr::read_volatile(Self::ADDRESS) & mask) == Self::T::from(0)
}
}
fn wait_until_set(bits: RegisterBits<Self>) {
Self::wait_until_mask_set_raw(bits.mask);
}
#[inline(always)]
fn wait_until_mask_set_raw(mask: Self::T) {
wait_until(|| Self::is_mask_set_raw(mask))
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RegisterBits<R: Register> {
mask: R::T,
_phantom: marker::PhantomData<R>,
}
impl<R> RegisterBits<R> where R: Register {
pub const fn new(mask: R::T) -> Self {
RegisterBits { mask, _phantom: marker::PhantomData }
}
pub fn zero() -> Self {
RegisterBits::new(0u8.into())
}
}
impl<R> ops::BitOr for RegisterBits<R> where R: Register
{
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
RegisterBits::new(self.mask | rhs.mask)
}
}
impl<R> ops::BitOrAssign for RegisterBits<R> where R: Register {
fn bitor_assign(&mut self, rhs: Self) {
self.mask |= rhs.mask;
}
}
impl<R> ops::BitAnd for RegisterBits<R> where R: Register
{
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
RegisterBits::new(self.mask & rhs.mask)
}
}
impl<R> ops::BitAndAssign for RegisterBits<R> where R: Register {
fn bitand_assign(&mut self, rhs: Self) {
self.mask &= rhs.mask;
}
}
impl<R> ops::Not for RegisterBits<R> where R: Register {
type Output = Self;
fn not(self) -> Self {
RegisterBits::new(!self.mask)
}
}
impl<R> From<RegisterBits<R>> for u8 where R: Register<T=u8> {
fn from(other: RegisterBits<R>) -> u8 { other.mask }
}
impl<R> From<RegisterBits<R>> for u16 where R: Register<T=u16> {
fn from(other: RegisterBits<R>) -> u16 { other.mask }
}
impl RegisterValue for u8 { }
impl RegisterValue for u16 { }
#[inline(always)]
fn wait_until<F>(mut f: F)
where F: FnMut() -> bool {
loop {
if f() {
break;
}
}
}