diff --git a/tools/cabana/dbc/dbc.cc b/tools/cabana/dbc/dbc.cc index 909390fd27..e404bde99c 100644 --- a/tools/cabana/dbc/dbc.cc +++ b/tools/cabana/dbc/dbc.cc @@ -13,6 +13,30 @@ std::vector cabana::Msg::getSignals() const { return ret; } +void cabana::Msg::updateMask() { + mask.clear(); + for (int i = 0; i < size; i++) { + mask.push_back(0x00); + } + + for (auto &sig : sigs) { + int i = sig.msb / 8; + int bits = sig.size; + while (i >= 0 && i < size && bits > 0) { + int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8; + int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1; + + int sz = msb - lsb + 1; + int shift = (lsb - (i * 8)); + + mask[i] |= ((1ULL << sz) - 1) << shift; + + bits -= size; + i = sig.is_little_endian ? i - 1 : i + 1; + } + } +} + void cabana::Signal::updatePrecision() { precision = std::max(num_decimals(factor), num_decimals(offset)); } diff --git a/tools/cabana/dbc/dbc.h b/tools/cabana/dbc/dbc.h index fdbbc9d169..be0057cf56 100644 --- a/tools/cabana/dbc/dbc.h +++ b/tools/cabana/dbc/dbc.h @@ -65,6 +65,9 @@ namespace cabana { uint32_t size; QList sigs; + QList mask; + void updateMask(); + std::vector getSignals() const; const cabana::Signal *sig(const QString &sig_name) const { auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; }); diff --git a/tools/cabana/dbc/dbcfile.cc b/tools/cabana/dbc/dbcfile.cc index 0534ce39ff..9173080796 100644 --- a/tools/cabana/dbc/dbcfile.cc +++ b/tools/cabana/dbc/dbcfile.cc @@ -55,6 +55,7 @@ void DBCFile::open(const QString &content) { sig.is_little_endian = s.is_little_endian; sig.updatePrecision(); } + m.updateMask(); } parseExtraInfo(content); @@ -103,6 +104,7 @@ bool DBCFile::writeContents(const QString &fn) { cabana::Signal *DBCFile::addSignal(const MessageId &id, const cabana::Signal &sig) { if (auto m = const_cast(msg(id.address))) { m->sigs.push_back(sig); + m->updateMask(); return &m->sigs.last(); } @@ -113,6 +115,7 @@ cabana::Signal *DBCFile::addSignal(const MessageId &id, const cabana::Signal &si if (auto m = const_cast(msg(id))) { if (auto s = (cabana::Signal *)m->sig(sig_name)) { *s = sig; + m->updateMask(); return s; } } @@ -135,6 +138,7 @@ void DBCFile::removeSignal(const MessageId &id, const QString &sig_name) { auto it = std::find_if(m->sigs.begin(), m->sigs.end(), [&](auto &s) { return s.name == sig_name; }); if (it != m->sigs.end()) { m->sigs.erase(it); + m->updateMask(); } } } @@ -167,6 +171,15 @@ QString DBCFile::newSignalName(const MessageId &id) { return name; } +const QList& DBCFile::mask(const MessageId &id) const { + const cabana::Msg *m = msg(id); + if (m != nullptr) { + return m->mask; + } else { + return empty_mask; + } +} + std::map DBCFile::getMessages() { return msgs; } diff --git a/tools/cabana/dbc/dbcfile.h b/tools/cabana/dbc/dbcfile.h index e048dc5839..8083704160 100644 --- a/tools/cabana/dbc/dbcfile.h +++ b/tools/cabana/dbc/dbcfile.h @@ -41,6 +41,8 @@ public: QString newMsgName(const MessageId &id); QString newSignalName(const MessageId &id); + const QList& mask(const MessageId &id) const; + std::map getMessages(); const cabana::Msg *msg(const MessageId &id) const; const cabana::Msg *msg(uint32_t address) const; @@ -58,4 +60,5 @@ private: void parseExtraInfo(const QString &content); std::map msgs; QString name_; + QList empty_mask; }; diff --git a/tools/cabana/dbc/dbcmanager.cc b/tools/cabana/dbc/dbcmanager.cc index 390ded8512..2451ff9b00 100644 --- a/tools/cabana/dbc/dbcmanager.cc +++ b/tools/cabana/dbc/dbcmanager.cc @@ -188,6 +188,15 @@ QString DBCManager::newSignalName(const MessageId &id) { return dbc_file->newSignalName(id); } +const QList& DBCManager::mask(const MessageId &id) const { + auto sources_dbc_file = findDBCFile(id); + if (!sources_dbc_file) { + return empty_mask; + } + auto [_, dbc_file] = *sources_dbc_file; + return dbc_file->mask(id); +} + std::map DBCManager::getMessages(uint8_t source) { std::map ret; diff --git a/tools/cabana/dbc/dbcmanager.h b/tools/cabana/dbc/dbcmanager.h index 96d9380dbd..3b148bb61d 100644 --- a/tools/cabana/dbc/dbcmanager.h +++ b/tools/cabana/dbc/dbcmanager.h @@ -39,6 +39,8 @@ public: QString newMsgName(const MessageId &id); QString newSignalName(const MessageId &id); + const QList& mask(const MessageId &id) const; + std::map getMessages(uint8_t source); const cabana::Msg *msg(const MessageId &id) const; const cabana::Msg* msg(uint8_t source, const QString &name); @@ -57,6 +59,7 @@ public: private: SourceSet sources; + QList empty_mask; public slots: void updateSources(const SourceSet &s); diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 4c193666dc..13e8f70a8f 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -138,6 +138,7 @@ std::deque HistoryLogModel::fetchData(InputIt first, I } std::deque HistoryLogModel::fetchData(uint64_t from_time, uint64_t min_time) { + const QList mask; const auto &events = can->events(msg_id); const auto freq = can->lastMessage(msg_id).freq; const bool update_colors = !display_signals_mode || sigs.empty(); @@ -150,7 +151,7 @@ std::deque HistoryLogModel::fetchData(uint64_t from_ti auto msgs = fetchData(first, events.rend(), min_time); if (update_colors && (min_time > 0 || messages.empty())) { for (auto it = msgs.rbegin(); it != msgs.rend(); ++it) { - hex_colors.compute(it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, freq); + hex_colors.compute(it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, mask, freq); it->colors = hex_colors.colors; } } @@ -163,7 +164,7 @@ std::deque HistoryLogModel::fetchData(uint64_t from_ti auto msgs = fetchData(first, events.cend(), 0); if (update_colors) { for (auto it = msgs.begin(); it != msgs.end(); ++it) { - hex_colors.compute(it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, freq); + hex_colors.compute(it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, mask, freq); it->colors = hex_colors.colors; } } diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index f7b25bde51..66523333ad 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -51,6 +51,9 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { suppress_clear = new QPushButton(); suppress_layout->addWidget(suppress_add); suppress_layout->addWidget(suppress_clear); + QCheckBox *suppress_defined_signals = new QCheckBox(tr("Suppress Defined Signals"), this); + suppress_defined_signals->setChecked(settings.suppress_defined_signals); + suppress_layout->addWidget(suppress_defined_signals); main_layout->addLayout(suppress_layout); // signals/slots @@ -61,6 +64,9 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { view->setUniformRowHeights(!settings.multiple_lines_bytes); model->sortMessages(); }); + QObject::connect(suppress_defined_signals, &QCheckBox::stateChanged, [=](int state) { + settings.suppress_defined_signals = (state == Qt::Checked); + }); QObject::connect(can, &AbstractStream::msgsReceived, model, &MessageListModel::msgsReceived); QObject::connect(can, &AbstractStream::streamStarted, this, &MessagesWidget::reset); QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages); diff --git a/tools/cabana/settings.cc b/tools/cabana/settings.cc index f759324988..d0cada680a 100644 --- a/tools/cabana/settings.cc +++ b/tools/cabana/settings.cc @@ -38,6 +38,7 @@ void Settings::save() { s.setValue("log_livestream", log_livestream); s.setValue("log_path", log_path); s.setValue("drag_direction", drag_direction); + s.setValue("suppress_defined_signals", suppress_defined_signals); } void Settings::load() { @@ -61,6 +62,7 @@ void Settings::load() { log_livestream = s.value("log_livestream", true).toBool(); log_path = s.value("log_path").toString(); drag_direction = (Settings::DragDirection)s.value("drag_direction", 0).toInt(); + suppress_defined_signals = s.value("suppress_defined_signals", false).toBool(); if (log_path.isEmpty()) { log_path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/cabana_live_stream/"; } diff --git a/tools/cabana/settings.h b/tools/cabana/settings.h index 11548ef5cc..b8a3797f86 100644 --- a/tools/cabana/settings.h +++ b/tools/cabana/settings.h @@ -36,6 +36,7 @@ public: int sparkline_range = 15; // 15 seconds bool multiple_lines_bytes = true; bool log_livestream = true; + bool suppress_defined_signals = false; QString log_path; QString last_dir; QString last_route_dir; diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 3c7291ea38..3451c15291 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -27,7 +27,8 @@ void AbstractStream::updateMessages(QHash *messages) { } void AbstractStream::updateEvent(const MessageId &id, double sec, const uint8_t *data, uint8_t size) { - all_msgs[id].compute((const char *)data, size, sec, getSpeed()); + QList mask = settings.suppress_defined_signals ? dbc()->mask(id) : QList(); + all_msgs[id].compute((const char *)data, size, sec, getSpeed(), mask); if (!new_msgs->contains(id)) { new_msgs->insert(id, {}); } @@ -67,10 +68,11 @@ void AbstractStream::updateLastMsgsTo(double sec) { auto it = std::lower_bound(ev.crbegin(), ev.crend(), last_ts, [](auto e, uint64_t ts) { return e->mono_time > ts; }); + QList mask = settings.suppress_defined_signals ? dbc()->mask(id) : QList(); if (it != ev.crend()) { double ts = (*it)->mono_time / 1e9 - routeStartTime(); auto &m = all_msgs[id]; - m.compute((const char *)(*it)->dat, (*it)->size, ts, getSpeed()); + m.compute((const char *)(*it)->dat, (*it)->size, ts, getSpeed(), mask); m.count = std::distance(it, ev.crend()); m.freq = m.count / std::max(1.0, ts); } @@ -153,7 +155,7 @@ static inline QColor blend(const QColor &a, const QColor &b) { return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2, (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2); } -void CanData::compute(const char *can_data, const int size, double current_sec, double playback_speed, uint32_t in_freq) { +void CanData::compute(const char *can_data, const int size, double current_sec, double playback_speed, const QList &mask, uint32_t in_freq) { ts = current_sec; ++count; freq = in_freq == 0 ? count / std::max(1.0, current_sec) : in_freq; @@ -171,8 +173,9 @@ void CanData::compute(const char *can_data, const int size, double current_sec, const QColor &greyish_blue = !lighter ? GREYISH_BLUE : GREYISH_BLUE_LIGHTER; for (int i = 0; i < size; ++i) { - const uint8_t last = dat[i]; - const uint8_t cur = can_data[i]; + const uint8_t mask_byte = (i < mask.size()) ? (~mask[i]) : 0xff; + const uint8_t last = dat[i] & mask_byte; + const uint8_t cur = can_data[i] & mask_byte; const int delta = cur - last; if (last != cur) { diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index d031b6229c..80c11d2f19 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -13,7 +13,7 @@ #include "tools/replay/replay.h" struct CanData { - void compute(const char *dat, const int size, double current_sec, double playback_speed, uint32_t in_freq = 0); + void compute(const char *dat, const int size, double current_sec, double playback_speed, const QList &mask, uint32_t in_freq = 0); double ts = 0.; uint32_t count = 0;