dashboard/
eco_can.rs

1//! Contains structs for CAN packages
2//! ### CAN Package Information
3//! A CAN package is setup like this:
4//! ```rust
5//! #[allow(non_camel_case_types)]
6//! #[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
7//! #[repr(C)]
8//! pub struct FDCAN_PACKAGE_NAME {
9//!     // Package Data
10//! }
11//! impl FDCANPack for FDCAN_FetPack_t {
12//!    const FDCAN_BYTES: FDCANLength = BYTE_LENGTH; // set this to the size of the package in bytes
13//!    const FDCAN_ID: u32 = CAN_ID;    // the ID of the CAN package
14//! }
15//! ```
16//! `#[allow(non_camel_case_types)]` allows non-camel-case names for FDCAN packages
17//!
18//! `#[derive(bincode::Encode, bincode::Decode)]` makes the
19//! package able to be encoded to and decoded from bytes.
20//!
21//! `#[derive(Clone)]` allows the package to be copied.
22//!
23//! `#[derive(Debug)]` allows the package to be formatted in log messages.
24//!
25//! `#[derive(Default)]` allows the package to be inialized with default variables (usually 0).
26//!
27//! `#[repr(C)]` Make Rust use the same memory layout for this struct as C to ensure compatility.
28//! For more information: [https://doc.rust-lang.org/nomicon/other-reprs.html](https://doc.rust-lang.org/nomicon/other-reprs.html)
29
30use bincode::error::DecodeError;
31use defmt::Format;
32
33/// Bit Definitions for FET State
34#[allow(non_camel_case_types)]
35#[repr(u8)]
36pub enum FetBit {
37    ALL_FET_OFF = 0x00,
38    FUELCELL_FET = 0x01,
39    CAP_FET = 0x02,
40    RES_FET = 0x04,
41    OUT_FET = 0x08,
42}
43
44/// FET States
45#[allow(non_camel_case_types)]
46#[derive(Clone, Debug, Format)]
47#[repr(u8)]
48pub enum FetState {
49    FET_STBY = FetBit::ALL_FET_OFF as u8,
50    FET_CHRGE = FetBit::FUELCELL_FET as u8 | FetBit::CAP_FET as u8 | FetBit::RES_FET as u8,
51    FET_RUN = FetBit::FUELCELL_FET as u8
52        | FetBit::CAP_FET as u8
53        | FetBit::RES_FET as u8
54        | FetBit::OUT_FET as u8,
55}
56
57/// Bit Definitions for REL Board State
58#[allow(non_camel_case_types)]
59#[repr(u8)]
60pub enum RelayBit {
61    ALL_RELAY_OFF = 0x00,
62    CAP_RELAY = 0x01,
63    RES_RELAY = 0x02,
64    DSCHRGE_RELAY = 0x04,
65    MTR_RELAY = 0x08,
66}
67/// Relay Board State
68#[allow(non_camel_case_types)]
69#[derive(Clone, Debug, Format, PartialEq, Eq)]
70#[repr(u8)]
71pub enum RelayState {
72    RELAY_STBY = RelayBit::ALL_RELAY_OFF as u8,
73    RELAY_STRTP = RelayBit::RES_RELAY as u8 | RelayBit::DSCHRGE_RELAY as u8,
74    RELAY_CHRGE = RelayBit::RES_RELAY as u8,
75    RELAY_RUN =
76        RelayBit::CAP_RELAY as u8 | RelayBit::DSCHRGE_RELAY as u8 | RelayBit::MTR_RELAY as u8,
77}
78impl FDCANPack for RelayState {
79    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_1;
80    const FDCAN_ID: u32 = 0x018;
81}
82impl TryFrom<u8> for RelayState {
83    type Error = DecodeError;
84    fn try_from(value: u8) -> Result<Self, Self::Error> {
85        const RELAY_STBY: u8 = RelayState::RELAY_STBY as u8;
86        const RELAY_STRTP: u8 = RelayState::RELAY_STRTP as u8;
87        const RELAY_CHRGE: u8 = RelayState::RELAY_CHRGE as u8;
88        const RELAY_RUN: u8 = RelayState::RELAY_RUN as u8;
89
90        match value {
91            RELAY_STBY => Ok(RelayState::RELAY_STBY),
92            RELAY_STRTP => Ok(RelayState::RELAY_STRTP),
93            RELAY_CHRGE => Ok(RelayState::RELAY_CHRGE),
94            RELAY_RUN => Ok(RelayState::RELAY_RUN),
95            _ => Err(DecodeError::Other("Invalid Relay State")),
96        }
97    }
98}
99
100/// The length of the package in bytes, can be up to 64 bytes.
101///
102/// pub structs must be a certain size for FDCAN to transfer
103/// The following package sizes (in bytes) are 0, 1, 2, 3, 4, 5, 6,
104/// 7, 8, 12, 16, 20, 24, 32, 48, 64.
105#[allow(non_camel_case_types)]
106pub enum FDCANLength {
107    BYTES_0 = 0,
108    BYTES_1 = 1,
109    BYTES_2 = 2,
110    BYTES_3 = 3,
111    BYTES_4 = 4,
112    BYTES_5 = 5,
113    BYTES_6 = 6,
114    BYTES_7 = 7,
115    BYTES_8 = 8,
116    BYTES_12 = 12,
117    BYTES_16 = 16,
118    BYTES_20 = 20,
119    BYTES_24 = 24,
120    BYTES_32 = 32,
121    BYTES_48 = 48,
122    BYTES_64 = 64,
123}
124
125/// Prerequisite trait for FDCAN Packages
126///
127/// Sets the ID and number of bytes for a CAN package.
128/// Note that associated constants do not increase the size of a struct's memory.
129pub trait FDCANPack {
130    /// The length of the package in bytes, can be up to 64 bytes.
131    ///
132    /// pub structs must be a certain size for FDCAN to transfer
133    /// The following package sizes (in bytes) are 0, 1, 2, 3, 4, 5, 6,
134    /// 7, 8, 12, 16, 20, 24, 32, 48, 64.
135    const FDCAN_BYTES: FDCANLength;
136    /// 12 bit ID
137    ///
138    /// Reserved IDs up to 0x01F
139    ///
140    /// 0x010 = 0b00000010000
141    ///
142    /// 0x01F = 0b00000011111
143    ///
144    /// To receive all can filter ids within
145    /// this range you must set the mask to
146    /// 0x7F0 = 0b11111110000
147    ///
148    /// because you care that the bits \[10:4\]
149    /// of the can id are exactly the same as
150    /// bits \[10:4\] in 0x010/0x01F but the last four bits \[3:0\] can be 0 or 1
151    /// The same logic will be applied henceforth
152    const FDCAN_ID: u32;
153}
154
155// Highest priority CAN messages
156// ranging from 0x000 to 0x00F
157// All boards must accept these
158// messages
159/// 1 indicates tripped alarm
160pub const FDCAN_H2ALARM_ID: u16 = 0x001;
161/// 1 indicates led on
162pub const FDCAN_SYNCLED_ID: u16 = 0x00F;
163
164#[allow(non_camel_case_types)]
165#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
166#[repr(C)]
167pub struct FDCAN_FetPack_t {
168    pub fet_config: u32,
169    pub input_volt: u32,
170    pub cap_volt: u32,
171    pub cap_curr: u32,
172    pub res_curr: u32,
173    pub out_curr: u32,
174}
175impl FDCANPack for FDCAN_FetPack_t {
176    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_24;
177    const FDCAN_ID: u32 = 0x010;
178}
179
180#[allow(non_camel_case_types)]
181#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
182#[repr(C)]
183pub struct ECOCAN_RelPackChrg_t {
184    pub fc_coloumbs: i32,
185    pub cap_coloumbs: i32,
186}
187impl FDCANPack for ECOCAN_RelPackChrg_t {
188    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
189    const FDCAN_ID: u32 = 0x013;
190}
191
192#[allow(non_camel_case_types)]
193#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
194#[repr(C)]
195pub struct FDCAN_RelPackNrg_t {
196    pub fc_joules: i32,
197    pub cap_joules: i32,
198}
199impl FDCANPack for FDCAN_RelPackNrg_t {
200    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
201    const FDCAN_ID: u32 = 0x014;
202}
203
204#[allow(non_camel_case_types)]
205#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
206#[repr(C)]
207pub struct FDCAN_RelPackMtr_t {
208    pub mtr_volt: u32,
209    pub mtr_curr: u32,
210}
211impl FDCANPack for FDCAN_RelPackMtr_t {
212    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
213    const FDCAN_ID: u32 = 0x015;
214}
215
216#[allow(non_camel_case_types)]
217#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
218#[repr(C)]
219pub struct FDCAN_RelPackCap_t {
220    pub cap_volt: u32,
221    pub cap_curr: i32,
222}
223impl FDCANPack for FDCAN_RelPackCap_t {
224    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
225    const FDCAN_ID: u32 = 0x016;
226}
227
228#[allow(non_camel_case_types)]
229#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
230#[repr(C)]
231pub struct FDCAN_RelPackFc_t {
232    pub fc_volt: u32,
233    pub fc_curr: u32,
234}
235impl FDCANPack for FDCAN_RelPackFc_t {
236    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
237    const FDCAN_ID: u32 = 0x017;
238}
239
240#[allow(non_camel_case_types)]
241#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
242#[repr(C)]
243pub struct FDCAN_FccPack1_t {
244    pub fc_temp: i32,
245    pub fc_press: u32,
246}
247impl FDCANPack for FDCAN_FccPack1_t {
248    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
249    const FDCAN_ID: u32 = 0x020;
250}
251
252#[allow(non_camel_case_types)]
253#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
254#[repr(C)]
255pub struct FDCAN_FccPack2_t {
256    pub fan_rpm1: u32,
257    pub fan_rpm2: u32,
258}
259impl FDCANPack for FDCAN_FccPack2_t {
260    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
261    const FDCAN_ID: u32 = 0x021;
262}
263
264#[allow(non_camel_case_types)]
265#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
266#[repr(C)]
267pub struct FDCAN_FccPack3_t {
268    pub bme_temp: u32,
269    pub bme_humid: u32,
270}
271impl FDCANPack for FDCAN_FccPack3_t {
272    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
273    const FDCAN_ID: u32 = 0x022;
274}
275
276// Reserved IDs up to 0x03F
277// 0x030 = 0b00001000000
278// 0x03F = 0b00001001111
279// Mask: 0x7F0
280
281#[allow(non_camel_case_types)]
282#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
283#[repr(C)]
284pub struct ECOCAN_H2Pack1_t {
285    pub h2_sense_1: u16,
286    pub h2_sense_2: u16,
287    pub h2_sense_3: u16,
288    pub h2_sense_4: u16,
289}
290impl FDCANPack for ECOCAN_H2Pack1_t {
291    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
292    const FDCAN_ID: u32 = 0x030;
293}
294
295#[allow(non_camel_case_types)]
296#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
297#[repr(C)]
298pub struct ECOCAN_H2Pack2_t {
299    pub bme_temp: u16,
300    pub bme_humid: u16,
301    pub imon_7v: u16,
302    pub imon_12v: u16,
303}
304impl FDCANPack for ECOCAN_H2Pack2_t {
305    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
306    const FDCAN_ID: u32 = 0x031;
307}
308
309#[allow(non_camel_case_types)]
310#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
311#[repr(C)]
312pub struct ECOCAN_H2_ARM_ALARM_t {
313    pub h2_alarm_armed: u8,
314}
315impl FDCANPack for ECOCAN_H2_ARM_ALARM_t {
316    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_1;
317    const FDCAN_ID: u32 = 0x032;
318}
319
320#[allow(non_camel_case_types)]
321#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
322#[repr(C)]
323pub struct FDCAN_BOOSTPack1_t {
324    pub in_curr: u32,
325    pub in_volt: u32,
326}
327impl FDCANPack for FDCAN_BOOSTPack1_t {
328    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
329    const FDCAN_ID: u32 = 0x040;
330}
331
332#[allow(non_camel_case_types)]
333#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
334#[repr(C)]
335pub struct FDCAN_BOOSTPack2_t {
336    pub out_curr: u32,
337    pub out_volt: u32,
338}
339impl FDCANPack for FDCAN_BOOSTPack2_t {
340    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
341    const FDCAN_ID: u32 = 0x041;
342}
343
344#[allow(non_camel_case_types)]
345#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
346#[repr(C)]
347pub struct FDCAN_BOOSTPack3_t {
348    pub efficiency: u32,
349    pub joules: u32,
350}
351impl FDCANPack for FDCAN_BOOSTPack3_t {
352    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_8;
353    const FDCAN_ID: u32 = 0x042;
354}
355
356#[allow(non_camel_case_types)]
357#[derive(bincode::Encode, bincode::Decode, PartialEq, Clone, Debug, Format, Default)]
358#[repr(C)]
359pub struct FDCAN_BATTPack2_t {
360    pub out_curr: u16,
361    pub out_volt: u16,
362}
363impl FDCANPack for FDCAN_BATTPack2_t {
364    const FDCAN_BYTES: FDCANLength = FDCANLength::BYTES_4;
365    const FDCAN_ID: u32 = 0x050;
366}