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 aliasOpenLCB 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 onlineAfter 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.
- Message
Frame Type - OpenLCB message frame types (bits 26-24 when bit 27 is set).
Functions§
- cid_
frames - Build the four CID frames (CID7..CID4) reserving
aliasfornode.