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:
+11
-5
@@ -511,17 +511,23 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QString sigString;
|
||||
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("\n");
|
||||
}
|
||||
else if (sig->isMultiplexed && overwriteDups) //wasn't in this exact frame but is in the message. Use cached value
|
||||
if (sig->isMultiplexor)
|
||||
{
|
||||
tempString.append(sig->makePrettyOutput(sig->cachedValue.toDouble(), sig->cachedValue.toLongLong()));
|
||||
tempString.append("\n");
|
||||
qDebug() << "Multiplexor. Diving into the tree";
|
||||
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;
|
||||
|
||||
+64
-34
@@ -31,6 +31,65 @@ DBC_SIGNAL::DBC_SIGNAL()
|
||||
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
|
||||
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;
|
||||
double endResult;
|
||||
|
||||
//if (!isSignalInMessage(frame)) return false;
|
||||
|
||||
if (valType == STRING)
|
||||
{
|
||||
QString buildString;
|
||||
@@ -78,18 +139,6 @@ bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString, bool o
|
||||
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 || valType == UNSIGNED_INT)
|
||||
{
|
||||
@@ -164,22 +213,13 @@ bool DBC_SIGNAL::processAsInt(const CANFrame &frame, int32_t &outValue)
|
||||
{
|
||||
int32_t result = 0;
|
||||
bool isSigned = false;
|
||||
|
||||
if (valType == STRING || valType == SP_FLOAT || valType == DP_FLOAT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//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 (!isSignalInMessage(frame)) return false;
|
||||
|
||||
if (valType == SIGNED_INT) isSigned = true;
|
||||
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;
|
||||
}
|
||||
|
||||
//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 (!isSignalInMessage(frame)) return false;
|
||||
|
||||
if (valType == SIGNED_INT) isSigned = true;
|
||||
if (valType == SIGNED_INT || valType == UNSIGNED_INT)
|
||||
|
||||
@@ -116,6 +116,7 @@ public: //TODO: this is sloppy. It shouldn't all be public!
|
||||
bool processAsInt(const CANFrame &frame, int32_t &outValue);
|
||||
bool processAsDouble(const CANFrame &frame, double &outValue);
|
||||
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 *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());
|
||||
}
|
||||
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
|
||||
|
||||
+35
-1
@@ -1250,6 +1250,7 @@ bool DBCFile::saveFile(QString fileName)
|
||||
QFile *outFile = new QFile(fileName);
|
||||
QString nodesOutput, msgOutput, commentsOutput, valuesOutput;
|
||||
QString defaultsOutput, attrValOutput;
|
||||
bool hasExtendedMultiplexing = false;
|
||||
|
||||
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
@@ -1380,11 +1381,18 @@ bool DBCFile::saveFile(QString fileName)
|
||||
|
||||
msgOutput.append(" SG_ " + sig->name);
|
||||
|
||||
if (sig->isMultiplexor) msgOutput.append(" M");
|
||||
if (sig->isMultiplexed)
|
||||
{
|
||||
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) + "@");
|
||||
|
||||
@@ -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
|
||||
outFile->write(attrValOutput.toUtf8());
|
||||
outFile->write(defaultsOutput.toUtf8());
|
||||
|
||||
@@ -450,6 +450,27 @@ void DBCMainEditor::updatedSignal(DBC_SIGNAL *sig)
|
||||
QTreeWidgetItem *item = signalToItem.value(sig);
|
||||
QString sigInfo = createSignalText(sig);
|
||||
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.";
|
||||
}
|
||||
|
||||
+12
-2
@@ -19,6 +19,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
dbcHandler = DBCHandler::getReference();
|
||||
dbcMessage = nullptr;
|
||||
currentSignal = nullptr;
|
||||
inhibitMsgProc = false;
|
||||
|
||||
QStringList headers2;
|
||||
headers2 << "Value" << "Text";
|
||||
@@ -267,9 +268,12 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
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
|
||||
//add it to this one, update this signal's parent multiplexor
|
||||
DBC_SIGNAL *newSig = dbcMessage->sigHandler->findSignalByName(ui->cbMultiplexParent->currentText());
|
||||
@@ -280,6 +284,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
currentSignal->multiplexParent = newSig;
|
||||
newSig->multiplexedChildren.append(currentSignal);
|
||||
dbcFile->setDirtyFlag();
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -431,6 +436,8 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
{
|
||||
unsigned char bitpattern[8];
|
||||
|
||||
inhibitMsgProc = true;
|
||||
|
||||
if (sig == nullptr) {
|
||||
ui->groupBox->setEnabled(false);
|
||||
ui->txtName->setText("");
|
||||
@@ -451,6 +458,7 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
ui->bitfield->updateData(bitpattern, true);
|
||||
ui->comboReceiver->setCurrentIndex(0);
|
||||
ui->comboType->setCurrentIndex(0);
|
||||
inhibitMsgProc = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -489,7 +497,7 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
for (int i = 0; i < numSigs; 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);
|
||||
if (sig->multiplexParent == sig_iter) ui->cbMultiplexParent->setCurrentIndex(ui->cbMultiplexParent->count() - 1);
|
||||
@@ -565,6 +573,8 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inhibitMsgProc = false;
|
||||
}
|
||||
|
||||
/* fillValueTable also handles "enabled" state */
|
||||
|
||||
@@ -38,6 +38,7 @@ private:
|
||||
DBC_SIGNAL *currentSignal;
|
||||
DBCFile *dbcFile;
|
||||
bool inhibitCellChanged;
|
||||
bool inhibitMsgProc;
|
||||
|
||||
void fillSignalForm(DBC_SIGNAL *sig);
|
||||
void fillValueTable(DBC_SIGNAL *sig);
|
||||
|
||||
Reference in New Issue
Block a user