#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Level {
Low,
High,
}
impl Level {
pub fn inverted(self) -> Level {
match self {
Level::Low => Level::High,
Level::High => Level::Low,
}
}
pub fn is_high(self) -> bool {
matches!(self, Level::High)
}
pub fn is_low(self) -> bool {
matches!(self, Level::Low)
}
pub fn from_bool(high: bool) -> Level {
if high {
Level::High
} else {
Level::Low
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
Input,
Output,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Pull {
None,
Up,
Down,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Drive {
PushPull,
OpenDrain,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Edge {
Rising,
Falling,
Both,
}
impl Edge {
pub fn triggered_by(self, from: Level, to: Level) -> bool {
match (from, to) {
(Level::Low, Level::High) => matches!(self, Edge::Rising | Edge::Both),
(Level::High, Level::Low) => matches!(self, Edge::Falling | Edge::Both),
_ => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Polarity {
ActiveHigh,
ActiveLow,
}
impl Polarity {
pub fn level(self, asserted: bool) -> Level {
match self {
Polarity::ActiveHigh => Level::from_bool(asserted),
Polarity::ActiveLow => Level::from_bool(!asserted),
}
}
pub fn is_asserted(self, level: Level) -> bool {
match self {
Polarity::ActiveHigh => level.is_high(),
Polarity::ActiveLow => level.is_low(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn level_helpers() {
assert_eq!(Level::Low.inverted(), Level::High);
assert_eq!(Level::High.inverted(), Level::Low);
assert!(Level::High.is_high() && !Level::High.is_low());
assert_eq!(Level::from_bool(true), Level::High);
assert_eq!(Level::from_bool(false), Level::Low);
}
#[test]
fn edges_fire_on_the_right_transition() {
assert!(Edge::Rising.triggered_by(Level::Low, Level::High));
assert!(!Edge::Rising.triggered_by(Level::High, Level::Low));
assert!(Edge::Falling.triggered_by(Level::High, Level::Low));
assert!(!Edge::Falling.triggered_by(Level::Low, Level::High));
assert!(Edge::Both.triggered_by(Level::Low, Level::High));
assert!(Edge::Both.triggered_by(Level::High, Level::Low));
assert!(!Edge::Both.triggered_by(Level::High, Level::High));
assert!(!Edge::Rising.triggered_by(Level::Low, Level::Low));
}
#[test]
fn active_high_is_the_direct_mapping() {
assert_eq!(Polarity::ActiveHigh.level(true), Level::High);
assert_eq!(Polarity::ActiveHigh.level(false), Level::Low);
assert!(Polarity::ActiveHigh.is_asserted(Level::High));
assert!(!Polarity::ActiveHigh.is_asserted(Level::Low));
}
#[test]
fn active_low_inverts() {
assert_eq!(Polarity::ActiveLow.level(true), Level::Low);
assert_eq!(Polarity::ActiveLow.level(false), Level::High);
assert!(Polarity::ActiveLow.is_asserted(Level::Low));
assert!(!Polarity::ActiveLow.is_asserted(Level::High));
}
#[test]
fn level_and_is_asserted_are_inverses() {
for polarity in [Polarity::ActiveHigh, Polarity::ActiveLow] {
for asserted in [true, false] {
assert_eq!(polarity.is_asserted(polarity.level(asserted)), asserted);
}
}
}
}