use crate::ral::pwm;
type AnyPwmInstance = crate::AnyInstance<pwm::RegisterBlock>;
pub struct Pwm {
pwm: AnyPwmInstance,
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Mask : u8 {
const SM0 = 1 << 0;
const SM1 = 1 << 1;
const SM2 = 1 << 2;
const SM3 = 1 << 3;
}
}
impl Pwm {
pub fn new<const N: u8>(pwm: pwm::Instance<N>) -> Self {
self::new(crate::into_any(pwm))
}
pub fn load_ok(&self) -> Mask {
let ldok = crate::ral::read_reg!(crate::ral::pwm, self.pwm, MCTRL, LDOK);
Mask::from_bits_truncate(ldok as u8)
}
pub fn set_load_ok(&mut self, mask: Mask) {
crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, LDOK: mask.bits() as u16);
}
pub fn clear_load_ok(&mut self, mask: Mask) {
crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, CLDOK: mask.bits() as u16);
}
pub fn run(&self) -> Mask {
let run = crate::ral::read_reg!(crate::ral::pwm, self.pwm, MCTRL, RUN);
Mask::from_bits_truncate(run as u8)
}
pub fn set_run(&mut self, mask: Mask) {
crate::ral::modify_reg!(crate::ral::pwm, self.pwm, MCTRL, RUN: mask.bits() as u16);
}
pub fn output_enable(&self, channel: Channel) -> Mask {
let mask = match channel {
Channel::A => crate::ral::read_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMA_EN),
Channel::B => crate::ral::read_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMB_EN),
};
Mask::from_bits_truncate(mask as u8)
}
pub fn set_output_enable(&mut self, mask: Mask, channel: Channel) {
let mask = mask.bits() as u16;
match channel {
Channel::A => crate::ral::modify_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMA_EN: mask),
Channel::B => crate::ral::modify_reg!(crate::ral::pwm, self.pwm, OUTEN, PWMB_EN: mask),
}
}
}
impl Pwm {
fn submodule(&self, sm: SM) -> &pwm::sm::RegisterBlock {
&self.pwm.SM[sm as usize]
}
pub fn sm_count(&self, sm: SM) -> i16 {
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCNT) as _
}
pub fn initial_count(&self, sm: SM) -> i16 {
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMINIT) as _
}
pub fn set_initial_count(&self, sm: SM, counter: i16) {
crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMINIT, counter as _);
}
pub fn load_frequency(&self, sm: SM) -> u16 {
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDFQ) + 1
}
pub fn set_load_frequency(&mut self, sm: SM, ldfq: u16) {
let ldfq = ldfq.clamp(1, 16) - 1;
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDFQ: ldfq);
}
pub fn prescaler(&self, sm: SM) -> Prescaler {
let prescaler = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, PRSC);
#[allow(clippy::assertions_on_constants)]
{
use pwm::sm::SMCTRL;
const _: () = assert!(SMCTRL::PRSC::mask >> SMCTRL::PRSC::offset == 7u16);
const _: () = assert!(Prescaler::Prescaler128 as u16 == 7u16);
}
unsafe { core::mem::transmute(prescaler) }
}
pub fn set_prescaler(&mut self, sm: SM, prescaler: Prescaler) {
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, PRSC: prescaler as u16)
}
pub fn pair_operation(&self, sm: SM) -> PairOperation {
let indep = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, INDEP);
#[allow(clippy::assertions_on_constants)]
{
use pwm::sm::SMCTRL2;
const _: () = assert!(SMCTRL2::INDEP::mask >> SMCTRL2::INDEP::offset == 1u16);
}
unsafe { core::mem::transmute(indep) }
}
pub fn set_pair_operation(&mut self, sm: SM, pair_operation: PairOperation) {
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, INDEP: pair_operation as u16);
}
pub fn debug_enable(&self, sm: SM) -> bool {
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, DBGEN == 1)
}
pub fn set_debug_enable(&mut self, sm: SM, enable: bool) {
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, DBGEN: enable as u16);
}
pub fn wait_enable(&self, sm: SM) -> bool {
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, WAITEN == 1)
}
pub fn set_wait_enable(&mut self, sm: SM, enable: bool) {
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, WAITEN: enable as u16);
}
pub fn clock_select(&self, sm: SM) -> ClockSelect {
const IPG: u16 = ClockSelect::Ipg as u16;
const EXT: u16 = ClockSelect::External as u16;
const SM0: u16 = ClockSelect::Submodule0 as u16;
match crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL2, CLK_SEL) {
IPG => ClockSelect::Ipg,
EXT => ClockSelect::External,
SM0 => ClockSelect::Submodule0,
_ => unreachable!("Reserved value"),
}
}
pub fn set_clock_select(&mut self, sm: SM, clock_select: ClockSelect) {
assert!(SM::SM0 != sm || clock_select != ClockSelect::Submodule0);
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL2, CLK_SEL: clock_select as u16);
}
pub fn load_mode(&self, sm: SM) -> LoadMode {
let (immediate, full, half) =
crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD, FULL, HALF);
if immediate != 0 {
LoadMode::Immediate
} else {
LoadMode::ReloadCycle {
full: full != 0,
half: half != 0,
}
}
}
pub fn set_load_mode(&mut self, sm: SM, load_mode: LoadMode) {
match load_mode {
LoadMode::Immediate => {
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD: 1)
}
LoadMode::ReloadCycle { full, half } => {
assert!(
full || half,
"LoadMode::ReloadCycle must set at least full or half"
);
crate::ral::modify_reg!(pwm::sm, self.submodule(sm), SMCTRL, LDMOD: 0, FULL: full as u16, HALF: half as u16)
}
}
}
pub fn status(&self, sm: SM) -> Status {
let sts = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMSTS);
Status::from_bits_truncate(sts)
}
pub fn clear_status(&self, sm: SM, status: Status) {
let sts = status & Status::W1C;
crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMSTS, sts.bits())
}
pub fn interrupts(&self, sm: SM) -> Interrupts {
let inten = crate::ral::read_reg!(pwm::sm, self.submodule(sm), SMINTEN);
Interrupts::from_bits_truncate(inten)
}
pub fn set_interrupts(&self, sm: SM, interrupts: Interrupts) {
crate::ral::write_reg!(pwm::sm, self.submodule(sm), SMINTEN, interrupts.bits());
}
pub fn value(&self, sm: SM, value_register: ValueRegister) -> i16 {
let sm = self.submodule(sm);
(match value_register {
ValueRegister::Val0 => crate::ral::read_reg!(pwm::sm, sm, SMVAL0),
ValueRegister::Val1 => crate::ral::read_reg!(pwm::sm, sm, SMVAL1),
ValueRegister::Val2 => crate::ral::read_reg!(pwm::sm, sm, SMVAL2),
ValueRegister::Val3 => crate::ral::read_reg!(pwm::sm, sm, SMVAL3),
ValueRegister::Val4 => crate::ral::read_reg!(pwm::sm, sm, SMVAL4),
ValueRegister::Val5 => crate::ral::read_reg!(pwm::sm, sm, SMVAL5),
}) as _
}
pub fn turn_on(&self, sm: SM, channel: Channel) -> i16 {
self.value(sm, turn_on(channel))
}
pub fn turn_off(&self, sm: SM, channel: Channel) -> i16 {
self.value(sm, turn_off(channel))
}
pub fn set_value(&self, sm: SM, value_register: ValueRegister, value: i16) {
let value = value as u16;
let sm = self.submodule(sm);
match value_register {
ValueRegister::Val0 => crate::ral::write_reg!(pwm::sm, sm, SMVAL0, value),
ValueRegister::Val1 => crate::ral::write_reg!(pwm::sm, sm, SMVAL1, value),
ValueRegister::Val2 => crate::ral::write_reg!(pwm::sm, sm, SMVAL2, value),
ValueRegister::Val3 => crate::ral::write_reg!(pwm::sm, sm, SMVAL3, value),
ValueRegister::Val4 => crate::ral::write_reg!(pwm::sm, sm, SMVAL4, value),
ValueRegister::Val5 => crate::ral::write_reg!(pwm::sm, sm, SMVAL5, value),
}
}
pub fn set_turn_on(&self, sm: SM, channel: Channel, compare: i16) {
self.set_value(sm, turn_on(channel), compare);
}
pub fn set_turn_off(&self, sm: SM, channel: Channel, compare: i16) {
self.set_value(sm, turn_off(channel), compare);
}
pub fn output_masks(&self) -> OutputMasks {
let (pwm_a, pwm_b) = crate::ral::read_reg!(pwm, self.pwm, MASK, MASKA, MASKB);
OutputMasks {
pwm_a: Mask::from_bits_truncate(pwm_a as u8),
pwm_b: Mask::from_bits_truncate(pwm_b as u8),
}
}
pub fn set_output_masks(&self, masks: OutputMasks) {
crate::ral::write_reg!(pwm, self.pwm, MASK,
MASKA: masks.pwm_a.bits() as u16,
MASKB: masks.pwm_b.bits() as u16,
);
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[non_exhaustive] pub struct OutputMasks {
pub pwm_a: Mask,
pub pwm_b: Mask,
}
impl OutputMasks {
pub const fn empty() -> Self {
Self {
pwm_a: Mask::empty(),
pwm_b: Mask::empty(),
}
}
pub const fn all() -> Self {
Self {
pwm_a: Mask::all(),
pwm_b: Mask::all(),
}
}
}
#[inline(never)]
fn new(pwm: AnyPwmInstance) -> Pwm {
crate::ral::write_reg!(crate::ral::pwm, pwm, FCTRL0, FLVL: 0xF);
crate::ral::write_reg!(crate::ral::pwm, pwm, FSTS0, FFLAG: 0xF);
Pwm { pwm }
}
#[repr(usize)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SM {
SM0 = 0,
SM1 = 1,
SM2 = 2,
SM3 = 3,
}
impl SM {
#[inline]
pub const fn mask(self) -> Mask {
Mask::from_bits_truncate(1 << (self as u8))
}
}
impl From<SM> for Mask {
#[inline]
fn from(value: SM) -> Self {
value.mask()
}
}
impl core::ops::BitOr for SM {
type Output = Mask;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output {
self.mask() | rhs.mask()
}
}
impl core::ops::BitOr<Mask> for SM {
type Output = Mask;
#[inline]
fn bitor(self, rhs: Mask) -> Self::Output {
self.mask() | rhs
}
}
impl core::ops::BitOr<SM> for Mask {
type Output = Mask;
#[inline]
fn bitor(self, rhs: SM) -> Self::Output {
self | rhs.mask()
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum Prescaler {
Prescaler1,
Prescaler2,
Prescaler4,
Prescaler8,
Prescaler16,
Prescaler32,
Prescaler64,
Prescaler128,
}
impl Prescaler {
pub const fn divider(self) -> u32 {
1 << self as u32
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum PairOperation {
Complementary,
Independent,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum ClockSelect {
Ipg,
External,
Submodule0,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LoadMode {
ReloadCycle {
full: bool,
half: bool,
},
Immediate,
}
impl LoadMode {
pub const fn reload_full() -> Self {
Self::ReloadCycle {
full: true,
half: false,
}
}
pub const fn reload_half() -> Self {
Self::ReloadCycle {
full: false,
half: true,
}
}
pub const fn reload_both() -> Self {
Self::ReloadCycle {
full: true,
half: true,
}
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Status : u16 {
const REGISTER_UPDATED = 1 << 14;
const RELOAD_ERROR = 1 << 13;
const RELOAD = 1 << 12;
const COMPARE_VAL5 = 1 << 5;
const COMPARE_VAL4 = 1 << 4;
const COMPARE_VAL3 = 1 << 3;
const COMPARE_VAL2 = 1 << 2;
const COMPARE_VAL1 = 1 << 1;
const COMPARE_VAL0 = 1 << 0;
}
}
impl Status {
pub const W1C: Status = Self::REGISTER_UPDATED.complement();
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Interrupts : u16 {
const RELOAD_ERROR = 1 << 13;
const RELOAD = 1 << 12;
const COMPARE_VAL5 = 1 << 5;
const COMPARE_VAL4 = 1 << 4;
const COMPARE_VAL3 = 1 << 3;
const COMPARE_VAL2 = 1 << 2;
const COMPARE_VAL1 = 1 << 1;
const COMPARE_VAL0 = 1 << 0;
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueRegister {
Val0,
Val1,
Val2,
Val3,
Val4,
Val5,
}
pub const FULL_RELOAD_VALUE_REGISTER: ValueRegister = ValueRegister::Val1;
pub const HALF_RELOAD_VALUE_REGISTER: ValueRegister = ValueRegister::Val0;
pub const fn turn_on(channel: Channel) -> ValueRegister {
match channel {
Channel::A => ValueRegister::Val2,
Channel::B => ValueRegister::Val4,
}
}
pub const fn turn_off(channel: Channel) -> ValueRegister {
match channel {
Channel::A => ValueRegister::Val3,
Channel::B => ValueRegister::Val5,
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Channel {
A,
B,
}