use crate::ral;
pub struct Gpt<const N: u8> {
gpt: ral::gpt::Instance<N>,
}
pub type Gpt1 = Gpt<1>;
pub type Gpt2 = Gpt<2>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum ClockSource {
NoClock,
PeripheralClock,
HighFrequencyReferenceClock,
ExternalClock,
LowFrequencyReferenceClock,
CrystalOscillator,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(usize)]
pub enum OutputCompareRegister {
OCR1 = 0,
OCR2 = 1,
OCR3 = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Restart,
FreeRunning,
}
impl<const N: u8> Gpt<N> {
pub fn new(gpt: ral::gpt::Instance<N>) -> Self {
ral::modify_reg!(ral::gpt, gpt, CR, EN: 0);
ral::modify_reg!(ral::gpt, gpt, CR, SWR: 1);
while ral::read_reg!(ral::gpt, gpt, CR, SWR == 1) {}
ral::write_reg!(ral::gpt, gpt, SR, 0b11_1111);
Self { gpt }
}
pub fn divider(&self) -> u32 {
ral::read_reg!(ral::gpt, self.gpt, PR, PRESCALER) + 1
}
pub fn set_divider(&mut self, divider: u32) {
let prescaler = divider.clamp(1, 4096) - 1;
ral::modify_reg!(ral::gpt, self.gpt, PR, PRESCALER: prescaler);
}
pub fn divider_24mhz(&self) -> u32 {
ral::read_reg!(ral::gpt, self.gpt, PR, PRESCALER24M) + 1
}
pub fn set_divider_24mhz(&mut self, divider: u32) {
let prescaler = divider.clamp(1, 16) - 1;
ral::modify_reg!(ral::gpt, self.gpt, PR, PRESCALER24M: prescaler);
}
pub fn mode(&self) -> Mode {
if ral::read_reg!(ral::gpt, self.gpt, CR, FRR == 0) {
Mode::Restart
} else {
Mode::FreeRunning
}
}
pub fn set_mode(&mut self, mode: Mode) {
ral::modify_reg!(ral::gpt, self.gpt, CR, FRR: (mode as u32))
}
pub fn clock_source(&self) -> ClockSource {
let clock_source = ral::read_reg!(ral::gpt, self.gpt, CR, CLKSRC);
match clock_source {
0 => ClockSource::NoClock,
1 => ClockSource::PeripheralClock,
2 => ClockSource::HighFrequencyReferenceClock,
3 => ClockSource::ExternalClock,
4 => ClockSource::LowFrequencyReferenceClock,
5 => ClockSource::CrystalOscillator,
_ => unreachable!("Reserved GPT clock source"),
}
}
pub fn set_clock_source(&mut self, clock_source: ClockSource) {
ral::modify_reg!(
ral::gpt,
self.gpt,
CR,
CLKSRC: clock_source as u32,
EN_24M: (ClockSource::CrystalOscillator == clock_source) as u32);
}
pub fn set_reset_on_enable(&mut self, reset_on_enable: bool) {
ral::modify_reg!(ral::gpt, self.gpt, CR, ENMOD: (reset_on_enable as u32));
}
pub fn is_reset_on_enable(&self) -> bool {
ral::read_reg!(ral::gpt, self.gpt, CR, ENMOD == 1)
}
pub fn enable(&mut self) {
ral::modify_reg!(ral::gpt, self.gpt, CR, EN: 1);
}
pub fn disable(&mut self) {
ral::modify_reg!(ral::gpt, self.gpt, CR, EN: 0);
}
pub fn is_enabled(&self) -> bool {
ral::read_reg!(ral::gpt, self.gpt, CR, EN == 1)
}
pub fn set_wait_mode_enable(&mut self, wait: bool) {
ral::modify_reg!(ral::gpt, self.gpt, CR, WAITEN: (wait as u32));
}
pub fn is_wait_mode_enabled(&self) -> bool {
ral::read_reg!(ral::gpt, self.gpt, CR, WAITEN == 1)
}
pub fn set_output_interrupt_on_compare(&mut self, ocr: OutputCompareRegister, intr: bool) {
match ocr {
OutputCompareRegister::OCR1 => {
ral::modify_reg!(ral::gpt, self.gpt, IR, OF1IE: intr as u32)
}
OutputCompareRegister::OCR2 => {
ral::modify_reg!(ral::gpt, self.gpt, IR, OF2IE: intr as u32)
}
OutputCompareRegister::OCR3 => {
ral::modify_reg!(ral::gpt, self.gpt, IR, OF3IE: intr as u32)
}
}
}
pub fn is_output_interrupt_on_compare(&self, ocr: OutputCompareRegister) -> bool {
match ocr {
OutputCompareRegister::OCR1 => ral::read_reg!(ral::gpt, self.gpt, IR, OF1IE == 1),
OutputCompareRegister::OCR2 => ral::read_reg!(ral::gpt, self.gpt, IR, OF2IE == 1),
OutputCompareRegister::OCR3 => ral::read_reg!(ral::gpt, self.gpt, IR, OF3IE == 1),
}
}
pub fn count(&self) -> u32 {
ral::read_reg!(ral::gpt, self.gpt, CNT)
}
pub fn set_output_compare_count(&self, ocr: OutputCompareRegister, count: u32) {
ral::write_reg!(ral::gpt, self.gpt, OCR[ocr as usize], count);
}
pub fn output_compare_count(&self, ocr: OutputCompareRegister) -> u32 {
ral::read_reg!(ral::gpt, self.gpt, OCR[ocr as usize])
}
pub fn is_elapsed(&self, ocr: OutputCompareRegister) -> bool {
match ocr {
OutputCompareRegister::OCR1 => ral::read_reg!(ral::gpt, self.gpt, SR, OF1 == 1),
OutputCompareRegister::OCR2 => ral::read_reg!(ral::gpt, self.gpt, SR, OF2 == 1),
OutputCompareRegister::OCR3 => ral::read_reg!(ral::gpt, self.gpt, SR, OF3 == 1),
}
}
pub fn clear_elapsed(&self, ocr: OutputCompareRegister) {
match ocr {
OutputCompareRegister::OCR1 => ral::modify_reg!(ral::gpt, self.gpt, SR, OF1: 1),
OutputCompareRegister::OCR2 => ral::modify_reg!(ral::gpt, self.gpt, SR, OF2: 1),
OutputCompareRegister::OCR3 => ral::modify_reg!(ral::gpt, self.gpt, SR, OF3: 1),
}
}
pub fn set_rollover_interrupt_enable(&mut self, rov: bool) {
ral::modify_reg!(ral::gpt, self.gpt, IR, ROVIE: (rov as u32));
}
pub fn is_rollover_interrupt_enabled(&self) -> bool {
ral::read_reg!(ral::gpt, self.gpt, IR, ROVIE == 1)
}
pub fn is_rollover(&self) -> bool {
ral::read_reg!(ral::gpt, self.gpt, SR, ROV == 1)
}
pub fn clear_rollover(&self) {
ral::modify_reg!(ral::gpt, self.gpt, SR, ROV: 1);
}
pub fn reset(&mut self) {
ral::modify_reg!(ral::gpt, self.gpt, CR, SWR: 1);
while ral::read_reg!(ral::gpt, self.gpt, CR, SWR == SWR_1) {}
}
pub fn release(self) -> ral::gpt::Instance<N> {
self.gpt
}
}