From 62e168905a911f9ec31aabecc390db13c2ff1059 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Sun, 10 Jan 2016 21:54:33 -0500 Subject: [PATCH] Properly hooked up multiplexed signals. They now show up correctly when "Interpret Frames" is selected on the main screen. Fixed some bugs related to the new DBC code. --- canframemodel.cpp | 9 +++-- dbc_classes.h | 3 ++ dbchandler.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++-- dbchandler.h | 3 +- dbcsignaleditor.cpp | 9 +++++ 5 files changed, 115 insertions(+), 8 deletions(-) diff --git a/canframemodel.cpp b/canframemodel.cpp index a7d9127..cba0699 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -202,9 +202,12 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const tempString.append(msg->name + " " + msg->comment + "\r\n"); for (int j = 0; j < msg->msgSignals.length(); j++) { - - tempString.append(dbcHandler->processSignal(thisFrame, msg->msgSignals.at(j))); - tempString.append("\r\n"); + QString sigString = dbcHandler->processSignal(thisFrame, msg->msgSignals.at(j)); + if (sigString.length() > 1) //weeds out signals that don't actually exist in this message (due to multiplexing) + { + tempString.append(sigString); + tempString.append("\r\n"); + } } } } diff --git a/dbc_classes.h b/dbc_classes.h index 0a43bbf..9449c78 100644 --- a/dbc_classes.h +++ b/dbc_classes.h @@ -54,6 +54,8 @@ public: QList attributes; }; +class DBC_MESSAGE; //forward reference so that DBC_SIGNAL can compile before we get to real definition of DBC_MESSAGE + class DBC_SIGNAL { public: @@ -70,6 +72,7 @@ public: double min; double max; DBC_NODE *receiver; + DBC_MESSAGE *parentMessage; QString unitName; QString comment; QList attributes; diff --git a/dbchandler.cpp b/dbchandler.cpp index bf3f2d3..ce2b652 100644 --- a/dbchandler.cpp +++ b/dbchandler.cpp @@ -67,6 +67,10 @@ void DBCHandler::loadDBCFile(QString filename) bool isMultiplexed = false; DBC_SIGNAL sig; + sig.multiplexValue = 0; + sig.isMultiplexed = false; + sig.isMultiplexor = false; + qDebug() << "Found a SG line"; regex.setPattern("^SG\\_ *(\\w+) *M *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); @@ -93,6 +97,8 @@ void DBCHandler::loadDBCFile(QString filename) { regex.setPattern("^SG\\_ *(\\w+) *: *(\\d+)\\|(\\d+)@(\\d+)([\\+|\\-]) \\(([0-9.+\\-eE]+),([0-9.+\\-eE]+)\\) \\[([0-9.+\\-eE]+)\\|([0-9.+\\-eE]+)\\] \\\"(.*)\\\" (.*)"); match = regex.match(line); + sig.isMultiplexed = false; + sig.isMultiplexor = false; } } @@ -149,6 +155,7 @@ void DBCHandler::loadDBCFile(QString filename) sig.receiver = findNodeByName(tmp); } else sig.receiver = findNodeByName(match.captured(11 + offset)); + sig.parentMessage = currentMessage; currentMessage->msgSignals.append(sig); if (isMultiplexor) currentMessage->multiplexorSignal = ¤tMessage->msgSignals.last(); } @@ -606,6 +613,18 @@ QString DBCHandler::processSignal(const CANFrame &frame, const DBC_SIGNAL &sig) return buildString; } + //if this is a multiplexed signal then we have to see if it is even found in the current message + if (sig.isMultiplexed) + { + if (sig.parentMessage->multiplexorSignal != NULL) + { + int val; + if (!processSignalInt(frame, *sig.parentMessage->multiplexorSignal, val)) return ""; + if (val != sig.multiplexValue) return ""; //signal not found in this message + } + else return ""; + } + if (sig.valType == SIGNED_INT) isSigned = true; if (sig.valType == SIGNED_INT || sig.valType == UNSIGNED_INT) { @@ -653,14 +672,28 @@ QString DBCHandler::processSignal(const CANFrame &frame, const DBC_SIGNAL &sig) //Works quite a bit like the above version but this one is cut down and only will return int32_t which is perfect for //uses like calculating a multiplexor value or if you know you are going to get an integer returned //from a signal and you want to use it as-is and not have to convert back from a string. Use with caution though -//as this basically assumes the signal is an integer. If it isn't you get -1 back. -int32_t processSignalInt(const CANFrame &frame, const DBC_SIGNAL &sig) +//as this basically assumes the signal is an integer. +//The call syntax is different from the more generic processSignal. Instead of returning the value we return +//true or false to show whether the function succeeded. The variable to fill out is passed by reference. +bool DBCHandler::processSignalInt(const CANFrame &frame, const DBC_SIGNAL &sig, int32_t &outValue) { int32_t result = 0; bool isSigned = false; if (sig.valType == STRING || sig.valType == SP_FLOAT || sig.valType == DP_FLOAT) { - return -1; //I warned you! + return false; + } + + //if this is a multiplexed signal then we have to see if it is even found in the current message + if (sig.isMultiplexed) + { + if (sig.parentMessage->multiplexorSignal != NULL) + { + int val; + if (!processSignalInt(frame, *sig.parentMessage->multiplexorSignal, val)) return false; + if (val != sig.multiplexValue) return false; //signal not found in this message + } + else return false; } if (sig.valType == SIGNED_INT) isSigned = true; @@ -669,7 +702,65 @@ int32_t processSignalInt(const CANFrame &frame, const DBC_SIGNAL &sig) double endResult = ((double)result * sig.factor) + sig.bias; result = (int32_t)endResult; - return result; + outValue = result; + return true; +} + + +//Another cut down version that will only return double precision data. This can be used on any of the types +//except STRING. Useful for when you know you'll need floating point data and don't want to incur a conversion +//back and forth to double or float. Such a use is the graphing window. +//Similar syntax to processSignalInt but with double instead. +bool DBCHandler::processSignalDouble(const CANFrame &frame, const DBC_SIGNAL &sig, double &outValue) +{ + int64_t result = 0; + bool isSigned = false; + double endResult; + + if (sig.valType == STRING) + { + return false; + } + + //if this is a multiplexed signal then we have to see if it is even found in the current message + if (sig.isMultiplexed) + { + if (sig.parentMessage->multiplexorSignal != NULL) + { + int val; + if (!processSignalInt(frame, *sig.parentMessage->multiplexorSignal, val)) return false; + if (val != sig.multiplexValue) return false; //signal not found in this message + } + else return false; + } + + if (sig.valType == SIGNED_INT) isSigned = true; + if (sig.valType == SIGNED_INT || sig.valType == UNSIGNED_INT) + { + result = Utility::processIntegerSignal(frame.data, sig.startBit, sig.signalSize, sig.intelByteOrder, isSigned); + endResult = ((double)result * sig.factor) + sig.bias; + result = (int64_t)endResult; + } + else if (sig.valType == SP_FLOAT) + { + //The theory here is that we force the integer signal code to treat this as + //a 32 bit unsigned integer. This integer is then cast into a float in such a way + //that the bytes that make up the integer are instead treated as having made up + //a 32 bit single precision float. That's evil incarnate but it is very fast and small + //in terms of new code. + result = Utility::processIntegerSignal(frame.data, sig.startBit, 32, false, false); + endResult = (*((float *)(&result)) * sig.factor) + sig.bias; + } + else //double precision float + { + //like the above, this is rotten and evil and wrong in so many ways. Force + //calculation of a 64 bit integer and then cast it into a double. + result = Utility::processIntegerSignal(frame.data, 0, 64, false, false); + endResult = (*((double *)(&result)) * sig.factor) + sig.bias; + } + + outValue = endResult; + return true; } //given a byte it will reverse the bit order in that byte diff --git a/dbchandler.h b/dbchandler.h index 8bb6f07..291ac8c 100644 --- a/dbchandler.h +++ b/dbchandler.h @@ -19,7 +19,8 @@ public: void saveDBCFile(QString); void listDebugging(); QString processSignal(const CANFrame &frame, const DBC_SIGNAL &sig); - int32_t processSignalInt(const CANFrame &frame, const DBC_SIGNAL &sig); + bool processSignalInt(const CANFrame &frame, const DBC_SIGNAL &sig, int32_t &outValue); + bool processSignalDouble(const CANFrame &frame, const DBC_SIGNAL &sig, double &outValue); DBC_NODE *findNodeByName(QString name); DBC_NODE *findNodeByIdx(int idx); diff --git a/dbcsignaleditor.cpp b/dbcsignaleditor.cpp index 1c0b098..6b51190 100644 --- a/dbcsignaleditor.cpp +++ b/dbcsignaleditor.cpp @@ -181,6 +181,8 @@ DBCSignalEditor::DBCSignalEditor(DBCHandler *handler, QWidget *parent) : { currentSignal->isMultiplexed = true; currentSignal->isMultiplexor = false; + //if the set multiplexor for the message was this signal then clear it + if (dbcMessage->multiplexorSignal == currentSignal) dbcMessage->multiplexorSignal = NULL; } }); @@ -189,8 +191,12 @@ DBCSignalEditor::DBCSignalEditor(DBCHandler *handler, QWidget *parent) : { if (state) //signal is now set as a multiplexed signal { + //don't allow this signal to be a multiplexor if there is already one for this message. + //if (dbcMessage->multiplexorSignal != currentSignal && dbcMessage->multiplexorSignal != NULL) return; //I spoke too soon above... currentSignal->isMultiplexed = false; currentSignal->isMultiplexor = true; + //we just set that this is the multiplexor so update the message to show that as well. + dbcMessage->multiplexorSignal = currentSignal; } }); @@ -201,6 +207,7 @@ DBCSignalEditor::DBCSignalEditor(DBCHandler *handler, QWidget *parent) : { currentSignal->isMultiplexed = false; currentSignal->isMultiplexor = false; + if (dbcMessage->multiplexorSignal == currentSignal) dbcMessage->multiplexorSignal = NULL; } }); } @@ -326,6 +333,7 @@ void DBCSignalEditor::addNewSignal() newSig.isMultiplexed = false; newSig.isMultiplexor = false; newSig.multiplexValue = 0; + newSig.parentMessage = dbcMessage; ui->signalsList->addItem(newName); dbcMessage->msgSignals.append(newSig); if (dbcMessage->msgSignals.count() == 1) clickSignalList(0); @@ -406,6 +414,7 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig) ui->rbMultiplexed->setChecked(sig->isMultiplexed); ui->rbMultiplexor->setChecked(sig->isMultiplexor); ui->rbNotMulti->setChecked( !(sig->isMultiplexor | sig->isMultiplexed) ); + qDebug() << sig->isMultiplexor << "*" << sig->isMultiplexed; memset(bitpattern, 0, 8); //clear it out first.