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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![cfg_attr(not(feature = "std"), no_std)]

#[macro_use]
extern crate serde_derive;
extern crate serde;

extern crate enum_iter;

#[cfg(not(feature = "std"))]
extern crate core as std;

use enum_iter::EnumIter;

pub const MAX_INTENSITY: u16 = 16000;
pub const COMM_VERSION: u16 = 3;
pub const BAUD_RATE: u32 = 230_400;

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
pub enum ToDevice {
    DeviceState(DeviceState),
    EchoRequest8((u8, u8, u8, u8, u8, u8, u8, u8)),
    VersionRequest,
}

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
pub enum FromDevice {
    DeviceState(DeviceState),
    EchoResponse8((u8, u8, u8, u8, u8, u8, u8, u8)),
    VersionResponse(u16),
    StateWasSet,
}

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
pub struct CounterInfo {
    pub cnt: u16,
    pub psc: u16,
    pub arr: u16,
    pub ccr1: u16,
    // pub ccmr1: u16,
    // pub cr1: u16,
    pub cr2_ois1: Option<u8>,
    // pub egr: u16,
    // pub ccer: u16,
}

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
pub struct DeviceState {
    pub ch1: ChannelState,
    pub ch2: ChannelState,
    pub ch3: ChannelState,
    pub ch4: ChannelState,
}

impl DeviceState {
    pub const fn default() -> DeviceState {
        DeviceState {
            ch1: ChannelState::default(1),
            ch2: ChannelState::default(2),
            ch3: ChannelState::default(3),
            ch4: ChannelState::default(4),
        }
    }
}

impl Default for DeviceState {
    fn default() -> DeviceState {
        DeviceState::default()
    }
}

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
pub struct ChannelState {
    pub num: u8,
    pub on_state: OnState,
    pub intensity: u16,
}

impl ChannelState {
    pub const fn default(num: u8) -> ChannelState {
        ChannelState {
            num,
            on_state: OnState::Off,
            intensity: MAX_INTENSITY,
        }
    }
}

impl Default for ChannelState {
    fn default() -> ChannelState {
        ChannelState::default(1)
    }
}

#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[cfg_attr(feature = "print-defmt", derive(defmt::Format))]
#[derive(Default)]
pub enum OnState {
    #[default]
    Off,
    ConstantOn,
}

impl std::fmt::Display for OnState {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        std::fmt::Debug::fmt(self, fmt)
    }
}

// I found this necessary to avoid lifetime error in led-box-firmware. Not
// sure why this needs to be allocated as with const to be 'static in this
// case (but not in standard linux target).
const ON_STATE_VARIANTS: [OnState; 2] = [OnState::Off, OnState::ConstantOn];
const ON_STATE_VARIANTS_REF: &[OnState] = &ON_STATE_VARIANTS;

impl EnumIter for OnState {
    fn variants() -> &'static [Self] {
        ON_STATE_VARIANTS_REF
    }
}