1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
pub mod board;
pub mod chip;
pub mod utilities;

#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum State {
    #[default]
    Undefined,
    Low,
    High,
    Analog(f32),
}

impl State {
    pub fn feed_state(&mut self, state: State) -> Self {
        match state {
            State::Low if matches!(self, State::Undefined) => State::Low,
            State::High => State::High,
            State::Analog(_) if matches!(self, State::High) => State::High,
            State::Analog(v) => {
                if let State::Analog(bv) = self {
                    if v < *bv {
                        *self
                    } else {
                        State::Analog(v)
                    }
                } else {
                    State::Analog(v)
                }
            }
            State::Undefined | State::Low => *self,
        }
    }

    pub fn as_analog(&self, conversion_target: f32) -> Self {
        match self {
            State::Undefined | State::Low => State::Analog(0.0),
            State::High => Self::Analog(conversion_target),
            State::Analog(_) => *self,
        }
    }

    pub fn as_logic(&self, threshold: f32) -> Self {
        match self {
            State::Undefined => State::Low,
            State::Low | State::High => *self,
            State::Analog(v) => {
                if *v >= threshold {
                    State::High
                } else {
                    State::Low
                }
            }
        }
    }
}

impl From<State> for bool {
    fn from(value: State) -> Self {
        match value {
            State::Undefined | State::Low => false,
            State::High => true,
            State::Analog(v) => v != 0.0,
        }
    }
}

impl From<bool> for State {
    fn from(value: bool) -> Self {
        if value {
            State::High
        } else {
            State::Low
        }
    }
}