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:
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));
if (qFromLittleEndian(header.sig) == 0x47474F4C)
{
qDebug() << "Proper BLF file header token";
}
else return false;
while (!inFile->atEnd())
{
qDebug() << "Position within file: " << inFile->pos();
inFile->read((char *)&objHeader, sizeof(objHeader));
if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C)
{
int readSize = objHeader.objSize - sizeof(BLF_OBJ_HEADER);
qDebug() << "Proper object header token. Read Size: " << readSize;
fileData = inFile->read(readSize);
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)
{
qDebug() << "Object is a container. Uncompressing it";
fileData.prepend(objHeader.uncompSize & 0xFF);
fileData.prepend((objHeader.uncompSize >> 8) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 16) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 24) & 0xFF);
uncompressedData += qUncompress(fileData);
qDebug() << "Uncompressed size: " << uncompressedData.count();
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)
{
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.isReceived = true;
frame.len = canObject.dlc;
if (canObject.flags & BLF_REMOTE_FLAG) {
frame.remote = true;
} 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
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);
}
else
{
qDebug() << "Unexpected object header signature, aborting";
return false;
}
}
uncompressedData.remove(0, pos);
qDebug() << "After removing used data uncompressedData is now this big: " << uncompressedData.count();
}
}
else return false;
+9 -9
View File
@@ -37,15 +37,15 @@ struct BLF_FILE_HEADER
struct BLF_OBJ_HEADER
{
uint32_t sig;
uint16_t headerSize;
uint16_t headerVersion;
uint32_t objSize;
uint32_t objType;
uint32_t flags;
uint16_t nothing;
uint16_t objVer;
uint64_t uncompSize;
uint32_t sig; //0 offset from start
uint16_t headerSize; //4
uint16_t headerVersion; //6
uint32_t objSize; //8
uint32_t objType; //12
uint32_t flags; //16
uint16_t nothing; //20
uint16_t objVer; //22
uint64_t uncompSize; //24
}; //32 bytes
struct BLF_OBJECT
+18 -4
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->cbLoop, SIGNAL(clicked(bool)), this, SLOT(changeLooping(bool)));
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->btnLoadLive, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadLive);
connect(ui->tblSequence, &QTableWidget::cellPressed, this, &FramePlaybackWindow::seqTableCellClicked);
@@ -95,6 +95,15 @@ void FramePlaybackWindow::showEvent(QShowEvent *)
{
readSettings();
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)
@@ -264,6 +273,9 @@ void FramePlaybackWindow::refreshIDList()
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();
QHash<int, bool>::Iterator filterIter;
@@ -276,6 +288,8 @@ void FramePlaybackWindow::refreshIDList()
}
//default is to sort in ascending order
ui->listID->sortItems();
connect(ui->listID, &QListWidget::itemChanged, this, &FramePlaybackWindow::changeIDFiltering);
}
void FramePlaybackWindow::calculateWhichBus()
@@ -579,9 +593,9 @@ void FramePlaybackWindow::changeSendingBus(int newIdx)
void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item)
{
qDebug() << "Changed ID filter";
int ID = Utility::ParseStringToNum(item->text());
currentSeqItem->idFilters[ID] = item->checkState();
qDebug() << "Changed ID filter " << item->text() << " : " << item->checkState();
int ID = Utility::ParseStringToNum(item->text());
currentSeqItem->idFilters[ID] = (item->checkState() == Qt::Checked) ? true : false;
}
void FramePlaybackWindow::btnSelectAllClick()
+1 -1
View File
@@ -838,7 +838,7 @@ void FrameSenderWindow::processCellChange(int line, int col)
break;
case 2: //ID field
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 2)->text());
if (tempVal < 1) tempVal = 1;
if (tempVal < 0) tempVal = 0;
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
sendingData[line].ID = tempVal;
if (sendingData[line].ID > 0x7FF) {
+6 -1
View File
@@ -161,7 +161,10 @@ MainWindow::MainWindow(QWidget *parent) :
temp.ID = 0x100;
temp.len = 0;
model->addFrame(temp, true);
qApp->processEvents();
tickGUIUpdate(); //force a GUI refresh so that the row exists to measure
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;
model->clearFrames();
@@ -172,10 +175,12 @@ MainWindow::MainWindow(QWidget *parent) :
connectionWindow = new ConnectionWindow();
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->actionMotorControlConfig->setVisible(false);
ui->actionSignal_Viewer->setVisible(false);
ui->actionSingle_Multi_State_2->setVisible(false);
//ui->actionSingle_Multi_State_2->setVisible(false);
installEventFilter(this);
}
+51 -21
View File
@@ -194,11 +194,22 @@ void RangeStateWindow::refreshFilterList()
void RangeStateWindow::recalcButton()
{
QHash<int, bool>::iterator iter;
QMap<int, bool>::iterator iter;
uint32_t id;
ui->listCandidates->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)
{
@@ -214,10 +225,11 @@ void RangeStateWindow::recalcButton()
if (modelFrames->at(j).ID == id) frameCache.append(modelFrames->at(j));
}
//now we've got a list with all the same ID. Time to send it off for processing
signalsFactory();
signalsFactory();
}
}
progress.cancel();
qDebug() << "Found " << foundSignals.count() << " signals total.";
}
@@ -237,8 +249,9 @@ void RangeStateWindow::signalsFactory()
int maxBits = frameCache.at(0).len * 8;
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)
{
if (sigType & 1)
@@ -272,7 +285,7 @@ bool RangeStateWindow::processSignal(int startBit, int bitLength, int sensitivit
int64_t valu;
int64_t highestValue = -1000000000000LL;
int64_t lowestValue = 1000000000000LL;
double multiplier;
double lerpPoint = ((double)sensitivity - 10.0) / 240.0;
int numFrames = 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
//multiplier is calculated such that the range of the signal is scaled down to the value of sensitivity.
//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;
int64_t range = highestValue - lowestValue;
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++)
{
@@ -316,19 +329,36 @@ bool RangeStateWindow::processSignal(int startBit, int bitLength, int sensitivit
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.
//for a first test lets let through any signal where the acceleration values are all much smaller than the signal range
//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 first order diff doesn't seem too large
bool isGood = true;
int comparisonValue = Utility::Lerp(sensitivity / 5, sensitivity / 40, (sensitivity - 10) / 240.0);
qDebug() << "range: " << sensitivity << " comparisonvalue: " << comparisonValue;
int comparisonValue = Utility::Lerp((double)range * 0.55, 0, lerpPoint);
qDebug() << " 1st Delta comparisonvalue: " << comparisonValue;
int overValues = 0;
for (i = 0; i < diff2.count(); i++)
for (i = 0; i < diff1.count(); i++)
{
if (abs(diff1[i]) > comparisonValue) overValues++;
}
int maxOvers = Utility::Lerp(4, numFrames / 50.0, 1.0 - ((sensitivity -10) / 240.0));
qDebug() << "Max Overs: " << maxOvers;
int maxOvers = Utility::Lerp(numFrames / 30.0, 2, lerpPoint);
qDebug() << "1st order overages: " << overValues << " Max Overs: " << maxOvers;
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;
if (isGood)
{
+2 -1
View File
@@ -2,6 +2,7 @@
#define RANGESTATEWINDOW_H
#include <QDialog>
#include <QMap>
#include "can_structs.h"
namespace Ui {
@@ -27,7 +28,7 @@ private:
const QVector<CANFrame> *modelFrames;
QVector<CANFrame> frameCache;
QList<int64_t> foundSignals;
QHash<int, bool> idFilters;
QMap<int, bool> idFilters;
void refreshFilterList();
void closeEvent(QCloseEvent *event);