Skip to main content

rsiot/components_config/can_general/
can_id_helper.rs

1//! Пример реализации структуры идентификаторов CAN
2//!
3//! Используется расширенный формат шириной 29 бит. Стурктура идентификатора:
4//! - 5 бит - (prio) - приоритет
5//! - 8 бит - (src) - адрес отправителя
6//! - 8 бит - (dst) - адрес получателя
7//! - 8 бит - (type) - тип кадра. Между отправителем и получателем может быть много разных кадров
8
9use bitvec::prelude::*;
10
11use super::CanId;
12
13#[derive(Debug, Default, PartialEq)]
14/// Структура идентификатора CAN
15pub struct CanIdHelper(u32);
16
17impl CanIdHelper {
18    /// Создать новый идентификатор CAN
19    pub fn new(prio: u8, src: u8, dst: u8, type_: u8) -> Self {
20        let mut value = 0;
21        let bits = value.view_bits_mut::<Lsb0>();
22        bits[24..29].store_be(prio);
23        bits[16..24].store_be(src);
24        bits[8..16].store_be(dst);
25        bits[0..8].store_be(type_);
26        Self(value)
27    }
28
29    /// Установить приоритет
30    pub fn set_prio(self, prio: u8) -> Self {
31        let mut value = self.0;
32        let bits = value.view_bits_mut::<Lsb0>();
33        bits[24..29].store_be(prio);
34        Self(value)
35    }
36
37    /// Установить адрес отправителя
38    pub fn set_src(self, src: u8) -> Self {
39        let mut value = self.0;
40        let bits = value.view_bits_mut::<Lsb0>();
41        bits[16..24].store_be(src);
42        Self(value)
43    }
44
45    /// Установить адрес получателя
46    pub fn set_dst(self, dst: u8) -> Self {
47        let mut value = self.0;
48        let bits = value.view_bits_mut::<Lsb0>();
49        bits[8..16].store_be(dst);
50        Self(value)
51    }
52
53    /// Установить тип кадра
54    pub fn set_type(self, type_: u8) -> Self {
55        let mut value = self.0;
56        let bits = value.view_bits_mut::<Lsb0>();
57        bits[0..8].store_be(type_);
58        Self(value)
59    }
60}
61
62impl From<CanIdHelper> for u32 {
63    fn from(id: CanIdHelper) -> Self {
64        id.0
65    }
66}
67impl From<&CanIdHelper> for u32 {
68    fn from(id: &CanIdHelper) -> Self {
69        id.0
70    }
71}
72impl From<u32> for CanIdHelper {
73    fn from(value: u32) -> Self {
74        Self(value)
75    }
76}
77
78impl From<CanIdHelper> for CanId {
79    fn from(value: CanIdHelper) -> Self {
80        Self::Extended(value.0)
81    }
82}
83impl TryFrom<CanId> for CanIdHelper {
84    type Error = String;
85
86    fn try_from(value: CanId) -> Result<Self, Self::Error> {
87        match value {
88            CanId::Standard(_) => Err("Standard id not supported".to_string()),
89            CanId::Extended(v) => {
90                let id: CanIdHelper = v.into();
91                Ok(id)
92            }
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    //! cargo test components_config::can_general::can_id_helper --features="cmp_linux_can" -- --nocapture
100
101    use super::*;
102
103    use pretty_assertions::assert_eq;
104
105    #[test]
106    fn test_1() {
107        let id = CanIdHelper::default().set_prio(1);
108        assert_eq!(Into::<u32>::into(&id), 0x01000000);
109
110        let id = id.set_src(120);
111        assert_eq!(Into::<u32>::into(&id), 0x01780000);
112
113        let id = id.set_dst(76);
114        assert_eq!(Into::<u32>::into(&id), 0x01784C00);
115
116        let id = id.set_type(40);
117        assert_eq!(Into::<u32>::into(&id), 0x01784C28);
118    }
119}