Skip to main content

Module can

Module can 

Source
Expand description

CAN frame layer: 29-bit extended identifiers as laid out by the OpenLCB CAN Frame Transfer Standard.

 bit 28     : reserved, always 1
 bit 27     : 1 = OpenLCB message frame, 0 = CAN control frame
 bits 26-24 : frame type (message) / sequence (control)
 bits 23-12 : variable field (CAN-MTI, destination alias, or Node ID chunk)
 bits 11-0  : source alias

OpenLCB on CAN uses only CAN 2.0B extended frames. The 29-bit identifier is split into fields as shown above; the CAN Frame Transfer Standard defines two families of frames:

  • Control frames (bit 27 = 0) manage aliases. They never carry an OpenLCB message. See the alias login below.
  • Message frames (bit 27 = 1) carry OpenLCB messages. Bits 26-24 select the MessageFrameType: a global/addressed message whose CAN-MTI is in the variable field, one of four datagram frame kinds with the destination alias in the variable field, or a stream frame.

Because CAN arbitration lets the lowest identifier win, the layout also acts as a priority scheme: control frames beat message frames, and lower MTIs beat higher ones.

§Aliases and the login sequence

A 48-bit Node ID does not fit into the identifier, so each node reserves a 12-bit alias (see crate::alias) and uses it as the source field of every frame. Reserving an alias takes these control frames:

  CID7  [Node ID bits 47-36 | alias]   "I want this alias" (4 frames,
  CID6  [Node ID bits 35-24 | alias]    together they spell out the
  CID5  [Node ID bits 23-12 | alias]    whole Node ID, so two nodes
  CID4  [Node ID bits 11-0  | alias]    can't send identical frames)
    … wait at least 200 ms; if anyone objects or uses the alias, start over …
  RID   [alias]                         "Reserved"
  AMD   [alias] data = Node ID          "alias ↔ Node ID mapping defined"
  Initialization Complete (a normal message frame) — node is now online

After that the node must defend its alias: if another node sends a CID for it, answer with RID; if another node actually transmits with it, send AMR (Alias Map Reset) and choose a new one. AME (Alias Mapping Enquiry) asks nodes to repeat their AMD, either all of them (empty data) or the one whose Node ID is in the data. Node implements all of this; cid_frames and CanHeader are the building blocks.

§Example

use rolcb::can::{CanFrame, CanHeader, MessageFrameType};
use rolcb::Mti;

// A Verify Node ID Global message from alias 0xABC.
let id = CanHeader::Message { mti: Mti::VERIFY_NODE_ID_GLOBAL, alias: 0xABC }.encode();
assert_eq!(id, 0x1949_0ABC);

// Decoding is total: any 29-bit value maps to some CanHeader.
assert_eq!(CanHeader::decode(0x1070_1285), CanHeader::Amd { alias: 0x285 });
assert_eq!(
    CanHeader::decode(0x1A45_6123),
    CanHeader::Datagram { kind: MessageFrameType::DatagramOnly, dest: 0x456, alias: 0x123 },
);

let frame = CanFrame::new(id, &[])?;
assert_eq!(frame.src_alias(), 0xABC);
assert!(matches!(frame.header(), CanHeader::Message { mti: Mti::VERIFY_NODE_ID_GLOBAL, .. }));

Structs§

CanFrame
A CAN 2.0B frame with a 29-bit identifier and up to 8 data bytes.

Enums§

CanHeader
A decoded CAN identifier.
MessageFrameType
OpenLCB message frame types (bits 26-24 when bit 27 is set).

Functions§

cid_frames
Build the four CID frames (CID7..CID4) reserving alias for node.