use super::*;
use core::ptr::{read_volatile, write_volatile};
pub trait RegField<T: RegTag>: Sized {
type Reg: Reg<T>;
const OFFSET: usize;
const WIDTH: usize;
}
pub trait RegFieldBit<T: RegTag>: RegField<T> {}
pub trait RegFieldBits<T: RegTag>: RegField<T> {}
pub trait RRegField<T: RegTag>
where
Self: RegField<T>,
Self::Reg: RReg<T>,
{
#[inline(always)]
fn load_val(&self) -> <Self::Reg as Reg<T>>::Val {
unsafe {
<Self::Reg as Reg<T>>::Val::from_raw(read_volatile(
Self::Reg::ADDRESS
as *const <<Self::Reg as Reg<T>>::Val as RegVal>::Raw,
))
}
}
}
pub trait WRegField<T: RegTag>
where
Self: RegField<T>,
Self::Reg: WReg<T>,
{
}
pub trait RoRegField<T: RegTag>
where
Self: RRegField<T>,
Self::Reg: RReg<T>,
{
}
pub trait WoRegField<T: RegTag>
where
Self: WRegField<T>,
Self::Reg: WReg<T>,
{
}
pub trait WoWoRegField<T: RegTag>
where
Self: WoRegField<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 reset<F>(&self, f: F)
where
F: Fn(&mut <Self::Reg as Reg<T>>::Val);
}
pub trait RRegFieldBit<T: RegTag>
where
Self: RegFieldBit<T> + RRegField<T>,
Self::Reg: RReg<T>,
{
fn read(&self, val: &<Self::Reg as Reg<T>>::Val) -> bool;
fn read_bit(&self) -> bool;
}
pub trait WRegFieldBit<T: RegTag>
where
Self: RegFieldBit<T> + WRegField<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> + WoRegField<T>,
Self::Reg: WoReg<T>,
{
fn set_bit(&self);
fn clear_bit(&self);
fn toggle_bit(&self);
}
pub trait RRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + RRegField<T>,
Self::Reg: RReg<T>,
{
fn read(
&self,
val: &<Self::Reg as Reg<T>>::Val,
) -> <<Self::Reg as Reg<T>>::Val as RegVal>::Raw;
fn read_bits(&self) -> <<Self::Reg as Reg<T>>::Val as RegVal>::Raw;
}
pub trait WRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + WRegField<T>,
Self::Reg: WReg<T>,
{
fn write(
&self,
val: &mut <Self::Reg as Reg<T>>::Val,
bits: <<Self::Reg as Reg<T>>::Val as RegVal>::Raw,
);
}
pub trait WoWoRegFieldBits<T: RegTag>
where
Self: RegFieldBits<T> + WoRegField<T>,
Self::Reg: WoReg<T>,
{
fn write_bits(&self, bits: <<Self::Reg as Reg<T>>::Val as RegVal>::Raw);
}
impl<T, U> WoWoRegField<T> for U
where
T: RegTag,
U: WoRegField<T>,
U::Reg: WoReg<T>,
{
#[inline(always)]
fn default_val(&self) -> <U::Reg as Reg<T>>::Val {
unsafe { <U::Reg as Reg<T>>::Val::default() }
}
#[inline(always)]
fn store_val(&self, val: <U::Reg as Reg<T>>::Val) {
unsafe {
write_volatile(
U::Reg::ADDRESS as *mut <<U::Reg as Reg<T>>::Val as RegVal>::Raw,
val.raw(),
);
}
}
#[inline(always)]
fn reset<F>(&self, f: F)
where
F: Fn(&mut <U::Reg as Reg<T>>::Val),
{
let mut val = self.default_val();
f(&mut val);
self.store_val(val);
}
}
impl<T, U> RRegFieldBit<T> for U
where
T: RegTag,
U: RegFieldBit<T> + RRegField<T>,
U::Reg: RReg<T>,
{
#[inline(always)]
fn read(&self, val: &<U::Reg as Reg<T>>::Val) -> bool {
unsafe {
val.read_bit(<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(
U::OFFSET,
))
}
}
#[inline(always)]
fn read_bit(&self) -> bool {
self.read(&self.load_val())
}
}
impl<T, U> WRegFieldBit<T> for U
where
T: RegTag,
U: RegFieldBit<T> + WRegField<T>,
U::Reg: WReg<T>,
{
#[inline(always)]
fn set(&self, val: &mut <U::Reg as Reg<T>>::Val) {
unsafe {
val.set_bit(<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(
U::OFFSET,
));
}
}
#[inline(always)]
fn clear(&self, val: &mut <U::Reg as Reg<T>>::Val) {
unsafe {
val.clear_bit(<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(
U::OFFSET,
));
}
}
#[inline(always)]
fn toggle(&self, val: &mut <U::Reg as Reg<T>>::Val) {
unsafe {
val.toggle_bit(<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(
U::OFFSET,
));
}
}
}
impl<T, U> WoWoRegFieldBit<T> for U
where
T: RegTag,
U: RegFieldBit<T> + WoRegField<T>,
U::Reg: WoReg<T>,
{
#[inline(always)]
fn set_bit(&self) {
self.reset(|val| {
self.set(val);
});
}
#[inline(always)]
fn clear_bit(&self) {
self.reset(|val| {
self.clear(val);
});
}
#[inline(always)]
fn toggle_bit(&self) {
self.reset(|val| {
self.toggle(val);
});
}
}
impl<T, U> RRegFieldBits<T> for U
where
T: RegTag,
U: RegFieldBits<T> + RRegField<T>,
U::Reg: RReg<T>,
{
#[inline(always)]
fn read(
&self,
val: &<U::Reg as Reg<T>>::Val,
) -> <<U::Reg as Reg<T>>::Val as RegVal>::Raw {
unsafe {
val.read_bits(
<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(U::OFFSET),
<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(U::WIDTH),
)
}
}
#[inline(always)]
fn read_bits(&self) -> <<U::Reg as Reg<T>>::Val as RegVal>::Raw {
self.read(&self.load_val())
}
}
impl<T, U> WRegFieldBits<T> for U
where
T: RegTag,
U: RegFieldBits<T> + WRegField<T>,
U::Reg: WReg<T>,
{
#[inline(always)]
fn write(
&self,
val: &mut <U::Reg as Reg<T>>::Val,
bits: <<U::Reg as Reg<T>>::Val as RegVal>::Raw,
) {
unsafe {
val.write_bits(
<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(U::OFFSET),
<<U::Reg as Reg<T>>::Val as RegVal>::Raw::from_usize(U::WIDTH),
bits,
);
}
}
}
impl<T, U> WoWoRegFieldBits<T> for U
where
T: RegTag,
U: RegFieldBits<T> + WoRegField<T>,
U::Reg: WoReg<T>,
{
#[inline(always)]
fn write_bits(&self, bits: <<U::Reg as Reg<T>>::Val as RegVal>::Raw) {
self.reset(|val| {
self.write(val, bits);
});
}
}