mod output;
mod ral;
pub use self::ral::{Submodule, Submodules};
use crate::ral::pwm;
pub use output::Output;
pub struct Pwm<const N: u8> {
pwm: pwm::Instance<N>,
}
bitflags::bitflags! {
pub struct Mask : u8 {
const SM0 = 1 << 0;
const SM1 = 1 << 1;
const SM2 = 1 << 2;
const SM3 = 1 << 3;
}
}
impl<const N: u8> Pwm<N> {
pub const N: u8 = N;
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, channel: Channel, mask: Mask) {
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),
}
}
fn rmw_outen(&mut self, channel: Channel, mask: Mask, enable: bool) {
let mut outen = self.output_enable(channel);
outen.set(mask, enable);
self.set_output_enable(channel, outen);
}
}
pub fn new<const N: u8>(pwm: pwm::Instance<N>) -> (Pwm<N>, Submodules<N>) {
crate::ral::write_reg!(crate::ral::pwm, pwm, FCTRL0, FLVL: 0xF);
crate::ral::write_reg!(crate::ral::pwm, pwm, FSTS0, FFLAG: 0xF);
let submodules = self::ral::submodules(&pwm);
(Pwm { pwm }, submodules)
}
impl<const N: u8, const M: u8> Submodule<N, M> {
pub const MASK: Mask = Mask::from_bits_truncate(1 << M);
pub const fn mask(&self) -> Mask {
Self::MASK
}
pub fn count(&self) -> i16 {
crate::ral::read_reg!(self::ral, self, SMCNT)
}
pub fn initial_count(&self) -> i16 {
crate::ral::read_reg!(self::ral, self, SMINIT)
}
pub fn set_initial_count(&self, pwm: &Pwm<N>, counter: i16) {
if !self.load_ok(pwm) {
crate::ral::write_reg!(self::ral, self, SMINIT, counter);
}
}
pub fn load_frequency(&self) -> u16 {
crate::ral::read_reg!(self::ral, self, SMCTRL, LDFQ) + 1
}
pub fn set_load_frequency(&mut self, ldfq: u16) {
let ldfq = ldfq.clamp(1, 16) - 1;
crate::ral::modify_reg!(self::ral, self, SMCTRL, LDFQ: ldfq);
}
pub fn prescaler(&self) -> Prescaler {
let prescaler = crate::ral::read_reg!(self::ral, self, SMCTRL, PRSC);
#[allow(clippy::assertions_on_constants)]
{
use self::ral::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, prescaler: Prescaler) {
crate::ral::modify_reg!(self::ral, self, SMCTRL, PRSC: prescaler as u16)
}
pub fn pair_operation(&self) -> PairOperation {
let indep = crate::ral::read_reg!(self::ral, self, SMCTRL2, INDEP);
#[allow(clippy::assertions_on_constants)]
{
use self::ral::SMCTRL2;
const _: () = assert!(SMCTRL2::INDEP::mask >> SMCTRL2::INDEP::offset == 1u16);
}
unsafe { core::mem::transmute(indep) }
}
pub fn set_pair_operation(&mut self, pair_operation: PairOperation) {
crate::ral::modify_reg!(self::ral, self, SMCTRL2, INDEP: pair_operation as u16);
}
pub fn debug_enable(&self) -> bool {
crate::ral::read_reg!(self::ral, self, SMCTRL2, DBGEN == 1)
}
pub fn set_debug_enable(&mut self, enable: bool) {
crate::ral::modify_reg!(self::ral, self, SMCTRL2, DBGEN: enable as u16);
}
pub fn wait_enable(&self) -> bool {
crate::ral::read_reg!(self::ral, self, SMCTRL2, WAITEN == 1)
}
pub fn set_wait_enable(&mut self, enable: bool) {
crate::ral::modify_reg!(self::ral, self, SMCTRL2, WAITEN: enable as u16);
}
pub fn clock_select(&self) -> 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!(self::ral, self, SMCTRL2, CLK_SEL) {
IPG => ClockSelect::Ipg,
EXT => ClockSelect::External,
SM0 => ClockSelect::Submodule0,
_ => unreachable!("Reserved value"),
}
}
pub fn set_clock_select(&mut self, clock_select: ClockSelect) {
assert!(0 != M || clock_select != ClockSelect::Submodule0);
crate::ral::modify_reg!(self::ral, self, SMCTRL2, CLK_SEL: clock_select as u16);
}
pub fn load_mode(&self) -> LoadMode {
let (immediate, full, half) =
crate::ral::read_reg!(self::ral, self, 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, load_mode: LoadMode) {
match load_mode {
LoadMode::Immediate => crate::ral::modify_reg!(self::ral, self, SMCTRL, LDMOD: 1),
LoadMode::ReloadCycle { full, half } => {
assert!(
full || half,
"LoadMode::ReloadCycle must set at least full or half"
);
crate::ral::modify_reg!(self::ral, self, SMCTRL, LDMOD: 0, FULL: full as u16, HALF: half as u16)
}
}
}
pub fn status(&self) -> Status {
let sts = crate::ral::read_reg!(self::ral, self, SMSTS);
Status::from_bits_truncate(sts)
}
pub fn clear_status(&self, status: Status) {
let sts = status & Status::W1C;
crate::ral::write_reg!(self::ral, self, SMSTS, sts.bits())
}
pub fn interrupts(&self) -> Interrupts {
let inten = crate::ral::read_reg!(self::ral, self, SMINTEN);
Interrupts::from_bits_truncate(inten)
}
pub fn set_interrupts(&self, interrupts: Interrupts) {
crate::ral::write_reg!(self::ral, self, SMINTEN, interrupts.bits());
}
pub fn value(&self, value_register: ValueRegister) -> i16 {
match value_register {
ValueRegister::Val0 => crate::ral::read_reg!(self::ral, self, SMVAL0),
ValueRegister::Val1 => crate::ral::read_reg!(self::ral, self, SMVAL1),
ValueRegister::Val2 => crate::ral::read_reg!(self::ral, self, SMVAL2),
ValueRegister::Val3 => crate::ral::read_reg!(self::ral, self, SMVAL3),
ValueRegister::Val4 => crate::ral::read_reg!(self::ral, self, SMVAL4),
ValueRegister::Val5 => crate::ral::read_reg!(self::ral, self, SMVAL5),
}
}
pub fn turn_on(&self, channel: Channel) -> i16 {
self.value(turn_on(channel))
}
pub fn turn_off(&self, channel: Channel) -> i16 {
self.value(turn_off(channel))
}
pub fn set_value(&self, value_register: ValueRegister, value: i16) {
match value_register {
ValueRegister::Val0 => crate::ral::write_reg!(self::ral, self, SMVAL0, value),
ValueRegister::Val1 => crate::ral::write_reg!(self::ral, self, SMVAL1, value),
ValueRegister::Val2 => crate::ral::write_reg!(self::ral, self, SMVAL2, value),
ValueRegister::Val3 => crate::ral::write_reg!(self::ral, self, SMVAL3, value),
ValueRegister::Val4 => crate::ral::write_reg!(self::ral, self, SMVAL4, value),
ValueRegister::Val5 => crate::ral::write_reg!(self::ral, self, SMVAL5, value),
}
}
pub fn set_turn_on(&self, channel: Channel, compare: i16) {
self.set_value(turn_on(channel), compare);
}
pub fn set_turn_off(&self, channel: Channel, compare: i16) {
self.set_value(turn_off(channel), compare);
}
pub fn load_ok(&self, pwm: &Pwm<N>) -> bool {
pwm.load_ok().intersects(Self::MASK)
}
pub fn set_load_ok(&self, pwm: &mut Pwm<N>) {
pwm.set_load_ok(Self::MASK);
}
pub fn clear_load_ok(&self, pwm: &mut Pwm<N>) {
pwm.clear_load_ok(Self::MASK);
}
pub fn is_running(&self, pwm: &Pwm<N>) -> bool {
pwm.run().intersects(Self::MASK)
}
pub fn output_enable(&self, pwm: &Pwm<N>, channel: Channel) -> bool {
pwm.output_enable(channel).intersects(Self::MASK)
}
pub fn set_output_enable(&self, pwm: &mut Pwm<N>, channel: Channel, enable: bool) {
pwm.rmw_outen(channel, Self::MASK, enable);
}
pub fn set_running(&self, pwm: &mut Pwm<N>, run: bool) {
let mut mask = pwm.run();
mask.set(Self::MASK, run);
pwm.set_run(mask);
}
}
#[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
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum PairOperation {
Complementary,
Independent,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum ClockSelect {
Ipg,
External,
Submodule0,
}
#[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! {
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! {
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;
}
}
#[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,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Channel {
A,
B,
}