Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DBC]Add support for multiple signal multiplexor values #719

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 112 additions & 22 deletions dbc/dbc_classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,12 @@ DBC_MESSAGE::DBC_MESSAGE()
sender = nullptr;
}

DBC_SIGNAL::DBC_SIGNAL()
void DBC_SIGNAL::addMultiplexRange(int min, int max)
{
bias = 0;
isMultiplexed = false;
isMultiplexor = false;
max = 1;
min = 0;
multiplexLowValue = 0;
multiplexHighValue = 0;
factor = 1.0;
intelByteOrder = false;
parentMessage = nullptr;
multiplexParent = nullptr;
receiver = nullptr;
signalSize = 1;
startBit = 1;
valType = DBC_SIG_VAL_TYPE::UNSIGNED_INT;
if (min != max)
hasExtendedMultiplexing = true;
isMultiplexed = true;
multiplexLowAndHighValues.append(QPair<int, int>(min, max));
}

bool DBC_SIGNAL::isSignalInMessage(const CANFrame &frame)
Expand All @@ -42,11 +31,7 @@ bool DBC_SIGNAL::isSignalInMessage(const CANFrame &frame)
{
int val;
if (!multiplexParent->processAsInt(frame, val)) return false;
if ((val >= multiplexLowValue) && (val <= multiplexHighValue))
{
return true;
}
else return false;
return isValueMatchingMultiplex(val);
}
else return false;
}
Expand All @@ -55,6 +40,111 @@ bool DBC_SIGNAL::isSignalInMessage(const CANFrame &frame)
else return true; //if signal isn't multiplexed then it's definitely in the message
}

bool DBC_SIGNAL::isValueMatchingMultiplex(int val) const
{
for (auto limitPair : multiplexLowAndHighValues) {
if ((limitPair.first <= val) && (val <= limitPair.second))
return true;
}
return false;
}

QString DBC_SIGNAL::multiplexDbcString(DbcMuxStringFormat fmt) const
{
QString ret;
for (auto limitPair : multiplexLowAndHighValues) {
if (fmt == MuxStringFormat_DbcFile) {
if (!ret.isEmpty())
ret.append(QStringLiteral(" "));
ret.append(QString("%1-%2").arg(limitPair.first).arg(limitPair.second));
} else {
if (!ret.isEmpty())
ret.append(QStringLiteral(";"));
ret.append(QString::number(limitPair.first));
if (limitPair.first != limitPair.second)
ret.append(QString("-%1").arg(limitPair.second));
}
}
return ret;
}

void DBC_SIGNAL::copyMultiplexValuesFromSignal(const DBC_SIGNAL &signal)
{
isMultiplexed = signal.isMultiplexed;
for (auto multiplexSignalPair : signal.multiplexLowAndHighValues) {
multiplexLowAndHighValues.append(multiplexSignalPair);
}
}

/**
* @brief DBC_SIGNAL::parseDbcMultiplexUiString
* Method for parsing the Vector CANDB++ like multiplex definitions:
*
* Single values has to be separated by semicolons
* and the value ranges by hypens
* (e.g.: 1;2;5-7)
* @param multiplexes in the format from the UI
* @param errorString output parameter to pass the failure text if parsing failed
* @return true if the multiplexes parameter could be parsed properly
*/
bool DBC_SIGNAL::parseDbcMultiplexUiString(const QString &multiplexes, QString &errorString)
{
QList<QPair<int, int>> multiplexLowAndHighValuesTemp;
const auto muxes = multiplexes.split(QChar(';'), Qt::SkipEmptyParts);
for (const auto &mux : muxes) {
bool ok = false;
if (mux.contains(QChar('-'))) {
const auto minMax = mux.split(QChar('-'));
if (minMax.count() != 2) {
errorString = QObject::tr("The %1 part contains more than one '-' sign").arg(mux);
return false;
}

int min = minMax.at(0).toInt(&ok);
if (!ok) {
errorString = QObject::tr("Unable to parse the %1 part to integer").arg(minMax.at(0));
return false;
}

int max = minMax.at(1).toInt(&ok);
if (!ok) {
errorString = QObject::tr("Unable to parse the %1 part to integer").arg(minMax.at(1));
return false;
}

multiplexLowAndHighValuesTemp.append(QPair<int, int>(min, max));
} else {
int value = mux.toInt(&ok);
if (!ok) {
errorString = QObject::tr("Unable to parse the %1 part to integer").arg(mux);
return false;
}
multiplexLowAndHighValuesTemp.append(QPair<int, int>(value, value));
}
}
multiplexLowAndHighValues.clear();
multiplexLowAndHighValues = multiplexLowAndHighValuesTemp;
return true;
}

