use crate::private::ringq::{Coalesce, QueueError};
use crate::devices::button::ButtonState;
use crate::devices::serialport::SerialState;
use crate::hal::generic::timer::TimerIdentity;
use crate::hal::generic::port::PinIdentity;
use crate::hal::generic::serial::SerialPortIdentity;
#[derive(Clone,Copy,PartialEq,Eq)]
pub enum OxideEvent {
Initialise,
ClockTick(TimerIdentity, u16),
ButtonEvent(PinIdentity, ButtonState),
SerialEvent(SerialPortIdentity, SerialState)
}
#[derive(Clone,Copy)]
pub struct OxideEventEnvelope<'e> {
receiver: Option<&'e dyn EventSource>,
event: OxideEvent
}
pub trait EventSource {
fn listen(&'static self);
fn process_event(&self, evt: OxideEvent);
}
pub trait EventSink {
fn event(event: OxideEventEnvelope);
}
pub struct EventDevNull {
}
impl<'e> OxideEventEnvelope<'e> {
pub fn to(receiver: &'e dyn EventSource, event: OxideEvent) -> Self {
OxideEventEnvelope {
receiver: Some(receiver),
event
}
}
pub fn anon(event: OxideEvent) -> Self {
OxideEventEnvelope {
receiver: None,
event
}
}
pub fn unwrap(&self) -> OxideEvent {
self.event
}
pub(crate) fn invoke_recipient(&self) {
match self.receiver {
Some(ev_src) => {
ev_src.process_event(self.event);
},
None => {}
}
}
}
impl Coalesce for OxideEvent {
fn coalesce(&mut self, with: &Self) -> Result<(), QueueError> {
match self {
OxideEvent::ClockTick(source1, myticks) => {
match with {
OxideEvent::ClockTick(source2, ticks) => {
if (source1 == source2) && (u16::MAX - *myticks) > *ticks {
*myticks += ticks;
Ok(())
} else {
Err(QueueError::CannotCoalesce)
}
},
_ => Err(QueueError::CannotCoalesce)
}
},
OxideEvent::SerialEvent(source1, state) => {
match with {
OxideEvent::SerialEvent(source2, with_state) => {
if (source1 == source2) && (state == with_state) {
Ok(())
} else {
Err(QueueError::CannotCoalesce)
}
},
_ => Err(QueueError::CannotCoalesce)
}
},
_ => Err(QueueError::CannotCoalesce)
}
}
}
impl Coalesce for OxideEventEnvelope<'_> {
fn coalesce(&mut self, with: &Self) -> Result<(), QueueError> {
match (self.receiver, with.receiver) {
(Some(my_receiver),Some(with_receiver)) => {
if my_receiver as *const _ == with_receiver as *const _ {
self.event.coalesce(&with.event)
} else {
Err(QueueError::CannotCoalesce)
}
}
_=> Err(QueueError::CannotCoalesce)
}
}
}
impl EventSink for EventDevNull {
fn event(_event: OxideEventEnvelope) {
}
}
#[cfg(test)]
mod tests {
use crate::event::{EventSource, OxideEvent, OxideEventEnvelope};
use crate::private::ringq::Coalesce;
use crate::event::OxideEvent::{ButtonEvent, ClockTick, SerialEvent};
use crate::devices::serialport::SerialState;
use crate::devices::button::ButtonState;
use crate::hal::generic::timer::TimerIdentity;
use crate::hal::generic::serial::SerialPortIdentity;
use crate::hal::generic::port::PinIdentity;
use crate::panic_if_err;
struct DummyEventSource {
}
impl EventSource for DummyEventSource {
fn listen(&'static self) {
todo!()
}
fn process_event(&self, evt: OxideEvent) {
unimplemented!()
}
}
#[test]
fn test_event_coalesce_masterclockevent() {
static DES : DummyEventSource = DummyEventSource {};
let mut event1 = OxideEventEnvelope::to(&DES, ClockTick(TimerIdentity::Tcb0, 12));
let event2 = OxideEventEnvelope::to(&DES, ClockTick(TimerIdentity::Tcb0, 14));
event1.coalesce(&event2);
if let ClockTick(TimerIdentity::Tcb0, ticks) = event1.unwrap() {
println!("Coalesced MasterClockEvent (ticks == {})", ticks);
assert_eq!(ticks, 26);
}
}
#[test]
fn test_event_coalesce_serialevent_ok() {
static DES : DummyEventSource = DummyEventSource {};
let mut event1 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::ReadAvailable));
let event2 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::ReadAvailable));
panic_if_err!(event1.coalesce(&event2));
let mut event1 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::BreakDetected));
let event2 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::BreakDetected));
panic_if_err!(event1.coalesce(&event2));
}
#[test]
#[should_panic]
fn test_event_coalesce_serialevent_fail() {
static DES : DummyEventSource = DummyEventSource {};
let mut event1 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::ReadAvailable));
let event2 = OxideEventEnvelope::to(&DES, SerialEvent(SerialPortIdentity::Usart0, SerialState::BreakDetected));
let thing = event1.coalesce(&event2);
panic_if_err!(event1.coalesce(&event2));
}
#[test]
#[should_panic]
fn test_event_coalesce_fail() {
static DES : DummyEventSource = DummyEventSource {};
let mut event1 = OxideEventEnvelope::to(&DES, ClockTick(TimerIdentity::Tcb0, 42));
let event2 = OxideEventEnvelope::to(&DES, ButtonEvent(PinIdentity::PortA(0),ButtonState::Pressed));
panic_if_err!(event1.coalesce(&event2));
}
}