use crate::Command;
pub struct EventReceiver<PROTOCOL> {
pub sm: PROTOCOL,
precalc_multiplier: u32,
}
impl<PROTOCOL: ReceiverSM> EventReceiver<PROTOCOL> {
pub fn new(samplerate: u32) -> Self {
Self {
sm: PROTOCOL::create(),
precalc_multiplier: crate::TIMEBASE / samplerate,
}
}
pub fn edge_event<T: Into<u32>>(
&mut self,
edge: bool,
delta_samples: T,
) -> Result<Option<PROTOCOL::Cmd>, Error> {
let dt_us = delta_samples.into() * self.precalc_multiplier;
let state: State = self.sm.event(edge, dt_us).into();
match state {
State::Done => {
let cmd = self.sm.command();
self.sm.reset();
Ok(cmd)
}
State::Error(err) => {
self.sm.reset();
Err(err)
}
State::Idle | State::Receiving => Ok(None),
}
}
pub fn reset(&mut self) {
self.sm.reset();
}
}
pub struct PeriodicReceiver<PROTOCOL> {
pub recv: EventReceiver<PROTOCOL>,
edge: bool,
last: u32,
}
impl<PROTOCOL: ReceiverSM> PeriodicReceiver<PROTOCOL> {
pub fn new(samplerate: u32) -> Self {
Self {
recv: EventReceiver::new(samplerate),
edge: false,
last: 0,
}
}
pub fn poll(&mut self, edge: bool, ts: u32) -> Result<Option<PROTOCOL::Cmd>, Error> {
if self.edge == edge {
return Ok(None);
}
let dt = ts.wrapping_sub(self.last);
self.last = ts;
self.edge = edge;
self.recv.edge_event(edge, dt)
}
pub fn reset(&mut self) {
self.recv.reset()
}
}
pub trait ReceiverSM {
type Cmd: Command;
type InternalState: Into<State>;
fn create() -> Self;
fn event(&mut self, edge: bool, dt: u32) -> Self::InternalState;
fn command(&self) -> Option<Self::Cmd>;
fn reset(&mut self);
}
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum State {
Idle,
Receiving,
Done,
Error(Error),
}
impl Default for State {
fn default() -> State {
State::Idle
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Error {
Address,
Data,
Other,
}