bool DBC_SIGNAL::multiplexesIdenticalToSignal(DBC_SIGNAL *other) const
{
auto othersMuxes = other->multiplexLowAndHighValues;
for (auto myMux : multiplexLowAndHighValues) {
bool found = false;
for (auto otherMux : othersMuxes) {
if (myMux == otherMux) {
othersMuxes.removeAll(myMux);
found = true;
break;
}
}
if (!found)
return false;
}
return othersMuxes.isEmpty();
}

//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)
{
Expand All @@ -69,7 +159,7 @@ QString DBC_SIGNAL::processSignalTree(const CANFrame &frame)

foreach (DBC_SIGNAL *sig, multiplexedChildren)
{
if ( (val >= sig->multiplexLowValue) && (val <= sig->multiplexHighValue) )
if (sig->isValueMatchingMultiplex(val))
{
qDebug() << "Found match for multiplex value range - " << sig->name;
QString sigString;
Expand Down
51 changes: 34 additions & 17 deletions dbc/dbc_classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,44 @@ class DBC_SIGNAL;
class DBC_SIGNAL
{
public: //TODO: this is sloppy. It shouldn't all be public!
DBC_SIGNAL() = default;

enum DbcMuxStringFormat {
MuxStringFormat_DbcFile,
MuxStringFormat_UI
};
QString name;
int startBit;
int signalSize;
bool intelByteOrder; //true is obviously little endian. False is big endian
bool isMultiplexor;
bool isMultiplexed;
int multiplexHighValue;
int multiplexLowValue;
DBC_SIG_VAL_TYPE valType;
double factor;
double bias;
double min;
double max;
DBC_NODE *receiver; //it is fast to have a pointer but dangerous... Make sure to walk the whole tree and delete everything so nobody has stale references.
DBC_MESSAGE *parentMessage;
int startBit = 1;
int signalSize = 1;
bool intelByteOrder = false; //true is obviously little endian. False is big endian

bool isMultiplexor = false;
bool isMultiplexed = false;
void addMultiplexRange(int min, int max);
int multiplexHighValue = 0;
int multiplexLowValue = 0;
bool hasExtendedMultiplexing = false;
QList<DBC_SIGNAL *> multiplexedChildren;
DBC_SIGNAL *multiplexParent = nullptr;
QString multiplexDbcString(DbcMuxStringFormat fmt = MuxStringFormat_DbcFile) const;
void copyMultiplexValuesFromSignal(const DBC_SIGNAL &signal);
bool parseDbcMultiplexUiString(const QString &multiplexes, QString &errorString);
bool multiplexesIdenticalToSignal(DBC_SIGNAL *other) const;

DBC_SIG_VAL_TYPE valType = DBC_SIG_VAL_TYPE::UNSIGNED_INT;
double factor = 1.0;
double bias = 0;
double min = 0;
double max = 1;
DBC_NODE *receiver = nullptr; //it is fast to have a pointer but dangerous... Make sure to walk the whole tree and delete everything so nobody has stale references.
DBC_MESSAGE *parentMessage = nullptr;
QString unitName;
QString comment;
QVariant cachedValue;
QList<DBC_ATTRIBUTE_VALUE> attributes;
QList<DBC_VAL_ENUM_ENTRY> valList;
QList<DBC_SIGNAL *> multiplexedChildren;
DBC_SIGNAL *multiplexParent;
DBC_SIGNAL *self;

DBC_SIGNAL();
bool processAsText(const CANFrame &frame, QString &outString, bool outputName = true, bool outputUnit = true);
bool processAsInt(const CANFrame &frame, int32_t &outValue);
bool processAsDouble(const CANFrame &frame, double &outValue);
Expand All @@ -123,11 +136,15 @@ class DBC_SIGNAL
DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name);
DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx);
bool isSignalInMessage(const CANFrame &frame);
bool isValueMatchingMultiplex(int val) const;


friend bool operator<(const DBC_SIGNAL& l, const DBC_SIGNAL& r)
{
return (l.name.toLower() < r.name.toLower());
}
private:
QList<QPair<int, int>> multiplexLowAndHighValues;
};

class DBCSignalHandler; //forward declaration to keep from having to include dbchandler.h in this file and thus create a loop
Expand Down
47 changes: 20 additions & 27 deletions dbc/dbchandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,6 @@ DBC_SIGNAL* DBCFile::parseSignalLine(QString line, DBC_MESSAGE *msg)
//bool isMultiplexed = false;
DBC_SIGNAL sig;

sig.multiplexLowValue = 0;
sig.multiplexHighValue = 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]+)\\] \\\"(.*)\\\" (.*)");

