use core::marker::PhantomData;
use core::cell::RefCell;
use core::ops::DerefMut;
use crate::alloc::boxed::Box;
use crate::event::{EventSink, EventSource, OxideEvent, OxideEventEnvelope};
use crate::hal::generic::timer::{RtcCalibration, RtcPrescaler, RtcSource, RtcTimerCalibration, TimerControl, TimerIsrCallback};
use crate::hal::generic::timer::TimerMode::Periodic;
use crate::panic_if_none;
use crate::util::OwnOrBorrowMut;
use super::masterclock::TickCallback;
use super::masterclock::TickEvents;
pub struct WallClock<'wc,T,S>
where
T: 'static + TimerControl + RtcTimerCalibration,
S: EventSink
{
timer: OwnOrBorrowMut<'static,T>,
phantom: PhantomData<S>,
on_tick: RefCell<Option<Box<dyn TickCallback + 'wc>>>
}
impl<T,S> WallClock<'_,T,S>
where
T: 'static + TimerControl + RtcTimerCalibration,
S: EventSink
{
pub fn using<OT: Into<OwnOrBorrowMut<'static,T>>>(timer: OT) -> Self {
let mut timer : OwnOrBorrowMut<T> = timer.into();
timer.set_clock_calibration(RtcSource::Int1k,
RtcCalibration::Fast(0),
RtcPrescaler::Div4);
timer.set_mode(Periodic);
timer.set_interrupt_period(1024);
Self {
timer,
phantom: PhantomData::default(),
on_tick: RefCell::new(None)
}
}
pub fn with_timer(timer: &'static mut T) -> Self {
Self::using(timer)
}
}
impl<'wc, T, S> TickEvents<'wc> for WallClock<'wc, T, S>
where
T: 'static + TimerControl + RtcTimerCalibration,
S: EventSink
{
fn on_tick(&mut self, bf: Box<dyn TickCallback + 'wc>) {
self.on_tick.replace(Some(bf));
}
}
impl<T,S> EventSource for WallClock<'_,T,S>
where
T: 'static + TimerControl + RtcTimerCalibration,
S: EventSink
{
fn listen(&'static self) {
self.timer.start(TimerIsrCallback::WithData(|source, ticks, udata| {
S::event(OxideEventEnvelope::to(unsafe { &*(panic_if_none!(udata) as *const WallClock<T,S> as *const dyn EventSource) },
OxideEvent::ClockTick(source,ticks)));
true
}, self as *const dyn core::any::Any ));
}
fn process_event(&self, evt: OxideEvent) {
match (self.on_tick.borrow_mut().deref_mut(), evt) {
(Some(f), OxideEvent::ClockTick(source, ticks)) => {
(*f)(source,ticks)
},
_ => {}
}
}
}