141 lines
4.8 KiB
C++
141 lines
4.8 KiB
C++
/**
|
|
* @file dbc_decoder.h
|
|
* @brief
|
|
*
|
|
* Created: 2026-03-13
|
|
* Author: Deeaitch (Dim. Himro)
|
|
*
|
|
* Licensed under the MIT License.
|
|
* See LICENSE file in the project root for full license text.
|
|
*/
|
|
|
|
#ifndef DBC_DECODER_H
|
|
#define DBC_DECODER_H
|
|
|
|
#include <cstdint>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
#include "decode_database.h"
|
|
|
|
/**
|
|
* @brief Raw CAN frame used for runtime or trace decoding.
|
|
*/
|
|
struct RawCanFrame {
|
|
std::uint32_t canId = 0U; /**< Normalized CAN ID. */
|
|
bool isExtended = false; /**< true for extended frame. */
|
|
std::vector<std::uint8_t> data; /**< Payload bytes. */
|
|
|
|
RawCanFrame() = default;
|
|
};
|
|
|
|
enum class SignalDecodeStatus {
|
|
InvalidDefinition,
|
|
InsufficientPayload,
|
|
SelectorUnavailable,
|
|
Inactive,
|
|
Valid,
|
|
PhysicalConversionFailed
|
|
};
|
|
|
|
/** Frame summary: short payload takes precedence over individual signal errors. */
|
|
enum class FrameDecodeStatus {
|
|
UnknownFrame,
|
|
InsufficientPayload,
|
|
SignalErrors,
|
|
Valid
|
|
};
|
|
|
|
/**
|
|
* @brief One decoded signal value.
|
|
*/
|
|
struct DecodedSignalValue {
|
|
std::shared_ptr<const DecodeSignal> definition; /**< Owning immutable definition. */
|
|
SignalKey key; /**< Stable application identifier. */
|
|
RawSignalValue rawValue = std::uint64_t(0U); /**< Exact raw value for Valid or PhysicalConversionFailed. */
|
|
double physicalValue = 0.0; /**< Conversion result, possibly NaN/Inf on failure. */
|
|
bool valid = false; /**< true if decoding succeeded. */
|
|
SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition;
|
|
|
|
/** Lookup using the raw integer; nullptr for invalid or unmapped values. */
|
|
const std::string *GetValueDescription() const {
|
|
return valid && definition ? FindValueDescription(definition->valueDescriptions, rawValue) : nullptr;
|
|
}
|
|
|
|
DecodedSignalValue() = default;
|
|
};
|
|
|
|
/**
|
|
* @brief Fully decoded frame.
|
|
*/
|
|
struct DecodedFrameValue {
|
|
std::shared_ptr<const DecodeFrame> definition; /**< Owning immutable definition. */
|
|
FrameKey key; /**< Stable application identifier. */
|
|
std::vector<DecodedSignalValue> signals; /**< Decoded signal values. */
|
|
bool valid = false; /**< true if frame was matched. */
|
|
FrameDecodeStatus status = FrameDecodeStatus::UnknownFrame; /**< Inspect signals for individual failures. */
|
|
|
|
DecodedFrameValue() = default;
|
|
};
|
|
|
|
/**
|
|
* @brief Runtime CAN decoder using prebuilt decode database.
|
|
*/
|
|
class DbcDecoder {
|
|
public:
|
|
/**
|
|
* @brief Find frame definition by CAN ID.
|
|
* @param database Runtime decode database.
|
|
* @param canId Normalized CAN ID.
|
|
* @param isExtended true for extended frame.
|
|
* @return Owning immutable frame handle or nullptr. Safe across reload.
|
|
*/
|
|
std::shared_ptr<const DecodeFrame> FindFrame(const DecodeDatabase &database,
|
|
std::uint32_t canId,
|
|
bool isExtended) const;
|
|
|
|
/**
|
|
* @brief Decode one raw CAN frame.
|
|
* @param database Runtime decode database.
|
|
* @param frame Raw CAN frame.
|
|
* Short payloads decode available signals; bytes beyond declared DLC are ignored.
|
|
* @return Decoded frame value.
|
|
*/
|
|
DecodedFrameValue Decode(const DecodeDatabase &database,
|
|
const RawCanFrame &frame) const;
|
|
|
|
private:
|
|
static bool IsValidDefinition(const DecodeSignal &signal, std::uint8_t dlc);
|
|
|
|
struct SelectorState {
|
|
const DecodeSignal *definition = nullptr;
|
|
bool valid = false;
|
|
bool available = false;
|
|
std::uint64_t value = 0U;
|
|
};
|
|
|
|
static SelectorState ReadSelector(const DecodeFrame &definition, const RawCanFrame &frame);
|
|
static DecodedSignalValue DecodeOneSignal(const DecodeSignal &signal,
|
|
std::uint8_t dlc,
|
|
const RawCanFrame &frame,
|
|
const SelectorState &selector);
|
|
|
|
static bool ExtractUnsigned(const std::vector<std::uint8_t> &data,
|
|
const DecodeSignal &signal,
|
|
std::uint64_t &value);
|
|
|
|
static bool ExtractIntel(const std::vector<std::uint8_t> &data,
|
|
std::uint32_t startBit,
|
|
std::uint32_t length,
|
|
std::uint64_t &value);
|
|
|
|
static bool ExtractMotorola(const std::vector<std::uint8_t> &data,
|
|
std::uint32_t startBit,
|
|
std::uint32_t length,
|
|
std::uint64_t &value);
|
|
|
|
static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
|
|
};
|
|
|
|
#endif /* DBC_DECODER_H */
|