From 0f3f9e0fad44d2978d5e3daccd972dbd289d842d Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Sun, 18 Dec 2016 21:40:56 -0500 Subject: [PATCH] Unified time base now so both GVRET and Socketcan devices yield timestamps in microseconds since the program started or clear was pressed, fixed frames per second display, fixed timestamps for sent frames --- connections/canconmanager.cpp | 13 +++++++++ connections/canconmanager.h | 4 +++ connections/gvretserial.cpp | 52 +++++++++++++++++++++++------------ connections/gvretserial.h | 8 +++--- connections/socketcan.cpp | 4 ++- connections/socketcan.h | 1 + mainwindow.cpp | 7 +++-- 7 files changed, 63 insertions(+), 26 deletions(-) diff --git a/connections/canconmanager.cpp b/connections/canconmanager.cpp index 4092f86..008ee03 100644 --- a/connections/canconmanager.cpp +++ b/connections/canconmanager.cpp @@ -1,3 +1,5 @@ +#include + #include "canconmanager.h" @@ -18,8 +20,14 @@ CANConManager::CANConManager(QObject *parent): QObject(parent) mTimer.setInterval(250); /*tick 4 times a second */ mTimer.setSingleShot(false); mTimer.start(); + + resetTimeBasis(); } +void CANConManager::resetTimeBasis() +{ + mTimestampBasis = QDateTime::currentMSecsSinceEpoch() * 1000; +} CANConManager::~CANConManager() { @@ -70,6 +78,10 @@ void CANConManager::refreshCanList() } } +uint64_t CANConManager::getTimeBasis() +{ + return mTimestampBasis; +} QList& CANConManager::getConnections() { @@ -139,6 +151,7 @@ bool CANConManager::sendFrame(const CANFrame& pFrame) { workingFrame.bus -= busBase; workingFrame.isReceived = false; + workingFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() * 1000) - mTimestampBasis); txFrame = conn->getQueue().get(); *txFrame = workingFrame; conn->getQueue().queue(); diff --git a/connections/canconmanager.h b/connections/canconmanager.h index d9c7e40..dc94431 100644 --- a/connections/canconmanager.h +++ b/connections/canconmanager.h @@ -20,6 +20,9 @@ public: CANConnection* getByName(const QString& pName) const; + uint64_t getTimeBasis(); + void resetTimeBasis(); + int getNumBuses(); /** @@ -46,6 +49,7 @@ private: static CANConManager* mInstance; QList mConns; QTimer mTimer; + uint64_t mTimestampBasis; }; #endif // CANCONNECTIONMODEL_H diff --git a/connections/gvretserial.cpp b/connections/gvretserial.cpp index c76a5ee..90a79a1 100644 --- a/connections/gvretserial.cpp +++ b/connections/gvretserial.cpp @@ -18,7 +18,8 @@ GVRetSerial::GVRetSerial(QString portName) : gotValidated = true; isAutoRestart = false; - txTimestampBasis = QDateTime::currentMSecsSinceEpoch(); + timeBasis = 0; + lastSystemTimeBasis = 0; readSettings(); } @@ -147,18 +148,10 @@ bool GVRetSerial::piSendFrame(const CANFrame& frame) int c; int ID; CANFrame tempFrame = frame; - tempFrame.isReceived = false; - tempFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() - txTimestampBasis) * 1000); + 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. - /* model lives in UI thread, we need to call invokeMethod */ - //QMetaObject::invokeMethod(model, "addFrame", - // Qt::QueuedConnection, - // Q_ARG(CANFrame, tempFrame), - // Q_ARG(bool, false)); - framesRapid++; if (serial == NULL) return false; @@ -240,7 +233,7 @@ void GVRetSerial::connectDevice() output.append((char)0xF1); //another command to the GVRET output.append((char)0x07); //request device information - output.append((char)0xF1); + /*output.append((char)0xF1); output.append((char)0x08); //setting singlewire mode if (settings.value("Main/SingleWireMode", false).toBool()) { @@ -249,7 +242,7 @@ void GVRetSerial::connectDevice() else { output.append((char)0xFF); //signal we don't want single wire mode - } + }*/ output.append((char)0xF1); //yet another command output.append((char)0x09); //comm validation command @@ -293,7 +286,8 @@ void GVRetSerial::disconnectDevice() { void GVRetSerial::connectionTimeout() { //one second after trying to connect are we actually connected? - if (CANCon::NOT_CONNECTED==getStatus()) //no? + //if (CANCon::NOT_CONNECTED==getStatus()) //no? + if (!gotValidated) { //then emit the the failure signal and see if anyone cares qDebug() << "Failed to connect to GVRET at that com port"; @@ -307,10 +301,11 @@ void GVRetSerial::readSerialData() { QByteArray data = serial->readAll(); unsigned char c; - //qDebug() << (tr("Got data from serial. Len = %0").arg(data.length())); + qDebug() << (tr("Got data from serial. Len = %0").arg(data.length())); for (int i = 0; i < data.length(); i++) { c = data.at(i); + //qDebug() << c << " " << QString::number(c, 16) << " " << QString(c); procRXChar(c); } } @@ -376,6 +371,8 @@ void GVRetSerial::procRXChar(unsigned char c) break; case 3: buildFrame.timestamp |= (uint)c << 24; + + buildFrame.timestamp += timeBasis; break; case 4: buildFrame.ID = c; @@ -425,7 +422,7 @@ void GVRetSerial::procRXChar(unsigned char c) qDebug() << "can't get a frame, ERROR"; //take the time the frame came in and try to resync the time base. - if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame.timestamp / 1000); + //if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame.timestamp / 1000); } } break; @@ -447,7 +444,9 @@ void GVRetSerial::procRXChar(unsigned char c) case 3: buildTimeBasis += ((uint32_t)c << 24); qDebug() << "GVRET firmware reports timestamp of " << buildTimeBasis; - txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - ((uint64_t)buildTimeBasis / (uint64_t)1000ull); + + rebuildLocalTimeBasis(); + continuousTimeSync = false; rx_state = IDLE; break; @@ -576,11 +575,28 @@ void GVRetSerial::procRXChar(unsigned char c) } } +void GVRetSerial::rebuildLocalTimeBasis() +{ + uint64_t currTime = QDateTime::currentMSecsSinceEpoch() * 1000; + + /* + our time basis is the value we have to modulate the main system basis by in order + to sync the GVRET timestamps to the rest of the system. + The rest of the system uses CANConManager::getInstance()->getTimeBasis as the basis. + GVRET returns to us the current time since boot up in microseconds. + currTime stores the "system" timestamp when the GVRET timestamp was retrieved. + */ + lastSystemTimeBasis = CANConManager::getInstance()->getTimeBasis(); + int64_t systemDelta = currTime - lastSystemTimeBasis; + int32_t localDelta = buildTimeBasis - systemDelta; + timeBasis = localDelta; +} void GVRetSerial::handleTick() { + if (lastSystemTimeBasis != CANConManager::getInstance()->getTimeBasis()) rebuildLocalTimeBasis(); //qDebug() << "Tick!"; - +/* if( CANCon::CONNECTED == getStatus() ) { if (!gotValidated && doValidation) @@ -600,7 +616,7 @@ void GVRetSerial::handleTick() } } } - +*/ if (doValidation && serial && serial->isOpen()) sendCommValidation(); } diff --git a/connections/gvretserial.h b/connections/gvretserial.h index 4038a01..915af16 100644 --- a/connections/gvretserial.h +++ b/connections/gvretserial.h @@ -10,10 +10,9 @@ #include /*************/ - #include "canframemodel.h" #include "canconnection.h" - +#include "canconmanager.h" namespace SERIALSTATE { @@ -65,12 +64,12 @@ private: void readSettings(); void procRXChar(unsigned char); void sendCommValidation(); + void rebuildLocalTimeBasis(); protected: QTimer mTimer; QThread mThread; - bool doValidation; bool gotValidated; bool isAutoRestart; @@ -85,8 +84,9 @@ protected: bool can0ListenOnly, can1ListenOnly; int deviceBuildNum; int deviceSingleWireMode; - uint64_t txTimestampBasis; uint32_t buildTimeBasis; + int32_t timeBasis; + uint64_t lastSystemTimeBasis; }; #endif // GVRETSERIAL_H diff --git a/connections/socketcan.cpp b/connections/socketcan.cpp index b49e1fe..771f686 100644 --- a/connections/socketcan.cpp +++ b/connections/socketcan.cpp @@ -155,6 +155,8 @@ void SocketCan::framesReceived() /* test */ bool sndNotif = false; + uint64_t timeBasis = CANConManager::getInstance()->getTimeBasis(); + /* sanity checks */ if(!mDev_p) return; @@ -185,7 +187,7 @@ void SocketCan::framesReceived() frame_p->extended = false; frame_p->ID = recFrame.frameId(); frame_p->isReceived = true; - frame_p->timestamp = recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds(); + frame_p->timestamp = (recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds()) - timeBasis; /* enqueue frame */ getQueue().queue(); diff --git a/connections/socketcan.h b/connections/socketcan.h index c303236..debd091 100644 --- a/connections/socketcan.h +++ b/connections/socketcan.h @@ -8,6 +8,7 @@ #include "canframemodel.h" #include "canconnection.h" +#include "canconmanager.h" class SocketCan : public CANConnection diff --git a/mainwindow.cpp b/mainwindow.cpp index 9498a0c..0d73526 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -477,8 +477,8 @@ void MainWindow::filterClearAll() void MainWindow::tickGUIUpdate() { rxFrames = model->sendBulkRefresh(); - if(rxFrames>0) - { + //if(rxFrames>0) + //{ int elapsed = elapsedTime->elapsed(); if(elapsed) { framesPerSec = rxFrames * 1000 / elapsed; @@ -499,7 +499,7 @@ void MainWindow::tickGUIUpdate() if (model->needsFilterRefresh()) updateFilterList(); rxFrames = 0; - } + //} } void MainWindow::gotFrames(int framesSinceLastUpdate) @@ -533,6 +533,7 @@ void MainWindow::clearFrames() { ui->canFramesView->scrollToTop(); model->clearFrames(); + CANConManager::getInstance()->resetTimeBasis(); ui->lbNumFrames->setText(QString::number(model->rowCount())); bDirty = false; loadedFileName = "";