use crate::clock::Smclk;
use core::marker::PhantomData;
use embedded_hal::timer::{Cancel, CountDown, Periodic};
use msp430fr247x as pac;
use pac::{rtc::rtcctl::RTCSS_A, RTC};
use void::Void;
mod sealed {
use super::*;
pub trait SealedRtcClockSrc {}
impl SealedRtcClockSrc for RtcSmclk {}
impl SealedRtcClockSrc for RtcVloclk {}
}
pub trait RtcClockSrc: sealed::SealedRtcClockSrc {
#[doc(hidden)]
const CLK_SRC: RTCSS_A;
}
pub struct RtcSmclk;
impl RtcClockSrc for RtcSmclk {
const CLK_SRC: RTCSS_A = RTCSS_A::SMCLK;
}
pub struct RtcVloclk;
impl RtcClockSrc for RtcVloclk {
const CLK_SRC: RTCSS_A = RTCSS_A::VLOCLK;
}
pub struct Rtc<SRC: RtcClockSrc> {
periph: RTC,
_src: PhantomData<SRC>,
}
impl Rtc<RtcVloclk> {
pub fn new(rtc: RTC) -> Self {
Rtc {
periph: rtc,
_src: PhantomData,
}
}
}
pub use pac::rtc::rtcctl::RTCPS_A as RtcDiv;
impl<SRC: RtcClockSrc> Rtc<SRC> {
#[inline]
pub fn use_smclk(self, _smclk: &Smclk) -> Rtc<RtcSmclk> {
Rtc {
periph: self.periph,
_src: PhantomData,
}
}
#[inline]
pub fn use_vloclk(self) -> Rtc<RtcVloclk> {
Rtc {
periph: self.periph,
_src: PhantomData,
}
}
#[inline]
pub fn set_clk_div(&mut self, div: RtcDiv) {
self.periph
.rtcctl
.modify(|r, w| unsafe { w.bits(r.bits()) }.rtcps().variant(div));
}
#[inline]
pub fn enable_interrupts(&mut self) {
self.periph.rtcctl.write(|w| w.rtcie().set_bit());
}
#[inline]
pub fn disable_interrupts(&mut self) {
self.periph.rtcctl.write(|w| w.rtcie().clear_bit());
}
#[inline]
pub fn clear_interrupt(&mut self) {
self.periph.rtciv.read();
}
#[inline]
pub fn get_count(&self) -> u16 {
self.periph.rtccnt.read().bits()
}
}
impl<SRC: RtcClockSrc> CountDown for Rtc<SRC> {
type Time = u16;
#[inline]
fn start<T: Into<Self::Time>>(&mut self, count: T) {
self.periph
.rtcmod
.write(|w| unsafe { w.bits(count.into()) });
self.periph.rtciv.read();
self.periph.rtcctl.modify(|r, w| {
unsafe { w.bits(r.bits()) }
.rtcss()
.variant(SRC::CLK_SRC)
.rtcsr()
.set_bit()
});
}
#[inline]
fn wait(&mut self) -> nb::Result<(), Void> {
if self.periph.rtcctl.read().rtcifg().bit() {
self.periph.rtciv.read();
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl<SRC: RtcClockSrc> Cancel for Rtc<SRC> {
type Error = Void;
#[inline]
fn cancel(&mut self) -> Result<(), Self::Error> {
self.periph
.rtcctl
.write(|w| w.rtcss().variant(RTCSS_A::DISABLED));
Ok(())
}
}
impl<SRC: RtcClockSrc> Periodic for Rtc<SRC> {}