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;
|
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
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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());
|
||||||
|
|||||||
@@ -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
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user