#![allow(clippy::suspicious_op_assign_impl)]
#![allow(clippy::suspicious_arithmetic_impl)]
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Add, AddAssign, BitAnd, BitOr, Not, Shl, Shr};
pub trait IntLike:
BitAnd<Output = Self>
+ BitOr<Output = Self>
+ Not<Output = Self>
+ Eq
+ Shr<usize, Output = Self>
+ Shl<usize, Output = Self>
+ Copy
+ Clone
{
fn zero() -> Self;
}
impl IntLike for u8 {
fn zero() -> Self {
0
}
}
impl IntLike for u16 {
fn zero() -> Self {
0
}
}
impl IntLike for u32 {
fn zero() -> Self {
0
}
}
impl IntLike for u64 {
fn zero() -> Self {
0
}
}
pub trait RegisterLongName {}
impl RegisterLongName for () {}
pub trait TryFromValue<V> {
type EnumType;
fn try_from(v: V) -> Option<Self::EnumType>;
}
#[repr(transparent)]
pub struct ReadWrite<T: IntLike, R: RegisterLongName = ()> {
value: T,
associated_register: PhantomData<R>,
}
#[repr(transparent)]
pub struct ReadOnly<T: IntLike, R: RegisterLongName = ()> {
value: T,
associated_register: PhantomData<R>,
}
#[repr(transparent)]
pub struct WriteOnly<T: IntLike, R: RegisterLongName = ()> {
value: T,
associated_register: PhantomData<R>,
}
impl<T: IntLike, R: RegisterLongName> ReadWrite<T, R> {
#[inline]
pub fn get(&self) -> T {
unsafe { ::core::ptr::read_volatile(&self.value) }
}
#[inline]
pub fn set(&self, value: T) {
unsafe { ::core::ptr::write_volatile(&self.value as *const T as *mut T, value) }
}
#[inline]
pub fn read(&self, field: Field<T, R>) -> T {
(self.get() & (field.mask << field.shift)) >> field.shift
}
#[inline]
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
let val: T = self.read(field);
E::try_from(val)
}
#[inline]
pub fn extract(&self) -> LocalRegisterCopy<T, R> {
LocalRegisterCopy::new(self.get())
}
#[inline]
pub fn write(&self, field: FieldValue<T, R>) {
self.set(field.value);
}
#[inline]
pub fn modify(&self, field: FieldValue<T, R>) {
let reg: T = self.get();
self.set((reg & !field.mask) | field.value);
}
#[inline]
pub fn modify_no_read(&self, original: LocalRegisterCopy<T, R>, field: FieldValue<T, R>) {
self.set((original.get() & !field.mask) | field.value);
}
#[inline]
pub fn is_set(&self, field: Field<T, R>) -> bool {
self.read(field) != T::zero()
}
#[inline]
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask != T::zero()
}
#[inline]
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask == field.value
}
}
impl<T: IntLike, R: RegisterLongName> ReadOnly<T, R> {
#[inline]
pub fn get(&self) -> T {
unsafe { ::core::ptr::read_volatile(&self.value) }
}
#[inline]
pub fn read(&self, field: Field<T, R>) -> T {
(self.get() & (field.mask << field.shift)) >> field.shift
}
#[inline]
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
let val: T = self.read(field);
E::try_from(val)
}
#[inline]
pub fn extract(&self) -> LocalRegisterCopy<T, R> {
LocalRegisterCopy::new(self.get())
}
#[inline]
pub fn is_set(&self, field: Field<T, R>) -> bool {
self.read(field) != T::zero()
}
#[inline]
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask != T::zero()
}
#[inline]
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask == field.value
}
}
impl<T: IntLike, R: RegisterLongName> WriteOnly<T, R> {
#[inline]
pub fn set(&self, value: T) {
unsafe { ::core::ptr::write_volatile(&self.value as *const T as *mut T, value) }
}
#[inline]
pub fn write(&self, field: FieldValue<T, R>) {
self.set(field.value);
}
}
#[derive(Copy, Clone)]
pub struct LocalRegisterCopy<T: IntLike, R: RegisterLongName = ()> {
value: T,
associated_register: PhantomData<R>,
}
impl<T: IntLike, R: RegisterLongName> LocalRegisterCopy<T, R> {
pub const fn new(value: T) -> Self {
LocalRegisterCopy {
value: value,
associated_register: PhantomData,
}
}
#[inline]
pub fn get(&self) -> T {
self.value
}
#[inline]
pub fn read(&self, field: Field<T, R>) -> T {
(self.value & (field.mask << field.shift)) >> field.shift
}
#[inline]
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
let val: T = self.read(field);
E::try_from(val)
}
#[inline]
pub fn is_set(&self, field: Field<T, R>) -> bool {
self.read(field) != T::zero()
}
#[inline]
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
self.value & field.mask != T::zero()
}
#[inline]
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
self.value & field.mask == field.value
}
#[inline]
pub fn bitand(&self, rhs: T) -> LocalRegisterCopy<T, R> {
LocalRegisterCopy::new(self.value & rhs)
}
}
impl<T: IntLike + fmt::Debug, R: RegisterLongName> fmt::Debug for LocalRegisterCopy<T, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.value)
}
}
impl<R: RegisterLongName> From<LocalRegisterCopy<u8, R>> for u8 {
fn from(r: LocalRegisterCopy<u8, R>) -> u8 {
r.value
}
}
impl<R: RegisterLongName> From<LocalRegisterCopy<u16, R>> for u16 {
fn from(r: LocalRegisterCopy<u16, R>) -> u16 {
r.value
}
}
impl<R: RegisterLongName> From<LocalRegisterCopy<u32, R>> for u32 {
fn from(r: LocalRegisterCopy<u32, R>) -> u32 {
r.value
}
}
impl<R: RegisterLongName> From<LocalRegisterCopy<u64, R>> for u64 {
fn from(r: LocalRegisterCopy<u64, R>) -> u64 {
r.value
}
}
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct InMemoryRegister<T: IntLike, R: RegisterLongName = ()> {
value: T,
associated_register: PhantomData<R>,
}
impl<T: IntLike, R: RegisterLongName> InMemoryRegister<T, R> {
pub const fn new(value: T) -> Self {
InMemoryRegister {
value: value,
associated_register: PhantomData,
}
}
#[inline]
pub fn get(&self) -> T {
unsafe { ::core::ptr::read_volatile(&self.value) }
}
#[inline]
pub fn set(&self, value: T) {
unsafe { ::core::ptr::write_volatile(&self.value as *const T as *mut T, value) }
}
#[inline]
pub fn read(&self, field: Field<T, R>) -> T {
(self.get() & (field.mask << field.shift)) >> field.shift
}
#[inline]
pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(&self, field: Field<T, R>) -> Option<E> {
let val: T = self.read(field);
E::try_from(val)
}
#[inline]
pub fn extract(&self) -> LocalRegisterCopy<T, R> {
LocalRegisterCopy::new(self.get())
}
#[inline]
pub fn write(&self, field: FieldValue<T, R>) {
self.set(field.value);
}
#[inline]
pub fn modify(&self, field: FieldValue<T, R>) {
let reg: T = self.get();
self.set((reg & !field.mask) | field.value);
}
#[inline]
pub fn modify_no_read(&self, original: LocalRegisterCopy<T, R>, field: FieldValue<T, R>) {
self.set((original.get() & !field.mask) | field.value);
}
#[inline]
pub fn is_set(&self, field: Field<T, R>) -> bool {
self.read(field) != T::zero()
}
#[inline]
pub fn matches_any(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask != T::zero()
}
#[inline]
pub fn matches_all(&self, field: FieldValue<T, R>) -> bool {
self.get() & field.mask == field.value
}
}
#[derive(Copy, Clone)]
pub struct Field<T: IntLike, R: RegisterLongName> {
pub mask: T,
pub shift: usize,
associated_register: PhantomData<R>,
}
impl<R: RegisterLongName> Field<u8, R> {
pub const fn new(mask: u8, shift: usize) -> Field<u8, R> {
Field {
mask: mask,
shift: shift,
associated_register: PhantomData,
}
}
pub fn val(&self, value: u8) -> FieldValue<u8, R> {
FieldValue::<u8, R>::new(self.mask, self.shift, value)
}
}
impl<R: RegisterLongName> Field<u16, R> {
pub const fn new(mask: u16, shift: usize) -> Field<u16, R> {
Field {
mask: mask,
shift: shift,
associated_register: PhantomData,
}
}
pub fn val(&self, value: u16) -> FieldValue<u16, R> {
FieldValue::<u16, R>::new(self.mask, self.shift, value)
}
}
impl<R: RegisterLongName> Field<u32, R> {
pub const fn new(mask: u32, shift: usize) -> Field<u32, R> {
Field {
mask: mask,
shift: shift,
associated_register: PhantomData,
}
}
pub fn val(&self, value: u32) -> FieldValue<u32, R> {
FieldValue::<u32, R>::new(self.mask, self.shift, value)
}
}
impl<R: RegisterLongName> Field<u64, R> {
pub const fn new(mask: u64, shift: usize) -> Field<u64, R> {
Field {
mask: mask,
shift: shift,
associated_register: PhantomData,
}
}
pub fn val(&self, value: u64) -> FieldValue<u64, R> {
FieldValue::<u64, R>::new(self.mask, self.shift, value)
}
}
#[derive(Copy, Clone)]
pub struct FieldValue<T: IntLike, R: RegisterLongName> {
pub mask: T,
pub value: T,
associated_register: PhantomData<R>,
}
impl<R: RegisterLongName> FieldValue<u8, R> {
pub const fn new(mask: u8, shift: usize, value: u8) -> Self {
FieldValue {
mask: mask << shift,
value: (value << shift) & (mask << shift),
associated_register: PhantomData,
}
}
pub fn mask(self) -> u8 {
self.mask as u8
}
#[inline]
pub fn read(&self, field: Field<u8, R>) -> u8 {
(self.value & (field.mask << field.shift)) >> field.shift
}
}
impl<R: RegisterLongName> From<FieldValue<u8, R>> for u8 {
fn from(val: FieldValue<u8, R>) -> u8 {
val.value
}
}
impl<R: RegisterLongName> FieldValue<u16, R> {
pub const fn new(mask: u16, shift: usize, value: u16) -> Self {
FieldValue {
mask: mask << shift,
value: (value << shift) & (mask << shift),
associated_register: PhantomData,
}
}
pub fn mask(self) -> u16 {
self.mask as u16
}
#[inline]
pub fn read(&self, field: Field<u16, R>) -> u16 {
(self.value & (field.mask << field.shift)) >> field.shift
}
}
impl<R: RegisterLongName> From<FieldValue<u16, R>> for u16 {
fn from(val: FieldValue<u16, R>) -> u16 {
val.value
}
}
impl<R: RegisterLongName> FieldValue<u32, R> {
pub const fn new(mask: u32, shift: usize, value: u32) -> Self {
FieldValue {
mask: mask << shift,
value: (value << shift) & (mask << shift),
associated_register: PhantomData,
}
}
pub fn mask(self) -> u32 {
self.mask as u32
}
#[inline]
pub fn read(&self, field: Field<u32, R>) -> u32 {
(self.value & (field.mask << field.shift)) >> field.shift
}
}
impl<R: RegisterLongName> From<FieldValue<u32, R>> for u32 {
fn from(val: FieldValue<u32, R>) -> u32 {
val.value
}
}
impl<R: RegisterLongName> FieldValue<u64, R> {
pub const fn new(mask: u64, shift: usize, value: u64) -> Self {
FieldValue {
mask: mask << shift,
value: (value << shift) & (mask << shift),
associated_register: PhantomData,
}
}
pub fn mask(self) -> u64 {
self.mask as u64
}
#[inline]
pub fn read(&self, field: Field<u64, R>) -> u64 {
(self.value & (field.mask << field.shift)) >> field.shift
}
}
impl<R: RegisterLongName> From<FieldValue<u64, R>> for u64 {
fn from(val: FieldValue<u64, R>) -> u64 {
val.value
}
}
impl<T: IntLike, R: RegisterLongName> FieldValue<T, R> {
pub fn modify(self, val: T) -> T {
(val & !self.mask) | self.value
}
}
impl<T: IntLike, R: RegisterLongName> Add for FieldValue<T, R> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
FieldValue {
mask: self.mask | rhs.mask,
value: self.value | rhs.value,
associated_register: PhantomData,
}
}
}
impl<T: IntLike, R: RegisterLongName> AddAssign for FieldValue<T, R> {
fn add_assign(&mut self, rhs: FieldValue<T, R>) {
*self = FieldValue {
mask: self.mask | rhs.mask,
value: self.value | rhs.value,
associated_register: PhantomData,
};
}
}