125 lines
3.9 KiB
C++
125 lines
3.9 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
|
|
};
|
|
|
|
/**
|
|
* @brief One decoded signal value.
|
|
*/
|
|
struct DecodedSignalValue {
|
|
const DecodeSignal *definition = nullptr; /**< Signal definition. */
|
|
RawSignalValue rawValue = std::uint64_t(0U); /**< Exact signed or unsigned raw value. */
|
|
double physicalValue = 0.0; /**< Converted physical value. */
|
|
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 {
|
|
const DecodeFrame *definition = nullptr; /**< Frame definition. */
|
|
std::vector<DecodedSignalValue> signals; /**< Decoded signal values. */
|
|
bool valid = false; /**< true if frame was matched. */
|
|
|
|
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 Pointer to frame definition or nullptr.
|
|
*/
|
|
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.
|
|
* @return Decoded frame value.
|
|
*/
|
|
DecodedFrameValue Decode(const DecodeDatabase &database,
|
|
const RawCanFrame &frame) const;
|
|
|
|
private:
|
|
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,
|
|
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 */
|