Fixes to make extended multiplexing code work properly, implementation

of nested multiplexing in main screen for interpretation.

Overall, it's ugly but mostly functional at this point.
This commit is contained in:
Collin Kidder
2021-02-25 21:24:21 -05:00
parent bcfaffbe5d
commit af0194c5a5
7 changed files with 150 additions and 44 deletions
+11 -5
View File
@@ -511,17 +511,23 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
{ {
QString sigString; QString sigString;
DBC_SIGNAL* sig = msg->sigHandler->findSignalByIdx(j); DBC_SIGNAL* sig = msg->sigHandler->findSignalByIdx(j);
if (sig->processAsText(thisFrame, sigString))
if ( (sig->multiplexParent == nullptr) && sig->processAsText(thisFrame, sigString))
{ {
tempString.append(sigString); tempString.append(sigString);
tempString.append("\n"); tempString.append("\n");
} if (sig->isMultiplexor)
else if (sig->isMultiplexed && overwriteDups) //wasn't in this exact frame but is in the message. Use cached value
{ {
tempString.append(sig->makePrettyOutput(sig->cachedValue.toDouble(), sig->cachedValue.toLongLong())); qDebug() << "Multiplexor. Diving into the tree";
tempString.append("\n"); tempString.append(sig->processSignalTree(thisFrame));
} }
} }
//else if (sig->isMultiplexed && overwriteDups) //wasn't in this exact frame but is in the message. Use cached value
//{
// tempString.append(sig->makePrettyOutput(sig->cachedValue.toDouble(), sig->cachedValue.toLongLong()));
// tempString.append("\n");
//}
}
} }
} }
return tempString; return tempString;
+64 -34
View File
@@ -31,6 +31,65 @@ DBC_SIGNAL::DBC_SIGNAL()
valType = DBC_SIG_VAL_TYPE::UNSIGNED_INT; valType = DBC_SIG_VAL_TYPE::UNSIGNED_INT;
} }
bool DBC_SIGNAL::isSignalInMessage(const CANFrame &frame)
{
if (isMultiplexor && !isMultiplexed) return true; //the root multiplexor is always in the message.
if (isMultiplexed)
{
if (parentMessage->multiplexorSignal != nullptr)
{
return _sigInMsgPriv(frame, parentMessage->multiplexorSignal);
}
else return false;
}
else return true;
}
bool DBC_SIGNAL::_sigInMsgPriv(const CANFrame &frame, DBC_SIGNAL *multiplexor)
{
int val;
if (!multiplexor->processAsInt(frame, val)) return false;
foreach (DBC_SIGNAL *child, multiplexedChildren)
{
if ((val >= child->multiplexLowValue) && (val <= child->multiplexHighValue))
{
if (child->isMultiplexor) return _sigInMsgPriv(frame, child); //recurse down a level and keep searching
if (child == this) return true; //if we are that child then we matched!
}
}
return false; //signal not found in this message
}
//Take all the children of this signal and see if they exist in the message. Can be called recursively to descend the dependency tree
QString DBC_SIGNAL::processSignalTree(const CANFrame &frame)
{
QString build;
int val;
if (!this->processAsInt(frame, val)) return build;
qDebug() << val;
foreach (DBC_SIGNAL *sig, multiplexedChildren)
{
if ( (val >= sig->multiplexLowValue) && (val <= sig->multiplexHighValue) )
{
qDebug() << "Found match for multiplex value range - " << sig->name;
QString sigString;
if (sig->processAsText(frame, sigString))
{
qDebug() << "Returned value: " << sigString;
build.append(sigString);
build.append("\n");
if (sig->isMultiplexor)
{
qDebug() << "Spelunkin!";
build.append(sig->processSignalTree(frame));
}
}
}
}
return build;
}
/* /*
The way that the DBC file format works is kind of weird... For intel format signals you count up The way that the DBC file format works is kind of weird... For intel format signals you count up
from the start bit to the end bit which is (startbit + signallength - 1). At each point from the start bit to the end bit which is (startbit + signallength - 1). At each point
@@ -67,6 +126,8 @@ bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString, bool o
bool isInteger = false; bool isInteger = false;
double endResult; double endResult;
//if (!isSignalInMessage(frame)) return false;
if (valType == STRING) if (valType == STRING)
{ {
QString buildString; QString buildString;
@@ -78,18 +139,6 @@ bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString, bool o
return true; return true;
} }
//if this is a multiplexed signal then we have to see if it is even found in the current message
if (isMultiplexed)
{
if (parentMessage->multiplexorSignal != nullptr)
{
int val;
if (!parentMessage->multiplexorSignal->processAsInt(frame, val)) return false;
if (val != multiplexLowValue) return false; //signal not found in this message
}
else return false;
}
if (valType == SIGNED_INT) isSigned = true; if (valType == SIGNED_INT) isSigned = true;
if (valType == SIGNED_INT || valType == UNSIGNED_INT) if (valType == SIGNED_INT || valType == UNSIGNED_INT)
{ {
@@ -164,22 +213,13 @@ bool DBC_SIGNAL::processAsInt(const CANFrame &frame, int32_t &outValue)
{ {
int32_t result = 0; int32_t result = 0;
bool isSigned = false; bool isSigned = false;
if (valType == STRING || valType == SP_FLOAT || valType == DP_FLOAT) if (valType == STRING || valType == SP_FLOAT || valType == DP_FLOAT)
{ {
return false; return false;
} }
//if this is a multiplexed signal then we have to see if it is even found in the current message //if (!isSignalInMessage(frame)) return false;
if (isMultiplexed)
{
if (parentMessage->multiplexorSignal != nullptr)
{
int val;
if (!parentMessage->multiplexorSignal->processAsInt(frame, val)) return false;
if (val != multiplexLowValue) return false; //signal not found in this message
}
else return false;
}
if (valType == SIGNED_INT) isSigned = true; if (valType == SIGNED_INT) isSigned = true;
if ( static_cast<int>(frame.payload().length() * 8) < (startBit + signalSize) ) if ( static_cast<int>(frame.payload().length() * 8) < (startBit + signalSize) )
@@ -212,17 +252,7 @@ bool DBC_SIGNAL::processAsDouble(const CANFrame &frame, double &outValue)
return false; return false;
} }
//if this is a multiplexed signal then we have to see if it is even found in the current message //if (!isSignalInMessage(frame)) return false;
if (isMultiplexed)
{
if (parentMessage->multiplexorSignal != nullptr)
{
int val;
if (!parentMessage->multiplexorSignal->processAsInt(frame, val)) return false;
if (val != multiplexLowValue) return false; //signal not found in this message
}
else return false;
}
if (valType == SIGNED_INT) isSigned = true; if (valType == SIGNED_INT) isSigned = true;
if (valType == SIGNED_INT || valType == UNSIGNED_INT) if (valType == SIGNED_INT || valType == UNSIGNED_INT)
+4
View File
@@ -116,6 +116,7 @@ public: //TODO: this is sloppy. It shouldn't all be public!
bool processAsInt(const CANFrame &frame, int32_t &outValue); bool processAsInt(const CANFrame &frame, int32_t &outValue);
bool processAsDouble(const CANFrame &frame, double &outValue); bool processAsDouble(const CANFrame &frame, double &outValue);
QString makePrettyOutput(double floatVal, int64_t intVal, bool outputName = true, bool isInteger = false); QString makePrettyOutput(double floatVal, int64_t intVal, bool outputName = true, bool isInteger = false);
QString processSignalTree(const CANFrame &frame);
DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name); DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name);
DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx); DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx);
@@ -123,6 +124,9 @@ public: //TODO: this is sloppy. It shouldn't all be public!
{ {
return (l.name.toLower() < r.name.toLower()); return (l.name.toLower() < r.name.toLower());
} }
private:
bool isSignalInMessage(const CANFrame &frame);
bool _sigInMsgPriv(const CANFrame &frame, DBC_SIGNAL *multiplexor);
}; };
class DBCSignalHandler; //forward declaration to keep from having to include dbchandler.h in this file and thus create a loop class DBCSignalHandler; //forward declaration to keep from having to include dbchandler.h in this file and thus create a loop
+35 -1
View File
@@ -1250,6 +1250,7 @@ bool DBCFile::saveFile(QString fileName)
QFile *outFile = new QFile(fileName); QFile *outFile = new QFile(fileName);
QString nodesOutput, msgOutput, commentsOutput, valuesOutput; QString nodesOutput, msgOutput, commentsOutput, valuesOutput;
QString defaultsOutput, attrValOutput; QString defaultsOutput, attrValOutput;
bool hasExtendedMultiplexing = false;
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text)) if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
{ {
@@ -1380,11 +1381,18 @@ bool DBCFile::saveFile(QString fileName)
msgOutput.append(" SG_ " + sig->name); msgOutput.append(" SG_ " + sig->name);
if (sig->isMultiplexor) msgOutput.append(" M");
if (sig->isMultiplexed) if (sig->isMultiplexed)
{ {
msgOutput.append(" m" + QString::number(sig->multiplexLowValue)); msgOutput.append(" m" + QString::number(sig->multiplexLowValue));
} }
if (sig->isMultiplexor)
{
if (!sig->isMultiplexed) msgOutput.append(" ");
msgOutput.append("M");
}
//check for the two telltale signs that we've got extended multiplexing going on.
if (sig->isMultiplexed && sig->isMultiplexor) hasExtendedMultiplexing = true;
if (sig->multiplexLowValue != sig->multiplexHighValue) hasExtendedMultiplexing = true;
msgOutput.append(" : " + QString::number(sig->startBit) + "|" + QString::number(sig->signalSize) + "@"); msgOutput.append(" : " + QString::number(sig->startBit) + "|" + QString::number(sig->signalSize) + "@");
@@ -1521,6 +1529,32 @@ bool DBCFile::saveFile(QString fileName)
} }
} }
//extended multiplexing uses SG_MUL_VAL_ to specify the relationships. If a signal is marked
//as multiplexed then output a record for it. That's the most complete option. We've already
//given the single value multiplex above for backward compatibility with things that don't support extended mode
if (hasExtendedMultiplexing)
{
for (int x = 0; x < messageHandler->getCount(); x++)
{
DBC_MESSAGE *msg = messageHandler->findMsgByIdx(x);
for (int s = 0; s < msg->sigHandler->getCount(); s++)
{
DBC_SIGNAL *sig = msg->sigHandler->findSignalByIdx(s);
if (sig->isMultiplexed)
{
msgOutput.append("SG_MUL_VAL_ " + QString::number(msg->ID) + " ");
msgOutput.append(sig->name + " " + sig->parentMessage->name + " ");
msgOutput.append(QString::number(sig->multiplexLowValue) + "-" + QString::number(sig->multiplexHighValue) + ";");
msgOutput.append("\n");
outFile->write(msgOutput.toUtf8());
msgOutput.clear(); //got to reset it after writing
}
}
}
}
//now write out all of the accumulated comments and value tables from above //now write out all of the accumulated comments and value tables from above
outFile->write(attrValOutput.toUtf8()); outFile->write(attrValOutput.toUtf8());
outFile->write(defaultsOutput.toUtf8()); outFile->write(defaultsOutput.toUtf8());
+21
View File
@@ -450,6 +450,27 @@ void DBCMainEditor::updatedSignal(DBC_SIGNAL *sig)
QTreeWidgetItem *item = signalToItem.value(sig); QTreeWidgetItem *item = signalToItem.value(sig);
QString sigInfo = createSignalText(sig); QString sigInfo = createSignalText(sig);
item->setText(0, sigInfo); item->setText(0, sigInfo);
if (sig->isMultiplexed)
{
if (item->parent()->data(0, Qt::UserRole).toInt() == 3) //if our parent is another signal
{
QString nameString = item->parent()->text(0);
if (nameString.contains("(")) nameString = nameString.split(" ")[1];
else nameString = nameString.split(" ")[0];
DBC_SIGNAL *oldParent = sig->parentMessage->sigHandler->findSignalByName(nameString);
if (oldParent && (oldParent != sig->multiplexParent))
{
qDebug() << "You changed the signal's parent";
QTreeWidgetItem *newParent = nullptr;
newParent = signalToItem.value(sig->multiplexParent);
QTreeWidgetItem *prevParent = signalToItem.value(oldParent);
prevParent->removeChild(item);
newParent->addChild(item);
ui->treeDBC->setCurrentItem(item);
ui->treeDBC->sortItems(0, Qt::AscendingOrder); //resort because we just moved an item
}
}
}
} }
else qDebug() << "That signal doesn't exist. That's a bug dude."; else qDebug() << "That signal doesn't exist. That's a bug dude.";
} }
+12 -2
View File
@@ -19,6 +19,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
dbcHandler = DBCHandler::getReference(); dbcHandler = DBCHandler::getReference();
dbcMessage = nullptr; dbcMessage = nullptr;
currentSignal = nullptr; currentSignal = nullptr;
inhibitMsgProc = false;
QStringList headers2; QStringList headers2;
headers2 << "Value" << "Text"; headers2 << "Value" << "Text";
@@ -267,9 +268,12 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
dbcFile->setDirtyFlag(); dbcFile->setDirtyFlag();
}); });
connect(ui->cbMultiplexParent, &QComboBox::currentTextChanged, connect(ui->cbMultiplexParent, &QComboBox::textActivated,
[=]() [=]()
{ {
if (currentSignal == nullptr) return;
if (inhibitMsgProc) return;
//qDebug() << "Curr text: :" << ui->cbMultiplexParent->currentText();
//try to look up the signal that we're set to now, remove this signal from existing children list //try to look up the signal that we're set to now, remove this signal from existing children list
//add it to this one, update this signal's parent multiplexor //add it to this one, update this signal's parent multiplexor
DBC_SIGNAL *newSig = dbcMessage->sigHandler->findSignalByName(ui->cbMultiplexParent->currentText()); DBC_SIGNAL *newSig = dbcMessage->sigHandler->findSignalByName(ui->cbMultiplexParent->currentText());
@@ -280,6 +284,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
currentSignal->multiplexParent = newSig; currentSignal->multiplexParent = newSig;
newSig->multiplexedChildren.append(currentSignal); newSig->multiplexedChildren.append(currentSignal);
dbcFile->setDirtyFlag(); dbcFile->setDirtyFlag();
emit updatedTreeInfo(currentSignal);
} }
}); });
@@ -431,6 +436,8 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
{ {
unsigned char bitpattern[8]; unsigned char bitpattern[8];
inhibitMsgProc = true;
if (sig == nullptr) { if (sig == nullptr) {
ui->groupBox->setEnabled(false); ui->groupBox->setEnabled(false);
ui->txtName->setText(""); ui->txtName->setText("");
@@ -451,6 +458,7 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
ui->bitfield->updateData(bitpattern, true); ui->bitfield->updateData(bitpattern, true);
ui->comboReceiver->setCurrentIndex(0); ui->comboReceiver->setCurrentIndex(0);
ui->comboType->setCurrentIndex(0); ui->comboType->setCurrentIndex(0);
inhibitMsgProc = false;
return; return;
} }
@@ -489,7 +497,7 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
for (int i = 0; i < numSigs; i++) for (int i = 0; i < numSigs; i++)
{ {
DBC_SIGNAL *sig_iter = dbcMessage->sigHandler->findSignalByIdx(i); DBC_SIGNAL *sig_iter = dbcMessage->sigHandler->findSignalByIdx(i);
if (sig_iter->isMultiplexor && (sig_iter != sig)) if (sig_iter && sig_iter->isMultiplexor && (sig_iter != sig))
{ {
ui->cbMultiplexParent->addItem(sig_iter->name); ui->cbMultiplexParent->addItem(sig_iter->name);
if (sig->multiplexParent == sig_iter) ui->cbMultiplexParent->setCurrentIndex(ui->cbMultiplexParent->count() - 1); if (sig->multiplexParent == sig_iter) ui->cbMultiplexParent->setCurrentIndex(ui->cbMultiplexParent->count() - 1);
@@ -565,6 +573,8 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
break; break;
} }
} }
inhibitMsgProc = false;
} }
/* fillValueTable also handles "enabled" state */ /* fillValueTable also handles "enabled" state */
+1
View File
@@ -38,6 +38,7 @@ private:
DBC_SIGNAL *currentSignal; DBC_SIGNAL *currentSignal;
DBCFile *dbcFile; DBCFile *dbcFile;
bool inhibitCellChanged; bool inhibitCellChanged;
bool inhibitMsgProc;
void fillSignalForm(DBC_SIGNAL *sig); void fillSignalForm(DBC_SIGNAL *sig);
void fillValueTable(DBC_SIGNAL *sig); void fillValueTable(DBC_SIGNAL *sig);