Files
canFD_esp32_glm-oh-my-open-/dbc_parser.cpp
2026-02-20 17:50:40 +00:00

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);
}