|
|
|
@ -1,5 +1,6 @@ |
|
|
|
|
#include "tools/cabana/tools/findsimilarbits.h" |
|
|
|
|
|
|
|
|
|
#include <QGridLayout> |
|
|
|
|
#include <QHeaderView> |
|
|
|
|
#include <QHBoxLayout> |
|
|
|
|
#include <QIntValidator> |
|
|
|
@ -16,20 +17,23 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi |
|
|
|
|
|
|
|
|
|
QVBoxLayout *main_layout = new QVBoxLayout(this); |
|
|
|
|
|
|
|
|
|
QHBoxLayout *form_layout = new QHBoxLayout(); |
|
|
|
|
bus_combo = new QComboBox(this); |
|
|
|
|
QHBoxLayout *src_layout = new QHBoxLayout(); |
|
|
|
|
src_bus_combo = new QComboBox(this); |
|
|
|
|
find_bus_combo = new QComboBox(this); |
|
|
|
|
QSet<uint8_t> bus_set; |
|
|
|
|
for (auto it = can->last_msgs.begin(); it != can->last_msgs.end(); ++it) { |
|
|
|
|
bus_set << it.key().source; |
|
|
|
|
} |
|
|
|
|
for (uint8_t bus : bus_set) { |
|
|
|
|
bus_combo->addItem(QString::number(bus), bus); |
|
|
|
|
for (auto cb : {src_bus_combo, find_bus_combo}) { |
|
|
|
|
for (uint8_t bus : bus_set) { |
|
|
|
|
cb->addItem(QString::number(bus), bus); |
|
|
|
|
} |
|
|
|
|
cb->model()->sort(0); |
|
|
|
|
cb->setCurrentIndex(0); |
|
|
|
|
} |
|
|
|
|
bus_combo->model()->sort(0); |
|
|
|
|
bus_combo->setCurrentIndex(0); |
|
|
|
|
|
|
|
|
|
msg_cb = new QComboBox(this); |
|
|
|
|
// TODO: update when bus_combo changes
|
|
|
|
|
// TODO: update when src_bus_combo changes
|
|
|
|
|
for (auto &[id, msg] : dbc()->getMessages(0)) { |
|
|
|
|
msg_cb->addItem(msg.name, id.address); |
|
|
|
|
} |
|
|
|
@ -37,29 +41,44 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi |
|
|
|
|
msg_cb->setCurrentIndex(0); |
|
|
|
|
|
|
|
|
|
byte_idx_sb = new QSpinBox(this); |
|
|
|
|
byte_idx_sb->setFixedWidth(50); |
|
|
|
|
byte_idx_sb->setRange(0, 63); |
|
|
|
|
|
|
|
|
|
bit_idx_sb = new QSpinBox(this); |
|
|
|
|
bit_idx_sb->setFixedWidth(50); |
|
|
|
|
bit_idx_sb->setRange(0, 7); |
|
|
|
|
|
|
|
|
|
form_layout->addWidget(new QLabel("Bus")); |
|
|
|
|
form_layout->addWidget(bus_combo); |
|
|
|
|
form_layout->addWidget(msg_cb); |
|
|
|
|
form_layout->addWidget(new QLabel("Byte Index")); |
|
|
|
|
form_layout->addWidget(byte_idx_sb); |
|
|
|
|
form_layout->addWidget(new QLabel("Bit Index")); |
|
|
|
|
form_layout->addWidget(bit_idx_sb); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src_layout->addWidget(new QLabel(tr("Bus"))); |
|
|
|
|
src_layout->addWidget(src_bus_combo); |
|
|
|
|
src_layout->addWidget(msg_cb); |
|
|
|
|
src_layout->addWidget(new QLabel(tr("Byte Index"))); |
|
|
|
|
src_layout->addWidget(byte_idx_sb); |
|
|
|
|
src_layout->addWidget(new QLabel(tr("Bit Index"))); |
|
|
|
|
src_layout->addWidget(bit_idx_sb); |
|
|
|
|
src_layout->addStretch(0); |
|
|
|
|
|
|
|
|
|
QHBoxLayout *find_layout = new QHBoxLayout(); |
|
|
|
|
find_layout->addWidget(new QLabel(tr("Bus"))); |
|
|
|
|
find_layout->addWidget(find_bus_combo); |
|
|
|
|
find_layout->addWidget(new QLabel(tr("Equal"))); |
|
|
|
|
equal_combo = new QComboBox(this); |
|
|
|
|
equal_combo->addItems({"Yes", "No"}); |
|
|
|
|
find_layout->addWidget(equal_combo); |
|
|
|
|
min_msgs = new QLineEdit(this); |
|
|
|
|
min_msgs->setValidator(new QIntValidator(this)); |
|
|
|
|
min_msgs->setText("100"); |
|
|
|
|
form_layout->addWidget(new QLabel("Min msg count")); |
|
|
|
|
form_layout->addWidget(min_msgs); |
|
|
|
|
find_layout->addWidget(new QLabel(tr("Min msg count"))); |
|
|
|
|
find_layout->addWidget(min_msgs); |
|
|
|
|
search_btn = new QPushButton(tr("&Find"), this); |
|
|
|
|
form_layout->addWidget(search_btn); |
|
|
|
|
form_layout->addStretch(1); |
|
|
|
|
main_layout->addLayout(form_layout); |
|
|
|
|
find_layout->addWidget(search_btn); |
|
|
|
|
find_layout->addStretch(0); |
|
|
|
|
|
|
|
|
|
QGridLayout *grid_layout = new QGridLayout(); |
|
|
|
|
grid_layout->addWidget(new QLabel("Find From:"), 0, 0); |
|
|
|
|
grid_layout->addLayout(src_layout, 0, 1); |
|
|
|
|
grid_layout->addWidget(new QLabel("Find In:"), 1, 0); |
|
|
|
|
grid_layout->addLayout(find_layout, 1, 1); |
|
|
|
|
main_layout->addLayout(grid_layout); |
|
|
|
|
|
|
|
|
|
table = new QTableWidget(this); |
|
|
|
|
table->setSelectionBehavior(QAbstractItemView::SelectRows); |
|
|
|
@ -70,10 +89,9 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi |
|
|
|
|
|
|
|
|
|
setMinimumSize({700, 500}); |
|
|
|
|
QObject::connect(search_btn, &QPushButton::clicked, this, &FindSimilarBitsDlg::find); |
|
|
|
|
|
|
|
|
|
QObject::connect(table, &QTableWidget::doubleClicked, [this](const QModelIndex &index) { |
|
|
|
|
if (index.isValid()) { |
|
|
|
|
MessageId msg_id = {.source = (uint8_t)bus_combo->currentData().toUInt(), .address = table->item(index.row(), 0)->text().toUInt(0, 16)}; |
|
|
|
|
MessageId msg_id = {.source = (uint8_t)find_bus_combo->currentData().toUInt(), .address = table->item(index.row(), 0)->text().toUInt(0, 16)}; |
|
|
|
|
emit openMessage(msg_id); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
@ -83,7 +101,8 @@ void FindSimilarBitsDlg::find() { |
|
|
|
|
search_btn->setEnabled(false); |
|
|
|
|
table->clear(); |
|
|
|
|
uint32_t selected_address = msg_cb->currentData().toUInt(); |
|
|
|
|
auto msg_mismatched = calcBits(bus_combo->currentText().toUInt(), selected_address, byte_idx_sb->value(), bit_idx_sb->value(), min_msgs->text().toInt()); |
|
|
|
|
auto msg_mismatched = calcBits(src_bus_combo->currentText().toUInt(), selected_address, byte_idx_sb->value(), bit_idx_sb->value(), |
|
|
|
|
find_bus_combo->currentText().toUInt(), equal_combo->currentIndex() == 0, min_msgs->text().toInt()); |
|
|
|
|
table->setRowCount(msg_mismatched.size()); |
|
|
|
|
table->setColumnCount(6); |
|
|
|
|
table->setHorizontalHeaderLabels({"address", "byte idx", "bit idx", "mismatches", "total msgs", "% mismatched"}); |
|
|
|
@ -94,32 +113,41 @@ void FindSimilarBitsDlg::find() { |
|
|
|
|
table->setItem(i, 2, new QTableWidgetItem(QString::number(m.bit_idx))); |
|
|
|
|
table->setItem(i, 3, new QTableWidgetItem(QString::number(m.mismatches))); |
|
|
|
|
table->setItem(i, 4, new QTableWidgetItem(QString::number(m.total))); |
|
|
|
|
table->setItem(i, 5, new QTableWidgetItem(QString::number(m.perc))); |
|
|
|
|
table->setItem(i, 5, new QTableWidgetItem(QString::number(m.perc, 'f', 2))); |
|
|
|
|
} |
|
|
|
|
search_btn->setEnabled(true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QList<FindSimilarBitsDlg::mismatched_struct> FindSimilarBitsDlg::calcBits(uint8_t bus, uint32_t selected_address, int byte_idx, int bit_idx, int min_msgs_cnt) { |
|
|
|
|
QList<FindSimilarBitsDlg::mismatched_struct> FindSimilarBitsDlg::calcBits(uint8_t bus, uint32_t selected_address, int byte_idx, |
|
|
|
|
int bit_idx, uint8_t find_bus, bool equal, int min_msgs_cnt) { |
|
|
|
|
QHash<uint32_t, QVector<uint32_t>> mismatches; |
|
|
|
|
QHash<uint32_t, uint32_t> msg_count; |
|
|
|
|
auto events = can->rawEvents(); |
|
|
|
|
int bit_to_find = -1; |
|
|
|
|
for (const auto &[id, msg] : can->events()) { |
|
|
|
|
if (id.source == bus) { |
|
|
|
|
for (const auto &c : msg) { |
|
|
|
|
if (id.address == selected_address && c.size > byte_idx) { |
|
|
|
|
bit_to_find = ((c.dat[byte_idx] >> (7 - bit_idx)) & 1) != 0; |
|
|
|
|
for (auto e : *events) { |
|
|
|
|
if (e->which == cereal::Event::Which::CAN) { |
|
|
|
|
for (const auto &c : e->event.getCan()) { |
|
|
|
|
uint8_t src = c.getSrc(); |
|
|
|
|
uint32_t address = c.getAddress(); |
|
|
|
|
const auto dat = c.getDat(); |
|
|
|
|
if (src == bus) { |
|
|
|
|
if (address == selected_address && dat.size() > byte_idx) { |
|
|
|
|
bit_to_find = ((dat[byte_idx] >> (7 - bit_idx)) & 1) != 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
++msg_count[id.address]; |
|
|
|
|
if (bit_to_find == -1) continue; |
|
|
|
|
if (src == find_bus) { |
|
|
|
|
++msg_count[address]; |
|
|
|
|
if (bit_to_find == -1) continue; |
|
|
|
|
|
|
|
|
|
auto &mismatched = mismatches[id.address]; |
|
|
|
|
if (mismatched.size() < c.size * 8) { |
|
|
|
|
mismatched.resize(c.size * 8); |
|
|
|
|
} |
|
|
|
|
for (int i = 0; i < c.size; ++i) { |
|
|
|
|
for (int j = 0; j < 8; ++j) { |
|
|
|
|
int bit = ((c.dat[i] >> (7 - j)) & 1) != 0; |
|
|
|
|
mismatched[i * 8 + j] += (bit != bit_to_find); |
|
|
|
|
auto &mismatched = mismatches[address]; |
|
|
|
|
if (mismatched.size() < dat.size() * 8) { |
|
|
|
|
mismatched.resize(dat.size() * 8); |
|
|
|
|
} |
|
|
|
|
for (int i = 0; i < dat.size(); ++i) { |
|
|
|
|
for (int j = 0; j < 8; ++j) { |
|
|
|
|
int bit = ((dat[i] >> (7 - j)) & 1) != 0; |
|
|
|
|
mismatched[i * 8 + j] += equal ? (bit != bit_to_find) : (bit == bit_to_find); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|