Merge pull request #141 from collin80/WIP

Wip
This commit is contained in:
Collin Kidder
2018-06-04 19:40:49 -04:00
committed by GitHub
7 changed files with 118 additions and 40 deletions
+31 -3
View File
@@ -11,7 +11,6 @@ BLFHandler::BLFHandler()
} }
/* /*
Written while peeking at source code here: Written while peeking at source code here:
https://python-can.readthedocs.io/en/latest/_modules/can/io/blf.html https://python-can.readthedocs.io/en/latest/_modules/can/io/blf.html
@@ -38,28 +37,44 @@ bool BLFHandler::loadBLF(QString filename, QVector<CANFrame>* frames)
inFile->read((char *)&header, sizeof(header)); inFile->read((char *)&header, sizeof(header));
if (qFromLittleEndian(header.sig) == 0x47474F4C) if (qFromLittleEndian(header.sig) == 0x47474F4C)
{ {
qDebug() << "Proper BLF file header token";
} }
else return false; else return false;
while (!inFile->atEnd()) while (!inFile->atEnd())
{ {
qDebug() << "Position within file: " << inFile->pos();
inFile->read((char *)&objHeader, sizeof(objHeader)); inFile->read((char *)&objHeader, sizeof(objHeader));
if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C) if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C)
{ {
int readSize = objHeader.objSize - sizeof(BLF_OBJ_HEADER); int readSize = objHeader.objSize - sizeof(BLF_OBJ_HEADER);
qDebug() << "Proper object header token. Read Size: " << readSize;
fileData = inFile->read(readSize); fileData = inFile->read(readSize);
junk = inFile->read(readSize % 4); //file is padded so sizes must always end up on even multiple of 4 junk = inFile->read(readSize % 4); //file is padded so sizes must always end up on even multiple of 4
//qDebug() << "Fudge bytes in readSize: " << (readSize % 4);
if (objHeader.objType == BLF_CONTAINER) if (objHeader.objType == BLF_CONTAINER)
{ {
qDebug() << "Object is a container. Uncompressing it";
fileData.prepend(objHeader.uncompSize & 0xFF); fileData.prepend(objHeader.uncompSize & 0xFF);
fileData.prepend((objHeader.uncompSize >> 8) & 0xFF); fileData.prepend((objHeader.uncompSize >> 8) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 16) & 0xFF); fileData.prepend((objHeader.uncompSize >> 16) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 24) & 0xFF); fileData.prepend((objHeader.uncompSize >> 24) & 0xFF);
uncompressedData += qUncompress(fileData); uncompressedData += qUncompress(fileData);
qDebug() << "Uncompressed size: " << uncompressedData.count();
pos = 0; pos = 0;
while (pos + sizeof(BLF_OBJ_HEADER) < uncompressedData.count()) bool foundHeader = false;
//first skip forward to find a header signature - usually not necessary
while ( (int)(pos + sizeof(BLF_OBJ_HEADER)) < uncompressedData.count())
{ {
memcpy(&obj.header, uncompressedData.mid(pos, sizeof(BLF_OBJ_HEADER)).constData(), sizeof(BLF_OBJ_HEADER)); int32_t *headerSig = (int32_t *)(uncompressedData.constData() + pos);
if (*headerSig == 0x4A424F4C) break;
pos += 4;
}
//then process all the objects
while ( (int)(pos + sizeof(BLF_OBJ_HEADER)) < uncompressedData.count())
{
memcpy(&obj.header, (uncompressedData.constData() + pos), sizeof(BLF_OBJ_HEADER));
qDebug() << "Pos: " << pos << " Type: " << obj.header.objType << "Obj Size: " << obj.header.objSize;
if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C) if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C)
{ {
fileData = uncompressedData.mid(pos + sizeof(BLF_OBJ_HEADER), obj.header.objSize - sizeof(BLF_OBJ_HEADER)); fileData = uncompressedData.mid(pos + sizeof(BLF_OBJ_HEADER), obj.header.objSize - sizeof(BLF_OBJ_HEADER));
@@ -72,6 +87,7 @@ bool BLFHandler::loadBLF(QString filename, QVector<CANFrame>* frames)
frame.ID = canObject.id & 0x1FFFFFFFull; frame.ID = canObject.id & 0x1FFFFFFFull;
frame.isReceived = true; frame.isReceived = true;
frame.len = canObject.dlc; frame.len = canObject.dlc;
if (canObject.flags & BLF_REMOTE_FLAG) { if (canObject.flags & BLF_REMOTE_FLAG) {
frame.remote = true; frame.remote = true;
} else { } else {
@@ -81,10 +97,22 @@ bool BLFHandler::loadBLF(QString filename, QVector<CANFrame>* frames)
frame.timestamp = obj.header.uncompSize / 1000000.0; //uncompsize field also used for timestamp oddly enough frame.timestamp = obj.header.uncompSize / 1000000.0; //uncompsize field also used for timestamp oddly enough
frames->append(frame); frames->append(frame);
} }
else
{
//qDebug() << "Not a can frame! ObjType: " << obj.header.objType;
if (obj.header.objType > 0xFFFF)
return false;
}
pos += obj.header.objSize + (obj.header.objSize % 4); pos += obj.header.objSize + (obj.header.objSize % 4);
} }
else
{
qDebug() << "Unexpected object header signature, aborting";
return false;
}
} }
uncompressedData.remove(0, pos); uncompressedData.remove(0, pos);
qDebug() << "After removing used data uncompressedData is now this big: " << uncompressedData.count();
} }
} }
else return false; else return false;
+9 -9
View File
@@ -37,15 +37,15 @@ struct BLF_FILE_HEADER
struct BLF_OBJ_HEADER struct BLF_OBJ_HEADER
{ {
uint32_t sig; uint32_t sig; //0 offset from start
uint16_t headerSize; uint16_t headerSize; //4
uint16_t headerVersion; uint16_t headerVersion; //6
uint32_t objSize; uint32_t objSize; //8
uint32_t objType; uint32_t objType; //12
uint32_t flags; uint32_t flags; //16
uint16_t nothing; uint16_t nothing; //20
uint16_t objVer; uint16_t objVer; //22
uint64_t uncompSize; uint64_t uncompSize; //24
}; //32 bytes }; //32 bytes
struct BLF_OBJECT struct BLF_OBJECT
+17 -3
View File
@@ -61,7 +61,7 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, QWidge
connect(ui->spinBurstSpeed, SIGNAL(valueChanged(int)), this, SLOT(changeBurstRate(int))); connect(ui->spinBurstSpeed, SIGNAL(valueChanged(int)), this, SLOT(changeBurstRate(int)));
//connect(ui->cbLoop, SIGNAL(clicked(bool)), this, SLOT(changeLooping(bool))); //connect(ui->cbLoop, SIGNAL(clicked(bool)), this, SLOT(changeLooping(bool)));
connect(ui->comboCANBus, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSendingBus(int))); connect(ui->comboCANBus, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSendingBus(int)));
connect(ui->listID, &QListWidget::itemClicked, this, &FramePlaybackWindow::changeIDFiltering); connect(ui->listID, &QListWidget::itemChanged, this, &FramePlaybackWindow::changeIDFiltering);
connect(ui->btnLoadFile, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadFile); connect(ui->btnLoadFile, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadFile);
connect(ui->btnLoadLive, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadLive); connect(ui->btnLoadLive, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadLive);
connect(ui->tblSequence, &QTableWidget::cellPressed, this, &FramePlaybackWindow::seqTableCellClicked); connect(ui->tblSequence, &QTableWidget::cellPressed, this, &FramePlaybackWindow::seqTableCellClicked);
@@ -95,6 +95,15 @@ void FramePlaybackWindow::showEvent(QShowEvent *)
{ {
readSettings(); readSettings();
installEventFilter(this); installEventFilter(this);
int numBuses = CANConManager::getInstance()->getNumBuses();
ui->comboCANBus->clear();
for (int n = 0; n < numBuses; n++) ui->comboCANBus->addItem(QString::number(n));
ui->comboCANBus->addItem(tr("All"));
ui->comboCANBus->addItem(tr("From File"));
ui->comboCANBus->setCurrentIndex(0);
playbackObject.initialize();
playbackObject.setNumBuses(numBuses);
} }
void FramePlaybackWindow::closeEvent(QCloseEvent *event) void FramePlaybackWindow::closeEvent(QCloseEvent *event)
@@ -264,6 +273,9 @@ void FramePlaybackWindow::refreshIDList()
ui->tblSequence->setCurrentCell(currentSeqNum, 0); ui->tblSequence->setCurrentCell(currentSeqNum, 0);
//this signal would otherwise be called constantly as we do this routine. Turn it off temporarily
disconnect(ui->listID, &QListWidget::itemChanged, this, &FramePlaybackWindow::changeIDFiltering);
ui->listID->clear(); ui->listID->clear();
QHash<int, bool>::Iterator filterIter; QHash<int, bool>::Iterator filterIter;
@@ -276,6 +288,8 @@ void FramePlaybackWindow::refreshIDList()
} }
//default is to sort in ascending order //default is to sort in ascending order
ui->listID->sortItems(); ui->listID->sortItems();
connect(ui->listID, &QListWidget::itemChanged, this, &FramePlaybackWindow::changeIDFiltering);
} }
void FramePlaybackWindow::calculateWhichBus() void FramePlaybackWindow::calculateWhichBus()
@@ -579,9 +593,9 @@ void FramePlaybackWindow::changeSendingBus(int newIdx)
void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item) void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item)
{ {
qDebug() << "Changed ID filter"; qDebug() << "Changed ID filter " << item->text() << " : " << item->checkState();
int ID = Utility::ParseStringToNum(item->text()); int ID = Utility::ParseStringToNum(item->text());
currentSeqItem->idFilters[ID] = item->checkState(); currentSeqItem->idFilters[ID] = (item->checkState() == Qt::Checked) ? true : false;
} }
void FramePlaybackWindow::btnSelectAllClick() void FramePlaybackWindow::btnSelectAllClick()
+1 -1
View File
@@ -838,7 +838,7 @@ void FrameSenderWindow::processCellChange(int line, int col)
break; break;
case 2: //ID field case 2: //ID field
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 2)->text()); tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 2)->text());
if (tempVal < 1) tempVal = 1; if (tempVal < 0) tempVal = 0;
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF; if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
sendingData[line].ID = tempVal; sendingData[line].ID = tempVal;
if (sendingData[line].ID > 0x7FF) { if (sendingData[line].ID > 0x7FF) {
+6 -1
View File
@@ -161,7 +161,10 @@ MainWindow::MainWindow(QWidget *parent) :
temp.ID = 0x100; temp.ID = 0x100;
temp.len = 0; temp.len = 0;
model->addFrame(temp, true); model->addFrame(temp, true);
qApp->processEvents();
tickGUIUpdate(); //force a GUI refresh so that the row exists to measure
normalRowHeight = ui->canFramesView->rowHeight(0); normalRowHeight = ui->canFramesView->rowHeight(0);
if (normalRowHeight == 0) normalRowHeight = 30; //should not be necessary but provides a sane number if something stupid happened.
qDebug() << "normal row height = " << normalRowHeight; qDebug() << "normal row height = " << normalRowHeight;
model->clearFrames(); model->clearFrames();
@@ -172,10 +175,12 @@ MainWindow::MainWindow(QWidget *parent) :
connectionWindow = new ConnectionWindow(); connectionWindow = new ConnectionWindow();
connect(this, SIGNAL(suspendCapturing(bool)), connectionWindow, SLOT(setSuspendAll(bool))); connect(this, SIGNAL(suspendCapturing(bool)), connectionWindow, SLOT(setSuspendAll(bool)));
//these either are unfinished/not working or are not for general use. But,they exist
//so if you want to enable them and play with them then go for it.
ui->actionFirmware_Update->setVisible(false); ui->actionFirmware_Update->setVisible(false);
ui->actionMotorControlConfig->setVisible(false); ui->actionMotorControlConfig->setVisible(false);
ui->actionSignal_Viewer->setVisible(false); ui->actionSignal_Viewer->setVisible(false);
ui->actionSingle_Multi_State_2->setVisible(false); //ui->actionSingle_Multi_State_2->setVisible(false);
installEventFilter(this); installEventFilter(this);
} }
+50 -20
View File
@@ -194,11 +194,22 @@ void RangeStateWindow::refreshFilterList()
void RangeStateWindow::recalcButton() void RangeStateWindow::recalcButton()
{ {
QHash<int, bool>::iterator iter; QMap<int, bool>::iterator iter;
uint32_t id; uint32_t id;
ui->listCandidates->clear(); ui->listCandidates->clear();
foundSignals.clear(); foundSignals.clear();
ui->graphSignal->clearGraphs();
QProgressDialog progress(qApp->activeWindow());
progress.setWindowModality(Qt::WindowModal);
progress.setLabelText("Calculating");
progress.setCancelButton(0);
progress.setRange(0,0);
progress.setMinimumDuration(0);
progress.show();
for (iter = idFilters.begin(); iter != idFilters.end(); ++iter) for (iter = idFilters.begin(); iter != idFilters.end(); ++iter)
{ {
@@ -218,6 +229,7 @@ void RangeStateWindow::recalcButton()
} }
} }
progress.cancel();
qDebug() << "Found " << foundSignals.count() << " signals total."; qDebug() << "Found " << foundSignals.count() << " signals total.";
} }
@@ -237,8 +249,9 @@ void RangeStateWindow::signalsFactory()
int maxBits = frameCache.at(0).len * 8; int maxBits = frameCache.at(0).len * 8;
int sens = ui->slideSensitivity->value(); int sens = ui->slideSensitivity->value();
for (int sigSize = maxSig; sigSize >= minSig; sigSize--) for (int sigSize = maxSig; sigSize >= minSig; sigSize -= granularity)
{ {
qApp->processEvents();
for (int startBit = 0; startBit < maxBits; startBit += granularity) for (int startBit = 0; startBit < maxBits; startBit += granularity)
{ {
if (sigType & 1) if (sigType & 1)
@@ -272,7 +285,7 @@ bool RangeStateWindow::processSignal(int startBit, int bitLength, int sensitivit
int64_t valu; int64_t valu;
int64_t highestValue = -1000000000000LL; int64_t highestValue = -1000000000000LL;
int64_t lowestValue = 1000000000000LL; int64_t lowestValue = 1000000000000LL;
double multiplier; double lerpPoint = ((double)sensitivity - 10.0) / 240.0;
int numFrames = frameCache.count(); int numFrames = frameCache.count();
scaledVals.reserve(frameCache.count()); scaledVals.reserve(frameCache.count());
@@ -292,17 +305,17 @@ bool RangeStateWindow::processSignal(int startBit, int bitLength, int sensitivit
if (lowestValue == highestValue) return false; //a signal that never changes is worthless and not a range signal if (lowestValue == highestValue) return false; //a signal that never changes is worthless and not a range signal
//multiplier is calculated such that the range of the signal is scaled down to the value of sensitivity. int64_t range = highestValue - lowestValue;
//so, if we have a sensitivity of 50 then the range is scaled so that it is 50
//this has the effect of smoothing the data a bit by completely removing the fine detail. It's irrelevant to
//an algorithm like this anyway and just gets in the way.
//Also, we're going to offset by lowest value so that everything is based at a value of 0 as the low end.
//All of this drastically modifies the actual signal but that's OK, we're looking for patterns here not
//being faithful to the signal (what a dirty cheater)
int range = highestValue - lowestValue;
multiplier = (double)sensitivity / (double)range;
for (i = 0; i < numFrames; i++) scaledVals.append((int)((Utility::processIntegerSignal(frameCache.at(i).data, startBit, bitLength, !bigEndian, isSigned) - lowestValue) * multiplier)); int64_t maxRange = isSigned?(1<<(bitLength - 1)):(1 << bitLength);
//at highest sensitivity require signal to at least range 20% of max range
//at lowest sensitivity require signal to at least range 1% of max range
int64_t requiredRange = Utility::Lerp(maxRange * 0.01, maxRange * 0.2, lerpPoint);
if (range < requiredRange)
return false; //doesn't range enough.
for (i = 0; i < numFrames; i++)
scaledVals.append((int)((Utility::processIntegerSignal(frameCache.at(i).data, startBit, bitLength, !bigEndian, isSigned) - lowestValue)));
for (i = 1; i < numFrames; i++) for (i = 1; i < numFrames; i++)
{ {
@@ -316,19 +329,36 @@ bool RangeStateWindow::processSignal(int startBit, int bitLength, int sensitivit
diff2.append(valu); diff2.append(valu);
} }
//now the differences are all stored so let's go through and see if they seem to suggest a ramping sort of signal or not. //now the differences are all stored so let's go through and see if first order diffs seem to suggest a ramping sort of signal or not.
//for a first test lets let through any signal where the acceleration values are all much smaller than the signal range //for a first test lets let through any signal where the first order diff doesn't seem too large
bool isGood = true; bool isGood = true;
int comparisonValue = Utility::Lerp(sensitivity / 5, sensitivity / 40, (sensitivity - 10) / 240.0); int comparisonValue = Utility::Lerp((double)range * 0.55, 0, lerpPoint);
qDebug() << "range: " << sensitivity << " comparisonvalue: " << comparisonValue; qDebug() << " 1st Delta comparisonvalue: " << comparisonValue;
int overValues = 0; int overValues = 0;
for (i = 0; i < diff2.count(); i++) for (i = 0; i < diff1.count(); i++)
{ {
if (abs(diff1[i]) > comparisonValue) overValues++; if (abs(diff1[i]) > comparisonValue) overValues++;
} }
int maxOvers = Utility::Lerp(4, numFrames / 50.0, 1.0 - ((sensitivity -10) / 240.0)); int maxOvers = Utility::Lerp(numFrames / 30.0, 2, lerpPoint);
qDebug() << "Max Overs: " << maxOvers; qDebug() << "1st order overages: " << overValues << " Max Overs: " << maxOvers;
if (overValues > maxOvers) isGood = false; if (overValues > maxOvers) isGood = false;
if (isGood)
{
//now look at the second order differentials. This is acceleration. There shouldn't be hard acceleration in values for a ranging signal
comparisonValue = Utility::Lerp((double)range * 0.20, 1, lerpPoint);
maxOvers = Utility::Lerp(8, 2, lerpPoint); //really clamp down on second order over limits
qDebug() << "2nd Delta comparisonvalue: " << comparisonValue;
overValues = 0;
for (i = 0; i < diff2.count(); i++)
{
if (abs(diff2[i]) > comparisonValue) overValues++;
}
if (overValues > maxOvers) isGood = false;
qDebug() << "2nd order overages: " << overValues << " Max Overs: " << maxOvers;
if (overValues > maxOvers) isGood = false;
}
qDebug() << "Is this signal good: " << isGood << " Num overs: " << overValues; qDebug() << "Is this signal good: " << isGood << " Num overs: " << overValues;
if (isGood) if (isGood)
{ {
+2 -1
View File
@@ -2,6 +2,7 @@
#define RANGESTATEWINDOW_H #define RANGESTATEWINDOW_H
#include <QDialog> #include <QDialog>
#include <QMap>
#include "can_structs.h" #include "can_structs.h"
namespace Ui { namespace Ui {
@@ -27,7 +28,7 @@ private:
const QVector<CANFrame> *modelFrames; const QVector<CANFrame> *modelFrames;
QVector<CANFrame> frameCache; QVector<CANFrame> frameCache;
QList<int64_t> foundSignals; QList<int64_t> foundSignals;
QHash<int, bool> idFilters; QMap<int, bool> idFilters;
void refreshFilterList(); void refreshFilterList();
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);