stm32g473_hal_oppe/fdcan/
id.rs1use core::cmp::{Ord, Ordering};
4
5use super::message_ram::enums::{IdType, RemoteTransmissionRequest};
6
7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
9#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
10pub struct StandardId(u16);
11
12impl StandardId {
13 pub const ZERO: Self = Self(0);
15
16 pub const MAX: Self = Self(0x7FF);
18
19 #[inline]
23 pub const fn new(raw: u16) -> Option<Self> {
24 if raw <= 0x7FF {
25 Some(Self(raw))
26 } else {
27 None
28 }
29 }
30
31 #[inline]
38 pub const unsafe fn new_unchecked(raw: u16) -> Self {
39 Self(raw)
40 }
41
42 #[inline]
44 pub fn as_raw(&self) -> u16 {
45 self.0
46 }
47}
48impl From<StandardId> for IdType {
49 fn from(_id: StandardId) -> Self {
50 IdType::StandardId
51 }
52}
53
54#[derive(Debug, Copy, Clone, Eq, PartialEq)]
56#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
57pub struct ExtendedId(u32);
58
59impl ExtendedId {
60 pub const ZERO: Self = Self(0);
62
63 pub const MAX: Self = Self(0x1FFF_FFFF);
65
66 #[inline]
70 pub const fn new(raw: u32) -> Option<Self> {
71 if raw <= 0x1FFF_FFFF {
72 Some(Self(raw))
73 } else {
74 None
75 }
76 }
77
78 #[inline]
85 pub const unsafe fn new_unchecked(raw: u32) -> Self {
86 Self(raw)
87 }
88
89 #[inline]
91 pub fn as_raw(&self) -> u32 {
92 self.0
93 }
94
95 pub fn standard_id(&self) -> StandardId {
97 StandardId((self.0 >> 18) as u16)
99 }
100}
101
102impl From<ExtendedId> for IdType {
103 fn from(_id: ExtendedId) -> Self {
104 IdType::ExtendedId
105 }
106}
107
108#[derive(Debug, Copy, Clone, Eq, PartialEq)]
110#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
111pub enum Id {
112 Standard(StandardId),
114
115 Extended(ExtendedId),
117}
118
119impl From<StandardId> for Id {
120 #[inline]
121 fn from(id: StandardId) -> Self {
122 Id::Standard(id)
123 }
124}
125
126impl From<ExtendedId> for Id {
127 #[inline]
128 fn from(id: ExtendedId) -> Self {
129 Id::Extended(id)
130 }
131}
132
133impl From<Id> for IdType {
134 #[inline]
135 fn from(id: Id) -> Self {
136 match id {
137 Id::Standard(id) => id.into(),
138 Id::Extended(id) => id.into(),
139 }
140 }
141}
142
143#[derive(Clone, Copy, Debug, PartialEq, Eq)]
154#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
155pub(crate) struct IdReg(u32);
156
157impl IdReg {
158 const STANDARD_SHIFT: u32 = 18;
159 #[allow(dead_code)]
160 const STANDARD_MASK: u32 = 0x1FFC0000;
161
162 const EXTENDED_SHIFT: u32 = 0;
163 const EXTENDED_MASK: u32 = 0x1FFFFFFF;
164
165 const XTD_SHIFT: u32 = 30;
166 const XTD_MASK: u32 = 1 << Self::XTD_SHIFT;
167
168 const RTR_SHIFT: u32 = 29;
169 const RTR_MASK: u32 = 1 << Self::RTR_SHIFT;
170
171 fn new_standard(id: StandardId) -> Self {
175 Self(u32::from(id.as_raw()) << Self::STANDARD_SHIFT)
176 }
177
178 fn new_extended(id: ExtendedId) -> Self {
182 Self(id.as_raw() << Self::EXTENDED_SHIFT | (1 << Self::XTD_SHIFT))
183 }
184
185 pub(crate) fn as_raw_id(&self) -> u32 {
186 self.0 & Self::EXTENDED_MASK
187 }
188
189 pub(crate) fn from_register(id: u32, rtr: RemoteTransmissionRequest, xtd: IdType) -> Self {
190 let rtr: u32 = match rtr {
191 RemoteTransmissionRequest::TransmitDataFrame => 0,
192 RemoteTransmissionRequest::TransmitRemoteFrame => 1 << Self::RTR_SHIFT,
193 };
194 let xtd: u32 = match xtd {
195 IdType::StandardId => 0,
196 IdType::ExtendedId => 1 << Self::XTD_SHIFT,
197 };
198 Self(id | rtr | xtd)
199 }
200
201 #[must_use = "returns a new IdReg without modifying `self`"]
204 pub(crate) fn with_rtr(self, rtr: bool) -> Self {
205 if rtr {
206 Self(self.0 | (1 << Self::RTR_SHIFT))
207 } else {
208 Self(self.0 & !Self::RTR_MASK)
209 }
210 }
211
212 pub fn to_id(self) -> Id {
214 if self.is_extended() {
215 Id::Extended(unsafe {
216 ExtendedId::new_unchecked((self.0 >> Self::EXTENDED_SHIFT) & Self::EXTENDED_MASK)
217 })
218 } else {
219 Id::Standard(unsafe {
220 StandardId::new_unchecked(
221 ((self.0 >> Self::STANDARD_SHIFT) & Self::STANDARD_MASK) as u16,
222 )
223 })
224 }
225 }
226
227 pub fn is_extended(self) -> bool {
229 (self.0 & Self::XTD_MASK) != 0
230 }
231
232 pub fn is_standard(self) -> bool {
234 !self.is_extended()
235 }
236
237 pub(crate) fn rtr(self) -> bool {
239 self.0 & Self::RTR_MASK != 0
240 }
241}
242impl From<Id> for IdReg {
243 fn from(id: Id) -> Self {
244 match id {
245 Id::Standard(s) => IdReg::new_standard(s),
246 Id::Extended(e) => IdReg::new_extended(e),
247 }
248 }
249}
250impl From<IdReg> for Id {
251 fn from(idr: IdReg) -> Self {
252 idr.to_id()
253 }
254}
255impl From<IdReg> for IdType {
256 #[inline]
257 fn from(id: IdReg) -> Self {
258 if id.is_standard() {
259 IdType::StandardId
260 } else {
261 IdType::ExtendedId
262 }
263 }
264}
265impl From<IdReg> for RemoteTransmissionRequest {
266 #[inline]
267 fn from(id: IdReg) -> Self {
268 if id.rtr() {
269 RemoteTransmissionRequest::TransmitRemoteFrame
270 } else {
271 RemoteTransmissionRequest::TransmitDataFrame
272 }
273 }
274}
275
276impl Ord for IdReg {
278 fn cmp(&self, other: &Self) -> Ordering {
279 let rtr = self.rtr().cmp(&other.rtr()).reverse();
281
282 let id_a = self.to_id();
283 let id_b = other.to_id();
284 match (id_a, id_b) {
285 (Id::Standard(a), Id::Standard(b)) => {
286 a.as_raw().cmp(&b.as_raw()).reverse().then(rtr)
288 }
289 (Id::Extended(a), Id::Extended(b)) => a.as_raw().cmp(&b.as_raw()).reverse().then(rtr),
290 (Id::Standard(a), Id::Extended(b)) => {
291 a.as_raw()
293 .cmp(&b.standard_id().as_raw())
294 .reverse()
295 .then(Ordering::Greater)
296 }
297 (Id::Extended(a), Id::Standard(b)) => a
298 .standard_id()
299 .as_raw()
300 .cmp(&b.as_raw())
301 .reverse()
302 .then(Ordering::Less),
303 }
304 }
305}
306
307impl PartialOrd for IdReg {
308 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
309 Some(self.cmp(other))
310 }
311}