From f6b5db96170a76676ca462633e12f4e60f5186f0 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Tue, 1 Dec 2015 20:25:52 -0500 Subject: [PATCH] Added the ability to track which direction frames are coming from (from us or to us), import that detail from file formats that support it, save it to file formats that support it. Also some bug fixes. --- can_structs.h | 1 + canframemodel.cpp | 35 +++++++++++++++-------- config.h | 2 +- framefileio.cpp | 69 +++++++++++++++++++++++++++++++++------------ mainwindow.cpp | 7 ++--- scriptcontainer.cpp | 21 +++++++++++++- scriptcontainer.h | 6 ++++ serialworker.cpp | 9 ++++-- 8 files changed, 111 insertions(+), 39 deletions(-) diff --git a/can_structs.h b/can_structs.h index f230964..92e4491 100644 --- a/can_structs.h +++ b/can_structs.h @@ -9,6 +9,7 @@ public: int ID; int bus; bool extended; + bool isReceived; //did we receive this or send it? int len; unsigned char data[8]; uint64_t timestamp; diff --git a/canframemodel.cpp b/canframemodel.cpp index bd2d578..beb978a 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -17,7 +17,7 @@ int CANFrameModel::totalFrameCount() int CANFrameModel::columnCount(const QModelIndex &index) const { Q_UNUSED(index); - return 6; + return 7; } CANFrameModel::CANFrameModel(QObject *parent) @@ -159,7 +159,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const if (!index.isValid()) return QVariant(); - if (index.row() >= filteredFrames.count()) + if (index.row() >= (filteredFrames.count())) return QVariant(); if (role == Qt::DisplayRole) { @@ -168,7 +168,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const { case 0: //timestamp if (!timeSeconds) return QString::number(thisFrame.timestamp); - else return QString::number(thisFrame.timestamp / 1000000.0f); + else return QString::number((double)thisFrame.timestamp / 1000000.0, 'f', 6); break; case 1: //id return Utility::formatNumber(thisFrame.ID); @@ -176,13 +176,17 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const case 2: //ext return QString::number(thisFrame.extended); break; - case 3: //bus + case 3: //direction + if (thisFrame.isReceived) return QString(tr("Rx")); + else return QString(tr("Tx")); + break; + case 4: //bus return QString::number(thisFrame.bus); break; - case 4: //len + case 5: //len return QString::number(thisFrame.len); break; - case 5: //data + case 6: //data for (int i = 0; i < thisFrame.len; i++) { tempString.append(Utility::formatNumber(thisFrame.data[i])); @@ -234,12 +238,15 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation, return QString(tr("Ext")); break; case 3: - return QString(tr("Bus")); + return QString(tr("Dir")); break; case 4: - return QString(tr("Len")); + return QString(tr("Bus")); break; case 5: + return QString(tr("Len")); + break; + case 6: return QString(tr("Data")); break; } @@ -385,6 +392,11 @@ void CANFrameModel::clearFrames() */ void CANFrameModel::insertFrames(const QVector &newFrames) { + //not resetting the model here because the serial worker automatically does a bulk refresh every 1/4 second + //and that refresh will cause the view to update. If you do both it usually ends up thinking you have + //double the number of frames. + //beginResetModel(); + mutex.lock(); int insertedFiltered = 0; for (int i = 0; i < newFrames.count(); i++) { @@ -400,9 +412,10 @@ void CANFrameModel::insertFrames(const QVector &newFrames) filteredFrames.append(newFrames[i]); } } - - beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + insertedFiltered); - endInsertRows(); + mutex.unlock(); + //endResetModel(); + //beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + insertedFiltered); + //endInsertRows(); if (needFilterRefresh) emit updatedFiltersList(); } diff --git a/config.h b/config.h index dba170f..b3e533a 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #ifndef CONFIG #define CONFIG -#define VERSION 142 +#define VERSION 143 //try to keep this in sync. //SavvyCAN will complain if you connect a GVRET board with a revision diff --git a/framefileio.cpp b/framefileio.cpp index c2fad71..38bd344 100644 --- a/framefileio.cpp +++ b/framefileio.cpp @@ -94,7 +94,7 @@ bool FrameFileIO::loadCRTDFile(QString filename, QVector* frames) return false; } - line = inFile->readLine(); //read out the header first and discard it. + line = inFile->readLine().toUpper(); //read out the header first and discard it. while (!inFile->atEnd()) { lineCounter++; @@ -121,11 +121,14 @@ bool FrameFileIO::loadCRTDFile(QString filename, QVector* frames) } //qDebug() << "decimal places " << decimalPlaces; thisFrame.timestamp = (int64_t)(tokens[0].toDouble() * multiplier); - if (tokens[1] == "R11" || tokens[1] == "R29") + char firstChar = tokens[1].left(1)[0]; + if (firstChar == 'R' || firstChar == 'T') { thisFrame.ID = tokens[2].toInt(NULL, 16); - if (tokens[1] == "R29") thisFrame.extended = true; + if (tokens[1] == "R29" || tokens[1] == "T29") thisFrame.extended = true; else thisFrame.extended = false; + if (firstChar == 'T') thisFrame.isReceived = false; + else thisFrame.isReceived = true; thisFrame.bus = 0; thisFrame.len = tokens.length() - 3; for (int d = 0; d < thisFrame.len; d++) @@ -171,11 +174,15 @@ bool FrameFileIO::saveCRTDFile(QString filename, const QVector* frames outFile->write(QString::number(frames->at(c).timestamp / 1000000.0, 'f', 6).toUtf8()); outFile->putChar(' '); + + if (frames->at(c).isReceived) outFile->putChar('R'); + else outFile->putChar('T'); + if (frames->at(c).extended) { - outFile->write("R29 "); + outFile->write("29 "); } - else outFile->write("R11 "); + else outFile->write("11 "); outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8()); outFile->putChar(' '); @@ -199,6 +206,7 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector* frames) QFile *inFile = new QFile(filename); CANFrame thisFrame; QByteArray line; + int fileVersion = 1; long long timeStamp = Utility::GetTimeMS(); int lineCounter = 0; @@ -208,7 +216,8 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector* frames) return false; } - line = inFile->readLine(); //read out the header first and discard it. + line = inFile->readLine().toUpper(); //read out the header first and discard it. + if (line.at(23) == 'D') fileVersion = 2; //Dir is found starting at position 23 if this is a V2 file while (!inFile->atEnd()) { lineCounter++; @@ -236,11 +245,27 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector* frames) thisFrame.ID = tokens[1].toInt(NULL, 16); if (tokens[2].toUpper().contains("TRUE")) thisFrame.extended = 1; else thisFrame.extended = 0; - thisFrame.bus = tokens[3].toInt(); - thisFrame.len = tokens[4].toInt(); - for (int c = 0; c < 8; c++) thisFrame.data[c] = 0; - for (int d = 0; d < thisFrame.len; d++) - thisFrame.data[d] = tokens[5 + d].toInt(NULL, 16); + + if (fileVersion == 1) + { + thisFrame.isReceived = true; + thisFrame.bus = tokens[3].toInt(); + thisFrame.len = tokens[4].toInt(); + for (int c = 0; c < 8; c++) thisFrame.data[c] = 0; + for (int d = 0; d < thisFrame.len; d++) + thisFrame.data[d] = tokens[5 + d].toInt(NULL, 16); + } + else if (fileVersion == 2) + { + if (tokens[3].at(0) == 'R') thisFrame.isReceived = true; + else thisFrame.isReceived = false; + thisFrame.bus = tokens[4].toInt(); + thisFrame.len = tokens[5].toInt(); + for (int c = 0; c < 8; c++) thisFrame.data[c] = 0; + for (int d = 0; d < thisFrame.len; d++) + thisFrame.data[d] = tokens[6 + d].toInt(NULL, 16); + } + frames->append(thisFrame); } } @@ -260,7 +285,7 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector* f return false; } - outFile->write("Time Stamp,ID,Extended,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8"); + outFile->write("Time Stamp,ID,Extended,Dir,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8"); outFile->write("\n"); for (int c = 0; c < frames->count(); c++) @@ -281,6 +306,9 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector* f if (frames->at(c).extended) outFile->write("true,"); else outFile->write("false,"); + if (frames->at(c).isReceived) outFile->write("Rx,"); + else outFile->write("Tx,"); + outFile->write(QString::number(frames->at(c).bus).toUtf8()); outFile->putChar(44); @@ -449,7 +477,7 @@ bool FrameFileIO::loadLogFile(QString filename, QVector* frames) lineCounter = 0; } - line = inFile->readLine(); + line = inFile->readLine().toUpper(); if (line.startsWith("***")) continue; if (line.length() > 1) { @@ -458,6 +486,8 @@ bool FrameFileIO::loadLogFile(QString filename, QVector* frames) timeStamp = (timeToks[0].toInt() * (1000ul * 1000ul * 60ul * 60ul)) + (timeToks[1].toInt() * (1000ul * 1000ul * 60ul)) + (timeToks[2].toInt() * (1000ul * 1000ul)) + (timeToks[3].toInt() * 100ul); thisFrame.timestamp = timeStamp; + if (tokens[1].at(0) == 'R') thisFrame.isReceived = true; + else thisFrame.isReceived = false; thisFrame.ID = tokens[3].right(tokens[3].length() - 2).toInt(NULL, 16); if (tokens[4] == "s") thisFrame.extended = false; else thisFrame.extended = true; @@ -513,7 +543,8 @@ bool FrameFileIO::saveLogFile(QString filename, const QVector* frames) tempStamp = timestamp.addMSecs(frames->at(c).timestamp / 1000); outFile->write(tempStamp.toString("h:m:s:z").toUtf8()); - outFile->write(" Rx "); + if (frames->at(c).isReceived) outFile->write(" Rx "); + else outFile->write(" Tx "); outFile->write(QString::number(frames->at(c).bus).toUtf8() + " "); outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8()); if (frames->at(c).extended) outFile->write(" x "); @@ -549,7 +580,7 @@ bool FrameFileIO::loadMicrochipFile(QString filename, QVector* frames) CANFrame thisFrame; QByteArray line; bool inComment = false; - long long timeStamp = Utility::GetTimeMS(); + long long timeStamp; int lineCounter = 0; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) @@ -580,9 +611,10 @@ bool FrameFileIO::loadMicrochipFile(QString filename, QVector* frames) if (!inComment) { QList tokens = line.split(';'); - timeStamp += 5; + timeStamp = tokens[0].toInt() * 1000; thisFrame.timestamp = timeStamp; - + if (tokens[1].at(0) == 'R') thisFrame.isReceived = true; + else thisFrame.isReceived = false; thisFrame.ID = Utility::ParseStringToNum(tokens[2]); if (thisFrame.ID <= 0x7FF) thisFrame.extended = false; else thisFrame.extended = true; @@ -643,7 +675,8 @@ bool FrameFileIO::saveMicrochipFile(QString filename, const QVector* f } outFile->write(QString::number((int)(frames->at(c).timestamp / 1000)).toUtf8()); - outFile->write(";RX;"); + if (frames->at(c).isReceived) outFile->write(";RX;"); + else outFile->write(";TX;"); outFile->write("0x" + QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8() + ";"); outFile->write(QString::number(frames->at(c).len).toUtf8() + ";"); diff --git a/mainwindow.cpp b/mainwindow.cpp index e57d5ea..f656310 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -49,15 +49,13 @@ MainWindow::MainWindow(QWidget *parent) : readSettings(); - QStringList headers; - headers << "Timestamp" << "ID" << "Ext" << "Bus" << "Len" << "Data"; - //model->setHorizontalHeaderLabels(headers); ui->canFramesView->setColumnWidth(0, 110); ui->canFramesView->setColumnWidth(1, 70); ui->canFramesView->setColumnWidth(2, 40); ui->canFramesView->setColumnWidth(3, 40); ui->canFramesView->setColumnWidth(4, 40); - ui->canFramesView->setColumnWidth(5, 275); + ui->canFramesView->setColumnWidth(5, 40); + ui->canFramesView->setColumnWidth(6, 275); QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader(); HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview //enabling the below line kills performance in every way imaginable. Left here as a warning. Do not do this. @@ -500,7 +498,6 @@ void MainWindow::handleLoadFile() if (result) { model->insertFrames(tempFrames); - QStringList fileList = filename.split('/'); loadedFileName = fileList[fileList.length() - 1]; diff --git a/scriptcontainer.cpp b/scriptcontainer.cpp index c146800..5fb658f 100644 --- a/scriptcontainer.cpp +++ b/scriptcontainer.cpp @@ -58,8 +58,14 @@ void ScriptContainer::setErrorWidget(QListWidget *list) void ScriptContainer::setFilter(QJSValue id, QJSValue mask, QJSValue bus) { + uint32_t idVal = id.toUInt(); + uint32_t maskVal = mask.toUInt(); + int busVal = bus.toInt(); qDebug() << "Called set filter"; - qDebug() << id.toInt() << "*" << mask.toInt() << "*" << bus.toInt(); + qDebug() << idVal << "*" << maskVal << "*" << busVal; + CANFilter filter; + filter.setFilter(idVal, maskVal, busVal); + filters.append(filter); } void ScriptContainer::setTickInterval(QJSValue interval) @@ -77,6 +83,7 @@ void ScriptContainer::setTickInterval(QJSValue interval) void ScriptContainer::clearFilters() { qDebug() << "Called clear filters"; + filters.clear(); } void ScriptContainer::sendFrame(QJSValue id, QJSValue length, QJSValue data) @@ -84,6 +91,18 @@ void ScriptContainer::sendFrame(QJSValue id, QJSValue length, QJSValue data) qDebug() << "called send frame"; } +void ScriptContainer::gotFrame(const CANFrame &frame) +{ + for (int i = 0; i < filters.length(); i++) + { + if (filters[i].checkFilter(frame.ID, frame.bus)) + { + + return; //as soon as one filter matches we jump out + } + } +} + void ScriptContainer::tick() { if (tickFunction.isCallable()) diff --git a/scriptcontainer.h b/scriptcontainer.h index 09c4f90..fc354ba 100644 --- a/scriptcontainer.h +++ b/scriptcontainer.h @@ -1,6 +1,9 @@ #ifndef SCRIPTCONTAINER_H #define SCRIPTCONTAINER_H +#include "can_structs.h" +#include "canfilter.h" + #include #include #include @@ -11,6 +14,8 @@ class ScriptContainer : public QObject public: ScriptContainer(); + void gotFrame(const CANFrame &frame); + QString fileName; QString filePath; QString scriptText; @@ -34,6 +39,7 @@ private: QJSValue tickFunction; QTimer timer; QListWidget *errorWidget; + QList filters; }; #endif // SCRIPTCONTAINER_H diff --git a/serialworker.cpp b/serialworker.cpp index 9586c74..4b4ad23 100644 --- a/serialworker.cpp +++ b/serialworker.cpp @@ -155,11 +155,13 @@ void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0) QByteArray buffer; int c; int ID; + CANFrame tempFrame = *frame; + tempFrame.isReceived = false; //qDebug() << "Sending out frame with id " << frame->ID; - //show our sent frames in the list too. This happens even if we're not connected. - canModel->addFrame(*frame, false); + //show our sent frames in the list too. This happens even if we're not connected. + canModel->addFrame(tempFrame, false); gotFrames++; if (!connected) return; @@ -310,6 +312,7 @@ void SerialWorker::procRXChar(unsigned char c) //qDebug() << "emit from serial handler to main form id: " << buildFrame->ID; if (capturing) { + buildFrame->isReceived = true; canModel->addFrame(*buildFrame, false); gotFrames++; if (buildFrame->ID == targetID) emit gotTargettedFrame(canModel->rowCount() - 1); @@ -445,7 +448,7 @@ void SerialWorker::handleTick() emit frameUpdateTick(framesPerSec / 4, gotFrames); //sends stats to interested parties canModel->sendBulkRefresh(gotFrames); gotFrames = 0; - if (doValidation && connected) sendCommValidation(); + if (doValidation && serial) sendCommValidation(); } void SerialWorker::handleReconnect()