diff --git a/blfhandler.cpp b/blfhandler.cpp index 41ada14..439c2ef 100644 --- a/blfhandler.cpp +++ b/blfhandler.cpp @@ -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* 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* 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* 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; diff --git a/blfhandler.h b/blfhandler.h index fc334c1..fb158c0 100644 --- a/blfhandler.h +++ b/blfhandler.h @@ -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 diff --git a/frameplaybackwindow.cpp b/frameplaybackwindow.cpp index 7d74e24..f303f9b 100644 --- a/frameplaybackwindow.cpp +++ b/frameplaybackwindow.cpp @@ -61,7 +61,7 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector *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::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() diff --git a/framesenderwindow.cpp b/framesenderwindow.cpp index d74cddb..5d69e01 100644 --- a/framesenderwindow.cpp +++ b/framesenderwindow.cpp @@ -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) { diff --git a/mainwindow.cpp b/mainwindow.cpp index 2d4b6e7..6a34cc2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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); } diff --git a/re/rangestatewindow.cpp b/re/rangestatewindow.cpp index 511e9ab..840b6d6 100644 --- a/re/rangestatewindow.cpp +++ b/re/rangestatewindow.cpp @@ -194,11 +194,22 @@ void RangeStateWindow::refreshFilterList() void RangeStateWindow::recalcButton() { - QHash::iterator iter; + QMap::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) { diff --git a/re/rangestatewindow.h b/re/rangestatewindow.h index 193e052..b4db783 100644 --- a/re/rangestatewindow.h +++ b/re/rangestatewindow.h @@ -2,6 +2,7 @@ #define RANGESTATEWINDOW_H #include +#include #include "can_structs.h" namespace Ui { @@ -27,7 +28,7 @@ private: const QVector *modelFrames; QVector frameCache; QList foundSignals; - QHash idFilters; + QMap idFilters; void refreshFilterList(); void closeEvent(QCloseEvent *event);