479 lines
7.3 KiB
Markdown
479 lines
7.3 KiB
Markdown
|
||
# DBC Parser Module Documentation
|
||
|
||
## Overview
|
||
|
||
This module implements a minimal DBC parser intended for use in the **FrameTap** project.
|
||
|
||
Its purpose is to read a DBC file and convert it into an internal representation that can later be used for:
|
||
|
||
- displaying CAN frames and signals
|
||
- building a hierarchical structure for UI
|
||
- integrating with Qt Model/View
|
||
- selecting signals for plotting
|
||
- preparing for runtime CAN/J1939 decoding
|
||
|
||
The implementation intentionally follows the **KISS principle**:
|
||
|
||
- simple
|
||
- readable
|
||
- easy to modify
|
||
- independent from Qt
|
||
|
||
This is **not a full DBC parser**, but a practical foundation that can be extended gradually.
|
||
|
||
---
|
||
|
||
# Architecture
|
||
|
||
The module uses a simple processing pipeline.
|
||
|
||
DBC file
|
||
↓
|
||
DbcParser
|
||
↓
|
||
DbcDatabase
|
||
↓
|
||
DbcTreeBuilder
|
||
↓
|
||
TreeNode hierarchy
|
||
↓
|
||
Future Qt Model/View integration
|
||
|
||
Each component has a clear responsibility.
|
||
|
||
| Component | Responsibility |
|
||
|-----------|---------------|
|
||
| DbcParser | Reads and parses the DBC file |
|
||
| DbcDatabase | Stores parsed frames and signals |
|
||
| DbcTreeBuilder | Converts the database into a tree |
|
||
| TreeNode | Represents hierarchical nodes |
|
||
|
||
This separation allows the parser to remain independent from UI or visualization logic.
|
||
|
||
---
|
||
|
||
# File Structure
|
||
|
||
The module consists of several logical parts.
|
||
|
||
## Data structures
|
||
|
||
Files:
|
||
|
||
signal_info.h
|
||
frame_info.h
|
||
dbc_database.h
|
||
|
||
These files define the internal representation of parsed data.
|
||
|
||
## Tree representation
|
||
|
||
Files:
|
||
|
||
tree_node.h
|
||
tree_node.cpp
|
||
|
||
Defines a simple hierarchical structure that can later be used by UI components.
|
||
|
||
## Parser
|
||
|
||
Files:
|
||
|
||
dbc_parser.h
|
||
dbc_parser.cpp
|
||
|
||
Responsible for reading the DBC file and extracting frame and signal information.
|
||
|
||
## Tree builder
|
||
|
||
Files:
|
||
|
||
dbc_tree_builder.h
|
||
dbc_tree_builder.cpp
|
||
|
||
Converts the parsed database into a tree representation.
|
||
|
||
---
|
||
|
||
# Data Structures
|
||
|
||
## SignalInfo
|
||
|
||
Represents a single signal defined in a DBC file.
|
||
|
||
Fields:
|
||
|
||
- name
|
||
- startBit
|
||
- length
|
||
- isLittleEndian
|
||
- isSigned
|
||
- factor
|
||
- offset
|
||
- minimum
|
||
- maximum
|
||
- unit
|
||
- receivers
|
||
- comment
|
||
|
||
Notes:
|
||
|
||
- receivers may contain multiple ECUs
|
||
- comment is optional
|
||
- factor and offset define physical conversion
|
||
|
||
Physical value is calculated as:
|
||
|
||
physical = raw * factor + offset
|
||
|
||
---
|
||
|
||
## FrameInfo
|
||
|
||
Represents a CAN frame.
|
||
|
||
Fields:
|
||
|
||
- name
|
||
- canId
|
||
- dlc
|
||
- transmitter
|
||
- comment
|
||
- signals
|
||
- pgn
|
||
- hasPgn
|
||
|
||
Notes:
|
||
|
||
- signals is a vector of SignalInfo
|
||
- transmitter is the ECU that sends the frame
|
||
- pgn is derived using simplified J1939 logic
|
||
|
||
---
|
||
|
||
## DbcDatabase
|
||
|
||
Top level container for parsed data.
|
||
|
||
DbcDatabase
|
||
└── vector<FrameInfo>
|
||
|
||
This structure represents the entire DBC file content.
|
||
|
||
---
|
||
|
||
# Tree Representation
|
||
|
||
The module converts the parsed data into a tree.
|
||
|
||
Node types:
|
||
|
||
- Root
|
||
- Frame
|
||
- Signal
|
||
|
||
Example structure:
|
||
|
||
dbc
|
||
├── EngineData
|
||
│ ├── EngineSpeed
|
||
│ ├── OilTemp
|
||
│ └── CoolantTemp
|
||
└── VehicleData
|
||
├── VehicleSpeed
|
||
└── Odometer
|
||
|
||
Each node stores either:
|
||
|
||
- FrameInfo
|
||
- SignalInfo
|
||
|
||
This tree structure is designed to integrate easily with Qt Model/View.
|
||
|
||
---
|
||
|
||
# Parser
|
||
|
||
The parser is implemented in:
|
||
|
||
dbc_parser.h
|
||
dbc_parser.cpp
|
||
|
||
It performs line-based parsing of the DBC file.
|
||
|
||
Supported elements:
|
||
|
||
- BO_
|
||
- SG_
|
||
- CM_
|
||
|
||
---
|
||
|
||
# Supported DBC Syntax
|
||
|
||
## Frame Definition
|
||
|
||
Example:
|
||
|
||
BO_ 256 EngineData: 8 EEC1
|
||
|
||
Parsed values:
|
||
|
||
| Field | Meaning |
|
||
|------|---------|
|
||
| 256 | CAN identifier |
|
||
| EngineData | frame name |
|
||
| 8 | DLC |
|
||
| EEC1 | transmitter ECU |
|
||
|
||
---
|
||
|
||
## Signal Definition
|
||
|
||
Example:
|
||
|
||
SG_ EngineSpeed : 0|16@1+ (0.125,0) [0|8000] "rpm" ECU1,ECU2
|
||
|
||
Parsed values:
|
||
|
||
| Field | Meaning |
|
||
|------|---------|
|
||
| EngineSpeed | signal name |
|
||
| 0 | start bit |
|
||
| 16 | signal length |
|
||
| @1 | little endian |
|
||
| + | unsigned |
|
||
| factor | 0.125 |
|
||
| offset | 0 |
|
||
| minimum | 0 |
|
||
| maximum | 8000 |
|
||
| unit | rpm |
|
||
| receivers | ECU1, ECU2 |
|
||
|
||
---
|
||
|
||
## Comments
|
||
|
||
Frame comment example:
|
||
|
||
CM_ BO_ 256 "Engine data frame";
|
||
|
||
Signal comment example:
|
||
|
||
CM_ SG_ 256 EngineSpeed "Actual engine speed";
|
||
|
||
Stored in:
|
||
|
||
- FrameInfo::comment
|
||
- SignalInfo::comment
|
||
|
||
---
|
||
|
||
# PGN Extraction
|
||
|
||
PGN is derived using simplified J1939 logic.
|
||
|
||
Typical identifier layout:
|
||
|
||
Priority
|
||
Reserved
|
||
Data Page
|
||
PDU Format
|
||
PDU Specific
|
||
Source Address
|
||
|
||
The parser extracts PGN from the 29‑bit CAN identifier.
|
||
|
||
This is only an approximation and not full J1939 validation.
|
||
|
||
---
|
||
|
||
# Example Usage
|
||
|
||
DbcParser parser;
|
||
|
||
DbcDatabase database = parser.ParseFile("example.dbc");
|
||
|
||
DbcTreeBuilder builder;
|
||
|
||
std::unique_ptr<TreeNode> root = builder.Build(database);
|
||
|
||
After this step, the tree can be used by a UI or visualization system.
|
||
|
||
---
|
||
|
||
# Example Tree
|
||
|
||
dbc
|
||
├── EngineData
|
||
│ ├── EngineSpeed
|
||
│ ├── OilTemp
|
||
│ └── CoolantTemp
|
||
└── VehicleData
|
||
├── VehicleSpeed
|
||
└── Odometer
|
||
|
||
---
|
||
|
||
# Limitations
|
||
|
||
The current implementation intentionally does not support many advanced DBC features.
|
||
|
||
Not supported yet:
|
||
|
||
- multiplexed signals
|
||
- BA_ attributes
|
||
- BA_DEF_ definitions
|
||
- VAL_ value tables
|
||
- signal groups
|
||
- complex syntax variations
|
||
|
||
These can be added later if required.
|
||
|
||
---
|
||
|
||
# Design Principles
|
||
|
||
## KISS
|
||
|
||
The parser avoids complex grammar systems or tokenizers in order to keep the code easy to understand and maintain.
|
||
|
||
## Separation of Concerns
|
||
|
||
Parsing, storage, and tree building are separate components.
|
||
|
||
This allows reuse for:
|
||
|
||
- GUI display
|
||
- runtime decoding
|
||
- export
|
||
- filtering
|
||
- testing
|
||
|
||
## Qt Independence
|
||
|
||
The parser itself does not depend on Qt.
|
||
|
||
Qt integration should be implemented through a separate adapter layer.
|
||
|
||
---
|
||
|
||
# Future Development
|
||
|
||
Recommended evolution path.
|
||
|
||
## Stage 1 (current)
|
||
|
||
- BO_
|
||
- SG_
|
||
- CM_
|
||
- transmitter
|
||
- receivers
|
||
- basic PGN extraction
|
||
- tree representation
|
||
|
||
## Stage 2
|
||
|
||
Add:
|
||
|
||
- extended CAN ID detection
|
||
- better PGN extraction
|
||
- parent pointer in TreeNode
|
||
- Qt Model adapter
|
||
|
||
## Stage 3
|
||
|
||
Add support for:
|
||
|
||
- VAL_ value tables
|
||
- BA_ attributes
|
||
- BA_DEF_ definitions
|
||
- extended comments
|
||
|
||
## Stage 4
|
||
|
||
Advanced functionality:
|
||
|
||
- multiplexing
|
||
- runtime signal decoding
|
||
- integration with CAN stream
|
||
- drag‑and‑drop plotting
|
||
|
||
---
|
||
|
||
# Intended Usage in FrameTap
|
||
|
||
This module allows FrameTap to:
|
||
|
||
- load DBC files
|
||
- display frames and signals
|
||
- select signals
|
||
- search signals
|
||
- display metadata
|
||
- prepare runtime decoding
|
||
|
||
Example workflow:
|
||
|
||
Load DBC
|
||
↓
|
||
Browse signals
|
||
↓
|
||
Select signal
|
||
↓
|
||
Decode CAN frames
|
||
↓
|
||
Plot physical values
|
||
|
||
---
|
||
|
||
# Why Abstract Factory Is Not Used
|
||
|
||
An abstract factory is intentionally not used at this stage.
|
||
|
||
The current structure already separates responsibilities clearly:
|
||
|
||
parser → database → tree builder → tree
|
||
|
||
Factories can be introduced later if multiple internal representations become necessary.
|
||
|
||
---
|
||
|
||
# Build Integration
|
||
|
||
The module is independent of any specific build system.
|
||
|
||
It can be integrated using:
|
||
|
||
- CMake
|
||
- qmake
|
||
- Makefile
|
||
|
||
Simply include the source files in your project.
|
||
|
||
---
|
||
|
||
# Summary
|
||
|
||
This module provides a minimal but extensible DBC parser designed for **FrameTap**.
|
||
|
||
Key properties:
|
||
|
||
- simple
|
||
- modular
|
||
- Qt‑independent
|
||
- extendable
|
||
|
||
It converts a DBC file into an internal structure:
|
||
|
||
frame → signals
|
||
|
||
with metadata such as:
|
||
|
||
- transmitter
|
||
- receivers
|
||
- comments
|
||
- basic PGN information
|
||
|
||
This forms the foundation for future CAN signal visualization and decoding.
|