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