Skip to content

Commit

Permalink
Require the CAN frame type when creating a CanId
Browse files Browse the repository at this point in the history
The most reliable way to know if a CAN ID is standard or extended is for
the driver to determine this (based on the IDE bit, which isn't
contained in the 29-bit ID). So we require the driver to determine the
frame type when creating the ID.

This was supposed to have been merged as a part of [1], but because of a
rebase-and-force-push snafu, probably as a result of poor Git hygiene on
my part, these changes were overwritten before the PR was merged.

[1] #4
  • Loading branch information
Notgnoshi committed Aug 8, 2023
1 parent 40da124 commit f361065
Showing 1 changed file with 33 additions and 26 deletions.
59 changes: 33 additions & 26 deletions src/driver/can_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,40 @@ pub enum Type {
#[repr(transparent)]
pub struct CanId(u32);

// Linux uses the top three unused bits to indicate whether the frame is standard/extended, remote,
// or an error frame. We do the same, because it's convenient.
const CAN_EFF_FLAG: u32 = 0x80000000;
// const CAN_RTR_FLAG: u32 = 0x40000000;
// const CAN_ERR_FLAG: u32 = 0x20000000;

const CAN_EFF_MASK: u32 = 0x1FFFFFFF;
const CAN_SFF_MASK: u32 = 0x000007FF;

impl CanId {
pub fn new(raw: u32) -> Self {
pub fn new(raw: u32, type_: Type) -> Self {
let raw = match type_ {
Type::Extended => (raw & CAN_EFF_MASK) | CAN_EFF_FLAG,
Type::Standard => raw & CAN_SFF_MASK,
};
Self(raw)
}

/// Get the raw value of the CAN ID
#[inline]
pub fn raw(&self) -> u32 {
self.0
match self.type_() {
Type::Extended => self.0 & CAN_EFF_MASK,
Type::Standard => self.0 & CAN_SFF_MASK,
}
}

/// Get the type of the ID (standard or extended)
#[inline]
pub fn type_(&self) -> Type {
if self.raw() <= 0x7FF {
Type::Standard
} else {
if self.0 & CAN_EFF_FLAG != 0 {
Type::Extended
} else {
Type::Standard
}
}

Expand Down Expand Up @@ -123,62 +139,53 @@ impl CanId {
mod tests {
use super::*;

#[test]
fn test_standard_extended() {
let can_id = CanId::new(0x07FF);
assert_eq!(can_id.type_(), Type::Standard);

let can_id = CanId::new(0x08FF);
assert_eq!(can_id.type_(), Type::Extended);
}

#[test]
fn test_priority() {
let can_id = CanId::new(0x18EF1CF5);
let can_id = CanId::new(0x18EF1CF5, Type::Extended);
assert_eq!(can_id.priority(), Priority::Default);
}

#[test]
fn test_source_address() {
let can_id = CanId::new(0x0705);
let can_id = CanId::new(0x0705, Type::Standard);
assert_eq!(can_id.type_(), Type::Standard);
// TODO: Is this right? Do 11-bit IDs always have a global address?
assert_eq!(can_id.source_address(), Address::GLOBAL);

let can_id = CanId::new(0x18EF1CF5);
let can_id = CanId::new(0x18EF1CF5, Type::Extended);
assert_eq!(can_id.source_address(), Address(0xF5));
}

#[test]
fn test_destination_address() {
let can_id = CanId::new(0x0705);
let can_id = CanId::new(0x0705, Type::Standard);
assert_eq!(can_id.destination_address(), Address::GLOBAL);

let can_id = CanId::new(0x18EEFF1C);
let can_id = CanId::new(0x18EEFF1C, Type::Extended);
assert_eq!(can_id.destination_address(), Address::GLOBAL);

let can_id = CanId::new(0x09F8031C);
let can_id = CanId::new(0x09F8031C, Type::Extended);
assert_eq!(can_id.destination_address(), Address::GLOBAL);

let can_id = CanId::new(0x0CAC1C13);
let can_id = CanId::new(0x0CAC1C13, Type::Extended);
assert_eq!(can_id.destination_address(), Address(0x1C));
}

#[test]
fn test_pgn() {
let can_id = CanId::new(0x07FF);
let can_id = CanId::new(0x07FF, Type::Standard);
assert_eq!(can_id.pgn(), Pgn::NULL);

let can_id = CanId::new(0x0CAC1C13);
let can_id = CanId::new(0x0CAC1C13, Type::Extended);
assert_eq!(can_id.pgn(), Pgn::from_raw(0x0AC00));

let can_id = CanId::new(0x18FF3F13);
let can_id = CanId::new(0x18FF3F13, Type::Extended);
assert_eq!(can_id.pgn(), Pgn::from_raw(0x0FF3F));

let can_id = CanId::new(0x18EF1CF5);
let can_id = CanId::new(0x18EF1CF5, Type::Extended);
assert_eq!(can_id.pgn(), Pgn::from_raw(0x0EF00));

let can_id = CanId::new(0x18EEFF1C);
let can_id = CanId::new(0x18EEFF1C, Type::Extended);
assert_eq!(can_id.pgn(), Pgn::from_raw(0x0EE00));
}
}

0 comments on commit f361065

Please sign in to comment.