use core::ptr::{read_volatile, write_volatile};
use core::ops::{Add, Sub, Not, BitAnd, BitOr, Shl, Shr, BitAndAssign, BitOrAssign};
#[doc = "Zero trait allows types to be created with a value of zero"]
pub trait Zero {
fn zero() -> Self;
}
#[doc = "One trait allows types to be created with a value of one"]
pub trait One {
fn one() -> Self;
}
#[doc = "RegisterType trait allows register implementations to be generic over unsigned integer types"]
pub trait RegisterType<T>: Zero + One
+ Not<Output=T> + Add<T, Output=T> + Sub<T, Output=T>
+ BitAnd<T, Output=T> + BitOr<T, Output=T> + BitAndAssign<T> + BitOrAssign<T>
+ Shl<T, Output=T> + Shr<T, Output=T>
+ Clone + Copy + Default + PartialEq {}
#[doc = "Helper macro to generate RegisterType implementations for a given type"]
#[macro_export]
macro_rules! register_impl {
($t: ty) => {
impl RegisterType<$t> for $t {}
impl One for $t {
fn one() -> $t { 1 }
}
impl Zero for $t {
fn zero() -> $t { 0 }
}
}
}
register_impl!(u8);
register_impl!(u16);
register_impl!(u32);
register_impl!(u64);
#[derive(Debug, PartialEq, Clone)]
pub struct Register<T: RegisterType<T>> (pub(crate) usize, pub(crate) T);
impl <T: RegisterType<T>>Register<T> {
#[doc = "Creates a new register of the provided type with the specified address"]
#[doc = "Note that `impl RegisterType<T> for T {}` is required for unimplemented types"]
pub fn new(addr: usize) -> Register<T> {
Register(addr, T::default())
}
#[doc = "Creates a new 16-bit ride register"]
pub fn u16(addr: usize) -> Register<u16> {
Register::<u16>::new(addr)
}
#[doc = "Creates a new 32-bit register"]
pub fn u32(addr: usize) -> Register<u32> {
Register::<u32>::new(addr)
}
#[doc = "Reads the register value and returns a new instance with internal value set."]
pub fn read(&mut self) -> Register<T> {
let mut reg = self.clone();
unsafe {
reg.1 = read_volatile(self.0 as *const T)
}
reg
}
#[doc = "clears the internal register value"]
pub fn zero(&mut self) -> Register<T> {
let mut reg = self.clone();
reg.1 = T::zero();
reg
}
#[doc = "returns the register value"]
pub fn value(&self) -> T {
self.1.clone()
}
#[doc = "sets the internal value of the register"]
pub fn set(mut self, val: T) -> Register<T> {
self.1 = val;
self
}
#[doc = "boolean and the provided and current values"]
pub fn and(mut self, val: T) -> Register<T> {
self.1 = self.1 & val;
self
}
#[doc = "ors the provided and current values"]
pub fn or(mut self, val: T) -> Register<T> {
self.1 |= val;
self
}
#[doc = "clears the masked area of the provided value"]
pub fn clear(mut self, mask: T) -> Register<T> {
self.1 &= !mask;
self
}
#[doc = "returns a boolean consisting to the indexed bit"]
pub fn get_bit(&self, i: T) -> bool {
self.1.clone() & (T::one() << i) != T::zero()
}
#[doc = "Sets a bit in the current value"]
pub fn set_bit(mut self, i: T, v: bool) -> Register<T> {
self.1 = match v {
true => self.1 | (T::one() << i),
false => self.1 & !(T::one() << i),
};
self
}
#[doc = "Fetches a value with the provided mask and shift"]
#[doc = "Note that shift is applied prior to masking, so mask should always start at 0b1"]
pub fn get_masked(&self, shift: T, mask: T) -> T {
read_masked!(self.1, shift, mask)
}
#[doc = "Sets a value with a provided mask and shift"]
#[doc = "Note that mask is applied before shifting, so mask should always start at 0b1"]
pub fn set_masked(mut self, shift: T, mask: T, val: T) -> Register<T> {
write_masked!(self.1, shift, mask, val);
self
}
#[doc = "Writes the internal value to the register"]
pub fn write(self) {
unsafe {
write_volatile(self.0 as *mut T, self.1)
}
}
}
#[cfg(test)]
mod tests {
use ::register::Register;
#[test]
fn set() {
let mut r = Register::<u16>(0, 0);
assert_eq!(0, r.value());
r = r.set(100);
assert_eq!(100, r.value());
}
#[test]
fn zero() {
let mut r = Register::<u16>(0, 100);
assert_eq!(100, r.value());
r = r.zero();
assert_eq!(0, r.value());
}
#[test]
fn and() {
let mut r = Register::<u16>(0, 0xFFFF);
r = r.and(0xF0F0);
assert_eq!(0xF0F0, r.value());
}
#[test]
fn or() {
let mut r = Register::<u16>(0, 0xF0F0);
r = r.or(0x0F00);
assert_eq!(0xFFF0, r.value());
}
#[test]
fn clear() {
let mut r = Register::<u16>(0, 0xF0F0);
r = r.clear(0xF000);
assert_eq!(0x00F0, r.value());
}
#[test]
fn get_bit() {
let r = Register::<u16>(0, 0b0101);
assert_eq!(true, r.get_bit(0));
assert_eq!(false, r.get_bit(1));
assert_eq!(true, r.get_bit(2));
assert_eq!(false, r.get_bit(3));
}
#[test]
fn set_bit() {
let mut r = Register::<u16>(0, 0b0001);
r = r.set_bit(2, true);
assert_eq!(0b0101, r.value());
r = r.set_bit(2, false);
assert_eq!(0b0001, r.value());
}
#[test]
fn get_masked() {
let mut r = Register::<u16>(0, 0xFAF0);
assert_eq!(0x00, r.get_masked(0, 0xf));
assert_eq!(0x0F, r.get_masked(4, 0xf));
assert_eq!(0xFA, r.get_masked(8, 0xff));
}
#[test]
fn set_masked() {
let mut r = Register::<u16>(0, 0x0000);
r = r.set_masked(0, 0xFF, 0xF0);
assert_eq!(0x00F0, r.value());
r = r.set_masked(8, 0xF, 0xA);
assert_eq!(0x0AF0, r.value());
r = r.set_masked(12, 0xF, 0xB);
assert_eq!(0xBAF0, r.value());
}
}