HardFOC Core
API reference
Loading...
Searching...
No Matches
HfCanFrameRecord.h
Go to the documentation of this file.
1
27#pragma once
28
29#include <cstddef>
30#include <cstdint>
31
32#include "HfCanPort.h"
33
34namespace hf::can::record {
35
36inline constexpr uint8_t kVersion = 1U;
37inline constexpr std::size_t kHeaderSize = 8U;
38inline constexpr std::size_t kRecordHeaderSize = 6U;
39inline constexpr std::size_t kMaxRecordSize = kRecordHeaderSize + kFdMaxLen;
41inline constexpr std::size_t kMaxDatagram = 4096U;
42inline constexpr uint32_t kIdExtBit = 0x80000000U;
43inline constexpr uint32_t kIdRtrBit = 0x40000000U;
45
47inline constexpr uint8_t kDgramKeepAlive = 0x01U;
48
50struct Header {
51 uint8_t version{kVersion};
52 uint8_t flags{0};
53 uint16_t seq{0};
54 uint32_t epoch{0};
55};
56
58enum class DecodeError : uint8_t {
59 None = 0,
60 Truncated,
62 BadLength,
63 BadFrame,
64};
65
66inline void PutU16(uint8_t* p, uint16_t v) noexcept {
67 p[0] = static_cast<uint8_t>(v);
68 p[1] = static_cast<uint8_t>(v >> 8U);
69}
70inline void PutU32(uint8_t* p, uint32_t v) noexcept {
71 p[0] = static_cast<uint8_t>(v);
72 p[1] = static_cast<uint8_t>(v >> 8U);
73 p[2] = static_cast<uint8_t>(v >> 16U);
74 p[3] = static_cast<uint8_t>(v >> 24U);
75}
76inline uint16_t GetU16(const uint8_t* p) noexcept {
77 return static_cast<uint16_t>(static_cast<uint16_t>(p[0]) | static_cast<uint16_t>(p[1] << 8U));
78}
79inline uint32_t GetU32(const uint8_t* p) noexcept {
80 return static_cast<uint32_t>(p[0]) | (static_cast<uint32_t>(p[1]) << 8U) | (static_cast<uint32_t>(p[2]) << 16U) |
81 (static_cast<uint32_t>(p[3]) << 24U);
82}
83
85inline std::size_t EncodeHeader(uint8_t* out, const Header& h) noexcept {
86 out[0] = h.version;
87 out[1] = h.flags;
88 PutU16(&out[2], h.seq);
89 PutU32(&out[4], h.epoch);
90 return kHeaderSize;
91}
92
94constexpr std::size_t RecordSize(const CanFrame& f) noexcept { return kRecordHeaderSize + f.len; }
95
100inline std::size_t EncodeRecord(uint8_t* out, std::size_t cap, const CanFrame& f) noexcept {
101 if (!IsWellFormed(f) || cap < RecordSize(f)) {
102 return 0U;
103 }
104 uint32_t id = f.id;
105 if (f.IsExtended()) id |= kIdExtBit;
106 if (f.IsRemote()) id |= kIdRtrBit;
107 PutU32(&out[0], id);
108 out[4] = static_cast<uint8_t>(f.flags & kRecordFlagMask);
109 out[5] = f.len;
110 for (uint8_t i = 0; i < f.len; ++i) {
111 out[kRecordHeaderSize + i] = f.data[i];
112 }
113 return RecordSize(f);
114}
115
121template <typename OnFrame>
122DecodeError DecodeDatagram(const uint8_t* p, std::size_t n, Header* header, OnFrame&& on_frame) {
123 if (n < kHeaderSize) return DecodeError::Truncated;
124 if (p[0] != kVersion) return DecodeError::BadVersion;
125 Header h;
126 h.version = p[0];
127 h.flags = p[1];
128 h.seq = GetU16(&p[2]);
129 h.epoch = GetU32(&p[4]);
130 for (int pass = 0; pass < 2; ++pass) {
131 std::size_t off = kHeaderSize;
132 while (off < n) {
133 if (n - off < kRecordHeaderSize) return DecodeError::Truncated;
134 const uint32_t raw = GetU32(&p[off]);
135 CanFrame f;
136 f.flags = static_cast<uint8_t>(p[off + 4U] & kRecordFlagMask);
137 if ((p[off + 4U] & static_cast<uint8_t>(~kRecordFlagMask)) != 0U) return DecodeError::BadFrame;
138 f.len = p[off + 5U];
139 if (f.len > kFdMaxLen) return DecodeError::BadLength;
140 if (n - off - kRecordHeaderSize < f.len) return DecodeError::Truncated;
141 if ((raw & kIdExtBit) != 0U) f.flags |= frame_flag::kExt;
142 if ((raw & kIdRtrBit) != 0U) f.flags |= frame_flag::kRtr;
143 f.id = raw & ~(kIdExtBit | kIdRtrBit);
144 if (!IsWellFormed(f)) return DecodeError::BadFrame;
145 if (pass == 1) {
146 for (uint8_t i = 0; i < f.len; ++i) {
147 f.data[i] = p[off + kRecordHeaderSize + i];
148 }
149 on_frame(static_cast<const CanFrame&>(f));
150 }
151 off += kRecordHeaderSize + f.len;
152 }
153 }
154 if (header != nullptr) *header = h;
155 return DecodeError::None;
156}
157
158} // namespace hf::can::record
Transport-neutral CAN frame and the ICanPort interface for port bindings (EspTwaiPort,...
constexpr uint8_t kFdf
FD frame format.
Definition HfCanPort.h:42
constexpr uint8_t kBrs
bit-rate switch (FD only)
Definition HfCanPort.h:43
constexpr uint8_t kEsi
error state indicator (FD only)
Definition HfCanPort.h:44
constexpr uint8_t kRtr
remote request (classic only)
Definition HfCanPort.h:41
constexpr uint8_t kExt
29-bit identifier
Definition HfCanPort.h:40
Definition HfCanFrameRecord.h:34
std::size_t EncodeRecord(uint8_t *out, std::size_t cap, const CanFrame &f) noexcept
Append the record of f.
Definition HfCanFrameRecord.h:100
constexpr uint8_t kDgramKeepAlive
Definition HfCanFrameRecord.h:47
uint32_t GetU32(const uint8_t *p) noexcept
Definition HfCanFrameRecord.h:79
constexpr std::size_t kMaxDatagram
Definition HfCanFrameRecord.h:41
constexpr uint8_t kRecordFlagMask
Definition HfCanFrameRecord.h:44
constexpr uint32_t kIdExtBit
Definition HfCanFrameRecord.h:42
void PutU32(uint8_t *p, uint32_t v) noexcept
Definition HfCanFrameRecord.h:70
DecodeError DecodeDatagram(const uint8_t *p, std::size_t n, Header *header, OnFrame &&on_frame)
Decode a datagram; on_frame(const CanFrame&) is called per record.
Definition HfCanFrameRecord.h:122
constexpr std::size_t kHeaderSize
Definition HfCanFrameRecord.h:37
constexpr std::size_t kRecordHeaderSize
Definition HfCanFrameRecord.h:38
constexpr std::size_t RecordSize(const CanFrame &f) noexcept
Bytes the record of f takes.
Definition HfCanFrameRecord.h:94
constexpr std::size_t kMaxRecordSize
Definition HfCanFrameRecord.h:39
void PutU16(uint8_t *p, uint16_t v) noexcept
Definition HfCanFrameRecord.h:66
constexpr uint32_t kIdRtrBit
Definition HfCanFrameRecord.h:43
constexpr uint8_t kVersion
Definition HfCanFrameRecord.h:36
std::size_t EncodeHeader(uint8_t *out, const Header &h) noexcept
Write the header; out has kHeaderSize bytes.
Definition HfCanFrameRecord.h:85
DecodeError
Why a datagram was rejected.
Definition HfCanFrameRecord.h:58
@ Truncated
shorter than the header, or a record runs past the end
@ BadFrame
record is not a well-formed frame (flags, id range, length)
@ BadLength
record len > 64
uint16_t GetU16(const uint8_t *p) noexcept
Definition HfCanFrameRecord.h:76
constexpr bool IsWellFormed(const CanFrame &f) noexcept
Structurally valid frame (flags, id range, length for the frame kind)?
Definition HfCanPort.h:67
constexpr uint8_t kFdMaxLen
Largest CAN FD payload in bytes.
Definition HfCanPort.h:32
One CAN or CAN FD frame; len is a byte count, never a DLC code.
Definition HfCanPort.h:49
uint32_t id
Definition HfCanPort.h:50
uint8_t len
Definition HfCanPort.h:51
uint8_t flags
Definition HfCanPort.h:52
uint8_t data[kFdMaxLen]
Definition HfCanPort.h:53
Datagram header.
Definition HfCanFrameRecord.h:50
uint16_t seq
Definition HfCanFrameRecord.h:53
uint32_t epoch
Definition HfCanFrameRecord.h:54
uint8_t version
Definition HfCanFrameRecord.h:51
uint8_t flags
Definition HfCanFrameRecord.h:52