Skip to content

zi-m/dbcppp

Repository files navigation

[Build Status

dbcppp

A C/C++ DBC file parser based on boost.spirit. This library is designed for decoding performance.

Features

  • very fast decoding
  • verbose parser output in error case
  • DBC is editable through C/C++ interface exported from the library
  • read/write DBC file
  • decode functionality for frames of arbitrarily byte length
  • cantools like decoding
  • KCD file format support

Getting started

Build & Install

git clone --recurse-submodules https://github.com/xR3b0rn/dbcppp.git
cd dbcppp
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j
make RunTests
make install
ldconfig # on Unix-systems only

Usage example

Command line tool

dbc2

# generate C source from DBC/KCD
dbcppp dbc2 --dbc=file.dbc --format=C
# beauty or merge DBC/KCD
dbcppp dbc2 --dbc=file1.dbc --dbc=file2.kcd --format=DBC
# print DBC/KCD in human readable format
dbcppp dbc2 --dbc=file1.dbc --dbc=file2.kcd --format=human

decode

cantools like decoding:

candump any | dbcppp decode --bus=vcan0,file1.dbc --bus=vcan1,file2.dbc

Library

#include <fstream>
#include <dbcppp/Network.h>
int main()
{
    std::unique_ptr<dbcppp::INetwork> net;
    {
        std::ifstream idbc("your.dbc");
        net = dbcppp::INetwork::LoadDBCFromIs(idbc);
    }
    std::unordered_map<uint64_t, const dbcppp::IMessage*> messages;
    for (const dbcppp::IMessage& msg : net->Messages())
    {
        messages.insert(std::make_pair(msg.Id(), &msg));
    }
    can_frame frame;
    while (1)
    {
        receive_frame_data(&frame);
        auto iter = messages.find(frame.can_id);
        if (iter != messages.end())
        {
            const dbcppp::IMessage* msg = iter->second;
            std::cout << "Received Message: " << msg->Name() << "\n";
            for (const dbcppp::ISignal& sig : msg->Signals())
            {
                const dbcppp::ISignal* mux_sig = msg->MuxSignal();
                if (sig.MultiplexerIndicator() != dbcppp::ISignal::EMultiplexer::MuxValue ||
                    (mux_sig && mux_sig->Decode(frame.data) == sig.MultiplexerSwitchValue()))
                {
                    std::cout << "\t" << sig.Name() << "=" << sig.RawToPhys(sig.Decode(frame.data)) << sig.Unit() << "\n";
                }
            }
        }
    }
}
  • C
#include <stdio.h>
#include <dbcppp/CApi.h>
int main()
{
    const dbcppp_Nework* net = dbcppp_NetworkLoadDBCFromFile("your.dbc");
    if (net)
    {
        can_frame frame;
        while (1)
        {
            receive_can_frame_from_somewhere(&frame);
            const dbcppp_Message* msg = nullptr;
            auto n_msgs = dbcppp_NetworkMessages_Size(net);
            for (uint64_t i = 0; i < n_msgs; i++)
            {
                const dbcppp_Message* msg = dbcppp_NetworkMessages_Get(i);
                if (dbcppp_MessageId(tmp) == frame.can_id)
                {
                    printf("Received message: %s\n", dbcppp_MessageGetName(msg));
                    dbcppp_MessageForEachSignal(msg, print_signal_data, &frame);
                    for (uint64_t i = 0; i < dbcppp_MessageSignals_Size(msg); i++)
                    {
                        const dbcppp_Signal* sig = dbcppp_MessageSignals_Get(msg, i);
                        uint64_t raw = dbcppp_SignalDecode(sig, frame.data);
                        double phys = dbcppp_SignalRawToPhys(sig, raw);
                        printf("\t%s=%f\n", dbcppp_SignalName(sig), phys);
                    }
                }
            }
        }
    }
    dbcppp_NetworkFree(net);
}

DBC data types

Supported

  • version
  • new_symbols
  • bit_timing
  • nodes
  • value_tables
  • messages
  • message_transmitters
  • environment_variables
  • environment_variables_data
  • signal_types
  • comments
  • attribute_definitions
  • attribute_defaults
  • attribute_values
  • value_descriptions
  • signal_extended_value_type_list
  • signal_groups
  • signal_multiplexer_value

Not supported yet

  • sigtype_attr_list
  • signal_type_refs

Decode-function

The signals decode function is using prestored masks and fixed offsets to speed up calculation, therefore the decoding-function should be almost as fast as a code generated decode function would be. The assembly of the decode-function on its critical path (signed and byte swap must happen) looks like this (VS19 10.0.18362.0 compiler):

template <Alignment aAlignment, Signal::ByteOrder aByteOrder, Signal::ValueType aValueType, Signal::ExtendedValueType aExtendedValueType>
double template_decode(const Signal* sig, const void* nbytes) noexcept
00007FF8025BCA73  mov         rax,rcx  
00007FF8025BCA76  mov         rcx,qword ptr [rcx+140h]  
00007FF8025BCA7D  xorps       xmm0,xmm0  
00007FF8025BCA80  bswap       r8  
00007FF8025BCA83  shr         r8,cl  
00007FF8025BCA86  and         r8,qword ptr [rax+130h]  
00007FF8025BCA8D  mov         rcx,qword ptr [rax+138h]  
00007FF8025BCA94  mov         rax,rcx  
00007FF8025BCA97  or          rcx,r8  
00007FF8025BCA9A  and         rax,r8  
00007FF8025BCA9D  cmove       rcx,r8  
00007FF8025BCAA1  cvtsi2sd    xmm0,rcx  
00007FF8025BCAA6  ret   

On the best path (no byteswap must take place and ExtendedValueType == Double) the decode function only has 5 instructions:

template <Alignment aAlignment, Signal::ByteOrder aByteOrder, Signal::ValueType aValueType, Signal::ExtendedValueType aExtendedValueType>
double template_decode(const Signal* sig, const void* nbytes) noexcept
00007FF8025BCAF0  mov         rax,qword ptr [rdx]  
00007FF8025BCAF3  mov         qword ptr [rsp+8],rcx  
00007FF8025BCAF8  mov         qword ptr [sig],rax  
00007FF8025BCAFD  movsd       xmm0,mmword ptr [data]  
00007FF8025BCB03  ret  

Known issues

  • tests for decoding function for float/double is failing on some maschines (currently only confirmed for System/s390x)

Similar projects

License

In order to make the distribution and integration of this project as easy as possible, this software shall stay accessable under the MIT license conditions. However, currently some parts of the KCD parsing logic is linked directly into the libdbcppp library what is in direct conflict with the LGPL license of the KCD XSD specification. Please consider this when using the libdbcppp library. For more related information see #78.

About

C/C++ DBC file parser/tool

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 97.9%
  • C 1.7%
  • CMake 0.4%