DBC Framework
DBC parsing and CAN signal decoding framework
dbc_decoder.cpp
Go to the documentation of this file.
1
12#include "dbc_decoder.h"
13
15 std::uint32_t canId,
16 bool isExtended) const {
17 const FrameKey key (canId, isExtended);
18 const std::unordered_map<FrameKey, std::size_t, FrameKeyHasher>::const_iterator it =
19 database.frameIndexByKey.find (key);
20
21 if (it == database.frameIndexByKey.end())
22 return nullptr;
23
24 const std::size_t index = it->second;
25 if (index >= database.frames.size())
26 return nullptr;
27
28 return &database.frames[index];
29}
30
32 const RawCanFrame &frame) const {
33 DecodedFrameValue result;
34 const DecodeFrame *definition = FindFrame (database, frame.canId, frame.isExtended);
35
36 if (definition == nullptr)
37 return result;
38
39 result.definition = definition;
40 result.valid = true;
41
42 for (std::size_t signalIndex = 0U; signalIndex < definition->signals.size(); ++signalIndex) {
43 const DecodeSignal &signal = definition->signals[signalIndex];
44 DecodedSignalValue decoded;
45 std::uint64_t unsignedValue = 0U;
46
47 decoded.definition = &signal;
48
49 if (!ExtractUnsigned (frame.data, signal, unsignedValue)) {
50 decoded.valid = false;
51 result.signals.push_back (decoded);
52 continue;
53 }
54
55 if (signal.valueType == ValueType::Signed)
56 decoded.rawValue = SignExtend (unsignedValue, signal.length);
57 else
58 decoded.rawValue = static_cast<std::int64_t> (unsignedValue);
59
60 decoded.physicalValue =
61 (static_cast<double> (decoded.rawValue) * signal.factor) + signal.offset;
62 decoded.valid = true;
63
64 result.signals.push_back (decoded);
65 }
66
67 return result;
68}
69
70bool DbcDecoder::ExtractUnsigned (const std::vector<std::uint8_t> &data,
71 const DecodeSignal &signal,
72 std::uint64_t &value) {
73 if ((signal.length == 0U) || (signal.length > 64U))
74 return false;
75
76 if (signal.byteOrder == ByteOrder::Intel)
77 return ExtractIntel (data, signal.startBit, signal.length, value);
78
79 return ExtractMotorola (data, signal.startBit, signal.length, value);
80}
81
82bool DbcDecoder::ExtractIntel (const std::vector<std::uint8_t> &data,
83 std::uint32_t startBit,
84 std::uint32_t length,
85 std::uint64_t &value) {
86 value = 0U;
87
88 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
89 const std::uint32_t absoluteBit = startBit + bitIndex;
90 const std::uint32_t byteIndex = absoluteBit / 8U;
91 const std::uint32_t bitInByte = absoluteBit % 8U;
92
93 if (byteIndex >= data.size())
94 return false;
95
96 const std::uint64_t bitValue =
97 (static_cast<std::uint64_t> ((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
98
99 value |= bitValue;
100 }
101
102 return true;
103}
104
105bool DbcDecoder::ExtractMotorola (const std::vector<std::uint8_t> &data,
106 std::uint32_t startBit,
107 std::uint32_t length,
108 std::uint64_t &value) {
109 /*
110 * DBC Motorola bit numbering:
111 * - startBit points to the most significant bit of the signal
112 * - inside a byte, bit numbering goes 7..0
113 * - crossing byte boundary moves to the next byte, bit 7
114 */
115
116 value = 0U;
117
118 std::int32_t currentBit = static_cast<std::int32_t> (startBit);
119
120 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
121 if (currentBit < 0)
122 return false;
123
124 const std::uint32_t absoluteBit = static_cast<std::uint32_t> (currentBit);
125 const std::uint32_t byteIndex = absoluteBit / 8U;
126 const std::uint32_t bitFromMsb = absoluteBit % 8U;
127 const std::uint32_t bitInByte = 7U - bitFromMsb;
128
129 if (byteIndex >= data.size())
130 return false;
131
132 value <<= 1U;
133 value |= static_cast<std::uint64_t> ((data[byteIndex] >> bitInByte) & 0x01U);
134
135 if ((absoluteBit % 8U) == 7U)
136 currentBit = static_cast<std::int32_t> ((byteIndex + 1U) * 8U);
137 else
138 --currentBit;
139 }
140
141 return true;
142}
143
144std::int64_t DbcDecoder::SignExtend (std::uint64_t value, std::uint32_t bitLength) {
145 if ((bitLength == 0U) || (bitLength >= 64U))
146 return static_cast<std::int64_t> (value);
147
148 const std::uint64_t signMask = (static_cast<std::uint64_t> (1U) << (bitLength - 1U));
149 const std::uint64_t valueMask = (static_cast<std::uint64_t> (1U) << bitLength) - 1U;
150
151 value &= valueMask;
152
153 if ((value & signMask) == 0U)
154 return static_cast<std::int64_t> (value);
155
156 return static_cast<std::int64_t> (value | (~valueMask));
157}
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
Definition: dbc_decoder.cpp:31
const DecodeFrame * FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
Definition: dbc_decoder.cpp:14
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Runtime decode database with fast lookup by CAN ID.
Runtime-ready frame definition.
Runtime-ready signal definition.
ValueType valueType
std::uint32_t startBit
ByteOrder byteOrder
std::uint32_t length
Fully decoded frame.
Definition: dbc_decoder.h:55
const DecodeFrame * definition
Definition: dbc_decoder.h:56
One decoded signal value.
Definition: dbc_decoder.h:38
std::int64_t rawValue
Definition: dbc_decoder.h:40
const DecodeSignal * definition
Definition: dbc_decoder.h:39
Key for fast frame lookup.
Raw CAN frame used for runtime or trace decoding.
Definition: dbc_decoder.h:23
std::vector< std::uint8_t > data
Definition: dbc_decoder.h:26
std::uint32_t canId
Definition: dbc_decoder.h:24
bool isExtended
Definition: dbc_decoder.h:25