Expand All @@ -529,10 +524,7 @@ DBC_SIGNAL* DBCFile::parseSignalLine(QString line, DBC_MESSAGE *msg)
if (match.hasMatch())
{
qDebug() << "Multiplexed signal";
//isMultiplexed = true;
sig.isMultiplexed = true;
sig.multiplexLowValue = match.captured(2).toInt();
sig.multiplexHighValue = sig.multiplexLowValue;
sig.addMultiplexRange(match.captured(2).toInt(), match.captured(2).toInt());
offset = 1;
}
else
Expand All @@ -543,9 +535,7 @@ DBC_SIGNAL* DBCFile::parseSignalLine(QString line, DBC_MESSAGE *msg)
{
qDebug() << "Extended Multiplexor Signal";
sig.isMultiplexor = true; //we don't set the local isMessageMultiplexor variable because this isn't the top level multiplexor
sig.isMultiplexed = true; //but, it is both a multiplexor and multiplexed
sig.multiplexLowValue = match.captured(2).toInt();
sig.multiplexHighValue = sig.multiplexLowValue;
sig.addMultiplexRange(match.captured(2).toInt(), match.captured(2).toInt());
offset = 1;
}
else
Expand Down Expand Up @@ -643,7 +633,7 @@ bool DBCFile::parseSignalMultiplexValueLine(QString line)
QRegularExpressionMatch match;

