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.
This commit is contained in:
Collin Kidder
2015-12-01 20:25:52 -05:00
parent 0ff076de3a
commit f6b5db9617
8 changed files with 111 additions and 39 deletions
+1
View File
@@ -9,6 +9,7 @@ public:
int ID; int ID;
int bus; int bus;
bool extended; bool extended;
bool isReceived; //did we receive this or send it?
int len; int len;
unsigned char data[8]; unsigned char data[8];
uint64_t timestamp; uint64_t timestamp;
+24 -11
View File
@@ -17,7 +17,7 @@ int CANFrameModel::totalFrameCount()
int CANFrameModel::columnCount(const QModelIndex &index) const int CANFrameModel::columnCount(const QModelIndex &index) const
{ {
Q_UNUSED(index); Q_UNUSED(index);
return 6; return 7;
} }
CANFrameModel::CANFrameModel(QObject *parent) CANFrameModel::CANFrameModel(QObject *parent)
@@ -159,7 +159,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if (index.row() >= filteredFrames.count()) if (index.row() >= (filteredFrames.count()))
return QVariant(); return QVariant();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
@@ -168,7 +168,7 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
{ {
case 0: //timestamp case 0: //timestamp
if (!timeSeconds) return QString::number(thisFrame.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; break;
case 1: //id case 1: //id
return Utility::formatNumber(thisFrame.ID); return Utility::formatNumber(thisFrame.ID);
@@ -176,13 +176,17 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
case 2: //ext case 2: //ext
return QString::number(thisFrame.extended); return QString::number(thisFrame.extended);
break; 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); return QString::number(thisFrame.bus);
break; break;
case 4: //len case 5: //len
return QString::number(thisFrame.len); return QString::number(thisFrame.len);
break; break;
case 5: //data case 6: //data
for (int i = 0; i < thisFrame.len; i++) for (int i = 0; i < thisFrame.len; i++)
{ {
tempString.append(Utility::formatNumber(thisFrame.data[i])); tempString.append(Utility::formatNumber(thisFrame.data[i]));
@@ -234,12 +238,15 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
return QString(tr("Ext")); return QString(tr("Ext"));
break; break;
case 3: case 3:
return QString(tr("Bus")); return QString(tr("Dir"));
break; break;
case 4: case 4:
return QString(tr("Len")); return QString(tr("Bus"));
break; break;
case 5: case 5:
return QString(tr("Len"));
break;
case 6:
return QString(tr("Data")); return QString(tr("Data"));
break; break;
} }
@@ -385,6 +392,11 @@ void CANFrameModel::clearFrames()
*/ */
void CANFrameModel::insertFrames(const QVector<CANFrame> &newFrames) void CANFrameModel::insertFrames(const QVector<CANFrame> &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; int insertedFiltered = 0;
for (int i = 0; i < newFrames.count(); i++) for (int i = 0; i < newFrames.count(); i++)
{ {
@@ -400,9 +412,10 @@ void CANFrameModel::insertFrames(const QVector<CANFrame> &newFrames)
filteredFrames.append(newFrames[i]); filteredFrames.append(newFrames[i]);
} }
} }
mutex.unlock();
beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + insertedFiltered); //endResetModel();
endInsertRows(); //beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + insertedFiltered);
//endInsertRows();
if (needFilterRefresh) emit updatedFiltersList(); if (needFilterRefresh) emit updatedFiltersList();
} }
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef CONFIG #ifndef CONFIG
#define CONFIG #define CONFIG
#define VERSION 142 #define VERSION 143
//try to keep this in sync. //try to keep this in sync.
//SavvyCAN will complain if you connect a GVRET board with a revision //SavvyCAN will complain if you connect a GVRET board with a revision
+51 -18
View File
@@ -94,7 +94,7 @@ bool FrameFileIO::loadCRTDFile(QString filename, QVector<CANFrame>* frames)
return false; 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()) { while (!inFile->atEnd()) {
lineCounter++; lineCounter++;
@@ -121,11 +121,14 @@ bool FrameFileIO::loadCRTDFile(QString filename, QVector<CANFrame>* frames)
} }
//qDebug() << "decimal places " << decimalPlaces; //qDebug() << "decimal places " << decimalPlaces;
thisFrame.timestamp = (int64_t)(tokens[0].toDouble() * multiplier); 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); 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; else thisFrame.extended = false;
if (firstChar == 'T') thisFrame.isReceived = false;
else thisFrame.isReceived = true;
thisFrame.bus = 0; thisFrame.bus = 0;
thisFrame.len = tokens.length() - 3; thisFrame.len = tokens.length() - 3;
for (int d = 0; d < thisFrame.len; d++) for (int d = 0; d < thisFrame.len; d++)
@@ -171,11 +174,15 @@ bool FrameFileIO::saveCRTDFile(QString filename, const QVector<CANFrame>* frames
outFile->write(QString::number(frames->at(c).timestamp / 1000000.0, 'f', 6).toUtf8()); outFile->write(QString::number(frames->at(c).timestamp / 1000000.0, 'f', 6).toUtf8());
outFile->putChar(' '); outFile->putChar(' ');
if (frames->at(c).isReceived) outFile->putChar('R');
else outFile->putChar('T');
if (frames->at(c).extended) 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->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8());
outFile->putChar(' '); outFile->putChar(' ');
@@ -199,6 +206,7 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
QFile *inFile = new QFile(filename); QFile *inFile = new QFile(filename);
CANFrame thisFrame; CANFrame thisFrame;
QByteArray line; QByteArray line;
int fileVersion = 1;
long long timeStamp = Utility::GetTimeMS(); long long timeStamp = Utility::GetTimeMS();
int lineCounter = 0; int lineCounter = 0;
@@ -208,7 +216,8 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
return false; 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()) { while (!inFile->atEnd()) {
lineCounter++; lineCounter++;
@@ -236,11 +245,27 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
thisFrame.ID = tokens[1].toInt(NULL, 16); thisFrame.ID = tokens[1].toInt(NULL, 16);
if (tokens[2].toUpper().contains("TRUE")) thisFrame.extended = 1; if (tokens[2].toUpper().contains("TRUE")) thisFrame.extended = 1;
else thisFrame.extended = 0; else thisFrame.extended = 0;
thisFrame.bus = tokens[3].toInt();
thisFrame.len = tokens[4].toInt(); if (fileVersion == 1)
for (int c = 0; c < 8; c++) thisFrame.data[c] = 0; {
for (int d = 0; d < thisFrame.len; d++) thisFrame.isReceived = true;
thisFrame.data[d] = tokens[5 + d].toInt(NULL, 16); 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); frames->append(thisFrame);
} }
} }
@@ -260,7 +285,7 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector<CANFrame>* f
return false; 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"); outFile->write("\n");
for (int c = 0; c < frames->count(); c++) for (int c = 0; c < frames->count(); c++)
@@ -281,6 +306,9 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector<CANFrame>* f
if (frames->at(c).extended) outFile->write("true,"); if (frames->at(c).extended) outFile->write("true,");
else outFile->write("false,"); 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->write(QString::number(frames->at(c).bus).toUtf8());
outFile->putChar(44); outFile->putChar(44);
@@ -449,7 +477,7 @@ bool FrameFileIO::loadLogFile(QString filename, QVector<CANFrame>* frames)
lineCounter = 0; lineCounter = 0;
} }
line = inFile->readLine(); line = inFile->readLine().toUpper();
if (line.startsWith("***")) continue; if (line.startsWith("***")) continue;
if (line.length() > 1) if (line.length() > 1)
{ {
@@ -458,6 +486,8 @@ bool FrameFileIO::loadLogFile(QString filename, QVector<CANFrame>* frames)
timeStamp = (timeToks[0].toInt() * (1000ul * 1000ul * 60ul * 60ul)) + (timeToks[1].toInt() * (1000ul * 1000ul * 60ul)) timeStamp = (timeToks[0].toInt() * (1000ul * 1000ul * 60ul * 60ul)) + (timeToks[1].toInt() * (1000ul * 1000ul * 60ul))
+ (timeToks[2].toInt() * (1000ul * 1000ul)) + (timeToks[3].toInt() * 100ul); + (timeToks[2].toInt() * (1000ul * 1000ul)) + (timeToks[3].toInt() * 100ul);
thisFrame.timestamp = timeStamp; 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); thisFrame.ID = tokens[3].right(tokens[3].length() - 2).toInt(NULL, 16);
if (tokens[4] == "s") thisFrame.extended = false; if (tokens[4] == "s") thisFrame.extended = false;
else thisFrame.extended = true; else thisFrame.extended = true;
@@ -513,7 +543,8 @@ bool FrameFileIO::saveLogFile(QString filename, const QVector<CANFrame>* frames)
tempStamp = timestamp.addMSecs(frames->at(c).timestamp / 1000); tempStamp = timestamp.addMSecs(frames->at(c).timestamp / 1000);
outFile->write(tempStamp.toString("h:m:s:z").toUtf8()); 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).bus).toUtf8() + " ");
outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8()); outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8());
if (frames->at(c).extended) outFile->write(" x "); if (frames->at(c).extended) outFile->write(" x ");
@@ -549,7 +580,7 @@ bool FrameFileIO::loadMicrochipFile(QString filename, QVector<CANFrame>* frames)
CANFrame thisFrame; CANFrame thisFrame;
QByteArray line; QByteArray line;
bool inComment = false; bool inComment = false;
long long timeStamp = Utility::GetTimeMS(); long long timeStamp;
int lineCounter = 0; int lineCounter = 0;
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -580,9 +611,10 @@ bool FrameFileIO::loadMicrochipFile(QString filename, QVector<CANFrame>* frames)
if (!inComment) if (!inComment)
{ {
QList<QByteArray> tokens = line.split(';'); QList<QByteArray> tokens = line.split(';');
timeStamp += 5; timeStamp = tokens[0].toInt() * 1000;
thisFrame.timestamp = timeStamp; thisFrame.timestamp = timeStamp;
if (tokens[1].at(0) == 'R') thisFrame.isReceived = true;
else thisFrame.isReceived = false;
thisFrame.ID = Utility::ParseStringToNum(tokens[2]); thisFrame.ID = Utility::ParseStringToNum(tokens[2]);
if (thisFrame.ID <= 0x7FF) thisFrame.extended = false; if (thisFrame.ID <= 0x7FF) thisFrame.extended = false;
else thisFrame.extended = true; else thisFrame.extended = true;
@@ -643,7 +675,8 @@ bool FrameFileIO::saveMicrochipFile(QString filename, const QVector<CANFrame>* f
} }
outFile->write(QString::number((int)(frames->at(c).timestamp / 1000)).toUtf8()); 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("0x" + QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8() + ";");
outFile->write(QString::number(frames->at(c).len).toUtf8() + ";"); outFile->write(QString::number(frames->at(c).len).toUtf8() + ";");
+2 -5
View File
@@ -49,15 +49,13 @@ MainWindow::MainWindow(QWidget *parent) :
readSettings(); readSettings();
QStringList headers;
headers << "Timestamp" << "ID" << "Ext" << "Bus" << "Len" << "Data";
//model->setHorizontalHeaderLabels(headers);
ui->canFramesView->setColumnWidth(0, 110); ui->canFramesView->setColumnWidth(0, 110);
ui->canFramesView->setColumnWidth(1, 70); ui->canFramesView->setColumnWidth(1, 70);
ui->canFramesView->setColumnWidth(2, 40); ui->canFramesView->setColumnWidth(2, 40);
ui->canFramesView->setColumnWidth(3, 40); ui->canFramesView->setColumnWidth(3, 40);
ui->canFramesView->setColumnWidth(4, 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(); QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview 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. //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) if (result)
{ {
model->insertFrames(tempFrames); model->insertFrames(tempFrames);
QStringList fileList = filename.split('/'); QStringList fileList = filename.split('/');
loadedFileName = fileList[fileList.length() - 1]; loadedFileName = fileList[fileList.length() - 1];
+20 -1
View File
@@ -58,8 +58,14 @@ void ScriptContainer::setErrorWidget(QListWidget *list)
void ScriptContainer::setFilter(QJSValue id, QJSValue mask, QJSValue bus) 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() << "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) void ScriptContainer::setTickInterval(QJSValue interval)
@@ -77,6 +83,7 @@ void ScriptContainer::setTickInterval(QJSValue interval)
void ScriptContainer::clearFilters() void ScriptContainer::clearFilters()
{ {
qDebug() << "Called clear filters"; qDebug() << "Called clear filters";
filters.clear();
} }
void ScriptContainer::sendFrame(QJSValue id, QJSValue length, QJSValue data) 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"; 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() void ScriptContainer::tick()
{ {
if (tickFunction.isCallable()) if (tickFunction.isCallable())
+6
View File
@@ -1,6 +1,9 @@
#ifndef SCRIPTCONTAINER_H #ifndef SCRIPTCONTAINER_H
#define SCRIPTCONTAINER_H #define SCRIPTCONTAINER_H
#include "can_structs.h"
#include "canfilter.h"
#include <QJSEngine> #include <QJSEngine>
#include <QTimer> #include <QTimer>
#include <qlistwidget.h> #include <qlistwidget.h>
@@ -11,6 +14,8 @@ class ScriptContainer : public QObject
public: public:
ScriptContainer(); ScriptContainer();
void gotFrame(const CANFrame &frame);
QString fileName; QString fileName;
QString filePath; QString filePath;
QString scriptText; QString scriptText;
@@ -34,6 +39,7 @@ private:
QJSValue tickFunction; QJSValue tickFunction;
QTimer timer; QTimer timer;
QListWidget *errorWidget; QListWidget *errorWidget;
QList<CANFilter> filters;
}; };
#endif // SCRIPTCONTAINER_H #endif // SCRIPTCONTAINER_H
+6 -3
View File
@@ -155,11 +155,13 @@ void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
QByteArray buffer; QByteArray buffer;
int c; int c;
int ID; int ID;
CANFrame tempFrame = *frame;
tempFrame.isReceived = false;
//qDebug() << "Sending out frame with id " << frame->ID; //qDebug() << "Sending out frame with id " << frame->ID;
//show our sent frames in the list too. This happens even if we're not connected. //show our sent frames in the list too. This happens even if we're not connected.
canModel->addFrame(*frame, false); canModel->addFrame(tempFrame, false);
gotFrames++; gotFrames++;
if (!connected) return; if (!connected) return;
@@ -310,6 +312,7 @@ void SerialWorker::procRXChar(unsigned char c)
//qDebug() << "emit from serial handler to main form id: " << buildFrame->ID; //qDebug() << "emit from serial handler to main form id: " << buildFrame->ID;
if (capturing) if (capturing)
{ {
buildFrame->isReceived = true;
canModel->addFrame(*buildFrame, false); canModel->addFrame(*buildFrame, false);
gotFrames++; gotFrames++;
if (buildFrame->ID == targetID) emit gotTargettedFrame(canModel->rowCount() - 1); 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 emit frameUpdateTick(framesPerSec / 4, gotFrames); //sends stats to interested parties
canModel->sendBulkRefresh(gotFrames); canModel->sendBulkRefresh(gotFrames);
gotFrames = 0; gotFrames = 0;
if (doValidation && connected) sendCommValidation(); if (doValidation && serial) sendCommValidation();
} }
void SerialWorker::handleReconnect() void SerialWorker::handleReconnect()