Appendix B — CAN Frame Format Reference

OpenLCB uses CAN 2.0B extended frames with 29-bit identifiers. This appendix documents the bit-field layout of the CAN identifier and the different frame types used by the protocol.

B.1 29-Bit Identifier Layout

The 29-bit CAN extended identifier is divided into fields that differ based on whether the frame is a control frame or an OpenLCB message frame:

Bit:  28  27  26 25 24  23 22 21 20 19 18 17 16 15 14 13 12  11 10 9 8 7 6 5 4 3 2 1 0
      [R] [M] [--- Frame Type/Seq ---] [------ Variable Field ------] [-- Source Alias --]

R   = Reserved (bit 28): always 1 on transmit, ignored on receive
M   = OpenLCB Message flag (bit 27): 1 = OpenLCB message, 0 = CAN control frame
Bits 26-24 = Frame Type (messages) or Sequence Number (control frames)
Bits 23-12 = Variable Field (MTI for messages, sub-type for control frames)
Bits 11-0  = Source Alias (12-bit CAN alias of the sending node)

Identifier Masks

ConstantValuePurpose
RESERVED_TOP_BIT0x10000000Bit 28 -- always set to 1
CAN_OPENLCB_MSG0x08000000Bit 27 -- 1 = OpenLCB message frame
MASK_CAN_FRAME_SEQUENCE_NUMBER0x07000000Bits 26-24 -- frame type or sequence number
MASK_CAN_VARIABLE_FIELD0x00FFF000Bits 23-12 -- MTI or control frame sub-type
MASK_CAN_SOURCE_ALIAS0x00000FFFBits 11-0 -- source node alias

B.2 Frame Type Classification

flowchart TD A["CAN Frame Received"] --> B{"Bit 27 set?"} B -->|"Yes (1)"| C["OpenLCB Message Frame"] B -->|"No (0)"| D["CAN Control Frame"] C --> E{"Frame Type
bits 26-24"} E -->|"001"| F["Standard Message"] E -->|"010"| G["Datagram Only"] E -->|"011"| H["Datagram First"] E -->|"100"| I["Datagram Middle"] E -->|"101"| J["Datagram Final"] E -->|"110"| K["Reserved"] E -->|"111"| L["Stream"] D --> M{"Sequence bits
26-24 + Variable"} M --> N["CID / RID / AMD / AME / AMR"]

B.3 OpenLCB Message Frame Types

ConstantValueBits 26-24Description
OPENLCB_MESSAGE_STANDARD_FRAME_TYPE0x01000000001Global or addressed OpenLCB message (MTI in variable field)
CAN_FRAME_TYPE_DATAGRAM_ONLY0x02000000010Complete datagram in a single CAN frame
CAN_FRAME_TYPE_DATAGRAM_FIRST0x03000000011First frame of a multi-frame datagram
CAN_FRAME_TYPE_DATAGRAM_MIDDLE0x04000000100Middle frame of a multi-frame datagram
CAN_FRAME_TYPE_DATAGRAM_FINAL0x05000000101Final frame of a multi-frame datagram
CAN_FRAME_TYPE_RESERVED0x06000000110Reserved for future use
CAN_FRAME_TYPE_STREAM0x07000000111Stream data frame

B.4 CAN Control Frames

Control frames have bit 27 = 0. They handle alias allocation and mapping management:

Check ID (CID) Frames

ConstantValueBits 26-24Variable Field Contains
CAN_CONTROL_FRAME_CID70x07000000111Node ID bits 47-36 (first 12 bits)
CAN_CONTROL_FRAME_CID60x06000000110Node ID bits 35-24 (2nd 12 bits)
CAN_CONTROL_FRAME_CID50x05000000101Node ID bits 23-12 (3rd 12 bits)
CAN_CONTROL_FRAME_CID40x04000000100Node ID bits 11-0 (last 12 bits)

Alias Management Frames

ConstantValueDescriptionData Field
CAN_CONTROL_FRAME_RID0x00700000Reserve ID -- claims the aliasEmpty (0 bytes)
CAN_CONTROL_FRAME_AMD0x00701000Alias Map Definition -- maps alias to Node ID6-byte Node ID
CAN_CONTROL_FRAME_AME0x00702000Alias Mapping Enquiry -- query alias ownership6-byte Node ID (or empty for global query)
CAN_CONTROL_FRAME_AMR0x00703000Alias Map Reset -- node releasing alias6-byte Node ID

B.5 Multi-Frame Message Indicator Bits

For standard OpenLCB messages that span multiple CAN frames (not datagrams), the first data byte contains framing bits:

ConstantValueBits 5-4Meaning
MULTIFRAME_ONLY0x0000Single frame (complete message)
MULTIFRAME_FIRST0x1001First frame of multi-frame sequence
MULTIFRAME_FINAL0x2010Final frame of multi-frame sequence
MULTIFRAME_MIDDLE0x3011Middle frame of multi-frame sequence
Mask

Use MASK_MULTIFRAME_BITS (0x30) to extract the framing indicator from the first data byte.

B.6 Datagram Frame Sequencing

Datagrams up to 8 bytes use a single "Datagram Only" frame. Larger datagrams (up to 72 bytes) are split across multiple frames:

sequenceDiagram participant S as Sender participant B as CAN Bus participant R as Receiver Note over S,R: Datagram ≤ 8 bytes S->>B: Datagram Only (type 0x02) B->>R: Complete datagram Note over S,R: Datagram > 8 bytes S->>B: Datagram First (type 0x03) [8 bytes] S->>B: Datagram Middle (type 0x04) [8 bytes] S->>B: Datagram Middle (type 0x04) [8 bytes] S->>B: Datagram Final (type 0x05) [2-8 bytes] B->>R: Assembled datagram R->>B: Datagram OK Reply B->>S: Acknowledgment

For datagram frames, the variable field (bits 23-12) carries the destination alias instead of the MTI. The frame type bits (26-24) identify the frame as a datagram.

B.7 CAN Identifier Field Masks (OpenLCB Messages)

When the frame is a standard OpenLCB message (frame type = 001), the variable field contains the MTI. These masks extract specific MTI sub-fields from the CAN identifier:

ConstantValuePurpose
MASK_CAN_STREAM_OR_DATAGRAM0x01000000Stream/datagram indicator in CAN ID
MASK_CAN_PRIORITY0x00C00000Priority field in CAN ID
MASK_CAN_SIMPLE_PROTOCOL0x00010000Simple protocol indicator
MASK_CAN_DEST_ADDRESS_PRESENT0x00008000Destination address present
MASK_CAN_EVENT_PRESENT0x00004000Event ID present in payload
MASK_CAN_PRIORITY_MODIFIER0x00003000Priority modifier bits
Source Reference

All CAN frame format constants are defined in openlcb_defines.h. CAN frame type definitions are in the can_frame_format and can_control_frames Doxygen groups.

← Prev: Appendix A — MTI Reference Next: Appendix C — Address Spaces →