241 lines
6.2 KiB
C++
241 lines
6.2 KiB
C++
// dbc_parser.cpp - DBC Parser Implementation
|
|
|
|
#include "dbc_parser.h"
|
|
|
|
DbcDatabase dbcDB;
|
|
|
|
bool parseDBC(const char* content) {
|
|
clearDBC();
|
|
|
|
if (!content || strlen(content) == 0) {
|
|
return false;
|
|
}
|
|
|
|
// Simple DBC parser - looks for BO_ and SG_ lines
|
|
const char* ptr = content;
|
|
DbcMessage* currentMsg = nullptr;
|
|
|
|
while (*ptr) {
|
|
// Parse message definition: BO_ 123 MessageName: 8 Vector__XXX
|
|
if (strncmp(ptr, "BO_ ", 4) == 0) {
|
|
if (dbcDB.messageCount >= MAX_DBC_MESSAGES) break;
|
|
|
|
ptr += 4;
|
|
char* end;
|
|
uint32_t msgId = strtoul(ptr, &end, 10);
|
|
if (ptr == end) continue;
|
|
ptr = end;
|
|
|
|
// Skip whitespace
|
|
while (*ptr && isspace(*ptr)) ptr++;
|
|
|
|
// Read message name
|
|
char name[32];
|
|
int i = 0;
|
|
while (*ptr && *ptr != ':' && i < 31) {
|
|
name[i++] = *ptr++;
|
|
}
|
|
name[i] = '\0';
|
|
|
|
// Skip to DLC
|
|
if (*ptr == ':') ptr++;
|
|
while (*ptr && isspace(*ptr)) ptr++;
|
|
|
|
uint8_t dlc = (uint8_t)strtoul(ptr, &end, 10);
|
|
|
|
// Store message
|
|
DbcMessage* msg = &dbcDB.messages[dbcDB.messageCount++];
|
|
msg->id = msgId;
|
|
strncpy(msg->name, name, 31);
|
|
msg->dlc = dlc;
|
|
msg->signalCount = 0;
|
|
msg->signalStartIndex = dbcDB.signalCount;
|
|
currentMsg = msg;
|
|
}
|
|
// Parse signal definition: SG_ SignalName : 0|16@1+ (0.1,0) [0|6553.5] "V" Vector__XXX
|
|
else if (strncmp(ptr, " SG_ ", 5) == 0 && currentMsg) {
|
|
if (dbcDB.signalCount >= MAX_DBC_SIGNALS) break;
|
|
|
|
ptr += 5;
|
|
|
|
// Read signal name
|
|
char name[32];
|
|
int i = 0;
|
|
while (*ptr && *ptr != ':' && i < 31) {
|
|
name[i++] = *ptr++;
|
|
}
|
|
name[i] = '\0';
|
|
|
|
// Skip to startBit|length
|
|
if (*ptr == ':') ptr++;
|
|
while (*ptr && isspace(*ptr)) ptr++;
|
|
|
|
// Parse startBit|length@endian+signed
|
|
char* end;
|
|
uint32_t startBit = strtoul(ptr, &end, 10);
|
|
if (*end != '|') continue;
|
|
ptr = end + 1;
|
|
|
|
uint32_t length = strtoul(ptr, &end, 10);
|
|
if (*end != '@') continue;
|
|
ptr = end + 1;
|
|
|
|
bool isLittleEndian = (*ptr == '1');
|
|
ptr++;
|
|
|
|
bool isSigned = (*ptr == '-');
|
|
ptr++;
|
|
|
|
// Skip to factor,offset
|
|
while (*ptr && *ptr != '(') ptr++;
|
|
if (*ptr == '(') ptr++;
|
|
|
|
float factor = strtof(ptr, &end);
|
|
if (*end != ',') continue;
|
|
ptr = end + 1;
|
|
|
|
float offset = strtof(ptr, &end);
|
|
|
|
// Store signal
|
|
DbcSignal* sig = &dbcDB.signals[dbcDB.signalCount++];
|
|
strncpy(sig->name, name, 31);
|
|
sig->startBit = startBit;
|
|
sig->length = length;
|
|
sig->isLittleEndian = isLittleEndian;
|
|
sig->isSigned = isSigned;
|
|
sig->factor = factor;
|
|
sig->offset = offset;
|
|
sig->min = 0;
|
|
sig->max = 0;
|
|
sig->unit[0] = '\0';
|
|
sig->messageId = currentMsg->id;
|
|
|
|
currentMsg->signalCount++;
|
|
}
|
|
|
|
// Move to next line
|
|
while (*ptr && *ptr != '\n') ptr++;
|
|
if (*ptr == '\n') ptr++;
|
|
}
|
|
|
|
dbcDB.loaded = (dbcDB.messageCount > 0);
|
|
return dbcDB.loaded;
|
|
}
|
|
|
|
DbcMessage* getMessageById(uint32_t id) {
|
|
for (uint16_t i = 0; i < dbcDB.messageCount; i++) {
|
|
if (dbcDB.messages[i].id == id) {
|
|
return &dbcDB.messages[i];
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
DbcSignal* getSignalByName(DbcMessage* msg, const char* name) {
|
|
if (!msg) return nullptr;
|
|
|
|
for (uint16_t i = 0; i < msg->signalCount; i++) {
|
|
DbcSignal* sig = &dbcDB.signals[msg->signalStartIndex + i];
|
|
if (strcmp(sig->name, name) == 0) {
|
|
return sig;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
uint16_t getSignalsForMessage(uint32_t msgId, DbcSignal** signals) {
|
|
DbcMessage* msg = getMessageById(msgId);
|
|
if (!msg) return 0;
|
|
|
|
*signals = &dbcDB.signals[msg->signalStartIndex];
|
|
return msg->signalCount;
|
|
}
|
|
|
|
float extractSignalValue(const uint8_t* data, const DbcSignal* signal) {
|
|
if (!data || !signal) return 0.0f;
|
|
|
|
uint64_t rawValue = 0;
|
|
uint32_t startBit = signal->startBit;
|
|
uint32_t length = signal->length;
|
|
|
|
if (signal->isLittleEndian) {
|
|
// Little endian: startBit is from LSB
|
|
uint32_t byteOffset = startBit / 8;
|
|
uint32_t bitOffset = startBit % 8;
|
|
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
uint32_t bitPos = bitOffset + i;
|
|
uint32_t bytePos = byteOffset + (bitPos / 8);
|
|
uint32_t bitInByte = bitPos % 8;
|
|
|
|
if (bytePos < 64) {
|
|
bool bitSet = (data[bytePos] >> bitInByte) & 0x01;
|
|
if (bitSet) {
|
|
rawValue |= (1ULL << i);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Big endian: startBit is from MSB
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
uint32_t bitPos = startBit - i;
|
|
uint32_t bytePos = bitPos / 8;
|
|
uint32_t bitInByte = 7 - (bitPos % 8);
|
|
|
|
if (bytePos < 64) {
|
|
bool bitSet = (data[bytePos] >> bitInByte) & 0x01;
|
|
if (bitSet) {
|
|
rawValue |= (1ULL << (length - 1 - i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle signed values
|
|
if (signal->isSigned) {
|
|
if (rawValue & (1ULL << (length - 1))) {
|
|
// Negative number - sign extend
|
|
rawValue |= (~0ULL) << length;
|
|
}
|
|
}
|
|
|
|
// Apply factor and offset
|
|
float physicalValue = ((float)(int64_t)rawValue) * signal->factor + signal->offset;
|
|
|
|
return physicalValue;
|
|
}
|
|
|
|
void clearDBC() {
|
|
dbcDB.messageCount = 0;
|
|
dbcDB.signalCount = 0;
|
|
dbcDB.loaded = false;
|
|
}
|
|
|
|
bool loadDBCFromSD(const char* filename) {
|
|
// TODO: Implement SD card file loading
|
|
// This would read the file and call parseDBC()
|
|
return false;
|
|
}
|
|
|
|
void getDBCSummary(char* buffer, size_t bufferSize) {
|
|
if (!dbcDB.loaded) {
|
|
strncpy(buffer, "{\"loaded\":false}", bufferSize);
|
|
return;
|
|
}
|
|
|
|
int pos = snprintf(buffer, bufferSize, "{\"loaded\":true,\"messages\":[%d],\"signals\":[%d],\"msgs\":[",
|
|
dbcDB.messageCount, dbcDB.signalCount);
|
|
|
|
for (uint16_t i = 0; i < dbcDB.messageCount && pos < (int)bufferSize - 100; i++) {
|
|
if (i > 0) {
|
|
pos += snprintf(buffer + pos, bufferSize - pos, ",");
|
|
}
|
|
DbcMessage* msg = &dbcDB.messages[i];
|
|
pos += snprintf(buffer + pos, bufferSize - pos,
|
|
"{\"id\":%u,\"name\":\"%s\",\"dlc\":%d,\"sigCount\":%d}",
|
|
msg->id, msg->name, msg->dlc, msg->signalCount);
|
|
}
|
|
|
|
strncat(buffer, "]}", bufferSize - pos - 1);
|
|
}
|