qDebug() << "Found a multiplex definition line";
regex.setPattern("^SG\\_MUL\\_VAL\\_ (\\d+) ([-\\w]+) ([-\\w]+) (\\d+)\\-(\\d+);");
regex.setPattern("^SG\\_MUL\\_VAL\\_ (\\d+) ([-\\w]+) ([-\\w]+) ((?:\\d+\\-\\d+[\\s]*[\\,]?[\\s]*)*)");
match = regex.match(line);
//captured 1 is message ID
//Captured 2 is signal name
Expand All @@ -661,11 +651,21 @@ bool DBCFile::parseSignalMultiplexValueLine(QString line)
DBC_SIGNAL *parentSignal = msg->sigHandler->findSignalByName(match.captured(3));
if (parentSignal != nullptr)
{
//now need to add "thisSignal" to the children multiplexed signals of "parentSignal"
const QStringList ranges = match.captured(4).split(QChar(','), Qt::SkipEmptyParts);
for (const QString &range : ranges) {
//now need to add "thisSignal" to the children multiplexed signals of "parentSignal"
const QStringList rangeSides = range.trimmed().split(QChar('-'));
if (rangeSides.count() != 2) {
qDebug() << QString("Malformed range definition: '%2' found in the multiplexed signal: %1")
.arg(match.captured(1).arg(range.trimmed()));
return false;
}
int rangeMin = rangeSides.at(0).toInt();
int rangeMax = rangeSides.at(1).toInt();
thisSignal->multiplexParent = parentSignal;
thisSignal->addMultiplexRange(rangeMin, rangeMax);
}
parentSignal->multiplexedChildren.append(thisSignal);
thisSignal->multiplexParent = parentSignal;
thisSignal->multiplexLowValue = match.captured(4).toInt();
thisSignal->multiplexHighValue = match.captured(5).toInt();
return true;
}
}
Expand Down Expand Up @@ -1458,7 +1458,7 @@ bool DBCFile::saveFile(QString fileName)
}
//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;
if (sig->hasExtendedMultiplexing) hasExtendedMultiplexing = true;

msgOutput.append(" : " + QString::number(sig->startBit) + "|" + QString::number(sig->signalSize) + "@");

Expand Down Expand Up @@ -1625,7 +1625,7 @@ bool DBCFile::saveFile(QString fileName)
{
msgOutput.append("SG_MUL_VAL_ " + QString::number(ID) + " ");
msgOutput.append(sig->name + " " + sig->multiplexParent->name + " ");
msgOutput.append(QString::number(sig->multiplexLowValue) + "-" + QString::number(sig->multiplexHighValue) + ";");
msgOutput.append(sig->multiplexDbcString() + ";");
msgOutput.append("\n");
extMultiplexOutput.append(msgOutput);
msgOutput.clear(); //got to reset it after writing
Expand Down Expand Up @@ -2042,14 +2042,7 @@ DBCFile* DBCHandler::loadJSONFile(QString filename)
if (!sigObj.find("mux_id")->isUndefined())
{
QJsonValue muxVal = sigObj.find("mux_id").value();
sig.multiplexLowValue = muxVal.toInt();
sig.multiplexHighValue = sig.multiplexLowValue;
sig.isMultiplexed = true;
}
else
{
sig.multiplexLowValue = 0;
sig.multiplexHighValue = 0;
sig.addMultiplexRange(muxVal.toInt(), muxVal.toInt());
}
QJsonValue muxerVal = sigObj.find("is_muxer").value();
if (!muxerVal.isNull())
Expand Down
7 changes: 2 additions & 5 deletions dbc/dbcmaineditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,7 @@ QString DBCMainEditor::createSignalText(DBC_SIGNAL *sig)
QString sigInfo;
if (sig->isMultiplexed)
{
sigInfo = "(" + QString::number(sig->multiplexLowValue);
if (sig->multiplexHighValue != sig->multiplexLowValue) sigInfo += "-" + QString::number(sig->multiplexHighValue);
sigInfo += ") ";
sigInfo = "(" + sig->multiplexDbcString() + ") ";
}
sigInfo.append(sig->name);

Expand Down Expand Up @@ -624,8 +622,7 @@ void DBCMainEditor::copyMessageToNode(DBC_NODE *parentNode, DBC_MESSAGE *source,
sig.isMultiplexor = false; //sigSource->isMultiplexor;
sig.max = sigSource->max;
sig.min = sigSource->min;
sig.multiplexLowValue = sigSource->multiplexLowValue;
sig.multiplexHighValue = sigSource->multiplexHighValue;
sig.copyMultiplexValuesFromSignal(*sigSource);
sig.factor = sigSource->factor;
sig.intelByteOrder = sigSource->intelByteOrder;
sig.parentMessage = &msg;
Expand Down
Loading