Skip to content

Adding CAN FD 64 frame support to blf reader #568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 13, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions can/io/blf.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ class BLFParseError(Exception):
# valid data bytes, data
CAN_FD_MSG_STRUCT = struct.Struct("<HBBLLBBB5x64s")

# channel, dlc, valid payload length of data, tx count, arbitration id,
# frame length, flags, bit rate used in arbitration phase,
# bit rate used in data phase, time offset of brs field,
# time offset of crc delimiter field, bit count, direction,
# offset if extDataOffset is used, crc
CAN_FD_MSG_64_STRUCT = struct.Struct("<BBBBLLLLLLLHBBL")

# channel, length, flags, ecc, position, dlc, frame length, id, flags ext, data
CAN_ERROR_EXT_STRUCT = struct.Struct("<HHLBBBxLLH2x8s")

Expand All @@ -81,6 +88,7 @@ class BLFParseError(Exception):
CAN_MESSAGE2 = 86
GLOBAL_MARKER = 96
CAN_FD_MESSAGE = 100
CAN_FD_MESSAGE_64 = 101

NO_COMPRESSION = 0
ZLIB_DEFLATE = 2
Expand All @@ -91,6 +99,12 @@ class BLFParseError(Exception):
BRS = 0x2
ESI = 0x4

# CAN FD 64 Flags
REMOTE_FLAG_64 = 0x0010
EDL_64 = 0x1000
BRS_64 = 0x2000
ESI_64 = 0x4000

TIME_TEN_MICS = 0x00000001
TIME_ONE_NANS = 0x00000002

Expand Down Expand Up @@ -236,6 +250,29 @@ def __iter__(self):
data=can_data[:length],
channel=channel - 1)
yield msg
elif obj_type == CAN_FD_MESSAGE_64:
(
channel, dlc, _, _, can_id, _, fd_flags
) = CAN_FD_MSG_64_STRUCT.unpack_from(data, pos)[:7]
length = dlc2len(dlc)
can_data = struct.unpack_from(
"<{}s".format(length),
data,
pos + CAN_FD_MSG_64_STRUCT.size
)[0]
msg = Message(
timestamp=timestamp,
arbitration_id=can_id & 0x1FFFFFFF,
is_extended_id=bool(can_id & CAN_MSG_EXT),
is_remote_frame=bool(fd_flags & REMOTE_FLAG_64),
is_fd=bool(fd_flags & EDL_64),
bitrate_switch=bool(fd_flags & BRS_64),
error_state_indicator=bool(fd_flags & ESI_64),
dlc=length,
data=can_data[:length],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be more efficient something like this instead of unpacking the raw data above:

data_offset = pos + CAN_FD_MSG_64_STRUCT.size

data[data_offset:data_offset + length]

Also I've realized it should really be the valid payload length and not the DLC to support remote frames correctly, but it is more of a sanity thing.

channel=channel - 1
)
yield msg
elif obj_type == CAN_ERROR_EXT:
(channel, _, _, _, _, dlc, _, can_id, _,
can_data) = CAN_ERROR_EXT_STRUCT.unpack_from(data, pos)
Expand All @@ -247,6 +284,8 @@ def __iter__(self):
data=can_data[:dlc],
channel=channel - 1)
yield msg
# else:
# LOG.warning("Unknown object type (%d)", obj_type)

pos = next_pos

Expand Down