use core::iter::FusedIterator;
use crate::flags::{self, Flags, INT_CFG, INT_DIR, INT_EN};
use crate::HP203B;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Event {
PATraversed,
TemperatureTraversed,
PAOutsideWindow,
TemperatureOutsideWindow,
}
#[allow(clippy::from_over_into)]
impl Into<flags::INT_EN> for Event {
fn into(self) -> flags::INT_EN {
use Event::*;
match self {
PATraversed => INT_EN::PA_TRAV_EN,
TemperatureTraversed => INT_EN::T_TRAV_EN,
PAOutsideWindow => INT_EN::PA_WIN_EN,
TemperatureOutsideWindow => INT_EN::T_WIN_EN,
}
}
}
#[allow(clippy::from_over_into)]
impl Into<flags::INT_CFG> for Event {
fn into(self) -> flags::INT_CFG {
use Event::*;
match self {
PATraversed => INT_CFG::PA_TRAV_CFG,
TemperatureTraversed => INT_CFG::T_TRAV_CFG,
PAOutsideWindow => INT_CFG::PA_WIN_CFG,
TemperatureOutsideWindow => INT_CFG::T_WIN_CFG,
}
}
}
#[allow(clippy::from_over_into)]
impl Into<flags::INT_SRC> for Event {
fn into(self) -> flags::INT_SRC {
use Event::*;
match self {
PATraversed => flags::INT_SRC::PA_TRAV,
TemperatureTraversed => flags::INT_SRC::T_TRAV,
PAOutsideWindow => flags::INT_SRC::PA_WIN,
TemperatureOutsideWindow => flags::INT_SRC::T_WIN,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InterruptSetting {
Disabled,
Enabled,
EnabledWithPin,
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum WindowPosition {
AboveWindow,
BelowWindow,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TraversalDirection {
Rising,
Falling,
}
#[derive(Clone)]
pub struct Interrupts(flags::INT_SRC);
impl Interrupts {
pub(crate) fn new(flags: flags::INT_SRC) -> Self {
Self(flags)
}
}
impl Iterator for Interrupts {
type Item = Event;
fn next(&mut self) -> Option<Self::Item> {
use flags::INT_SRC;
for flag in crate::flags::INT_SRC_VARIANTS {
if self.0.contains(flag) {
self.0.remove(flag);
return Some(match flag {
INT_SRC::PA_TRAV => Event::PATraversed,
INT_SRC::PA_WIN => Event::PAOutsideWindow,
INT_SRC::T_TRAV => Event::TemperatureTraversed,
INT_SRC::T_WIN => Event::TemperatureOutsideWindow,
_ => continue,
});
}
}
None
}
}
impl FusedIterator for Interrupts {}
#[allow(clippy::module_name_repetitions)]
pub trait HasInterrupts<E> {
fn interrupts(&mut self) -> Result<Interrupts, E>;
fn interrupt_setting(&mut self, event: Event) -> Result<InterruptSetting, E>;
fn setup_interrupts<S: IntoIterator<Item = (Event, InterruptSetting)>>(
&mut self,
settings: S,
) -> Result<(), E>;
fn block_on(&mut self, event: Event) -> nb::Result<(), E>;
fn pa_traverse_direction(&mut self) -> Result<Option<TraversalDirection>, E>;
fn temp_traverse_direction(&mut self) -> Result<Option<TraversalDirection>, E>;
fn pa_window_status(&mut self) -> Result<Option<WindowPosition>, E>;
fn temp_window_status(&mut self) -> Result<Option<WindowPosition>, E>;
}
impl<I, M, C, E> HasInterrupts<E> for HP203B<I, M, C>
where
I: embedded_hal::i2c::blocking::I2c<Error = E>,
M: crate::mode::BarometricMeasurement,
C: crate::csb::CSB,
{
fn interrupts(&mut self) -> Result<Interrupts, E> {
Ok(Interrupts::new(self.get_interrupts()?))
}
fn setup_interrupts<S: IntoIterator<Item = (Event, InterruptSetting)>>(
&mut self,
settings: S,
) -> Result<(), E> {
let mut enabled_flags = self.get_interrupts_enabled()?;
let mut pinout_flags = self.get_interrupts_pinout()?;
for (event, setting) in settings {
let en_flag = event.into();
let pinout_flag = event.into();
let (en, pinout) = match setting {
InterruptSetting::Enabled => (true, false),
InterruptSetting::EnabledWithPin => (true, true),
InterruptSetting::Disabled => (false, false),
};
enabled_flags.set(en_flag, en);
pinout_flags.set(pinout_flag, pinout);
}
self.set_interrupts_enabled(enabled_flags)?;
self.set_interrupts_pinout(pinout_flags)?;
Ok(())
}
fn interrupt_setting(&mut self, event: Event) -> Result<InterruptSetting, E> {
let enabled = self.get_interrupts_enabled()?.contains(event.into());
let pinout = self.get_interrupts_pinout()?.contains(event.into());
Ok(match (enabled, pinout) {
(true, true) => InterruptSetting::EnabledWithPin,
(true, false) => InterruptSetting::Enabled,
(false, _) => InterruptSetting::Disabled,
})
}
fn block_on(&mut self, event: Event) -> nb::Result<(), E> {
self.inner_block(event.into())
}
fn pa_traverse_direction(&mut self) -> Result<Option<TraversalDirection>, E> {
if self.interrupt_setting(Event::PATraversed)? == InterruptSetting::Disabled {
return Ok(None);
}
let extras = self.get_interrupt_extras()?;
Ok(Some(if extras.contains(INT_DIR::P_TRAV_DIR) {
TraversalDirection::Rising
} else {
TraversalDirection::Falling
}))
}
fn temp_traverse_direction(&mut self) -> Result<Option<TraversalDirection>, E> {
if self.interrupt_setting(Event::TemperatureTraversed)? == InterruptSetting::Disabled {
return Ok(None);
}
let extras = self.get_interrupt_extras()?;
Ok(Some(if extras.contains(INT_DIR::P_TRAV_DIR) {
TraversalDirection::Rising
} else {
TraversalDirection::Falling
}))
}
fn pa_window_status(&mut self) -> Result<Option<WindowPosition>, E> {
if self.interrupt_setting(Event::PATraversed)? == InterruptSetting::Disabled {
return Ok(None);
}
let extras = self.get_interrupt_extras()?;
Ok(Some(if extras.contains(INT_DIR::P_WIN_DIR) {
WindowPosition::AboveWindow
} else {
WindowPosition::BelowWindow
}))
}
fn temp_window_status(&mut self) -> Result<Option<WindowPosition>, E> {
if self.interrupt_setting(Event::TemperatureTraversed)? == InterruptSetting::Disabled {
return Ok(None);
}
let extras = self.get_interrupt_extras()?;
Ok(Some(if extras.contains(INT_DIR::T_WIN_DIR) {
WindowPosition::AboveWindow
} else {
WindowPosition::BelowWindow
}))
}
}