use crate::{
bitfield::{Bitfield, Bits},
reg::{
tag::{Crt, RegAtomic, RegTag, Srt, Urt},
RReg, Reg, WReg, WoReg,
},
token::Token,
};
use core::ptr::{read_volatile, write_volatile};
pub trait RegField<T: RegTag>: Token + Sync {
type Reg: Reg<T>;
type URegField: RegField<Urt>;
type SRegField: RegField<Srt>;
type CRegField: RegField<Crt>;
const OFFSET: usize;
const WIDTH: usize;
#[inline]
fn into_unsync(self) -> Self
where
Self: RegField<Urt>,
{
self
}
#[inline]
fn into_sync(self) -> Self
where
Self: RegField<Srt>,
{
self
}
#[inline]
fn into_copy(self) -> Self::CRegField
where
T: RegAtomic,
{
unsafe { Self::CRegField::take() }
}
#[inline]
fn as_sync(&self) -> &Self::SRegField
where
T: RegAtomic,
{
unsafe { &*(self as *const Self).cast::<Self::SRegField>() }
}
}
pub trait RegFieldBit<T: RegTag>: RegField<T> {}
pub trait RegFieldBits<T: RegTag>: RegField<T> {}
#[allow(clippy::upper_case_acronyms)]
pub trait RRRegField<T: RegTag>
where
Self: RegField<T>,
Self::Reg: RReg<T>,
{
#[inline]
fn load_val(&self) -> <Self::Reg as Reg<T>>::Val {
unsafe {
Self::Reg::val_from(read_volatile(
Self::Reg::ADDRESS as *const <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits,
))
}
}
}
#[allow(clippy::upper_case_acronyms)]
pub trait WWRegField<T: RegTag>
where
Self: RegField<T>,
Self::Reg: WReg<T>,
{
}
pub trait RoRRegField<T: RegTag>
where
Self: RRRegField<T>,
Self::Reg: RReg<T>,
{
}
pub trait WoWRegField<T: RegTag>
where
Self: WWRegField<T>,
Self::Reg: WReg<T>,
{
}
pub trait WoWoRegField<T: RegTag>
where
Self: WoWRegField<T>,
Self::Reg: WoReg<T>,
{
fn default_val(&self) -> <Self::Reg as Reg<T>>::Val;
fn store_val(&self, val: <Self::Reg as Reg<T>>::Val);
fn store<F>(&self, f: F)
where
F: Fn(&mut <Self::Reg as Reg<T>>::Val);
}
#[allow(clippy::upper_case_acronyms)]
pub trait RRRegFieldBit<T: RegTag>
where
Self: RegFieldBit<T> + RRRegField<T>,
Self::Reg: RReg<T>,
{
fn read(&self, val: &<Self::Reg as Reg<T>>::Val) -> bool;
fn read_bit(&self) -> bool;
}
#[allow(clippy::upper_case_acronyms)]
pub trait WWRegFieldBit<T: RegTag>
where
Self: RegFieldBit<T> + WWRegField<T>,
Self::Reg: WReg<T>,
{
fn set(&self, val: &mut <Self::Reg as Reg<T>>::Val);
fn clear(&self, val: &mut <Self::Reg as Reg<T>>::Val);
fn toggle(&self, val: &mut <Self::Reg as Reg<T>>::Val);
}
pub trait WoWoRegFieldBit<T: RegTag>
where
Self: RegFieldBit<T> + WoWRegField<T>,
Self::Reg: WoReg<T>,
{
fn set_bit(&self);
fn clear_bit(&self);
fn toggle_bit(&self);
}
#[allow(clippy::upper_case_acronyms)]
pub trait RRRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + RRRegField<T>,
Self::Reg: RReg<T>,
{
fn read(
&self,
val: &<Self::Reg as Reg<T>>::Val,
) -> <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits;
fn read_bits(&self) -> <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits;
}
#[allow(clippy::upper_case_acronyms)]
pub trait WWRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + WWRegField<T>,
Self::Reg: WReg<T>,
{
fn write(
&self,
val: &mut <Self::Reg as Reg<T>>::Val,
bits: <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits,
);
}
pub trait WoWoRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + WoWRegField<T>,
Self::Reg: WoReg<T>,
{
fn write_bits(&self, bits: <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits);
}
impl<T, R> WoWoRegField<T> for R
where
T: RegTag,
R: WoWRegField<T>,
R::Reg: WoReg<T>,
{
#[inline]
fn default_val(&self) -> <Self::Reg as Reg<T>>::Val {
unsafe { Self::Reg::val_from(<Self::Reg as Reg<T>>::RESET) }
}
#[inline]
fn store_val(&self, val: <Self::Reg as Reg<T>>::Val) {
unsafe {
write_volatile(
Self::Reg::ADDRESS as *mut <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits,
val.bits(),
);
}
}
#[inline]
fn store<F>(&self, f: F)
where
F: Fn(&mut <Self::Reg as Reg<T>>::Val),
{
let mut val = self.default_val();
f(&mut val);
self.store_val(val);
}
}
impl<T, R> RRRegFieldBit<T> for R
where
T: RegTag,
R: RegFieldBit<T> + RRRegField<T>,
R::Reg: RReg<T>,
{
#[inline]
fn read(&self, val: &<Self::Reg as Reg<T>>::Val) -> bool {
unsafe {
val.read_bit(<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::OFFSET))
}
}
#[inline]
fn read_bit(&self) -> bool {
self.read(&self.load_val())
}
}
impl<T, R> WWRegFieldBit<T> for R
where
T: RegTag,
R: RegFieldBit<T> + WWRegField<T>,
R::Reg: WReg<T>,
{
#[inline]
fn set(&self, val: &mut <Self::Reg as Reg<T>>::Val) {
unsafe {
val.set_bit(<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::OFFSET));
}
}
#[inline]
fn clear(&self, val: &mut <Self::Reg as Reg<T>>::Val) {
unsafe {
val.clear_bit(<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::OFFSET));
}
}
#[inline]
fn toggle(&self, val: &mut <Self::Reg as Reg<T>>::Val) {
unsafe {
val.toggle_bit(<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(
Self::OFFSET,
));
}
}
}
impl<T, R> WoWoRegFieldBit<T> for R
where
T: RegTag,
R: RegFieldBit<T> + WoWRegField<T>,
R::Reg: WoReg<T>,
{
#[inline]
fn set_bit(&self) {
self.store(|val| {
self.set(val);
});
}
#[inline]
fn clear_bit(&self) {
self.store(|val| {
self.clear(val);
});
}
#[inline]
fn toggle_bit(&self) {
self.store(|val| {
self.toggle(val);
});
}
}
impl<T, R> RRRegFieldBits<T> for R
where
T: RegTag,
R: RegFieldBits<T> + RRRegField<T>,
R::Reg: RReg<T>,
{
#[inline]
fn read(
&self,
val: &<Self::Reg as Reg<T>>::Val,
) -> <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits {
unsafe {
val.read_bits(
<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::OFFSET),
<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::WIDTH),
)
}
}
#[inline]
fn read_bits(&self) -> <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits {
self.read(&self.load_val())
}
}
impl<T, R> WWRegFieldBits<T> for R
where
T: RegTag,
R: RegFieldBits<T> + WWRegField<T>,
R::Reg: WReg<T>,
{
#[inline]
fn write(
&self,
val: &mut <Self::Reg as Reg<T>>::Val,
bits: <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits,
) {
unsafe {
val.write_bits(
<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::OFFSET),
<<Self::Reg as Reg<T>>::Val as Bitfield>::Bits::from_usize(Self::WIDTH),
bits,
);
}
}
}
impl<T, R> WoWoRegFieldBits<T> for R
where
T: RegTag,
R: RegFieldBits<T> + WoWRegField<T>,
R::Reg: WoReg<T>,
{
#[inline]
fn write_bits(&self, bits: <<Self::Reg as Reg<T>>::Val as Bitfield>::Bits) {
self.store(|val| {
self.write(val, bits);
});
}
}