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

This commit is contained in:
Collin Kidder
2016-12-18 21:40:56 -05:00
parent 71a039ec64
commit 0f3f9e0fad
7 changed files with 63 additions and 26 deletions
+13
View File
@@ -1,3 +1,5 @@
#include <QDateTime>
#include "canconmanager.h" #include "canconmanager.h"
@@ -18,8 +20,14 @@ CANConManager::CANConManager(QObject *parent): QObject(parent)
mTimer.setInterval(250); /*tick 4 times a second */ mTimer.setInterval(250); /*tick 4 times a second */
mTimer.setSingleShot(false); mTimer.setSingleShot(false);
mTimer.start(); mTimer.start();
resetTimeBasis();
} }
void CANConManager::resetTimeBasis()
{
mTimestampBasis = QDateTime::currentMSecsSinceEpoch() * 1000;
}
CANConManager::~CANConManager() CANConManager::~CANConManager()
{ {
@@ -70,6 +78,10 @@ void CANConManager::refreshCanList()
} }
} }
uint64_t CANConManager::getTimeBasis()
{
return mTimestampBasis;
}
QList<CANConnection*>& CANConManager::getConnections() QList<CANConnection*>& CANConManager::getConnections()
{ {
@@ -139,6 +151,7 @@ bool CANConManager::sendFrame(const CANFrame& pFrame)
{ {
workingFrame.bus -= busBase; workingFrame.bus -= busBase;
workingFrame.isReceived = false; workingFrame.isReceived = false;
workingFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() * 1000) - mTimestampBasis);
txFrame = conn->getQueue().get(); txFrame = conn->getQueue().get();
*txFrame = workingFrame; *txFrame = workingFrame;
conn->getQueue().queue(); conn->getQueue().queue();
+4
View File
@@ -20,6 +20,9 @@ public:
CANConnection* getByName(const QString& pName) const; CANConnection* getByName(const QString& pName) const;
uint64_t getTimeBasis();
void resetTimeBasis();
int getNumBuses(); int getNumBuses();
/** /**
@@ -46,6 +49,7 @@ private:
static CANConManager* mInstance; static CANConManager* mInstance;
QList<CANConnection*> mConns; QList<CANConnection*> mConns;
QTimer mTimer; QTimer mTimer;
uint64_t mTimestampBasis;
}; };
#endif // CANCONNECTIONMODEL_H #endif // CANCONNECTIONMODEL_H
+34 -18
View File
@@ -18,7 +18,8 @@ GVRetSerial::GVRetSerial(QString portName) :
gotValidated = true; gotValidated = true;
isAutoRestart = false; isAutoRestart = false;
txTimestampBasis = QDateTime::currentMSecsSinceEpoch(); timeBasis = 0;
lastSystemTimeBasis = 0;
readSettings(); readSettings();
} }
@@ -147,18 +148,10 @@ bool GVRetSerial::piSendFrame(const CANFrame& frame)
int c; int c;
int ID; int ID;
CANFrame tempFrame = frame; CANFrame tempFrame = frame;
tempFrame.isReceived = false; tempFrame.isReceived = false;
tempFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() - txTimestampBasis) * 1000);
//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.
/* 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++; framesRapid++;
if (serial == NULL) return false; if (serial == NULL) return false;
@@ -240,7 +233,7 @@ void GVRetSerial::connectDevice()
output.append((char)0xF1); //another command to the GVRET output.append((char)0xF1); //another command to the GVRET
output.append((char)0x07); //request device information output.append((char)0x07); //request device information
output.append((char)0xF1); /*output.append((char)0xF1);
output.append((char)0x08); //setting singlewire mode output.append((char)0x08); //setting singlewire mode
if (settings.value("Main/SingleWireMode", false).toBool()) if (settings.value("Main/SingleWireMode", false).toBool())
{ {
@@ -249,7 +242,7 @@ void GVRetSerial::connectDevice()
else else
{ {
output.append((char)0xFF); //signal we don't want single wire mode output.append((char)0xFF); //signal we don't want single wire mode
} }*/
output.append((char)0xF1); //yet another command output.append((char)0xF1); //yet another command
output.append((char)0x09); //comm validation command output.append((char)0x09); //comm validation command
@@ -293,7 +286,8 @@ void GVRetSerial::disconnectDevice() {
void GVRetSerial::connectionTimeout() void GVRetSerial::connectionTimeout()
{ {
//one second after trying to connect are we actually connected? //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 //then emit the the failure signal and see if anyone cares
qDebug() << "Failed to connect to GVRET at that com port"; qDebug() << "Failed to connect to GVRET at that com port";
@@ -307,10 +301,11 @@ void GVRetSerial::readSerialData()
{ {
QByteArray data = serial->readAll(); QByteArray data = serial->readAll();
unsigned char c; 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++) for (int i = 0; i < data.length(); i++)
{ {
c = data.at(i); c = data.at(i);
//qDebug() << c << " " << QString::number(c, 16) << " " << QString(c);
procRXChar(c); procRXChar(c);
} }
} }
@@ -376,6 +371,8 @@ void GVRetSerial::procRXChar(unsigned char c)
break; break;
case 3: case 3:
buildFrame.timestamp |= (uint)c << 24; buildFrame.timestamp |= (uint)c << 24;
buildFrame.timestamp += timeBasis;
break; break;
case 4: case 4:
buildFrame.ID = c; buildFrame.ID = c;
@@ -425,7 +422,7 @@ void GVRetSerial::procRXChar(unsigned char c)
qDebug() << "can't get a frame, ERROR"; qDebug() << "can't get a frame, ERROR";
//take the time the frame came in and try to resync the time base. //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; break;
@@ -447,7 +444,9 @@ void GVRetSerial::procRXChar(unsigned char c)
case 3: case 3:
buildTimeBasis += ((uint32_t)c << 24); buildTimeBasis += ((uint32_t)c << 24);
qDebug() << "GVRET firmware reports timestamp of " << buildTimeBasis; qDebug() << "GVRET firmware reports timestamp of " << buildTimeBasis;
txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - ((uint64_t)buildTimeBasis / (uint64_t)1000ull);
rebuildLocalTimeBasis();
continuousTimeSync = false; continuousTimeSync = false;
rx_state = IDLE; rx_state = IDLE;
break; 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() void GVRetSerial::handleTick()
{ {
if (lastSystemTimeBasis != CANConManager::getInstance()->getTimeBasis()) rebuildLocalTimeBasis();
//qDebug() << "Tick!"; //qDebug() << "Tick!";
/*
if( CANCon::CONNECTED == getStatus() ) if( CANCon::CONNECTED == getStatus() )
{ {
if (!gotValidated && doValidation) if (!gotValidated && doValidation)
@@ -600,7 +616,7 @@ void GVRetSerial::handleTick()
} }
} }
} }
*/
if (doValidation && serial && serial->isOpen()) sendCommValidation(); if (doValidation && serial && serial->isOpen()) sendCommValidation();
} }
+4 -4
View File
@@ -10,10 +10,9 @@
#include <QDateTime> #include <QDateTime>
/*************/ /*************/
#include "canframemodel.h" #include "canframemodel.h"
#include "canconnection.h" #include "canconnection.h"
#include "canconmanager.h"
namespace SERIALSTATE { namespace SERIALSTATE {
@@ -65,12 +64,12 @@ private:
void readSettings(); void readSettings();
void procRXChar(unsigned char); void procRXChar(unsigned char);
void sendCommValidation(); void sendCommValidation();
void rebuildLocalTimeBasis();
protected: protected:
QTimer mTimer; QTimer mTimer;
QThread mThread; QThread mThread;
bool doValidation; bool doValidation;
bool gotValidated; bool gotValidated;
bool isAutoRestart; bool isAutoRestart;
@@ -85,8 +84,9 @@ protected:
bool can0ListenOnly, can1ListenOnly; bool can0ListenOnly, can1ListenOnly;
int deviceBuildNum; int deviceBuildNum;
int deviceSingleWireMode; int deviceSingleWireMode;
uint64_t txTimestampBasis;
uint32_t buildTimeBasis; uint32_t buildTimeBasis;
int32_t timeBasis;
uint64_t lastSystemTimeBasis;
}; };
#endif // GVRETSERIAL_H #endif // GVRETSERIAL_H
+3 -1
View File
@@ -155,6 +155,8 @@ void SocketCan::framesReceived()
/* test */ /* test */
bool sndNotif = false; bool sndNotif = false;
uint64_t timeBasis = CANConManager::getInstance()->getTimeBasis();
/* sanity checks */ /* sanity checks */
if(!mDev_p) if(!mDev_p)
return; return;
@@ -185,7 +187,7 @@ void SocketCan::framesReceived()
frame_p->extended = false; frame_p->extended = false;
frame_p->ID = recFrame.frameId(); frame_p->ID = recFrame.frameId();
frame_p->isReceived = true; 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 */ /* enqueue frame */
getQueue().queue(); getQueue().queue();
+1
View File
@@ -8,6 +8,7 @@
#include "canframemodel.h" #include "canframemodel.h"
#include "canconnection.h" #include "canconnection.h"
#include "canconmanager.h"
class SocketCan : public CANConnection class SocketCan : public CANConnection
+4 -3
View File
@@ -477,8 +477,8 @@ void MainWindow::filterClearAll()
void MainWindow::tickGUIUpdate() void MainWindow::tickGUIUpdate()
{ {
rxFrames = model->sendBulkRefresh(); rxFrames = model->sendBulkRefresh();
if(rxFrames>0) //if(rxFrames>0)
{ //{
int elapsed = elapsedTime->elapsed(); int elapsed = elapsedTime->elapsed();
if(elapsed) { if(elapsed) {
framesPerSec = rxFrames * 1000 / elapsed; framesPerSec = rxFrames * 1000 / elapsed;
@@ -499,7 +499,7 @@ void MainWindow::tickGUIUpdate()
if (model->needsFilterRefresh()) updateFilterList(); if (model->needsFilterRefresh()) updateFilterList();
rxFrames = 0; rxFrames = 0;
} //}
} }
void MainWindow::gotFrames(int framesSinceLastUpdate) void MainWindow::gotFrames(int framesSinceLastUpdate)
@@ -533,6 +533,7 @@ void MainWindow::clearFrames()
{ {
ui->canFramesView->scrollToTop(); ui->canFramesView->scrollToTop();
model->clearFrames(); model->clearFrames();
CANConManager::getInstance()->resetTimeBasis();
ui->lbNumFrames->setText(QString::number(model->rowCount())); ui->lbNumFrames->setText(QString::number(model->rowCount()));
bDirty = false; bDirty = false;
loadedFileName = ""; loadedFileName = "";