14#include "signal_layout.h"
17#include <unordered_set>
22 bool isExtended)
const {
23 return ResolveFrame(database, canId, isExtended).
definition;
27 std::uint32_t canId,
bool isExtended) {
28 const std::shared_ptr<const DecodeFrame> exact = database.
FindFrame(
FrameKey(canId, isExtended));
30 return {exact,
false};
31 if (!isExtended || canId > 0x1FFFFFFFU)
38 return DecodeImpl(database, frame,
nullptr);
43 const std::vector<SignalKey> &selection)
const {
44 return DecodeImpl(database, frame, &selection);
49 const std::vector<SignalKey> *selection)
const {
54 result.
status = FrameDecodeStatus::AmbiguousFrame;
57 const std::shared_ptr<const DecodeFrame> definition = match.
definition;
58 if (definition ==
nullptr)
60 result.
key = definition->GetKey();
62 std::vector<const DecodeSignal *> selected;
63 if (selection !=
nullptr) {
64 selected.reserve(selection->size());
65 std::unordered_set<SignalKey, SignalKeyHasher> keys;
67 if (!(key.frame == result.
key))
68 throw std::invalid_argument(
"Selected signal belongs to another frame: " + key.name);
69 if (!keys.insert(key).second)
70 throw std::invalid_argument(
"Duplicate selected signal: " + key.name);
71 const std::shared_ptr<const DecodeSignal> signal = database.
FindSignal(key);
73 throw std::invalid_argument(
"Unknown selected signal: " + key.name);
74 selected.push_back(signal.get());
80 result.
status = frame.
data.size() < definition->dlc
81 ? FrameDecodeStatus::InsufficientPayload
82 : FrameDecodeStatus::Valid;
84 const SelectorState selector = ReadSelector(*definition, frame);
85 const std::size_t count = selection !=
nullptr ? selected.size() : definition->signals.size();
86 result.signals.reserve(count);
87 for (std::size_t index = 0U; index < count; ++index) {
88 const DecodeSignal &signal = selection !=
nullptr ? *selected[index] : definition->signals[index];
89 DecodedSignalValue decoded = DecodeOneSignal(signal, definition->dlc, frame, selector);
90 if (!decoded.
valid && decoded.
status != SignalDecodeStatus::Inactive &&
91 result.
status == FrameDecodeStatus::Valid)
92 result.
status = FrameDecodeStatus::SignalErrors;
93 decoded.
definition = std::shared_ptr<const DecodeSignal>(definition, &signal);
95 result.signals.push_back(std::move(decoded));
101bool DbcDecoder::IsValidDefinition(
const DecodeSignal &signal, std::uint8_t dlc) {
102 if ((signal.
byteOrder != ByteOrder::Intel && signal.
byteOrder != ByteOrder::Motorola) ||
110 signal.
byteOrder == ByteOrder::Intel, dlc);
113DbcDecoder::SelectorState DbcDecoder::ReadSelector(
const DecodeFrame &definition,
115 SelectorState selector;
116 std::size_t count = 0U;
119 selector.definition = &signal;
127 selector.valid = signal.
valueType == ValueType::Unsigned &&
128 IsValidDefinition(signal, definition.
dlc);
129 selector.available = selector.valid && ExtractUnsigned(frame.
data, signal, selector.value);
136 const SelectorState &selector) {
138 std::uint64_t unsignedValue = 0U;
140 if (!IsValidDefinition(signal, dlc) ||
141 (signal.
multiplexing.
role != MultiplexRole::Unconditional && !selector.valid)) {
145 if (selector.definition->length < 64U && signal.
multiplexing.
value >= (std::uint64_t(1U) << selector.definition->length)) {
148 if (!selector.available) {
149 decoded.
status = SignalDecodeStatus::SelectorUnavailable;
153 decoded.
status = SignalDecodeStatus::Inactive;
157 if (!ExtractUnsigned(frame.
data, signal, unsignedValue)) {
158 decoded.
status = SignalDecodeStatus::InsufficientPayload;
162 if (signal.
valueType == ValueType::Signed)
168 if (
const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.
rawValue))
169 numericValue =
static_cast<double>(*signedValue);
171 numericValue =
static_cast<double>(std::get<std::uint64_t>(decoded.
rawValue));
174 decoded.
status = SignalDecodeStatus::PhysicalConversionFailed;
177 decoded.
valid =
true;
178 decoded.
status = SignalDecodeStatus::Valid;
183bool DbcDecoder::ExtractUnsigned(
const std::vector<std::uint8_t> &data,
185 std::uint64_t &value) {
189 if (signal.
byteOrder == ByteOrder::Intel)
192 return ExtractMotorola(data, signal.
startBit, signal.
length, value);
195bool DbcDecoder::ExtractIntel(
const std::vector<std::uint8_t> &data,
196 std::uint32_t startBit,
197 std::uint32_t length,
198 std::uint64_t &value) {
201 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
202 const std::uint64_t absoluteBit = std::uint64_t(startBit) + bitIndex;
203 const std::uint64_t byteIndex = absoluteBit / 8U;
204 const std::uint32_t bitInByte = absoluteBit % 8U;
206 if (byteIndex >= data.size())
209 const std::uint64_t bitValue =
210 (
static_cast<std::uint64_t
>((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
218bool DbcDecoder::ExtractMotorola(
const std::vector<std::uint8_t> &data,
219 std::uint32_t startBit,
220 std::uint32_t length,
221 std::uint64_t &value) {
232 std::size_t byteIndex = startBit / 8U;
233 std::uint32_t bitInByte = startBit % 8U;
235 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
236 if (byteIndex >= data.size())
240 value |=
static_cast<std::uint64_t
>((data[byteIndex] >> bitInByte) & 0x01U);
242 if (bitInByte == 0U) {
252std::int64_t DbcDecoder::SignExtend(std::uint64_t value, std::uint32_t bitLength) {
253 if ((bitLength == 0U) || (bitLength > 64U))
256 const std::uint64_t signMask = std::uint64_t(1U) << (bitLength - 1U);
257 const std::uint64_t valueMask = (bitLength == 64U)
259 : (std::uint64_t(1U) << bitLength) - 1U;
262 if ((value & signMask) == 0U)
263 return static_cast<std::int64_t
>(value);
266 return -1 -
static_cast<std::int64_t
>((~value) & valueMask);
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
std::shared_ptr< const DecodeFrame > FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find exact CAN ID first, then unique PGN among explicitly J1939 definitions.
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const
CAN frame decoding API and result types.
Runtime-ready frame definition.
Runtime-ready signal definition.
Multiplexing multiplexing
std::shared_ptr< const DecodeFrame > definition
One decoded signal value.
std::shared_ptr< const DecodeSignal > definition
SignalDecodeStatus status
Stable frame identifier: normalized CAN ID and frame type.
std::shared_ptr< const DecodeFrame > definition
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data