use core::marker;
pub struct Periph<RB, const A: usize> {
_marker: marker::PhantomData<RB>,
}
unsafe impl<RB, const A: usize> Send for Periph<RB, A> {}
impl<RB, const A: usize> Periph<RB, A> {
pub const PTR: *const RB = A as *const _;
#[inline(always)]
pub const fn ptr() -> *const RB {
Self::PTR
}
pub unsafe fn steal() -> Self {
Self {
_marker: marker::PhantomData,
}
}
}
impl<RB, const A: usize> core::ops::Deref for Periph<RB, A> {
type Target = RB;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
pub trait RawReg:
Copy
+ From<bool>
+ core::ops::BitOr<Output = Self>
+ core::ops::BitAnd<Output = Self>
+ core::ops::BitOrAssign
+ core::ops::BitAndAssign
+ core::ops::Not<Output = Self>
+ core::ops::Shl<u8, Output = Self>
{
fn mask<const WI: u8>() -> Self;
const ZERO: Self;
const ONE: Self;
}
macro_rules! raw_reg {
($U:ty, $size:literal, $mask:ident) => {
impl RawReg for $U {
#[inline(always)]
fn mask<const WI: u8>() -> Self {
$mask::<WI>()
}
const ZERO: Self = 0;
const ONE: Self = 1;
}
const fn $mask<const WI: u8>() -> $U {
<$U>::MAX >> ($size - WI)
}
impl FieldSpec for $U {
type Ux = $U;
}
};
}
raw_reg!(u8, 8, mask_u8);
raw_reg!(u16, 16, mask_u16);
raw_reg!(u32, 32, mask_u32);
raw_reg!(u64, 64, mask_u64);
pub trait RegisterSpec {
type Ux: RawReg;
}
pub trait FieldSpec: Sized {
type Ux: Copy + core::fmt::Debug + PartialEq + From<Self>;
}
pub trait IsEnum: FieldSpec {}
pub trait Readable: RegisterSpec {}
pub trait Writable: RegisterSpec {
type Safety;
const ZERO_TO_MODIFY_FIELDS_BITMAP: Self::Ux = Self::Ux::ZERO;
const ONE_TO_MODIFY_FIELDS_BITMAP: Self::Ux = Self::Ux::ZERO;
}
pub trait Resettable: RegisterSpec {
const RESET_VALUE: Self::Ux = Self::Ux::ZERO;
#[inline(always)]
fn reset_value() -> Self::Ux {
Self::RESET_VALUE
}
}
#[doc(hidden)]
pub mod raw {
use super::{marker, BitM, FieldSpec, RegisterSpec, Unsafe, Writable};
pub struct R<REG: RegisterSpec> {
pub(crate) bits: REG::Ux,
pub(super) _reg: marker::PhantomData<REG>,
}
pub struct W<REG: RegisterSpec> {
pub(crate) bits: REG::Ux,
pub(super) _reg: marker::PhantomData<REG>,
}
pub struct FieldReader<FI = u8>
where
FI: FieldSpec,
{
pub(crate) bits: FI::Ux,
_reg: marker::PhantomData<FI>,
}
impl<FI: FieldSpec> FieldReader<FI> {
#[allow(unused)]
#[inline(always)]
pub(crate) const fn new(bits: FI::Ux) -> Self {
Self {
bits,
_reg: marker::PhantomData,
}
}
}
pub struct BitReader<FI = bool> {
pub(crate) bits: bool,
_reg: marker::PhantomData<FI>,
}
impl<FI> BitReader<FI> {
#[allow(unused)]
#[inline(always)]
pub(crate) const fn new(bits: bool) -> Self {
Self {
bits,
_reg: marker::PhantomData,
}
}
}
#[must_use = "after creating `FieldWriter` you need to call field value setting method"]
pub struct FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
{
pub(crate) w: &'a mut W<REG>,
pub(crate) o: u8,
_field: marker::PhantomData<(FI, Safety)>,
}
impl<'a, REG, const WI: u8, FI, Safety> FieldWriter<'a, REG, WI, FI, Safety>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
{
#[allow(unused)]
#[inline(always)]
pub(crate) fn new(w: &'a mut W<REG>, o: u8) -> Self {
Self {
w,
o,
_field: marker::PhantomData,
}
}
}
#[must_use = "after creating `BitWriter` you need to call bit setting method"]
pub struct BitWriter<'a, REG, FI = bool, M = BitM>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
pub(crate) w: &'a mut W<REG>,
pub(crate) o: u8,
_field: marker::PhantomData<(FI, M)>,
}
impl<'a, REG, FI, M> BitWriter<'a, REG, FI, M>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[allow(unused)]
#[inline(always)]
pub(crate) fn new(w: &'a mut W<REG>, o: u8) -> Self {
Self {
w,
o,
_field: marker::PhantomData,
}
}
}
}
pub type R<REG> = raw::R<REG>;
impl<REG: RegisterSpec> R<REG> {
#[inline(always)]
pub const fn bits(&self) -> REG::Ux {
self.bits
}
}
impl<REG: RegisterSpec, FI> PartialEq<FI> for R<REG>
where
REG::Ux: PartialEq,
FI: Copy,
REG::Ux: From<FI>,
{
#[inline(always)]
fn eq(&self, other: &FI) -> bool {
self.bits.eq(®::Ux::from(*other))
}
}
pub type W<REG> = raw::W<REG>;
impl<REG: Writable> W<REG> {
#[inline(always)]
pub unsafe fn bits(&mut self, bits: REG::Ux) -> &mut Self {
self.bits = bits;
self
}
}
impl<REG> W<REG>
where
REG: Writable<Safety = Safe>,
{
#[inline(always)]
pub fn set(&mut self, bits: REG::Ux) -> &mut Self {
self.bits = bits;
self
}
}
pub type FieldReader<FI = u8> = raw::FieldReader<FI>;
pub type BitReader<FI = bool> = raw::BitReader<FI>;
impl<FI: FieldSpec> FieldReader<FI> {
#[inline(always)]
pub const fn bits(&self) -> FI::Ux {
self.bits
}
}
impl<FI: FieldSpec> core::fmt::Debug for FieldReader<FI> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.bits, f)
}
}
impl<FI> PartialEq<FI> for FieldReader<FI>
where
FI: FieldSpec + Copy,
{
#[inline(always)]
fn eq(&self, other: &FI) -> bool {
self.bits.eq(&FI::Ux::from(*other))
}
}
impl<FI> PartialEq<FI> for BitReader<FI>
where
FI: Copy,
bool: From<FI>,
{
#[inline(always)]
fn eq(&self, other: &FI) -> bool {
self.bits.eq(&bool::from(*other))
}
}
impl<FI> BitReader<FI> {
#[inline(always)]
pub const fn bit(&self) -> bool {
self.bits
}
#[inline(always)]
pub const fn bit_is_clear(&self) -> bool {
!self.bit()
}
#[inline(always)]
pub const fn bit_is_set(&self) -> bool {
self.bit()
}
}
impl<FI> core::fmt::Debug for BitReader<FI> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.bits, f)
}
}
pub struct Safe;
pub struct Unsafe;
pub struct Range<const MIN: u64, const MAX: u64>;
pub struct RangeFrom<const MIN: u64>;
pub struct RangeTo<const MAX: u64>;
pub type FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe> =
raw::FieldWriter<'a, REG, WI, FI, Safety>;
impl<REG, const WI: u8, FI, Safety> FieldWriter<'_, REG, WI, FI, Safety>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
{
pub const WIDTH: u8 = WI;
#[inline(always)]
pub const fn width(&self) -> u8 {
WI
}
#[inline(always)]
pub const fn offset(&self) -> u8 {
self.o
}
}
impl<'a, REG, const WI: u8, FI, Safety> FieldWriter<'a, REG, WI, FI, Safety>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
REG::Ux: From<FI::Ux>,
{
#[inline(always)]
pub unsafe fn bits(self, value: FI::Ux) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::mask::<WI>() << self.o);
self.w.bits |= (REG::Ux::from(value) & REG::Ux::mask::<WI>()) << self.o;
self.w
}
}
impl<'a, REG, const WI: u8, FI> FieldWriter<'a, REG, WI, FI, Safe>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
REG::Ux: From<FI::Ux>,
{
#[inline(always)]
pub fn set(self, value: FI::Ux) -> &'a mut W<REG> {
unsafe { self.bits(value) }
}
}
impl<'a, REG, const WI: u8, FI, const MIN: u64, const MAX: u64>
FieldWriter<'a, REG, WI, FI, Range<MIN, MAX>>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
REG::Ux: From<FI::Ux>,
u64: From<FI::Ux>,
{
#[inline(always)]
pub fn set(self, value: FI::Ux) -> &'a mut W<REG> {
{
let value = u64::from(value);
assert!(value >= MIN && value <= MAX);
}
unsafe { self.bits(value) }
}
}
impl<'a, REG, const WI: u8, FI, const MIN: u64> FieldWriter<'a, REG, WI, FI, RangeFrom<MIN>>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
REG::Ux: From<FI::Ux>,
u64: From<FI::Ux>,
{
#[inline(always)]
pub fn set(self, value: FI::Ux) -> &'a mut W<REG> {
{
let value = u64::from(value);
assert!(value >= MIN);
}
unsafe { self.bits(value) }
}
}
impl<'a, REG, const WI: u8, FI, const MAX: u64> FieldWriter<'a, REG, WI, FI, RangeTo<MAX>>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
REG::Ux: From<FI::Ux>,
u64: From<FI::Ux>,
{
#[inline(always)]
pub fn set(self, value: FI::Ux) -> &'a mut W<REG> {
{
let value = u64::from(value);
assert!(value <= MAX);
}
unsafe { self.bits(value) }
}
}
impl<'a, REG, const WI: u8, FI, Safety> FieldWriter<'a, REG, WI, FI, Safety>
where
REG: Writable + RegisterSpec,
FI: IsEnum,
REG::Ux: From<FI::Ux>,
{
#[inline(always)]
pub fn variant(self, variant: FI) -> &'a mut W<REG> {
unsafe { self.bits(FI::Ux::from(variant)) }
}
}
macro_rules! bit_proxy {
($writer:ident, $mwv:ident) => {
#[doc(hidden)]
pub struct $mwv;
/// Bit-wise write field proxy
pub type $writer<'a, REG, FI = bool> = raw::BitWriter<'a, REG, FI, $mwv>;
impl<'a, REG, FI> $writer<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
pub const WIDTH: u8 = 1;
#[inline(always)]
pub const fn width(&self) -> u8 {
Self::WIDTH
}
#[inline(always)]
pub const fn offset(&self) -> u8 {
self.o
}
#[inline(always)]
pub fn bit(self, value: bool) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w.bits |= (REG::Ux::from(value) & REG::Ux::ONE) << self.o;
self.w
}
#[inline(always)]
pub fn variant(self, variant: FI) -> &'a mut W<REG> {
self.bit(bool::from(variant))
}
}
};
}
bit_proxy!(BitWriter, BitM);
bit_proxy!(BitWriter1S, Bit1S);
bit_proxy!(BitWriter0C, Bit0C);
bit_proxy!(BitWriter1C, Bit1C);
bit_proxy!(BitWriter0S, Bit0S);
bit_proxy!(BitWriter1T, Bit1T);
bit_proxy!(BitWriter0T, Bit0T);
impl<'a, REG, FI> BitWriter<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn set_bit(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
#[inline(always)]
pub fn clear_bit(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
impl<'a, REG, FI> BitWriter1S<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn set_bit(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
impl<'a, REG, FI> BitWriter0C<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn clear_bit(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
impl<'a, REG, FI> BitWriter1C<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn clear_bit_by_one(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
impl<'a, REG, FI> BitWriter0S<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn set_bit_by_zero(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
impl<'a, REG, FI> BitWriter1T<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn toggle_bit(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
impl<'a, REG, FI> BitWriter0T<'a, REG, FI>
where
REG: Writable + RegisterSpec,
bool: From<FI>,
{
#[inline(always)]
pub fn toggle_bit(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}